- Standardize multilog to s25000 n4 (~100KB cap) to prevent filling /data - Use VeDbusService register=False + deferred register() in dbus-generator-ramp and dbus-vrm-history - Add @exit_on_error decorator to template GLib callback - Document best practices in README and template README Made-with: Cursor
134 lines
3.9 KiB
Python
Executable File
134 lines
3.9 KiB
Python
Executable File
#!/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 ve_utils import exit_on_error # 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)
|
|
|
|
@exit_on_error
|
|
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()
|