Skip to content

Vessel Management System

Stubb edited this page May 13, 2026 · 4 revisions

The Vessel Management System (VMS) is the umbrella term for the Pi-based hardware/software stack that manages Defiant's operational state, sensors, and automation. It comprises three Raspberry Pis at the nav desk, the Victron Cerbo GX, and a network of MQTT and REST data flows that converge on Home Assistant as the single source of truth for boat state.

image

The stack assembled in the nav desk

Hosts

Home Assistant Pi (HAOS)

The state plane. See Home-Assistant for hardware and sensor details.

  • Standard HA web UI / REST API; the defiant CLI uses the REST API for state reads/writes.
  • Hosts the Mosquitto MQTT broker that all onboard sensor publishers feed into.
  • Long-lived access tokens issued from the HA profile page for programmatic clients.

OpenPlotter Pi (Pi 5 + MacArthur HAT)

The navigation plane. See Nav for AIS / N2K / autopilot wiring.

  • Signal K with the signalk-mqtt-home-assistant plugin (despite the name, it publishes RAW SK deltas — not HA-discovery configs — see Nav § Signal K → HA bridge).
  • Publishes navigation.position, navigation.speedOverGround, navigation.courseOverGroundTrue to bare MQTT topics on the HA broker; minimum interval 60 s.
  • Mirrors the chartplotter view to the helm tablet.

Ironclaw agent Pi

The agent plane. Headless Pi 5 running an ironclaw instance ("Stubb", First Mate persona aboard Defiant) with telegram + web channels.

  • Reaches HA over the LAN for state queries via the defiant CLI.
  • Reachable remotely via Tailscale Funnel (deploy / hostname details kept out of this wiki).

Victron Cerbo GX

The energy plane.

  • Multi/SmartShunt data via the Cerbo's built-in MQTT (HA broker).
  • sensor.gx_device_ac_active_input_source is the canonical shore-power signal (unknown | grid | generator | shore_power | not_connected); MPPT data still pending the BLE proxy path (see Electrical).

Operational state — the defiant_* entities

HA is the source of truth for everything the agent and any future dashboards need to know about the boat:

Field HA entity Source Domain
Latitude input_number.defiant_latitude Auto-fed by Signal K (~60 s) input_number
Longitude input_number.defiant_longitude Auto-fed by Signal K (~60 s) input_number
Location name input_text.defiant_location_name Manual input_text
Mode input_select.defiant_mode Auto-set by automations (or manual) input_select
Destination input_text.defiant_destination Manual (only meaningful when mode=underway) input_text
Destination lat/lon input_number.defiant_destination_latitude/_longitude Manual input_number
ETA input_datetime.defiant_eta Manual input_datetime

Mode enum values: underway | anchored | moored | docked | hauled-out | unknown.

Live SK telemetry (read-only, not part of canonical state)

Created by the Signal K → HA bridge via MQTT discovery; used by automations and exposed for any consumer that wants raw nav data:

  • sensor.defiant_signal_k_defiant_latitude (°)
  • sensor.defiant_signal_k_defiant_longitude (°)
  • sensor.defiant_signal_k_defiant_speed_over_ground (kn)
  • sensor.defiant_signal_k_defiant_course_over_ground (°, normalised 0–360)
  • device_tracker.defiant_signal_k_defiant (zone-friendly tracker for the HA UI)

Automations

Automation Trigger Action
defiant_shore_power_docked sensor.gx_device_ac_active_input_sourceshore_power or grid, mode != docked Set mode = docked
defiant_shore_power_lost_notice shore power → not_connected while mode = docked Logbook entry only — disconnect is ambiguous (underway / cord-pulled / hauled)
defiant_sync_signal_k_position_to_helpers SK lat/lon sensor change Mirror to input_number.defiant_latitude/_longitude
defiant_sog_sustained_underway SoG > 1.0 kn for 5 min, mode != underway Set mode = underway
defiant_sog_stopped_while_underway_notice SoG < 0.3 kn for 10 min while mode = underway Logbook entry only — arrival type ambiguous

Two non-actions are deliberate:

  • Mode auto-clear on shore-power loss: disconnect could mean leaving the slip (underway), pulling the cord (still docked), or hauling out — auto-clearing would be wrong as often as right.
  • Mode auto-clear on SoG drop: arrival type (anchor / mooring / slip / drifting) cannot be inferred from SoG alone.

Data flow

NMEA 2000 / NMEA 0183 / GPS  ──→  OpenPlotter (Signal K)
                                          │
                                          ▼ MQTT (signalk-mqtt-ha plugin)
                          navigation.position, .speedOverGround, .courseOverGroundTrue
                                          │
Cerbo GX ─────────→ MQTT ────────→  Mosquitto on HAOS Pi  ←──── ESPHome devices
                                          │
                                          ▼ HA MQTT discovery
                              sensor.* / device_tracker.* / binary_sensor.*
                                          │
                                          ▼ automations
                          input_select.defiant_mode, input_number.defiant_latitude, ...
                                          │
                                          ▼ REST
                                  `defiant` CLI on ironclaw

Repository support

Setup scripts and automation JSONs live in scripts/ha_setup/ in the refit repo:

  • create_helpers.py — idempotent; creates the defiant_* helper entities via the HA WebSocket API.
  • signalk_mqtt_discovery.py — publishes retained MQTT discovery messages so HA picks up the SK MQTT topics as sensor.defiant_signal_k_* and device_tracker.defiant_signal_k_defiant.
  • automations.json / automation_*.json — one file per automation listed above.

The defiant CLI uses HOME_ASSISTANT_ACCESS_TOKEN from environment or repo .env to talk to HA.

Why HA is canonical (and not a TOML on the agent Pi)

HA already runs on the LAN with a UI, history, auth, and physical-world auto-detection (Victron, Signal K, ESPHome). Multiple consumers — the agent, future dashboards, automations, scripts on other Pis — read the same REST endpoint for free. Hand-rolling a TOML on the ironclaw filesystem would duplicate all of that and never get the auto-detection.

The defiant state CLI keeps a write-through cache at ~/.defiant/state-cache.toml so reads survive HA being briefly unreachable; writes always go to HA, and a write failure exits non-zero rather than silently caching (a write that only made it to the cache would desync from every other consumer).

Cross-refs

  • HA hardware + sensor inventory: Home-Assistant
  • Navigation hardware (AIS, N2K, autopilot, OpenPlotter): Nav
  • Network architecture (Starlink, LAN, switch): Connectivity
  • Victron / energy details: Electrical

Clone this wiki locally