Skip to content

The device catalogue ​

Everything the boat says arrives on one family of MQTT topics, and every topic names the piece of equipment it came from. This chapter explains how that naming works and what a payload looks like; the pages it links to, one per device model, list every field of every frame.

For the owner and the crew, the useful idea is small: each box on board has a kind and a number. The kind is a function code — 5 means a battery, 8 means a lighting module, 10 means a solar charger. The number is the instance: the first battery is 0, the second is 1. Together they make the address that appears in every topic and on every screen that reports a fault.

For an integrator this chapter plus the pages below are the whole interface. There is nothing else to read: the daemon has no API beyond these topics.

Connection ​

ParameterValue
Host127.0.0.1 — the daemon connects to the local broker
Port1883 (MQTT over TCP)
WebSocket port1884, proxied by nginx at /ws/boat for web clients
TLSnone
Client IDmuxen-boat
Keepalive5 s

Those values come from src/init.c (the daemon's MQTT context) and config/mosquitto-boat.conf (the listeners the package installs).

sh
# Watch everything on the broker
mosquitto_sub -h 127.0.0.1 -p 1883 -t '#' -v

# Watch all device traffic
mosquitto_sub -h 127.0.0.1 -t 'device/#' -v

Topic format ​

device/<function>/<instance>/<subtopic>
ElementMeaning
<function>the CAN function code, taken from the source address of the frame — the table below
<instance>which device of that kind, 0-based
<subtopic>the frame name (life, state, …), or command for an inbound control message

Most devices publish a life frame — the periodic "here is what I am doing" message — plus one or more state frames carrying the slower or less central values. The subtopic names are per device model and are listed on each page.

Four topics do not follow the plain form:

TopicDirectionPurpose
device/<function>/<instance>/error/<errorCode>publishedDiagnostic Trouble Code, see common
device/<function>/<instance>/resetcommandgeneric reset, any function
device/<function>/<instance>/rtr/<frameId>commandgeneric Remote Transmission Request, any function
device/interface, system/time, app/boat/infopublishedthe daemon's own topics, see system

Payload envelope ​

Every payload decoded from a CAN frame is wrapped the same way:

json
{ "data": { /* frame fields */ }, "metadata": { "rxdate": "...", "rxTimestamp": 0, "expireAfterSec": 0 } }
Metadata keyTypeNotes
rxdatestringreception time, ISO-8601 UTC with milliseconds: YYYY-MM-DDTHH:MM:SS.mmmZ. Lowercase rxdate on all CAN-derived topics
rxTimestampintreception time, Unix epoch seconds
expireAfterSecinthow long the value stays meaningful; past that age a consumer must treat it as stale
counterintsome life frames carry the CAN rolling counter here; noted per frame on each page

expireAfterSec is the field that matters operationally. It is per frame, not global — 5 seconds for wind data, 30 for most equipment, a year for identity frames like uid — and it is how a screen tells "the battery is at 12.8 V" from "the battery was at 12.8 V before it stopped answering". The daemon does not delete a topic when a device goes quiet; the consumer is expected to compare rxdate against system/time.

The device/interface topic predates this convention and uses a capital rxDate (see system). The TypeScript client normalises both onto rxdate.

Numbers decoded from CAN carry a fixed precision — 0.1 V, 0.1 A, 4 decimals for an angle in radians — and are serialised rounded to that many decimals. Each page states the precision per field.

Enumerated fields are emitted twice: a human-readable string under the field name, and the raw integer under <name>Code. A consumer should switch on the Code and display the string, because the string is the part that may be reworded.

The service runs with --json-plain, so payloads on a live Brain are compact single-line JSON. The examples in the catalogue are shown formatted for reading.

Generic commands ​

Two commands work on every function code. Both take an empty payload — the topic carries everything:

sh
# Reset the device at function 3, instance 2
mosquitto_pub -h 127.0.0.1 -t 'device/3/2/reset' -m ''

# Ask the device at function 3, instance 5 to send frame id 2 now
mosquitto_pub -h 127.0.0.1 -t 'device/3/5/rtr/2' -m ''

reset sends a diagnostic reset request to that device. rtr sends a Remote Transmission Request for one frame id, which is how a client gets a value immediately instead of waiting for the next periodic broadcast — useful for the slow frames, and for filling a screen at load time.

Per-device commands go to device/<function>/<instance>/command with a JSON body, and are documented on each device's page. Sixteen function codes accept them; the rest are read-only. There is no reply topic and no acknowledgement: a command either produces a CAN frame or is dropped, and the confirmation is the device's next published frame.

A command that the daemon cannot encode is discarded silently at the default log level. Running the daemon with -v prints the reason — an out-of-range channel, a conflicting pair of flags, a payload with no actionable field. Troubleshooting lists the messages.

Malformed input is safe: an empty payload, a truncated payload or invalid JSON is rejected by the parser and ignored.

The catalogue ​

One page per device model. <i> is the instance in every topic below.

CodeDeviceCommandsPage
anyCommon broadcast frames—common — the frames any device can send whatever its function: Diagnostic Trouble Codes, device UID, boot flag, communication shutdown
0Button / control panel✓button — physical button panel: which of its 8 buttons are pressed, the colour and blink state of its 8 LEDs, and a command that simulates a press
1Bloc8 power outputs✓bloc8 — 8-channel power distribution block with per-channel current sensing, short-circuit and not-connected detection, dimming and bus voltage
3Power source interconnection✓interco — battery interconnection and parallel-bus manager: per-input state with over-current and over-voltage flags, and the current through the interconnection
4Power source genset✓group — generator/group manager: run state, oil and water temperature alarms, the no-start and no-cut-off interlocks, RPM and output power, with start / stop commands
5Battery✓battery — battery monitor: voltage, current, state of charge, temperature, charge request, charge and discharge limits, cycle count
6Converter (inverter/charger)✓converter — inverter/charger: charger and inverter state on both the output and the input side, AC input selection and per-input current limits
7Motor✓motor — propulsion motor controller: state, voltage, current, temperature, signed RPM, and drive / regeneration / regulator commands with a setpoint
8Lighting✓lighting — 6-channel lighting controller: per-channel on/off and dimming level
10Solar MPPT✓solar — solar charge controller: charger state and off-reason, panel voltage/current, regulator temperature, and the full charger parameter set
11Wind turbine (EOL)✓wind-turbine — wind generator: state, output voltage and current, temperature, rotation speed, and an on / off / automatic command
12Navigation instruments—navigation — wind (relative and true), heading, speed, distance and time to destination, and instrument time
16IMOCA keel (team access)—keel-imoca — canting-keel system: sensor presence and lockouts, keel angle and ram pressures, capacitor bank, wing angles
17Generic I/O✓generic-io — general-purpose I/O module: two relays, two digital inputs, two analogue inputs, and a per-channel relay command
20Watermaker✓watermaker — desalinator: production state, salinity, flow, filter and high-pressure readings, pump and valve states, and mode commands
21HVAC✓hvac — air conditioning unit: measured temperature and setpoint, fan speed, heating/cooling/dehumidify mode, and a two-field command
22 / 23SFSP receiver / interface—sfsp — wireless switch system: the receiver reports how many switches it emulates, the interface reports its 8 button states and its signal strength
24Magic trim—magictrim — trim actuator: motor presence and rotation, RPM, current, voltage, and port/starboard pressures
25Remote battery switch✓remote-switch — remote main switch: contactor and injection state, connected battery count, injected current, and force/auto commands
26CGS (generator set)—cgs — generator set controller: contactor, drive, safe-stop and fault flags, motor and controller temperatures, torque, load and electrical power
27Alternator✓alternator — alternator regulator: charge state, working mode, voltage, current, RPM, temperature and load, with on / auto / boost commands
28Thermal engine—thermal-engine — combustion engine interface: RPM, load and torque, hour meter, coolant, oil and fuel readings, transmission gear
30Battery concentrator—battery-concentrator — bank-level battery reporting: state, charge request, voltage, current, state of charge, temperature, battery type, and charge/discharge limits
32Bow thruster✓bow-thruster — bow thruster: running direction, thrust percentage, voltage, current, hour meter, temperature, azimuth angle
—Daemon topics—system — system/time and device/interface: the Brain's clock and the CAN link's own health

The function code is also what makes a device's numeric id: a MUXEN device id is function × 64 + instance, which is the form the diagnostic tooling uses. The MQTT topics use the two parts separately.

Which frames reach the UDP output ​

When the daemon is started with --udp, a subset of the decoded frames is also emitted as NMEA-0183-style sentences over UDP, in addition to — never instead of — the MQTT publication. The subset is fixed in src/dispatcher-can.c and covers bloc8, motor, battery, solar, converter, navigation, interconnection, button, group, lighting, IMOCA keel (except the wing frame), generic I/O, wind turbine and SFSP.

Everything else — HVAC, watermaker, magic trim, CGS, alternator, thermal engine, bow thruster, remote switch, battery concentrator, the common broadcast frames and the daemon's own topics — is MQTT only. See Reference.

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