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:
24
_template/.gitignore
vendored
Normal file
24
_template/.gitignore
vendored
Normal 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
44
_template/README.md
Normal 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
68
_template/build-package.sh
Executable 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
22
_template/config.py
Normal 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
131
_template/dbus-template.py
Executable 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
115
_template/install.sh
Executable 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
2
_template/service/log/run
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
exec multilog t s99999 n8 /var/log/dbus-template
|
||||
5
_template/service/run
Executable file
5
_template/service/run
Executable 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
32
_template/uninstall.sh
Executable 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 ""
|
||||
Reference in New Issue
Block a user