mirror of
https://github.com/naruxde/revpimodio2.git
synced 2025-11-08 13:53:53 +01:00
Add .last cycle flag to Cycletools, better sync of loops on program end.
The .last cycle flag will be True on the last cycle, if the program received an exit event or after calling .exit(). close #4
This commit is contained in:
@@ -86,7 +86,7 @@ class Cycletools:
|
||||
"""
|
||||
|
||||
__slots__ = "__cycle", "__cycletime", "__ucycle", \
|
||||
"__dict_ton", "__dict_tof", "__dict_tp", "first", \
|
||||
"__dict_ton", "__dict_tof", "__dict_tp", "first", "last", \
|
||||
"flag1c", "flag5c", "flag10c", "flag15c", "flag20c", \
|
||||
"flank5c", "flank10c", "flank15c", "flank20c", "var"
|
||||
|
||||
@@ -106,6 +106,7 @@ class Cycletools:
|
||||
self.flag10c = False
|
||||
self.flag15c = False
|
||||
self.flag20c = False
|
||||
self.last = False
|
||||
|
||||
# Flankenmerker
|
||||
self.flank5c = True
|
||||
|
||||
@@ -23,15 +23,15 @@ class RevPiModIO(object):
|
||||
"""
|
||||
Klasse fuer die Verwaltung der piCtory Konfiguration.
|
||||
|
||||
Diese Klasse uebernimmt die gesamte Konfiguration aus piCtory und bilded
|
||||
die Devices und IOs ab. Sie uebernimmt die exklusive Verwaltung des
|
||||
Diese Klasse uebernimmt die gesamte Konfiguration aus piCtory und
|
||||
laedt die Devices und IOs. Sie uebernimmt die exklusive Verwaltung des
|
||||
Prozessabbilds und stellt sicher, dass die Daten synchron sind.
|
||||
Sollten nur einzelne Devices gesteuert werden, verwendet man
|
||||
RevPiModIOSelected() und uebergibt bei Instantiierung eine Liste mit
|
||||
Device Positionen oder Device Namen.
|
||||
"""
|
||||
|
||||
__slots__ = "__cleanupfunc", "_autorefresh", "_buffedwrite", \
|
||||
__slots__ = "__cleanupfunc", "_autorefresh", "_buffedwrite", "_exit_level", \
|
||||
"_configrsc", "_direct_output", "_exit", "_imgwriter", "_ioerror", \
|
||||
"_length", "_looprunning", "_lst_devselect", "_lst_refresh", \
|
||||
"_maxioerrors", "_myfh", "_myfh_lck", "_monitoring", "_procimg", \
|
||||
@@ -82,6 +82,7 @@ class RevPiModIO(object):
|
||||
self._buffedwrite = False
|
||||
self._debug = 1
|
||||
self._exit = Event()
|
||||
self._exit_level = 0
|
||||
self._imgwriter = None
|
||||
self._ioerror = 0
|
||||
self._length = 0
|
||||
@@ -143,6 +144,32 @@ class RevPiModIO(object):
|
||||
if not self._monitoring:
|
||||
self.writeprocimg()
|
||||
|
||||
def __exit_jobs(self):
|
||||
"""Shutdown sub systems."""
|
||||
if self._exit_level & 1:
|
||||
# Nach Ausführung kann System weiter verwendet werden
|
||||
self._exit_level ^= 1
|
||||
|
||||
# ProcimgWriter beenden und darauf warten
|
||||
if self._imgwriter is not None and self._imgwriter.is_alive():
|
||||
self._imgwriter.stop()
|
||||
self._imgwriter.join(2.5)
|
||||
|
||||
# Alle Devices aus Autorefresh entfernen
|
||||
while len(self._lst_refresh) > 0:
|
||||
dev = self._lst_refresh.pop()
|
||||
dev._selfupdate = False
|
||||
if not self._monitoring:
|
||||
self.writeprocimg(dev)
|
||||
|
||||
if self._exit_level & 2:
|
||||
self._myfh.close()
|
||||
self.app = None
|
||||
self.core = None
|
||||
self.device = None
|
||||
self.io = None
|
||||
self.summary = None
|
||||
|
||||
def _configure(self, jconfigrsc: dict) -> None:
|
||||
"""
|
||||
Verarbeitet die piCtory Konfigurationsdatei.
|
||||
@@ -626,13 +653,8 @@ class RevPiModIO(object):
|
||||
|
||||
def cleanup(self) -> None:
|
||||
"""Beendet autorefresh und alle Threads."""
|
||||
self._exit_level |= 2
|
||||
self.exit(full=True)
|
||||
self._myfh.close()
|
||||
self.app = None
|
||||
self.core = None
|
||||
self.device = None
|
||||
self.io = None
|
||||
self.summary = None
|
||||
|
||||
def cycleloop(self, func, cycletime=50):
|
||||
"""
|
||||
@@ -697,16 +719,20 @@ class RevPiModIO(object):
|
||||
self._exit.clear()
|
||||
self._looprunning = True
|
||||
cycleinfo = helpermodule.Cycletools(self._imgwriter.refresh)
|
||||
e = None
|
||||
ec = None
|
||||
try:
|
||||
while ec is None and not self._exit.is_set():
|
||||
while ec is None and not cycleinfo.last:
|
||||
# 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():
|
||||
if not self._imgwriter.is_alive():
|
||||
self.exit(full=False)
|
||||
self._looprunning = False
|
||||
raise RuntimeError("autorefresh thread not running")
|
||||
e = RuntimeError("autorefresh thread not running")
|
||||
break
|
||||
|
||||
# Abfragen um loop bei exit zu verlassen
|
||||
cycleinfo.last = self._exit.is_set()
|
||||
|
||||
continue
|
||||
self._imgwriter.newdata.clear()
|
||||
|
||||
@@ -714,24 +740,31 @@ class RevPiModIO(object):
|
||||
self._imgwriter.lck_refresh.acquire()
|
||||
|
||||
# Funktion aufrufen und auswerten
|
||||
cycleinfo.last = self._exit.is_set()
|
||||
ec = func(cycleinfo)
|
||||
cycleinfo._docycle()
|
||||
|
||||
# autorefresh freigeben
|
||||
self._imgwriter.lck_refresh.release()
|
||||
except Exception as e:
|
||||
except Exception as ex:
|
||||
if self._imgwriter.lck_refresh.locked():
|
||||
self._imgwriter.lck_refresh.release()
|
||||
self.exit(full=False)
|
||||
e = ex
|
||||
finally:
|
||||
# Cycleloop beenden
|
||||
self._looprunning = False
|
||||
raise e
|
||||
|
||||
# Cycleloop beenden
|
||||
self._looprunning = False
|
||||
|
||||
# Alte autorefresh Zeit setzen
|
||||
self._imgwriter.refresh = old_cycletime
|
||||
|
||||
# Exitstrategie ausführen
|
||||
self.__exit_jobs()
|
||||
|
||||
# Auf Fehler prüfen die im loop geworfen wurden
|
||||
if e is not None:
|
||||
raise e
|
||||
|
||||
return ec
|
||||
|
||||
def exit(self, full=True) -> None:
|
||||
@@ -747,6 +780,11 @@ class RevPiModIO(object):
|
||||
|
||||
:param full: Entfernt auch alle Devices aus autorefresh
|
||||
"""
|
||||
self._exit_level |= 1 if full else 0
|
||||
|
||||
# Echten Loopwert vor Events speichern
|
||||
full = full and not self._looprunning
|
||||
|
||||
# Benutzerevent
|
||||
self.exitsignal.set()
|
||||
|
||||
@@ -754,21 +792,7 @@ class RevPiModIO(object):
|
||||
self._waitexit.set()
|
||||
|
||||
if full:
|
||||
# ProcimgWriter beenden und darauf warten
|
||||
if self._imgwriter is not None and self._imgwriter.is_alive():
|
||||
self._imgwriter.stop()
|
||||
self._imgwriter.join(self._imgwriter._refresh)
|
||||
|
||||
# Mainloop beenden und darauf 1 Sekunde warten
|
||||
if self._th_mainloop is not None and self._th_mainloop.is_alive():
|
||||
self._th_mainloop.join(1)
|
||||
|
||||
# Alle Devices aus Autorefresh entfernen
|
||||
while len(self._lst_refresh) > 0:
|
||||
dev = self._lst_refresh.pop()
|
||||
dev._selfupdate = False
|
||||
if not self._monitoring:
|
||||
self.writeprocimg(dev)
|
||||
self.__exit_jobs()
|
||||
|
||||
def export_replaced_ios(self, filename="replace_ios.conf") -> None:
|
||||
"""
|
||||
@@ -990,7 +1014,10 @@ class RevPiModIO(object):
|
||||
self._looprunning = False
|
||||
self._th_mainloop = None
|
||||
|
||||
# Fehler prüfen
|
||||
# Exitstrategie ausführen
|
||||
self.__exit_jobs()
|
||||
|
||||
# Auf Fehler prüfen die im loop geworfen wurden
|
||||
if e is not None:
|
||||
raise e
|
||||
|
||||
@@ -1190,7 +1217,7 @@ class RevPiModIOSelected(RevPiModIO):
|
||||
Klasse fuer die Verwaltung einzelner Devices aus piCtory.
|
||||
|
||||
Diese Klasse uebernimmt nur angegebene Devices der piCtory Konfiguration
|
||||
und bilded sie inkl. IOs ab. Sie uebernimmt die exklusive Verwaltung des
|
||||
und laedt sie inkl. IOs. Sie uebernimmt die exklusive Verwaltung des
|
||||
Adressbereichs im Prozessabbild an dem sich die angegebenen Devices
|
||||
befinden und stellt sicher, dass die Daten synchron sind.
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user