4 Commits

Author SHA1 Message Date
acdb814007 doc(revpiconfig): Docstrings for get_rfkill_index and simple_systemd
The new docstrings provide detailed explanations of the purpose,
parameters, and return values for both functions, improving code
readability and maintainability. This ensures better understanding for
future contributors and reduces ambiguity.
2025-04-21 14:44:50 +02:00
8451b5401b doc(revpiconfig): Add docstrings to enums in revpi_config.py
This update introduces detailed docstrings for the `ComputeModuleTypes`
and `ConfigActions` enumeration classes. The docstrings provide
descriptions for each class and their attributes, improving code
readability and maintainability.
2025-04-21 14:44:04 +02:00
0fe8be6515 doc(revpiconfig): Add docstrings to RevPiConfig class and methods
Enhance documentation for the `RevPiConfig` class, its methods, and
properties to improve code readability and ease of use. The added
docstrings provide clear explanations of the class's purpose,
attributes, and functionality for developers and users. This update
supports better maintainability and understanding of the codebase.
2025-04-21 14:42:14 +02:00
5d376acf49 doc(revpiconfig): Add detailed docstrings to ConfigTxt methods
Enhance the `ConfigTxt` class with comprehensive docstrings for all
methods, providing clear explanations of their functionality,
parameters, and return values. This improves code readability and
facilitates easier maintenance and understanding for future developers.
2025-04-21 14:38:32 +02:00
9 changed files with 13 additions and 432 deletions

View File

@@ -1,22 +0,0 @@
<!-- /usr/share/dbus-1/system.d/com.revolutionpi.ios1.conf -->
<busconfig>
<!-- Allow full access to root as the bus owner -->
<policy user="root">
<allow own="com.revolutionpi.ios1"/>
<allow send_destination="com.revolutionpi.ios1"/>
<allow receive_sender="com.revolutionpi.ios1"/>
</policy>
<!-- System group picontrol -->
<policy group="picontrol">
<allow send_destination="com.revolutionpi.ios1"
send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_destination="com.revolutionpi.ios1"
send_interface="com.revolutionpi.middleware1.PiControl"/>
</policy>
<!-- Standard-Policy -->
<policy context="default">
<deny send_destination="com.revolutionpi.ios1"/>
</policy>
</busconfig>

View File

@@ -1,4 +1,4 @@
<!-- /usr/share/dbus-1/system.d/com.revolutionpi.middleware1.conf -->
<!-- /etc/dbus-1/system.d/revpi-middleware.conf -->
<busconfig>
<!-- Allow full access to root as the bus owner -->
<policy user="root">
@@ -12,7 +12,7 @@
<allow send_destination="com.revolutionpi.middleware1"
send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_destination="com.revolutionpi.middleware1"
send_interface="com.revolutionpi.middleware1.PiControl"/>
send_interface="com.revolutionpi.middleware1.picontrol"/>
</policy>
<!-- Standard-Policy -->

View File

@@ -1,46 +0,0 @@
from time import time
from gi.repository import GLib
from pydbus import SystemBus
detected_signal = False
timestamp = time()
bus = SystemBus()
bus_revpi = bus.get("com.revolutionpi.ios1", "/com/revolutionpi/ios1")
interface = bus_revpi["com.revolutionpi.ios1.IoManager"]
io_o_1_path = interface.Get("O_1")
io_revpiled_path = interface.Get("RevPiLED")
io_RevPiLED = bus.get("com.revolutionpi.ios1", io_revpiled_path)
io_O_1 = bus.get("com.revolutionpi.ios1", io_o_1_path)
def signal_handler(io_name, io_value):
global timestamp
print(f"Signal received: {io_name} = {io_value}")
if io_name == "O_1":
timestamp = time()
io_RevPiLED.Set("com.revolutionpi.ios1.OutInt", "value", GLib.Variant("i", int(io_value)))
elif io_name == "I_1":
io_RevPiLED.Set("com.revolutionpi.ios1.OutInt", "value", GLib.Variant("i", int(io_value)))
io_O_1.Set("com.revolutionpi.ios1.OutBool", "value", GLib.Variant("b", not io_value))
print(time() - timestamp)
# Start event detection
interface.ActivateIoEvents()
interface.onIoChanged = signal_handler
try:
loop = GLib.MainLoop()
loop.run()
except KeyboardInterrupt:
pass
# Stop event detection
interface.DeactivateIoEvents()

View File

@@ -9,7 +9,6 @@ from time import perf_counter
from . import proginit as pi
from .dbus_middleware1.bus_provider import BusProvider
from .ios1.bus_provider_io import BusProviderIo
log = getLogger(__name__)
@@ -27,7 +26,6 @@ class MiddlewareDaemon:
self._running = True
self.bus_provider = None
self.io_bus_provider = None
self._configure()
log.debug("leave MiddlewareDaemon.__init__")
@@ -41,16 +39,11 @@ class MiddlewareDaemon:
def dbus_start(self):
log.debug("enter MiddlewareDaemon.dbus_start")
if self.bus_provider and self.bus_provider.is_alive():
return
dbus_middleware_running = self.bus_provider and self.bus_provider.is_alive()
if not dbus_middleware_running:
self.bus_provider = BusProvider(use_system_bus=not pi.pargs.use_session_bus)
self.bus_provider.start()
dbus_io_middleware_running = self.io_bus_provider and self.io_bus_provider.is_alive()
if not dbus_io_middleware_running:
self.io_bus_provider = BusProviderIo(use_system_bus=not pi.pargs.use_session_bus)
self.io_bus_provider.start()
self.bus_provider = BusProvider(use_system_bus=not pi.pargs.use_session_bus)
self.bus_provider.start()
log.debug("leave MiddlewareDaemon.dbus_start")
@@ -63,12 +56,6 @@ class MiddlewareDaemon:
if self.bus_provider.is_alive():
log.warning("dbus provider thread is still alive")
if self.io_bus_provider:
self.io_bus_provider.stop()
self.io_bus_provider.join(timeout=10.0)
if self.io_bus_provider.is_alive():
log.warning("dbus io provider thread is still alive")
log.debug("leave MiddlewareDaemon.dbus_stop")
def reload_config(self) -> None:

View File

@@ -10,7 +10,6 @@ from glob import glob
from logging import getLogger
from os import X_OK, access
from os.path import exists, join
from threading import Thread
from typing import List, Optional
from pydbus import SystemBus
@@ -555,11 +554,7 @@ def configure_gui(action: ConfigActions):
return gui_available
bus = SystemBus()
systemd = bus.get(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
)
systemd_manager = systemd["org.freedesktop.systemd1.Manager"]
systemd_manager = bus.get(".systemd1")
if action is ConfigActions.ENABLE:
systemd_manager.SetDefaultTarget("graphical.target", True)
@@ -659,51 +654,21 @@ def simple_systemd(action: ConfigActions, unit: str):
ValueError: If the specified action is not supported.
"""
bus = SystemBus()
systemd = bus.get(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
)
systemd_manager = systemd["org.freedesktop.systemd1.Manager"]
systemd_manager = bus.get(".systemd1")
if action is ConfigActions.ENABLE:
def thread_unit_config():
"""Change configuration asynchronously."""
# Dbus call: UnmaskUnitFiles(in as files, in b runtime, out a(sss) changes
lst_change_unmask = systemd_manager.UnmaskUnitFiles([unit], False)
# Dbus call: EnableUnitFiles(in as files, in b runtime, in b force,
# out b carries_install_info, out a(sss) changes
lst_change_enable = systemd_manager.EnableUnitFiles([unit], False, False)
if lst_change_unmask or lst_change_enable:
# Reload systemd after modified unit property
systemd_manager.Reload()
Thread(target=thread_unit_config, daemon=True).start()
# Dbus call: StartUnit(in s name, in s mode, out o job
systemd_manager.UnmaskUnitFiles([unit], False)
systemd_manager.EnableUnitFiles([unit], False, False)
systemd_manager.StartUnit(unit, "replace")
elif action is ConfigActions.DISABLE:
def thread_unit_config():
"""Change configuration asynchronously."""
# Dbus call: DisableUnitFiles (in as files, in b runtime, out a(sss) changes)
change = systemd_manager.DisableUnitFiles([unit], False)
if change:
# Reload systemd after modified unit property
systemd_manager.Reload()
Thread(target=thread_unit_config, daemon=True).start()
# Dbus call: StopUnit(in s name,in s mode, out o job
systemd_manager.StopUnit(unit, "replace")
systemd_manager.DisableUnitFiles([unit], False)
elif action is ConfigActions.STATUS:
try:
unit_path = systemd_manager.LoadUnit(unit)
properties = bus.get("org.freedesktop.systemd1", unit_path)
properties = bus.get(".systemd1", unit_path)
except Exception:
log.warning(f"could not get systemd unit {unit}")
return False
@@ -713,7 +678,7 @@ def simple_systemd(action: ConfigActions, unit: str):
elif action is ConfigActions.AVAILABLE:
try:
unit_path = systemd_manager.LoadUnit(unit)
properties = bus.get("org.freedesktop.systemd1", unit_path)
properties = bus.get(".systemd1", unit_path)
except Exception:
log.warning(f"could not get systemd unit {unit}")
return False
@@ -723,8 +688,6 @@ def simple_systemd(action: ConfigActions, unit: str):
else:
raise ValueError(f"action {action} not supported")
return None
if __name__ == "__main__":
rc = RevPiConfig()

View File

@@ -1,5 +0,0 @@
# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2025 KUNBUS GmbH
# SPDX-License-Identifier: GPL-2.0-or-later
"""D-Bus ios version 1 of revpi_middleware."""
from .ios1_helper import REVPI_DBUS_BASE_PATH, REVPI_DBUS_NAME

View File

@@ -1,100 +0,0 @@
# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2025 KUNBUS GmbH
# SPDX-License-Identifier: GPL-2.0-or-later
"""D-Bus bus provider for revpi_middleware."""
from logging import getLogger
from threading import Thread
import revpimodio2
from gi.repository import GLib
from pydbus import SessionBus, SystemBus
from revpimodio2 import Cycletools
from . import REVPI_DBUS_NAME
from .interface_ios import (
InterfaceIoManager,
InterfaceInpBool,
InterfaceOutBool,
InterfaceInpInt,
InterfaceOutInt,
)
log = getLogger(__name__)
class BusProviderIo(Thread):
def __init__(
self,
picontrol_device="/dev/piControl0",
config_rsc="/etc/revpi/config.rsc",
use_system_bus=True,
):
log.debug("enter BusProviderIo.__init__")
super().__init__()
self._bus = SystemBus() if use_system_bus else SessionBus()
self._dc_io_interfaces = {}
self._loop = GLib.MainLoop()
self._modio = revpimodio2.RevPiModIO(
procimg=picontrol_device,
configrsc=config_rsc,
shared_procimg=True,
)
self.picontrol_device = picontrol_device
self.config_rsc = config_rsc
def run(self):
log.debug("enter BusProviderIo.run")
self._dc_io_interfaces.clear()
for io in self._modio.io:
interface = None
value_type = type(io.value)
if value_type is bool:
interface = (
InterfaceInpBool(self._bus, io)
if io.type == revpimodio2.INP
else InterfaceOutBool(self._bus, io)
)
elif value_type is int:
interface = (
InterfaceInpInt(self._bus, io)
if io.type == revpimodio2.INP
else InterfaceOutInt(self._bus, io)
)
if interface is not None:
self._dc_io_interfaces[io.name] = interface
lst_interfaces = [
(f"io/{io_name}", self._dc_io_interfaces[io_name]) for io_name in self._dc_io_interfaces
]
try:
self._bus.publish(
REVPI_DBUS_NAME,
InterfaceIoManager(self._modio, self._dc_io_interfaces),
*lst_interfaces,
)
except Exception as e:
log.error(f"can not publish dbus {REVPI_DBUS_NAME}: {e}")
try:
self._loop.run()
except Exception as e:
log.error(f"can not run dbus mainloop: {e}")
self._modio.cleanup()
log.debug("leave BusProviderIo.run")
def stop(self):
log.debug("enter BusProviderIo.stop")
self._loop.quit()
log.debug("leave BusProviderIo.stop")
@property
def running(self):
return self._loop.is_running()

View File

@@ -1,159 +0,0 @@
# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2025 KUNBUS GmbH
# SPDX-License-Identifier: GPL-2.0-or-later
"""D-Bus interfaces for IOs."""
from gi.overrides.GLib import Variant
from pydbus.generic import signal
from revpimodio2 import RevPiModIO, Cycletools
from .ios1_helper import REVPI_DBUS_BASE_PATH, DbusInterfaceIo
class InterfaceIoManager:
"""
<node>
<interface name="com.revolutionpi.ios1.IoManager">
<method name="GetAllInputs">
<arg type="as" direction="out"/>
</method>
<method name="GetAllOutputs">
<arg type="as" direction="out"/>
</method>
<method name="Get">
<arg name="io_name" type="s" direction="in"/>
<arg name="object-path" type="o" direction="out"/>
</method>
<method name="ActivateIoEvents">
</method>
<method name="DeactivateIoEvents">
</method>
<signal name="IoChanged">
<arg name="name" type="s" direction="out"/>
<arg name="value" type="v" direction="out"/>
</signal>
</interface>
</node>
"""
interface_name = "com.revolutionpi.ios1.IoManager"
IoChanged = signal()
def __init__(self, modio: RevPiModIO, io_interfaces: dict[str, DbusInterfaceIo]):
self._dc_io_interfaces = io_interfaces
self.modio = modio
self.lst_inp = []
for dev in self.modio.device:
for io in dev.get_inputs():
self.lst_inp.append(self._get_io_path(io.name))
self.lst_out = []
for dev in self.modio.device:
for io in dev.get_outputs():
self.lst_out.append(self._get_io_path(io.name))
def _modio_cycle(self, ct: Cycletools) -> None:
for io_name in self._dc_io_interfaces:
interface = self._dc_io_interfaces[io_name]
if ct.changed(interface.io):
interface.emit_io_change()
self.IoChanged(interface.io.name, Variant("b", interface.io.value))
def _get_io_path(self, io_name: str) -> str:
return f"{REVPI_DBUS_BASE_PATH}/io/{io_name}"
def GetAllInputs(self) -> list[str]:
return self.lst_inp
def GetAllOutputs(self) -> list[str]:
return self.lst_out
def Get(self, io_name) -> str:
if io_name in self.modio.io:
return self._get_io_path(io_name)
raise KeyError(f"No IO with name '{io_name}' found.")
def ActivateIoEvents(self) -> None:
if not self.modio._looprunning:
self.modio.autorefresh_all()
self.modio.cycleloop(self._modio_cycle, cycletime=50, blocking=False)
def DeactivateIoEvents(self) -> None:
self.modio.exit(False)
class InterfaceInpBool(DbusInterfaceIo):
"""
<node>
<interface name="com.revolutionpi.ios1.InpBool">
<property name="bmk" type="s" access="read"/>
<property name="name" type="s" access="read"/>
<property name="value" type="b" access="read"/>
</interface>
</node>
"""
interface_name = "com.revolutionpi.ios1.InpBool"
@property
def bmk(self) -> str:
return self.io.bmk
@property
def name(self) -> str:
return self.io.name
@property
def value(self) -> bool:
return self.io.value
class InterfaceOutBool(InterfaceInpBool):
"""
<node>
<interface name="com.revolutionpi.ios1.OutBool">
<property name="bmk" type="s" access="read"/>
<property name="name" type="s" access="read"/>
<property name="value" type="b" access="readwrite"/>
</interface>
</node>
"""
interface_name = "com.revolutionpi.ios1.OutBool"
@property
def value(self) -> bool:
return super().value
@value.setter
def value(self, value: bool):
self.io.value = value
self.io._parentdevice._modio.writeprocimg()
class InterfaceInpInt(DbusInterfaceIo):
"""
<node>
<interface name="com.revolutionpi.ios1.InpInt">
<property name="bmk" type="s" access="read"/>
<property name="name" type="s" access="read"/>
<property name="value" type="i" access="read"/>
</interface>
</node>
"""
interface_name = "com.revolutionpi.ios1.InpInt"
class InterfaceOutInt(InterfaceInpInt):
"""
<node>
<interface name="com.revolutionpi.ios1.OutInt">
<property name="bmk" type="s" access="read"/>
<property name="name" type="s" access="read"/>
<property name="value" type="i" access="readwrite"/>
</interface>
</node>
"""
interface_name = "com.revolutionpi.ios1.OutInt"

View File

@@ -1,37 +0,0 @@
# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: 2025 KUNBUS GmbH
# SPDX-License-Identifier: GPL-2.0-or-later
"""Helper for io read and write."""
from logging import getLogger
from gi.overrides.GLib import Variant
from pydbus import SessionBus, SystemBus
from pydbus.generic import signal
from revpimodio2.io import IOBase
log = getLogger(__name__)
REVPI_DBUS_NAME = "com.revolutionpi.ios1"
REVPI_DBUS_BASE_PATH = "/com/revolutionpi/ios1"
class DbusInterfaceIo:
interface_name = ""
PropertiesChanged = signal()
def __init__(self, dbus: SystemBus or SessionBus, io: IOBase):
self.dbus = dbus
self.io = io
self.variant_type = "b" if type(self.io.value) is bool else "i"
def emit_io_change(self):
if not self.interface_name:
return
if self.interface_name:
print(type(self.io.value))
self.PropertiesChanged(
self.interface_name,
{"value": int(self.io.value)},
[],
)