6 Commits

Author SHA1 Message Date
Sven Sager
6d77dcddba feat(io): Integrate com.revolutionpi.ios1 bus to daemon
Signed-off-by: Sven Sager <s.sager@kunbus.com>
2025-05-22 11:09:53 +02:00
Sven Sager
e7768d8b2b doc(io): Add IO example program
Signed-off-by: Sven Sager <s.sager@kunbus.com>
2025-05-22 11:09:26 +02:00
Sven Sager
82c72e918e feat(io): Add dbus policy for com.revolutionpi.ios1 bus
Signed-off-by: Sven Sager <s.sager@kunbus.com>
2025-05-22 11:09:10 +02:00
Sven Sager
1774422dff feat(io): Add dbus bus com.revolutionpi.ios1
Signed-off-by: Sven Sager <s.sager@kunbus.com>
2025-05-22 11:08:48 +02:00
cc560770ce feat(revpiconfig): Make unit config changes asynchronous
Refactored unit enable/disable actions to run in separate threads,
ensuring non-blocking operations. This enhances performance and avoids
potential delays during systemd operations.
2025-04-22 13:42:33 +02:00
4df903783c fix(revpiconfig): Ensure systemd reloads after unit changes
Added systemd reload calls after unit enable/disable to reflect changes.
Adjusted DBus method calls to capture and utilize change outputs
effectively. This improves reliability in applying unit modifications.
2025-04-22 12:35:43 +02:00
16 changed files with 418 additions and 187 deletions

View File

@@ -0,0 +1,22 @@
<!-- /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

@@ -0,0 +1,46 @@
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()

88
debian/changelog vendored
View File

@@ -1,88 +0,0 @@
revpi-middleware (0.0.4-1+deb12+1) bookworm; urgency=medium
* fix(dbus): Update DBus policy file path and interface name
* fix(dbus): Update systemd interface and path handling
* doc(revpiconfig): Add detailed docstrings to ConfigTxt methods
* doc(revpiconfig): Add docstrings to `RevPiConfig` class and methods
* doc(revpiconfig): Add docstrings to enums in `revpi_config.py`
* doc(revpiconfig): Docstrings for `get_rfkill_index` and `simple_systemd`
-- Sven Sager <s.sager@kunbus.com> Tue, 22 Apr 2025 11:08:12 +0200
revpi-middleware (0.0.3-1+deb12+1) bookworm; urgency=medium
* refactor: Update interface name from 'picontrol' to 'PiControl'
* feat(dbus): Add `grep` function to search for patterns in a file
* fix(cli): Change absolute imports to relative imports
* feat(dbus): Add D-Bus interface for system configuration in middleware
* feat(dbus): Add GUI configuration handling to interface_config.py
* feat(revpiconfig): Add RevPiConfig class for device information handling
* refactor(dbus): Move system configuration methods to revpi_config.py
* feat(dbus): Remove 'var-log.mount' feature
* feat(dbus): Add avahi-daemon configuration to system services
* feat(dbus): Add dphys-swapfile configuration functionality
* feat(revpiconfig): Add ConfigTxt class for managing config.txt file
* feat(dbus): Add support for configuring the external antenna
* feat(dbus): Add support for configuring 'revpi-con-can' feature
* feat(revpiconfig): Enhance Wi-Fi detection and add rfkill index support
* feat(dbus): Add Wi-Fi configuration support to the system config
* refactor(revpiconfig: Change Wi-Fi detection and rfkill index logic
* feat(dbus): Add Bluetooth configuration functionality
* feat(dbus): Add InterfaceRevpiConfig to DBus interfaces list
* feat(cli): Add `get_properties` helper function for DBus interactions
* feat(cli): Add CLI command for configuring Revpi features
* feat(cli): Add CLI support for RevPi configuration object (revpi-config)
* feat(revpiconfig): Replace rfkill subprocess calls with sysfs writes
* refactor: Rename WiFi to WLAN for consistent terminology
* feat(deb): Add dependencies for `dtoverlay` command
-- Sven Sager <s.sager@kunbus.com> Mon, 21 Apr 2025 13:44:18 +0200
revpi-middleware (0.0.2-1+deb12+1) bookworm; urgency=medium
* refactor(dbus): Move D-Bus helper functions to a dedicated file
* refactor(dbus): Move ResetDriverWatchdog to process_image_helper.py
* refactor(dbus): Parameterize `picontrol_device` and `config_rsc`
* feat: Add session bus option for local testing and development
* feat(dbus): Add import for BusProvider in dbus_middleware1 module
* feat(dbus): Add `running` property to `BusProvider`
* refactor(cli): D-Bus helpers support session and system bus types
* fix(dbus): Add error handling for DBus publishing and main loop
* refactor(dbus): piControl driver reset with PiControlIoctl class
* test(dbus): Add unit test framework for dbus_middleware1 module
* test(dbus): Add unit tests for PiControl D-Bus interface
* refactor(dbus): Fix typo and remove unused thread instance
* refactor(dbus): D-Bus interface management with cleanup support.
* test(dbus): Add support for testing driver reset notification
* feat(deb): Add dbus for testing to build dependencies
* fix(deb): Skip tests because of missing SystemBus in build container
-- Sven Sager <s.sager@kunbus.com> Sat, 19 Apr 2025 16:34:20 +0200
revpi-middleware (0.0.1-1+deb12+1) bookworm; urgency=medium
* docs: Start git project with python git-ignore and Readme
* docs: Use 'reuse' for SPDX Headers and Licenses
* feat: Add python base project files
* feat: Add proginit application basic module
* feat: Add the data directory for additional data files for the project
* test: Add tests directory with a dummy test
* build: Add all necessary files for the build system
* feat: Add dummy main application script
* feat: Add systemd file and data to integrate the app as a daemon
* chore: Update proginit to 1.4.0
* feat(dbus): Add ResetDriverWatchdog helper as global dbus helper
* feat(process_image): Add D-Bus interface for piControl driver
* feat(dbus): Add initial D-Bus middleware implementation
* feat(dbus): Add `extend_interface` function for dynamic interface naming
* feat(dbus): Add DBus policy configuration for revpi-middleware
* feat: Add MiddlewareDaemon implementation to revpi-middleware
* feat: Add daemon mode and signal handling to main application
* feat(cli): Add D-Bus helper functions for CLI commands.
* feat(cli): Add await_signal function to handle D-Bus signals
* feat(cli): Add `await-reset` to wait for piControl reset signal
* chore(build): Update requirements for this project
* feat(cli): Add new CLI tool entry point for `revpictl`
* feat(deb): Start packaging branch
-- Sven Sager <s.sager@kunbus.com> Fri, 18 Apr 2025 19:02:20 +0200

39
debian/control vendored
View File

@@ -1,39 +0,0 @@
Source: revpi-middleware
Section: python
Priority: optional
Maintainer: KUNBUS GmbH <support@kunbus.com>
Rules-Requires-Root: no
Homepage: https://revolutionpi.com/
Vcs-Browser: https://gitlab.com/revolutionpi/revpi-middleware
Vcs-Git: https://gitlab.com/revolutionpi/revpi-middleware.git -b debian/bookworm
Build-Depends:
dbus,
dbus-x11,
debhelper-compat (= 13),
dh-python,
python3-all,
python3-gi (>= 3.42.2),
python3-pydbus (>= 0.6.0),
python3-setuptools,
Standards-Version: 4.6.2
Package: revpi-middleware
Architecture: all
Pre-Depends: ${misc:Pre-Depends}
Depends:
raspi-utils-dt | libraspberrypi-bin,
${python3:Depends},
${misc:Depends}
Description: Revolution Pi middleware with D-Bus interface
The Revolution Pi middleware provides a robust communication interface for
Revolution Pi industrial computers. It enables seamless integration between
hardware components and applications through a D-Bus interface. The middleware
serves as a bridge for data exchange, device configuration, and system
monitoring.
.
Key features:
* Hardware abstraction layer for Revolution Pi I/O modules
* Real-time data processing and event handling
* Simplified API for accessing Revolution Pi hardware features
* Extensive configuration options for industrial automation tasks
* Built-in monitoring and diagnostic capabilities

27
debian/copyright vendored
View File

@@ -1,27 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https://gitlab.com/revolutionpi/opcua-revpi-server
Files: *
Copyright: 2025 KUNBUS GmbH
License: GPL-2+
Files: debian/*
Copyright: 2025 KUNBUS GmbH
License: GPL-2+
License: GPL-2+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".

7
debian/gbp.conf vendored
View File

@@ -1,7 +0,0 @@
[DEFAULT]
upstream-branch = main
upstream-tag = v%(version)s
debian-branch=debian/bookworm
debian-tag = debian/%(version)s
debian-tag-msg = %(pkg)s Debian release %(version)s
pristine-tar = True

View File

@@ -1,4 +0,0 @@
data/dbus-policy/com.revolutionpi.middleware1.conf /usr/share/dbus-1/system.d
data/etc/default/revpi-middleware /etc/default/
data/etc/revpi-middleware/revpi-middleware.conf /etc/revpi-middleware/
data/systemd/before_253/revpi-middleware.service /lib/systemd/system/

View File

@@ -1,2 +0,0 @@
/usr/share/revpi-middleware/revpi-middleware /usr/sbin/revpi-middleware
/usr/share/revpi-middleware/revpicli /usr/bin/revpicli

12
debian/rules vendored
View File

@@ -1,12 +0,0 @@
#!/usr/bin/make -f
export PYBUILD_NAME=revpi-middleware
export PYBUILD_INSTALL_ARGS=--install-lib=/usr/share/$(PYBUILD_NAME)/ --install-scripts=/usr/share/$(PYBUILD_NAME)/
%:
dh $@ --with python3 --buildsystem=pybuild
override_dh_auto_test:
# Currently, the tests have to be skipped, because no SystemBus is
# available in the Docker container.
@echo "Skipped tests"

View File

@@ -1 +0,0 @@
3.0 (quilt)

View File

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

View File

@@ -10,6 +10,7 @@ from glob import glob
from logging import getLogger from logging import getLogger
from os import X_OK, access from os import X_OK, access
from os.path import exists, join from os.path import exists, join
from threading import Thread
from typing import List, Optional from typing import List, Optional
from pydbus import SystemBus from pydbus import SystemBus
@@ -665,13 +666,39 @@ def simple_systemd(action: ConfigActions, unit: str):
systemd_manager = systemd["org.freedesktop.systemd1.Manager"] systemd_manager = systemd["org.freedesktop.systemd1.Manager"]
if action is ConfigActions.ENABLE: if action is ConfigActions.ENABLE:
systemd_manager.UnmaskUnitFiles([unit], False)
systemd_manager.EnableUnitFiles([unit], False, False) 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.StartUnit(unit, "replace") systemd_manager.StartUnit(unit, "replace")
elif action is ConfigActions.DISABLE: 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.StopUnit(unit, "replace")
systemd_manager.DisableUnitFiles([unit], False)
elif action is ConfigActions.STATUS: elif action is ConfigActions.STATUS:
try: try:
@@ -696,6 +723,8 @@ def simple_systemd(action: ConfigActions, unit: str):
else: else:
raise ValueError(f"action {action} not supported") raise ValueError(f"action {action} not supported")
return None
if __name__ == "__main__": if __name__ == "__main__":
rc = RevPiConfig() rc = RevPiConfig()

View File

@@ -0,0 +1,5 @@
# -*- 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

@@ -0,0 +1,100 @@
# -*- 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

@@ -0,0 +1,159 @@
# -*- 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

@@ -0,0 +1,37 @@
# -*- 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)},
[],
)