diff --git a/doc/plcsystem.html b/doc/plcsystem.html
index 8a5219e..42c4fc0 100644
--- a/doc/plcsystem.html
+++ b/doc/plcsystem.html
@@ -46,7 +46,7 @@ Thread
Class Attributes
Class Methods
@@ -60,6 +60,12 @@ Methods
RevPiPlc |
Instantiiert RevPiPlc-Klasse. |
+| __get_autoreloaddelay |
+Getter fuer autoreloaddelay. |
+
+| __set_autoreloaddelay |
+Setter fuer autoreloaddelay. |
+
| _configureplw |
Konfiguriert den PipeLogwriter fuer Ausgaben der PLCAPP. |
@@ -90,6 +96,23 @@ RevPiPlc (Constructor)
RevPiPlc(program, arguments, pversion)
Instantiiert RevPiPlc-Klasse.
+
+
+RevPiPlc.__get_autoreloaddelay
+__get_autoreloaddelay()
+
+Getter fuer autoreloaddelay.
+
+- Returns:
+-
+Delayzeit in Sekunden
+
+
+
+RevPiPlc.__set_autoreloaddelay
+__set_autoreloaddelay(value)
+
+Setter fuer autoreloaddelay.
RevPiPlc._configureplw
diff --git a/doc/revpipyload.html b/doc/revpipyload.html
index 33187e1..e478cd8 100644
--- a/doc/revpipyload.html
+++ b/doc/revpipyload.html
@@ -78,6 +78,12 @@ Methods
RevPiPyLoad |
Instantiiert RevPiPyLoad-Klasse. |
+| _check_mustrestart_plcprogram |
+Prueft ob sich kritische Werte veraendert haben. |
+
+| _check_mustrestart_plcslave |
+Prueft ob sich kritische Werte veraendert haben. |
+
| _loadconfig |
Load configuration file and setup modul. |
@@ -105,6 +111,15 @@ Methods
| stop |
Stop revpipyload. |
+| stop_plcprogram |
+Beendet PLC Programm. |
+
+| stop_plcslave |
+Beendet PLC Slave. |
+
+| stop_xmlrpcserver |
+Beendet XML-RPC. |
+
| xml_getconfig |
Uebertraegt die RevPiPyLoad Konfiguration. |
@@ -174,7 +189,29 @@ RevPiPyLoad (Constructor)
RevPiPyLoad()
Instantiiert RevPiPyLoad-Klasse.
-
+
+
+RevPiPyLoad._check_mustrestart_plcprogram
+_check_mustrestart_plcprogram()
+
+Prueft ob sich kritische Werte veraendert haben.
+
+- Returns:
+-
+True, wenn Subsystemneustart noetig ist
+
+
+
+RevPiPyLoad._check_mustrestart_plcslave
+_check_mustrestart_plcslave()
+
+Prueft ob sich kritische Werte veraendert haben.
+
+- Returns:
+-
+True, wenn Subsystemneustart noetig ist
+
+
RevPiPyLoad._loadconfig
_loadconfig()
@@ -251,6 +288,24 @@ RevPiPyLoad.stop
stop()
Stop revpipyload.
+
+
+RevPiPyLoad.stop_plcprogram
+stop_plcprogram()
+
+Beendet PLC Programm.
+
+
+RevPiPyLoad.stop_plcslave
+stop_plcslave()
+
+Beendet PLC Slave.
+
+
+RevPiPyLoad.stop_xmlrpcserver
+stop_xmlrpcserver()
+
+Beendet XML-RPC.
RevPiPyLoad.xml_getconfig
diff --git a/eric-revpipyload.api b/eric-revpipyload.api
index b654401..11fd074 100644
--- a/eric-revpipyload.api
+++ b/eric-revpipyload.api
@@ -19,9 +19,12 @@ picontrolserver.RevPiSlave?1(ipacl, port=55234)
picontrolserver.RevPiSlaveDev.run?4()
picontrolserver.RevPiSlaveDev.stop?4()
picontrolserver.RevPiSlaveDev?1(devcon, acl)
+plcsystem.RevPiPlc.__get_autoreloaddelay?6()
+plcsystem.RevPiPlc.__set_autoreloaddelay?6(value)
plcsystem.RevPiPlc._configureplw?5()
plcsystem.RevPiPlc._setuppopen?5()
plcsystem.RevPiPlc._spopen?5(lst_proc)
+plcsystem.RevPiPlc.autoreloaddelay?7
plcsystem.RevPiPlc.newlogfile?4()
plcsystem.RevPiPlc.run?4()
plcsystem.RevPiPlc.stop?4()
@@ -45,6 +48,8 @@ proginit.pargs?7
proginit.picontrolreset?7
proginit.rapcatalog?7
proginit.startdir?7
+revpipyload.RevPiPyLoad._check_mustrestart_plcprogram?5()
+revpipyload.RevPiPyLoad._check_mustrestart_plcslave?5()
revpipyload.RevPiPyLoad._loadconfig?5()
revpipyload.RevPiPyLoad._plcslave?5()
revpipyload.RevPiPyLoad._plcthread?5()
@@ -55,6 +60,9 @@ revpipyload.RevPiPyLoad.packapp?4(mode="tar", pictory=False)
revpipyload.RevPiPyLoad.root?7
revpipyload.RevPiPyLoad.start?4()
revpipyload.RevPiPyLoad.stop?4()
+revpipyload.RevPiPyLoad.stop_plcprogram?4()
+revpipyload.RevPiPyLoad.stop_plcslave?4()
+revpipyload.RevPiPyLoad.stop_xmlrpcserver?4()
revpipyload.RevPiPyLoad.xml_getconfig?4()
revpipyload.RevPiPyLoad.xml_getfilelist?4()
revpipyload.RevPiPyLoad.xml_getpictoryrsc?4()
diff --git a/revpipyload.e4p b/revpipyload.e4p
index e7f4e7a..d2fe227 100644
--- a/revpipyload.e4p
+++ b/revpipyload.e4p
@@ -1,7 +1,7 @@
-
+
en_US
@@ -9,7 +9,7 @@
Python3
Console
Dieser Loader wird über das Init-System geladen und führt das angegebene Pythonprogramm aus. Es ist für den RevolutionPi gedacht um automatisch das SPS-Programm zu starten.
- 0.6.2
+ 0.6.3
Sven Sager
akira@narux.de
@@ -23,6 +23,8 @@
revpipyload/picontrolserver.py
revpipyload/helper.py
revpipyload/xrpcserver.py
+ revpipyload/shared/ipaclmanager.py
+ revpipyload/shared/__init__.py
@@ -215,6 +217,7 @@
data
deb
dist
+ demo
diff --git a/revpipyload/picontrolserver.py b/revpipyload/picontrolserver.py
index bc207da..809a8e8 100644
--- a/revpipyload/picontrolserver.py
+++ b/revpipyload/picontrolserver.py
@@ -69,7 +69,7 @@ class RevPiSlave(Thread):
self.exitcode = -1
# Verbindung annehmen
- proginit.logger.debug("accept new connection")
+ proginit.logger.info("accept new connection for revpinetio")
try:
tup_sock = self.so.accept()
except:
diff --git a/revpipyload/plcsystem.py b/revpipyload/plcsystem.py
index 61958ee..8bb778f 100644
--- a/revpipyload/plcsystem.py
+++ b/revpipyload/plcsystem.py
@@ -33,6 +33,8 @@ class RevPiPlc(Thread):
super().__init__()
self._arguments = arguments
+ self._autoreloaddelay = 5 * 2
+ self._delaycounter = 5 * 2
self._evt_exit = Event()
self._plw = self._configureplw()
self._program = program
@@ -47,6 +49,18 @@ class RevPiPlc(Thread):
self.zeroonerror = False
self.zeroonexit = False
+ def __get_autoreloaddelay(self):
+ """Getter fuer autoreloaddelay.
+ @return Delayzeit in Sekunden """
+ return int(self._autoreloaddelay / 2)
+
+ def __set_autoreloaddelay(self, value):
+ """Setter fuer autoreloaddelay."""
+ if type(value) != int:
+ raise RuntimeError("parameter value must be ")
+ self._autoreloaddelay = value * 2
+ self._delaycounter = value * 2
+
def _configureplw(self):
"""Konfiguriert den PipeLogwriter fuer Ausgaben der PLCAPP.
@return PipeLogwriter()"""
@@ -132,14 +146,13 @@ class RevPiPlc(Thread):
_setuprt(self._procplc.pid, self._evt_exit)
# Überwachung starten
- delaycounter = self.autoreloaddelay
while not self._evt_exit.is_set():
# Auswerten
self.exitcode = self._procplc.poll()
if self.exitcode is not None:
- if delaycounter == self.autoreloaddelay:
+ if self._delaycounter == self.autoreloaddelay:
if self.exitcode > 0:
# PLC Python Programm abgestürzt
proginit.logger.error(
@@ -165,10 +178,10 @@ class RevPiPlc(Thread):
)
if not self._evt_exit.is_set() and self.autoreload:
- if delaycounter > 0:
- delaycounter -= 1
+ if self._delaycounter > 0:
+ self._delaycounter -= 1
else:
- delaycounter = self.autoreloaddelay
+ self._delaycounter = self.autoreloaddelay
# Prozess neu starten
self._procplc = self._spopen(lst_proc)
@@ -240,3 +253,5 @@ class RevPiPlc(Thread):
proginit.logger.debug("log pipes successfully closed")
proginit.logger.debug("leave RevPiPlc.stop()")
+
+ autoreloaddelay = property(__get_autoreloaddelay, __set_autoreloaddelay)
diff --git a/revpipyload/revpipyload.py b/revpipyload/revpipyload.py
index 0ce57a4..509a38d 100755
--- a/revpipyload/revpipyload.py
+++ b/revpipyload/revpipyload.py
@@ -50,7 +50,7 @@ from time import asctime
from xmlrpc.client import Binary
from xrpcserver import SaveXMLRPCServer
-pyloadversion = "0.6.2"
+pyloadversion = "0.6.3"
class RevPiPyLoad():
@@ -72,12 +72,18 @@ class RevPiPyLoad():
self.evt_loadconfig = Event()
self.globalconfig = ConfigParser()
self.logr = logsystem.LogReader()
- self.plc = None
- self.plc_pause = False
self.tfile = {}
self.xsrv = None
self.xml_ps = None
+ # Berechtigungsmanger
+ self.plcslaveacl = IpAclManager(minlevel=0, maxlevel=1)
+ self.xmlrpcacl = IpAclManager(minlevel=0, maxlevel=4)
+
+ # Threads/Prozesse
+ self.th_plcslave = None
+ self.plc = None
+
# Konfiguration laden
self._loadconfig()
@@ -89,19 +95,59 @@ class RevPiPyLoad():
proginit.logger.debug("leave RevPiPyLoad.__init__()")
+ def _check_mustrestart_plcslave(self):
+ """Prueft ob sich kritische Werte veraendert haben.
+ @return True, wenn Subsystemneustart noetig ist"""
+ if self.th_plcslave is None:
+ return True
+ elif "PLCSLAVE" not in self.globalconfig:
+ return True
+ else:
+ ip = self.globalconfig["PLCSLAVE"].get("bindip", "127.0.0.1")
+ if ip == "*":
+ ip = ""
+ elif ip == "":
+ ip = "127.0.0.1"
+ port = int(self.globalconfig["PLCSLAVE"].get("port", 55234))
+
+ return (
+ self.plcslave !=
+ int(self.globalconfig["PLCSLAVE"].get("plcslave", 0))
+ or self.plcslavebindip != ip
+ or self.plcslaveport != port
+ )
+
+ def _check_mustrestart_plcprogram(self):
+ """Prueft ob sich kritische Werte veraendert haben.
+ @return True, wenn Subsystemneustart noetig ist"""
+ if self.plc is None:
+ return True
+ elif "XMLRPC" not in self.globalconfig:
+ return True
+ else:
+ return (
+ self.plcworkdir !=
+ self.globalconfig["DEFAULT"].get("plcworkdir", ".")
+ or self.plcprogram !=
+ self.globalconfig["DEFAULT"].get("plcprogram", "none.py")
+ or self.plcarguments !=
+ self.globalconfig["DEFAULT"].get("plcarguments", "")
+ or self.plcuid !=
+ int(self.globalconfig["DEFAULT"].get("plcuid", 65534))
+ or self.plcgid !=
+ int(self.globalconfig["DEFAULT"].get("plcgid", 65534))
+ or self.pythonversion !=
+ int(self.globalconfig["DEFAULT"].get("pythonversion", 3))
+ or self.rtlevel !=
+ int(self.globalconfig["DEFAULT"].get("rtlevel", 0))
+ )
+
def _loadconfig(self):
"""Load configuration file and setup modul."""
proginit.logger.debug("enter RevPiPyLoad._loadconfig()")
- self.evt_loadconfig.clear()
- pauseproc = False
-
- if not self._exit:
- proginit.logger.info(
- "shutdown revpipyload while getting new config"
- )
- self.stop()
- pauseproc = True
+ # Subsysteme herunterfahren
+ self.stop_xmlrpcserver()
# Konfigurationsdatei laden
proginit.logger.info(
@@ -109,6 +155,10 @@ class RevPiPyLoad():
)
self.globalconfig.read(proginit.globalconffile)
+ # Merker für Subsystem-Neustart nach laden, vor setzen
+ restart_plcslave = self._check_mustrestart_plcslave()
+ restart_plcprogram = self._check_mustrestart_plcprogram()
+
# Konfiguration verarbeiten [DEFAULT]
self.autoreload = \
int(self.globalconfig["DEFAULT"].get("autoreload", 1))
@@ -140,12 +190,15 @@ class RevPiPyLoad():
if "PLCSLAVE" in self.globalconfig:
self.plcslave = \
int(self.globalconfig["PLCSLAVE"].get("plcslave", 0))
- self.plcslaveacl = IpAclManager(minlevel=0, maxlevel=1)
+
+ # Berechtigungen laden, wenn aktiv ist
if not self.plcslaveacl.loadaclfile(
self.globalconfig["PLCSLAVE"].get("aclfile", "")):
proginit.logger.warning(
"can not load plcslave acl - wrong format"
)
+ if self.plcslave != 1:
+ self.stop_plcslave()
# Bind IP lesen und anpassen
self.plcslavebindip = \
@@ -163,7 +216,7 @@ class RevPiPyLoad():
if "XMLRPC" in self.globalconfig:
self.xmlrpc = \
int(self.globalconfig["XMLRPC"].get("xmlrpc", 0))
- self.xmlrpcacl = IpAclManager(minlevel=0, maxlevel=4)
+
if not self.xmlrpcacl.loadaclfile(
self.globalconfig["XMLRPC"].get("aclfile", "")):
proginit.logger.warning(
@@ -188,12 +241,37 @@ class RevPiPyLoad():
)
os.chdir(self.plcworkdir)
- # PLC Threads konfigurieren
- self.plc = self._plcthread()
- self.th_plcslave = self._plcslave()
+ # PLC Programm konfigurieren
+ if restart_plcprogram:
+ self.stop_plcprogram()
+ self.plc = self._plcthread()
+
+ if not self._exit and self.plc is not None and self.autostart:
+ proginit.logger.info("restart plc program after reload")
+ self.plc.start()
+
+ else:
+ proginit.logger.info(
+ "configure plc program parameters after reload"
+ )
+ self.plc.autoreload = self.autoreload
+ self.plc.autoreloaddelay = self.autoreloaddelay
+ self.plc.zeroonerror = self.zeroonerror
+ self.plc.zeroonexit = self.zeroonexit
+
+ # PLC-Slave konfigurieren
+ if restart_plcslave:
+ self.stop_plcslave()
+ self.th_plcslave = self._plcslave()
+
+ if not self._exit and self.th_plcslave is not None:
+ proginit.logger.info("restart plc slave after reload")
+ self.th_plcslave.start()
# XMLRPC-Server Instantiieren und konfigurieren
- if self.xmlrpc == 1:
+ if self.xmlrpc == 0:
+ self.xmlrpc = None
+ else:
proginit.logger.debug("create xmlrpc server")
self.xsrv = SaveXMLRPCServer(
(self.xmlrpcbindip, self.xmlrpcport),
@@ -276,11 +354,13 @@ class RevPiPyLoad():
proginit.logger.debug("created xmlrpc server")
- if pauseproc:
- proginit.logger.info(
- "start revpipyload after getting new config"
- )
- self.start()
+ # Neustart bei reload
+ if not self._exit:
+ proginit.logger.info("start xmlrpc-server")
+ self.xsrv.start()
+
+ # Konfiguration abschließen
+ self.evt_loadconfig.clear()
proginit.logger.debug("leave RevPiPyLoad._loadconfig()")
@@ -297,7 +377,7 @@ class RevPiPyLoad():
))
return None
- proginit.logger.debug("create PLC watcher")
+ proginit.logger.debug("create PLC program watcher")
th_plc = plcsystem.RevPiPlc(
os.path.join(self.plcworkdir, self.plcprogram),
self.plcarguments,
@@ -423,17 +503,21 @@ class RevPiPyLoad():
# Slaveausfuehrung übergeben
self.th_plcslave.start()
- if self.autostart:
- proginit.logger.debug("starting revpiplc-thread")
- if self.plc is not None:
- self.plc.start()
+ # PLC Programm automatisch starten
+ if self.autostart and self.plc is not None:
+ self.plc.start()
- while not self._exit \
- and not self.evt_loadconfig.is_set():
+ # mainloop
+ while not self._exit:
+
+ # Neue Konfiguration laden
+ if self.evt_loadconfig.is_set():
+ proginit.logger.info("got reqeust to reload config")
+ self._loadconfig()
# PLC Server Thread prüfen
- if self.plcslave \
- and not (self.plc_pause or self.th_plcslave.is_alive()):
+ if self.plcslave and self.th_plcslave is not None \
+ and not self.th_plcslave.is_alive():
proginit.logger.warning(
"restart plc slave after thread was not running"
)
@@ -452,39 +536,57 @@ class RevPiPyLoad():
self.evt_loadconfig.wait(1)
- if not self._exit:
- proginit.logger.info("exit python plc program to reload config")
- self._loadconfig()
+ proginit.logger.info("stopping revpipyload")
+
+ # Alle Sub-Systeme beenden
+ self.stop_plcslave()
+ self.stop_plcprogram()
+ self.stop_xmlrpcserver()
+
+ # Logreader schließen
+ self.logr.closeall()
proginit.logger.debug("leave RevPiPyLoad.start()")
def stop(self):
"""Stop revpipyload."""
proginit.logger.debug("enter RevPiPyLoad.stop()")
-
- proginit.logger.info("stopping revpipyload")
self._exit = True
+ proginit.logger.debug("leave RevPiPyLoad.stop()")
- if self.th_plcslave is not None and self.th_plcslave.is_alive():
- proginit.logger.debug("stopping revpi slave thread")
- self.th_plcslave.stop()
- self.th_plcslave.join()
- proginit.logger.debug("revpi slave thread successfully closed")
+ def stop_plcprogram(self):
+ """Beendet PLC Programm."""
+ proginit.logger.debug("enter RevPiPyLoad.stop_plcprogram()")
if self.plc is not None and self.plc.is_alive():
- proginit.logger.debug("stopping revpiplc thread")
+ proginit.logger.info("stopping revpiplc thread")
self.plc.stop()
self.plc.join()
proginit.logger.debug("revpiplc thread successfully closed")
- if self.xmlrpc >= 1:
+ proginit.logger.debug("leave RevPiPyLoad.stop_plcprogram()")
+
+ def stop_plcslave(self):
+ """Beendet PLC Slave."""
+ proginit.logger.debug("enter RevPiPyLoad.stop_plcslave()")
+
+ if self.th_plcslave is not None and self.th_plcslave.is_alive():
+ proginit.logger.info("stopping revpi slave thread")
+ self.th_plcslave.stop()
+ self.th_plcslave.join()
+ proginit.logger.debug("revpi slave thread successfully closed")
+
+ proginit.logger.debug("leave RevPiPyLoad.stop_plcslave()")
+
+ def stop_xmlrpcserver(self):
+ """Beendet XML-RPC."""
+ proginit.logger.debug("enter RevPiPyLoad.stop_xmlrpcserver()")
+
+ if self.xsrv is not None:
proginit.logger.info("shutting down xmlrpc-server")
self.xsrv.stop()
- # Logreader schließen
- self.logr.closeall()
-
- proginit.logger.debug("leave RevPiPyLoad.stop()")
+ proginit.logger.debug("leave RevPiPyLoad.stop_xmlrpcserver()")
def xml_getconfig(self):
"""Uebertraegt die RevPiPyLoad Konfiguration.
@@ -618,9 +720,7 @@ class RevPiPyLoad():
"""
proginit.logger.debug("xmlrpc call plcstop")
if self.plc is not None and self.plc.is_alive():
- self.plc.stop()
- self.plc.join()
- proginit.logger.debug("revpiplc thread successfully closed")
+ self.stop_plcprogram()
return self.plc.exitcode
else:
return -1
@@ -725,6 +825,13 @@ class RevPiPyLoad():
str(dc[key])
)
+ # conf-Datei schreiben
+ with open(proginit.globalconffile, "w") as fh:
+ self.globalconfig.write(fh)
+ proginit.logger.info(
+ "got new config and wrote it to {}".format(proginit.globalconffile)
+ )
+
# ACLs sofort übernehmen und schreiben
str_acl = dc.get("plcslaveacl", None)
if str_acl is not None and self.plcslaveacl.acl != str_acl:
@@ -759,16 +866,8 @@ class RevPiPyLoad():
)
)
- # conf-Datei schreiben
- with open(proginit.globalconffile, "w") as fh:
- self.globalconfig.write(fh)
- proginit.logger.info(
- "got new config and wrote it to {}".format(proginit.globalconffile)
- )
-
- if loadnow:
- # RevPiPyLoad neu konfigurieren
- self.evt_loadconfig.set()
+ # RevPiPyLoad neu konfigurieren
+ self.evt_loadconfig.set()
return True
@@ -862,7 +961,6 @@ class RevPiPyLoad():
-2: Laeuft bereits
"""
- self.plc_pause = False
if self.th_plcslave is not None and self.th_plcslave.is_alive():
return -2
else:
@@ -876,9 +974,9 @@ class RevPiPyLoad():
def xml_plcslavestop(self):
"""Stoppt den PLC Slave Server.
@return True, wenn stop erfolgreich"""
- self.plc_pause = True
if self.th_plcslave is not None:
- self.th_plcslave.stop()
+ self.stop_plcslave()
+ self.th_plcslave = None
return True
else:
return False
diff --git a/setup.py b/setup.py
index 079f00e..9565b6d 100644
--- a/setup.py
+++ b/setup.py
@@ -27,7 +27,7 @@ setup(
license="LGPLv3",
name="revpipyload",
- version="0.6.2",
+ version="0.6.3",
scripts=["data/revpipyload"],
@@ -39,9 +39,12 @@ setup(
"data/etc/avahi/services/revpipyload.service",
]),
("/etc/revpipyload", [
+ "data/etc/revpipyload/aclplcslave.conf",
+ "data/etc/revpipyload/aclxmlrpc.conf",
"data/etc/revpipyload/revpipyload.conf",
]),
("share/revpipyload", glob("revpipyload/*.*")),
+ ("share/revpipyload/shared", glob("revpipyload/shared/*.*")),
("/var/lib/revpipyload", [
"data/var/lib/revpipyload/.placeholder",
])