Appearance
Reference
Everything muxen-uds exposes, in tables. Prose lives in the earlier chapters.
Programs
| Program | Path | What it is |
|---|---|---|
muxen-uds | /usr/bin/muxen-uds | the CLI; every command lives here |
muxen-udsd | /usr/bin/muxen-udsd | the WebSocket daemon |
muxen-scan | /usr/bin/muxen-scan | wrapper, execs muxen-uds scan |
muxen-uid | /usr/bin/muxen-uid | wrapper, execs muxen-uds uid |
muxen-deploy | /usr/bin/muxen-deploy | wrapper, execs muxen-uds deploy |
The three wrappers are shortcuts for one fixed operation each, not front ends for the command they run. They take no arguments of their own and refuse to run if given any, printing the equivalent muxen-uds invocation and exiting 2:
$ muxen-scan --timeout 10
muxen-scan: takes no arguments (got '--timeout')
muxen-scan runs `muxen-uds scan`: a passive scan on the default interface.
For anything else, run: muxen-uds scan [OPTION]...Use muxen-uds directly whenever you need an option. The wrappers prefer the muxen-uds sitting next to them rather than trusting $PATH, and exit 127 if the exec fails.
Invocation
muxen-uds [OPTION] <command> [COMMAND OPTION]
muxen-udsd [OPTION]Common options come before the command name; command options come after it. muxen-uds --help prints the common options and every command; muxen-uds <command> --help prints that command's own.
Common options
| Option | Default | Applies to | Description |
|---|---|---|---|
-h, --help | — | both | print help and exit |
-v, --verbose | quiet | both | raise the log level; repeatable (-v, -vv) |
-V, --version | — | both | print the version and exit |
-i, --interface canX | can0 | both | CAN interface to use |
-d, --device-id 0x1C0 | none | CLI | target by network address, 0–0xFFF |
-F, --function 1 | none | CLI | target by function code (with --instance) |
-I, --instance 0 | none | CLI | target instance, 0–63 |
-c, --client-id 0x3C0 | 0x27F | both | client address used to contact the device |
-p, --port 12345 | 12345 | daemon | TCP port of the WebSocket server |
--mqtt-host 127.0.0.1 | 127.0.0.1 | daemon | MQTT broker of the app/uds/info topic |
--mqtt-port 1883 | 1883 | daemon | port of that broker |
-s, --speedy | off | CLI | no retry, short timeouts |
--firmware-4x | off | both | compatibility mode for 4.x device firmware |
--deviceId and --clientId are accepted as aliases of --device-id and --client-id. --firmware-4x, --mqtt-host and --mqtt-port have no short form. The unit restricts the daemon to the loopback interface, so the broker must be local.
Combining --device-id with --function/--instance is refused.
Both programs share one option parser, so the daemon accepts the device-selection and --speedy flags too — but ignores them: it takes the target and the speedy flag from each request instead. muxen-udsd --help prints only the options that apply to it.
Log levels
| Level | Flag | Output |
|---|---|---|
| quiet | (default) | errors and the raw result of the command only |
| simple | -v | plus one summary line per command |
| detail | -vv | plus all diagnostic chatter |
--speedy
| normal | --speedy | |
|---|---|---|
| UDS request timeout | 2000 ms | 500 ms |
| UDS attempts | 3 | 1 |
| UID scan window | 4000 ms | 2000 ms |
| UID request re-broadcast | every 1000 ms | every 500 ms |
The firmware transfer and the writeconfig write step use their own fixed values and are unaffected.
Device addressing
deviceId = function * 64 + instance function 0–63, instance 0–63| Value | Meaning |
|---|---|
0x000–0xFFE | a device address |
0xFFF | the "no device" sentinel used internally; also the upper bound accepted by the daemon |
instance 63 | the parking address of a function |
Commands
Commands marked (no device) operate on the whole bus and take no --device-id.
scan — passive discovery (no device)
Listens on the bus and lists the devices that announce themselves. Sends nothing.
| Option | Default | Description |
|---|---|---|
--timeout <s> | 5 | scan duration in seconds |
--max-device <n> | 128 | size of the result table |
sh
muxen-uds -i can0 scan --timeout 5WebSocket data: [{ instance, function, functionName, deviceId, when }].
uid — UID tools (no device)
Active scan, and UID-addressed operations.
| Option | Description |
|---|---|
-s, --scan | active scan; detects addressing collisions |
-S, --scan-to-json <file> | write the scan result to a JSON file |
-u, --uid <16 hex> | select a device by UID (optional 0x prefix) |
-i, --instance <n> | change the selected device's instance, 0–63 |
-l, --locate | locate the selected device (LED animation) |
-U, --uds | enable UDS on the selected device |
-f, --preferred-function-code <n> | function to activate for UDS when the UID answers on several |
--instance, --locate and --uds each require --uid. With no option at all, uid performs a scan.
sh
muxen-uds -i can0 uid --scan
muxen-uds -i can0 uid --uid 0x0011223344556677 --instance 2WebSocket data: { duplicate, devices: [{ deviceId, uid }] }.
reset
Ask the MCU to perform a cold start.
| Option | Default | Description |
|---|---|---|
--delay <ms> | 500 | delay before the reset, 0–65535 |
locate
LED animation on the target device. No options.
readconfig
Read the configuration table.
| Option | Description |
|---|---|
--only-id <n> | read only this identifier |
--only-name <name> | keep only this parameter, by name (repeatable) |
--save-as-csv <file> | also save the table as CSV |
--save-as-json <file> | also save the table as JSON |
--only-id and --only-name are mutually exclusive.
WebSocket data: [{ id, name, type, value }].
writeconfig
Update the configuration table.
| Option | Default | Description |
|---|---|---|
--id <n> | — | parameter identifier to write |
--name <name> | — | parameter name to write |
--value <v> | — | new value |
--clear | — | write 0 / the empty string |
--from-json <file> | — | restore a whole configuration from JSON |
--reboot / --no-reboot | no reboot | reboot after a successful write |
--check-only | off | dry run: report sync status, write nothing |
Select by --id or --name, never both, and never together with --from-json.
factory
| Option | Description |
|---|---|
--reset-device-id | reset the device CAN address, then reboot the device |
--reset-device-configuration | reset all configuration except the CAN address |
--allocate-device-configuration <device-id> | allocate a configuration section for a dynamic device, 0–0xFFF |
--port <0-255> | port for the allocated device |
At least one of the first three is required.
firmware
| Option | Description |
|---|---|
--srec <file> | firmware file in SREC format, path as given |
--name <name> | file name looked up inside the firmware store |
Streams percent progress over the WebSocket.
listfirmware — (no device)
Lists the images under the firmware store. No options.
firmware: 010010004: 010010004-v6.2-NMEA2000.srec (hw: 990010061)WebSocket data: [{ name, code, filename, firmware, hardwareId, softwareId }]. hardwareId and softwareId are null when products.json carries no annotation for that file.
deploy — (optional device)
Deploy a configuration to the devices described in a project file.
| Option | Default | Description |
|---|---|---|
--filepath <file> | /etc/muxen/deploy.json | project file to use |
--project <id> | — | shorthand for /etc/muxen/configuration/<id>.json |
--check-only | off | dry run: report whether each device matches the project, change nothing |
--force | off | deploy even when the UID scan did not detect the device |
--no-epaper | off | skip writing the e-paper legends declared by the project |
--epaper-only | off | write only the e-paper legends: no factory reset, no parameter write, no deployed.json update |
--lang <REGION> | primary language | region code of the legend variant to write, up to 7 characters |
-d restricts the deploy to one device.
--check-only skips the factory reset, the 3-second flash wait, the legend write and the deployed.json update, and runs the parameter write step in writeconfig --check-only mode. Use checkconfig instead when you want the list of differences rather than a yes/no.
WebSocket data: [{ deviceId, deployed, error?, legendsFailed? }], error being offline, factory reset failed, or out of sync under --check-only; legendsFailed lists the zones whose legend write failed, present only when at least one did.
checkconfig — (optional device)
Compare device configurations against a project file. Read-only.
| Option | Default | Description |
|---|---|---|
--filepath <file> | /etc/muxen/deploy.json | project file to use |
--project <id> | — | shorthand for /etc/muxen/configuration/<id>.json |
--force | off | check even when the UID scan did not detect the device |
WebSocket data: [{ deviceId, online, mismatches[], missingOnDevice[], missingInProject[] }].
backup — (no device)
Passive scan, then a readconfig per device found, saving one JSON file per device in the current working directory as device-0xNNN-function-NN-instance-NN.json. No options. CLI only.
routine
Execute a raw UDS RoutineControl request.
| Option | Description |
|---|---|
--action <0-255> | routine control action (1 start, 2 stop, 3 request results) |
--routine <0-65535> | routine identifier |
--payload <hex> | hexadecimal string sent as the binary payload |
legend
Push one e-paper bitmap to a zone of a Bloc 8's panel. Frames and compresses the bitmap the way the panel expects it — see internal/epaper-bpu8s.md.
| Option | Description |
|---|---|
--zone <16-35> | zone the bitmap is for |
--payload <hex> | the 800-byte bitmap as 1600 hexadecimal characters, uncompressed |
--raw | send it uncompressed, for timing what the compression is worth |
Command availability
| Command | CLI | WebSocket | Device required | Worker |
|---|---|---|---|---|
scan | yes | yes | no | passive |
listfirmware | yes | yes | no | passive |
uid | yes | yes | no | active |
backup | yes | no | no | — |
deploy | yes | yes | optional | active |
checkconfig | yes | yes | optional | active |
reset | yes | yes | yes | active |
locate | yes | yes | yes | active |
readconfig | yes | yes | yes | active |
writeconfig | yes | yes | yes | active |
factory | yes | yes | yes | active |
firmware | yes | yes | yes | active |
routine | yes | yes | yes | active |
legend | yes | yes | yes | active |
Parameter types
type | Width | Notes |
|---|---|---|
int8_t, int16_t, int32_t, int64_t | 1, 2, 4, 8 bytes | signed |
uint8_t, uint16_t, uint32_t, uint64_t | 1, 2, 4, 8 bytes | unsigned |
string | up to 1024 characters | prints as (empty) when empty |
Parameter names are up to 256 characters.
Read-only names, never written from any source: ProductId, HardwareId, SoftwareId, SoftwareVersion, FonctionGroup.
Saved configuration file
json
{
"version": 1,
"parameters": [
{ "id": 4, "name": "VbatMin", "type": "uint16_t", "value": 2800 }
]
}Written by readconfig --save-as-json, read by writeconfig --from-json. The CSV form has the header id,name,type,value and is not restorable.
Files and directories
| Path | Role |
|---|---|
/usr/lib/muxen/firmware/ | firmware store, read directly |
/usr/lib/muxen/firmware/products.json | firmware catalog |
/usr/lib/muxen/firmware/<code>/*.srec | the images |
/etc/muxen/deploy.json | default project file |
/etc/muxen/configuration/<id>.json | named project, via --project <id> |
/var/lib/muxen/deployed.json | device id → UID record written by deploy |
/usr/lib/systemd/system/muxen-uds.service | the unit |
/etc/nginx/snippets/muxen-ws-uds.conf | proxies /ws/uds to 127.0.0.1:12345 |
/etc/nginx/snippets/muxen-deployed.conf | serves deployed.json at /api/deployed.json |
/usr/share/bash-completion/completions/muxen-uds | bash completion |
Neither nginx snippet is included by anything in this package. The site configuration that includes them is shipped by the boat's UI interface package (muxen-interface-*), one site file per boat, and that same file defines the map $http_upgrade $connection_upgrade block the /ws/uds proxy needs. The include is unconditional there — no trailing * — so on a boat whose interface site includes muxen-ws-uds.conf, nginx will not start unless this package is installed.
systemd
| Property | Value |
|---|---|
| Unit | muxen-uds.service |
| Description | UDS interface for the CAN boat |
ExecStart | /usr/bin/muxen-udsd --interface ${MUXEN_INTERFACE} |
Environment | MUXEN_INTERFACE=can0 |
User / Group | muxen / muxen |
StateDirectory | muxen |
Restart | always, after 30 s |
PartOf | muxen.target |
WantedBy | muxen.target |
The unit is hardened: NoNewPrivileges, ProtectSystem=strict, PrivateDevices, ProtectHome, ProtectKernelModules, ProtectKernelTunables, ProtectProc=invisible, RestrictNamespaces, RestrictRealtime, RestrictSUIDSGID, LockPersonality, RemoveIPC, SystemCallArchitectures=native, a long CapabilityBoundingSet deny list, a SystemCallFilter deny list (@privileged, @module, @mount, @debug, @reboot, @raw-io, @clock, @resources, @swap, @cpu-emulation, @obsolete) with SystemCallErrorNumber=EPERM, and RestrictNetworkInterfaces=lo.
The package declares the muxen-restart-target dpkg trigger, so installing or upgrading it participates in the MUXEN target restart handled by muxen-systemd. It also activates nginx-reload, so a running nginx reloads once at the end of the transaction and serves a changed muxen-ws-uds.conf or muxen-deployed.conf at once.
Packaging
| Field | Value |
|---|---|
| Source / binary package | muxen-uds |
Depends | muxen-systemd (plus ${misc:Depends}, ${shlibs:Depends}) |
Recommends | muxen-firmware (>= 2026.07.29-2), can-utils |
Replaces | uds |
Breaks | uds, and every client older than the 10.0.0 protocol: muxen-portal (<< 1.2.0~), muxen-interface-bali (<< 1.14.0~), muxen-interface-raken (<< 7.7.0~), muxen-decepticon (<< 1.14.0~), muxen-interface-test-bench (<< 1.4.0~) |
| Architecture | any, Multi-Arch: foreign |
WebSocket daemon
| Property | Value |
|---|---|
| TCP port | 12345 (-p) |
| Protocol name | muxen-ws-uds |
| Transport | plain WebSocket; no TLS in the daemon |
| Max request size | 1 MiB; larger messages are dropped |
| Receive buffer | 64 KiB per message chunk |
| Per-client send queue | 256 messages |
| Request queue | 64 messages per worker |
| Response outbox | 256 messages |
| Workers | 1 active + 1 passive |
| Tracked aborted jobs | 128 |
| Tracked closed sessions | 128 |
| Longest tracked uuid | 64 characters |
| First frame | hello, per connection |
| MQTT info | app/uds/info, retained, QoS 1 |
Wire format: WebSocket protocol.
Exit status
| Code | Meaning |
|---|---|
0 | success |
1 | failure — bad usage, parse error, or a non-zero command result |
127 | a wrapper (muxen-scan/muxen-uid/muxen-deploy) could not exec muxen-uds |
There are no finer-grained exit codes: internal error values are reported in the log line, not in the exit status.
At -v or above, the last line reports the command, the device and the internal return code:
cmd: reset device-id=0x280 rc=0Over the WebSocket the same value is response.rc, where 0 is success.
