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.

+
Up
+

+ +

Var

+ +

+Derived from

+None +

+Class Attributes

+ + +
None
+

+Class Methods

+ + +
None
+

+Methods

+ + +
None
+

+Static Methods

+ + +
None
+
Up

\ 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