From 87a648cbc68d5b079047edd3325858e7d80df02a Mon Sep 17 00:00:00 2001 From: NaruX Date: Sat, 2 Dec 2017 16:17:02 +0100 Subject: [PATCH] =?UTF-8?q?IOEvent-Klasse=20eingebaut=20-=20Ersetzt=20tupl?= =?UTF-8?q?e()=20reg=5Fevent,=20reg=5Ftimerevent=20=C3=BCber=20zentrale=20?= =?UTF-8?q?Funktion=20verwaltet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/revpimodio2.io.html | 69 +++++++++++++++ eric-revpimodio2.api | 1 + revpimodio2/helper.py | 32 +++---- revpimodio2/io.py | 180 +++++++++++++++++----------------------- revpimodio2/modio.py | 4 +- 5 files changed, 166 insertions(+), 120 deletions(-) diff --git a/doc/revpimodio2.io.html b/doc/revpimodio2.io.html index 223107a..d8ca045 100644 --- a/doc/revpimodio2.io.html +++ b/doc/revpimodio2.io.html @@ -24,6 +24,9 @@ Classes IOBase Basisklasse fuer alle IO-Objekte. +IOEvent +Basisklasse fuer IO-Events. + IOList Basisklasse fuer direkten Zugriff auf IO Objekte. @@ -141,6 +144,9 @@ Methods __len__ Gibt die Bytelaenge des IO zurueck. +__reg_xevent +Verwaltet reg_event und reg_timerevent. + __str__ -Wert der Klasse. @@ -228,6 +234,29 @@ Gibt die Bytelaenge des IO zurueck.
Bytelaenge des IO - 0 bei BITs
+ +

+IOBase.__reg_xevent

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

+Verwaltet reg_event und reg_timerevent. +

+
func
+
+Funktion die bei Aenderung aufgerufen werden soll +
delay
+
+Verzoegerung in ms zum Ausloesen - auch bei Wertaenderung +
edge
+
+Ausfuehren bei RISING, FALLING or BOTH Wertaenderung +
as_thread
+
+Bei True, Funktion als EventCallback-Thread ausfuehren +
overwrite
+
+Wenn True, wird Event bei ueberschrieben +

IOBase.__str__

@@ -468,6 +497,46 @@ Zeit in ms nach der abgebrochen wird
Up


+ +

IOEvent

+

+Basisklasse fuer IO-Events. +

+

+Derived from

+object +

+Class Attributes

+ + +
None
+

+Class Methods

+ + +
None
+

+Methods

+ + + + + +
IOEventInit IOEvent class.
+

+Static Methods

+ + +
None
+ +

+IOEvent (Constructor)

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

+Init IOEvent class. +

+
Up
+

IOList

diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api index ade70dc..6c5077f 100644 --- a/eric-revpimodio2.api +++ b/eric-revpimodio2.api @@ -105,6 +105,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.IOList._private_register_new_io_object?5(new_io) revpimodio2.io.IOList?1() revpimodio2.io.IntIO._get_signed?5() diff --git a/revpimodio2/helper.py b/revpimodio2/helper.py index bca9ef2..b2375f5 100644 --- a/revpimodio2/helper.py +++ b/revpimodio2/helper.py @@ -321,11 +321,11 @@ class ProcimgWriter(Thread): continue for regfunc in dev._dict_events[io_event]: - if regfunc[1] == BOTH \ - or regfunc[1] == RISING and boolor \ - or regfunc[1] == FALLING and not boolor: - if regfunc[3] == 0: - if regfunc[2]: + if regfunc.edge == BOTH \ + or regfunc.edge == RISING and boolor \ + or regfunc.edge == FALLING and not boolor: + if regfunc.delay == 0: + if regfunc.as_thread: self.__eventqth.put( (regfunc, io_event._name, io_event.value), False @@ -340,14 +340,15 @@ class ProcimgWriter(Thread): tupfire = ( regfunc, io_event._name, io_event.value ) - if regfunc[4] or tupfire not in self.__dict_delay: + if regfunc.overwrite \ + or tupfire not in self.__dict_delay: self.__dict_delay[tupfire] = ceil( - regfunc[3] / 1000 / self._refresh + regfunc.delay / 1000 / self._refresh ) else: for regfunc in dev._dict_events[io_event]: - if regfunc[3] == 0: - if regfunc[2]: + if regfunc.delay == 0: + if regfunc.as_thread: self.__eventqth.put( (regfunc, io_event._name, io_event.value), False @@ -362,9 +363,10 @@ class ProcimgWriter(Thread): tupfire = ( regfunc, io_event._name, io_event.value ) - if regfunc[4] or tupfire not in self.__dict_delay: + if regfunc.overwrite \ + or tupfire not in self.__dict_delay: self.__dict_delay[tupfire] = ceil( - regfunc[3] / 1000 / self._refresh + regfunc.delay / 1000 / self._refresh ) # Nach Verarbeitung aller IOs die Bytes kopieren (Lock ist noch drauf) @@ -376,10 +378,9 @@ class ProcimgWriter(Thread): try: tup_fireth = self.__eventqth.get(timeout=1) th = EventCallback( - tup_fireth[0][0], tup_fireth[1], tup_fireth[2] + tup_fireth[0].func, tup_fireth[1], tup_fireth[2] ) th.start() - # TODO: Error handling except queue.Empty: pass @@ -492,7 +493,7 @@ class ProcimgWriter(Thread): # Verzögerte Events prüfen if self.__eventwork: for tup_fire in list(self.__dict_delay.keys()): - if tup_fire[0][4] \ + if tup_fire[0].overwrite \ and getattr(self._modio.io, tup_fire[1]).value != \ tup_fire[2]: del self.__dict_delay[tup_fire] @@ -500,7 +501,7 @@ class ProcimgWriter(Thread): self.__dict_delay[tup_fire] -= 1 if self.__dict_delay[tup_fire] <= 0: # Verzögertes Event übernehmen und löschen - if tup_fire[0][2]: + if tup_fire[0].as_thread: self.__eventqth.put(tup_fire, False) else: self._eventq.put(tup_fire, False) @@ -530,6 +531,7 @@ class ProcimgWriter(Thread): def stop(self): """Beendet die automatische Prozessabbildsynchronisierung.""" + self._collect_events(False) self._work.set() def set_maxioerrors(self, value): diff --git a/revpimodio2/io.py b/revpimodio2/io.py index 1bc8946..4e50f5b 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -11,6 +11,19 @@ from threading import Event from revpimodio2 import RISING, FALLING, BOTH, INP, OUT, MEM, consttostr +class IOEvent(object): + + """Basisklasse fuer IO-Events.""" + + def __init__(self, func, edge, as_thread, delay, overwrite): + """Init IOEvent class.""" + self.as_thread = as_thread + self.delay = delay + self.edge = edge + self.func = func + self.overwrite = overwrite + + class IOList(object): """Basisklasse fuer direkten Zugriff auf IO Objekte.""" @@ -317,6 +330,67 @@ class IOBase(object): @return Namen des IOs""" return self._name + def __reg_xevent(self, func, delay, edge, as_thread, overwrite): + """Verwaltet reg_event und reg_timerevent. + + @param func Funktion die bei Aenderung aufgerufen werden soll + @param delay Verzoegerung in ms zum Ausloesen - auch bei Wertaenderung + @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 + + """ + # Prüfen ob Funktion callable ist + if not callable(func): + raise AttributeError( + "registered function '{}' is not callable".format(func) + ) + if type(delay) != int or delay < 0: + raise AttributeError( + "'delay' must be and greater or equal 0" + ) + if edge != BOTH and self._bitaddress < 0: + raise AttributeError( + "parameter 'edge' can be used with bit io objects only" + ) + + if self not in self._parentdevice._dict_events: + 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]: + if regfunc.func != func: + # Nächsten Eintrag testen + continue + + if edge == BOTH or regfunc.edge == BOTH: + if self._bitaddress < 0: + raise AttributeError( + "io '{}' with function '{}' already in list." + "".format(self._name, func) + ) + else: + raise AttributeError( + "io '{}' with function '{}' already in list with " + "edge '{}' - edge '{}' not allowed anymore".format( + self._name, func, + consttostr(regfunc.edge), consttostr(edge) + ) + ) + elif regfunc.edge == edge: + raise AttributeError( + "io '{}' with function '{}' for given edge '{}' " + "already in list".format( + self._name, func, consttostr(edge) + ) + ) + + # Eventfunktion einfügen + self._parentdevice._dict_events[self].append( + IOEvent(func, edge, as_thread, delay, overwrite) + ) + def _get_address(self): """Gibt die absolute Byteadresse im Prozessabbild zurueck. @return Absolute Byteadresse""" @@ -365,56 +439,7 @@ class IOBase(object): @param as_thread Bei True, Funktion als EventCallback-Thread ausfuehren """ - # Prüfen ob Funktion callable ist - if not callable(func): - raise AttributeError( - "registered function '{}' is not callable".format(func) - ) - if type(delay) != int or delay < 0: - raise AttributeError( - "'delay' must be and greater or equal 0" - ) - if edge != BOTH and self._bitaddress < 0: - raise AttributeError( - "parameter 'edge' can be used with bit io objects only" - ) - - if self not in self._parentdevice._dict_events: - self._parentdevice._dict_events[self] = \ - [(func, edge, as_thread, delay, True)] - else: - # Prüfen ob Funktion schon registriert ist - for regfunc in self._parentdevice._dict_events[self]: - if regfunc[0] != func: - # Nächsten Eintrag testen - continue - - if edge == BOTH or regfunc[1] == BOTH: - if self._bitaddress < 0: - raise AttributeError( - "io '{}' with function '{}' already in list." - "".format(self._name, func) - ) - else: - raise AttributeError( - "io '{}' with function '{}' already in list with " - "edge '{}' - edge '{}' not allowed anymore".format( - self._name, func, - consttostr(regfunc[1]), consttostr(edge) - ) - ) - elif regfunc[1] == edge: - raise AttributeError( - "io '{}' with function '{}' for given edge '{}' " - "already in list".format( - self._name, func, consttostr(edge) - ) - ) - - # Eventfunktion einfügen - self._parentdevice._dict_events[self].append( - (func, edge, as_thread, delay, True) - ) + self.__reg_xevent(func, delay, edge, as_thread, True) def reg_timerevent(self, func, delay, edge=BOTH, as_thread=False): """Registriert fuer IO einen Timer, welcher nach delay func ausfuehrt. @@ -435,56 +460,7 @@ class IOBase(object): @param as_thread Bei True, Funktion als EventCallback-Thread ausfuehren """ - # Prüfen ob Funktion callable ist - if not callable(func): - raise AttributeError( - "registered function '{}' is not callable".format(func) - ) - if type(delay) != int or delay < 0: - raise AttributeError( - "'delay' must be and greater or equal 0" - ) - if edge != BOTH and self._bitaddress < 0: - raise AttributeError( - "parameter 'edge' can be used with bit io objects only" - ) - - if self not in self._parentdevice._dict_events: - self._parentdevice._dict_events[self] = \ - [(func, edge, as_thread, delay, False)] - else: - # Prüfen ob Funktion schon registriert ist - for regfunc in self._parentdevice._dict_events[self]: - if regfunc[0] != func: - # Nächsten Eintrag testen - continue - - if edge == BOTH or regfunc[1] == BOTH: - if self._bitaddress < 0: - raise AttributeError( - "io '{}' with function '{}' already in list." - "".format(self._name, func) - ) - else: - raise AttributeError( - "io '{}' with function '{}' already in list with " - "edge '{}' - edge '{}' not allowed anymore".format( - self._name, func, - consttostr(regfunc[1]), consttostr(edge) - ) - ) - elif regfunc[1] == edge: - raise AttributeError( - "io '{}' with function '{}' for given edge '{}' " - "already in list".format( - self._name, func, consttostr(edge) - ) - ) - - # Eventfunktion einfügen - self._parentdevice._dict_events[self].append( - (func, edge, as_thread, delay, False) - ) + self.__reg_xevent(func, delay, edge, as_thread, False) def replace_io(self, name, frm, **kwargs): """Ersetzt bestehenden IO mit Neuem. @@ -613,8 +589,8 @@ class IOBase(object): else: newlist = [] for regfunc in self._parentdevice._dict_events[self]: - if regfunc[0] != func or edge is not None \ - and regfunc[1] != edge: + if regfunc.func != func or edge is not None \ + and regfunc.edge != edge: newlist.append(regfunc) diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index f88cce0..f6c740e 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -418,7 +418,6 @@ class RevPiModIO(object): if self._imgwriter is not None and self._imgwriter.is_alive(): self._imgwriter.stop() self._imgwriter.join(self._imgwriter._refresh) - # NOTE: Prüfen, ob es sauber läuft! if self._th_mainloop is not None and self._th_mainloop.is_alive(): self._th_mainloop.join(1) while len(self._lst_refresh) > 0: @@ -426,7 +425,6 @@ class RevPiModIO(object): dev._selfupdate = False if not self._monitoring: self.writeprocimg(dev) - # NOTE: Loops müssen sich selber IMMER sauber beenden def get_jconfigrsc(self): """Laed die piCotry Konfiguration und erstellt ein . @@ -540,7 +538,7 @@ class RevPiModIO(object): try: tup_fire = self._imgwriter._eventq.get(timeout=1) # Direct callen da Prüfung in io.IOBase.reg_event ist - tup_fire[0][0](tup_fire[1], tup_fire[2]) + tup_fire[0].func(tup_fire[1], tup_fire[2]) except Empty: if not self._exit.is_set() and not self._imgwriter.is_alive(): self.exit(full=False)