AIS Vessel Tracking
Heimdall tracks nearby vessels via aisstream.io, a WebSocket-based AIS (Automatic Identification System) data provider. Vessel positions are streamed in real time to connected frontend clients.
How It Works
- The
AisClient(inheimdall-websocket) connects towss://stream.aisstream.io/v0/stream. - It subscribes with a bounding box centered on the latest GPS position, updated every 60 seconds if the vessel moves more than 1 km.
- Two message types are processed:
PositionReport— updates position, speed, heading.ShipStaticData— updates name, type, dimensions.
- Vessel data is maintained in an in-memory
HashMap<MMSI, Vessel>. - Updates are throttled to 1/sec and broadcast to WebSocket channel
"vessels". - Stale vessels (no update for 30 minutes) are pruned every 30 seconds.
Configuration
[ais]
enabled = false
api_key = "" # env: HEIMDALL__AIS__API_KEY
radius_km = 10.0
ignore_mmsi = [] # MMSI blocklist (e.g. own vessel)
Environment: HEIMDALL__AIS__API_KEY=your-key
WebSocket Channel
There are no REST or GraphQL endpoints for AIS data. Subscribe to channel "vessels" via WebSocket.
interface VesselsMessage {
type: 'vessels';
data: {
vessels: Vessel[];
bbox: {
center: [number, number];
radius_km: number;
sw: [number, number];
ne: [number, number];
};
};
}
interface Vessel {
mmsi: number;
name: string;
shipType: number | null;
navStatus: number | null;
length: number | null;
beam: number | null;
lat: number;
lng: number;
heading: number | null; // null when unavailable (AIS code 511)
course: number | null;
speedKmh: number; // converted from knots (* 1.852)
lastUpdate: string; // ISO 8601
}
See the WebSocket API for connection details.
Frontend Integration
Use the useVessels hook and VesselMarker component from @elcto/ui:
import { useVessels, VesselMarker } from '@elcto/ui';
const { vessels, bbox, connected } = useVessels(wsUrl);
VesselMarker renders a color-coded dot on the map:
- Orange — moving vessel
- Gray — stationary or moored
The marker includes a directional arrow (heading) and a cycling info badge (name, speed, ship type).
Vessel Data Notes
- Speed is stored and transmitted in km/h (converted from AIS knots:
knots × 1.852). - Heading value
511in the AIS protocol means "unavailable" — mapped tonull. - The bounding box subscription is GPS-position-dependent. If no GPS data exists, the AIS client waits before subscribing.
- Ship type and navigation status codes are translated to German labels via
translateShipType()andtranslateNavStatus()utilities in@elcto/ui.
Reconnection
The client uses exponential backoff (3s → 60s max) on disconnect.