From cc689a58eb443b3f9a51308eb36ced28bcb4b9b3 Mon Sep 17 00:00:00 2001 From: Sven Sager Date: Wed, 1 Nov 2023 11:12:43 +0100 Subject: [PATCH] feat: Add support for RO device This adds the RO device as its own class. The RO device has a special ioctl function, via which the switching cycles of the relays can be called up. Relay outputs from the RO device get the additional attribute 'cycles', which returns the number of switching cycles. The implementation via RevPiNetIO classes cannot currently be implemented because the server does not support a return value. Signed-off-by: Sven Sager --- src/revpimodio2/device.py | 23 +++++++- src/revpimodio2/io.py | 119 ++++++++++++++++++++++++++++++++++++++ src/revpimodio2/modio.py | 3 + 3 files changed, 144 insertions(+), 1 deletion(-) diff --git a/src/revpimodio2/device.py b/src/revpimodio2/device.py index 5e65de1..263265e 100644 --- a/src/revpimodio2/device.py +++ b/src/revpimodio2/device.py @@ -10,7 +10,7 @@ from threading import Event, Lock, Thread from ._internal import INP, OUT, MEM, PROCESS_IMAGE_SIZE from .helper import ProcimgWriter -from .io import IOBase, IntIO, IntIOCounter, IntIOReplaceable, MemIO +from .io import IOBase, IntIO, IntIOCounter, IntIOReplaceable, MemIO, RelaisOutput, IntRelaisOutput from .pictory import ProductType @@ -333,6 +333,15 @@ class Device(object): if iotype == MEM: # Memory setting io_new = MemIO(self, dict_io[key], iotype, "little", False) + elif isinstance(self, RoModule) and dict_io[key][3] == "1": + # Relais of RO are on device address "1" and has a cycle counter + if dict_io[key][7]: + # Each relais output has a single bit + io_new = RelaisOutput(self, dict_io[key], iotype, "little", False) + else: + # All relais outputs are in one byte + io_new = IntRelaisOutput(self, dict_io[key], iotype, "little", False) + elif bool(dict_io[key][7]): # Bei Bitwerten IOBase verwenden io_new = IOBase(self, dict_io[key], iotype, "little", False) @@ -1918,6 +1927,18 @@ class DioModule(Device): super().__init__(parentmodio, dict_device, simulator=simulator) +class RoModule(Device): + """Relais output (RO) module with""" + + def __init__(self, parentmodio, dict_device, simulator=False): + """ + Relais outputs of this device has a cycle counter for the relais. + + :rev: :func:`Device.__init__()` + """ + super().__init__(parentmodio, dict_device, simulator=simulator) + + class Gateway(Device): """ Klasse fuer die RevPi Gateway-Devices. diff --git a/src/revpimodio2/io.py b/src/revpimodio2/io.py index b78dfd7..4dae8bd 100644 --- a/src/revpimodio2/io.py +++ b/src/revpimodio2/io.py @@ -1187,6 +1187,125 @@ class IntIOReplaceable(IntIO): ) +class RelaisOutput(IOBase): + """ + Class for relais outputs to access the cycle counters. + + This class extends the function of to the function + 'get_cycles' and the property 'cycles' to retrieve the relay cycle + counters. + + :ref: :class:`IOBase` + """ + + def __init__(self, parentdevice, valuelist, iotype, byteorder, signed): + """ + Extend with functions to access cycle counters. + + :ref: :func:`IOBase.__init__(...)` + """ + super().__init__(parentdevice, valuelist, iotype, byteorder, signed) + + """ + typedef struct SROGetCountersStr + { + /* Address of module in current configuration */ + uint8_t i8uAddress; + uint32_t counter[REVPI_RO_NUM_RELAY_COUNTERS]; + } SROGetCounters; + """ + # Device position + padding + four counter with 4 byte each + self.__ioctl_arg_format = " and + to add the function 'get_cycles' and the property + 'cycles' to retrieve the relay cycle counters. + + Since both classes inherit from BaseIO, both __init__ functions are called + and the logic is combined. In this case, there is only one 'self' object of + IOBase, which of both classes in inheritance is extended with this. + + :ref: :class:`IOBase` + """ + + pass + + class StructIO(IOBase): """ Klasse fuer den Zugriff auf Daten ueber ein definierten struct. diff --git a/src/revpimodio2/modio.py b/src/revpimodio2/modio.py index 49abefd..38bceb1 100644 --- a/src/revpimodio2/modio.py +++ b/src/revpimodio2/modio.py @@ -353,6 +353,9 @@ class RevPiModIO(object): if pt == ProductType.DIO or pt == ProductType.DI or pt == ProductType.DO: # DIO / DI / DO dev_new = devicemodule.DioModule(self, device, simulator=self._simulator) + elif pt == ProductType.RO: + # RO + dev_new = devicemodule.RoModule(self, device, simulator=self._simulator) else: # Alle anderen IO-Devices dev_new = devicemodule.Device(self, device, simulator=self._simulator)