handlesignalend() prüfte immer auf cleanupfunc, auch wenn None

cycleloop cycletime=None gesetzt - bei Nichtangabe wurde immer 50 gesetzt
io.reg_timerevent() hinzugefügt
docstring
This commit is contained in:
2017-08-31 14:27:38 +02:00
parent 705ae09cd0
commit c226e91550
8 changed files with 148 additions and 24 deletions

View File

@@ -24,7 +24,7 @@ __all__ = ["RevPiModIO", "RevPiModIOSelected", "RevPiModIODriver"]
__author__ = "Sven Sager <akira@revpimodio.org>"
__name__ = "revpimodio2"
__package__ = "revpimodio2"
__version__ = "2.0.1"
__version__ = "2.0.2"
# Global package values
OFF = 0

View File

@@ -363,6 +363,9 @@ class IOBase(object):
aendert. Mit Angabe von optionalen Parametern kann das
Ausloeseverhalten gesteuert werden.
HINWEIS: Die delay-Zeit muss in die .cycletime passen, ist dies nicht
der Fall, wird IMMER aufgerundet!
@param func Funktion die bei Aenderung aufgerufen werden soll
@param delay Verzoegerung in ms zum Ausloesen wenn Wert gleich bleibt
@param edge Ausfuehren bei RISING, FALLING or BOTH Wertaenderung
@@ -376,7 +379,7 @@ class IOBase(object):
)
if type(delay) != int or delay < 0:
raise AttributeError(
"parameter 'delay' must be greater or equal 0"
"'delay' must be <class 'int'> and greater or equal 0"
)
if edge != BOTH and self._bitaddress < 0:
raise AttributeError(
@@ -385,7 +388,7 @@ class IOBase(object):
if self not in self._parentdevice._dict_events:
self._parentdevice._dict_events[self] = \
[(func, edge, as_thread, delay)]
[(func, edge, as_thread, delay, True)]
else:
# Prüfen ob Funktion schon registriert ist
for regfunc in self._parentdevice._dict_events[self]:
@@ -417,7 +420,77 @@ class IOBase(object):
# Eventfunktion einfügen
self._parentdevice._dict_events[self].append(
(func, edge, as_thread, delay)
(func, edge, as_thread, delay, True)
)
def reg_timerevent(self, func, delay, edge=BOTH, as_thread=False):
"""Registriert fuer IO einen Timer, welcher nach delay func ausfuehrt.
Der Timer wird gestartet, wenn sich der IO Wert aendert und fuehrt die
uebergebene Funktion aus - auch wenn sich der IO Wert in der
zwischenzeit geaendert hat. Sollte der Timer nicht abelaufen sein und
die Bedingugn erneut zutreffen, wird der Timer NICHT auf den delay Wert
zurueckgesetzt oder ein zweites Mal gestartet. Fuer dieses Verhalten
kann .reg_event(..., delay=wert) verwendet werden.
HINWEIS: Die delay-Zeit muss in die .cycletime passen, ist dies nicht
der Fall, wird IMMER aufgerundet!
@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
"""
# 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)
)
def replace_io(self, name, frm, **kwargs):

View File

@@ -8,6 +8,7 @@
"""RevPiModIO Hauptklasse."""
import warnings
from json import load as jload
from math import ceil
from os import access, F_OK, R_OK
from signal import signal, SIG_DFL, SIGINT, SIGTERM
from threading import Thread, Event
@@ -313,7 +314,7 @@ class RevPiModIO(object):
self.io = None
self.summary = None
def cycleloop(self, func, cycletime=50):
def cycleloop(self, func, cycletime=None):
"""Startet den Cycleloop.
Der aktuelle Programmthread wird hier bis Aufruf von
@@ -336,7 +337,8 @@ class RevPiModIO(object):
Prozessabbild gesetzt werden.
@param func Funktion, die ausgefuehrt werden soll
@param cycletime autorefresh Wert in Millisekunden
@param cycletime Zykluszeit in Millisekunden, bei Nichtangabe wird
aktuelle .cycletime Zeit verwendet - Standardwert 50 ms
@return None
"""
@@ -357,7 +359,7 @@ class RevPiModIO(object):
)
# Zykluszeit übernehmen
if cycletime != self._imgwriter.refresh:
if not (cycletime is None or cycletime == self._imgwriter.refresh):
self._imgwriter.refresh = cycletime
# Cycleloop starten
@@ -460,7 +462,7 @@ class RevPiModIO(object):
"""
# Prüfen ob Funktion callable ist
if not callable(cleanupfunc):
if not (cleanupfunc is None or callable(cleanupfunc)):
raise RuntimeError(
"registered function '{}' ist not callable".format(cleanupfunc)
)
@@ -526,7 +528,6 @@ class RevPiModIO(object):
lst_fire = []
dict_delay = {}
while not self._exit.is_set():
# Auf neue Daten warten und nur ausführen wenn set()
if not self._imgwriter.newdata.wait(2.5):
if not self._exit.is_set() and not self._imgwriter.is_alive():
@@ -573,11 +574,14 @@ class RevPiModIO(object):
))
else:
# Verzögertes Event in dict einfügen
dict_delay[(
tupfire = (
regfunc, io_event._name, io_event.value
)] = int(
regfunc[3] / self._imgwriter.refresh
)
if regfunc[4] or tupfire not in dict_delay:
dict_delay[tupfire] = ceil(
regfunc[3] /
self._imgwriter.refresh
)
else:
for regfunc in dev._dict_events[io_event]:
if regfunc[3] == 0:
@@ -586,9 +590,12 @@ class RevPiModIO(object):
)
else:
# Verzögertes Event in dict einfügen
dict_delay[(
regfunc, io_event._name, io_event.value
)] = int(regfunc[3] / self._imgwriter.refresh)
if regfunc[4] or regfunc not in dict_delay:
dict_delay[(
regfunc, io_event._name, io_event.value
)] = ceil(
regfunc[3] / self._imgwriter.refresh
)
# Nach Verarbeitung aller IOs die Bytes kopieren
dev._filelock.acquire()
@@ -599,9 +606,13 @@ class RevPiModIO(object):
if not freeze:
self._imgwriter.lck_refresh.release()
# EventTuple:
# ((func, edge, as_thread, delay, löschen), ioname, iovalue)
# Verzögerte Events prüfen
for tup_fire in list(dict_delay.keys()):
if getattr(self.io, tup_fire[1]).value != tup_fire[2]:
if tup_fire[0][4] \
and getattr(self.io, tup_fire[1]).value != tup_fire[2]:
del dict_delay[tup_fire]
else:
dict_delay[tup_fire] -= 1
@@ -612,7 +623,6 @@ class RevPiModIO(object):
# Erst nach Datenübernahme alle Events feuern
while len(lst_fire) > 0:
# EventTuple ((func, edge, as_thread, delay), ioname, iovalue)
tup_fire = lst_fire.pop()
if tup_fire[0][2]:
th = helpermodule.EventCallback(