Fehlerverwaltung bei cycleloop und mainloop

Device.__contains__ Rückgabe bei ersetzen IOs nun False
RevPiModIO.__del__ löst klarere Fehler bei falscher Instantiierung aus
This commit is contained in:
2017-11-08 17:46:50 +01:00
parent 709c0f95be
commit 5887a22ba0
8 changed files with 67 additions and 47 deletions

View File

@@ -480,7 +480,7 @@ IO-Name <class 'str'> / IO-Bytenummer <class 'int'>
</dl><dl>
<dt>Returns:</dt>
<dd>
True, wenn device vorhanden
True, wenn IO auf Device vorhanden
</dd>
</dl><a NAME="Device.__getioiter" ID="Device.__getioiter"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">

View File

@@ -541,7 +541,7 @@ Prueft ob IO existiert.
</p><dl>
<dt><i>key</i></dt>
<dd>
IO-Name <class 'str'> oder Byte <class 'int'>
IO-Name <class 'str'> oder Bytenummer <class 'int'>
</dd>
</dl><dl>
<dt>Returns:</dt>

View File

@@ -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-11-02, 13:54:10 -->
<!-- Saved: 2017-11-06, 13:58:17 -->
<!-- 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.6</Version>
<Version>2.0.7</Version>
<Author>Sven Sager</Author>
<Email>akira@narux.de</Email>
<Eol index="1"/>
@@ -31,7 +31,8 @@
<Source>test/web_virtdevdriver.py</Source>
<Source>test/web_benniesrun.py</Source>
<Source>test/web_benniesrunxxl.py</Source>
<Source>test_unit.py</Source>
<Source>test/test_unit.py</Source>
<Source>test/test_unitnet.py</Source>
</Sources>
<Forms/>
<Translations/>
@@ -43,7 +44,7 @@
<Other>MANIFEST.in</Other>
<Other>eric-revpimodio2.api</Other>
</Others>
<MainScript>test_unit.py</MainScript>
<MainScript>test/test_unit.py</MainScript>
<Vcs>
<VcsType>Mercurial</VcsType>
<VcsOptions>
@@ -182,7 +183,6 @@
<value>
<list>
<string>setup.py</string>
<string>test_unit.py</string>
</list>
</value>
<key>
@@ -229,7 +229,6 @@
<value>
<list>
<string>setup.py</string>
<string>test_unit.py</string>
</list>
</value>
<key>
@@ -281,7 +280,7 @@
<string>ExcludeFiles</string>
</key>
<value>
<string>*/test_unit.py</string>
<string>./test/*</string>
</value>
<key>
<string>ExcludeMessages</string>

View File

@@ -24,7 +24,7 @@ __all__ = [
__author__ = "Sven Sager <akira@revpimodio.org>"
__name__ = "revpimodio2"
__package__ = "revpimodio2"
__version__ = "2.0.6"
__version__ = "2.0.7"
# Global package values
OFF = 0

View File

@@ -171,18 +171,20 @@ class Device(object):
def __contains__(self, key):
"""Prueft ob IO auf diesem Device liegt.
@param key IO-Name <class 'str'> / IO-Bytenummer <class 'int'>
@return True, wenn device vorhanden"""
if type(key) == str:
return key in self._modio.io \
and getattr(self._modio.io, key)._parentdevice == self
elif type(key) == int:
@return True, wenn IO auf Device vorhanden"""
if issubclass(type(key), IOBase):
# Umwandlung für key
key = key._name
if type(key) == int:
if key in self._modio.io:
for io in self._modio.io[key]:
if io is not None and io._parentdevice == self:
return True
return False
else:
return key._parentdevice == self
return key in self._modio.io \
and getattr(self._modio.io, key)._parentdevice == self
def __int__(self):
"""Gibt die Positon im RevPi Bus zurueck.

View File

@@ -22,11 +22,10 @@ class IOList(object):
def __contains__(self, key):
"""Prueft ob IO existiert.
@param key IO-Name <class 'str'> oder Byte <class 'int'>
@param key IO-Name <class 'str'> oder Bytenummer <class 'int'>
@return True, wenn IO vorhanden / Byte belegt"""
if type(key) == int:
return key in self.__dict_iobyte \
and len(self.__dict_iobyte[key]) > 0
return len(self.__dict_iobyte.get(key, [])) > 0
else:
return hasattr(self, key) and type(getattr(self, key)) != DeadIO

View File

@@ -86,9 +86,10 @@ class RevPiModIO(object):
def __del__(self):
"""Zerstoert alle Klassen um aufzuraeumen."""
self.exit(full=True)
if self._myfh is not None:
self._myfh.close()
if hasattr(self, "_exit"):
self.exit(full=True)
if self._myfh is not None:
self._myfh.close()
def __evt_exit(self, signum, sigframe):
"""Eventhandler fuer Programmende.
@@ -368,23 +369,33 @@ class RevPiModIO(object):
self._looprunning = True
cycleinfo = helpermodule.Cycletools(self._imgwriter.refresh)
ec = None
while ec is None and 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():
raise RuntimeError("autorefresh thread not running")
continue
self._imgwriter.newdata.clear()
try:
while ec is None and 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():
self.exit(full=False)
self._looprunning = False
raise RuntimeError("autorefresh thread not running")
continue
self._imgwriter.newdata.clear()
# Vor Aufruf der Funktion autorefresh sperren
self._imgwriter.lck_refresh.acquire()
# Vor Aufruf der Funktion autorefresh sperren
self._imgwriter.lck_refresh.acquire()
# Funktion aufrufen und auswerten
ec = func(cycleinfo)
cycleinfo._docycle()
# Funktion aufrufen und auswerten
ec = func(cycleinfo)
cycleinfo._docycle()
# autorefresh freigeben
self._imgwriter.lck_refresh.release()
# autorefresh freigeben
self._imgwriter.lck_refresh.release()
except Exception as e:
if self._imgwriter.lck_refresh.locked():
self._imgwriter.lck_refresh.release()
self.exit(full=False)
self._looprunning = False
raise e
# Cycleloop beenden
self._looprunning = False
@@ -533,6 +544,8 @@ class RevPiModIO(object):
# 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():
self.exit(full=False)
self._looprunning = False
raise RuntimeError("autorefresh thread not running")
continue
@@ -624,16 +637,23 @@ class RevPiModIO(object):
del dict_delay[tup_fire]
# Erst nach Datenübernahme alle Events feuern
while len(lst_fire) > 0:
tup_fire = lst_fire.pop()
if tup_fire[0][2]:
th = helpermodule.EventCallback(
tup_fire[0][0], tup_fire[1], tup_fire[2]
)
th.start()
else:
# Direct callen da Prüfung in io.IOBase.reg_event ist
tup_fire[0][0](tup_fire[1], tup_fire[2])
try:
while len(lst_fire) > 0:
tup_fire = lst_fire.pop()
if tup_fire[0][2]:
th = helpermodule.EventCallback(
tup_fire[0][0], tup_fire[1], tup_fire[2]
)
th.start()
else:
# Direct callen da Prüfung in io.IOBase.reg_event ist
tup_fire[0][0](tup_fire[1], tup_fire[2])
except Exception as e:
if self._imgwriter.lck_refresh.locked():
self._imgwriter.lck_refresh.release()
self.exit(full=False)
self._looprunning = False
raise e
# Refreshsperre aufheben wenn freeze
if freeze:

View File

@@ -16,7 +16,7 @@ setup(
license="LGPLv3",
name="revpimodio2",
version="2.0.6",
version="2.0.7",
packages=["revpimodio2"],
python_requires="~=3.2",