Skip to content

AIS ​

AIS is how ships announce themselves. Every vessel above a certain size, and a great many below it, carries a transponder that broadcasts its identity, position, course and speed on VHF. An AIS receiver on the boat picks those broadcasts up and puts them on the NMEA 2000 bus, and that is what draws the other traffic on the chart.

muxen-nmea2000 turns that stream into a single picture of everything currently around the boat: vessels, navigation marks that transmit their own position, search-and-rescue aircraft, and safety broadcasts. One message, rebuilt every 30 seconds, with each target's own position and recent track.

Why it needs assembling ​

An AIS transponder does not send one message describing a ship. It sends several different ones, on different schedules, and each carries a fraction of the picture:

  • Position every 2–10 seconds for a Class A vessel under way, every 30 seconds for Class B.
  • Identity and voyage — the vessel's name, call sign, type, dimensions, destination and draught — roughly every 6 minutes, and split across two separate messages for Class B.

So a ship appears on the chart within seconds as a moving triangle with no name, and acquires its name minutes later. That is the protocol working correctly, not a fault.

The only thing tying those messages together is the MMSI, a 9-digit number unique to the transponder. muxen-nmea2000 keys everything on the MMSI, merges each new message into the target it already has, and ages the parts out separately — because a name learned six minutes ago is still true, while a position from six minutes ago is not.

The MMSI also says what kind of thing is transmitting, from its leading digits: a number starting 99 is a navigation mark, one starting 111 is a search-and-rescue aircraft, and the rest are vessels. That is how targets are sorted into the three groups below.

What gets published ​

Enable it with --report-ais, or ReportAis in the deploy configuration.

  • Topic nmea/ais
  • Rate every 30 seconds
  • QoS 0, retained
  • expireAfterSec 30
data
├── ownShip          ← this boat, from the navigation report
├── aisTargets       ← object keyed by MMSI
├── atons            ← object keyed by MMSI
├── sarAircraft      ← object keyed by MMSI
└── safetyMessages   ← array
metadata

ownShip is present only when the navigation report has a position for this boat. It is what lets a consumer draw the traffic relative to the vessel without subscribing to a second topic.

A target carries, depending on what has arrived:

GroupFields
top levelmmsi, aisClass, lat, lon, rxTs, source
dynamicscourse over ground, speed over ground, heading, rate of turn
identityvessel name, call sign, IMO number, ship type
dimensionslength, beam
voyagedestination, ETA, draught, navigation status
trackrecent positions, newest last
closest approachcpaNm, tcpaSec

Aids to navigation carry mmsi, name, position, atonType, offPosition and virtualAton — the last distinguishing a real buoy with a transponder from a mark that exists only as a broadcast.

Search-and-rescue aircraft carry mmsi, position and alt.

Safety messages carry sourceMmsi, text, rxTs and, when addressed rather than broadcast, destinationMmsi.

The authoritative description of the payload is the JSON Schema at schemas/ais-schema.json, with a worked example in schemas/ais-sample.json. Where this chapter and the schema disagree, the schema is right.

Ageing ​

Each kind of information has its own time to live, counted from when it last arrived:

InformationTTL
position (Class A and Class B)60 s
identity, voyage and other static data300 s
aid to navigation180 s
SAR aircraft60 s
safety message300 s

A target whose position has expired stops being reported. Static data outliving position by five minutes is deliberate: a vessel that drops out of VHF range briefly comes back with its name intact rather than appearing as a fresh unnamed contact.

Track history ​

--ais-track-depth N (or AisTrackDepth) sets how many past positions are kept per target, so a consumer can draw a trail. The default is 10 and the value is clamped to 0–100; 0 disables track history.

Deeper tracks make the payload larger for every target at once. On a busy waterway with a hundred targets the difference between depth 10 and depth 100 is an order of magnitude in message size, republished every 30 seconds.

Which PGNs feed it ​

PGNName
129038AIS Class A Position Report
129039AIS Class B Position Report
129040AIS Class B Extended Position Report
129041AIS Aids to Navigation Report
129793AIS UTC and Date Report
129794AIS Class A Static and Voyage Related Data
129795AIS Addressed Safety Related Message
129796AIS Acknowledge
129797AIS Binary Broadcast Message
129798AIS SAR Aircraft Position Report
129801AIS Addressed Safety Related Message
129802AIS Safety Related Broadcast Message
129809AIS Class B Static Data, Part A
129810AIS Class B Static Data, Part B
129812AIS Single Slot Binary Message

All are Fast Packet except 129793.

Class B static data arriving in two parts — 129809 carrying the name, 129810 the call sign, type and dimensions — is why a Class B vessel can show a name for some minutes before the rest of its details fill in.

What it does not do ​

  • It does not transmit AIS. This daemon never puts an AIS message on the bus. Transmitting requires a licensed transponder with the boat's own MMSI.
  • It does not decide anything is dangerous. cpaNm and tcpaSec are computed and published; deciding what to do about them belongs to whatever draws the chart. There is no collision alarm here.
  • It is not a receiver. No AIS receiver on the bus means no targets, and the daemon has no way to tell that apart from empty water.

Diagnostics ​

sh
mosquitto_sub -h 127.0.0.1 -t 'nmea/ais' -v

--verbose-ais logs each target as it is created, merged and expired, including how many targets were removed on each pass.

Empty water on a busy day is nearly always one of three things: the module is off, the receiver is not on the bus, or the antenna is disconnected. nmea/devices settles the second, and nmea/device/<addr>/pgn/129038 with --mqtt-publish-pgn settles the third. See Troubleshooting.

Integration of multiplexed solutions
MUXEN and the MUXEN logo are trademarks of MUXEN SAS.