Verschmelzung mit default

This commit is contained in:
2017-03-28 11:14:58 +02:00
4 changed files with 171 additions and 32 deletions

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 revpipyload -->
<!-- Saved: 2017-03-28, 10:07:15 -->
<!-- Saved: 2017-03-27, 10:26:18 -->
<!-- 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>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.</Description>
<Version>0.2.11</Version>
<Version>0.3.0</Version>
<Author>Sven Sager</Author>
<Email>akira@narux.de</Email>
<Eol index="-1"/>

View File

@@ -63,7 +63,7 @@ def configure():
pargs.conffile = os.path.join(startdir, pargs.conffile)
if pargs.logfile is not None and os.path.dirname(pargs.logfile) == "":
pargs.logfile = os.path.join(startdir, pargs.logfile)
# Prüfen ob als Daemon ausgeführt werden soll
global forked
pidfile = "/var/run/revpipyload.pid"

View File

@@ -35,8 +35,10 @@ import proginit
import os
import shlex
import signal
import socket
import subprocess
import tarfile
import warnings
import zipfile
from concurrent import futures
from configparser import ConfigParser
@@ -47,13 +49,21 @@ from sys import stdout as sysstdout
from tempfile import mktemp
from threading import Thread, Event, Lock
from time import sleep, asctime
from timeit import default_timer
from xmlrpc.client import Binary
from xmlrpc.server import SimpleXMLRPCServer
configrsc = "/opt/KUNBUS/config.rsc"
picontrolreset = "/opt/KUNBUS/piControlReset"
procimg = "/dev/piControl0"
pyloadverion = "0.2.11"
pyloadverion = "0.3.0"
def _zeroprocimg():
"""Setzt Prozessabbild auf NULL."""
if os.path.exists(procimg):
f = open(procimg, "w+b", 0)
f.write(bytes(4096))
class LogReader():
@@ -304,7 +314,7 @@ class RevPiPlc(Thread):
elif proginit.pargs.logfile is not None:
logfile = proginit.pargs.logfile
if not logfile is None:
if logfile is not None:
logfile = PipeLogwriter(logfile)
proginit.logger.debug("leave RevPiPlc._configureplw()")
@@ -333,12 +343,6 @@ class RevPiPlc(Thread):
proginit.logger.debug("leave RevPiPlc._spopen()")
return sp
def _zeroprocimg(self):
"""Setzt Prozessabbild auf NULL."""
if os.path.exists("/dev/piControl0"):
f = open("/dev/piControl0", "w+b", 0)
f.write(bytes(4096))
def newlogfile(self):
"""Konfiguriert die FileHandler auf neue Logdatei."""
proginit.logger.debug("enter RevPiPlc.newlogfile()")
@@ -387,7 +391,7 @@ class RevPiPlc(Thread):
)
)
if self.zeroonerror:
self._zeroprocimg()
_zeroprocimg()
proginit.logger.warning(
"set piControl0 to ZERO after PLC program error")
@@ -395,7 +399,7 @@ class RevPiPlc(Thread):
# PLC Python Programm sauber beendet
proginit.logger.info("plc program did a clean exit")
if self.zeroonexit:
self._zeroprocimg()
_zeroprocimg()
proginit.logger.info(
"set piControl0 to ZERO after PLC program returns "
"clean exitcode")
@@ -457,7 +461,7 @@ class RevPiPlc(Thread):
self.exitcode = self._procplc.poll()
if self.zeroonexit and self.exitcode == 0 \
or self.zeroonerror and self.exitcode != 0:
self._zeroprocimg()
_zeroprocimg()
if self._plw is not None:
self._plw.stop()
@@ -468,6 +472,132 @@ class RevPiPlc(Thread):
proginit.logger.debug("leave RevPiPlc.stop()")
class RevPiSlave(Thread):
def __init__(self):
"""Instantiiert RevPiSlave-Klasse."""
super().__init__()
self.deadtime = 0.5
self._evt_exit = Event()
self.zeroonerror = False
self.zeroonexit = False
def run(self):
proginit.logger.debug("enter RevPiSlave.run()")
msgcli = [b'DATA', b'PICT', b'SEND']
# Socket öffnen und konfigurieren
self.so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while not self._evt_exit.is_set():
try:
self.so.bind(("", 55234))
except:
warnings.warn("can not bind socket - retry", Warning)
self._evt_exit.wait(1)
else:
break
self.so.listen(1)
self.rpi = None
while not self._evt_exit.is_set():
# Verbindung annehmen
proginit.logger.info("starte accept")
try:
self.rpi, addr = self.so.accept()
except:
proginit.logger.exception("after accept")
continue
# Prozessabbild öffnen
fh_proc = open(procimg, "r+b", 0)
# Erste Meldung erhalten
meldung = self.rpi.recv(12)
comtime = 0
while meldung[:4] in msgcli:
ot = default_timer()
# Meldung zerlegen
command = meldung[:4]
try:
startval = int(meldung[4:-4])
except:
startval = 0
try:
lenval = int(meldung[-4:])
except:
lenval = 0
if command == b'PICT':
# piCtory Konfiguration senden
proginit.logger.debug("transfair pictory configuration")
fh_pic = open(configrsc, "rb")
while True:
data = fh_pic.read(1024)
if data:
self.rpi.send(data)
else:
fh_pic.close()
break
# Abschlussmeldung
self.rpi.send(b'PICOK')
if command == b'DATA':
# Processabbild übertragen
bcount = 0
blength = lenval
fh_proc.seek(startval)
while bcount < blength:
self.rpi.send(fh_proc.read(1024))
bcount += 1024
if command == b'SEND':
# Ausgänge empfangen
block = self.rpi.recv(lenval)
fh_proc.seek(startval)
fh_proc.write(block)
# Nächste Meldung erhalten
meldung = self.rpi.recv(12)
# Verarbeitungszeit prüfen
comtime = default_timer() - ot
if comtime > self.deadtime:
proginit.logger.error(
"runtime more than {} ms: {}".format(
int(self.deadtime * 1000), int(comtime * 1000)
)
)
break
fh_proc.close()
self.rpi.shutdown(socket.SHUT_RDWR)
self.rpi.close()
if self.zeroonexit or comtime > self.deadtime and self.zeroonerror:
_zeroprocimg()
# Socket schließen
self.so.close()
proginit.logger.debug("leave RevPiSlave.run()")
def stop(self):
"""Beendet Slaveausfuehrung."""
proginit.logger.debug("enter RevPiSlave.stop()")
self._evt_exit.set()
if self.rpi is not None:
self.rpi.close()
self.so.shutdown(socket.SHUT_RDWR)
proginit.logger.debug("leave RevPiSlave.stop()")
class RevPiPyLoad():
"""Hauptklasse, die alle Funktionen zur Verfuegung stellt.
@@ -606,26 +736,35 @@ class RevPiPyLoad():
def _plcthread(self):
"""Konfiguriert den PLC-Thread fuer die Ausfuehrung.
@returns: PLC-Thread Object or None"""
th_plc = None
# Prüfen ob Programm existiert
if not os.path.exists(os.path.join(self.plcworkdir, self.plcprog)):
proginit.logger.error("plc file does not exists {}".format(
os.path.join(self.plcworkdir, self.plcprog)
))
return None
if self.plcslave:
# Slaveausfuehrung übergeben
th_plc = RevPiSlave()
th_plc.zeroonerror = self.zerooneerror
th_plc.zeroonexit = self.zeroonexit
proginit.logger.debug("create PLC watcher")
th_plc = RevPiPlc(
os.path.join(self.plcworkdir, self.plcprog),
self.plcarguments,
self.pythonver
)
th_plc.autoreload = self.autoreload
th_plc.gid = int(self.globalconfig["DEFAULT"].get("plcgid", 65534))
th_plc.uid = int(self.globalconfig["DEFAULT"].get("plcuid", 65534))
else:
# Prüfen ob Programm existiert
if not os.path.exists(os.path.join(self.plcworkdir, self.plcprog)):
proginit.logger.error("plc file does not exists {}".format(
os.path.join(self.plcworkdir, self.plcprog)
))
return None
proginit.logger.debug("create PLC watcher")
th_plc = RevPiPlc(
os.path.join(self.plcworkdir, self.plcprog),
self.plcarguments,
self.pythonver
)
th_plc.autoreload = self.autoreload
th_plc.gid = int(self.globalconfig["DEFAULT"].get("plcgid", 65534))
th_plc.uid = int(self.globalconfig["DEFAULT"].get("plcuid", 65534))
th_plc.zeroonerror = self.zeroonerror
th_plc.zeroonexit = self.zeroonexit
proginit.logger.debug("created PLC watcher")
th_plc.zeroonexit = self.zeroonexit
proginit.logger.debug("created PLC watcher")
return th_plc
def _sigexit(self, signum, frame):

View File

@@ -27,7 +27,7 @@ setup(
license="LGPLv3",
name="revpipyload",
version="0.2.11",
version="0.3.0",
scripts=["data/revpipyload"],