mirror of
https://github.com/naruxde/revpimodio2.git
synced 2025-11-08 22:03:53 +01:00
IOEvent-Klasse eingebaut - Ersetzt tuple()
reg_event, reg_timerevent über zentrale Funktion verwaltet
This commit is contained in:
@@ -24,6 +24,9 @@ Classes</h3>
|
||||
<td><a style="color:#0000FF" href="#IOBase">IOBase</a></td>
|
||||
<td>Basisklasse fuer alle IO-Objekte.</td>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#IOEvent">IOEvent</a></td>
|
||||
<td>Basisklasse fuer IO-Events.</td>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#IOList">IOList</a></td>
|
||||
<td>Basisklasse fuer direkten Zugriff auf IO Objekte.</td>
|
||||
</tr><tr>
|
||||
@@ -141,6 +144,9 @@ Methods</h3>
|
||||
<td><a style="color:#0000FF" href="#IOBase.__len__">__len__</a></td>
|
||||
<td>Gibt die Bytelaenge des IO zurueck.</td>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#IOBase.__reg_xevent">__reg_xevent</a></td>
|
||||
<td>Verwaltet reg_event und reg_timerevent.</td>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#IOBase.__str__">__str__</a></td>
|
||||
<td><class 'str'>-Wert der Klasse.</td>
|
||||
</tr><tr>
|
||||
@@ -228,6 +234,29 @@ Gibt die Bytelaenge des IO zurueck.
|
||||
<dd>
|
||||
Bytelaenge des IO - 0 bei BITs
|
||||
</dd>
|
||||
</dl><a NAME="IOBase.__reg_xevent" ID="IOBase.__reg_xevent"></a>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
IOBase.__reg_xevent</h3>
|
||||
<b>__reg_xevent</b>(<i>func, delay, edge, as_thread, overwrite</i>)
|
||||
<p>
|
||||
Verwaltet reg_event und reg_timerevent.
|
||||
</p><dl>
|
||||
<dt><i>func</i></dt>
|
||||
<dd>
|
||||
Funktion die bei Aenderung aufgerufen werden soll
|
||||
</dd><dt><i>delay</i></dt>
|
||||
<dd>
|
||||
Verzoegerung in ms zum Ausloesen - auch bei Wertaenderung
|
||||
</dd><dt><i>edge</i></dt>
|
||||
<dd>
|
||||
Ausfuehren bei RISING, FALLING or BOTH Wertaenderung
|
||||
</dd><dt><i>as_thread</i></dt>
|
||||
<dd>
|
||||
Bei True, Funktion als EventCallback-Thread ausfuehren
|
||||
</dd><dt><i>overwrite</i></dt>
|
||||
<dd>
|
||||
Wenn True, wird Event bei ueberschrieben
|
||||
</dd>
|
||||
</dl><a NAME="IOBase.__str__" ID="IOBase.__str__"></a>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
IOBase.__str__</h3>
|
||||
@@ -468,6 +497,46 @@ Zeit in ms nach der abgebrochen wird
|
||||
</dl>
|
||||
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
|
||||
<hr /><hr />
|
||||
<a NAME="IOEvent" ID="IOEvent"></a>
|
||||
<h2 style="background-color:#FFFFFF;color:#0000FF">IOEvent</h2>
|
||||
<p>
|
||||
Basisklasse fuer IO-Events.
|
||||
</p>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
Derived from</h3>
|
||||
object
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
Class Attributes</h3>
|
||||
<table>
|
||||
<tr><td>None</td></tr>
|
||||
</table>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
Class Methods</h3>
|
||||
<table>
|
||||
<tr><td>None</td></tr>
|
||||
</table>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
Methods</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<td><a style="color:#0000FF" href="#IOEvent.__init__">IOEvent</a></td>
|
||||
<td>Init IOEvent class.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
Static Methods</h3>
|
||||
<table>
|
||||
<tr><td>None</td></tr>
|
||||
</table>
|
||||
<a NAME="IOEvent.__init__" ID="IOEvent.__init__"></a>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
IOEvent (Constructor)</h3>
|
||||
<b>IOEvent</b>(<i>func, edge, as_thread, delay, overwrite</i>)
|
||||
<p>
|
||||
Init IOEvent class.
|
||||
</p>
|
||||
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
|
||||
<hr /><hr />
|
||||
<a NAME="IOList" ID="IOList"></a>
|
||||
<h2 style="background-color:#FFFFFF;color:#0000FF">IOList</h2>
|
||||
<p>
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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 <class 'int'> 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 <class 'int'> 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 <class 'int'> 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)
|
||||
|
||||
|
||||
@@ -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 <class 'dict'>.
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user