Skip to content

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
StateWhat happens in it
INITnothing yet; the state machine has been created but not started
DISCOVERINGan ISO Request for Address Claimed has been broadcast; every reply populates the peer registry
SELECTINGan address is chosen from the registry
CLAIMINGAddress Claimed has been transmitted; waiting out the contestation period
CLAIMEDthe address is in service; heartbeats run; ISO Requests are answered
CANNOT_CLAIMarbitration was lost on the address being claimed
SEARCHINGwalking the configured range for another free address
FAILEDno address could be claimed

Timings ​

ParameterValueOrigin
Discovery period2000 msa MUXEN choice, longer than the standard's 1.25 s answer window
Contestation period250 msJ1939-81
Retry delay after failure5000 msa MUXEN choice
Heartbeat interval60000 msper 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 0x80

If 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 address

CLAIMING → 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 ​

RangeUse
0–127preferred addresses, allocated by device class
128–247the NMEA 2000 dynamically assignable range
248–251reserved
252reserved for diagnostics
253reserved
254null address — "I have no address"
255global / 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 claimed

All 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.

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