Paul G 36a07dacb9 Extract shared signal-based D-Bus readers into lib/signal_reader.py
- Added lib/signal_reader.py with SignalGpsReader, SignalMeteoReader, and
  SignalDepthReader that use PropertiesChanged signal subscriptions instead
  of polling via GetValue(), reducing D-Bus overhead at steady state.
- Each reader discovers its service dynamically, seeds its cache with a
  one-shot GetValue, then relies on signals for all subsequent updates.
- Refactored dbus-tides, dbus-windy-station, dbus-no-foreign-land,
  dbus-lightning, and dbus-meteoblue-forecast to import from the shared
  library, removing ~600 lines of duplicated _unwrap() helpers and
  per-service GPS/meteo/depth reader classes.
- Updated install.sh for all five services to deploy signal_reader.py
  to /data/lib/ on the target device.
- Updated build-package.sh for all five services to bundle
  signal_reader.py into the .tar.gz package.
- Updated README.md with the new lib/ entry in the project table and
  documented the shared D-Bus readers pattern.
- Bumped version numbers in affected services (e.g. nfl_tracking 2.0.1).

Made-with: Cursor
2026-03-27 01:03:16 +00:00
2026-03-20 13:27:02 +00:00
2026-03-26 14:15:02 +00:00
2026-03-20 13:27:02 +00:00
2026-03-26 18:23:55 +00:00

Venus OS Boat Addons

Custom addons for a Cerbo GX running Venus OS on a sailboat. These services extend the system with weather monitoring, tide prediction, navigation tracking, generator management, and custom MFD displays.

All D-Bus services follow the same deployment pattern: build a .tar.gz package, copy it to /data/ on the Cerbo GX, and run install.sh. Services are managed by daemontools and survivase firmware updates via rc.local.

Projects

Project Type Language Description
axiom-nmea Library + Service Python Decodes Raymarine LightHouse protobuf multicast into NMEA 0183 sentences and Venus OS D-Bus services. Includes protocol documentation, debug tools, and a deployable D-Bus publisher.
dbus-generator-ramp D-Bus Service Python Gradually ramps inverter/charger input current when running on generator to avoid overload. Features warm-up hold, overload detection with fast recovery, and a persistent power correlation learning model.
lib Shared Library Python Signal-based D-Bus readers for GPS, meteo, and depth data. Uses PropertiesChanged subscriptions instead of polling, shared across all D-Bus services that consume sensor data.
dbus-lightning D-Bus Service Python Monitors real-time lightning strikes from the Blitzortung network via WebSocket. Filters by distance, analyzes storm approach speed, and estimates ETA.
dbus-meteoblue-forecast D-Bus Service Python Fetches 7-day weather forecasts from the Meteoblue API (wind, waves, precipitation, temperature). Adjusts refresh rate based on boat movement.
dbus-no-foreign-land D-Bus Service Python Sends GPS position and track data to noforeignland.com. Includes a QML settings page for the Venus OS GUI.
dbus-tides D-Bus Service Python Predicts tides by combining depth sensor readings with harmonic tidal models (NOAA stations and coastal grid). Records depth history in SQLite, detects high/low tides, and calibrates to chart depth.
dbus-vrm-history D-Bus Service Python Proxies historical data from the VRM cloud API and exposes it on D-Bus/MQTT for the frontend dashboard.
dbus-windy-station D-Bus Service Python Uploads weather observations from Raymarine sensors to Windy.com Stations API. Supports both legacy and v2 Venus OS GUI plugins.
mfd-custom-app Deployment Package Shell Builds and deploys the custom HTML5 app to the Cerbo GX. Overrides the stock Victron app with custom pages served via nginx. Supports SSH and USB installation.
venus-html5-app Frontend App TypeScript/React Fork of the Victron Venus HTML5 app with custom Marine2 views for weather, tides, tracking, generator status, and mooring. Displayed on Raymarine Axiom and other MFDs.
watermaker UI + API Docs React/JS Control interface for a watermaker PLC system. React SPA with REST/WebSocket/MQTT integration. Backend runs on a separate PLC controller.

Common D-Bus Service Structure

All Python D-Bus services share this layout:

dbus-<name>/
├── <name>.py              # Main service entry point
├── config.py              # Configuration constants
├── service/
│   ├── run                # daemontools entry point
│   └── log/run            # multilog configuration
├── install.sh             # Venus OS installation
├── uninstall.sh           # Cleanup
├── build-package.sh       # Creates deployable .tar.gz
└── README.md

At install time, install.sh symlinks velib_python from /opt/victronenergy/, installs the shared lib/signal_reader.py to /data/lib/, registers the service with daemontools, and adds an rc.local entry for persistence across firmware updates.

Shared D-Bus Readers -- Services that read GPS, meteo, or depth data from D-Bus should use the signal-based readers in lib/signal_reader.py (SignalGpsReader, SignalMeteoReader, SignalDepthReader) instead of polling with GetValue(). These readers bootstrap with a one-shot read, then subscribe to PropertiesChanged signals for zero-cost steady-state updates.

Deployment

# Build a package
cd dbus-<name>
./build-package.sh

# Copy to Cerbo GX
scp dbus-<name>-*.tar.gz root@<cerbo-ip>:/data/

# Install on device
ssh root@<cerbo-ip>
cd /data && tar -xzf dbus-<name>-*.tar.gz
bash /data/dbus-<name>/install.sh

# Check service status
svstat /service/dbus-<name>
tail -f /var/log/dbus-<name>/current | tai64nlocal

Development Prerequisites

  • Python 3.8+ -- for all D-Bus services
  • Node.js 20+ and npm -- for venus-html5-app and watermaker UI
  • SSH/root access to the Cerbo GX
  • Venus OS v3.10+ on the target device

Sensitive Configuration

Some projects require API keys or credentials. These are excluded from version control. Copy the example templates and fill in your values:

  • dbus-meteoblue-forecast/forecast_config.example.json --> forecast_config.json
  • dbus-windy-station/station_config.example.json --> station_config.json
  • watermaker/ui/.env.example --> .env

Venus OS Best Practices

These projects follow guidelines from the Venus OS wiki:

D-Bus Service Registration -- Create VeDbusService with register=False, add all paths and populate initial values, then call register(). This prevents consumers from querying the service before it is fully initialized (details).

Mandatory D-Bus Paths -- Every service must publish: /Mgmt/ProcessName, /Mgmt/ProcessVersion, /Mgmt/Connection, /DeviceInstance, /ProductId, /ProductName, /FirmwareVersion, /Connected.

Stability and Exception Handling -- Don't code too defensively. If something goes wrong, let the process exit cleanly and let daemontools restart it. For GLib.timeout_add callbacks in Python, an unhandled exception silently drops the callback without exiting; use exit_on_error() from ve_utils.py to ensure crashes propagate. Background threads should always set daemon=True (details).

Logging -- Use multilog t s25000 n4 in service/log/run to cap log storage at ~100KB per service (4 files x 25KB). This matches the Victron v2.23 standard and prevents filling the /data partition on space-constrained devices.

Service Directory -- Symlink services to /opt/victronenergy/service (not /service, which is a tmpfs overlay). The install.sh scripts handle this with fallback logic.

Persistence -- Install code under /data/ so it survives firmware updates. Add an entry in /data/rc.local to restore the service symlink after updates.

New Project Template

See [_template/](_template/) for a skeleton D-Bus service with all the boilerplate: main script, config, daemontools service, install/uninstall scripts, and build packaging.

Description
No description provided
Readme 20 MiB
Languages
Python 35.2%
TypeScript 25.7%
HTML 20.7%
JavaScript 10.5%
Shell 4.8%
Other 3%