4 Commits

Author SHA1 Message Date
bde3920fc1 feat: Add session bus option for local testing and development
Introduced a `--use-session-bus` flag to optionally use the D-Bus
session bus instead of the system bus. This allows better flexibility
for local testing and development scenarios without requiring
system-level changes. Updated related classes and functions to respect
the new flag.
2025-04-19 09:33:54 +02:00
a4ccb9081f refactor(dbus): Parameterize picontrol_device and config_rsc
Replaced hardcoded paths with configurable parameters `picontrol_device`
and `config_rsc` across multiple classes. This improves flexibility,
making the components adaptable to various environments or setups.
Updated corresponding initialization and method implementations to use
these parameters.
2025-04-19 08:21:24 +02:00
4c1dc1c9b5 refactor(dbus): Move ResetDriverWatchdog to process_image_helper.py
The ResetDriverWatchdog class was relocated from dbus_helper.py to a new
helper module, process_image_helper.py, to improve code organization
and maintainability. Updated imports in relevant files to reflect this
change.
2025-04-19 08:13:02 +02:00
e756d68556 refactor(dbus): Move D-Bus helper functions to a dedicated file
Consolidated `REVPI_DBUS_*` constants and `extend_interface` function
into `dbus_helper.py` for better modularity and reusability. Updated
imports across modules to reflect this change.
2025-04-19 07:56:17 +02:00
8 changed files with 75 additions and 47 deletions

View File

@@ -5,8 +5,9 @@ from threading import Thread
from time import sleep from time import sleep
from gi.repository import GLib from gi.repository import GLib
from pydbus import SystemBus from pydbus import SessionBus, SystemBus
from .. import proginit as pi
from ..dbus_middleware1 import REVPI_DBUS_BASE_PATH from ..dbus_middleware1 import REVPI_DBUS_BASE_PATH
from ..dbus_middleware1 import REVPI_DBUS_NAME from ..dbus_middleware1 import REVPI_DBUS_NAME
@@ -34,7 +35,7 @@ def simple_call(method: str, *args, interface: str, object_path=REVPI_DBUS_BASE_
Any Any
The result of the method invocation on the targeted D-Bus interface. The result of the method invocation on the targeted D-Bus interface.
""" """
bus = SystemBus() bus = SessionBus() if pi.pargs.use_session_bus else SystemBus()
revpi = bus.get(REVPI_DBUS_NAME, object_path) revpi = bus.get(REVPI_DBUS_NAME, object_path)
iface = revpi[interface] iface = revpi[interface]
return getattr(iface, method)(*args) return getattr(iface, method)(*args)
@@ -55,7 +56,7 @@ def await_signal(signal_name: str, timeout: int, interface: str, object_path=REV
detected_signal = True detected_signal = True
loop.quit() loop.quit()
bus = SystemBus() bus = SessionBus() if pi.pargs.use_session_bus else SystemBus()
revpi = bus.get(REVPI_DBUS_NAME, object_path) revpi = bus.get(REVPI_DBUS_NAME, object_path)
iface = revpi[interface] iface = revpi[interface]

View File

@@ -42,7 +42,7 @@ class MiddlewareDaemon:
if self.bus_provider and self.bus_provider.is_alive(): if self.bus_provider and self.bus_provider.is_alive():
return return
self.bus_provider = BusProvider() self.bus_provider = BusProvider(use_system_bus=not pi.pargs.use_session_bus)
self.bus_provider.start() self.bus_provider.start()
log.debug("leave MiddlewareDaemon.dbus_start") log.debug("leave MiddlewareDaemon.dbus_start")

View File

@@ -2,27 +2,5 @@
# SPDX-FileCopyrightText: 2025 KUNBUS GmbH # SPDX-FileCopyrightText: 2025 KUNBUS GmbH
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
"""D-Bus middleware version 1 of revpi_middleware.""" """D-Bus middleware version 1 of revpi_middleware."""
from ..__about__ import __author__, __copyright__, __license__, __version__ from .dbus_helper import REVPI_DBUS_BASE_PATH, REVPI_DBUS_NAME
from .dbus_helper import extend_interface
REVPI_DBUS_NAME = "com.revolutionpi.middleware1"
REVPI_DBUS_BASE_PATH = "/com/revolutionpi/middleware1"
def extend_interface(*args) -> str:
"""
Extends an interface name by appending additional segments to a pre-defined base name.
This function takes multiple arguments, concatenates them with a predefined base
interface name, and returns the resulting string, effectively constructing an
extended interface name.
Args:
*args: str
Components to be appended to the base interface name.
Returns:
str
Fully constructed interface name by joining the base interface name with
the provided segments.
"""
return ".".join([REVPI_DBUS_NAME, *args])

View File

@@ -6,7 +6,7 @@ from logging import getLogger
from threading import Thread from threading import Thread
from gi.repository import GLib from gi.repository import GLib
from pydbus import SystemBus from pydbus import SessionBus, SystemBus
from . import REVPI_DBUS_NAME from . import REVPI_DBUS_NAME
from .process_image import InterfacePiControl from .process_image import InterfacePiControl
@@ -16,19 +16,27 @@ log = getLogger(__name__)
class BusProvider(Thread): class BusProvider(Thread):
def __init__(self): def __init__(
self,
picontrol_device="/dev/piControl0",
config_rsc="/etc/revpi/config.rsc",
use_system_bus=True,
):
log.debug("enter BusProvider.__init__") log.debug("enter BusProvider.__init__")
super().__init__() super().__init__()
self._bus = SystemBus() self._bus = SystemBus() if use_system_bus else SessionBus()
self._loop = GLib.MainLoop() self._loop = GLib.MainLoop()
self.picontrol_device = picontrol_device
self.config_rsc = config_rsc
def run(self): def run(self):
log.debug("enter BusProvider.run") log.debug("enter BusProvider.run")
self._bus.publish( self._bus.publish(
REVPI_DBUS_NAME, REVPI_DBUS_NAME,
InterfacePiControl(), InterfacePiControl(self.picontrol_device, self.config_rsc),
) )
self._loop.run() self._loop.run()

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2025 KUNBUS GmbH
# SPDX-License-Identifier: GPL-2.0-or-later
"""Helper for dbus."""
from logging import getLogger
log = getLogger(__name__)
REVPI_DBUS_NAME = "com.revolutionpi.middleware1"
REVPI_DBUS_BASE_PATH = "/com/revolutionpi/middleware1"
def extend_interface(*args) -> str:
"""
Extends an interface name by appending additional segments to a pre-defined base name.
This function takes multiple arguments, concatenates them with a predefined base
interface name, and returns the resulting string, effectively constructing an
extended interface name.
Args:
*args: str
Components to be appended to the base interface name.
Returns:
str
Fully constructed interface name by joining the base interface name with
the provided segments.
"""
return ".".join([REVPI_DBUS_NAME, *args])

View File

@@ -8,7 +8,7 @@ from logging import getLogger
from pydbus.generic import signal from pydbus.generic import signal
from ..interface_helper import ResetDriverWatchdog from .process_image_helper import ResetDriverWatchdog
log = getLogger(__name__) log = getLogger(__name__)
@@ -27,10 +27,11 @@ class InterfacePiControl:
NotifyDriverReset = signal() NotifyDriverReset = signal()
def __init__(self): def __init__(self, picontrol_device: str, config_rsc: str):
self.pi_control = "/dev/piControl0" self.picontrol_device = picontrol_device
self.config_rsc = config_rsc
self.wd_reset_driver = ResetDriverWatchdog(self.pi_control) self.wd_reset_driver = ResetDriverWatchdog(self.picontrol_device)
self.wd_reset_driver.register_call(self.notify_reset_driver) self.wd_reset_driver.register_call(self.notify_reset_driver)
def notify_reset_driver(self): def notify_reset_driver(self):
@@ -40,9 +41,9 @@ class InterfacePiControl:
log.debug("enter InterfacePiControl.ResetDriver") log.debug("enter InterfacePiControl.ResetDriver")
try: try:
fd = os.open(self.pi_control, os.O_WRONLY) fd = os.open(self.picontrol_device, os.O_WRONLY)
except Exception as e: except Exception as e:
log.warning(f"could not open ${self.pi_control} to reset driver") log.warning(f"could not open ${self.picontrol_device} to reset driver")
raise e raise e
execption = None execption = None

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2020-2023 Sven Sager # SPDX-FileCopyrightText: 2025 KUNBUS GmbH
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
""" """
Helper for the process image. Helper for the process image.
@@ -7,7 +7,6 @@ Helper for the process image.
The ResetDriverWatchdog class is a copy of revpipyload project module "watchdogs" The ResetDriverWatchdog class is a copy of revpipyload project module "watchdogs"
https://github.com/naruxde/revpipyload/blob/b51c2b617a57cc7d96fd67e1da9f090a0624eacb/src/revpipyload/watchdogs.py https://github.com/naruxde/revpipyload/blob/b51c2b617a57cc7d96fd67e1da9f090a0624eacb/src/revpipyload/watchdogs.py
""" """
import os import os
from fcntl import ioctl from fcntl import ioctl
from logging import getLogger from logging import getLogger
@@ -19,9 +18,9 @@ log = getLogger(__name__)
class ResetDriverWatchdog(Thread): class ResetDriverWatchdog(Thread):
"""Watchdog to catch the reset_driver action.""" """Watchdog to catch the reset_driver action."""
def __init__(self, pi_control_device="/dev/piControl0"): def __init__(self, picontrol_device: str):
super(ResetDriverWatchdog, self).__init__() super(ResetDriverWatchdog, self).__init__()
self.procimg = pi_control_device self.procimg = picontrol_device
self.daemon = True self.daemon = True
self._calls = [] self._calls = []
self._exit = False self._exit = False
@@ -35,7 +34,7 @@ class ResetDriverWatchdog(Thread):
""" """
Mainloop of watchdog for reset_driver. Mainloop of watchdog for reset_driver.
If the thread can not open the process image or the IOCTL is not If the thread cannot open the process image or the IOCTL is not
implemented (wheezy), the thread function will stop. The trigger implemented (wheezy), the thread function will stop. The trigger
property will always return True. property will always return True.
""" """
@@ -51,7 +50,7 @@ class ResetDriverWatchdog(Thread):
) )
return return
# The ioctl will return 2 byte (c-type int) # The ioctl will return 2 bytes (c-type int)
byte_buff = bytearray(2) byte_buff = bytearray(2)
while not self._exit: while not self._exit:
try: try:
@@ -73,7 +72,7 @@ class ResetDriverWatchdog(Thread):
def register_call(self, function): def register_call(self, function):
"""Register a function, if watchdog triggers.""" """Register a function, if watchdog triggers."""
if not callable(function): if not callable(function):
return ValueError("Function is not callable.") raise ValueError("Function is not callable.")
if function not in self._calls: if function not in self._calls:
self._calls.append(function) self._calls.append(function)
@@ -89,7 +88,7 @@ class ResetDriverWatchdog(Thread):
log.debug("leave ResetDriverWatchdog.stop()") log.debug("leave ResetDriverWatchdog.stop()")
def unregister_call(self, function=None): def unregister_call(self, function=None):
"""Remove a function call on watchdog trigger.""" """Remove a function from the watchdog trigger."""
if function is None: if function is None:
self._calls.clear() self._calls.clear()
elif function in self._calls: elif function in self._calls:

View File

@@ -9,7 +9,7 @@ __version__ = "1.4.0"
import logging import logging
import sys import sys
from argparse import ArgumentParser, Namespace from argparse import ArgumentParser, Namespace, SUPPRESS
from configparser import ConfigParser from configparser import ConfigParser
from enum import Enum from enum import Enum
from os import R_OK, W_OK, access, environ, getpid, remove from os import R_OK, W_OK, access, environ, getpid, remove
@@ -262,6 +262,16 @@ parser = ArgumentParser(
prog=programname, prog=programname,
description="Program description", description="Program description",
) )
# Use session bus of D-Bus for local testing and development proposes (hidden)
parser.add_argument(
"--use-session-bus",
dest="use_session_bus",
action="store_true",
default=False,
help=SUPPRESS,
)
parser.add_argument("--version", action="version", version=f"%(prog)s {program_version}") parser.add_argument("--version", action="version", version=f"%(prog)s {program_version}")
parser.add_argument( parser.add_argument(
"-f", "-f",