mirror of
https://github.com/naruxde/revpimodio2.git
synced 2025-11-08 22:03:53 +01:00
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:
@@ -165,6 +165,9 @@ Methods</h3>
|
||||
<td><a style="color:#0000FF" href="#IOBase.reg_event">reg_event</a></td>
|
||||
<td>Registriert fuer IO ein Event bei der Eventueberwachung.</td>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#IOBase.reg_timerevent">reg_timerevent</a></td>
|
||||
<td>Registriert fuer IO einen Timer, welcher nach delay func ausfuehrt.</td>
|
||||
</tr><tr>
|
||||
<td><a style="color:#0000FF" href="#IOBase.replace_io">replace_io</a></td>
|
||||
<td>Ersetzt bestehenden IO mit Neuem.</td>
|
||||
</tr><tr>
|
||||
@@ -304,6 +307,9 @@ Registriert fuer IO ein Event bei der Eventueberwachung.
|
||||
Die uebergebene Funktion wird ausgefuehrt, wenn sich der IO Wert
|
||||
aendert. Mit Angabe von optionalen Parametern kann das
|
||||
Ausloeseverhalten gesteuert werden.
|
||||
</p><p>
|
||||
HINWEIS: Die delay-Zeit muss in die .cycletime passen, ist dies nicht
|
||||
der Fall, wird IMMER aufgerundet!
|
||||
</p><dl>
|
||||
<dt><i>func</i></dt>
|
||||
<dd>
|
||||
@@ -318,6 +324,36 @@ Ausfuehren bei RISING, FALLING or BOTH Wertaenderung
|
||||
<dd>
|
||||
Bei True, Funktion als EventCallback-Thread ausfuehren
|
||||
</dd>
|
||||
</dl><a NAME="IOBase.reg_timerevent" ID="IOBase.reg_timerevent"></a>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
IOBase.reg_timerevent</h3>
|
||||
<b>reg_timerevent</b>(<i>func, delay, edge=BOTH, as_thread=False</i>)
|
||||
<p>
|
||||
Registriert fuer IO einen Timer, welcher nach delay func ausfuehrt.
|
||||
</p><p>
|
||||
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.
|
||||
</p><p>
|
||||
HINWEIS: Die delay-Zeit muss in die .cycletime passen, ist dies nicht
|
||||
der Fall, wird IMMER aufgerundet!
|
||||
</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>
|
||||
</dl><a NAME="IOBase.replace_io" ID="IOBase.replace_io"></a>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
IOBase.replace_io</h3>
|
||||
|
||||
@@ -345,7 +345,7 @@ Beendet autorefresh und alle Threads.
|
||||
</p><a NAME="RevPiModIO.cycleloop" ID="RevPiModIO.cycleloop"></a>
|
||||
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||
RevPiModIO.cycleloop</h3>
|
||||
<b>cycleloop</b>(<i>func, cycletime=50</i>)
|
||||
<b>cycleloop</b>(<i>func, cycletime=None</i>)
|
||||
<p>
|
||||
Startet den Cycleloop.
|
||||
</p><p>
|
||||
@@ -373,7 +373,8 @@ Startet den Cycleloop.
|
||||
Funktion, die ausgefuehrt werden soll
|
||||
</dd><dt><i>cycletime</i></dt>
|
||||
<dd>
|
||||
autorefresh Wert in Millisekunden
|
||||
Zykluszeit in Millisekunden, bei Nichtangabe wird
|
||||
aktuelle .cycletime Zeit verwendet - Standardwert 50 ms
|
||||
</dd>
|
||||
</dl><dl>
|
||||
<dt>Returns:</dt>
|
||||
|
||||
@@ -86,6 +86,7 @@ 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_timerevent?4(func, delay, edge=BOTH, as_thread=False)
|
||||
revpimodio2.io.IOBase.replace_io?4(name, frm, **kwargs)
|
||||
revpimodio2.io.IOBase.set_value?4(value)
|
||||
revpimodio2.io.IOBase.type?7
|
||||
@@ -134,7 +135,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=50)
|
||||
revpimodio2.modio.RevPiModIO.cycleloop?4(func, cycletime=None)
|
||||
revpimodio2.modio.RevPiModIO.cycletime?7
|
||||
revpimodio2.modio.RevPiModIO.exit?4(full=True)
|
||||
revpimodio2.modio.RevPiModIO.get_jconfigrsc?4()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Project SYSTEM "Project-5.1.dtd">
|
||||
<!-- eric project file for project revpimodio2 -->
|
||||
<!-- Saved: 2017-08-29, 18:21:17 -->
|
||||
<!-- Saved: 2017-08-31, 13:28:15 -->
|
||||
<!-- Copyright (C) 2017 Sven Sager, akira@narux.de -->
|
||||
<Project version="5.1">
|
||||
<Language>en_US</Language>
|
||||
@@ -9,7 +9,7 @@
|
||||
<ProgLanguage mixed="0">Python3</ProgLanguage>
|
||||
<ProjectType>Console</ProjectType>
|
||||
<Description>Das Modul stellt alle Devices und IOs aus der piCtory Konfiguration in Python3 zur Verfügung. Es ermöglicht den direkten Zugriff auf die Werte über deren vergebenen Namen. Lese- und Schreibaktionen mit dem Prozessabbild werden von dem Modul selbst verwaltet, ohne dass sich der Programmierer um Offsets und Adressen kümmern muss. Für die Gatewaymodule wie ModbusTCP oder Profinet sind eigene 'Inputs' und 'Outputs' über einen bestimmten Adressbereich definierbar. Auf diese IOs kann mit Python3 über den Namen direkt auf die Werte zugegriffen werden.</Description>
|
||||
<Version>2.0.1</Version>
|
||||
<Version>2.0.2</Version>
|
||||
<Author>Sven Sager</Author>
|
||||
<Email>akira@narux.de</Email>
|
||||
<Eol index="1"/>
|
||||
@@ -28,6 +28,9 @@
|
||||
<Source>test/test_net_leistung.py</Source>
|
||||
<Source>test/web_cycleloop.py</Source>
|
||||
<Source>test/web_mainloop.py</Source>
|
||||
<Source>test/web_virtdevdriver.py</Source>
|
||||
<Source>test/web_benniesrun.py</Source>
|
||||
<Source>test/web_benniesrunxxl.py</Source>
|
||||
</Sources>
|
||||
<Forms/>
|
||||
<Translations/>
|
||||
@@ -349,7 +352,7 @@
|
||||
<string>ExcludeFiles</string>
|
||||
</key>
|
||||
<value>
|
||||
<string>*/test/*</string>
|
||||
<string>*/test/*,*/setup.py</string>
|
||||
</value>
|
||||
</dict>
|
||||
</value>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user