From fc233942988e35821300092a8eaf622f0a3dae6f Mon Sep 17 00:00:00 2001 From: NaruX Date: Sat, 8 Dec 2018 20:29:50 +0100 Subject: [PATCH] =?UTF-8?q?IntIOCounter=20Klasse=20erweitert=20mit=20ioctl?= =?UTF-8?q?=20Aufruf=20Devices=20erzeugen=20IntIOCounter-Objekt,=20wenn=20?= =?UTF-8?q?Counteradresse=20gefunden=20wird=20DioModule=20Klasse=20wird=20?= =?UTF-8?q?f=C3=BCr=20DIO=20/=20DI=20/=20DO=20verwendet=20und=20erm=C3=B6g?= =?UTF-8?q?licht=20Counterreset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/revpimodio2.device.html | 48 ++++++++++++++++++++++++++++++ doc/revpimodio2.io.html | 21 +++++++++++++- eric-revpimodio2.api | 2 ++ eric-revpimodio2.bas | 1 + revpimodio2.e4p | 4 +-- revpimodio2/__init__.py | 2 +- revpimodio2/device.py | 42 +++++++++++++++++++++++++-- revpimodio2/io.py | 58 ++++++++++++++++++++++++++++++++++--- revpimodio2/modio.py | 27 +++++++++++------ setup.py | 2 +- 10 files changed, 186 insertions(+), 21 deletions(-) diff --git a/doc/revpimodio2.device.html b/doc/revpimodio2.device.html index 9c859f3..d88c158 100644 --- a/doc/revpimodio2.device.html +++ b/doc/revpimodio2.device.html @@ -33,6 +33,9 @@ Classes DeviceList Basisklasse fuer direkten Zugriff auf Device Objekte. +DioModule +Stellt ein DIO / DI / DO Modul dar. + Gateway Klasse fuer die RevPi Gateway-Devices. @@ -1076,6 +1079,51 @@ Attributobjekt
Up


+ +

DioModule

+

+Stellt ein DIO / DI / DO Modul dar. +

+

+Derived from

+Device +

+Class Attributes

+ + +
__slots__
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + +
DioModuleErweitert Device-Klasse zum Erkennen von IntIOCounter.
+

+Static Methods

+ + +
None
+ +

+DioModule (Constructor)

+DioModule(parentmodio, dict_device, simulator=False) +

+Erweitert Device-Klasse zum Erkennen von IntIOCounter. +

+
See Also:
+
+Device.__init__(...) +
+
+
Up
+

Gateway

diff --git a/doc/revpimodio2.io.html b/doc/revpimodio2.io.html index 38ae5a1..e73df59 100644 --- a/doc/revpimodio2.io.html +++ b/doc/revpimodio2.io.html @@ -851,6 +851,9 @@ Class Methods Methods + + + @@ -860,7 +863,23 @@ Static Methods
IntIOCounterInstantiierung der IntIOCounter-Klasse.
reset Setzt den Counter des Inputs zurueck.
None
- + +

+IntIOCounter (Constructor)

+IntIOCounter(counter_id, parentdevice, valuelist, iotype, byteorder, signed) +

+Instantiierung der IntIOCounter-Klasse. +

+
counter_id
+
+ID fuer den Counter, zu dem der IO gehoert (0-15) +
+
+
See Also:
+
+IOBase.__init__(...) +
+

IntIOCounter.reset

reset() diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api index 4ebbb7d..3ecec16 100644 --- a/eric-revpimodio2.api +++ b/eric-revpimodio2.api @@ -58,6 +58,7 @@ revpimodio2.device.Device.syncoutputs?4() revpimodio2.device.Device.writeprocimg?4() revpimodio2.device.Device?1(parentmodio, dict_device, simulator=False) revpimodio2.device.DeviceList?1() +revpimodio2.device.DioModule?1(parentmodio, dict_device, simulator=False) revpimodio2.device.Gateway.get_rawbytes?4() revpimodio2.device.Gateway?1(parent, dict_device, simulator=False) revpimodio2.device.Virtual.writeinputdefaults?4() @@ -126,6 +127,7 @@ revpimodio2.io.IntIO.set_intvalue?4(value) revpimodio2.io.IntIO.signed?7 revpimodio2.io.IntIO.value?7 revpimodio2.io.IntIOCounter.reset?4() +revpimodio2.io.IntIOCounter?1(counter_id, parentdevice, valuelist, iotype, byteorder, signed) revpimodio2.io.IntIOReplaceable.replace_io?4(name, frm, **kwargs) revpimodio2.io.StructIO._get_frm?5() revpimodio2.io.StructIO._get_signed?5() diff --git a/eric-revpimodio2.bas b/eric-revpimodio2.bas index 861f740..56a0c5e 100644 --- a/eric-revpimodio2.bas +++ b/eric-revpimodio2.bas @@ -1,6 +1,7 @@ Base Device Connect Core Core Base +DioModule Device EventCallback Thread Gateway Device IntIO IOBase diff --git a/revpimodio2.e4p b/revpimodio2.e4p index d290131..ea88198 100644 --- a/revpimodio2.e4p +++ b/revpimodio2.e4p @@ -1,7 +1,7 @@ - + en_US @@ -9,7 +9,7 @@ Python3 Console Das Modul stellt alle Devices und IOs aus der piCtory Konfiguration in Python3 zur Verfügung. Es ermöglicht den direkten Zugriff auf die Werte über deren vergebenen Namen. Lese- und Schreibaktionen mit dem Prozessabbild werden von dem Modul selbst verwaltet, ohne dass sich der Programmierer um Offsets und Adressen kümmern muss. Für die Gatewaymodule wie ModbusTCP oder Profinet sind eigene 'Inputs' und 'Outputs' über einen bestimmten Adressbereich definierbar. Auf diese IOs kann mit Python3 über den Namen direkt auf die Werte zugegriffen werden. - 2.2.5 + 2.3.0 Sven Sager akira@narux.de diff --git a/revpimodio2/__init__.py b/revpimodio2/__init__.py index dc5d2ed..222c18c 100644 --- a/revpimodio2/__init__.py +++ b/revpimodio2/__init__.py @@ -22,7 +22,7 @@ __author__ = "Sven Sager " __copyright__ = "Copyright (C) 2018 Sven Sager" __license__ = "LGPLv3" __name__ = "revpimodio2" -__version__ = "2.2.5" +__version__ = "2.3.0" # Global package values OFF = 0 diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 2e695a3..e93bd54 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -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 diff --git a/revpimodio2/io.py b/revpimodio2/io.py index 46eae5c..c53946b 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -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 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): diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index d603992..a9cbeda 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -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 diff --git a/setup.py b/setup.py index d228303..f3cbc88 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ setup( license="LGPLv3", name="revpimodio2", - version="2.2.5", + version="2.3.0", packages=["revpimodio2"], python_requires="~=3.2",