delay Parameter für reg_event eingebaut

reg_event schneller und Prüfung auf doppelte Events verbessert
cycletime kann nicht mehr verändert werden, wenn ein Loop läuft
io.IntIO.get_int und .set_int in get_intvalue und set_intvalue geändert
docstring
This commit is contained in:
2017-08-29 18:22:14 +02:00
parent dcc8c22428
commit 5c7a540d29
11 changed files with 220 additions and 124 deletions

View File

@@ -23,6 +23,9 @@ fuehrt das Modul bei Datenaenderung aus.
Modules</h3> Modules</h3>
<table> <table>
<tr> <tr>
<td><a style="color:#0000FF" href="revpimodio2.__init__.html">revpimodio2</a></td>
<td>Stellt alle Klassen fuer den RevolutionPi zur Verfuegung.</td>
</tr><tr>
<td><a style="color:#0000FF" href="revpimodio2.app.html">app</a></td> <td><a style="color:#0000FF" href="revpimodio2.app.html">app</a></td>
<td>Bildet die App Sektion von piCtory ab.</td> <td>Bildet die App Sektion von piCtory ab.</td>
</tr><tr> </tr><tr>

View File

@@ -25,46 +25,35 @@ Global Attributes</h3>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Classes</h3> Classes</h3>
<table> <table>
<tr> <tr><td>None</td></tr>
<td><a style="color:#0000FF" href="#IOType">IOType</a></td>
<td>IO Typen.</td>
</tr>
</table> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Functions</h3> Functions</h3>
<table> <table>
<tr><td>None</td></tr> <tr>
<td><a style="color:#0000FF" href="#consttostr">consttostr</a></td>
<td>Gibt <class 'str'> fuer Konstanten zurueck.</td>
</tr>
</table> </table>
<hr /><hr /> <hr /><hr />
<a NAME="IOType" ID="IOType"></a> <a NAME="consttostr" ID="consttostr"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">IOType</h2> <h2 style="background-color:#FFFFFF;color:#0000FF">consttostr</h2>
<b>consttostr</b>(<i>value</i>)
<p> <p>
IO Typen. Gibt <class 'str'> fuer Konstanten zurueck.
</p> </p><p>
<h3 style="background-color:#FFFFFF;color:#FF0000"> Diese Funktion ist erforderlich, da enum in Python 3.2 nicht existiert.
Derived from</h3> </p><dl>
object <dt><i>value</i></dt>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <dd>
Class Attributes</h3> Konstantenwert
<table> </dd>
<tr><td>INP</td></tr><tr><td>MEM</td></tr><tr><td>OUT</td></tr> </dl><dl>
</table> <dt>Returns:</dt>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <dd>
Class Methods</h3> <class 'str'> Name der Konstanten
<table> </dd>
<tr><td>None</td></tr> </dl>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div> <div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /> <hr />
</body></html> </body></html>

View File

@@ -411,7 +411,7 @@ Methods</h3>
<td><a style="color:#0000FF" href="#Device.get_inputs">get_inputs</a></td> <td><a style="color:#0000FF" href="#Device.get_inputs">get_inputs</a></td>
<td>Gibt eine Liste aller Inputs zurueck.</td> <td>Gibt eine Liste aller Inputs zurueck.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#Device.get_memmories">get_memmories</a></td> <td><a style="color:#0000FF" href="#Device.get_memories">get_memories</a></td>
<td>Gibt eine Liste aller mems zurueck.</td> <td>Gibt eine Liste aller mems zurueck.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#Device.get_outputs">get_outputs</a></td> <td><a style="color:#0000FF" href="#Device.get_outputs">get_outputs</a></td>
@@ -603,10 +603,10 @@ Gibt eine Liste aller Inputs zurueck.
<dd> <dd>
<class 'list'> Inputs <class 'list'> Inputs
</dd> </dd>
</dl><a NAME="Device.get_memmories" ID="Device.get_memmories"></a> </dl><a NAME="Device.get_memories" ID="Device.get_memories"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
Device.get_memmories</h3> Device.get_memories</h3>
<b>get_memmories</b>(<i></i>) <b>get_memories</b>(<i></i>)
<p> <p>
Gibt eine Liste aller mems zurueck. Gibt eine Liste aller mems zurueck.
</p><dl> </p><dl>

View File

@@ -163,7 +163,7 @@ Methods</h3>
<td>Gibt den Wert des IOs zurueck.</td> <td>Gibt den Wert des IOs zurueck.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#IOBase.reg_event">reg_event</a></td> <td><a style="color:#0000FF" href="#IOBase.reg_event">reg_event</a></td>
<td>Registriert ein Event bei der Eventueberwachung.</td> <td>Registriert fuer IO ein Event bei der Eventueberwachung.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#IOBase.replace_io">replace_io</a></td> <td><a style="color:#0000FF" href="#IOBase.replace_io">replace_io</a></td>
<td>Ersetzt bestehenden IO mit Neuem.</td> <td>Ersetzt bestehenden IO mit Neuem.</td>
@@ -297,13 +297,20 @@ IO-Wert als <class 'bytes'> oder <class 'bool'>
</dl><a NAME="IOBase.reg_event" ID="IOBase.reg_event"></a> </dl><a NAME="IOBase.reg_event" ID="IOBase.reg_event"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
IOBase.reg_event</h3> IOBase.reg_event</h3>
<b>reg_event</b>(<i>func, edge=BOTH, as_thread=False</i>) <b>reg_event</b>(<i>func, delay=0, edge=BOTH, as_thread=False</i>)
<p> <p>
Registriert ein Event bei der Eventueberwachung. Registriert fuer IO ein Event bei der Eventueberwachung.
</p><p>
Die uebergebene Funktion wird ausgefuehrt, wenn sich der IO Wert
aendert. Mit Angabe von optionalen Parametern kann das
Ausloeseverhalten gesteuert werden.
</p><dl> </p><dl>
<dt><i>func</i></dt> <dt><i>func</i></dt>
<dd> <dd>
Funktion die bei Aenderung aufgerufen werden soll Funktion die bei Aenderung aufgerufen werden soll
</dd><dt><i>delay</i></dt>
<dd>
Verzoegerung in ms zum Ausloesen wenn Wert gleich bleibt
</dd><dt><i>edge</i></dt> </dd><dt><i>edge</i></dt>
<dd> <dd>
Ausfuehren bei RISING, FALLING or BOTH Wertaenderung Ausfuehren bei RISING, FALLING or BOTH Wertaenderung
@@ -317,23 +324,27 @@ IOBase.replace_io</h3>
<b>replace_io</b>(<i>name, frm, **kwargs</i>) <b>replace_io</b>(<i>name, frm, **kwargs</i>)
<p> <p>
Ersetzt bestehenden IO mit Neuem. Ersetzt bestehenden IO mit Neuem.
</p><p>
Wenn die kwargs fuer byteorder und defaultvalue nicht angegeben werden,
uebernimmt das System die Daten aus dem ersetzten IO.
</p><dl> </p><dl>
<dt><i>name</i></dt> <dt><i>name</i></dt>
<dd> <dd>
Name des neuen Inputs Name des neuen Inputs
</dd><dt><i>frm</i></dt> </dd><dt><i>frm</i></dt>
<dd> <dd>
struct formatierung (1 Zeichen) struct Formatierung (1 Zeichen)
</dd><dt><i>kwargs</i></dt> </dd><dt><i>kwargs</i></dt>
<dd> <dd>
Weitere Parameter: Weitere Parameter:
- bmk: Bezeichnung fuer Input - bmk: interne Bezeichnung fuer IO
- bit: Registriert IO als <class 'bool'> am angegebenen Bit im Byte - bit: Registriert IO als <class 'bool'> am angegebenen Bit im Byte
- byteorder: Byteorder fuer den Input, Standardwert=little - byteorder: Byteorder fuer den IO, Standardwert=little
- defaultvalue: Standardwert fuer Input, Standard ist 0 - defaultvalue: Standardwert fuer IO
- event: Funktion fuer Eventhandling registrieren - event: Funktion fuer Eventhandling registrieren
- delay: Verzoegerung in ms zum Ausloesen wenn Wert gleich bleibt
- edge: Event ausfuehren bei RISING, FALLING or BOTH Wertaenderung
- as_thread: Fuehrt die event-Funktion als RevPiCallback-Thread aus - as_thread: Fuehrt die event-Funktion als RevPiCallback-Thread aus
- edge: event-Ausfuehren bei RISING, FALLING or BOTH Wertaenderung
</dd> </dd>
</dl><dl> </dl><dl>
<dt><b>See Also:</b></dt> <dt><b>See Also:</b></dt>
@@ -380,7 +391,7 @@ Wartet auf Wertaenderung eines IOs.
HINWEIS: Wenn <class 'ProcimgWriter'> keine neuen Daten liefert, wird HINWEIS: Wenn <class 'ProcimgWriter'> keine neuen Daten liefert, wird
bis in die Ewigkeit gewartet (nicht bei Angabe von "timeout"). bis in die Ewigkeit gewartet (nicht bei Angabe von "timeout").
</p><p> </p><p>
Wenn edge mit RISING oder FALLING angegeben wird muss diese Flanke Wenn edge mit RISING oder FALLING angegeben wird, muss diese Flanke
ausgeloest werden. Sollte der Wert 1 sein beim Eintritt mit Flanke ausgeloest werden. Sollte der Wert 1 sein beim Eintritt mit Flanke
RISING, wird das Warten erst bei Aenderung von 0 auf 1 beendet. RISING, wird das Warten erst bei Aenderung von 0 auf 1 beendet.
</p><p> </p><p>
@@ -393,21 +404,21 @@ Wartet auf Wertaenderung eines IOs.
</p><p> </p><p>
Der Timeoutwert bricht beim Erreichen das Warten sofort mit Der Timeoutwert bricht beim Erreichen das Warten sofort mit
Wert 2 Rueckgabewert ab. (Das Timeout wird ueber die Zykluszeit Wert 2 Rueckgabewert ab. (Das Timeout wird ueber die Zykluszeit
der autorefresh Funktion berechnet, entspricht also nicht exact den der autorefresh Funktion berechnet, entspricht also nicht exakt den
angegeben Millisekunden! Es wird immer nach oben gerundet!) angegeben Millisekunden! Es wird immer nach oben gerundet!)
</p><dl> </p><dl>
<dt><i>edge</i></dt> <dt><i>edge</i></dt>
<dd> <dd>
Flanke RISING, FALLING, BOTH bei der mit True beendet wird Flanke RISING, FALLING, BOTH die eintreten muss
</dd><dt><i>exitevent</i></dt> </dd><dt><i>exitevent</i></dt>
<dd> <dd>
<class 'thrading.Event'> fuer vorzeitiges Beenden <class 'thrading.Event'> fuer vorzeitiges Beenden
</dd><dt><i>okvalue</i></dt> </dd><dt><i>okvalue</i></dt>
<dd> <dd>
IO-Wert, bei dem das Warten sofort mit True beendet wird IO-Wert, bei dem das Warten sofort beendet wird
</dd><dt><i>timeout</i></dt> </dd><dt><i>timeout</i></dt>
<dd> <dd>
Zeit in ms nach der mit False abgebrochen wird Zeit in ms nach der abgebrochen wird
</dd> </dd>
</dl><dl> </dl><dl>
<dt>Returns:</dt> <dt>Returns:</dt>
@@ -650,13 +661,13 @@ Methods</h3>
<td><a style="color:#0000FF" href="#IntIO._set_signed">_set_signed</a></td> <td><a style="color:#0000FF" href="#IntIO._set_signed">_set_signed</a></td>
<td>Left fest, ob der Wert Vorzeichenbehaftet behandelt werden soll.</td> <td>Left fest, ob der Wert Vorzeichenbehaftet behandelt werden soll.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#IntIO.get_int">get_int</a></td>
<td>Gibt IO-Wert zurueck mit Beachtung byteorder/signed.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IntIO.get_intdefaultvalue">get_intdefaultvalue</a></td> <td><a style="color:#0000FF" href="#IntIO.get_intdefaultvalue">get_intdefaultvalue</a></td>
<td>Gibt die Defaultvalue als <class 'int'> zurueck.</td> <td>Gibt die Defaultvalue als <class 'int'> zurueck.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#IntIO.set_int">set_int</a></td> <td><a style="color:#0000FF" href="#IntIO.get_intvalue">get_intvalue</a></td>
<td>Gibt IO-Wert zurueck mit Beachtung byteorder/signed.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IntIO.set_intvalue">set_intvalue</a></td>
<td>Setzt IO mit Beachtung byteorder/signed.</td> <td>Setzt IO mit Beachtung byteorder/signed.</td>
</tr> </tr>
</table> </table>
@@ -709,17 +720,6 @@ Left fest, ob der Wert Vorzeichenbehaftet behandelt werden soll.
<dd> <dd>
True, wenn mit Vorzeichen behandel True, wenn mit Vorzeichen behandel
</dd> </dd>
</dl><a NAME="IntIO.get_int" ID="IntIO.get_int"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IntIO.get_int</h3>
<b>get_int</b>(<i></i>)
<p>
Gibt IO-Wert zurueck mit Beachtung byteorder/signed.
</p><dl>
<dt>Returns:</dt>
<dd>
IO-Wert als <class 'int'>
</dd>
</dl><a NAME="IntIO.get_intdefaultvalue" ID="IntIO.get_intdefaultvalue"></a> </dl><a NAME="IntIO.get_intdefaultvalue" ID="IntIO.get_intdefaultvalue"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
IntIO.get_intdefaultvalue</h3> IntIO.get_intdefaultvalue</h3>
@@ -731,10 +731,21 @@ Gibt die Defaultvalue als <class 'int'> zurueck.
<dd> <dd>
<class 'int'> Defaultvalue <class 'int'> Defaultvalue
</dd> </dd>
</dl><a NAME="IntIO.set_int" ID="IntIO.set_int"></a> </dl><a NAME="IntIO.get_intvalue" ID="IntIO.get_intvalue"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
IntIO.set_int</h3> IntIO.get_intvalue</h3>
<b>set_int</b>(<i>value</i>) <b>get_intvalue</b>(<i></i>)
<p>
Gibt IO-Wert zurueck mit Beachtung byteorder/signed.
</p><dl>
<dt>Returns:</dt>
<dd>
IO-Wert als <class 'int'>
</dd>
</dl><a NAME="IntIO.set_intvalue" ID="IntIO.set_intvalue"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IntIO.set_intvalue</h3>
<b>set_intvalue</b>(<i>value</i>)
<p> <p>
Setzt IO mit Beachtung byteorder/signed. Setzt IO mit Beachtung byteorder/signed.
</p><dl> </p><dl>

View File

@@ -350,7 +350,7 @@ RevPiModIO.cycleloop</h3>
Startet den Cycleloop. Startet den Cycleloop.
</p><p> </p><p>
Der aktuelle Programmthread wird hier bis Aufruf von Der aktuelle Programmthread wird hier bis Aufruf von
RevPiDevicelist.exit() "gefangen". Er fuehrt nach jeder Aktualisierung .exit() "gefangen". Er fuehrt nach jeder Aktualisierung
des Prozessabbilds die uebergebene Funktion "func" aus und arbeitet sie des Prozessabbilds die uebergebene Funktion "func" aus und arbeitet sie
ab. Waehrend der Ausfuehrung der Funktion wird das Prozessabbild nicht ab. Waehrend der Ausfuehrung der Funktion wird das Prozessabbild nicht
weiter aktualisiert. Die Inputs behalten bis zum Ende den aktuellen weiter aktualisiert. Die Inputs behalten bis zum Ende den aktuellen

View File

@@ -5,6 +5,7 @@ revpimodio2.OFF?7
revpimodio2.RED?7 revpimodio2.RED?7
revpimodio2.RISING?7 revpimodio2.RISING?7
revpimodio2.app.App?1(app) revpimodio2.app.App?1(app)
revpimodio2.consttostr?4(value)
revpimodio2.device.Core.A1?7 revpimodio2.device.Core.A1?7
revpimodio2.device.Core.A2?7 revpimodio2.device.Core.A2?7
revpimodio2.device.Core._devconfigure?5() revpimodio2.device.Core._devconfigure?5()
@@ -33,7 +34,7 @@ revpimodio2.device.Device._get_producttype?5()
revpimodio2.device.Device.autorefresh?4(activate=True) revpimodio2.device.Device.autorefresh?4(activate=True)
revpimodio2.device.Device.get_allios?4() revpimodio2.device.Device.get_allios?4()
revpimodio2.device.Device.get_inputs?4() revpimodio2.device.Device.get_inputs?4()
revpimodio2.device.Device.get_memmories?4() revpimodio2.device.Device.get_memories?4()
revpimodio2.device.Device.get_outputs?4() revpimodio2.device.Device.get_outputs?4()
revpimodio2.device.Device.length?7 revpimodio2.device.Device.length?7
revpimodio2.device.Device.name?7 revpimodio2.device.Device.name?7
@@ -84,7 +85,7 @@ revpimodio2.io.IOBase.get_defaultvalue?4()
revpimodio2.io.IOBase.get_value?4() revpimodio2.io.IOBase.get_value?4()
revpimodio2.io.IOBase.length?7 revpimodio2.io.IOBase.length?7
revpimodio2.io.IOBase.name?7 revpimodio2.io.IOBase.name?7
revpimodio2.io.IOBase.reg_event?4(func, edge=BOTH, as_thread=False) revpimodio2.io.IOBase.reg_event?4(func, delay=0, edge=BOTH, as_thread=False)
revpimodio2.io.IOBase.replace_io?4(name, frm, **kwargs) revpimodio2.io.IOBase.replace_io?4(name, frm, **kwargs)
revpimodio2.io.IOBase.set_value?4(value) revpimodio2.io.IOBase.set_value?4(value)
revpimodio2.io.IOBase.type?7 revpimodio2.io.IOBase.type?7
@@ -99,9 +100,9 @@ revpimodio2.io.IntIO._set_byteorder?5(value)
revpimodio2.io.IntIO._set_signed?5(value) revpimodio2.io.IntIO._set_signed?5(value)
revpimodio2.io.IntIO.byteorder?7 revpimodio2.io.IntIO.byteorder?7
revpimodio2.io.IntIO.defaultvalue?7 revpimodio2.io.IntIO.defaultvalue?7
revpimodio2.io.IntIO.get_int?4()
revpimodio2.io.IntIO.get_intdefaultvalue?4() revpimodio2.io.IntIO.get_intdefaultvalue?4()
revpimodio2.io.IntIO.set_int?4(value) revpimodio2.io.IntIO.get_intvalue?4()
revpimodio2.io.IntIO.set_intvalue?4(value)
revpimodio2.io.IntIO.signed?7 revpimodio2.io.IntIO.signed?7
revpimodio2.io.IntIO.value?7 revpimodio2.io.IntIO.value?7
revpimodio2.io.StructIO._get_frm?5() revpimodio2.io.StructIO._get_frm?5()

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-5.1.dtd"> <!DOCTYPE Project SYSTEM "Project-5.1.dtd">
<!-- eric project file for project revpimodio2 --> <!-- eric project file for project revpimodio2 -->
<!-- Saved: 2017-08-26, 09:26:35 --> <!-- Saved: 2017-08-29, 18:21:17 -->
<!-- Copyright (C) 2017 Sven Sager, akira@narux.de --> <!-- Copyright (C) 2017 Sven Sager, akira@narux.de -->
<Project version="5.1"> <Project version="5.1">
<Language>en_US</Language> <Language>en_US</Language>
@@ -26,7 +26,6 @@
<Source>test/test_dio_mainloop.py</Source> <Source>test/test_dio_mainloop.py</Source>
<Source>test/test_dio_cycleloop.py</Source> <Source>test/test_dio_cycleloop.py</Source>
<Source>test/test_net_leistung.py</Source> <Source>test/test_net_leistung.py</Source>
<Source>revpimodio2/net.py</Source>
<Source>test/web_cycleloop.py</Source> <Source>test/web_cycleloop.py</Source>
<Source>test/web_mainloop.py</Source> <Source>test/web_mainloop.py</Source>
</Sources> </Sources>
@@ -338,4 +337,23 @@
</dict> </dict>
</CheckersParams> </CheckersParams>
</Checkers> </Checkers>
<OtherTools>
<OtherToolsParams>
<dict>
<key>
<string>CodeMetrics</string>
</key>
<value>
<dict>
<key>
<string>ExcludeFiles</string>
</key>
<value>
<string>*/test/*</string>
</value>
</dict>
</value>
</dict>
</OtherToolsParams>
</OtherTools>
</Project> </Project>

View File

@@ -35,3 +35,28 @@ FALLING = 32
BOTH = 33 BOTH = 33
warnings.simplefilter(action="always") warnings.simplefilter(action="always")
def consttostr(value):
"""Gibt <class 'str'> fuer Konstanten zurueck.
Diese Funktion ist erforderlich, da enum in Python 3.2 nicht existiert.
@param value Konstantenwert
@return <class 'str'> Name der Konstanten
"""
if value == 0:
return "OFF"
elif value == 1:
return "GREEN"
elif value == 2:
return "RED"
elif value == 31:
return "RISING"
elif value == 32:
return "FALLING"
elif value == 33:
return "BOTH"
else:
return ""

View File

@@ -317,7 +317,7 @@ class Device(object):
lst_return += lst_io lst_return += lst_io
return lst_return return lst_return
def get_memmories(self): def get_memories(self):
"""Gibt eine Liste aller mems zurueck. """Gibt eine Liste aller mems zurueck.
@return <class 'list'> Mems""" @return <class 'list'> Mems"""
lst_return = [] lst_return = []

View File

@@ -8,7 +8,7 @@
"""RevPiModIO Modul fuer die Verwaltung der IOs.""" """RevPiModIO Modul fuer die Verwaltung der IOs."""
import struct import struct
from threading import Event from threading import Event
from .__init__ import RISING, FALLING, BOTH from .__init__ import RISING, FALLING, BOTH, consttostr
class Type(object): class Type(object):
@@ -356,32 +356,44 @@ class IOBase(object):
else: else:
return bytes(self._parentdevice._ba_devdata[self._slc_address]) return bytes(self._parentdevice._ba_devdata[self._slc_address])
def reg_event(self, func, edge=BOTH, as_thread=False): def reg_event(self, func, delay=0, edge=BOTH, as_thread=False):
"""Registriert ein Event bei der Eventueberwachung. """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.
@param func Funktion die bei Aenderung aufgerufen werden soll @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 @param edge Ausfuehren bei RISING, FALLING or BOTH Wertaenderung
@param as_thread Bei True, Funktion als EventCallback-Thread ausfuehren @param as_thread Bei True, Funktion als EventCallback-Thread ausfuehren
""" """
# Prüfen ob Funktion callable ist # Prüfen ob Funktion callable ist
if not callable(func): if not callable(func):
raise RuntimeError( raise AttributeError(
"registered function '{}' ist not callable".format(func) "registered function '{}' is not callable".format(func)
)
if type(delay) != int or delay < 0:
raise AttributeError(
"parameter 'delay' must be greater or equal 0"
) )
if edge != BOTH and self._bitaddress < 0: if edge != BOTH and self._bitaddress < 0:
raise AttributeError( raise AttributeError(
"parameter 'edge' can be used with bit io objects only" "parameter 'edge' can be used with bit io objects only"
) )
if self not in self._parentdevice._dict_events: if self not in self._parentdevice._dict_events:
self._parentdevice._dict_events[self] = [(func, edge, as_thread)] self._parentdevice._dict_events[self] = \
[(func, edge, as_thread, delay)]
else: else:
# Prüfen ob Funktion schon registriert ist # Prüfen ob Funktion schon registriert ist
for regfunc in self._parentdevice._dict_events[self]: for regfunc in self._parentdevice._dict_events[self]:
if regfunc[0] != func:
# Nächsten Eintrag testen
continue
if regfunc[0] == func and edge == BOTH: if edge == BOTH or regfunc[1] == BOTH:
if self._bitaddress < 0: if self._bitaddress < 0:
raise AttributeError( raise AttributeError(
"io '{}' with function '{}' already in list." "io '{}' with function '{}' already in list."
@@ -389,35 +401,42 @@ class IOBase(object):
) )
else: else:
raise AttributeError( raise AttributeError(
"io '{}' with function '{}' already in list. " "io '{}' with function '{}' already in list with "
"edge 'BOTH' not allowed anymore".format( "edge '{}' - edge '{}' not allowed anymore".format(
self._name, func self._name, func,
consttostr(regfunc[1]), consttostr(edge)
) )
) )
elif regfunc[0] == func and regfunc[1] == edge: elif regfunc[1] == edge:
raise AttributeError( raise AttributeError(
"io '{}' with function '{}' for given edge " "io '{}' with function '{}' for given edge '{}' "
"already in list".format(self._name, func) "already in list".format(
self._name, func, consttostr(edge)
) )
else: )
# Eventfunktion einfügen
self._parentdevice._dict_events[self].append( self._parentdevice._dict_events[self].append(
(func, edge, as_thread) (func, edge, as_thread, delay)
) )
break
def replace_io(self, name, frm, **kwargs): def replace_io(self, name, frm, **kwargs):
"""Ersetzt bestehenden IO mit Neuem. """Ersetzt bestehenden IO mit Neuem.
Wenn die kwargs fuer byteorder und defaultvalue nicht angegeben werden,
uebernimmt das System die Daten aus dem ersetzten IO.
@param name Name des neuen Inputs @param name Name des neuen Inputs
@param frm struct formatierung (1 Zeichen) @param frm struct Formatierung (1 Zeichen)
@param kwargs Weitere Parameter: @param kwargs Weitere Parameter:
- bmk: Bezeichnung fuer Input - bmk: interne Bezeichnung fuer IO
- bit: Registriert IO als <class 'bool'> am angegebenen Bit im Byte - bit: Registriert IO als <class 'bool'> am angegebenen Bit im Byte
- byteorder: Byteorder fuer den Input, Standardwert=little - byteorder: Byteorder fuer den IO, Standardwert=little
- defaultvalue: Standardwert fuer Input, Standard ist 0 - defaultvalue: Standardwert fuer IO
- event: Funktion fuer Eventhandling registrieren - event: Funktion fuer Eventhandling registrieren
- delay: Verzoegerung in ms zum Ausloesen wenn Wert gleich bleibt
- edge: Event ausfuehren bei RISING, FALLING or BOTH Wertaenderung
- as_thread: Fuehrt die event-Funktion als RevPiCallback-Thread aus - as_thread: Fuehrt die event-Funktion als RevPiCallback-Thread aus
- edge: event-Ausfuehren bei RISING, FALLING or BOTH Wertaenderung
@see <a target="_blank" @see <a target="_blank"
href="https://docs.python.org/3/library/struct.html#format-characters" href="https://docs.python.org/3/library/struct.html#format-characters"
>Python3 struct</a> >Python3 struct</a>
@@ -449,8 +468,9 @@ class IOBase(object):
if reg_event is not None: if reg_event is not None:
io_new.reg_event( io_new.reg_event(
reg_event, reg_event,
as_thread=kwargs.get("as_thread", False), kwargs.get("delay", 0),
edge=kwargs.get("edge", BOTH) kwargs.get("edge", BOTH),
kwargs.get("as_thread", False)
) )
def set_value(self, value): def set_value(self, value):
@@ -548,7 +568,7 @@ class IOBase(object):
HINWEIS: Wenn <class 'ProcimgWriter'> keine neuen Daten liefert, wird HINWEIS: Wenn <class 'ProcimgWriter'> keine neuen Daten liefert, wird
bis in die Ewigkeit gewartet (nicht bei Angabe von "timeout"). bis in die Ewigkeit gewartet (nicht bei Angabe von "timeout").
Wenn edge mit RISING oder FALLING angegeben wird muss diese Flanke Wenn edge mit RISING oder FALLING angegeben wird, muss diese Flanke
ausgeloest werden. Sollte der Wert 1 sein beim Eintritt mit Flanke ausgeloest werden. Sollte der Wert 1 sein beim Eintritt mit Flanke
RISING, wird das Warten erst bei Aenderung von 0 auf 1 beendet. RISING, wird das Warten erst bei Aenderung von 0 auf 1 beendet.
@@ -561,13 +581,13 @@ class IOBase(object):
Der Timeoutwert bricht beim Erreichen das Warten sofort mit Der Timeoutwert bricht beim Erreichen das Warten sofort mit
Wert 2 Rueckgabewert ab. (Das Timeout wird ueber die Zykluszeit Wert 2 Rueckgabewert ab. (Das Timeout wird ueber die Zykluszeit
der autorefresh Funktion berechnet, entspricht also nicht exact den der autorefresh Funktion berechnet, entspricht also nicht exakt den
angegeben Millisekunden! Es wird immer nach oben gerundet!) angegeben Millisekunden! Es wird immer nach oben gerundet!)
@param edge Flanke RISING, FALLING, BOTH bei der mit True beendet wird @param edge Flanke RISING, FALLING, BOTH die eintreten muss
@param exitevent <class 'thrading.Event'> fuer vorzeitiges Beenden @param exitevent <class 'thrading.Event'> fuer vorzeitiges Beenden
@param okvalue IO-Wert, bei dem das Warten sofort mit True beendet wird @param okvalue IO-Wert, bei dem das Warten sofort beendet wird
@param timeout Zeit in ms nach der mit False abgebrochen wird @param timeout Zeit in ms nach der abgebrochen wird
@return <class 'int'> erfolgreich Werte <= 0 @return <class 'int'> erfolgreich Werte <= 0
- Erfolgreich gewartet - Erfolgreich gewartet
Wert 0: IO hat den Wert gewechselt Wert 0: IO hat den Wert gewechselt
@@ -695,7 +715,7 @@ class IntIO(IOBase):
self._defaultvalue, byteorder=self._byteorder, signed=self._signed self._defaultvalue, byteorder=self._byteorder, signed=self._signed
) )
def get_int(self): def get_intvalue(self):
"""Gibt IO-Wert zurueck mit Beachtung byteorder/signed. """Gibt IO-Wert zurueck mit Beachtung byteorder/signed.
@return IO-Wert als <class 'int'>""" @return IO-Wert als <class 'int'>"""
return int.from_bytes( return int.from_bytes(
@@ -704,7 +724,7 @@ class IntIO(IOBase):
signed=self._signed signed=self._signed
) )
def set_int(self, value): def set_intvalue(self, value):
"""Setzt IO mit Beachtung byteorder/signed. """Setzt IO mit Beachtung byteorder/signed.
@param value <class 'int'> Wert""" @param value <class 'int'> Wert"""
if type(value) == int: if type(value) == int:
@@ -722,7 +742,7 @@ class IntIO(IOBase):
byteorder = property(IOBase._get_byteorder, _set_byteorder) byteorder = property(IOBase._get_byteorder, _set_byteorder)
defaultvalue = property(get_intdefaultvalue) defaultvalue = property(get_intdefaultvalue)
signed = property(_get_signed, _set_signed) signed = property(_get_signed, _set_signed)
value = property(get_int, set_int) value = property(get_intvalue, set_intvalue)
class StructIO(IOBase): class StructIO(IOBase):

View File

@@ -281,6 +281,12 @@ class RevPiModIO(object):
def _set_cycletime(self, milliseconds): def _set_cycletime(self, milliseconds):
"""Setzt Aktualisierungsrate der Prozessabbild-Synchronisierung. """Setzt Aktualisierungsrate der Prozessabbild-Synchronisierung.
@param milliseconds <class 'int'> in Millisekunden""" @param milliseconds <class 'int'> in Millisekunden"""
if self._looprunning:
raise RuntimeError(
"can not change cycletime when cycleloop or mainloop are "
"running"
)
else:
self._imgwriter.refresh = milliseconds self._imgwriter.refresh = milliseconds
def _set_maxioerrors(self, value): def _set_maxioerrors(self, value):
@@ -311,7 +317,7 @@ class RevPiModIO(object):
"""Startet den Cycleloop. """Startet den Cycleloop.
Der aktuelle Programmthread wird hier bis Aufruf von Der aktuelle Programmthread wird hier bis Aufruf von
RevPiDevicelist.exit() "gefangen". Er fuehrt nach jeder Aktualisierung .exit() "gefangen". Er fuehrt nach jeder Aktualisierung
des Prozessabbilds die uebergebene Funktion "func" aus und arbeitet sie des Prozessabbilds die uebergebene Funktion "func" aus und arbeitet sie
ab. Waehrend der Ausfuehrung der Funktion wird das Prozessabbild nicht ab. Waehrend der Ausfuehrung der Funktion wird das Prozessabbild nicht
weiter aktualisiert. Die Inputs behalten bis zum Ende den aktuellen weiter aktualisiert. Die Inputs behalten bis zum Ende den aktuellen
@@ -518,6 +524,7 @@ class RevPiModIO(object):
dev._filelock.release() dev._filelock.release()
lst_fire = [] lst_fire = []
dict_delay = {}
while not self._exit.is_set(): while not self._exit.is_set():
# Auf neue Daten warten und nur ausführen wenn set() # Auf neue Daten warten und nur ausführen wenn set()
@@ -560,15 +567,28 @@ class RevPiModIO(object):
if regfunc[1] == BOTH \ if regfunc[1] == BOTH \
or regfunc[1] == RISING and boolor \ or regfunc[1] == RISING and boolor \
or regfunc[1] == FALLING and not boolor: or regfunc[1] == FALLING and not boolor:
lst_fire.append( if regfunc[3] == 0:
(regfunc, io_event._name, io_event.value) lst_fire.append((
regfunc, io_event._name, io_event.value
))
else:
# Verzögertes Event in dict einfügen
dict_delay[(
regfunc, io_event._name, io_event.value
)] = int(
regfunc[3] / self._imgwriter.refresh
) )
else: else:
for regfunc in dev._dict_events[io_event]: for regfunc in dev._dict_events[io_event]:
if regfunc[3] == 0:
lst_fire.append( lst_fire.append(
(regfunc, io_event._name, io_event.value) (regfunc, io_event._name, io_event.value)
) )
else:
# Verzögertes Event in dict einfügen
dict_delay[(
regfunc, io_event._name, io_event.value
)] = int(regfunc[3] / self._imgwriter.refresh)
# Nach Verarbeitung aller IOs die Bytes kopieren # Nach Verarbeitung aller IOs die Bytes kopieren
dev._filelock.acquire() dev._filelock.acquire()
@@ -579,20 +599,29 @@ class RevPiModIO(object):
if not freeze: if not freeze:
self._imgwriter.lck_refresh.release() self._imgwriter.lck_refresh.release()
# Verzögerte Events prüfen
for tup_fire in list(dict_delay.keys()):
if getattr(self.io, tup_fire[1]).value != tup_fire[2]:
del dict_delay[tup_fire]
else:
dict_delay[tup_fire] -= 1
if dict_delay[tup_fire] <= 0:
# Verzögertes Event übernehmen und löschen
lst_fire.append(tup_fire)
del dict_delay[tup_fire]
# Erst nach Datenübernahme alle Events feuern # Erst nach Datenübernahme alle Events feuern
while len(lst_fire) > 0: while len(lst_fire) > 0:
# EventTuple ((func, edge, as_thread, delay), ioname, iovalue)
tup_fire = lst_fire.pop() tup_fire = lst_fire.pop()
event_func = tup_fire[0][0]
passname = tup_fire[1]
passvalue = tup_fire[2]
if tup_fire[0][2]: if tup_fire[0][2]:
th = helpermodule.EventCallback( th = helpermodule.EventCallback(
event_func, passname, passvalue tup_fire[0][0], tup_fire[1], tup_fire[2]
) )
th.start() th.start()
else: else:
# Direct callen da Prüfung in RevPiDevice.reg_event ist # Direct callen da Prüfung in io.IOBase.reg_event ist
event_func(passname, passvalue) tup_fire[0][0](tup_fire[1], tup_fire[2])
# Refreshsperre aufheben wenn freeze # Refreshsperre aufheben wenn freeze
if freeze: if freeze: