Initial commit: Venus OS boat addons monorepo

Organizes 11 projects for Cerbo GX/Venus OS into a single repository:
- axiom-nmea: Raymarine LightHouse protocol decoder
- dbus-generator-ramp: Generator current ramp controller
- dbus-lightning: Blitzortung lightning monitor
- dbus-meteoblue-forecast: Meteoblue weather forecast
- dbus-no-foreign-land: noforeignland.com tracking
- dbus-tides: Tide prediction from depth + harmonics
- dbus-vrm-history: VRM cloud history proxy
- dbus-windy-station: Windy.com weather upload
- mfd-custom-app: MFD app deployment package
- venus-html5-app: Custom Victron HTML5 app fork
- watermaker: Watermaker PLC control UI

Adds root README, .gitignore, project template, and per-project
.gitignore files. Sensitive config files excluded via .gitignore
with .example templates provided.

Made-with: Cursor
This commit is contained in:
dev
2026-03-16 17:04:16 +00:00
commit 9756538f16
935 changed files with 113359 additions and 0 deletions

24
_template/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Build artifacts
*.tar.gz
*.sha256
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
*.egg
*.egg-info/
dist/
build/
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# Venus OS runtime (created during installation)
ext/

44
_template/README.md Normal file
View File

@@ -0,0 +1,44 @@
# dbus-template
Venus OS D-Bus service template. Use this as a starting point for new services.
## Getting Started
1. Copy this directory: `cp -r _template/ dbus-your-service-name/`
2. Rename `dbus-template.py` to match your service (e.g. `your_service.py`)
3. Update `config.py` with your service name, product ID, and settings
4. Update `service/run` to point to your renamed main script
5. Update `install.sh`: set `SERVICE_NAME` and `MAIN_SCRIPT` variables
6. Update `build-package.sh`: set `PACKAGE_NAME` and the file copy list
7. Replace this README with your own documentation
## Files
| File | Purpose |
|------|---------|
| `dbus-template.py` | Main service with D-Bus registration boilerplate |
| `config.py` | Configuration constants (service name, product ID, timing) |
| `service/run` | daemontools entry point |
| `service/log/run` | multilog configuration |
| `install.sh` | Venus OS installation (velib symlink, service registration, rc.local) |
| `uninstall.sh` | Removes service symlink |
| `build-package.sh` | Creates a deployable .tar.gz package |
## D-Bus Paths
Update these for your service:
| Path | Type | Description |
|------|------|-------------|
| `/ProductName` | string | Service display name |
| `/Connected` | int | Connection status (0/1) |
| `/Settings/Template/Enabled` | int | Enable/disable via settings |
## Checklist
- [ ] Unique service name in `config.py` (`com.victronenergy.yourservice`)
- [ ] Unique product ID in `config.py` (check existing services to avoid conflicts)
- [ ] All file references updated in `service/run`, `install.sh`, `build-package.sh`
- [ ] Custom D-Bus paths added
- [ ] Settings paths updated
- [ ] README replaced with your own documentation

68
_template/build-package.sh Executable file
View File

@@ -0,0 +1,68 @@
#!/bin/bash
#
# Build script for Venus OS D-Bus service package
#
# Usage:
# ./build-package.sh
# ./build-package.sh --version 1.0.0
#
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VERSION="0.1.0"
OUTPUT_DIR="$SCRIPT_DIR"
PACKAGE_NAME="dbus-template"
while [[ $# -gt 0 ]]; do
case $1 in
--version|-v) VERSION="$2"; shift 2 ;;
--output|-o) OUTPUT_DIR="$2"; shift 2 ;;
--help|-h)
echo "Usage: $0 [--version VERSION] [--output PATH]"
exit 0
;;
*) echo "Unknown option: $1"; exit 1 ;;
esac
done
BUILD_DIR=$(mktemp -d)
PACKAGE_DIR="$BUILD_DIR/$PACKAGE_NAME"
echo "Building $PACKAGE_NAME v$VERSION..."
mkdir -p "$PACKAGE_DIR/service/log"
# Copy application files -- update this list for your service
cp "$SCRIPT_DIR/dbus-template.py" "$PACKAGE_DIR/"
cp "$SCRIPT_DIR/config.py" "$PACKAGE_DIR/"
# Copy service and install files
cp "$SCRIPT_DIR/service/run" "$PACKAGE_DIR/service/"
cp "$SCRIPT_DIR/service/log/run" "$PACKAGE_DIR/service/log/"
cp "$SCRIPT_DIR/install.sh" "$PACKAGE_DIR/"
cp "$SCRIPT_DIR/uninstall.sh" "$PACKAGE_DIR/"
# Set permissions
chmod +x "$PACKAGE_DIR/dbus-template.py"
chmod +x "$PACKAGE_DIR/install.sh"
chmod +x "$PACKAGE_DIR/uninstall.sh"
chmod +x "$PACKAGE_DIR/service/run"
chmod +x "$PACKAGE_DIR/service/log/run"
# Create archive
mkdir -p "$OUTPUT_DIR"
TARBALL="$PACKAGE_NAME-$VERSION.tar.gz"
OUTPUT_ABS="$(cd "$OUTPUT_DIR" && pwd)"
cd "$BUILD_DIR"
tar --format=ustar -czf "$OUTPUT_ABS/$TARBALL" "$PACKAGE_NAME"
rm -rf "$BUILD_DIR"
echo "Package: $OUTPUT_ABS/$TARBALL"
echo ""
echo "Install on Venus OS:"
echo " scp $OUTPUT_ABS/$TARBALL root@<device-ip>:/data/"
echo " ssh root@<device-ip>"
echo " cd /data && tar -xzf $TARBALL"
echo " bash /data/$PACKAGE_NAME/install.sh"

22
_template/config.py Normal file
View File

@@ -0,0 +1,22 @@
"""
Configuration for dbus-YOUR-SERVICE-NAME.
Rename this file is not needed -- just update the values below.
"""
# Service identity
SERVICE_NAME = 'com.victronenergy.yourservice'
DEVICE_INSTANCE = 0
PRODUCT_NAME = 'Your Service Name'
PRODUCT_ID = 0xA1FF # Pick a unique product ID (0xA100-0xA1FF range)
FIRMWARE_VERSION = 0
CONNECTED = 1
# Version
VERSION = '0.1.0'
# Timing
MAIN_LOOP_INTERVAL_MS = 1000 # Main loop tick (milliseconds)
# Logging
LOG_LEVEL = 'INFO' # DEBUG, INFO, WARNING, ERROR

131
_template/dbus-template.py Executable file
View File

@@ -0,0 +1,131 @@
#!/usr/bin/env python3
"""
Venus OS D-Bus service template.
To create a new service:
1. Copy the _template/ directory and rename it to dbus-<your-service-name>/
2. Rename this file to match your service (e.g. your_service.py)
3. Update config.py with your service name, product ID, etc.
4. Update service/run to point to your renamed script
5. Update install.sh with your service name
6. Update build-package.sh with your file list
"""
import logging
import os
import signal
import sys
import time
sys.path.insert(1, os.path.join(os.path.dirname(__file__), 'ext', 'velib_python'))
from vedbus import VeDbusService # noqa: E402
from settingsdevice import SettingsDevice # noqa: E402
import dbus # noqa: E402
from gi.repository import GLib # noqa: E402
from config import ( # noqa: E402
SERVICE_NAME,
DEVICE_INSTANCE,
PRODUCT_NAME,
PRODUCT_ID,
FIRMWARE_VERSION,
CONNECTED,
MAIN_LOOP_INTERVAL_MS,
LOG_LEVEL,
VERSION,
)
logger = logging.getLogger('dbus-template')
class TemplateService:
"""Main service class. Rename to match your service."""
def __init__(self):
self._running = False
self._dbusservice = None
self._settings = None
def start(self):
"""Initialize D-Bus service and start the main loop."""
bus = dbus.SystemBus()
self._dbusservice = VeDbusService(
SERVICE_NAME, bus=bus, register=False
)
# Mandatory D-Bus paths
self._dbusservice.add_path('/Mgmt/ProcessName', __file__)
self._dbusservice.add_path('/Mgmt/ProcessVersion', VERSION)
self._dbusservice.add_path('/Mgmt/Connection', 'local')
self._dbusservice.add_path('/DeviceInstance', DEVICE_INSTANCE)
self._dbusservice.add_path('/ProductId', PRODUCT_ID)
self._dbusservice.add_path('/ProductName', PRODUCT_NAME)
self._dbusservice.add_path('/FirmwareVersion', FIRMWARE_VERSION)
self._dbusservice.add_path('/Connected', CONNECTED)
# --- Add your custom D-Bus paths here ---
# self._dbusservice.add_path('/YourPath', initial_value)
# Settings (stored in Venus OS localsettings, persist across reboots)
settings_path = '/Settings/Template'
supported_settings = {
'enabled': [settings_path + '/Enabled', 1, 0, 1],
# 'your_setting': [settings_path + '/YourSetting', default, min, max],
}
self._settings = SettingsDevice(
bus, supported_settings, self._on_setting_changed
)
self._dbusservice.register()
logger.info('Service registered on D-Bus as %s', SERVICE_NAME)
self._running = True
GLib.timeout_add(MAIN_LOOP_INTERVAL_MS, self._update)
def _update(self):
"""Called every MAIN_LOOP_INTERVAL_MS. Return True to keep running."""
if not self._running:
return False
# --- Add your main loop logic here ---
return True
def _on_setting_changed(self, setting, old, new):
"""Called when a Venus OS setting changes."""
logger.info('Setting %s changed: %s -> %s', setting, old, new)
def stop(self):
"""Clean shutdown."""
self._running = False
logger.info('Service stopped')
def main():
logging.basicConfig(
level=getattr(logging, LOG_LEVEL, logging.INFO),
format='%(asctime)s %(name)s %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
)
logger.info('Starting dbus-template v%s', VERSION)
service = TemplateService()
def shutdown(signum, frame):
logger.info('Received signal %d, shutting down...', signum)
service.stop()
sys.exit(0)
signal.signal(signal.SIGTERM, shutdown)
signal.signal(signal.SIGINT, shutdown)
service.start()
mainloop = GLib.MainLoop()
mainloop.run()
if __name__ == '__main__':
main()

115
_template/install.sh Executable file
View File

@@ -0,0 +1,115 @@
#!/bin/bash
#
# Installation script for Venus OS D-Bus service template
#
# Usage:
# chmod +x install.sh
# ./install.sh
#
set -e
SERVICE_NAME="dbus-template"
INSTALL_DIR="/data/$SERVICE_NAME"
MAIN_SCRIPT="dbus-template.py"
# Find velib_python
VELIB_DIR=""
if [ -d "/opt/victronenergy/velib_python" ]; then
VELIB_DIR="/opt/victronenergy/velib_python"
else
for candidate in \
"/opt/victronenergy/dbus-systemcalc-py/ext/velib_python" \
"/opt/victronenergy/dbus-generator/ext/velib_python" \
"/opt/victronenergy/dbus-mqtt/ext/velib_python" \
"/opt/victronenergy/dbus-digitalinputs/ext/velib_python" \
"/opt/victronenergy/vrmlogger/ext/velib_python"
do
if [ -d "$candidate" ] && [ -f "$candidate/vedbus.py" ]; then
VELIB_DIR="$candidate"
break
fi
done
fi
if [ -z "$VELIB_DIR" ]; then
VEDBUS_PATH=$(find /opt/victronenergy -name "vedbus.py" -path "*/velib_python/*" 2>/dev/null | head -1)
if [ -n "$VEDBUS_PATH" ]; then
VELIB_DIR=$(dirname "$VEDBUS_PATH")
fi
fi
# Determine service directory
if [ -d "/service" ] && [ ! -L "/service" ]; then
SERVICE_DIR="/service"
elif [ -d "/opt/victronenergy/service" ]; then
SERVICE_DIR="/opt/victronenergy/service"
elif [ -L "/service" ]; then
SERVICE_DIR=$(readlink -f /service)
else
SERVICE_DIR="/opt/victronenergy/service"
fi
echo "=================================================="
echo "$SERVICE_NAME - Installation"
echo "=================================================="
if [ ! -d "$SERVICE_DIR" ]; then
echo "ERROR: This doesn't appear to be a Venus OS device."
exit 1
fi
if [ ! -f "$INSTALL_DIR/$MAIN_SCRIPT" ]; then
echo "ERROR: Installation files not found in $INSTALL_DIR"
exit 1
fi
echo "1. Making scripts executable..."
chmod +x "$INSTALL_DIR/service/run"
chmod +x "$INSTALL_DIR/service/log/run"
chmod +x "$INSTALL_DIR/$MAIN_SCRIPT"
echo "2. Creating velib_python symlink..."
if [ -z "$VELIB_DIR" ]; then
echo "ERROR: Could not find velib_python on this system."
exit 1
fi
echo " Found velib_python at: $VELIB_DIR"
mkdir -p "$INSTALL_DIR/ext"
if [ -L "$INSTALL_DIR/ext/velib_python" ]; then
rm "$INSTALL_DIR/ext/velib_python"
fi
ln -s "$VELIB_DIR" "$INSTALL_DIR/ext/velib_python"
echo "3. Creating service symlink..."
if [ -L "$SERVICE_DIR/$SERVICE_NAME" ] || [ -e "$SERVICE_DIR/$SERVICE_NAME" ]; then
rm -rf "$SERVICE_DIR/$SERVICE_NAME"
fi
ln -s "$INSTALL_DIR/service" "$SERVICE_DIR/$SERVICE_NAME"
echo "4. Creating log directory..."
mkdir -p "/var/log/$SERVICE_NAME"
echo "5. Setting up rc.local for persistence..."
RC_LOCAL="/data/rc.local"
if [ ! -f "$RC_LOCAL" ]; then
echo "#!/bin/bash" > "$RC_LOCAL"
chmod +x "$RC_LOCAL"
fi
if ! grep -q "$SERVICE_NAME" "$RC_LOCAL"; then
echo "" >> "$RC_LOCAL"
echo "# $SERVICE_NAME" >> "$RC_LOCAL"
echo "if [ ! -L $SERVICE_DIR/$SERVICE_NAME ]; then" >> "$RC_LOCAL"
echo " ln -s /data/$SERVICE_NAME/service $SERVICE_DIR/$SERVICE_NAME" >> "$RC_LOCAL"
echo "fi" >> "$RC_LOCAL"
fi
echo ""
echo "=================================================="
echo "Installation complete!"
echo "=================================================="
echo ""
echo "To check status: svstat $SERVICE_DIR/$SERVICE_NAME"
echo "To view logs: tail -F /var/log/$SERVICE_NAME/current | tai64nlocal"
echo ""

2
_template/service/log/run Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
exec multilog t s99999 n8 /var/log/dbus-template

5
_template/service/run Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/sh
exec 2>&1
cd /data/dbus-template
export PYTHONPATH="/data/dbus-template/ext/velib_python:$PYTHONPATH"
exec python3 /data/dbus-template/dbus-template.py

32
_template/uninstall.sh Executable file
View File

@@ -0,0 +1,32 @@
#!/bin/bash
#
# Uninstall script for Venus OS D-Bus service template
#
set -e
SERVICE_NAME="dbus-template"
if [ -d "/service" ] && [ ! -L "/service" ]; then
SERVICE_DIR="/service"
elif [ -d "/opt/victronenergy/service" ]; then
SERVICE_DIR="/opt/victronenergy/service"
elif [ -L "/service" ]; then
SERVICE_DIR=$(readlink -f /service)
else
SERVICE_DIR="/opt/victronenergy/service"
fi
echo "Uninstalling $SERVICE_NAME..."
if [ -L "$SERVICE_DIR/$SERVICE_NAME" ]; then
svc -d "$SERVICE_DIR/$SERVICE_NAME" 2>/dev/null || true
sleep 2
rm "$SERVICE_DIR/$SERVICE_NAME"
echo "Service symlink removed"
fi
echo ""
echo "Uninstall complete."
echo "Files remain in /data/$SERVICE_NAME/ -- remove manually if desired."
echo ""