IntIOCounter Klasse erweitert mit ioctl Aufruf

Devices erzeugen IntIOCounter-Objekt, wenn Counteradresse gefunden wird
DioModule Klasse wird für DIO / DI / DO verwendet und ermöglicht Counterreset
This commit is contained in:
2018-12-08 20:29:50 +01:00
parent 1e309091e8
commit fc23394298
10 changed files with 186 additions and 21 deletions

View File

@@ -22,7 +22,7 @@ __author__ = "Sven Sager <akira@revpimodio.org>"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "LGPLv3"
__name__ = "revpimodio2"
__version__ = "2.2.5"
__version__ = "2.3.0"
# Global package values
OFF = 0

View File

@@ -258,14 +258,23 @@ class Device(object):
io_new = IOBase(
self, dict_io[key], iotype, "little", False
)
elif isinstance(self, DioModule) and \
dict_io[key][3] in self._lst_counter:
# Counter IO auf einem DI oder DIO
io_new = IntIOCounter(
self._lst_counter.index(dict_io[key][3]),
self, dict_io[key],
iotype,
"little",
False
)
elif isinstance(self, Gateway) and iotype != MEM:
# Ersetzbare IOs erzeugen
io_new = IntIOReplaceable(
self, dict_io[key],
iotype,
"little",
# Bei AIO (103) signed auf True setzen
self._producttype == 103
False
)
else:
io_new = IntIO(
@@ -858,6 +867,32 @@ class Connect(Core):
wdautotoggle = property(_get_wdtoggle, _set_wdtoggle)
class DioModule(Device):
"""Stellt ein DIO / DI / DO Modul dar."""
__slots__ = ("_lst_counter")
def __init__(self, parentmodio, dict_device, simulator=False):
"""Erweitert Device-Klasse zum Erkennen von IntIOCounter.
@see #Device.__init__ Device.__init__(...)"""
# Stringliste der Byteadressen
self._lst_counter = []
# Counter sind 4 Byte lang
producttype = int(dict_device.get("productType"))
if producttype == 96:
# DIO - Counter auf DINT 6 - 66
self._lst_counter = list(map(str, range(6, 70, 4)))
elif producttype == 97:
# DI - Counter auf DINT 4 - 64
self._lst_counter = list(map(str, range(4, 68, 4)))
# Basisklasse laden
super().__init__(parentmodio, dict_device, simulator=simulator)
class Gateway(Device):
"""Klasse fuer die RevPi Gateway-Devices.
@@ -930,6 +965,7 @@ class Virtual(Gateway):
# Outputs auf Bus schreiben
try:
# TODO: globalen FileHandler absichern
self._modio._myfh.seek(self._slc_inpoff.start)
self._modio._myfh.write(self._ba_devdata[self._slc_inp])
if self._modio._buffedwrite:
@@ -943,5 +979,5 @@ class Virtual(Gateway):
# Nachträglicher Import
from .io import IOBase, IntIO, IntIOReplaceable
from .io import IOBase, IntIO, IntIOCounter, IntIOReplaceable
from revpimodio2 import INP, OUT, MEM

View File

@@ -5,9 +5,16 @@ __copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "LGPLv3"
import struct
import warnings
from re import match as rematch
from threading import Event
from revpimodio2 import RISING, FALLING, BOTH, INP, OUT, MEM, consttostr
from .netio import RevPiNetIO
try:
# Funktioniert nur auf Unix
from fcntl import ioctl
except Exception:
ioctl = None
class IOEvent(object):
@@ -789,13 +796,56 @@ class IntIOCounter(IntIO):
"""Erweitert die IntIO-Klasse um die .reset() Funktion fuer Counter."""
__slots__ = ()
__slots__ = ("__ioctl_arg")
def __init__(
self, counter_id,
parentdevice, valuelist, iotype, byteorder, signed):
"""Instantiierung der IntIOCounter-Klasse.
@param counter_id ID fuer den Counter, zu dem der IO gehoert (0-15)
@see #IOBase.__init__ IOBase.__init__(...)
"""
if not (isinstance(counter_id, int) and 0 <= counter_id <= 15):
raise ValueError("counter_id must be <class 'int'> and 0 - 15")
# Deviceposition + Counter_ID
self.__ioctl_arg = \
parentdevice._position.to_bytes(1, "little") + \
(1 << counter_id).to_bytes(2, "big")
# Basisklasse laden
super().__init__(parentdevice, valuelist, iotype, byteorder, signed)
def reset(self):
"""Setzt den Counter des Inputs zurueck."""
# TODO: Counter ID ermitteln
# TODO: Counter reset durchführen
pass
if self._parentdevice._modio._monitoring:
raise RuntimeError(
"can not reset counter, while system is in monitoring mode"
)
if self._parentdevice._modio._simulator:
raise AttributeError(
"can not reset counter, while system is in simulator mode"
)
if isinstance(self._parentdevice._modio, RevPiNetIO):
# TODO: NetFH ansprechen und an RevPiPyLoad senden
warnings.warn("not jet implemented", FutureWarning)
elif self._parentdevice._modio._procimg != "/dev/piControl0":
# NOTE: Soll hier eine 0 in den Input geschrieben werden?
warnings.warn("this will work on a revolution pi only")
elif ioctl is None:
raise RuntimeError(
"can not reset counter on this system without ioctl"
)
else:
# Counter reset durchführen (Funktion K+20)
# TODO: globalen FileHandler absichern
ioctl(self._parentdevice._modio._myfh, 19220, self.__ioctl_arg)
class IntIOReplaceable(IntIO):

View File

@@ -13,12 +13,6 @@ from signal import signal, SIG_DFL, SIGINT, SIGTERM
from threading import Thread, Event
from timeit import default_timer
from . import app as appmodule
from . import device as devicemodule
from . import helper as helpermodule
from . import summary as summarymodule
from .io import IOList
class RevPiModIO(object):
@@ -161,6 +155,7 @@ class RevPiModIO(object):
device["position"] += 1
if device["type"] == "BASE":
# Basedevices
pt = int(device["productType"])
if pt == 95:
# RevPi Core
@@ -180,9 +175,17 @@ class RevPiModIO(object):
self.core = dev_new
elif device["type"] == "LEFT_RIGHT":
# IOs
dev_new = devicemodule.Device(
self, device, simulator=self._simulator
)
pt = int(device["productType"])
if pt == 96 or pt == 97 or pt == 98:
# DIO / DI / DO
dev_new = devicemodule.DioModule(
self, device, simulator=self._simulator
)
else:
# Alle anderen IO-Devices
dev_new = devicemodule.Device(
self, device, simulator=self._simulator
)
elif device["type"] == "VIRTUAL":
# Virtuals
dev_new = devicemodule.Virtual(
@@ -934,4 +937,10 @@ class RevPiModIODriver(RevPiModIOSelected):
# Nachträglicher Import
from . import app as appmodule
from . import device as devicemodule
from . import helper as helpermodule
from . import summary as summarymodule
from .io import IOList
from .netio import RevPiNetIODriver, RevPiNetIO