Appearance
muxen-energy — Overview
muxen-energy answers one question, continuously, for each electrical circuit on the boat: where is the current coming from, where is it going, and how long will it last?
Solar panels, a wind turbine, a hydrogenerator, a generator set, a battery charger, the propulsion motors and the battery bank each report their own current on the MUXEN bus, and each of them reports it in isolation. muxen-energy groups those readings into energy zones — one zone per electrical parc, typically "48 V port", "48 V starboard", "24 V service", "AC" — and publishes, once a second, a single summary per zone: total charge, total discharge, state of charge, power drawn, and the estimated time before the bank is empty or full.
That summary is what the boat's screens display as the energy page. The daemon itself has no user interface.
The problem it solves
A device on the bus reports a current, not a role. A converter feeding 24 V from the 48 V bank is a load on one parc and a source on the other, at the same instant. A motor is a load under power and a source when regenerating. Nothing on the wire says which parc a given battery belongs to.
muxen-energy resolves that from the boat's configuration file: each device carries a BindToParc parameter naming the zone it belongs to, and the daemon subscribes only to the devices it needs, attributes each current to the right side of the right zone, and closes the balance.
Closing the balance is the part that matters. Real boats have loads nobody instruments — lighting circuits, fridges, the autopilot. The daemon computes what the known equipment fails to account for and publishes it explicitly as chargeOther / dischargeOther, so that
charge - discharge == battery currentholds on every published payload, unconditionally. A boat with a large uninstrumented consumption gets an honest "other" figure rather than a summary that quietly disagrees with the battery.
Where it sits
CAN bus (can0) ──┐
├──► muxen-energy ──► MQTT app/energy/<zone> ──► screens
MQTT device/… ──┘ (1 Hz)
MQTT app/sensor/… ──┘| It reads | From | Purpose |
|---|---|---|
/etc/muxen/deploy.json | disk, once at startup | which devices belong to which zone, zone names, battery capacities |
| MUXEN CAN broadcast frames | can0 | live currents, voltages, state of charge |
device/<function>/<instance>/life and /state | MQTT | the same data, when started with --mqtt instead of a CAN interface |
app/sensor/<name> | MQTT | currents that come from an analogue sensor rather than a bus device |
| It writes | To | Purpose |
|---|---|---|
app/energy/<zone> | MQTT, retained, 1 Hz | the per-zone energy summary |
app/energy/info | MQTT, retained, on each connection | the daemon's identity, whether it is online, and its features |
It is a read-only participant on the bus: it never transmits a CAN frame and never sends a command to a device.
The package Recommends: muxen-boat, which is the daemon that turns CAN frames into the device/… MQTT topics — that is the pairing behind the --mqtt mode. Sensor variables arrive on app/sensor/<name>, published by muxen-sensors, which the package depends on at >= 5.0.0: that is the first version publishing on this prefix rather than on variable/<name>, and an install pinned to the legacy prefix has to be unpinned with this daemon.
What a zone is
A zone is an electrical parc: one battery bank plus everything wired to it. Zones are numbered, and the number is what a device's BindToParc parameter holds. Zone 1 is also the fallback: a device with no BindToParc lands there.
A converter is the one device that belongs to two zones at once — its output side to BindToParc, its input side to InputBindToParc — and the daemon subscribes it twice, reading a different frame on each side so the sign convention comes out right in both.
Energy zones covers zone assembly in full.
What the numbers mean
Every second, for each zone, the daemon takes the currents that arrived within the last five seconds, sums them per family, closes the balance with the residual, and estimates the remaining time from a filtered battery current. The filter is deliberately pessimistic: it leans on the most-discharging samples, so the autonomy shown to the crew errs short rather than long.
The energy balance explains each published field, including what socValid, chargeOther and autonomy actually mean.
Document map
| Document | Content |
|---|---|
| Getting started | install, start, verify, the minimum configuration |
| Energy zones | how zones are built from the configuration file |
| The energy balance | every published field, and the arithmetic behind it |
| Troubleshooting | symptom → cause → check → fix, plus FAQ and tips |
| Reference | CLI, environment, unit, MQTT and CAN interfaces, paths, exit codes |
