From 4b8fd5a2b6a531100f63168e61c7848368d38be6 Mon Sep 17 00:00:00 2001 From: NaruX Date: Fri, 27 Jul 2018 11:30:33 +0200 Subject: [PATCH 01/14] =?UTF-8?q?Erste=20Anpassungen=20f=C3=BCr=20RevPiCon?= =?UTF-8?q?nect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- revpimodio2.e4p | 4 ++-- revpimodio2/__init__.py | 2 +- revpimodio2/device.py | 2 +- revpimodio2/netio.py | 4 +++- setup.py | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/revpimodio2.e4p b/revpimodio2.e4p index ed44df3..662e053 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.1.6 + 2.2.0 Sven Sager akira@narux.de diff --git a/revpimodio2/__init__.py b/revpimodio2/__init__.py index 34507f3..d2e2fe4 100644 --- a/revpimodio2/__init__.py +++ b/revpimodio2/__init__.py @@ -25,7 +25,7 @@ __all__ = [ __author__ = "Sven Sager " __name__ = "revpimodio2" __package__ = "revpimodio2" -__version__ = "2.1.6" +__version__ = "2.2.0" # Global package values OFF = 0 diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 2cdd2e5..472ffee 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -236,7 +236,7 @@ class Device(object): for key in sorted(dict_io, key=lambda x: int(x)): # Neuen IO anlegen - if bool(dict_io[key][7]) or self._producttype == 95: + if bool(dict_io[key][7]) or isinstance(self, Core): # Bei Bitwerten oder Core RevPiIOBase verwenden io_new = IOBase( self, dict_io[key], iotype, "little", False diff --git a/revpimodio2/netio.py b/revpimodio2/netio.py index b8bf4e6..2d8b7b3 100644 --- a/revpimodio2/netio.py +++ b/revpimodio2/netio.py @@ -37,7 +37,9 @@ class NetFH(Thread): """ def __init__(self, address, timeout=500): - """Init NetFH-class.""" + """Init NetFH-class. + @param address IP Adresse des RevPi + @param timeout Timeout in Millisekunden der Verbindung""" super().__init__() self.daemon = True diff --git a/setup.py b/setup.py index da01631..76626d4 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ setup( license="LGPLv3", name="revpimodio2", - version="2.1.6", + version="2.2.0", packages=["revpimodio2"], python_requires="~=3.2", From 2ab799971f1b44ea0f4ea4652b55e8aba0018d82 Mon Sep 17 00:00:00 2001 From: NaruX Date: Sun, 29 Jul 2018 08:54:33 +0200 Subject: [PATCH 02/14] =?UTF-8?q?Verbesserung=20in=20LED=5FBYTE-Berechnung?= =?UTF-8?q?=20Byteorder=20f=C3=BCr=20Core-Funktionen=20fest=20auf=20"littl?= =?UTF-8?q?e"=20gesetzt=20Connect-Klasse=20von=20Core=20abgeleitet=20A3=20?= =?UTF-8?q?zur=20Connect=20Klasse=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/revpimodio2.device.html | 108 ++++++++++++++++++++++-- doc/revpimodio2.netio.html | 10 ++- eric-revpimodio2.api | 5 ++ eric-revpimodio2.bas | 1 + revpimodio2/device.py | 164 ++++++++++++++++++++++++++---------- revpimodio2/modio.py | 15 +++- 6 files changed, 247 insertions(+), 56 deletions(-) diff --git a/doc/revpimodio2.device.html b/doc/revpimodio2.device.html index c67d0b4..717b007 100644 --- a/doc/revpimodio2.device.html +++ b/doc/revpimodio2.device.html @@ -18,6 +18,9 @@ Global Attributes Classes + + + @@ -40,6 +43,78 @@ Functions
ConnectKlasse fuer den RevPi Connect.
Core Klasse fuer den RevPi Core.
None


+ +

Connect

+

+Klasse fuer den RevPi Connect. +

+ Stellt Funktionen fuer die LEDs, Watchdog und den Status zur Verfuegung. +

+ +

+

+Derived from

+Core +

+Class Attributes

+ + +
A3
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + + + + + + + +
_devconfigureConnect-Klasse vorbereiten.
_get_leda3Gibt den Zustand der LED A3 vom Connect zurueck.
_set_leda3Setzt den Zustand der LED A3 vom Connect.
+

+Static Methods

+ + +
None
+ +

+Connect._devconfigure

+_devconfigure() +

+Connect-Klasse vorbereiten. +

+

+Connect._get_leda3

+_get_leda3() +

+Gibt den Zustand der LED A3 vom Connect zurueck. +

+
Returns:
+
+0=aus, 1=gruen, 2=rot +
+
+

+Connect._set_leda3

+_set_leda3(value) +

+Setzt den Zustand der LED A3 vom Connect. +

+
value
+
+0=aus, 1=gruen, 2=rot +
+
+ +

Core

@@ -73,19 +148,22 @@ Methods Core-Klasse vorbereiten. _get_leda1 -Gibt den Zustand der LED A1 vom core zurueck. +Gibt den Zustand der LED A1 vom Core zurueck. _get_leda2 -Gibt den Zustand der LED A2 vom core zurueck. +Gibt den Zustand der LED A2 vom Core zurueck. _get_status Gibt den RevPi Core Status zurueck. +_set_calculatedled +Berechnet und setzt neuen Bytewert fuer LED byte. + _set_leda1 -Setzt den Zustand der LED A1 vom core. +Setzt den Zustand der LED A1 vom Core. _set_leda2 -Setzt den Zustand der LED A2 vom core. +Setzt den Zustand der LED A2 vom Core. errorlimit1 Setzt RS485 ErrorLimit1 auf neuen Wert. @@ -156,7 +234,7 @@ Core-Klasse vorbereiten. Core._get_leda1 _get_leda1()

-Gibt den Zustand der LED A1 vom core zurueck. +Gibt den Zustand der LED A1 vom Core zurueck.

Returns:
@@ -167,7 +245,7 @@ Gibt den Zustand der LED A1 vom core zurueck. Core._get_leda2 _get_leda2()

-Gibt den Zustand der LED A2 vom core zurueck. +Gibt den Zustand der LED A2 vom Core zurueck.

Returns:
@@ -184,12 +262,26 @@ Gibt den RevPi Core Status zurueck.
Status als
+
+

+Core._set_calculatedled

+_set_calculatedled(addresslist, shifted_value) +

+Berechnet und setzt neuen Bytewert fuer LED byte. +

+
addresslist
+
+Liste der Vergleicher +
shifed_value
+
+Bits vergleichen +

Core._set_leda1

_set_leda1(value)

-Setzt den Zustand der LED A1 vom core. +Setzt den Zustand der LED A1 vom Core.

value
@@ -200,7 +292,7 @@ Setzt den Zustand der LED A1 vom core. Core._set_leda2 _set_leda2(value)

-Setzt den Zustand der LED A2 vom core. +Setzt den Zustand der LED A2 vom Core.

value
diff --git a/doc/revpimodio2.netio.html b/doc/revpimodio2.netio.html index 801fb5d..0f6943f 100644 --- a/doc/revpimodio2.netio.html +++ b/doc/revpimodio2.netio.html @@ -128,7 +128,15 @@ NetFH (Constructor) NetFH(address, timeout=500)

Init NetFH-class. -

+

+
address
+
+IP Adresse des RevPi +
timeout
+
+Timeout in Millisekunden der Verbindung +
+

NetFH.__del__

__del__() diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api index 8caa1cc..c02b6a2 100644 --- a/eric-revpimodio2.api +++ b/eric-revpimodio2.api @@ -9,12 +9,17 @@ revpimodio2.RED?7 revpimodio2.RISING?7 revpimodio2.app.App?1(app) revpimodio2.consttostr?4(value) +revpimodio2.device.Connect.A3?7 +revpimodio2.device.Connect._devconfigure?5() +revpimodio2.device.Connect._get_leda3?5() +revpimodio2.device.Connect._set_leda3?5(value) revpimodio2.device.Core.A1?7 revpimodio2.device.Core.A2?7 revpimodio2.device.Core._devconfigure?5() revpimodio2.device.Core._get_leda1?5() revpimodio2.device.Core._get_leda2?5() revpimodio2.device.Core._get_status?5() +revpimodio2.device.Core._set_calculatedled?5(addresslist, shifted_value) revpimodio2.device.Core._set_leda1?5(value) revpimodio2.device.Core._set_leda2?5(value) revpimodio2.device.Core.errorlimit1?4(value) diff --git a/eric-revpimodio2.bas b/eric-revpimodio2.bas index 0edb3bc..9dcf76d 100644 --- a/eric-revpimodio2.bas +++ b/eric-revpimodio2.bas @@ -1,3 +1,4 @@ +Connect Core Core Device EventCallback Thread Gateway Device diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 472ffee..5dab905 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -246,6 +246,7 @@ class Device(object): self, dict_io[key], iotype, "little", + # Bei AIO (103) signed auf True setzen self._producttype == 103 ) @@ -421,7 +422,7 @@ class Core(Device): self._ioerrorlimit1 = 4 self._ioerrorlimit2 = 5 elif int_lenio == 8: - # core 1.2 + # Core 1.2 self._iocycle = 1 self._ioerrorcnt = 2 self._iotemperature = 3 @@ -449,14 +450,13 @@ class Core(Device): @return Aktuellen ErrorLimit oder None wenn nicht verfuegbar""" if errorlimit is None: return None if io_id is None else int.from_bytes( - self.__lst_io[io_id].get_value(), - byteorder=self.__lst_io[io_id]._byteorder + self.__lst_io[io_id].get_value(), byteorder="little" ) else: if 0 <= errorlimit <= 65535: - self.__lst_io[io_id].set_value(errorlimit.to_bytes( - 2, byteorder=self.__lst_io[io_id]._byteorder - )) + self.__lst_io[io_id].set_value( + errorlimit.to_bytes(2, byteorder="little") + ) else: raise ValueError( "errorlimit value must be between 0 and 65535" @@ -466,50 +466,65 @@ class Core(Device): """Gibt den RevPi Core Status zurueck. @return Status als """ return int.from_bytes( - self.__lst_io[0].get_value(), byteorder=self.__lst_io[0]._byteorder + self.__lst_io[0].get_value(), byteorder="little" ) def _get_leda1(self): - """Gibt den Zustand der LED A1 vom core zurueck. + """Gibt den Zustand der LED A1 vom Core zurueck. @return 0=aus, 1=gruen, 2=rot""" int_led = int.from_bytes( - self.__lst_io[self._ioled].get_value(), - byteorder=self.__lst_io[self._ioled]._byteorder + self.__lst_io[self._ioled].get_value(), byteorder="little" ) led = int_led & 1 led += int_led & 2 return led def _get_leda2(self): - """Gibt den Zustand der LED A2 vom core zurueck. + """Gibt den Zustand der LED A2 vom Core zurueck. @return 0=aus, 1=gruen, 2=rot""" int_led = int.from_bytes( - self.__lst_io[self._ioled].get_value(), - byteorder=self.__lst_io[self._ioled]._byteorder + self.__lst_io[self._ioled].get_value(), byteorder="little" ) >> 2 led = int_led & 1 led += int_led & 2 return led + def _set_calculatedled(self, addresslist, shifted_value): + """Berechnet und setzt neuen Bytewert fuer LED byte. + @param addresslist Liste der Vergleicher + @param shifed_value Bits vergleichen""" + # Byte als int holen + int_led = int.from_bytes( + self.__lst_io[self._ioled].get_value(), byteorder="little" + ) + + for int_bit in addresslist: + value = bool(shifted_value & int_bit) + if bool(int_led & 1) != value: + # Berechnen, wenn verändert + if value: + int_led += int_bit + else: + int_led -= int_bit + + # Zurückschreiben wenn verändert + self.__lst_io[self._ioled].set_value( + int_led.to_bytes(length=1, byteorder="little") + ) + def _set_leda1(self, value): - """Setzt den Zustand der LED A1 vom core. + """Setzt den Zustand der LED A1 vom Core. @param value 0=aus, 1=gruen, 2=rot""" if 0 <= value <= 3: - int_led = (self._get_leda2() << 2) + value - self.__lst_io[self._ioled].set_value(int_led.to_bytes( - length=1, byteorder=self.__lst_io[self._ioled]._byteorder - )) + self._set_calculatedled([1, 2], value) else: raise ValueError("led status must be between 0 and 3") def _set_leda2(self, value): - """Setzt den Zustand der LED A2 vom core. + """Setzt den Zustand der LED A2 vom Core. @param value 0=aus, 1=gruen, 2=rot""" if 0 <= value <= 3: - int_led = (value << 2) + self._get_leda1() - self.__lst_io[self._ioled].set_value(int_led.to_bytes( - length=1, byteorder=self.__lst_io[self._ioled]._byteorder - )) + self._set_calculatedled([4, 8], value << 2) else: raise ValueError("led status must be between 0 and 3") @@ -522,8 +537,7 @@ class Core(Device): """Statusbit fuer piControl-Treiber laeuft. @return True, wenn Treiber laeuft""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), - byteorder=self.__lst_io[0]._byteorder + self.__lst_io[0].get_value(), byteorder="little" ) & 1) @property @@ -531,8 +545,7 @@ class Core(Device): """Statusbit fuer ein IO-Modul nicht mit PiCtory konfiguriert. @return True, wenn IO Modul nicht konfiguriert""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), - byteorder=self.__lst_io[0]._byteorder + self.__lst_io[0].get_value(), byteorder="little" ) & 2) @property @@ -540,8 +553,7 @@ class Core(Device): """Statusbit fuer ein IO-Modul fehlt oder piGate konfiguriert. @return True, wenn IO-Modul fehlt oder piGate konfiguriert""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), - byteorder=self.__lst_io[0]._byteorder + self.__lst_io[0].get_value(), byteorder="little" ) & 4) @property @@ -549,8 +561,7 @@ class Core(Device): """Statusbit Modul belegt mehr oder weniger Speicher als konfiguriert. @return True, wenn falscher Speicher belegt ist""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), - byteorder=self.__lst_io[0]._byteorder + self.__lst_io[0].get_value(), byteorder="little" ) & 8) @property @@ -558,8 +569,7 @@ class Core(Device): """Statusbit links vom RevPi ist ein piGate Modul angeschlossen. @return True, wenn piGate links existiert""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), - byteorder=self.__lst_io[0]._byteorder + self.__lst_io[0].get_value(), byteorder="little" ) & 16) @property @@ -567,8 +577,7 @@ class Core(Device): """Statusbit rechts vom RevPi ist ein piGate Modul angeschlossen. @return True, wenn piGate rechts existiert""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), - byteorder=self.__lst_io[0]._byteorder + self.__lst_io[0].get_value(), byteorder="little" ) & 32) @property @@ -576,8 +585,7 @@ class Core(Device): """Gibt Zykluszeit der Prozessabbildsynchronisierung zurueck. @return Zykluszeit in ms""" return None if self._iocycle is None else int.from_bytes( - self.__lst_io[self._iocycle].get_value(), - byteorder=self.__lst_io[self._iocycle]._byteorder + self.__lst_io[self._iocycle].get_value(), byteorder="little" ) @property @@ -585,8 +593,7 @@ class Core(Device): """Gibt CPU-Temperatur zurueck. @return CPU-Temperatur in Celsius""" return None if self._iotemperature is None else int.from_bytes( - self.__lst_io[self._iotemperature].get_value(), - byteorder=self.__lst_io[self._iotemperature]._byteorder + self.__lst_io[self._iotemperature].get_value(), byteorder="little" ) @property @@ -594,8 +601,7 @@ class Core(Device): """Gibt CPU Taktfrequenz zurueck. @return CPU Taktfrequenz in MHz""" return None if self._iofrequency is None else int.from_bytes( - self.__lst_io[self._iofrequency].get_value(), - byteorder=self.__lst_io[self._iofrequency]._byteorder + self.__lst_io[self._iofrequency].get_value(), byteorder="little" ) * 10 @property @@ -603,8 +609,7 @@ class Core(Device): """Gibt Fehleranzahl auf RS485 piBridge Bus zurueck. @return Fehleranzahl der piBridge""" return None if self._ioerrorcnt is None else int.from_bytes( - self.__lst_io[self._ioerrorcnt].get_value(), - byteorder=self.__lst_io[self._ioerrorcnt]._byteorder + self.__lst_io[self._ioerrorcnt].get_value(), byteorder="little" ) @property @@ -632,6 +637,79 @@ class Core(Device): self.__errorlimit(self._ioerrorlimit2, value) +class Connect(Core): + + """Klasse fuer den RevPi Connect. + + Stellt Funktionen fuer die LEDs, Watchdog und den Status zur Verfuegung. + + """ + + def _devconfigure(self): + """Connect-Klasse vorbereiten.""" + super()._devconfigure() + + # TODO: IO Objekte für WD und X2 erzeugen + self.wd = None + self.x2in = None + self.x2out = None + + def _get_leda3(self): + """Gibt den Zustand der LED A3 vom Connect zurueck. + @return 0=aus, 1=gruen, 2=rot""" + int_led = int.from_bytes( + self.__lst_io[self._ioled].get_value(), byteorder="little" + ) >> 4 + led = int_led & 1 + led += int_led & 2 + return led + +# def _get_wd(self): +# """Gibt den Zustand des Watchdogs vom Connect zurueck. +# @return True / False muss getriggert werden""" +# int_led = int.from_bytes( +# self.__lst_io[self._ioled].get_value(), byteorder="little" +# ) +# return bool(int_led & 64) +# +# def _get_x2out(self): +# """Gibt den Zustand des Relais X2 vom Connect zurueck. +# @return True, wenn Relais geschlossen""" +# int_led = int.from_bytes( +# self.__lst_io[self._ioled].get_value(), byteorder="little" +# ) +# return bool(int_led & 128) + + def _set_leda3(self, value): + """Setzt den Zustand der LED A3 vom Connect. + @param value 0=aus, 1=gruen, 2=rot""" + if 0 <= value <= 3: + self._set_calculatedled([16, 32], value << 4) + else: + raise ValueError("led status must be between 0 and 3") + +# def _set_wd(self, value): +# """Setzt den Zustand des Watchdogs vom Connect. +# @param value True / False muss getriggert werden""" +# if isinstance(value, bool): +# self._set_calculatedled([128], 128) +# else: +# raise ValueError("value must be True / False") +# +# def _set_x2out(self, value): +# """Setzt den Zustand des Watchdogs vom Connect. +# @param value True / False muss getriggert werden""" +# if isinstance(value, bool): +# self._set_calculatedled([64], 64) +# else: +# raise ValueError("value must be True / False") + + A3 = property(_get_leda3, _set_leda3) +# WD = property(_get_wd, _set_wd) +# X2IN = property(_get_x2in) +# X2OUT = property(_get_x2out, _set_x2out) + + class Gateway(Device): """Klasse fuer die RevPi Gateway-Devices. diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index ff4c193..15472a7 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -150,10 +150,17 @@ class RevPiModIO(object): device["position"] += 1 if device["type"] == "BASE": - # Core - dev_new = devicemodule.Core( - self, device, simulator=self._simulator - ) + pt = int(device["productType"]) + if pt == 105: + # RevPi Connect + dev_new = devicemodule.Connect( + self, device, simulator=self._simulator + ) + else: + # RevPi Core immer als Fallback verwenden + dev_new = devicemodule.Core( + self, device, simulator=self._simulator + ) self.core = dev_new elif device["type"] == "LEFT_RIGHT": # IOs From c10f36001fc64014c3c3bbad2b9932470af9f7fa Mon Sep 17 00:00:00 2001 From: NaruX Date: Mon, 30 Jul 2018 12:24:12 +0200 Subject: [PATCH 03/14] =?UTF-8?q?IO=20Zuordnung=20in=20Core-Klasse=20jetzt?= =?UTF-8?q?=20IOBase=20Objekt=20kein=20Index=20mehr=20Watchdog=20und=20X2?= =?UTF-8?q?=20in/out=20werden=20als=20IOBase=20Objekte=20=C3=BCber=20core?= =?UTF-8?q?=20angeboten?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/revpimodio2.device.html | 6 +- revpimodio2/device.py | 141 +++++++++++++++--------------------- 2 files changed, 60 insertions(+), 87 deletions(-) diff --git a/doc/revpimodio2.device.html b/doc/revpimodio2.device.html index 717b007..0d5dd29 100644 --- a/doc/revpimodio2.device.html +++ b/doc/revpimodio2.device.html @@ -210,13 +210,13 @@ Static Methods

Core.__errorlimit

-__errorlimit(io_id, errorlimit) +__errorlimit(io, errorlimit)

Verwaltet das Lesen und Schreiben der ErrorLimits.

-
io_id
+
io
-Index des IOs fuer ErrorLimit +IOs Objekt fuer ErrorLimit
Returns:
diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 5dab905..b7b2d08 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -402,59 +402,60 @@ class Core(Device): def _devconfigure(self): """Core-Klasse vorbereiten.""" + # Eigene IO-Liste aufbauen + lst_io = [x for x in self.__iter__()] + + self._iostatusbyte = lst_io[0] self._iocycle = None self._iotemperature = None self._iofrequency = None self._ioerrorcnt = None - self._ioled = 1 + self._ioled = lst_io[1] self._ioerrorlimit1 = None self._ioerrorlimit2 = None - # Eigene IO-Liste aufbauen - self.__lst_io = [x for x in self.__iter__()] - - int_lenio = len(self.__lst_io) + int_lenio = len(lst_io) if int_lenio == 6: # Core 1.1 - self._iocycle = 1 - self._ioerrorcnt = 2 - self._ioled = 3 - self._ioerrorlimit1 = 4 - self._ioerrorlimit2 = 5 + self._iocycle = lst_io[1] + self._ioerrorcnt = lst_io[2] + self._ioled = lst_io[3] + self._ioerrorlimit1 = lst_io[4] + self._ioerrorlimit2 = lst_io[5] elif int_lenio == 8: # Core 1.2 - self._iocycle = 1 - self._ioerrorcnt = 2 - self._iotemperature = 3 - self._iofrequency = 4 - self._ioled = 5 - self._ioerrorlimit1 = 6 - self._ioerrorlimit2 = 7 + self._iocycle = lst_io[1] + self._ioerrorcnt = lst_io[2] + self._iotemperature = lst_io[3] + self._iofrequency = lst_io[4] + self._ioled = lst_io[5] + self._ioerrorlimit1 = lst_io[6] + self._ioerrorlimit2 = lst_io[7] if not (self._modio._monitoring or self._modio._simulator): # Für RS485 errors defaults laden sollte procimg NULL sein if self._ioerrorlimit1 is not None: - self.__lst_io[self._ioerrorlimit1].set_value( - self.__lst_io[self._ioerrorlimit1]._defaultvalue + self._ioerrorlimit1.set_value( + self._ioerrorlimit1._defaultvalue ) if self._ioerrorlimit2 is not None: - self.__lst_io[self._ioerrorlimit2].set_value( - self.__lst_io[self._ioerrorlimit2]._defaultvalue + self._ioerrorlimit2.set_value( + self._ioerrorlimit2._defaultvalue ) # RS485 errors schreiben self._modio.writeprocimg(self) - def __errorlimit(self, io_id, errorlimit): + def __errorlimit(self, io, errorlimit): """Verwaltet das Lesen und Schreiben der ErrorLimits. - @param io_id Index des IOs fuer ErrorLimit + @param io IOs Objekt fuer ErrorLimit @return Aktuellen ErrorLimit oder None wenn nicht verfuegbar""" if errorlimit is None: - return None if io_id is None else int.from_bytes( - self.__lst_io[io_id].get_value(), byteorder="little" + return None if io is None else int.from_bytes( + io.get_value(), byteorder="little" ) else: if 0 <= errorlimit <= 65535: - self.__lst_io[io_id].set_value( + io.set_value( errorlimit.to_bytes(2, byteorder="little") ) else: @@ -466,14 +467,14 @@ class Core(Device): """Gibt den RevPi Core Status zurueck. @return Status als """ return int.from_bytes( - self.__lst_io[0].get_value(), byteorder="little" + self._iostatusbyte.get_value(), byteorder="little" ) def _get_leda1(self): """Gibt den Zustand der LED A1 vom Core zurueck. @return 0=aus, 1=gruen, 2=rot""" int_led = int.from_bytes( - self.__lst_io[self._ioled].get_value(), byteorder="little" + self._ioled.get_value(), byteorder="little" ) led = int_led & 1 led += int_led & 2 @@ -483,7 +484,7 @@ class Core(Device): """Gibt den Zustand der LED A2 vom Core zurueck. @return 0=aus, 1=gruen, 2=rot""" int_led = int.from_bytes( - self.__lst_io[self._ioled].get_value(), byteorder="little" + self._ioled.get_value(), byteorder="little" ) >> 2 led = int_led & 1 led += int_led & 2 @@ -495,12 +496,12 @@ class Core(Device): @param shifed_value Bits vergleichen""" # Byte als int holen int_led = int.from_bytes( - self.__lst_io[self._ioled].get_value(), byteorder="little" + self._ioled.get_value(), byteorder="little" ) for int_bit in addresslist: value = bool(shifted_value & int_bit) - if bool(int_led & 1) != value: + if bool(int_led & int_bit) != value: # Berechnen, wenn verändert if value: int_led += int_bit @@ -508,9 +509,7 @@ class Core(Device): int_led -= int_bit # Zurückschreiben wenn verändert - self.__lst_io[self._ioled].set_value( - int_led.to_bytes(length=1, byteorder="little") - ) + self._ioled.set_value(int_led.to_bytes(length=1, byteorder="little")) def _set_leda1(self, value): """Setzt den Zustand der LED A1 vom Core. @@ -537,7 +536,7 @@ class Core(Device): """Statusbit fuer piControl-Treiber laeuft. @return True, wenn Treiber laeuft""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), byteorder="little" + self._iostatusbyte.get_value(), byteorder="little" ) & 1) @property @@ -545,7 +544,7 @@ class Core(Device): """Statusbit fuer ein IO-Modul nicht mit PiCtory konfiguriert. @return True, wenn IO Modul nicht konfiguriert""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), byteorder="little" + self._iostatusbyte.get_value(), byteorder="little" ) & 2) @property @@ -553,7 +552,7 @@ class Core(Device): """Statusbit fuer ein IO-Modul fehlt oder piGate konfiguriert. @return True, wenn IO-Modul fehlt oder piGate konfiguriert""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), byteorder="little" + self._iostatusbyte.get_value(), byteorder="little" ) & 4) @property @@ -561,7 +560,7 @@ class Core(Device): """Statusbit Modul belegt mehr oder weniger Speicher als konfiguriert. @return True, wenn falscher Speicher belegt ist""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), byteorder="little" + self._iostatusbyte.get_value(), byteorder="little" ) & 8) @property @@ -569,7 +568,7 @@ class Core(Device): """Statusbit links vom RevPi ist ein piGate Modul angeschlossen. @return True, wenn piGate links existiert""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), byteorder="little" + self._iostatusbyte.get_value(), byteorder="little" ) & 16) @property @@ -577,7 +576,7 @@ class Core(Device): """Statusbit rechts vom RevPi ist ein piGate Modul angeschlossen. @return True, wenn piGate rechts existiert""" return bool(int.from_bytes( - self.__lst_io[0].get_value(), byteorder="little" + self._iostatusbyte.get_value(), byteorder="little" ) & 32) @property @@ -585,7 +584,7 @@ class Core(Device): """Gibt Zykluszeit der Prozessabbildsynchronisierung zurueck. @return Zykluszeit in ms""" return None if self._iocycle is None else int.from_bytes( - self.__lst_io[self._iocycle].get_value(), byteorder="little" + self._iocycle.get_value(), byteorder="little" ) @property @@ -593,7 +592,7 @@ class Core(Device): """Gibt CPU-Temperatur zurueck. @return CPU-Temperatur in Celsius""" return None if self._iotemperature is None else int.from_bytes( - self.__lst_io[self._iotemperature].get_value(), byteorder="little" + self._iotemperature.get_value(), byteorder="little" ) @property @@ -601,7 +600,7 @@ class Core(Device): """Gibt CPU Taktfrequenz zurueck. @return CPU Taktfrequenz in MHz""" return None if self._iofrequency is None else int.from_bytes( - self.__lst_io[self._iofrequency].get_value(), byteorder="little" + self._iofrequency.get_value(), byteorder="little" ) * 10 @property @@ -609,7 +608,7 @@ class Core(Device): """Gibt Fehleranzahl auf RS485 piBridge Bus zurueck. @return Fehleranzahl der piBridge""" return None if self._ioerrorcnt is None else int.from_bytes( - self.__lst_io[self._ioerrorcnt].get_value(), byteorder="little" + self._ioerrorcnt.get_value(), byteorder="little" ) @property @@ -649,37 +648,30 @@ class Connect(Core): """Connect-Klasse vorbereiten.""" super()._devconfigure() - # TODO: IO Objekte für WD und X2 erzeugen - self.wd = None - self.x2in = None - self.x2out = None + # IO Objekte für WD und X2 in/out erzeugen + self.wd = IOBase(self, [ + "wd", 0, 1, self._ioled.address, + False, None, "Connect_WatchDog", "6" + ], OUT, "little", False) + self.x2in = IOBase(self, [ + "x2in", 0, 1, self._iostatusbyte.address, + False, None, "Connect_X2_IN", "6" + ], INP, "little", False) + self.x2out = IOBase(self, [ + "x2out", 0, 1, self._ioled.address, + False, None, "Connect_X2_OUT", "7" + ], OUT, "little", False) def _get_leda3(self): """Gibt den Zustand der LED A3 vom Connect zurueck. @return 0=aus, 1=gruen, 2=rot""" int_led = int.from_bytes( - self.__lst_io[self._ioled].get_value(), byteorder="little" + self._ioled.get_value(), byteorder="little" ) >> 4 led = int_led & 1 led += int_led & 2 return led -# def _get_wd(self): -# """Gibt den Zustand des Watchdogs vom Connect zurueck. -# @return True / False muss getriggert werden""" -# int_led = int.from_bytes( -# self.__lst_io[self._ioled].get_value(), byteorder="little" -# ) -# return bool(int_led & 64) -# -# def _get_x2out(self): -# """Gibt den Zustand des Relais X2 vom Connect zurueck. -# @return True, wenn Relais geschlossen""" -# int_led = int.from_bytes( -# self.__lst_io[self._ioled].get_value(), byteorder="little" -# ) -# return bool(int_led & 128) - def _set_leda3(self, value): """Setzt den Zustand der LED A3 vom Connect. @param value 0=aus, 1=gruen, 2=rot""" @@ -688,26 +680,7 @@ class Connect(Core): else: raise ValueError("led status must be between 0 and 3") -# def _set_wd(self, value): -# """Setzt den Zustand des Watchdogs vom Connect. -# @param value True / False muss getriggert werden""" -# if isinstance(value, bool): -# self._set_calculatedled([128], 128) -# else: -# raise ValueError("value must be True / False") -# -# def _set_x2out(self, value): -# """Setzt den Zustand des Watchdogs vom Connect. -# @param value True / False muss getriggert werden""" -# if isinstance(value, bool): -# self._set_calculatedled([64], 64) -# else: -# raise ValueError("value must be True / False") - A3 = property(_get_leda3, _set_leda3) -# WD = property(_get_wd, _set_wd) -# X2IN = property(_get_x2in) -# X2OUT = property(_get_x2out, _set_x2out) class Gateway(Device): From 5cb806bbc5a9dbb63118ea7cc8558976aa871491 Mon Sep 17 00:00:00 2001 From: NaruX Date: Wed, 1 Aug 2018 12:43:49 +0200 Subject: [PATCH 04/14] =?UTF-8?q?Berechnung=20von=20Bit-IOs=20=C3=BCber=20?= =?UTF-8?q?mehr=20als=202=20Bytes=20angepasst=20wd=20und=20x2out=20Ansteue?= =?UTF-8?q?rung=20verbessert=20Connect=20Funkscheiben=20werden=20als=20Dev?= =?UTF-8?q?ices=20ignoriert=20Alle=20Cores=20werden=20bei=20syncoutputs=20?= =?UTF-8?q?nicht=20mehr=20mit=20\x00=20vorbelegt=20issubclass=20gegen=20is?= =?UTF-8?q?instance=20getauscht=20.exitsignal-Event=20f=C3=BCr=20den=20Ben?= =?UTF-8?q?utzer=20hinzugef=C3=BCgt=20Bei=20Core-Klasse=20a*green=20/=20a*?= =?UTF-8?q?red=20als=20echte=20IOs=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- revpimodio2.e4p | 3 ++- revpimodio2/device.py | 49 ++++++++++++++++++++++++++++--------------- revpimodio2/io.py | 6 +++--- revpimodio2/modio.py | 40 ++++++++++++++++++++++++++++++----- revpimodio2/netio.py | 4 ++-- 5 files changed, 74 insertions(+), 28 deletions(-) diff --git a/revpimodio2.e4p b/revpimodio2.e4p index 662e053..75b395d 100644 --- a/revpimodio2.e4p +++ b/revpimodio2.e4p @@ -1,7 +1,7 @@ - + en_US @@ -38,6 +38,7 @@ test/web_startseite.py test/web_rpidaten.py test/web_rpii2c.py + test/test_unit_fh.py diff --git a/revpimodio2/device.py b/revpimodio2/device.py index b7b2d08..a842899 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -55,7 +55,7 @@ class DeviceList(object): def __delitem__(self, key): """Entfernt Device an angegebener Position. @param key Deviceposition zum entfernen""" - if issubclass(type(key), Device): + if isinstance(key, Device): key = key._position self.__delattr__(key) @@ -91,7 +91,7 @@ class DeviceList(object): """Setzt Attribute nur wenn Device. @param key Attributname @param value Attributobjekt""" - if issubclass(type(value), Device): + if isinstance(value, Device): object.__setattr__(self, key, value) self.__dict_position[value._position] = value elif key == "_DeviceList__dict_position": @@ -178,7 +178,7 @@ class Device(object): """Prueft ob IO auf diesem Device liegt. @param key IO-Name / IO-Bytenummer @return True, wenn IO auf Device vorhanden""" - if issubclass(type(key), IOBase): + if isinstance(key, IOBase): # Umwandlung für key key = key._name @@ -432,18 +432,23 @@ class Core(Device): self._ioerrorlimit1 = lst_io[6] self._ioerrorlimit2 = lst_io[7] - if not (self._modio._monitoring or self._modio._simulator): - # Für RS485 errors defaults laden sollte procimg NULL sein - if self._ioerrorlimit1 is not None: - self._ioerrorlimit1.set_value( - self._ioerrorlimit1._defaultvalue - ) - if self._ioerrorlimit2 is not None: - self._ioerrorlimit2.set_value( - self._ioerrorlimit2._defaultvalue - ) - # RS485 errors schreiben - self._modio.writeprocimg(self) + # Echte IOs erzeugen + self.a1green = IOBase(self, [ + "a1green", 0, 1, self._ioled.address, + False, None, "LED_A1_GREEN", "0" + ], OUT, "little", False) + self.a1red = IOBase(self, [ + "a1red", 0, 1, self._ioled.address, + False, None, "LED_A1_RED", "1" + ], OUT, "little", False) + self.a2green = IOBase(self, [ + "a2green", 0, 1, self._ioled.address, + False, None, "LED_A2_GREEN", "2" + ], OUT, "little", False) + self.a2red = IOBase(self, [ + "a2red", 0, 1, self._ioled.address, + False, None, "LED_A2_RED", "3" + ], OUT, "little", False) def __errorlimit(self, io, errorlimit): """Verwaltet das Lesen und Schreiben der ErrorLimits. @@ -648,10 +653,20 @@ class Connect(Core): """Connect-Klasse vorbereiten.""" super()._devconfigure() + # Echte IOs erzeugen + self.a3green = IOBase(self, [ + "a3green", 0, 1, self._ioled.address, + False, None, "LED_A3_GREEN", "4" + ], OUT, "little", False) + self.a3red = IOBase(self, [ + "a3red", 0, 1, self._ioled.address, + False, None, "LED_A3_RED", "5" + ], OUT, "little", False) + # IO Objekte für WD und X2 in/out erzeugen self.wd = IOBase(self, [ "wd", 0, 1, self._ioled.address, - False, None, "Connect_WatchDog", "6" + False, None, "Connect_WatchDog", "7" ], OUT, "little", False) self.x2in = IOBase(self, [ "x2in", 0, 1, self._iostatusbyte.address, @@ -659,7 +674,7 @@ class Connect(Core): ], INP, "little", False) self.x2out = IOBase(self, [ "x2out", 0, 1, self._ioled.address, - False, None, "Connect_X2_OUT", "7" + False, None, "Connect_X2_OUT", "6" ], OUT, "little", False) def _get_leda3(self): diff --git a/revpimodio2/io.py b/revpimodio2/io.py index abdbbbf..b62b04e 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -191,7 +191,7 @@ class IOList(object): def _private_register_new_io_object(self, new_io): """Registriert neues IO Objekt unabhaenging von __setattr__. @param new_io Neues IO Objekt""" - if issubclass(type(new_io), IOBase): + if isinstance(new_io, IOBase): if hasattr(self, new_io._name): raise AttributeError( "attribute {} already exists - can not set io".format( @@ -317,7 +317,7 @@ class IOBase(object): else: # Höhere Bits als 7 auf nächste Bytes umbrechen - int_startaddress += int((int(valuelist[7]) % 16) / 8) + int_startaddress += int(int(valuelist[7]) / 8) self._slc_address = slice( int_startaddress, int_startaddress + 1 ) @@ -519,7 +519,7 @@ class IOBase(object): >Python3 struct """ - if not issubclass(type(self._parentdevice), Gateway): + if not isinstance(self._parentdevice, Gateway): raise RuntimeError( "this function can be used for ios on gatway or virtual " "devices only" diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index 15472a7..a367f77 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -79,6 +79,9 @@ class RevPiModIO(object): self.io = None self.summary = None + # Event für Benutzeraktionen + self.exitsignal = Event() + # Nur Konfigurieren, wenn nicht vererbt if type(self) == RevPiModIO: self._configure(self.get_jconfigrsc()) @@ -177,6 +180,9 @@ class RevPiModIO(object): dev_new = devicemodule.Gateway( self, device, simulator=self._simulator ) + elif device["type"] == "RIGHT": + # Connectdevice + dev_new = None else: # Device-Type nicht gefunden warnings.warn( @@ -216,6 +222,20 @@ class RevPiModIO(object): if self._syncoutputs: self.syncoutputs() + # Für RS485 errors am core defaults laden sollte procimg NULL sein + if not (self.core is None or self._monitoring or self._simulator): + if self.core._ioerrorlimit1 is not None: + self.core._ioerrorlimit1.set_value( + self.core._ioerrorlimit1._defaultvalue + ) + if self.core._ioerrorlimit2 is not None: + self.core._ioerrorlimit2.set_value( + self.core._ioerrorlimit2._defaultvalue + ) + + # RS485 errors schreiben + self.writeprocimg(self.core) + # Optional ins autorefresh aufnehmen if self._autorefresh: self.autorefresh_all() @@ -374,6 +394,9 @@ class RevPiModIO(object): # Zeitänderung in _imgwriter neuladen self._imgwriter.newdata.clear() + # Benutzerevent + self.exitsignal.clear() + # Cycleloop starten self._exit.clear() self._looprunning = True @@ -423,6 +446,10 @@ class RevPiModIO(object): wird dann gestoppt und das Programm kann sauber beendet werden. @param full Entfernt auch alle Devices aus autorefresh""" + + # Benutzerevent + self.exitsignal.set() + self._exit.set() self._waitexit.set() @@ -544,6 +571,9 @@ class RevPiModIO(object): self._th_mainloop.start() return + # Benutzerevent + self.exitsignal.clear() + # Event säubern vor Eintritt in Mainloop self._exit.clear() self._looprunning = True @@ -592,7 +622,7 @@ class RevPiModIO(object): if device is None: mylist = self.device else: - dev = device if issubclass(type(device), devicemodule.Device) \ + dev = device if isinstance(device, devicemodule.Device) \ else self.device.__getitem__(device) if dev._selfupdate: @@ -647,7 +677,7 @@ class RevPiModIO(object): if device is None: mylist = self.device else: - dev = device if issubclass(type(device), devicemodule.Device) \ + dev = device if isinstance(device, devicemodule.Device) \ else self.device.__getitem__(device) mylist = [dev] @@ -667,12 +697,12 @@ class RevPiModIO(object): if device is None: mylist = self.device else: - dev = device if issubclass(type(device), devicemodule.Device) \ + dev = device if isinstance(device, devicemodule.Device) \ else self.device.__getitem__(device) if dev._selfupdate: raise RuntimeError( - "can not sync process image, while device '{}|{}'" + "can not sync outputs, while device '{}|{}'" "is in autorefresh mode".format(dev._position, dev._name) ) mylist = [dev] @@ -710,7 +740,7 @@ class RevPiModIO(object): if device is None: mylist = self.device else: - dev = device if issubclass(type(device), devicemodule.Device) \ + dev = device if isinstance(device, devicemodule.Device) \ else self.device.__getitem__(device) if dev._selfupdate: diff --git a/revpimodio2/netio.py b/revpimodio2/netio.py index 2d8b7b3..f2c1981 100644 --- a/revpimodio2/netio.py +++ b/revpimodio2/netio.py @@ -466,7 +466,7 @@ class RevPiNetIO(_RevPiModIO): if device is None: self._myfh.clear_dirtybytes() else: - dev = device if issubclass(type(device), Device) \ + dev = device if isinstance(device, Device) \ else self.device.__getitem__(device) mylist = [dev] @@ -486,7 +486,7 @@ class RevPiNetIO(_RevPiModIO): if device is None: mylist = self.device else: - dev = device if issubclass(type(device), Device) \ + dev = device if isinstance(device, Device) \ else self.device.__getitem__(device) mylist = [dev] From e7c1f522dc995010e8b2b86f75190209cf6d99de Mon Sep 17 00:00:00 2001 From: NaruX Date: Wed, 1 Aug 2018 15:49:02 +0200 Subject: [PATCH 05/14] watchdogtrigger in Connect-Klasse integriert (Wechselt alle 10 Sekunden) Adressen der core/connect IOs verbessert --- doc/revpimodio2.device.html | 50 +++++++++++++++++++++++++++++++-- doc/revpimodio2.io.html | 2 +- eric-revpimodio2.api | 3 ++ revpimodio2/device.py | 55 ++++++++++++++++++++++++++++++------- revpimodio2/io.py | 4 +-- 5 files changed, 99 insertions(+), 15 deletions(-) diff --git a/doc/revpimodio2.device.html b/doc/revpimodio2.device.html index 0d5dd29..21743ff 100644 --- a/doc/revpimodio2.device.html +++ b/doc/revpimodio2.device.html @@ -58,7 +58,7 @@ Core

Class Attributes

- +
A3
A3
watchdogtrigger

Class Methods

@@ -69,14 +69,23 @@ Class Methods Methods + + + + + + + + +
__wdtriggerWD Ausgang alle 10 Sekunden automatisch toggeln.
_devconfigure Connect-Klasse vorbereiten.
_get_leda3 Gibt den Zustand der LED A3 vom Connect zurueck.
_get_wdtriggerRuft den Wert fuer Autowatchdog ab.
_set_leda3 Setzt den Zustand der LED A3 vom Connect.
_set_wdtriggerSetzt den Wert fuer Autowatchdog.

@@ -84,7 +93,13 @@ Static Methods

None
- + +

+Connect.__wdtrigger

+__wdtrigger() +

+WD Ausgang alle 10 Sekunden automatisch toggeln. +

Connect._devconfigure

_devconfigure() @@ -101,6 +116,17 @@ Gibt den Zustand der LED A3 vom Connect zurueck.
0=aus, 1=gruen, 2=rot
+
+

+Connect._get_wdtrigger

+_get_wdtrigger() +

+Ruft den Wert fuer Autowatchdog ab. +

+
Returns:
+
+True, wenn Autowatchdog aktiv ist +

Connect._set_leda3

@@ -112,6 +138,26 @@ Setzt den Zustand der LED A3 vom Connect.
0=aus, 1=gruen, 2=rot
+
+

+Connect._set_wdtrigger

+_set_wdtrigger(value) +

+Setzt den Wert fuer Autowatchdog. +

+ Wird dieser Wert auf True gesetzt, wechselt im Hintergrund das noetige + Bit zum toggeln des Watchdogs alle 10 Sekunden zwichen True und False. + Dieses Bit wird bei autorefresh=True natuerlich automatisch in das + Prozessabbild geschrieben. +

+ WICHTIG: Sollte autorefresh=False sein, muss zyklisch + .writeprocimg() aufgerufen werden, um den Wert in das + Prozessabbild zu schreiben!!! +

+
value
+
+True zum aktivieren, Fals zum beenden +


diff --git a/doc/revpimodio2.io.html b/doc/revpimodio2.io.html index b3ac153..df89bfc 100644 --- a/doc/revpimodio2.io.html +++ b/doc/revpimodio2.io.html @@ -202,7 +202,7 @@ Parentdevice auf dem der IO liegt
valuelist
Datenliste fuer Instantiierung - ["name","defval","bitlen","startaddr",exp,"idx","bmk","bitaddr"] + ["name","defval","bitlen","startaddrdev",exp,"idx","bmk","bitaddr"]
iotype
Wert diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api index c02b6a2..306cc5f 100644 --- a/eric-revpimodio2.api +++ b/eric-revpimodio2.api @@ -12,7 +12,10 @@ revpimodio2.consttostr?4(value) revpimodio2.device.Connect.A3?7 revpimodio2.device.Connect._devconfigure?5() revpimodio2.device.Connect._get_leda3?5() +revpimodio2.device.Connect._get_wdtrigger?5() revpimodio2.device.Connect._set_leda3?5(value) +revpimodio2.device.Connect._set_wdtrigger?5(value) +revpimodio2.device.Connect.watchdogtrigger?7 revpimodio2.device.Core.A1?7 revpimodio2.device.Core.A2?7 revpimodio2.device.Core._devconfigure?5() diff --git a/revpimodio2/device.py b/revpimodio2/device.py index a842899..1f4b149 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -6,7 +6,7 @@ # (c) Sven Sager, License: LGPLv3 # """Modul fuer die Verwaltung der Devices.""" -from threading import Lock +from threading import Thread, Event, Lock from .helper import ProcimgWriter @@ -434,19 +434,19 @@ class Core(Device): # Echte IOs erzeugen self.a1green = IOBase(self, [ - "a1green", 0, 1, self._ioled.address, + "a1green", 0, 1, self._ioled._slc_address.start, False, None, "LED_A1_GREEN", "0" ], OUT, "little", False) self.a1red = IOBase(self, [ - "a1red", 0, 1, self._ioled.address, + "a1red", 0, 1, self._ioled._slc_address.start, False, None, "LED_A1_RED", "1" ], OUT, "little", False) self.a2green = IOBase(self, [ - "a2green", 0, 1, self._ioled.address, + "a2green", 0, 1, self._ioled._slc_address.start, False, None, "LED_A2_GREEN", "2" ], OUT, "little", False) self.a2red = IOBase(self, [ - "a2red", 0, 1, self._ioled.address, + "a2red", 0, 1, self._ioled._slc_address.start, False, None, "LED_A2_RED", "3" ], OUT, "little", False) @@ -649,31 +649,38 @@ class Connect(Core): """ + def __wdtrigger(self): + """WD Ausgang alle 10 Sekunden automatisch toggeln.""" + while not self.__evt_wdtrigger.wait(10): + self.wd.value = not self.wd.value + def _devconfigure(self): """Connect-Klasse vorbereiten.""" super()._devconfigure() + self.__evt_wdtrigger = Event() + self.__th_wdtrigger = None # Echte IOs erzeugen self.a3green = IOBase(self, [ - "a3green", 0, 1, self._ioled.address, + "a3green", 0, 1, self._ioled._slc_address.start, False, None, "LED_A3_GREEN", "4" ], OUT, "little", False) self.a3red = IOBase(self, [ - "a3red", 0, 1, self._ioled.address, + "a3red", 0, 1, self._ioled._slc_address.start, False, None, "LED_A3_RED", "5" ], OUT, "little", False) # IO Objekte für WD und X2 in/out erzeugen self.wd = IOBase(self, [ - "wd", 0, 1, self._ioled.address, + "wd", 0, 1, self._ioled._slc_address.start, False, None, "Connect_WatchDog", "7" ], OUT, "little", False) self.x2in = IOBase(self, [ - "x2in", 0, 1, self._iostatusbyte.address, + "x2in", 0, 1, self._iostatusbyte._slc_address.start, False, None, "Connect_X2_IN", "6" ], INP, "little", False) self.x2out = IOBase(self, [ - "x2out", 0, 1, self._ioled.address, + "x2out", 0, 1, self._ioled._slc_address.start, False, None, "Connect_X2_OUT", "6" ], OUT, "little", False) @@ -687,6 +694,12 @@ class Connect(Core): led += int_led & 2 return led + def _get_wdtrigger(self): + """Ruft den Wert fuer Autowatchdog ab. + @return True, wenn Autowatchdog aktiv ist""" + return self.__th_wdtrigger is not None \ + and self.__th_wdtrigger.is_alive() + def _set_leda3(self, value): """Setzt den Zustand der LED A3 vom Connect. @param value 0=aus, 1=gruen, 2=rot""" @@ -695,7 +708,29 @@ class Connect(Core): else: raise ValueError("led status must be between 0 and 3") + def _set_wdtrigger(self, value): + """Setzt den Wert fuer Autowatchdog. + + Wird dieser Wert auf True gesetzt, wechselt im Hintergrund das noetige + Bit zum toggeln des Watchdogs alle 10 Sekunden zwichen True und False. + Dieses Bit wird bei autorefresh=True natuerlich automatisch in das + Prozessabbild geschrieben. + + WICHTIG: Sollte autorefresh=False sein, muss zyklisch + .writeprocimg() aufgerufen werden, um den Wert in das + Prozessabbild zu schreiben!!! + + @param value True zum aktivieren, Fals zum beenden""" + if not value: + self.__evt_wdtrigger.set() + + elif not self._get_wdtrigger(): + self.__evt_wdtrigger.clear() + self.__th_wdtrigger = Thread(target=self.__wdtrigger, daemon=True) + self.__th_wdtrigger.start() + A3 = property(_get_leda3, _set_leda3) + watchdogtrigger = property(_get_wdtrigger, _set_wdtrigger) class Gateway(Device): diff --git a/revpimodio2/io.py b/revpimodio2/io.py index b62b04e..3568f10 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -255,13 +255,13 @@ class IOBase(object): @param parentdevice Parentdevice auf dem der IO liegt @param valuelist Datenliste fuer Instantiierung - ["name","defval","bitlen","startaddr",exp,"idx","bmk","bitaddr"] + ["name","defval","bitlen","startaddrdev",exp,"idx","bmk","bitaddr"] @param iotype Wert @param byteorder Byteorder 'little'/'big' fuer Berechnung @param sigend Intberechnung mit Vorzeichen durchfuehren """ - # ["name","defval","bitlen","startaddr",exp,"idx","bmk","bitaddr"] + # ["name","defval","bitlen","startaddrdev",exp,"idx","bmk","bitaddr"] # [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] self._parentdevice = parentdevice From 7e5787421d4556dc1c6becf23e553911ca85f138 Mon Sep 17 00:00:00 2001 From: NaruX Date: Wed, 1 Aug 2018 17:49:18 +0200 Subject: [PATCH 07/14] triggerwatchdog darf nicht in monitoring oder simulator mode verwendet werden --- revpimodio2.e4p | 4 ++-- revpimodio2/__init__.py | 2 +- revpimodio2/device.py | 10 ++++++++++ setup.py | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/revpimodio2.e4p b/revpimodio2.e4p index 75b395d..30e9b52 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.0 + 2.2.1 Sven Sager akira@narux.de diff --git a/revpimodio2/__init__.py b/revpimodio2/__init__.py index d2e2fe4..26bb056 100644 --- a/revpimodio2/__init__.py +++ b/revpimodio2/__init__.py @@ -25,7 +25,7 @@ __all__ = [ __author__ = "Sven Sager " __name__ = "revpimodio2" __package__ = "revpimodio2" -__version__ = "2.2.0" +__version__ = "2.2.1" # Global package values OFF = 0 diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 1f4b149..68e79c8 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -721,10 +721,20 @@ class Connect(Core): Prozessabbild zu schreiben!!! @param value True zum aktivieren, Fals zum beenden""" + if self._modio._monitoring: + raise RuntimeError( + "can not trigger watchdog, while system is in monitoring mode" + ) + if self._modio._simulator: + raise RuntimeError( + "can not trigger watchdog, while system is in simulator mode" + ) + if not value: self.__evt_wdtrigger.set() elif not self._get_wdtrigger(): + # Watchdogtrigger erstellen self.__evt_wdtrigger.clear() self.__th_wdtrigger = Thread(target=self.__wdtrigger, daemon=True) self.__th_wdtrigger.start() diff --git a/setup.py b/setup.py index 76626d4..892d30f 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ setup( license="LGPLv3", name="revpimodio2", - version="2.2.0", + version="2.2.1", packages=["revpimodio2"], python_requires="~=3.2", From 27a69488f4307e55550b200b7cac119a14160e62 Mon Sep 17 00:00:00 2001 From: NaruX Date: Thu, 9 Aug 2018 08:36:18 +0200 Subject: [PATCH 09/14] Connect-Attribut watchdogtrigger in wdautotoggle umbenannt Bei handlesignalend wird im monitoring Modus nicht mehr geschrieben --- doc/revpimodio2.device.html | 26 +++++++++++++------------- eric-revpimodio2.api | 6 +++--- revpimodio2.e4p | 4 ++-- revpimodio2/__init__.py | 2 +- revpimodio2/device.py | 34 +++++++++++++++++----------------- revpimodio2/modio.py | 5 +++-- setup.py | 2 +- 7 files changed, 40 insertions(+), 39 deletions(-) diff --git a/doc/revpimodio2.device.html b/doc/revpimodio2.device.html index 21743ff..09fa806 100644 --- a/doc/revpimodio2.device.html +++ b/doc/revpimodio2.device.html @@ -58,7 +58,7 @@ Core

Class Attributes

- +
A3
watchdogtrigger
A3
wdautotoggle

Class Methods

@@ -69,7 +69,7 @@ Class Methods Methods - + @@ -78,13 +78,13 @@ Methods - + - +
__wdtrigger__wdtoggle WD Ausgang alle 10 Sekunden automatisch toggeln.
_devconfigure _get_leda3 Gibt den Zustand der LED A3 vom Connect zurueck.
_get_wdtrigger_get_wdtoggle Ruft den Wert fuer Autowatchdog ab.
_set_leda3 Setzt den Zustand der LED A3 vom Connect.
_set_wdtrigger_set_wdtoggle Setzt den Wert fuer Autowatchdog.
@@ -93,10 +93,10 @@ Static Methods
None
- +

-Connect.__wdtrigger

-__wdtrigger() +Connect.__wdtoggle +__wdtoggle()

WD Ausgang alle 10 Sekunden automatisch toggeln.

@@ -116,10 +116,10 @@ Gibt den Zustand der LED A3 vom Connect zurueck.
0=aus, 1=gruen, 2=rot
-
+

-Connect._get_wdtrigger

-_get_wdtrigger() +Connect._get_wdtoggle +_get_wdtoggle()

Ruft den Wert fuer Autowatchdog ab.

@@ -138,10 +138,10 @@ Setzt den Zustand der LED A3 vom Connect.
0=aus, 1=gruen, 2=rot
-
+

-Connect._set_wdtrigger

-_set_wdtrigger(value) +Connect._set_wdtoggle +_set_wdtoggle(value)

Setzt den Wert fuer Autowatchdog.

diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api index 306cc5f..3371e9e 100644 --- a/eric-revpimodio2.api +++ b/eric-revpimodio2.api @@ -12,10 +12,10 @@ revpimodio2.consttostr?4(value) revpimodio2.device.Connect.A3?7 revpimodio2.device.Connect._devconfigure?5() revpimodio2.device.Connect._get_leda3?5() -revpimodio2.device.Connect._get_wdtrigger?5() +revpimodio2.device.Connect._get_wdtoggle?5() revpimodio2.device.Connect._set_leda3?5(value) -revpimodio2.device.Connect._set_wdtrigger?5(value) -revpimodio2.device.Connect.watchdogtrigger?7 +revpimodio2.device.Connect._set_wdtoggle?5(value) +revpimodio2.device.Connect.wdautotoggle?7 revpimodio2.device.Core.A1?7 revpimodio2.device.Core.A2?7 revpimodio2.device.Core._devconfigure?5() diff --git a/revpimodio2.e4p b/revpimodio2.e4p index 30e9b52..11a437a 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.1 + 2.2.2 Sven Sager akira@narux.de diff --git a/revpimodio2/__init__.py b/revpimodio2/__init__.py index 26bb056..ae8ffae 100644 --- a/revpimodio2/__init__.py +++ b/revpimodio2/__init__.py @@ -25,7 +25,7 @@ __all__ = [ __author__ = "Sven Sager " __name__ = "revpimodio2" __package__ = "revpimodio2" -__version__ = "2.2.1" +__version__ = "2.2.2" # Global package values OFF = 0 diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 68e79c8..7e60641 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -649,16 +649,16 @@ class Connect(Core): """ - def __wdtrigger(self): + def __wdtoggle(self): """WD Ausgang alle 10 Sekunden automatisch toggeln.""" - while not self.__evt_wdtrigger.wait(10): + while not self.__evt_wdtoggle.wait(10): self.wd.value = not self.wd.value def _devconfigure(self): """Connect-Klasse vorbereiten.""" super()._devconfigure() - self.__evt_wdtrigger = Event() - self.__th_wdtrigger = None + self.__evt_wdtoggle = Event() + self.__th_wdtoggle = None # Echte IOs erzeugen self.a3green = IOBase(self, [ @@ -694,11 +694,11 @@ class Connect(Core): led += int_led & 2 return led - def _get_wdtrigger(self): + def _get_wdtoggle(self): """Ruft den Wert fuer Autowatchdog ab. @return True, wenn Autowatchdog aktiv ist""" - return self.__th_wdtrigger is not None \ - and self.__th_wdtrigger.is_alive() + return self.__th_wdtoggle is not None \ + and self.__th_wdtoggle.is_alive() def _set_leda3(self, value): """Setzt den Zustand der LED A3 vom Connect. @@ -708,7 +708,7 @@ class Connect(Core): else: raise ValueError("led status must be between 0 and 3") - def _set_wdtrigger(self, value): + def _set_wdtoggle(self, value): """Setzt den Wert fuer Autowatchdog. Wird dieser Wert auf True gesetzt, wechselt im Hintergrund das noetige @@ -723,24 +723,24 @@ class Connect(Core): @param value True zum aktivieren, Fals zum beenden""" if self._modio._monitoring: raise RuntimeError( - "can not trigger watchdog, while system is in monitoring mode" + "can not toggle watchdog, while system is in monitoring mode" ) if self._modio._simulator: raise RuntimeError( - "can not trigger watchdog, while system is in simulator mode" + "can not toggle watchdog, while system is in simulator mode" ) if not value: - self.__evt_wdtrigger.set() + self.__evt_wdtoggle.set() - elif not self._get_wdtrigger(): - # Watchdogtrigger erstellen - self.__evt_wdtrigger.clear() - self.__th_wdtrigger = Thread(target=self.__wdtrigger, daemon=True) - self.__th_wdtrigger.start() + elif not self._get_wdtoggle(): + # Watchdogtoggler erstellen + self.__evt_wdtoggle.clear() + self.__th_wdtoggle = Thread(target=self.__wdtoggle, daemon=True) + self.__th_wdtoggle.start() A3 = property(_get_leda3, _set_leda3) - watchdogtrigger = property(_get_wdtrigger, _set_wdtrigger) + wdautotoggle = property(_get_wdtoggle, _set_wdtoggle) class Gateway(Device): diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index a367f77..4501c88 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -103,7 +103,8 @@ class RevPiModIO(object): if self.__cleanupfunc is not None: self.readprocimg() self.__cleanupfunc() - self.writeprocimg() + if not self._monitoring: + self.writeprocimg() def _configure(self, jconfigrsc): """Verarbeitet die piCtory Konfigurationsdatei.""" @@ -459,7 +460,7 @@ class RevPiModIO(object): self._imgwriter.stop() self._imgwriter.join(self._imgwriter._refresh) - # Mainloop beenden und darauf waretn + # Mainloop beenden und darauf 1 Sekunde warten if self._th_mainloop is not None and self._th_mainloop.is_alive(): self._th_mainloop.join(1) diff --git a/setup.py b/setup.py index 892d30f..a332834 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ setup( license="LGPLv3", name="revpimodio2", - version="2.2.1", + version="2.2.2", packages=["revpimodio2"], python_requires="~=3.2", From c2f26bcc984679cff933c1732f3a226f677394f3 Mon Sep 17 00:00:00 2001 From: NaruX Date: Sun, 12 Aug 2018 18:14:22 +0200 Subject: [PATCH 11/14] Code style --- doc/index-revpimodio2.html | 2 + doc/revpimodio2.__init__.html | 4 +- doc/revpimodio2.app.html | 2 +- doc/revpimodio2.device.html | 2 +- doc/revpimodio2.helper.html | 2 +- doc/revpimodio2.io.html | 2 +- doc/revpimodio2.modio.html | 2 +- doc/revpimodio2.netio.html | 2 +- doc/revpimodio2.summary.html | 2 +- revpimodio2.e4p | 114 +++++++++++++++++++++++++--------- revpimodio2/__init__.py | 12 ++-- revpimodio2/app.py | 9 +-- revpimodio2/device.py | 12 ++-- revpimodio2/helper.py | 22 +++---- revpimodio2/io.py | 55 ++++++++-------- revpimodio2/modio.py | 33 +++++----- revpimodio2/netio.py | 18 +++--- revpimodio2/summary.py | 9 +-- setup.py | 7 ++- 19 files changed, 177 insertions(+), 134 deletions(-) diff --git a/doc/index-revpimodio2.html b/doc/index-revpimodio2.html index c0634cd..f3bc051 100644 --- a/doc/index-revpimodio2.html +++ b/doc/index-revpimodio2.html @@ -9,6 +9,8 @@ revpimodio2

Stellt alle Klassen fuer den RevolutionPi zur Verfuegung.

+Webpage: https://revpimodio.org/ +

Stellt Klassen fuer die einfache Verwendung des Revolution Pis der Kunbus GmbH (https://revolution.kunbus.de/) zur Verfuegung. Alle I/Os werden aus der piCtory Konfiguration eingelesen und mit deren Namen direkt zugreifbar diff --git a/doc/revpimodio2.__init__.html b/doc/revpimodio2.__init__.html index 7b11ad7..2bb8f2b 100644 --- a/doc/revpimodio2.__init__.html +++ b/doc/revpimodio2.__init__.html @@ -9,6 +9,8 @@ revpimodio2.__init__

Stellt alle Klassen fuer den RevolutionPi zur Verfuegung.

+Webpage: https://revpimodio.org/ +

Stellt Klassen fuer die einfache Verwendung des Revolution Pis der Kunbus GmbH (https://revolution.kunbus.de/) zur Verfuegung. Alle I/Os werden aus der piCtory Konfiguration eingelesen und mit deren Namen direkt zugreifbar @@ -20,7 +22,7 @@ fuehrt das Modul bei Datenaenderung aus.

Global Attributes

- +
BOTH
FALLING
GREEN
INP
MEM
OFF
OUT
RED
RISING
__all__
__author__
__name__
__package__
__version__
BOTH
FALLING
GREEN
INP
MEM
OFF
OUT
RED
RISING
__all__
__author__
__copyright__
__license__
__name__
__version__

Classes

diff --git a/doc/revpimodio2.app.html b/doc/revpimodio2.app.html index c18e732..e6a1b6e 100644 --- a/doc/revpimodio2.app.html +++ b/doc/revpimodio2.app.html @@ -12,7 +12,7 @@ Bildet die App Sektion von piCtory ab.

Global Attributes

- +
None
__author__
__copyright__
__license__

Classes

diff --git a/doc/revpimodio2.device.html b/doc/revpimodio2.device.html index 09fa806..f3894a6 100644 --- a/doc/revpimodio2.device.html +++ b/doc/revpimodio2.device.html @@ -12,7 +12,7 @@ Modul fuer die Verwaltung der Devices.

Global Attributes

- +
None
__author__
__copyright__
__license__

Classes

diff --git a/doc/revpimodio2.helper.html b/doc/revpimodio2.helper.html index 3ece18f..ee90dfb 100644 --- a/doc/revpimodio2.helper.html +++ b/doc/revpimodio2.helper.html @@ -12,7 +12,7 @@ RevPiModIO Helperklassen und Tools.

Global Attributes

- +
None
__author__
__copyright__
__license__

Classes

diff --git a/doc/revpimodio2.io.html b/doc/revpimodio2.io.html index df89bfc..19eb3b7 100644 --- a/doc/revpimodio2.io.html +++ b/doc/revpimodio2.io.html @@ -12,7 +12,7 @@ RevPiModIO Modul fuer die Verwaltung der IOs.

Global Attributes

- +
None
__author__
__copyright__
__license__

Classes

diff --git a/doc/revpimodio2.modio.html b/doc/revpimodio2.modio.html index 0c7d8ec..80b6568 100644 --- a/doc/revpimodio2.modio.html +++ b/doc/revpimodio2.modio.html @@ -12,7 +12,7 @@ RevPiModIO Hauptklasse fuer piControl0 Zugriff.

Global Attributes

- +
None
__author__
__copyright__
__license__

Classes

diff --git a/doc/revpimodio2.netio.html b/doc/revpimodio2.netio.html index 0f6943f..4e6ebc1 100644 --- a/doc/revpimodio2.netio.html +++ b/doc/revpimodio2.netio.html @@ -12,7 +12,7 @@ RevPiModIO Hauptklasse fuer Netzwerkzugriff.

Global Attributes

- +
_sysdeldirty
_sysexit
_sysflush
_syspictory
_syssync
__author__
__copyright__
__license__
_sysdeldirty
_sysexit
_sysflush
_syspictory
_syssync

Classes

diff --git a/doc/revpimodio2.summary.html b/doc/revpimodio2.summary.html index 2741c25..194214e 100644 --- a/doc/revpimodio2.summary.html +++ b/doc/revpimodio2.summary.html @@ -12,7 +12,7 @@ Bildet die Summary-Sektion von piCtory ab.

Global Attributes

- +
None
__author__
__copyright__
__license__

Classes

diff --git a/revpimodio2.e4p b/revpimodio2.e4p index 11a437a..4223e53 100644 --- a/revpimodio2.e4p +++ b/revpimodio2.e4p @@ -1,7 +1,7 @@ - + en_US @@ -14,40 +14,40 @@ akira@narux.de - setup.py - revpimodio2/modio.py - revpimodio2/summary.py - revpimodio2/app.py - revpimodio2/io.py revpimodio2/__init__.py + revpimodio2/app.py revpimodio2/device.py revpimodio2/helper.py + revpimodio2/io.py + revpimodio2/modio.py revpimodio2/netio.py - test/test_dio_while2.py - test/test_dio_mainloop.py + revpimodio2/summary.py + setup.py test/test_dio_cycleloop.py + test/test_dio_mainloop.py + test/test_dio_while2.py test/test_net_leistung.py - test/web_cycleloop.py - test/web_mainloop.py - test/web_virtdevdriver.py + test/test_netio_brett.py + test/test_unit.py + test/test_unit_fh.py + test/test_unitnet.py test/web_benniesrun.py test/web_benniesrunxxl.py - test/test_unit.py - test/test_unitnet.py - test/test_netio_brett.py - test/web_startseite.py + test/web_cycleloop.py + test/web_mainloop.py test/web_rpidaten.py test/web_rpii2c.py - test/test_unit_fh.py + test/web_startseite.py + test/web_virtdevdriver.py - doc .hgignore MANIFEST.in + doc eric-revpimodio2.api test/test_unit.py @@ -153,9 +153,6 @@ - - - @@ -249,14 +246,6 @@ False - - sourceExtensions - - - - - - useRecursion @@ -276,6 +265,41 @@ + + BuiltinsChecker + + + + + chr + + + + unichr + + + + str + + + + unicode + + + + + + CopyrightAuthor + + + + + + CopyrightMinFileSize + + + 0 + DocstringType @@ -286,13 +310,13 @@ ExcludeFiles - + */test/* ExcludeMessages - E123,E226,E24 + E123,E226,E24,C101,E402,C111 FixCodes @@ -306,6 +330,12 @@ False + + FutureChecker + + + + HangClosing @@ -318,6 +348,24 @@ + + LineComplexity + + + 15 + + + LineComplexityScore + + + 10 + + + MaxCodeComplexity + + + 10 + MaxLineLength @@ -342,6 +390,12 @@ False + + ValidEncodings + + + latin-1, utf-8 + diff --git a/revpimodio2/__init__.py b/revpimodio2/__init__.py index ae8ffae..ce1eff2 100644 --- a/revpimodio2/__init__.py +++ b/revpimodio2/__init__.py @@ -1,12 +1,8 @@ # -*- coding: utf-8 -*- -# -# python3-RevPiModIO -# -# Webpage: https://revpimodio.org/ -# (c) Sven Sager, License: LGPLv3 -# """Stellt alle Klassen fuer den RevolutionPi zur Verfuegung. +Webpage: https://revpimodio.org/ + Stellt Klassen fuer die einfache Verwendung des Revolution Pis der Kunbus GmbH (https://revolution.kunbus.de/) zur Verfuegung. Alle I/Os werden aus der piCtory Konfiguration eingelesen und mit deren Namen direkt zugreifbar @@ -23,8 +19,9 @@ __all__ = [ "RevPiNetIO", "RevPiNetIOSelected", "RevPiNetIODriver" ] __author__ = "Sven Sager " +__copyright__ = "Copyright (C) 2018 Sven Sager" +__license__ = "LGPLv3" __name__ = "revpimodio2" -__package__ = "revpimodio2" __version__ = "2.2.2" # Global package values @@ -71,6 +68,7 @@ def consttostr(value): else: return "" + # Benötigte Klassen importieren from .modio import RevPiModIO, RevPiModIOSelected, RevPiModIODriver from .netio import RevPiNetIO, RevPiNetIOSelected, RevPiNetIODriver diff --git a/revpimodio2/app.py b/revpimodio2/app.py index 03d6c1e..010c437 100644 --- a/revpimodio2/app.py +++ b/revpimodio2/app.py @@ -1,11 +1,8 @@ # -*- coding: utf-8 -*- -# -# python3-RevPiModIO -# -# Webpage: https://revpimodio.org/ -# (c) Sven Sager, License: LGPLv3 -# """Bildet die App Sektion von piCtory ab.""" +__author__ = "Sven Sager" +__copyright__ = "Copyright (C) 2018 Sven Sager" +__license__ = "LGPLv3" class App(object): diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 7e60641..7754ecc 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- -# -# python3-RevPiModIO -# -# Webpage: https://revpimodio.org/ -# (c) Sven Sager, License: LGPLv3 -# """Modul fuer die Verwaltung der Devices.""" +__author__ = "Sven Sager" +__copyright__ = "Copyright (C) 2018 Sven Sager" +__license__ = "LGPLv3" + from threading import Thread, Event, Lock from .helper import ProcimgWriter @@ -65,7 +63,7 @@ class DeviceList(object): @return Gefundenes -Objekt""" if type(key) == int: if key not in self.__dict_position: - raise KeyError("no device on position {}".format(key)) + raise KeyError("no device on position {0}".format(key)) return self.__dict_position[key] else: return getattr(self, key) diff --git a/revpimodio2/helper.py b/revpimodio2/helper.py index 7d6557a..b79c2df 100644 --- a/revpimodio2/helper.py +++ b/revpimodio2/helper.py @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- -# -# python3-RevPiModIO -# -# Webpage: https://revpimodio.org/ -# (c) Sven Sager, License: LGPLv3 -# """RevPiModIO Helperklassen und Tools.""" +__author__ = "Sven Sager" +__copyright__ = "Copyright (C) 2018 Sven Sager" +__license__ = "LGPLv3" + import queue import warnings from math import ceil @@ -413,12 +411,12 @@ class ProcimgWriter(Thread): self._ioerror += 1 if self._maxioerrors != 0 and self._ioerror >= self._maxioerrors: raise RuntimeError( - "reach max io error count {} on process image".format( + "reach max io error count {0} on process image".format( self._maxioerrors ) ) warnings.warn( - "count {} io errors on process image".format(self._ioerror), + "count {0} io errors on process image".format(self._ioerror), RuntimeWarning ) @@ -443,7 +441,7 @@ class ProcimgWriter(Thread): # Lockobjekt holen und Fehler werfen, wenn nicht schnell genug if not self.lck_refresh.acquire(timeout=self._adjwait): warnings.warn( - "cycle time of {} ms exceeded on lock".format( + "cycle time of {0} ms exceeded on lock".format( int(self._refresh * 1000) ), RuntimeWarning @@ -496,8 +494,8 @@ class ProcimgWriter(Thread): # Verzögerte Events prüfen if self.__eventwork: for tup_fire in list(self.__dict_delay.keys()): - if tup_fire[0].overwrite \ - and getattr(self._modio.io, tup_fire[1]).value != \ + if tup_fire[0].overwrite and \ + getattr(self._modio.io, tup_fire[1]).value != \ tup_fire[2]: del self.__dict_delay[tup_fire] else: @@ -518,7 +516,7 @@ class ProcimgWriter(Thread): self._adjwait -= 0.001 if self._adjwait < 0: warnings.warn( - "cycle time of {} ms exceeded".format( + "cycle time of {0} ms exceeded".format( int(self._refresh * 1000) ), RuntimeWarning diff --git a/revpimodio2/io.py b/revpimodio2/io.py index 3568f10..839efe3 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- -# -# python3-RevPiModIO -# -# Webpage: https://revpimodio.org/ -# (c) Sven Sager, License: LGPLv3 -# """RevPiModIO Modul fuer die Verwaltung der IOs.""" +__author__ = "Sven Sager" +__copyright__ = "Copyright (C) 2018 Sven Sager" +__license__ = "LGPLv3" + import struct from re import match as rematch from threading import Event @@ -69,7 +67,7 @@ class IOList(object): if key in self.__dict_iorefname: return self.__dict_iorefname[key] else: - raise AttributeError("can not find io '{}'".format(key)) + raise AttributeError("can not find io '{0}'".format(key)) def __getitem__(self, key): """Ruft angegebenen IO ab. @@ -86,7 +84,7 @@ class IOList(object): """ if type(key) == int: if key not in self.__dict_iobyte: - raise KeyError("byte '{}' does not exist".format(key)) + raise KeyError("byte '{0}' does not exist".format(key)) return self.__dict_iobyte[key] elif type(key) == slice: return [ @@ -151,14 +149,14 @@ class IOList(object): if oldio._bitaddress >= 0: if io._bitaddress == oldio._bitaddress: raise MemoryError( - "bit {} already assigned to '{}'".format( + "bit {0} already assigned to '{1}'".format( io._bitaddress, oldio._name ) ) else: # Bereits überschriebene bytes sind ungültig raise MemoryError( - "new io '{}' overlaps memory of '{}'".format( + "new io '{0}' overlaps memory of '{1}'".format( io._name, oldio._name ) ) @@ -194,7 +192,7 @@ class IOList(object): if isinstance(new_io, IOBase): if hasattr(self, new_io._name): raise AttributeError( - "attribute {} already exists - can not set io".format( + "attribute {0} already exists - can not set io".format( new_io._name ) ) @@ -298,7 +296,7 @@ class IOBase(object): else: raise ValueError( "given bytes for default value must have a length " - "of {} but {} was given" + "of {0} but {1} was given" "".format(self._length, len(valuelist[1])) ) else: @@ -312,7 +310,7 @@ class IOBase(object): if len(buff) <= self._length: self._defaultvalue = \ buff + bytes(self._length - len(buff)) - except: + except Exception: pass else: @@ -328,7 +326,7 @@ class IOBase(object): else: try: self._defaultvalue = bool(int(valuelist[1])) - except: + except Exception: self._defaultvalue = False def __bool__(self): @@ -367,7 +365,7 @@ class IOBase(object): # Prüfen ob Funktion callable ist if not callable(func): raise AttributeError( - "registered function '{}' is not callable".format(func) + "registered function '{0}' is not callable".format(func) ) if type(delay) != int or delay < 0: raise AttributeError( @@ -391,20 +389,21 @@ class IOBase(object): if edge == BOTH or regfunc.edge == BOTH: if self._bitaddress < 0: raise AttributeError( - "io '{}' with function '{}' already in list." + "io '{0}' with function '{1}' already in list." "".format(self._name, func) ) else: raise AttributeError( - "io '{}' with function '{}' already in list with " - "edge '{}' - edge '{}' not allowed anymore".format( + "io '{0}' with function '{1}' already in list " + "with edge '{2}' - edge '{3}' not allowed anymore" + "".format( self._name, func, consttostr(regfunc.edge), consttostr(edge) ) ) elif regfunc.edge == edge: raise AttributeError( - "io '{}' with function '{}' for given edge '{}' " + "io '{0}' with function '{1}' for given edge '{2}' " "already in list".format( self._name, func, consttostr(edge) ) @@ -584,31 +583,31 @@ class IOBase(object): value else: raise ValueError( - "'{}' requires a object of length " - "{}, but {} was given".format( + "'{0}' requires a object of " + "length {1}, but {2} was given".format( self._name, self._length, len(value) ) ) else: raise ValueError( - "'{}' requires a object, not {}" + "'{0}' requires a object, not {1}" "".format(self._name, type(value)) ) elif self._iotype == INP: if self._parentdevice._modio._simulator: raise AttributeError( - "can not write to output '{}' in simulator mode" + "can not write to output '{0}' in simulator mode" "".format(self._name) ) else: raise AttributeError( - "can not write to input '{}'".format(self._name) + "can not write to input '{0}'".format(self._name) ) elif self._iotype == MEM: raise AttributeError( - "can not write to memory '{}'".format(self._name) + "can not write to memory '{0}'".format(self._name) ) def unreg_event(self, func=None, edge=None): @@ -679,7 +678,7 @@ class IOBase(object): # Prüfen ob Device in autorefresh ist if not self._parentdevice._selfupdate: raise RuntimeError( - "autorefresh is not activated for device '{}|{}' - there " + "autorefresh is not activated for device '{0}|{1}' - there " "will never be new data".format( self._parentdevice._position, self._parentdevice._name ) @@ -825,7 +824,7 @@ class IntIO(IOBase): )) else: raise ValueError( - "'{}' need a value, but {} was given" + "'{0}' need a value, but {1} was given" "".format(self._name, type(value)) ) @@ -873,7 +872,7 @@ class StructIO(IOBase): max_bits = parentio._length * 8 if not (0 <= bitaddress < max_bits): raise AttributeError( - "bitaddress must be a value between 0 and {}" + "bitaddress must be a value between 0 and {0}" "".format(max_bits - 1) ) bitlength = 1 diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index 4501c88..737ac5b 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- -# -# python3-RevPiModIO -# -# Webpage: https://revpimodio.org/ -# (c) Sven Sager, License: LGPLv3 -# """RevPiModIO Hauptklasse fuer piControl0 Zugriff.""" +__author__ = "Sven Sager" +__copyright__ = "Copyright (C) 2018 Sven Sager" +__license__ = "LGPLv3" + import warnings from json import load as jload from os import access, F_OK, R_OK @@ -187,7 +185,7 @@ class RevPiModIO(object): else: # Device-Type nicht gefunden warnings.warn( - "device type '{}' unknown".format(device["type"]), + "device type '{0}' unknown".format(device["type"]), Warning ) dev_new = None @@ -298,12 +296,12 @@ class RevPiModIO(object): self._ioerror += 1 if self._maxioerrors != 0 and self._ioerror >= self._maxioerrors: raise RuntimeError( - "reach max io error count {} on process image".format( + "reach max io error count {0} on process image".format( self._maxioerrors ) ) warnings.warn( - "got io error during {} and count {} errors now".format( + "got io error during {0} and count {1} errors now".format( action, self._ioerror ), RuntimeWarning @@ -385,7 +383,7 @@ class RevPiModIO(object): # Prüfen ob Funktion callable ist if not callable(func): raise RuntimeError( - "registered function '{}' ist not callable".format(func) + "registered function '{0}' ist not callable".format(func) ) # Zykluszeit übernehmen @@ -478,7 +476,7 @@ class RevPiModIO(object): if self._configrsc is not None: if not access(self._configrsc, F_OK | R_OK): raise RuntimeError( - "can not access pictory configuration at {}".format( + "can not access pictory configuration at {0}".format( self._configrsc)) else: # piCtory Konfiguration an bekannten Stellen prüfen @@ -489,7 +487,7 @@ class RevPiModIO(object): break if self._configrsc is None: raise RuntimeError( - "can not access known pictory configurations at {} - " + "can not access known pictory configurations at {0} - " "use 'configrsc' parameter so specify location" "".format(", ".join(lst_rsc)) ) @@ -497,7 +495,7 @@ class RevPiModIO(object): with open(self._configrsc, "r") as fhconfigrsc: try: jdata = jload(fhconfigrsc) - except: + except Exception: raise RuntimeError( "can not read piCtory configuration - check your hardware " "configuration http://revpi_ip/" @@ -529,7 +527,8 @@ class RevPiModIO(object): # Prüfen ob Funktion callable ist if not (cleanupfunc is None or callable(cleanupfunc)): raise RuntimeError( - "registered function '{}' ist not callable".format(cleanupfunc) + "registered function '{0}' ist not callable" + "".format(cleanupfunc) ) self.__cleanupfunc = cleanupfunc signal(SIGINT, self.__evt_exit) @@ -628,7 +627,7 @@ class RevPiModIO(object): if dev._selfupdate: raise RuntimeError( - "can not read process image, while device '{}|{}'" + "can not read process image, while device '{0}|{1}'" "is in autorefresh mode".format(dev._position, dev._name) ) mylist = [dev] @@ -703,7 +702,7 @@ class RevPiModIO(object): if dev._selfupdate: raise RuntimeError( - "can not sync outputs, while device '{}|{}'" + "can not sync outputs, while device '{0}|{1}'" "is in autorefresh mode".format(dev._position, dev._name) ) mylist = [dev] @@ -746,7 +745,7 @@ class RevPiModIO(object): if dev._selfupdate: raise RuntimeError( - "can not write process image, while device '{}|{}'" + "can not write process image, while device '{0}|{1}'" "is in autorefresh mode".format(dev._position, dev._name) ) mylist = [dev] diff --git a/revpimodio2/netio.py b/revpimodio2/netio.py index f2c1981..43325b9 100644 --- a/revpimodio2/netio.py +++ b/revpimodio2/netio.py @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- -# -# python3-RevPiModIO -# -# Webpage: https://revpimodio.org/ -# (c) Sven Sager, License: LGPLv3 -# """RevPiModIO Hauptklasse fuer Netzwerkzugriff.""" +__author__ = "Sven Sager" +__copyright__ = "Copyright (C) 2018 Sven Sager" +__license__ = "LGPLv3" + import socket import warnings from json import loads as jloads @@ -79,7 +77,7 @@ class NetFH(Thread): so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: so.connect(self._address) - except: + except Exception: so.close() else: # Alten Socket trennen @@ -141,7 +139,7 @@ class NetFH(Thread): self._slavesock.send(_sysexit) else: self._slavesock.shutdown(socket.SHUT_RDWR) - except: + except Exception: pass self._slavesock.close() @@ -178,7 +176,7 @@ class NetFH(Thread): def get_name(self): """Verbindugnsnamen zurueckgeben. @return IP:PORT""" - return "{}:{}".format(*self._address) + return "{0}:{1}".format(*self._address) def get_timeout(self): """Gibt aktuellen Timeout zurueck. @@ -423,7 +421,7 @@ class RevPiNetIO(_RevPiModIO): autorefresh, monitoring, syncoutputs, - "{}:{}".format(*self._address), + "{0}:{1}".format(*self._address), None, simulator ) diff --git a/revpimodio2/summary.py b/revpimodio2/summary.py index 0fcfb8d..9bdc72a 100644 --- a/revpimodio2/summary.py +++ b/revpimodio2/summary.py @@ -1,11 +1,8 @@ # -*- coding: utf-8 -*- -# -# python3-RevPiModIO -# -# Webpage: https://revpimodio.org/ -# (c) Sven Sager, License: LGPLv3 -# """Bildet die Summary-Sektion von piCtory ab.""" +__author__ = "Sven Sager" +__copyright__ = "Copyright (C) 2018 Sven Sager" +__license__ = "LGPLv3" class Summary(object): diff --git a/setup.py b/setup.py index a332834..0ec5220 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,10 @@ #! /usr/bin/env python3 # -*- coding: utf-8 -*- -# -# (c) Sven Sager, License: LGPLv3 -# """Setupscript fuer python3-revpimodio.""" +__author__ = "Sven Sager" +__copyright__ = "Copyright (C) 2018 Sven Sager" +__license__ = "LGPLv3" + from distutils.core import setup setup( From 70a95dcacdf8f41360413fb3fa6ceabd2b243129 Mon Sep 17 00:00:00 2001 From: NaruX Date: Mon, 13 Aug 2018 15:12:41 +0200 Subject: [PATCH 12/14] =?UTF-8?q?=5F=5Fslots=5F=5F=20f=C3=BCr=20alle=20m?= =?UTF-8?q?=C3=B6glichen=20Klassen=20implementiert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/revpimodio2.app.html | 2 +- doc/revpimodio2.device.html | 10 ++++---- doc/revpimodio2.helper.html | 38 ++++++++++++++++++++++++++--- doc/revpimodio2.io.html | 10 ++++---- doc/revpimodio2.modio.html | 6 ++--- doc/revpimodio2.netio.html | 8 +++---- doc/revpimodio2.summary.html | 2 +- revpimodio2.e4p | 4 ++-- revpimodio2/__init__.py | 2 +- revpimodio2/app.py | 2 ++ revpimodio2/device.py | 46 ++++++++++++++++++++++++++++-------- revpimodio2/helper.py | 16 +++++++++++++ revpimodio2/io.py | 13 ++++++++++ revpimodio2/modio.py | 11 +++++++++ revpimodio2/netio.py | 12 ++++++++++ revpimodio2/summary.py | 2 ++ setup.py | 2 +- 17 files changed, 150 insertions(+), 36 deletions(-) diff --git a/doc/revpimodio2.app.html b/doc/revpimodio2.app.html index e6a1b6e..e96c636 100644 --- a/doc/revpimodio2.app.html +++ b/doc/revpimodio2.app.html @@ -39,7 +39,7 @@ object

Class Attributes

- +
None
__slots__

Class Methods

diff --git a/doc/revpimodio2.device.html b/doc/revpimodio2.device.html index f3894a6..3e1d92a 100644 --- a/doc/revpimodio2.device.html +++ b/doc/revpimodio2.device.html @@ -58,7 +58,7 @@ Core

Class Attributes

- +
A3
wdautotoggle
A3
__slots__
wdautotoggle

Class Methods

@@ -176,7 +176,7 @@ Device

Class Attributes

- +
A1
A2
status
A1
A2
__slots__
status

Class Methods

@@ -496,7 +496,7 @@ object

Class Attributes

- +
length
name
offset
position
producttype
__slots__
length
name
offset
position
producttype

Class Methods

@@ -1024,7 +1024,7 @@ Device

Class Attributes

- +
None
__slots__

Class Methods

@@ -1093,7 +1093,7 @@ Gateway

Class Attributes

- +
None
__slots__

Class Methods

diff --git a/doc/revpimodio2.helper.html b/doc/revpimodio2.helper.html index ee90dfb..4868bdb 100644 --- a/doc/revpimodio2.helper.html +++ b/doc/revpimodio2.helper.html @@ -26,6 +26,9 @@ Classes ProcimgWriter Klasse fuer Synchroniseriungs-Thread. + +Var +

@@ -65,7 +68,7 @@ None

Class Attributes

- +
None
__slots__

Class Methods

@@ -351,7 +354,7 @@ Thread

Class Attributes

- +
None
__slots__

Class Methods

@@ -426,7 +429,7 @@ Thread

Class Attributes

- +
ioerrors
maxioerrors
refresh
__slots__
ioerrors
maxioerrors
refresh

Class Methods

@@ -587,6 +590,35 @@ ProcimgWriter.stop

Beendet die automatische Prozessabbildsynchronisierung.

+ +

+ +

Var

+ +

+Derived from

+None +

+Class Attributes

+ + +
None
+

+Class Methods

+ + +
None
+

+Methods

+ + +
None
+

+Static Methods

+ + +
None
+
\ No newline at end of file diff --git a/doc/revpimodio2.io.html b/doc/revpimodio2.io.html index 19eb3b7..7892835 100644 --- a/doc/revpimodio2.io.html +++ b/doc/revpimodio2.io.html @@ -54,7 +54,7 @@ object

Class Attributes

- +
_parentdevice
__slots__
_parentdevice

Class Methods

@@ -124,7 +124,7 @@ object

Class Attributes

- +
address
byteorder
defaultvalue
length
name
type
value
__slots__
address
byteorder
defaultvalue
length
name
type
value

Class Methods

@@ -520,7 +520,7 @@ object

Class Attributes

- +
None
__slots__

Class Methods

@@ -752,7 +752,7 @@ IOBase

Class Attributes

- +
byteorder
defaultvalue
signed
value
__slots__
byteorder
defaultvalue
signed
value

Class Methods

@@ -889,7 +889,7 @@ IOBase

Class Attributes

- +
defaultvalue
frm
signed
value
__slots__
defaultvalue
frm
signed
value

Class Methods

diff --git a/doc/revpimodio2.modio.html b/doc/revpimodio2.modio.html index 80b6568..0086303 100644 --- a/doc/revpimodio2.modio.html +++ b/doc/revpimodio2.modio.html @@ -54,7 +54,7 @@ object

Class Attributes

- +
configrsc
cycletime
ioerrors
length
maxioerrors
monitoring
procimg
simulator
__slots__
configrsc
cycletime
ioerrors
length
maxioerrors
monitoring
procimg
simulator

Class Methods

@@ -557,7 +557,7 @@ RevPiModIOSelected

Class Attributes

- +
None
__slots__

Class Methods

@@ -617,7 +617,7 @@ RevPiModIO

Class Attributes

- +
None
__slots__

Class Methods

diff --git a/doc/revpimodio2.netio.html b/doc/revpimodio2.netio.html index 4e6ebc1..8c1caa9 100644 --- a/doc/revpimodio2.netio.html +++ b/doc/revpimodio2.netio.html @@ -54,7 +54,7 @@ Thread

Class Attributes

- +
closed
name
timeout
__slots__
closed
name
timeout

Class Methods

@@ -323,7 +323,7 @@ _RevPiModIO

Class Attributes

- +
None
__slots__

Class Methods

@@ -448,7 +448,7 @@ RevPiNetIOSelected

Class Attributes

- +
None
__slots__

Class Methods

@@ -511,7 +511,7 @@ RevPiNetIO

Class Attributes

- +
None
__slots__

Class Methods

diff --git a/doc/revpimodio2.summary.html b/doc/revpimodio2.summary.html index 194214e..dd61e6e 100644 --- a/doc/revpimodio2.summary.html +++ b/doc/revpimodio2.summary.html @@ -39,7 +39,7 @@ object

Class Attributes

- +
None
__slots__

Class Methods

diff --git a/revpimodio2.e4p b/revpimodio2.e4p index 4223e53..9b5037a 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.2 + 2.2.3 Sven Sager akira@narux.de diff --git a/revpimodio2/__init__.py b/revpimodio2/__init__.py index ce1eff2..3f1af8c 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.2" +__version__ = "2.2.3" # Global package values OFF = 0 diff --git a/revpimodio2/app.py b/revpimodio2/app.py index 010c437..19389f2 100644 --- a/revpimodio2/app.py +++ b/revpimodio2/app.py @@ -9,6 +9,8 @@ class App(object): """Bildet die App Sektion der config.rsc ab.""" + __slots__ = "name", "version", "language", "layout" + def __init__(self, app): """Instantiiert die App-Klasse. @param app piCtory Appinformationen""" diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 7754ecc..72b0d6a 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -106,6 +106,13 @@ class Device(object): """ + __slots__ = "_ba_devdata", "_ba_datacp", \ + "_dict_events", "_filelock", "_length", "_modio", "_name", "_offset", \ + "_position", "_producttype", "_selfupdate", "_slc_devoff", \ + "_slc_inp", "_slc_inpoff", "_slc_mem", "_slc_memoff", \ + "_slc_out", "_slc_outoff", "bmk", "catalognr", "comment", "extend", \ + "guid", "id", "inpvariant", "outvariant", "type" + def __init__(self, parentmodio, dict_device, simulator=False): """Instantiierung der Device-Klasse. @@ -122,24 +129,24 @@ class Device(object): self._selfupdate = False # Wertzuweisung aus dict_device - self._name = dict_device.pop("name") - self._offset = int(dict_device.pop("offset")) - self._position = int(dict_device.pop("position")) - self._producttype = int(dict_device.pop("productType")) + self._name = dict_device.get("name") + self._offset = int(dict_device.get("offset")) + self._position = int(dict_device.get("position")) + self._producttype = int(dict_device.get("productType")) # IOM-Objekte erstellen und Adressen in SLCs speichern if simulator: self._slc_inp = self._buildio( - dict_device.pop("out"), INP) + dict_device.get("out"), INP) self._slc_out = self._buildio( - dict_device.pop("inp"), OUT) + dict_device.get("inp"), OUT) else: self._slc_inp = self._buildio( - dict_device.pop("inp"), INP) + dict_device.get("inp"), INP) self._slc_out = self._buildio( - dict_device.pop("out"), OUT) + dict_device.get("out"), OUT) self._slc_mem = self._buildio( - dict_device.pop("mem"), MEM + dict_device.get("mem"), MEM ) # SLCs mit offset berechnen @@ -162,7 +169,15 @@ class Device(object): self._ba_datacp = bytearray() # Alle restlichen attribute an Klasse anhängen - self.__dict__.update(dict_device) + self.bmk = dict_device.get("bmk", "") + self.catalognr = dict_device.get("catalogNr", "") + self.comment = dict_device.get("comment", "") + self.extend = dict_device.get("extend", {}) + self.guid = dict_device.get("GUID", "") + self.id = dict_device.get("id", "") + self.inpvariant = dict_device.get("inpVariant", 0) + self.outvariant = dict_device.get("outVariant", 0) + self.type = dict_device.get("type", "") # Spezielle Konfiguration von abgeleiteten Klassen durchführen self._devconfigure() @@ -398,6 +413,10 @@ class Core(Device): """ + __slots__ = "_iocycle", "_ioerrorcnt", "_iostatusbyte", "_iotemperature", \ + "_ioerrorlimit1", "_ioerrorlimit2", "_iofrequency", "_ioled", \ + "a1green", "a1red", "a2green", "a2red" + def _devconfigure(self): """Core-Klasse vorbereiten.""" # Eigene IO-Liste aufbauen @@ -647,6 +666,9 @@ class Connect(Core): """ + __slots__ = "__evt_wdtoggle", "__th_wdtoggle", "a3green", "a3red", "wd", \ + "x2in", "x2out" + def __wdtoggle(self): """WD Ausgang alle 10 Sekunden automatisch toggeln.""" while not self.__evt_wdtoggle.wait(10): @@ -754,6 +776,8 @@ class Gateway(Device): """ + __slots__ = "_dict_slc" + def __init__(self, parent, dict_device, simulator=False): """Erweitert Device-Klasse um get_rawbytes-Funktionen. @see #Device.__init__ Device.__init__(...)""" @@ -783,6 +807,8 @@ class Virtual(Gateway): """ + __slots__ = () + def writeinputdefaults(self): """Schreibt fuer ein virtuelles Device piCtory Defaultinputwerte. diff --git a/revpimodio2/helper.py b/revpimodio2/helper.py index b79c2df..b48ea94 100644 --- a/revpimodio2/helper.py +++ b/revpimodio2/helper.py @@ -37,6 +37,8 @@ class EventCallback(Thread): """ + __slots__ = "daemon", "exit", "func", "ioname", "iovalue" + def __init__(self, func, name, value): """Init EventCallback class. @@ -85,6 +87,11 @@ class Cycletools(): """ + __slots__ = "__cycle", "__cycletime", "__ucycle", \ + "__dict_ton", "__dict_tof", "__dict_tp", "first", \ + "flag1c", "flag5c", "flag10c", "flag15c", "flag20c", \ + "flank5c", "flank10c", "flank15c", "flank20c", "var" + def __init__(self, cycletime): """Init Cycletools class.""" self.__cycle = 0 @@ -108,6 +115,11 @@ class Cycletools(): self.flank15c = True self.flank20c = True + # Benutzerdaten + class Var: + pass + self.var = Var() + def _docycle(self): """Zyklusarbeiten.""" # Einschaltverzoegerung @@ -277,6 +289,10 @@ class ProcimgWriter(Thread): """ + __slots__ = "__dict_delay", "__eventth", "__eventqth", "__eventwork", \ + "_adjwait", "_eventq", "_ioerror", "_maxioerrors", "_modio", \ + "_refresh", "_work", "daemon", "lck_refresh", "newdata" + def __init__(self, parentmodio): """Init ProcimgWriter class. @param parentmodio Parent Object""" diff --git a/revpimodio2/io.py b/revpimodio2/io.py index 839efe3..b100cd4 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -14,6 +14,8 @@ class IOEvent(object): """Basisklasse fuer IO-Events.""" + __slots__ = "as_thread", "delay", "edge", "func", "overwrite" + def __init__(self, func, edge, as_thread, delay, overwrite): """Init IOEvent class.""" self.as_thread = as_thread @@ -220,6 +222,8 @@ class DeadIO(object): """Klasse, mit der ersetzte IOs verwaltet werden.""" + __slots__ = "__deadio" + def __init__(self, deadio): """Instantiierung der DeadIO-Klasse. @param deadio IO, der ersetzt wurde""" @@ -248,6 +252,10 @@ class IOBase(object): """ + __slots__ = "_bitaddress", "_bitlength", "_byteorder", "_defaultvalue", \ + "_iotype", "_length", "_name", "_parentdevice", \ + "_signed", "_slc_address", "bmk" + def __init__(self, parentdevice, valuelist, iotype, byteorder, signed): """Instantiierung der IOBase-Klasse. @@ -767,6 +775,8 @@ class IntIO(IOBase): """ + __slots__ = () + def __int__(self): """Gibt IO-Wert zurueck mit Beachtung byteorder/signed. @return IO-Wert als """ @@ -844,6 +854,9 @@ class StructIO(IOBase): """ + __slots__ = "__frm", "_parentio_address", "_parentio_defaultvalue", \ + "_parentio_length" + def __init__(self, parentio, name, frm, **kwargs): """Erstellt einen IO mit struct-Formatierung. diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index 737ac5b..2d73bac 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -31,6 +31,13 @@ class RevPiModIO(object): """ + __slots__ = "__cleanupfunc", "_autorefresh", "_buffedwrite", \ + "_configrsc", "_exit", "_imgwriter", "_ioerror", "_length", \ + "_looprunning", "_lst_devselect", "_lst_refresh", "_maxioerrors", \ + "_myfh", "_monitoring", "_procimg", "_simulator", "_syncoutputs", \ + "_th_mainloop", "_waitexit", \ + "core", "app", "device", "exitsignal", "io", "summary" + def __init__( self, autorefresh=False, monitoring=False, syncoutputs=True, procimg=None, configrsc=None, simulator=False): @@ -796,6 +803,8 @@ class RevPiModIOSelected(RevPiModIO): """ + __slots__ = () + def __init__( self, deviceselection, autorefresh=False, monitoring=False, syncoutputs=True, procimg=None, configrsc=None, simulator=False): @@ -860,6 +869,8 @@ class RevPiModIODriver(RevPiModIOSelected): """ + __slots__ = () + def __init__( self, virtdev, autorefresh=False, monitoring=False, syncoutputs=True, procimg=None, configrsc=None): diff --git a/revpimodio2/netio.py b/revpimodio2/netio.py index 43325b9..29a558a 100644 --- a/revpimodio2/netio.py +++ b/revpimodio2/netio.py @@ -34,6 +34,12 @@ class NetFH(Thread): """ + __slots__ = "__by_buff", "__int_buff", "__dictdirty", "__flusherr", \ + "__position", "__sockact", "__sockerr", "__sockend", "__socklock", \ + "__timeout", "__trigger", "__waitsync", \ + "_address", "_slavesock", \ + "daemon" + def __init__(self, address, timeout=500): """Init NetFH-class. @param address IP Adresse des RevPi @@ -379,6 +385,8 @@ class RevPiNetIO(_RevPiModIO): """ + __slots__ = "_address" + def __init__( self, address, autorefresh=False, monitoring=False, syncoutputs=True, simulator=False): @@ -530,6 +538,8 @@ class RevPiNetIOSelected(RevPiNetIO): """ + __slots__ = () + def __init__( self, address, deviceselection, autorefresh=False, monitoring=False, syncoutputs=True, simulator=False): @@ -595,6 +605,8 @@ class RevPiNetIODriver(RevPiNetIOSelected): """ + __slots__ = () + def __init__( self, address, virtdev, autorefresh=False, monitoring=False, syncoutputs=True): diff --git a/revpimodio2/summary.py b/revpimodio2/summary.py index 9bdc72a..361f5fa 100644 --- a/revpimodio2/summary.py +++ b/revpimodio2/summary.py @@ -9,6 +9,8 @@ class Summary(object): """Bildet die Summary-Sektion der config.rsc ab.""" + __slots__ = "inptotal", "outtotal" + def __init__(self, summary): """Instantiiert die RevPiSummary-Klasse. @param summary piCtory Summaryinformationen""" diff --git a/setup.py b/setup.py index 0ec5220..320a416 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ setup( license="LGPLv3", name="revpimodio2", - version="2.2.2", + version="2.2.3", packages=["revpimodio2"], python_requires="~=3.2", From 61ad36840d330de900b6aa3491edcd5d87841b9a Mon Sep 17 00:00:00 2001 From: NaruX Date: Tue, 14 Aug 2018 11:38:03 +0200 Subject: [PATCH 13/14] _dict_events ist nun Threadsicher Bei Fehler in ProcimgWriter System sauber verlassen --- doc/revpimodio2.helper.html | 5 +++++ revpimodio2/device.py | 5 ++--- revpimodio2/helper.py | 26 +++++++++++++++++--------- revpimodio2/io.py | 24 ++++++++++++++---------- revpimodio2/modio.py | 7 +++---- 5 files changed, 41 insertions(+), 26 deletions(-) diff --git a/doc/revpimodio2.helper.html b/doc/revpimodio2.helper.html index ee90dfb..5859e23 100644 --- a/doc/revpimodio2.helper.html +++ b/doc/revpimodio2.helper.html @@ -513,6 +513,11 @@ Aktiviert oder Deaktiviert die Eventueberwachung.
True aktiviert / False deaktiviert
+
+
Returns:
+
+True, wenn Anforderung erfolgreich war +

ProcimgWriter._get_ioerrors

diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 7754ecc..14e4d36 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -284,9 +284,8 @@ class Device(object): self._modio.readprocimg(self) # Datenkopie anlegen - self._filelock.acquire() - self._ba_datacp = self._ba_devdata[:] - self._filelock.release() + with self._filelock: + self._ba_datacp = self._ba_devdata[:] self._selfupdate = True diff --git a/revpimodio2/helper.py b/revpimodio2/helper.py index b79c2df..24b67de 100644 --- a/revpimodio2/helper.py +++ b/revpimodio2/helper.py @@ -384,10 +384,16 @@ class ProcimgWriter(Thread): def _collect_events(self, value): """Aktiviert oder Deaktiviert die Eventueberwachung. - @param value True aktiviert / False deaktiviert""" + @param value True aktiviert / False deaktiviert + @return True, wenn Anforderung erfolgreich war""" if type(value) != bool: raise ValueError("value must be ") + # Nur starten, wenn System läuft + if not self.is_alive(): + self.__eventwork = False + return False + if self.__eventwork != value: with self.lck_refresh: self.__eventwork = value @@ -401,6 +407,8 @@ class ProcimgWriter(Thread): self.__eventth.daemon = True self.__eventth.start() + return True + def _get_ioerrors(self): """Ruft aktuelle Anzahl der Fehler ab. @return Aktuelle Fehleranzahl""" @@ -456,13 +464,13 @@ class ProcimgWriter(Thread): if self._modio._monitoring: # Inputs und Outputs in Puffer for dev in self._modio._lst_refresh: - dev._filelock.acquire() - dev._ba_devdata[:] = bytesbuff[dev._slc_devoff] - if self.__eventwork \ - and len(dev._dict_events) > 0 \ - and dev._ba_datacp != dev._ba_devdata: - self.__check_change(dev) - dev._filelock.release() + with dev._filelock: + dev._ba_devdata[:] = bytesbuff[dev._slc_devoff] + if self.__eventwork \ + and len(dev._dict_events) > 0 \ + and dev._ba_datacp != dev._ba_devdata: + self.__check_change(dev) + else: # Inputs in Puffer, Outputs in Prozessabbild for dev in self._modio._lst_refresh: @@ -493,7 +501,7 @@ class ProcimgWriter(Thread): finally: # Verzögerte Events prüfen if self.__eventwork: - for tup_fire in list(self.__dict_delay.keys()): + for tup_fire in tuple(self.__dict_delay.keys()): if tup_fire[0].overwrite and \ getattr(self._modio.io, tup_fire[1]).value != \ tup_fire[2]: diff --git a/revpimodio2/io.py b/revpimodio2/io.py index 839efe3..05adbbd 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -377,8 +377,9 @@ class IOBase(object): ) if self not in self._parentdevice._dict_events: - self._parentdevice._dict_events[self] = \ - [IOEvent(func, edge, as_thread, delay, overwrite)] + with self._parentdevice._filelock: + self._parentdevice._dict_events[self] = \ + [IOEvent(func, edge, as_thread, delay, overwrite)] else: # Prüfen ob Funktion schon registriert ist for regfunc in self._parentdevice._dict_events[self]: @@ -410,9 +411,10 @@ class IOBase(object): ) # Eventfunktion einfügen - self._parentdevice._dict_events[self].append( - IOEvent(func, edge, as_thread, delay, overwrite) - ) + with self._parentdevice._filelock: + self._parentdevice._dict_events[self].append( + IOEvent(func, edge, as_thread, delay, overwrite) + ) def _get_address(self): """Gibt die absolute Byteadresse im Prozessabbild zurueck. @@ -619,7 +621,8 @@ class IOBase(object): """ if self in self._parentdevice._dict_events: if func is None: - del self._parentdevice._dict_events[self] + with self._parentdevice._filelock: + del self._parentdevice._dict_events[self] else: newlist = [] for regfunc in self._parentdevice._dict_events[self]: @@ -629,10 +632,11 @@ class IOBase(object): newlist.append(regfunc) # Wenn Funktionen übrig bleiben, diese übernehmen - if len(newlist) > 0: - self._parentdevice._dict_events[self] = newlist - else: - del self._parentdevice._dict_events[self] + with self._parentdevice._filelock: + if len(newlist) > 0: + self._parentdevice._dict_events[self] = newlist + else: + del self._parentdevice._dict_events[self] def wait(self, edge=BOTH, exitevent=None, okvalue=None, timeout=0): """Wartet auf Wertaenderung eines IOs. diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index 737ac5b..a871ef2 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -312,7 +312,7 @@ class RevPiModIO(object): @param milliseconds in Millisekunden""" if self._looprunning: raise RuntimeError( - "can not change cycletime when cycleloop or mainloop are " + "can not change cycletime when cycleloop or mainloop is " "running" ) else: @@ -580,9 +580,8 @@ class RevPiModIO(object): # Beim Eintritt in mainloop Bytecopy erstellen for dev in self._lst_refresh: - dev._filelock.acquire() - dev._ba_datacp = dev._ba_devdata[:] - dev._filelock.release() + with dev._filelock: + dev._ba_datacp = dev._ba_devdata[:] # ImgWriter mit Eventüberwachung aktivieren self._imgwriter._collect_events(True) From ebbdbcaceb5e46ec1e5317d89569f5bbdc1ea36c Mon Sep 17 00:00:00 2001 From: NaruX Date: Sat, 18 Aug 2018 19:01:13 +0200 Subject: [PATCH 14/14] =?UTF-8?q?Kleinste=20refresh-Zeit=20auf=205=20ms=20?= =?UTF-8?q?gesetzt=20Zykluszeit=20vom=20.cycleloop=20wird=20bei=20Aufruf?= =?UTF-8?q?=20auf=2050=20ms=20gesetzt=20Standardrefreshzeit=20wird=20nach?= =?UTF-8?q?=20CPU-Anzahl=20bestimmt=20Laufzeit=C3=BCberwachung=20f=C3=BCr?= =?UTF-8?q?=20Eventsystem=20eingebaut=20IOBase.export=20gibt=20Wert=20von?= =?UTF-8?q?=20'Export'=20in=20piCtory=20zur=C3=BCck=20Device.get=5F*=20Par?= =?UTF-8?q?ameter=20'export'=20Filtert=20auf=20piCtory=20'Export'=20Wert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/revpimodio2.device.html | 54 +++++++++++++++++++++++---- doc/revpimodio2.helper.html | 38 +++++++++++++++++-- doc/revpimodio2.modio.html | 15 ++++---- eric-revpimodio2.api | 10 ++--- revpimodio2/device.py | 73 ++++++++++++++++++++++++++++--------- revpimodio2/helper.py | 7 ++-- revpimodio2/io.py | 5 ++- revpimodio2/modio.py | 60 ++++++++++++++++++++++++------ 8 files changed, 205 insertions(+), 57 deletions(-) diff --git a/doc/revpimodio2.device.html b/doc/revpimodio2.device.html index 3e1d92a..f4ca33d 100644 --- a/doc/revpimodio2.device.html +++ b/doc/revpimodio2.device.html @@ -553,7 +553,7 @@ Methods Gibt eine Liste aller Inputs zurueck. get_memories -Gibt eine Liste aller mems zurueck. +Gibt eine Liste aller Memoryobjekte zurueck. get_outputs Gibt eine Liste aller Outputs zurueck. @@ -623,13 +623,16 @@ True, wenn IO auf Device vorhanden

Device.__getioiter

-__getioiter(ioslc) +__getioiter(ioslc, export)

Gibt mit allen IOs zurueck.

ioslc
IO Abschnitt +
export
+
+Filter fuer 'Export' Flag in piCtory
Returns:
@@ -741,10 +744,20 @@ Default True fuegt Device zur Synchronisierung hinzu

Device.get_allios

-get_allios() +get_allios(export=None)

Gibt eine Liste aller Inputs und Outputs zurueck, keine MEMs. +

+ Bleibt Parameter 'export' auf None werden alle Inputs und Outputs + zurueckgegeben. Wird 'export' auf True/False gesetzt, werden nur Inputs + und Outputs zurueckgegeben, bei denen der Wert 'Export' in piCtory + uebereinstimmt.

+
export
+
+Nur In-/Outputs mit angegebenen 'Export' Wert in piCtory +
+
Returns:
Input und Output, keine MEMs @@ -752,10 +765,19 @@ Gibt eine Liste aller Inputs und Outputs zurueck, keine MEMs.

Device.get_inputs

-get_inputs() +get_inputs(export=None)

Gibt eine Liste aller Inputs zurueck. +

+ Bleibt Parameter 'export' auf None werden alle Inputs zurueckgegeben. + Wird 'export' auf True/False gesetzt, werden nur Inputs zurueckgegeben, + bei denen der Wert 'Export' in piCtory uebereinstimmt.

+
export
+
+Nur Inputs mit angegebenen 'Export' Wert in piCtory +
+
Returns:
Inputs @@ -763,10 +785,19 @@ Gibt eine Liste aller Inputs zurueck.

Device.get_memories

-get_memories() +get_memories(export=None)

-Gibt eine Liste aller mems zurueck. +Gibt eine Liste aller Memoryobjekte zurueck. +

+ Bleibt Parameter 'export' auf None werden alle Mems zurueckgegeben. + Wird 'export' auf True/False gesetzt, werden nur Mems zurueckgegeben, + bei denen der Wert 'Export' in piCtory uebereinstimmt.

+
export
+
+Nur Mems mit angegebenen 'Export' Wert in piCtory +
+
Returns:
Mems @@ -774,10 +805,19 @@ Gibt eine Liste aller mems zurueck.

Device.get_outputs

-get_outputs() +get_outputs(export=None)

Gibt eine Liste aller Outputs zurueck. +

+ Bleibt Parameter 'export' auf None werden alle Outputs zurueckgegeben. + Wird 'export' auf True/False gesetzt, werden nur Outputs + zurueckgegeben, bei denen der Wert 'Export' in piCtory uebereinstimmt.

+
export
+
+Nur Outputs mit angegebenen 'Export' Wert in piCtory +
+
Returns:
Outputs diff --git a/doc/revpimodio2.helper.html b/doc/revpimodio2.helper.html index 5859e23..634fd01 100644 --- a/doc/revpimodio2.helper.html +++ b/doc/revpimodio2.helper.html @@ -26,6 +26,9 @@ Classes ProcimgWriter Klasse fuer Synchroniseriungs-Thread. + +Var +

@@ -65,7 +68,7 @@ None

Class Attributes

- +
None
__slots__

Class Methods

@@ -351,7 +354,7 @@ Thread

Class Attributes

- +
None
__slots__

Class Methods

@@ -426,7 +429,7 @@ Thread

Class Attributes

- +
ioerrors
maxioerrors
refresh
__slots__
ioerrors
maxioerrors
refresh

Class Methods

@@ -592,6 +595,35 @@ ProcimgWriter.stop

Beendet die automatische Prozessabbildsynchronisierung.

+ +

+ +

Var

+ +

+Derived from

+None +

+Class Attributes

+ + +
None
+

+Class Methods

+ + +
None
+

+Methods

+ + +
None
+

+Static Methods

+ + +
None
+
\ No newline at end of file diff --git a/doc/revpimodio2.modio.html b/doc/revpimodio2.modio.html index 0086303..75abfc6 100644 --- a/doc/revpimodio2.modio.html +++ b/doc/revpimodio2.modio.html @@ -345,7 +345,7 @@ Beendet autorefresh und alle Threads.

RevPiModIO.cycleloop

-cycleloop(func, cycletime=None) +cycleloop(func, cycletime=50)

Startet den Cycleloop.

@@ -358,23 +358,24 @@ Startet den Cycleloop. Prozessabbild geschrieben.

Verlassen wird der Cycleloop, wenn die aufgerufene Funktion einen - Rueckgabewert nicht gleich None liefert, oder durch Aufruf von - revpimodio.exit(). + Rueckgabewert nicht gleich None liefert (z.B. return True), oder durch + Aufruf von .exit().

HINWEIS: Die Aktualisierungszeit und die Laufzeit der Funktion duerfen die eingestellte autorefresh Zeit, bzw. uebergebene cycletime nicht ueberschreiten!

- Ueber das Attribut cycletime kann die Aktualisierungsrate fuer das - Prozessabbild gesetzt werden. + Ueber den Parameter cycletime wird die gewuenschte Zukluszeit der + uebergebenen Funktion gesetzt. Der Standardwert betraegt + 50 Millisekunden, in denen das Prozessabild eingelesen, die uebergebene + Funktion ausgefuert und das Prozessabbild geschrieben wird.

func
Funktion, die ausgefuehrt werden soll
cycletime
-Zykluszeit in Millisekunden, bei Nichtangabe wird - aktuelle .cycletime Zeit verwendet - Standardwert 50 ms +Zykluszeit in Millisekunden - Standardwert 50 ms
Returns:
diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api index 3371e9e..e993119 100644 --- a/eric-revpimodio2.api +++ b/eric-revpimodio2.api @@ -43,10 +43,10 @@ revpimodio2.device.Device._devconfigure?5() revpimodio2.device.Device._get_offset?5() revpimodio2.device.Device._get_producttype?5() revpimodio2.device.Device.autorefresh?4(activate=True) -revpimodio2.device.Device.get_allios?4() -revpimodio2.device.Device.get_inputs?4() -revpimodio2.device.Device.get_memories?4() -revpimodio2.device.Device.get_outputs?4() +revpimodio2.device.Device.get_allios?4(export=None) +revpimodio2.device.Device.get_inputs?4(export=None) +revpimodio2.device.Device.get_memories?4(export=None) +revpimodio2.device.Device.get_outputs?4(export=None) revpimodio2.device.Device.length?7 revpimodio2.device.Device.name?7 revpimodio2.device.Device.offset?7 @@ -152,7 +152,7 @@ revpimodio2.modio.RevPiModIO._set_maxioerrors?5(value) revpimodio2.modio.RevPiModIO.autorefresh_all?4() revpimodio2.modio.RevPiModIO.cleanup?4() revpimodio2.modio.RevPiModIO.configrsc?7 -revpimodio2.modio.RevPiModIO.cycleloop?4(func, cycletime=None) +revpimodio2.modio.RevPiModIO.cycleloop?4(func, cycletime=50) revpimodio2.modio.RevPiModIO.cycletime?7 revpimodio2.modio.RevPiModIO.exit?4(full=True) revpimodio2.modio.RevPiModIO.get_jconfigrsc?4() diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 859bed7..f9096cd 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -213,7 +213,7 @@ class Device(object): def __iter__(self): """Gibt Iterator aller IOs zurueck. @return aller IOs""" - return self.__getioiter(self._slc_devoff) + return self.__getioiter(self._slc_devoff, None) def __len__(self): """Gibt Anzahl der Bytes zurueck, die dieses Device belegt. @@ -225,13 +225,17 @@ class Device(object): @return Devicename""" return self._name - def __getioiter(self, ioslc): + def __getioiter(self, ioslc, export): """Gibt mit allen IOs zurueck. + @param ioslc IO Abschnitt - @return IOs als Iterator""" + @param export Filter fuer 'Export' Flag in piCtory + @return IOs als Iterator + + """ for lst_io in self._modio.io[ioslc]: for io in lst_io: - if io is not None: + if io is not None and (export is None or io.export == export): yield io def _buildio(self, dict_io, iotype): @@ -335,27 +339,60 @@ class Device(object): if not self._modio._monitoring: self._modio.writeprocimg(self) - def get_allios(self): + def get_allios(self, export=None): """Gibt eine Liste aller Inputs und Outputs zurueck, keine MEMs. - @return Input und Output, keine MEMs""" + + Bleibt Parameter 'export' auf None werden alle Inputs und Outputs + zurueckgegeben. Wird 'export' auf True/False gesetzt, werden nur Inputs + und Outputs zurueckgegeben, bei denen der Wert 'Export' in piCtory + uebereinstimmt. + + @param export Nur In-/Outputs mit angegebenen 'Export' Wert in piCtory + @return Input und Output, keine MEMs + + """ return list(self.__getioiter( - slice(self._slc_inpoff.start, self._slc_outoff.stop) + slice(self._slc_inpoff.start, self._slc_outoff.stop), export )) - def get_inputs(self): + def get_inputs(self, export=None): """Gibt eine Liste aller Inputs zurueck. - @return Inputs""" - return list(self.__getioiter(self._slc_inpoff)) - def get_outputs(self): + Bleibt Parameter 'export' auf None werden alle Inputs zurueckgegeben. + Wird 'export' auf True/False gesetzt, werden nur Inputs zurueckgegeben, + bei denen der Wert 'Export' in piCtory uebereinstimmt. + + @param export Nur Inputs mit angegebenen 'Export' Wert in piCtory + @return Inputs + + """ + return list(self.__getioiter(self._slc_inpoff, export)) + + def get_outputs(self, export=None): """Gibt eine Liste aller Outputs zurueck. - @return Outputs""" - return list(self.__getioiter(self._slc_outoff)) - def get_memories(self): - """Gibt eine Liste aller mems zurueck. - @return Mems""" - return list(self.__getioiter(self._slc_memoff)) + Bleibt Parameter 'export' auf None werden alle Outputs zurueckgegeben. + Wird 'export' auf True/False gesetzt, werden nur Outputs + zurueckgegeben, bei denen der Wert 'Export' in piCtory uebereinstimmt. + + @param export Nur Outputs mit angegebenen 'Export' Wert in piCtory + @return Outputs + + """ + return list(self.__getioiter(self._slc_outoff, export)) + + def get_memories(self, export=None): + """Gibt eine Liste aller Memoryobjekte zurueck. + + Bleibt Parameter 'export' auf None werden alle Mems zurueckgegeben. + Wird 'export' auf True/False gesetzt, werden nur Mems zurueckgegeben, + bei denen der Wert 'Export' in piCtory uebereinstimmt. + + @param export Nur Mems mit angegebenen 'Export' Wert in piCtory + @return Mems + + """ + return list(self.__getioiter(self._slc_memoff, export)) def readprocimg(self): """Alle Inputs fuer dieses Device vom Prozessabbild einlesen. @@ -832,7 +869,7 @@ class Virtual(Gateway): for io in self.get_inputs(): self._ba_devdata[io._slc_address] = io._defaultvalue - # Outpus auf Bus schreiben + # Outputs auf Bus schreiben try: self._modio._myfh.seek(self._slc_inpoff.start) self._modio._myfh.write(self._ba_devdata[self._slc_inp]) diff --git a/revpimodio2/helper.py b/revpimodio2/helper.py index 6a68e93..5405082 100644 --- a/revpimodio2/helper.py +++ b/revpimodio2/helper.py @@ -556,7 +556,6 @@ class ProcimgWriter(Thread): def stop(self): """Beendet die automatische Prozessabbildsynchronisierung.""" - self._collect_events(False) self._work.set() def set_maxioerrors(self, value): @@ -570,13 +569,13 @@ class ProcimgWriter(Thread): def set_refresh(self, value): """Setzt die Zykluszeit in Millisekunden. @param value Millisekunden""" - if type(value) == int and 10 <= value <= 2000: + if type(value) == int and 5 <= value <= 2000: waitdiff = self._refresh - self._adjwait self._refresh = value / 1000 - self._adjwait = self._refresh - waitdiff + self._adjwait = 0 if waitdiff < 0 else self._refresh - waitdiff else: raise ValueError( - "refresh time must be 10 to 2000 milliseconds" + "refresh time must be 5 to 2000 milliseconds" ) ioerrors = property(_get_ioerrors) diff --git a/revpimodio2/io.py b/revpimodio2/io.py index 05f781a..0c5a4d7 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -254,7 +254,7 @@ class IOBase(object): __slots__ = "_bitaddress", "_bitlength", "_byteorder", "_defaultvalue", \ "_iotype", "_length", "_name", "_parentdevice", \ - "_signed", "_slc_address", "bmk" + "_signed", "_slc_address", "bmk", "export" def __init__(self, parentdevice, valuelist, iotype, byteorder, signed): """Instantiierung der IOBase-Klasse. @@ -268,7 +268,7 @@ class IOBase(object): """ # ["name","defval","bitlen","startaddrdev",exp,"idx","bmk","bitaddr"] - # [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] + # [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] self._parentdevice = parentdevice # Bitadressen auf Bytes aufbrechen und umrechnen @@ -283,6 +283,7 @@ class IOBase(object): self._name = valuelist[0] self._signed = signed self.bmk = valuelist[6] + self.export = bool(valuelist[4]) int_startaddress = int(valuelist[3]) if self._bitaddress == -1: diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index 1363877..484567b 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -6,10 +6,12 @@ __license__ = "LGPLv3" import warnings from json import load as jload +from multiprocessing import cpu_count from os import access, F_OK, R_OK from queue import Empty 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 @@ -224,6 +226,10 @@ class RevPiModIO(object): # ImgWriter erstellen self._imgwriter = helpermodule.ProcimgWriter(self) + # Refreshzeit CM1 25 Hz / CM3 50 Hz + if not isinstance(self, RevPiNetIO): + self._imgwriter.refresh = 20 if cpu_count() > 1 else 40 + # Aktuellen Outputstatus von procimg einlesen if self._syncoutputs: self.syncoutputs() @@ -349,7 +355,7 @@ class RevPiModIO(object): self.io = None self.summary = None - def cycleloop(self, func, cycletime=None): + def cycleloop(self, func, cycletime=50): """Startet den Cycleloop. Der aktuelle Programmthread wird hier bis Aufruf von @@ -361,19 +367,20 @@ class RevPiModIO(object): Prozessabbild geschrieben. Verlassen wird der Cycleloop, wenn die aufgerufene Funktion einen - Rueckgabewert nicht gleich None liefert, oder durch Aufruf von - revpimodio.exit(). + Rueckgabewert nicht gleich None liefert (z.B. return True), oder durch + Aufruf von .exit(). HINWEIS: Die Aktualisierungszeit und die Laufzeit der Funktion duerfen die eingestellte autorefresh Zeit, bzw. uebergebene cycletime nicht ueberschreiten! - Ueber das Attribut cycletime kann die Aktualisierungsrate fuer das - Prozessabbild gesetzt werden. + Ueber den Parameter cycletime wird die gewuenschte Zukluszeit der + uebergebenen Funktion gesetzt. Der Standardwert betraegt + 50 Millisekunden, in denen das Prozessabild eingelesen, die uebergebene + Funktion ausgefuert und das Prozessabbild geschrieben wird. @param func Funktion, die ausgefuehrt werden soll - @param cycletime Zykluszeit in Millisekunden, bei Nichtangabe wird - aktuelle .cycletime Zeit verwendet - Standardwert 50 ms + @param cycletime Zykluszeit in Millisekunden - Standardwert 50 ms @return None """ @@ -385,7 +392,10 @@ class RevPiModIO(object): # Prüfen ob Devices in autorefresh sind if len(self._lst_refresh) == 0: - raise RuntimeError("no device with autorefresh activated") + raise RuntimeError( + "no device with autorefresh activated - use autorefresh=True " + "or call .autorefresh_all() before entering cycleloop" + ) # Prüfen ob Funktion callable ist if not callable(func): @@ -394,7 +404,8 @@ class RevPiModIO(object): ) # Zykluszeit übernehmen - if not (cycletime is None or cycletime == self._imgwriter.refresh): + old_cycletime = self._imgwriter.refresh + if not cycletime == self._imgwriter.refresh: self._imgwriter.refresh = cycletime # Zeitänderung in _imgwriter neuladen @@ -439,6 +450,9 @@ class RevPiModIO(object): # Cycleloop beenden self._looprunning = False + # Alte autorefresh Zeit setzen + self._imgwriter.refresh = old_cycletime + return ec def exit(self, full=True): @@ -568,7 +582,10 @@ class RevPiModIO(object): # Prüfen ob Devices in autorefresh sind if len(self._lst_refresh) == 0: - raise RuntimeError("no device with autorefresh activated") + raise RuntimeError( + "no device with autorefresh activated - use autorefresh=True " + "or call .autorefresh_all() before entering mainloop" + ) # Thread erstellen, wenn nicht blockieren soll if not blocking: @@ -593,12 +610,33 @@ class RevPiModIO(object): # ImgWriter mit Eventüberwachung aktivieren self._imgwriter._collect_events(True) e = None + runtime = 0 while not self._exit.is_set(): + + # Laufzeit der Eventqueue auf 0 setzen + if self._imgwriter._eventq.qsize() == 0: + runtime = 0 + try: tup_fire = self._imgwriter._eventq.get(timeout=1) + + # Messung Laufzeit der Queue starten + if runtime == 0: + runtime = default_timer() + # Direct callen da Prüfung in io.IOBase.reg_event ist tup_fire[0].func(tup_fire[1], tup_fire[2]) + + # Laufzeitprüfung + if runtime != -1 and \ + default_timer() - runtime > self._imgwriter._refresh: + runtime = -1 + warnings.warn( + "can not execute all event functions in one cycle - " + "rise .cycletime or optimize your event functions", + RuntimeWarning + ) except Empty: if not self._exit.is_set() and not self._imgwriter.is_alive(): self.exit(full=False) @@ -889,4 +927,4 @@ class RevPiModIODriver(RevPiModIOSelected): # Nachträglicher Import -from .netio import RevPiNetIODriver +from .netio import RevPiNetIODriver, RevPiNetIO