-
Notifications
You must be signed in to change notification settings - Fork 0
Vessel Management System
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.
The state plane. See Home-Assistant for hardware and sensor details.
- Standard HA web UI / REST API; the
defiantCLI 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.
The navigation plane. See Nav for AIS / N2K / autopilot wiring.
- Signal K with the
signalk-mqtt-home-assistantplugin (despite the name, it publishes RAW SK deltas — not HA-discovery configs — see Nav § Signal K → HA bridge). - Publishes
navigation.position,navigation.speedOverGround,navigation.courseOverGroundTrueto bare MQTT topics on the HA broker; minimum interval 60 s. - Mirrors the chartplotter view to the helm tablet.
The agent plane. Headless Pi 5 running an ironclaw instance ("Smee", First Mate persona aboard Defiant) with telegram + web channels.
- Reaches HA over the LAN for state queries via the
defiantCLI. - Reachable remotely via Tailscale Funnel (deploy / hostname details kept out of this wiki).
The energy plane.
- Multi/SmartShunt data via the Cerbo's built-in MQTT (HA broker).
-
sensor.gx_device_ac_active_input_sourceis the canonical shore-power signal (unknown | grid | generator | shore_power | not_connected); MPPT data still pending the BLE proxy path (see Electrical).
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.
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)
| Automation | Trigger | Action |
|---|---|---|
defiant_shore_power_docked |
sensor.gx_device_ac_active_input_source → shore_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.
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
Setup scripts and automation JSONs live in scripts/ha_setup/ in the refit repo:
-
create_helpers.py— idempotent; creates thedefiant_*helper entities via the HA WebSocket API. -
signalk_mqtt_discovery.py— publishes retained MQTT discovery messages so HA picks up the SK MQTT topics assensor.defiant_signal_k_*anddevice_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.
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).
- HA hardware + sensor inventory: Home-Assistant
- Navigation hardware (AIS, N2K, autopilot, OpenPlotter): Nav
- Network architecture (Starlink, LAN, switch): Connectivity
- Victron / energy details: Electrical