diff --git a/debian/revpipyload.logrotate b/debian/revpipyload.logrotate
index 4097d2c..9eb1bd6 100644
--- a/debian/revpipyload.logrotate
+++ b/debian/revpipyload.logrotate
@@ -1,12 +1,4 @@
/var/log/revpipyload
-{
- rotate 6
- weekly
- compress
- delaycompress
- missingok
- notifempty
-}
/var/log/revpipyloadapp
{
rotate 6
@@ -15,4 +7,7 @@
delaycompress
missingok
notifempty
+ postrotate
+ kill -SIGUSR1 `cat /var/run/revpipyload.pid` > /dev/null 2>&1 || true
+ endscript
}
diff --git a/doc/proginit.html b/doc/proginit.html
new file mode 100644
index 0000000..b22ec58
--- /dev/null
+++ b/doc/proginit.html
@@ -0,0 +1,50 @@
+
+
+proginit
+
+
+
+
+proginit
+
+Main functions of our program.
+
+
+Global Attributes
+
+| forked |
| globalconffile |
| logapp |
| logger |
| logplc |
| pargs |
+
+
+Classes
+
+
+Functions
+
+
+| cleanup |
+Clean up program. |
+
+| configure |
+Initialize general program functions. |
+
+
+
+
+cleanup
+cleanup()
+
+Clean up program.
+
+
+
+
+configure
+configure()
+
+Initialize general program functions.
+
+
+
+
\ No newline at end of file
diff --git a/doc/revpipyload.html b/doc/revpipyload.html
new file mode 100644
index 0000000..04a1008
--- /dev/null
+++ b/doc/revpipyload.html
@@ -0,0 +1,699 @@
+
+
+revpipyload
+
+
+
+
+revpipyload
+
+Revolution Pi Python PLC Loader.
+
+Stellt das RevPiPyLoad Programm bereit. Dieses Programm lauft als Daemon auf
+dem Revolution Pi. Es stellt Funktionen bereit, die es ermoeglichen ein Python
+Programm zu starten und fuehrt dessen Ausgaben in eine Logdatei. Die Logdaten
+koennen am Pi selber oder ueber eine XML-RPC Schnittstelle ausgelesen werden.
+
+Dieser Daemon prueft ob das Python Programm noch lauft und kann es im Fall
+eines Absturzes neu starten.
+
+Ueber diesen Daemon kann die gesamte piCtory Konfiguration exportiert oder
+importiert, ein Dump vom Prozessabbild gezogen und das eigene Python
+Programm hochgeladen werden.
+
+Es kann von dem Python Programm auch eine Archivdatei herunterladen werden,
+welche optional auch die piCtory Konfiguraiton beinhaltet. Damit kann man sehr
+schnell auf einem Revolution Pi das Programm inkl. piCtory Konfiguration
+austauschen.
+
+Die Zugriffsmoeglichkeiten koennen ueber einen Konfigurationsparameter
+begrenzt werden!
+
+
+Global Attributes
+
+| configrsc |
| picontrolreset |
| procimg |
| pyloadverion |
+
+
+Classes
+
+
+Functions
+
+
+
+LogReader
+
+Ermoeglicht den Zugriff auf die Logdateien.
+
+ Beinhaltet Funktionen fuer den Abruf der gesamten Logdatei fuer das
+ RevPiPyLoad-System und die Logdatei der PLC-Anwendung.
+ Ausserdem koennen nur neue Zeilen abgerufen werden, um eine dynamische
+ Logansicht zu ermoeglichen.
+
+
+
+
+Derived from
+None
+
+Class Attributes
+
+
+Class Methods
+
+
+Methods
+
+
+| LogReader |
+Instantiiert LogReader-Klasse. |
+
+| closeall |
+Fuehrt close auf File Handler durch. |
+
+| get_applines |
+Gibt neue Zeilen ab letzen Aufruf zurueck. |
+
+| get_applog |
+Gibt die gesamte Logdatei zurueck. |
+
+| get_plclines |
+Gibt neue Zeilen ab letzen Aufruf zurueck. |
+
+| get_plclog |
+Gibt die gesamte Logdatei zurueck. |
+
+
+
+Static Methods
+
+
+
+LogReader (Constructor)
+LogReader()
+
+Instantiiert LogReader-Klasse.
+
+
+LogReader.closeall
+closeall()
+
+Fuehrt close auf File Handler durch.
+
+
+LogReader.get_applines
+get_applines()
+
+Gibt neue Zeilen ab letzen Aufruf zurueck.
+
+- Returns:
+-
+list() mit neuen Zeilen
+
+
+
+LogReader.get_applog
+get_applog()
+
+Gibt die gesamte Logdatei zurueck.
+
+- Returns:
+-
+str() mit Logdaten
+
+
+
+LogReader.get_plclines
+get_plclines()
+
+Gibt neue Zeilen ab letzen Aufruf zurueck.
+
+- Returns:
+-
+list() mit neuen Zeilen
+
+
+
+LogReader.get_plclog
+get_plclog()
+
+Gibt die gesamte Logdatei zurueck.
+
+- Returns:
+-
+str() mit Logdaten
+
+
+
+
+
+PipeLogwriter
+
+
+Derived from
+Thread
+
+Class Attributes
+
+
+Class Methods
+
+
+Methods
+
+
+Static Methods
+
+
+
+PipeLogwriter (Constructor)
+PipeLogwriter(fh)
+
+
+PipeLogwriter.run
+run()
+
+
+PipeLogwriter.stop
+stop()
+
+
+
+
+RevPiPlc
+
+Verwaltet das PLC Python Programm.
+
+ Dieser Thread startet das PLC Python Programm und ueberwacht es. Sollte es
+ abstuerzen kann es automatisch neu gestartet werden. Die Ausgaben des
+ Programms werden in eine Logdatei umgeleitet, damit der Entwickler sein
+ Programm analysieren und debuggen kann.
+
+
+
+
+Derived from
+Thread
+
+Class Attributes
+
+
+Class Methods
+
+
+Methods
+
+
+Static Methods
+
+
+
+RevPiPlc (Constructor)
+RevPiPlc(program, arguments, pversion)
+
+Instantiiert RevPiPlc-Klasse.
+
+
+RevPiPlc._configurefh
+_configurefh()
+
+
+RevPiPlc._setuppopen
+_setuppopen()
+
+Setzt UID und GID fuer das PLC Programm.
+
+
+RevPiPlc._spopen
+_spopen(lst_proc, filenum=None)
+
+Startet das PLC Programm.
+
+- lst_proc:
+-
+Prozessliste
+
+
+- Returns:
+-
+subprocess
+
+
+
+RevPiPlc._zeroprocimg
+_zeroprocimg()
+
+Setzt Prozessabbild auf NULL.
+
+
+RevPiPlc.newlogfile
+newlogfile()
+
+
+RevPiPlc.run
+run()
+
+Fuehrt PLC-Programm aus und ueberwacht es.
+
+
+RevPiPlc.stop
+stop()
+
+Beendet PLC-Programm.
+
+
+
+
+RevPiPyLoad
+
+Hauptklasse, die alle Funktionen zur Verfuegung stellt.
+
+ Hier wird die gesamte Konfiguraiton eingelesen und der ggf. aktivierte
+ XML-RPC-Server gestartet.
+
+
+
+
+Derived from
+None
+
+Class Attributes
+
+
+Class Methods
+
+
+Methods
+
+
+Static Methods
+
+
+
+RevPiPyLoad (Constructor)
+RevPiPyLoad()
+
+Instantiiert RevPiPyLoad-Klasse.
+
+
+RevPiPyLoad._loadconfig
+_loadconfig()
+
+Load configuration file and setup modul.
+
+
+RevPiPyLoad._plcthread
+_plcthread()
+
+Konfiguriert den PLC-Thread fuer die Ausfuehrung.
+
+- Returns:
+-
+PLC-Thread Object or None
+
+
+
+RevPiPyLoad._sigexit
+_sigexit(signum, frame)
+
+Signal handler to clean and exit program.
+
+
+RevPiPyLoad._sigloadconfig
+_sigloadconfig(signum, frame)
+
+Signal handler to load configuration.
+
+
+RevPiPyLoad._signewlogfile
+_signewlogfile(signum, frame)
+
+Signal handler to start new logfile.
+
+
+RevPiPyLoad.packapp
+packapp(mode="tar", pictory=False)
+
+Erzeugt aus dem PLC-Programm ein TAR-File.
+
+- mode:
+-
+Packart 'tar' oder 'zip'
+
- pictory:
+-
+piCtory Konfiguration mit einpacken
+
+
+- Returns:
+-
+Dateinamen des Archivs
+
+
+
+RevPiPyLoad.start
+start()
+
+Start plcload and PLC python program.
+
+
+RevPiPyLoad.stop
+stop()
+
+Stop PLC python program and plcload.
+
+
+RevPiPyLoad.xml_getconfig
+xml_getconfig()
+
+Uebertraegt die RevPiPyLoad Konfiguration.
+
+- Returns:
+-
+dict() der Konfiguration
+
+
+
+RevPiPyLoad.xml_getfilelist
+xml_getfilelist()
+
+Uebertraegt die Dateiliste vom plcworkdir.
+
+- Returns:
+-
+list() mit Dateinamen
+
+
+
+RevPiPyLoad.xml_getpictoryrsc
+xml_getpictoryrsc()
+
+Gibt die config.rsc Datei von piCotry zurueck.
+
+- Returns:
+-
+xmlrpc.client.Binary()
+
+
+
+RevPiPyLoad.xml_getprocimg
+xml_getprocimg()
+
+Gibt die Rohdaten aus piControl0 zurueck.
+
+- Returns:
+-
+xmlrpc.client.Binary()
+
+
+
+RevPiPyLoad.xml_plcdownload
+xml_plcdownload(mode="tar", pictory=False)
+
+Uebertraegt ein Archiv vom plcworkdir.
+
+- mode:
+-
+Archivart 'tar' 'zip'
+
- pictory:
+-
+piCtory Konfiguraiton mit einpacken
+
+
+- Returns:
+-
+Binary() mit Archivdatei
+
+
+
+RevPiPyLoad.xml_plcexitcode
+xml_plcexitcode()
+
+Gibt den aktuellen exitcode vom PLC Programm zurueck.
+
+- Returns:
+-
+int() exitcode oder:
+ -1 laeuft noch
+ -2 Datei nicht gefunden
+ -3 Lief nie
+
+
+
+RevPiPyLoad.xml_plcrunning
+xml_plcrunning()
+
+Prueft ob das PLC Programm noch lauft.
+
+- Returns:
+-
+True, wenn das PLC Programm noch lauft
+
+
+
+RevPiPyLoad.xml_plcstart
+xml_plcstart()
+
+Startet das PLC Programm.
+
+- Returns:
+-
+int() Status:
+ -1 Programm lauft noch
+ -2 Datei nicht gefunden
+
+
+
+RevPiPyLoad.xml_plcstop
+xml_plcstop()
+
+Stoppt das PLC Programm.
+
+- Returns:
+-
+int() Exitcode vom PLC Programm
+ -1 PLC Programm lief nicht
+
+
+
+RevPiPyLoad.xml_plcupload
+xml_plcupload(filedata, filename)
+
+Empfaengt Dateien fuer das PLC Programm.
+
+- filedata:
+-
+GZIP Binary data der datei
+
- filename:
+-
+Name inkl. Unterverzeichnis der Datei
+
+
+- Returns:
+-
+Ture, wenn Datei erfolgreich gespeichert wurde
+
+
+
+RevPiPyLoad.xml_plcuploadclean
+xml_plcuploadclean()
+
+Loescht das gesamte plcworkdir Verzeichnis.
+
+- Returns:
+-
+True, wenn erfolgreich
+
+
+
+RevPiPyLoad.xml_reload
+xml_reload()
+
+Startet RevPiPyLoad neu und verwendet neue Konfiguraiton.
+
+
+RevPiPyLoad.xml_setconfig
+xml_setconfig(dc, loadnow=False)
+
+Empfaengt die RevPiPyLoad Konfiguration.
+
+- Returns:
+-
+True, wenn erfolgreich angewendet
+
+
+
+RevPiPyLoad.xml_setpictoryrsc
+xml_setpictoryrsc(filebytes, reset=False)
+
+Schreibt die config.rsc Datei von piCotry.
+
+- filebytes:
+-
+xmlrpc.client.Binary()-Objekt
+
- reset:
+-
+Reset piControl Device
+
+
+- Returns:
+-
+Statuscode:
+ 0 Alles erfolgreich
+ -1 Kann JSON-Datei nicht laden
+ -2 piCtory Elemente in JSON-Datei nicht gefunden
+ -3 Konnte Konfiguraiton nicht schreiben
+ Positive Zahl ist exitcode von piControlReset
+
+
+
+
+
\ No newline at end of file
diff --git a/revpipyload.e4p b/revpipyload.e4p
index 089f580..f87c5bd 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.2.9
+ 0.2.10
Sven Sager
akira@narux.de
diff --git a/revpipyload/proginit.py b/revpipyload/proginit.py
index 81b35bf..4898188 100644
--- a/revpipyload/proginit.py
+++ b/revpipyload/proginit.py
@@ -1,108 +1,121 @@
+#
+# RevPiPyLoad
+#
+# Webpage: https://revpimodio.org/revpipyplc/
+# (c) Sven Sager, License: LGPLv3
+#
# -*- coding: utf-8 -*-
"""Main functions of our program."""
import logging
import sys
from argparse import ArgumentParser
-from configparser import ConfigParser
from os import fork as osfork
from os.path import exists as ospexists
+forked = False
+globalconffile = None
logapp = "revpipyloadapp.log"
logplc = "revpipyload.log"
logger = None
pargs = None
-class ProgInit():
+def cleanup():
+ """Clean up program."""
+ # Logging beenden
+ logging.shutdown()
- """Programmfunktionen fuer Parameter und Logger."""
- def __del__(self):
- """Clean up program."""
- # Logging beenden
- logging.shutdown()
+def configure():
+ """Initialize general program functions."""
- def __init__(self):
- """Initialize general program functions."""
+ # Command arguments
+ parser = ArgumentParser(
+ description="RevolutionPi Python3 Loader"
+ )
+ parser.add_argument(
+ "-d", "--daemon", action="store_true", dest="daemon",
+ help="Run program as a daemon in background"
+ )
+ parser.add_argument(
+ "-c", "--conffile", dest="conffile",
+ default="revpipyload.conf",
+ help="Application configuration file"
+ )
+ parser.add_argument(
+ "-f", "--logfile", dest="logfile",
+ help="Save log entries to this file"
+ )
+ parser.add_argument(
+ "-v", "--verbose", action="count", dest="verbose",
+ help="Switch on verbose logging"
+ )
+ global pargs
+ pargs = parser.parse_args()
- # Command arguments
- parser = ArgumentParser(
- description="RevolutionPi Python3 Loader"
- )
- parser.add_argument(
- "-d", "--daemon", action="store_true", dest="daemon",
- help="Run program as a daemon in background"
- )
- parser.add_argument(
- "-c", "--conffile", dest="conffile",
- default="revpipyload.conf",
- help="Application configuration file"
- )
- parser.add_argument(
- "-f", "--logfile", dest="logfile",
- help="Save log entries to this file"
- )
- parser.add_argument(
- "-v", "--verbose", action="count", dest="verbose",
- help="Switch on verbose logging"
- )
- global pargs
- pargs = parser.parse_args()
+ # Prüfen ob als Daemon ausgeführt werden soll
+ global forked
+ pidfile = "/var/run/revpipyload.pid"
+ pid = 0
+ if pargs.daemon and not forked:
+ # Prüfen ob daemon schon läuft
+ if ospexists(pidfile):
+ raise SystemError(
+ "program already running as daemon. check {}".format(pidfile)
+ )
- # Prüfen ob als Daemon ausgeführt werden soll
- self.pidfile = "/var/run/revpipyload.pid"
- self.pid = 0
- if pargs.daemon:
- # Prüfen ob daemon schon läuft
- if ospexists(self.pidfile):
- raise SystemError(
- "program already running as daemon. check {}".format(
- self.pidfile
- )
- )
+ # Zum daemon machen
+ pid = osfork()
+ if pid > 0:
+ with open(pidfile, "w") as f:
+ f.write(str(pid))
+ sys.exit(0)
+ else:
+ forked = True
- self.pid = osfork()
- if self.pid > 0:
- with open(self.pidfile, "w") as f:
- f.write(str(self.pid))
- sys.exit(0)
+ if pargs.daemon:
+ global logapp
+ global logplc
- global logapp
- global logplc
+ # Ausgaben umhängen in Logfile
+ logapp = "/var/log/revpipyloadapp"
+ logplc = "/var/log/revpipyload"
+ pargs.conffile = "/etc/revpipyload/revpipyload.conf"
+ sys.stdout = open(logplc, "a")
+ sys.stderr = sys.stdout
- # Ausgaben umhängen in Logfile
- logapp = "/var/log/revpipyloadapp"
- logplc = "/var/log/revpipyload"
- pargs.conffile = "/etc/revpipyload/revpipyload.conf"
- sys.stdout = open(logplc, "a")
- sys.stderr = sys.stdout
+ # Initialize configparser globalconfig
+ global globalconffile
+ globalconffile = pargs.conffile
- # Initialize configparser globalconfig
- self.globalconffile = pargs.conffile
- self.globalconfig = ConfigParser()
- self.globalconfig.read(pargs.conffile)
+ # Program logger
+ global logger
+ logger = logging.getLogger()
- # Program logger
- global logger
- logger = logging.getLogger()
- logformat = logging.Formatter(
- "{asctime} [{levelname:8}] {message}",
- datefmt="%Y-%m-%d %H:%M:%S", style="{"
- )
- lhandler = logging.StreamHandler(sys.stdout)
+ # Alle handler entfernen
+ for lhandler in logger.handlers:
+ logger.removeHandler(lhandler)
+
+ # Neue Handler bauen
+ logformat = logging.Formatter(
+ "{asctime} [{levelname:8}] {message}",
+ datefmt="%Y-%m-%d %H:%M:%S", style="{"
+ )
+ lhandler = logging.StreamHandler(sys.stdout)
+ lhandler.setFormatter(logformat)
+ logger.addHandler(lhandler)
+
+ if pargs.logfile is not None:
+ lhandler = logging.FileHandler(filename=pargs.logfile)
lhandler.setFormatter(logformat)
logger.addHandler(lhandler)
- if pargs.logfile is not None:
- lhandler = logging.FileHandler(filename=pargs.logfile)
- lhandler.setFormatter(logformat)
- logger.addHandler(lhandler)
- # Loglevel auswerten
- if pargs.verbose is None:
- loglevel = logging.WARNING
- elif pargs.verbose == 1:
- loglevel = logging.INFO
- elif pargs.verbose > 1:
- loglevel = logging.DEBUG
- logger.setLevel(loglevel)
+ # Loglevel auswerten
+ if pargs.verbose is None:
+ loglevel = logging.WARNING
+ elif pargs.verbose == 1:
+ loglevel = logging.INFO
+ elif pargs.verbose > 1:
+ loglevel = logging.DEBUG
+ logger.setLevel(loglevel)
diff --git a/revpipyload/revpipyload.py b/revpipyload/revpipyload.py
index 2e19cbf..8824ac9 100755
--- a/revpipyload/revpipyload.py
+++ b/revpipyload/revpipyload.py
@@ -39,6 +39,7 @@ import subprocess
import tarfile
import zipfile
from concurrent import futures
+from configparser import ConfigParser
from json import loads as jloads
from re import match as rematch
from shutil import rmtree
@@ -51,7 +52,7 @@ from xmlrpc.server import SimpleXMLRPCServer
configrsc = "/opt/KUNBUS/config.rsc"
picontrolreset = "/opt/KUNBUS/piControlReset"
procimg = "/dev/piControl0"
-pyloadverion = "0.2.9"
+pyloadverion = "0.2.10"
class LogReader():
@@ -72,6 +73,13 @@ class LogReader():
self.fhplc = None
self.posplc = 0
+ def closeall(self):
+ """Fuehrt close auf File Handler durch."""
+ if self.fhapp is not None:
+ self.fhapp.close()
+ if self.fhplc is not None:
+ self.fhplc.close()
+
def get_applines(self):
"""Gibt neue Zeilen ab letzen Aufruf zurueck.
@returns: list() mit neuen Zeilen"""
@@ -152,6 +160,39 @@ class LogReader():
return self.fhplc.read()
+class PipeLogwriter(Thread):
+
+ def __init__(self, fh):
+ super().__init__()
+ self._exit = Event()
+ self.fh = fh
+ if fh is None:
+ self.pipeout = None
+ else:
+ self._pipein, self.pipeout = os.pipe()
+
+ def run(self):
+ if self.fh is not None:
+ fhread = os.fdopen(self._pipein)
+ proginit.logger.debug("enter logreader pipe")
+ while not self._exit.is_set():
+ line = fhread.readline()
+ try:
+ self.fh.write(line)
+ self.fh.flush()
+ except:
+ pass
+ proginit.logger.debug("leave logreader pipe")
+
+ def stop(self):
+ proginit.logger.debug("quit pipe logreader")
+ self._exit.set()
+ if self.pipeout is not None:
+ os.write(self.pipeout, b"\n")
+ os.close(self.pipeout)
+ os.close(self._pipein)
+
+
class RevPiPlc(Thread):
"""Verwaltet das PLC Python Programm.
@@ -170,8 +211,9 @@ class RevPiPlc(Thread):
self._arguments = arguments
self._evt_exit = Event()
self.exitcode = None
- self._fh = None
+ self._fh = self._configurefh()
self.gid = 65534
+ self.plw = None
self._program = program
self._procplc = None
self._pversion = pversion
@@ -179,21 +221,39 @@ class RevPiPlc(Thread):
self.zeroonerror = False
self.zeroonexit = False
+ def _configurefh(self):
+ # Ausgaben konfigurieren und ggf. umleiten
+ proginit.logger.debug("configure fh applog")
+ logfile = None
+ if proginit.pargs.daemon:
+ if os.access(os.path.dirname(proginit.logapp), os.R_OK | os.W_OK):
+ logfile = proginit.logapp
+ elif proginit.pargs.logfile is not None:
+ logfile = proginit.pargs.logfile
+
+ if logfile is not None:
+ return open(logfile, "a")
+ else:
+ return None
+
def _setuppopen(self):
"""Setzt UID und GID fuer das PLC Programm."""
+ proginit.logger.debug(
+ "set uid {} and gid {}".format(self.uid, self.gid))
os.setgid(self.gid)
os.setuid(self.uid)
- def _spopen(self, lst_proc):
+ def _spopen(self, lst_proc, filenum=None):
"""Startet das PLC Programm.
@param lst_proc: Prozessliste
@returns: subprocess"""
+ proginit.logger.debug("configure subprocess")
return subprocess.Popen(
lst_proc,
preexec_fn=self._setuppopen,
cwd=os.path.dirname(self._program),
bufsize=1,
- stdout=subprocess.STDOUT if self._fh is None else self._fh,
+ stdout=subprocess.STDOUT if filenum is None else filenum,
stderr=subprocess.STDOUT
)
@@ -203,6 +263,20 @@ class RevPiPlc(Thread):
f = open("/dev/piControl0", "w+b", 0)
f.write(bytes(4096))
+ def newlogfile(self):
+ if self._fh is not None:
+ self._fh.close()
+
+ self._fh = self._configurefh()
+ if self.plw is not None:
+ self.plw.fh = self._fh
+
+ self._fh.write("-" * 55)
+ self._fh.write("\nstart new logfile: {}\n".format(asctime()))
+ self._fh.flush()
+
+ proginit.logger.info("new plc logfile")
+
def run(self):
"""Fuehrt PLC-Programm aus und ueberwacht es."""
if self._pversion == 2:
@@ -214,25 +288,21 @@ class RevPiPlc(Thread):
self._program, self._arguments
))
- # Ausgaben konfigurieren und ggf. umleiten
- logfile = None
- if proginit.pargs.daemon:
- if os.access(os.path.dirname(proginit.logapp), os.R_OK | os.W_OK):
- logfile = proginit.logapp
- elif proginit.pargs.logfile is not None:
- logfile = proginit.pargs.logfile
-
- if logfile is not None:
- self._fh = open(logfile, "a")
+ # Logausgabe
+ if self._fh is not None:
self._fh.write("-" * 55)
self._fh.write("\nplc: {} started: {}\n".format(
os.path.basename(self._program), asctime()
))
self._fh.flush()
+ # LogWriter
+ self.plw = PipeLogwriter(self._fh)
+ self.plw.start()
+
# Prozess erstellen
proginit.logger.info("start plc program {}".format(self._program))
- self._procplc = self._spopen(lst_proc)
+ self._procplc = self._spopen(lst_proc, self.plw.pipeout)
while not self._evt_exit.is_set():
@@ -263,7 +333,7 @@ class RevPiPlc(Thread):
if not self._evt_exit.is_set() and self.autoreload:
# Prozess neu starten
- self._procplc = self._spopen(lst_proc)
+ self._procplc = self._spopen(lst_proc, self.plw.pipeout)
if self.exitcode == 0:
proginit.logger.warning(
"restart plc program after clean exit"
@@ -277,8 +347,15 @@ class RevPiPlc(Thread):
self._evt_exit.wait(1)
+ def stop(self):
+ """Beendet PLC-Programm."""
+ proginit.logger.info("stop revpiplc thread")
+ self._evt_exit.set()
+
# Prüfen ob es einen subprocess gibt
if self._procplc is None:
+ if self.plw is not None:
+ self.plw.stop()
return
# Prozess beenden
@@ -305,12 +382,11 @@ class RevPiPlc(Thread):
or self.zeroonerror and self.exitcode != 0:
self._zeroprocimg()
- def stop(self):
- """Beendet PLC-Programm."""
- self._evt_exit.set()
+ if self.plw is not None:
+ self.plw.stop()
-class RevPiPyLoad(proginit.ProgInit):
+class RevPiPyLoad():
"""Hauptklasse, die alle Funktionen zur Verfuegung stellt.
@@ -321,10 +397,11 @@ class RevPiPyLoad(proginit.ProgInit):
def __init__(self):
"""Instantiiert RevPiPyLoad-Klasse."""
- super().__init__()
+ proginit.configure()
+
self._exit = True
self.evt_loadconfig = Event()
-
+ self.globalconfig = ConfigParser()
self.logr = LogReader()
self.plc = None
self.tfile = {}
@@ -338,6 +415,7 @@ class RevPiPyLoad(proginit.ProgInit):
signal.signal(signal.SIGINT, self._sigexit)
signal.signal(signal.SIGTERM, self._sigexit)
signal.signal(signal.SIGHUP, self._sigloadconfig)
+ signal.signal(signal.SIGUSR1, self._signewlogfile)
def _loadconfig(self):
"""Load configuration file and setup modul."""
@@ -353,9 +431,9 @@ class RevPiPyLoad(proginit.ProgInit):
# Konfigurationsdatei laden
proginit.logger.info(
- "loading config file: {}".format(self.globalconffile)
+ "loading config file: {}".format(proginit.globalconffile)
)
- self.globalconfig.read(self.globalconffile)
+ self.globalconfig.read(proginit.globalconffile)
# Konfiguration verarbeiten
self.autoreload = \
@@ -473,11 +551,29 @@ class RevPiPyLoad(proginit.ProgInit):
proginit.logger.debug("got exit signal")
self.stop()
+ # Programm aufräumen
+ proginit.cleanup()
+
def _sigloadconfig(self, signum, frame):
"""Signal handler to load configuration."""
proginit.logger.debug("got reload config signal")
self.evt_loadconfig.set()
+ def _signewlogfile(self, signum, frame):
+ """Signal handler to start new logfile."""
+ proginit.logger.debug("got new logfile signal")
+
+ # Logger neu konfigurieren
+ proginit.configure()
+ proginit.logger.info("start new logfile: {}".format(asctime()))
+
+ # stdout für revpipyplc
+ if self.plc is not None:
+ self.plc.newlogfile()
+
+ # Logreader schließen
+ self.logr.closeall()
+
def packapp(self, mode="tar", pictory=False):
"""Erzeugt aus dem PLC-Programm ein TAR-File.
@@ -673,9 +769,13 @@ class RevPiPyLoad(proginit.ProgInit):
def xml_plcstop(self):
"""Stoppt das PLC Programm.
- @returns: int() Exitcode vom PLC Programm"""
+
+ @returns: int() Exitcode vom PLC Programm
+ -1 PLC Programm lief nicht
+
+ """
proginit.logger.debug("xmlrpc call plcstop")
- if self.plc is not None:
+ if self.plc is not None and self.plc.is_alive():
self.plc.stop()
self.plc.join()
return self.plc.exitcode
@@ -760,10 +860,10 @@ class RevPiPyLoad(proginit.ProgInit):
self.globalconfig.set("DEFAULT", key, str(dc[key]))
# conf-Datei schreiben
- fh = open(self.globalconffile, "w")
+ fh = open(proginit.globalconffile, "w")
self.globalconfig.write(fh)
proginit.logger.info(
- "got new config and wrote it to {}".format(self.globalconffile)
+ "got new config and wrote it to {}".format(proginit.globalconffile)
)
if loadnow:
diff --git a/setup.py b/setup.py
index d9bcac7..7c7ca4f 100644
--- a/setup.py
+++ b/setup.py
@@ -27,7 +27,7 @@ setup(
license="LGPLv3",
name="revpipyload",
- version="0.2.9",
+ version="0.2.10",
scripts=["data/revpipyload"],