diff --git a/src/revpi_middleware/ios1/__init__.py b/src/revpi_middleware/ios1/__init__.py
new file mode 100644
index 0000000..7abf777
--- /dev/null
+++ b/src/revpi_middleware/ios1/__init__.py
@@ -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
diff --git a/src/revpi_middleware/ios1/bus_provider_io.py b/src/revpi_middleware/ios1/bus_provider_io.py
new file mode 100644
index 0000000..27eb20d
--- /dev/null
+++ b/src/revpi_middleware/ios1/bus_provider_io.py
@@ -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()
diff --git a/src/revpi_middleware/ios1/interface_ios.py b/src/revpi_middleware/ios1/interface_ios.py
new file mode 100644
index 0000000..36a0943
--- /dev/null
+++ b/src/revpi_middleware/ios1/interface_ios.py
@@ -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:
+ """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+
+ 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):
+ """
+
+
+
+
+
+
+
+ """
+
+ 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):
+ """
+
+
+
+
+
+
+
+ """
+
+ 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):
+ """
+
+
+
+
+
+
+
+ """
+
+ interface_name = "com.revolutionpi.ios1.InpInt"
+
+
+class InterfaceOutInt(InterfaceInpInt):
+ """
+
+
+
+
+
+
+
+ """
+
+ interface_name = "com.revolutionpi.ios1.OutInt"
diff --git a/src/revpi_middleware/ios1/ios1_helper.py b/src/revpi_middleware/ios1/ios1_helper.py
new file mode 100644
index 0000000..82f956a
--- /dev/null
+++ b/src/revpi_middleware/ios1/ios1_helper.py
@@ -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)},
+ [],
+ )