diff --git a/doc/revpimodio2.device.html b/doc/revpimodio2.device.html index d88c158..0753f3b 100644 --- a/doc/revpimodio2.device.html +++ b/doc/revpimodio2.device.html @@ -556,6 +556,9 @@ Methods __getioiter Gibt mit allen IOs zurueck. +__getitem__ +Gibt IO an angegebener Stelle zurueck. + __int__ Gibt die Positon im RevPi Bus zurueck. @@ -580,6 +583,9 @@ Methods _get_producttype Gibt den Produkttypen des device zurueck. +_update_my_io_list +Erzeugt eine neue IO Liste fuer schnellen Zugriff. + autorefresh Registriert dieses Device fuer die automatische Synchronisierung. @@ -676,6 +682,22 @@ Filter fuer 'Export' Flag in piCtory
IOs als Iterator
+ +

+Device.__getitem__

+__getitem__(key) +

+Gibt IO an angegebener Stelle zurueck. +

+
key
+
+Index des IOs auf dem device als +
+
+
Returns:
+
+Gefundenes IO-Objekt +

Device.__int__

@@ -767,7 +789,13 @@ Gibt den Produkttypen des device zurueck.
Deviceprodukttyp
- + +

+Device._update_my_io_list

+_update_my_io_list() +

+Erzeugt eine neue IO Liste fuer schnellen Zugriff. +

Device.autorefresh

autorefresh(activate=True) @@ -1049,7 +1077,7 @@ DeviceList.__iter__ Gibt Iterator aller Devices zurueck.

Die Reihenfolge ist nach Position im Prozessabbild sortiert und nicht - nach Position (Dies entspricht der Positionierung aus piCtory)! + nach Positionsnummer (Dies entspricht der Positionierung aus piCtory)!

Returns:
diff --git a/doc/revpimodio2.io.html b/doc/revpimodio2.io.html index 0637b6f..a83171d 100644 --- a/doc/revpimodio2.io.html +++ b/doc/revpimodio2.io.html @@ -241,7 +241,7 @@ Bytelaenge des IO - 0 bei BITs

IOBase.__reg_xevent

-__reg_xevent(func, delay, edge, as_thread, overwrite) +__reg_xevent(func, delay, edge, as_thread, overwrite, prefire)

Verwaltet reg_event und reg_timerevent.

@@ -260,6 +260,9 @@ Bei True, Funktion als EventCallback-Thread ausfuehren
overwrite
Wenn True, wird Event bei ueberschrieben +
prefire
+
+Ausloesen mit aktuellem Wert, wenn mainloop startet

@@ -330,7 +333,7 @@ IO-Wert als oder

IOBase.reg_event

-reg_event(func, delay=0, edge=BOTH, as_thread=False) +reg_event(func, delay=0, edge=BOTH, as_thread=False, prefire=False)

Registriert fuer IO ein Event bei der Eventueberwachung.

@@ -353,6 +356,9 @@ Ausfuehren bei RISING, FALLING or BOTH Wertaenderung

as_thread
Bei True, Funktion als EventCallback-Thread ausfuehren +
prefire
+
+Ausloesen mit aktuellem Wert, wenn mainloop startet

@@ -502,7 +508,7 @@ Static Methods

IOEvent (Constructor)

-IOEvent(func, edge, as_thread, delay, overwrite) +IOEvent(func, edge, as_thread, delay, overwrite, prefire)

Init IOEvent class.

diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api index 889636a..f677fe9 100644 --- a/eric-revpimodio2.api +++ b/eric-revpimodio2.api @@ -43,6 +43,7 @@ revpimodio2.device.Device._buildio?5(dict_io, iotype) revpimodio2.device.Device._devconfigure?5() revpimodio2.device.Device._get_offset?5() revpimodio2.device.Device._get_producttype?5() +revpimodio2.device.Device._update_my_io_list?5() revpimodio2.device.Device.autorefresh?4(activate=True) revpimodio2.device.Device.get_allios?4(export=None) revpimodio2.device.Device.get_inputs?4(export=None) @@ -106,7 +107,7 @@ revpimodio2.io.IOBase.get_defaultvalue?4() revpimodio2.io.IOBase.get_value?4() revpimodio2.io.IOBase.length?7 revpimodio2.io.IOBase.name?7 -revpimodio2.io.IOBase.reg_event?4(func, delay=0, edge=BOTH, as_thread=False) +revpimodio2.io.IOBase.reg_event?4(func, delay=0, edge=BOTH, as_thread=False, prefire=False) revpimodio2.io.IOBase.reg_timerevent?4(func, delay, edge=BOTH, as_thread=False) revpimodio2.io.IOBase.set_value?4(value) revpimodio2.io.IOBase.type?7 @@ -114,7 +115,7 @@ revpimodio2.io.IOBase.unreg_event?4(func=None, edge=None) revpimodio2.io.IOBase.value?7 revpimodio2.io.IOBase.wait?4(edge=BOTH, exitevent=None, okvalue=None, timeout=0) revpimodio2.io.IOBase?1(parentdevice, valuelist, iotype, byteorder, signed) -revpimodio2.io.IOEvent?1(func, edge, as_thread, delay, overwrite) +revpimodio2.io.IOEvent?1(func, edge, as_thread, delay, overwrite, prefire) revpimodio2.io.IOList._private_register_new_io_object?5(new_io) revpimodio2.io.IOList?1() revpimodio2.io.IntIO._get_signed?5() diff --git a/revpimodio2/device.py b/revpimodio2/device.py index 0941f29..a668c62 100644 --- a/revpimodio2/device.py +++ b/revpimodio2/device.py @@ -72,7 +72,7 @@ class DeviceList(object): """Gibt Iterator aller Devices zurueck. Die Reihenfolge ist nach Position im Prozessabbild sortiert und nicht - nach Position (Dies entspricht der Positionierung aus piCtory)! + nach Positionsnummer (Dies entspricht der Positionierung aus piCtory)! @return aller Devices""" for dev in sorted( @@ -106,7 +106,7 @@ class Device(object): """ - __slots__ = "_ba_devdata", "_ba_datacp", \ + __slots__ = "__my_io_list", "_ba_devdata", "_ba_datacp", \ "_dict_events", "_filelock", "_length", "_modio", "_name", "_offset", \ "_position", "_producttype", "_selfupdate", "_slc_devoff", \ "_slc_inp", "_slc_inpoff", "_slc_mem", "_slc_memoff", \ @@ -126,6 +126,7 @@ class Device(object): self._dict_events = {} self._filelock = Lock() self._length = 0 + self.__my_io_list = [] self._selfupdate = False # Wertzuweisung aus dict_device @@ -182,6 +183,9 @@ class Device(object): # Spezielle Konfiguration von abgeleiteten Klassen durchführen self._devconfigure() + # IO Liste aktualisieren für schnellen Indexzugriff + self._update_my_io_list() + def __bytes__(self): """Gibt alle Daten des Devices als zurueck. @return Devicedaten als """ @@ -205,6 +209,12 @@ class Device(object): return key in self._modio.io \ and getattr(self._modio.io, key)._parentdevice == self + def __getitem__(self, key): + """Gibt IO an angegebener Stelle zurueck. + @param key Index des IOs auf dem device als + @return Gefundenes IO-Objekt""" + return self.__my_io_list[key] + def __int__(self): """Gibt die Positon im RevPi Bus zurueck. @return Positionsnummer""" @@ -312,6 +322,10 @@ class Device(object): @return Deviceprodukttyp""" return self._producttype + def _update_my_io_list(self): + """Erzeugt eine neue IO Liste fuer schnellen Zugriff.""" + self.__my_io_list = list(self.__iter__()) + def autorefresh(self, activate=True): """Registriert dieses Device fuer die automatische Synchronisierung. @param activate Default True fuegt Device zur Synchronisierung hinzu""" diff --git a/revpimodio2/helper.py b/revpimodio2/helper.py index 37af3cb..fb5e2ce 100644 --- a/revpimodio2/helper.py +++ b/revpimodio2/helper.py @@ -413,9 +413,11 @@ class ProcimgWriter(Thread): if self.__eventwork != value: with self.lck_refresh: self.__eventwork = value - self.__eventqth = queue.Queue() - self._eventq = queue.Queue() - self.__dict_delay = {} + if not value: + # Nur leeren beim deaktivieren + self.__eventqth = queue.Queue() + self._eventq = queue.Queue() + self.__dict_delay = {} # Threadmanagement if value and not self.__eventth.is_alive(): diff --git a/revpimodio2/io.py b/revpimodio2/io.py index ce3ba20..49fe18a 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -21,15 +21,16 @@ class IOEvent(object): """Basisklasse fuer IO-Events.""" - __slots__ = "as_thread", "delay", "edge", "func", "overwrite" + __slots__ = "as_thread", "delay", "edge", "func", "overwrite", "prefire" - def __init__(self, func, edge, as_thread, delay, overwrite): + def __init__(self, func, edge, as_thread, delay, overwrite, prefire): """Init IOEvent class.""" self.as_thread = as_thread self.delay = delay self.edge = edge self.func = func self.overwrite = overwrite + self.prefire = prefire class IOList(object): @@ -68,6 +69,7 @@ class IOList(object): self.__dict_iobyte[io_del.address] = [] object.__delattr__(self, key) + io_del._parentdevice._update_my_io_list() def __getattr__(self, key): """Verwaltet geloeschte IOs (Attribute, die nicht existieren). @@ -125,10 +127,10 @@ class IOList(object): def __setattr__(self, key, value): """Verbietet aus Leistungsguenden das direkte Setzen von Attributen.""" - if key in [ + if key in ( "_IOList__dict_iobyte", "_IOList__dict_iorefname" - ]: + ): object.__setattr__(self, key, value) else: raise AttributeError( @@ -221,6 +223,9 @@ class IOList(object): None, None, None, None, None, None, None, None ] self.__dict_iobyte[new_io.address][new_io._bitaddress] = new_io + + if type(new_io) is StructIO: + new_io._parentdevice._update_my_io_list() else: raise TypeError("io must be or sub class") @@ -368,7 +373,7 @@ class IOBase(object): @return Namen des IOs""" return self._name - def __reg_xevent(self, func, delay, edge, as_thread, overwrite): + def __reg_xevent(self, func, delay, edge, as_thread, overwrite, prefire): """Verwaltet reg_event und reg_timerevent. @param func Funktion die bei Aenderung aufgerufen werden soll @@ -376,6 +381,7 @@ class IOBase(object): @param edge Ausfuehren bei RISING, FALLING or BOTH Wertaenderung @param as_thread Bei True, Funktion als EventCallback-Thread ausfuehren @param overwrite Wenn True, wird Event bei ueberschrieben + @param prefire Ausloesen mit aktuellem Wert, wenn mainloop startet """ # Prüfen ob Funktion callable ist @@ -391,11 +397,15 @@ class IOBase(object): raise ValueError( "parameter 'edge' can be used with bit io objects only" ) + if prefire and self._parentdevice._modio._looprunning: + raise RuntimeError( + "prefire can not be used if mainloop is running" + ) if self not in self._parentdevice._dict_events: with self._parentdevice._filelock: self._parentdevice._dict_events[self] = \ - [IOEvent(func, edge, as_thread, delay, overwrite)] + [IOEvent(func, edge, as_thread, delay, overwrite, prefire)] else: # Prüfen ob Funktion schon registriert ist for regfunc in self._parentdevice._dict_events[self]: @@ -429,7 +439,7 @@ class IOBase(object): # Eventfunktion einfügen with self._parentdevice._filelock: self._parentdevice._dict_events[self].append( - IOEvent(func, edge, as_thread, delay, overwrite) + IOEvent(func, edge, as_thread, delay, overwrite, prefire) ) def _get_address(self): @@ -464,7 +474,8 @@ class IOBase(object): else: return bytes(self._parentdevice._ba_devdata[self._slc_address]) - def reg_event(self, func, delay=0, edge=BOTH, as_thread=False): + def reg_event( + self, func, delay=0, edge=BOTH, as_thread=False, prefire=False): """Registriert fuer IO ein Event bei der Eventueberwachung. Die uebergebene Funktion wird ausgefuehrt, wenn sich der IO Wert @@ -478,9 +489,10 @@ class IOBase(object): @param delay Verzoegerung in ms zum Ausloesen wenn Wert gleich bleibt @param edge Ausfuehren bei RISING, FALLING or BOTH Wertaenderung @param as_thread Bei True, Funktion als EventCallback-Thread ausfuehren + @param prefire Ausloesen mit aktuellem Wert, wenn mainloop startet """ - self.__reg_xevent(func, delay, edge, as_thread, True) + self.__reg_xevent(func, delay, edge, as_thread, True, prefire) def reg_timerevent(self, func, delay, edge=BOTH, as_thread=False): """Registriert fuer IO einen Timer, welcher nach delay func ausfuehrt. @@ -501,7 +513,7 @@ class IOBase(object): @param as_thread Bei True, Funktion als EventCallback-Thread ausfuehren """ - self.__reg_xevent(func, delay, edge, as_thread, False) + self.__reg_xevent(func, delay, edge, as_thread, False, False) def set_value(self, value): """Setzt den Wert des IOs. diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index 146629d..ee5677d 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -10,7 +10,7 @@ from json import load as jload from multiprocessing import cpu_count from os import access, F_OK, R_OK from queue import Empty -from revpimodio2 import acheck, DeviceNotFoundError +from revpimodio2 import acheck, DeviceNotFoundError, BOTH, RISING, FALLING from signal import signal, SIG_DFL, SIGINT, SIGTERM from threading import Thread, Event, Lock from timeit import default_timer @@ -771,11 +771,29 @@ class RevPiModIO(object): self._exit.clear() self._looprunning = True - # Beim Eintritt in mainloop Bytecopy erstellen + # Beim Eintritt in mainloop Bytecopy erstellen und prefire anhängen for dev in self._lst_refresh: with dev._filelock: dev._ba_datacp = dev._ba_devdata[:] + # Prefire Events vorbereiten + for io in dev._dict_events: + for regfunc in dev._dict_events[io]: + if not regfunc.prefire: + continue + + if regfunc.edge == BOTH \ + or regfunc.edge == RISING and io.value \ + or regfunc.edge == FALLING and not io.value: + if regfunc.as_thread: + self._imgwriter.__eventqth.put( + (regfunc, io._name, io.value), False + ) + else: + self._imgwriter._eventq.put( + (regfunc, io._name, io.value), False + ) + # ImgWriter mit Eventüberwachung aktivieren self._imgwriter._collect_events(True) e = None