Skip to content

muxen-synapse — Overview ​

muxen-synapse is the automation layer of the MUXEN Brain. It runs small, self-contained rules on board — "show the anchor light when it gets dark and we are lying at anchor", "cut the fresh-water pump when the tank runs low", "ask before starting the watermaker" — without anyone touching a switch and without new software being written for the boat.

Each rule is called an automation. An automation is a piece of Lua code that watches the boat's data, decides something, and either acts on a device or asks the crew first. Automations are turned on and off one at a time from the interface, and each one reports its own state, so you can always see which are running and which have a problem.

The problem it solves ​

The Brain already publishes everything the boat knows — tank levels, battery state, engine RPM, position — on MQTT, and every actuator on board already accepts a command on MQTT. What was missing was somewhere for the rules to live. Before synapse there was no scene engine, no rule engine and no macro system anywhere in the MUXEN stack: "if the bilge is high, run the pump" had no home.

Synapse is that home. Adding or changing an automation is a configuration change, not a software release.

Templates and instances ​

Reusable automations ship inside the package as a template library. A boat's deployed configuration then declares the instances it actually runs — which templates, how many of each, and with what settings.

/usr/share/muxen-synapse/          template library, shipped read-only
├── anchor-light-night.lua
├── sensor-level-detection.lua
└── …

/etc/muxen/deploy.json             per boat: which instances run, and how
  "synapse": {
    "fresh-water-port":  { "template": "sensor-level-detection", … }
    "fresh-water-stbd":  { "template": "sensor-level-detection", … }
    "custom":            { "script": "<inline lua>", … }
  }

An instance takes its code one of two ways:

ModeWhere the code livesEffect of a package update
templatethe shipped .lua file, read at load timethe instance follows the improved template automatically
scriptinline Lua stored in deploy.jsonfrozen — a private copy, unaffected by package updates

The same template can run several times under different instance ids with different settings, which is how one "sensor level detection" template covers four tanks.

The six shipped templates are described in The shipped automations.

Where it sits ​

Synapse owns no data and no device. It reads what other MUXEN daemons publish and writes commands the same daemons already accept.

Talks toOverFor
Mosquitto on 127.0.0.1:1883MQTTeverything — there is no other interface
muxen-boat, muxen-sensors, muxen-energyapp/sensor/<name>, device/<fc>/<inst>/…boat data in, device commands out
muxen-nmea2000nmea/…speed, heading, engine RPM, GPS fix
muxen-sextant (hard dependency, ≥ 2.2.0)sextant/sun, …/moon, …/tides, …/magneticsunrise, dusk, tides, nearest harbour
the config daemon/etc/muxen/deploy.jsonthe instance list — synapse only ever reads it
a frontend (raken)synapse/… topics + an nginx JSON indexlisting automations, toggling them, answering popups

It is not a UI: it publishes popup requests and a frontend renders them. It is not a data hub or a logger. It does not evaluate device-internal faults — that stays with muxen-alarms.

What ships ​

One Debian package, muxen-synapse, containing:

ComponentPath
The daemon/usr/bin/muxen-synapsed
The operator CLI/usr/bin/muxen-synapse-ctl
Template library + manifest/usr/share/muxen-synapse/
systemd unit/usr/lib/systemd/system/muxen-synapse.service
nginx snippets/etc/nginx/snippets/muxen-synapse-*.conf, muxen-ws-synapse.conf
Bash completion/usr/share/bash-completion/completions/

Lua 5.5 is vendored and statically linked, so no system Lua runtime is needed on any target.

The safety properties ​

Three guarantees hold whatever an automation does:

  • One automation cannot take down the others. Each runs in its own isolated Lua interpreter. A script's variables and functions are invisible to every other script, and tearing one down frees only that one.
  • No automation can freeze the boat's automation engine. Every callback runs under a hard 50 ms CPU budget. A runaway loop is aborted, logged, and counted; it cannot stall the daemon.
  • A broken automation stops itself. Five consecutive faults and the engine stops that instance rather than let it spin. Fixing the code and restarting recovers it automatically.

The scripting environment has no shell, no filesystem, no process control and no way to load code at runtime. How the engine runs automations covers all of this in operational detail.

Document map ​

DocumentContent
Getting startedinstall, start the service, run a first automation, verify it
The shipped automationsthe six shipped automations, what each does and how to set it up
Deploying automationsdeclaring instances in deploy.json, config, enable/disable, persisted state
Writing an automationauthoring an automation in Lua
How the engine runs automationshow the engine runs automations: isolation, watchdog, faults, popups, edge cases
muxen-synapse-ctl — the operator CLImuxen-synapse-ctl — the operator CLI
Troubleshootingsymptom → cause → check → fix, plus FAQ and Tips
ReferenceCLI flags, environment, paths, units, limits, exit codes
Lua API referencethe synapse.* Lua binding reference — for script authors
MQTT interfacethe synapse/ topic tree and payload shapes — for client implementers

Glossary ​

TermMeaning
TemplateA reusable .lua automation in the shipped library. Instantiated, never run directly.
InstanceA running automation declared in deploy.json, sourced from a template or from an inline script.
Instance idThe deploy.json key. Matches [a-zA-Z0-9-]+, and names the instance's synapse/<id> topic.
EngineThe muxen-synapsed daemon: resolves instances, loads them, runs and supervises them.
HookA function the engine calls on a script: onStart, onStop.
PopupA confirmation request an automation raises, carried in its status until the crew answers.
FeedbackThe crew's answer to a popup, returned over MQTT.
SnoozeA feedback choice that suppresses re-prompting for a set duration.
FSMAn optional small state machine a script uses for stateful behaviour, with per-state triggers.
ConfigRead-only per-instance tuning from deploy.json. The script receives it.
StateThe script-owned key/value store persisted in state.json. The script writes it.
WatchdogThe per-callback CPU-time cap that stops any script from blocking the engine.

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