Appearance
The address claim state machine
This chapter is the detailed version of Address claiming. It is for someone reading a --verbose-control log, implementing a compatible device, or diagnosing a bus where a device will not settle.
Nothing here is needed to use the system.
Every virtual device runs its own instance of this state machine, so a daemon runs four of them concurrently, over a shared registry of the peers seen on the bus.
States
┌────────┐
│ INIT │
└───┬────┘
│ start
▼
┌───────────────┐
┌─────────►│ DISCOVERING │◄──────────── retry, 5 s
│ └───────┬───────┘ │
│ │ 2 s │
│ ▼ │
│ ┌───────────────┐ │
│ │ SELECTING │ │
│ └───┬───────┬───┘ │
│ address │ │ nothing free │
│ chosen ▼ └───────────┐ │
│ ┌─────────────┐ ▼ │
│ │ CLAIMING │ ┌─────────┐───────┘
│ └──┬───────┬──┘ │ FAILED │
│ 250 ms │ │ lost └─────────┘
│ silence │ │ arbitration ▲
│ ▼ ▼ │
│ ┌──────────┐ ┌──────────────┐ │ not AAC
│ │ CLAIMED │ │ CANNOT_CLAIM ├───┘
│ └────┬─────┘ └──────┬───────┘
│ │ address │ AAC
│ │ lost ▼
│ │ ┌─────────────┐
│ └──────►│ SEARCHING ├──► CLAIMING
│ └──────┬──────┘
│ │ range exhausted
└───────────────────────┴──► FAILED| State | What happens in it |
|---|---|
INIT | nothing yet; the state machine has been created but not started |
DISCOVERING | an ISO Request for Address Claimed has been broadcast; every reply populates the peer registry |
SELECTING | an address is chosen from the registry |
CLAIMING | Address Claimed has been transmitted; waiting out the contestation period |
CLAIMED | the address is in service; heartbeats run; ISO Requests are answered |
CANNOT_CLAIM | arbitration was lost on the address being claimed |
SEARCHING | walking the configured range for another free address |
FAILED | no address could be claimed |
Timings
| Parameter | Value | Origin |
|---|---|---|
| Discovery period | 2000 ms | a MUXEN choice, longer than the standard's 1.25 s answer window |
| Contestation period | 250 ms | J1939-81 |
| Retry delay after failure | 5000 ms | a MUXEN choice |
| Heartbeat interval | 60000 ms | per virtual device, once claimed |
Transitions in detail
INIT → DISCOVERING
On start. The daemon broadcasts an ISO Request (PGN 59904) for Address Claimed (PGN 60928) to the global address and arms a 2-second timer. If the request cannot be sent, it goes straight to FAILED.
Discovery does not clear the shared peer registry. Four virtual devices discover concurrently, and a device clearing the registry would erase what its siblings had just learned.
DISCOVERING → SELECTING
When the 2-second timer expires.
SELECTING → CLAIMING
The preferred address is taken if the registry shows it free:
ACD: Selecting address (preferred=0x80, range=100-200, AAC=no, peers=7)
ACD: Selected preferred address 0x80If it is occupied, the registry names the occupant:
ACD: Preferred address 0x80 is taken by NAME=0x…and the daemon walks min-addr … max-addr in ascending order for the first free address. This walk happens only if the NAME is arbitrary-address-capable.
Without a peer registry — which does not occur in the shipped daemon, but the core supports it — the preferred address is claimed blind.
SELECTING → FAILED
No free address in the range, or the NAME is not arbitrary-address-capable and the preferred address is taken:
ACD: Failed to claim any addressCLAIMING → CLAIMED
The 250 ms contestation timer expires with no objection.
CLAIMING or CLAIMED → CANNOT_CLAIM
An Address Claimed for this address arrives from another NAME, and that NAME is lower than ours:
ACD: Conflict on 0x80 - we lose (higher NAME)From CLAIMED, the address-lost callback fires first, so the rest of the daemon knows the virtual device is off the air.
If the other NAME is higher, we win. The daemon re-transmits its own Address Claimed and stays where it is:
ACD: Conflict on 0x80 - we win (lower NAME)If the two NAMEs are equal, the frame is ignored. Two devices with the same NAME on one bus is a configuration error, and there is no arbitration rule that can resolve it.
CANNOT_CLAIM → SEARCHING or FAILED
SEARCHING if the NAME is arbitrary-address-capable, FAILED if not. This is the single most important consequence of that bit: a device without it cannot recover from losing an arbitration.
SEARCHING → CLAIMING
The search starts at the address after the last one tried, runs to max-addr, then wraps and runs from min-addr to the last one tried:
ACD: Found available address 0x84
ACD: Found available address 0x66 (wrapped)Starting after the last attempt rather than at the bottom of the range keeps four virtual devices from converging on the same address after a disturbance.
SEARCHING → FAILED
The whole range has been walked with nothing free.
FAILED → DISCOVERING
After the 5-second retry delay:
ACD: Retrying address claim...The retry is unbounded. A bus that is full now may not be in a minute.
Messages on the wire
PGN 60928 (0xEE00) — Address Claimed
Eight bytes, the device's 64-bit NAME, little-endian. Transmitted from the address being claimed, to the global address 255.
Sent when claiming, when re-asserting a claim after winning an arbitration, and in reply to an ISO Request for this PGN.
Cannot Claim Address
The same message transmitted from the null address, 254. It tells the bus that a device with this NAME exists but has no address.
PGN 59904 (0xEA00) — ISO Request
Three bytes, the requested PGN, little-endian. The daemon transmits it for PGN 60928 during discovery, and answers it for its own Address Claimed, Product Information (126996), Configuration Information (126998) and the transmit/receive PGN lists (126464).
PGN 65240 (0xFED8) — Commanded Address
Nine bytes — the target NAME and the new address — and therefore always sent over ISO transport rather than as a single frame. A device that receives one addressed to its own NAME moves to the commanded address. The daemon accepts these and saves the result to the state file.
PGN 126993 (0x1F011) — Heartbeat
Transmitted every 60 seconds by each claimed virtual device.
Address ranges
| Range | Use |
|---|---|
| 0–127 | preferred addresses, allocated by device class |
| 128–247 | the NMEA 2000 dynamically assignable range |
| 248–251 | reserved |
| 252 | reserved for diagnostics |
| 253 | reserved |
| 254 | null address — "I have no address" |
| 255 | global / broadcast |
The daemon's own default range is 100–200. It accepts 0–253 for all three address options and refuses 254 and 255.
Reading a log
ACD: INIT -> DISCOVERING
ACD: Starting address discovery (2000ms)...
ACD: Discovery complete
ACD: DISCOVERING -> SELECTING
ACD: Selecting address (preferred=0x80, range=100-200, AAC=no, peers=7)
ACD: Preferred address 0x80 is taken by NAME=0x800400820000000A
ACD: Selected available address 0x66
ACD: SELECTING -> CLAIMING
ACD: Claiming address 0x66...
ACD: CLAIMING -> CLAIMED
VDEV[nav]: Address 0x66 claimedAll of the ACD: lines require --verbose-control. The VDEV[…] claim lines and All 4 virtual devices claimed addresses do too. Without it, a healthy startup is quiet.
Standards
The arbitration rule, the 250 ms contestation period, the message layouts and the address allocation above come from SAE J1939-81 (Network Management), which NMEA 2000 builds on, and from ISO 11783-5. The 2-second discovery phase and the 5-second retry delay are this implementation's choices.
