95 lines
2.8 KiB
JavaScript
95 lines
2.8 KiB
JavaScript
import {cfg} from './config.mjs';
|
|
|
|
const CHANNEL_MAP = {0: 'A, B', 1: 'A', 2: 'B'};
|
|
const SENDER_TYPE = {
|
|
0: 'Other', 1: 'Unknown', 2: 'Cargo', 3: 'Class B',
|
|
4: 'Passenger', 5: 'Special', 6: 'Tanker', 7: 'High Speed',
|
|
8: 'Fishing', 9: 'Aircraft', 10: 'Helicopter', 11: 'Base Station',
|
|
12: 'AtoN', 13: 'SART/EPIRB'
|
|
};
|
|
|
|
let aisCache = null;
|
|
let aisCacheTs = 0;
|
|
const AIS_TTL = 1000;
|
|
|
|
function decodeMsgTypes(raw) {
|
|
const types = [];
|
|
for (let i = 0; i < 32; i++) {
|
|
if (raw & (1 << i)) types.push(i);
|
|
}
|
|
return types;
|
|
}
|
|
|
|
function decodeFlags(flags) {
|
|
return {
|
|
validated: flags & 3,
|
|
validated2: (flags & 3) == 2 ? -1 : flags & 3,
|
|
repeat: (flags >> 2) & 3,
|
|
virtual_aid: (flags >> 4) & 1,
|
|
approx: (flags >> 5) & 1,
|
|
channels: (flags >> 6) & 15,
|
|
cs_unit: (flags >> 10) & 3,
|
|
raim: (flags >> 12) & 3,
|
|
dte: (flags >> 14) & 3,
|
|
assigned: (flags >> 16) & 3,
|
|
display: (flags >> 18) & 3,
|
|
dsc: (flags >> 20) & 3,
|
|
band: (flags >> 22) & 3,
|
|
msg22: (flags >> 24) & 3,
|
|
off_position: (flags >> 26) & 3,
|
|
maneuver: (flags >> 28) & 3,
|
|
};
|
|
}
|
|
|
|
export async function getAIS() {
|
|
if (aisCache && Date.now() - aisCacheTs < AIS_TTL) return aisCache;
|
|
const {ADSB_URL} = cfg();
|
|
if (!ADSB_URL) return {data: []};
|
|
const r = await fetch(`${ADSB_URL}:9990/api/ships_array.json`);
|
|
const {dynamic, static: staticRows, time} = await r.json();
|
|
|
|
const staticMap = new Map(staticRows.map(row => [row[0], row]));
|
|
|
|
aisCache = dynamic.map(row => {
|
|
const [mmsi, lat, lon, distance, bearing, heading,
|
|
cog, speed, status, rrsi, ppm, count, msg_type,
|
|
last_signal, last_group, group_mask, flags, altitude,
|
|
received_stations, mmsi_type, shipclass, country] = row;
|
|
const s = staticMap.get(mmsi) ?? [];
|
|
const [_mmsi, shipname, callsign, destination, shiptype,
|
|
imo, to_bow, to_stern, to_port, to_starboard, draught,
|
|
eta_month, eta_day, eta_hour, eta_minute] = s;
|
|
|
|
const f = decodeFlags(flags);
|
|
|
|
return {
|
|
mmsi,
|
|
type: SENDER_TYPE[shipclass],
|
|
lat, lon, altitude,
|
|
heading, cog, speed,
|
|
distance, bearing,
|
|
destination,
|
|
rrsi, ppm, count,
|
|
msg_type: decodeMsgTypes(msg_type),
|
|
channels: CHANNEL_MAP[f.channels] ?? f.channels,
|
|
...f,
|
|
shiptype, imo, draught,
|
|
country, callsign,
|
|
shipname,
|
|
to_bow, to_stern, to_port, to_starboard,
|
|
eta_month, eta_day, eta_hour, eta_minute,
|
|
last_signal: last_signal ? time - last_signal : null,
|
|
last_group, group_mask,
|
|
received_stations, shipclass,
|
|
status
|
|
};
|
|
});
|
|
aisCacheTs = Date.now();
|
|
return aisCache;
|
|
}
|
|
|
|
export function getAISImage(mmsi) {
|
|
return fetch(`https://www.marinetraffic.com/getAssetDefaultPhoto/?photo_size=800&asset_type_id=0&asset_id=${mmsi}`,
|
|
{headers: {'User-Agent': 'Mozilla/5.0', 'Referer': 'https://www.marinetraffic.com/'}}).then(resp => resp.blob());
|
|
}
|