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"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-5.1.dtd"> <!DOCTYPE Project SYSTEM "Project-5.1.dtd">
<!-- eric project file for project revpipyload --> <!-- 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 --> <!-- Copyright (C) 2017 Sven Sager, akira@narux.de -->
<Project version="5.1"> <Project version="5.1">
<Language>en_US</Language> <Language>en_US</Language>
@@ -9,7 +9,7 @@
<ProgLanguage mixed="0">Python3</ProgLanguage> <ProgLanguage mixed="0">Python3</ProgLanguage>
<ProjectType>Console</ProjectType> <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> <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> <Author>Sven Sager</Author>
<Email>akira@narux.de</Email> <Email>akira@narux.de</Email>
<Eol index="-1"/> <Eol index="-1"/>

View File

@@ -35,8 +35,10 @@ import proginit
import os import os
import shlex import shlex
import signal import signal
import socket
import subprocess import subprocess
import tarfile import tarfile
import warnings
import zipfile import zipfile
from concurrent import futures from concurrent import futures
from configparser import ConfigParser from configparser import ConfigParser
@@ -47,13 +49,21 @@ from sys import stdout as sysstdout
from tempfile import mktemp from tempfile import mktemp
from threading import Thread, Event, Lock from threading import Thread, Event, Lock
from time import sleep, asctime from time import sleep, asctime
from timeit import default_timer
from xmlrpc.client import Binary from xmlrpc.client import Binary
from xmlrpc.server import SimpleXMLRPCServer from xmlrpc.server import SimpleXMLRPCServer
configrsc = "/opt/KUNBUS/config.rsc" configrsc = "/opt/KUNBUS/config.rsc"
picontrolreset = "/opt/KUNBUS/piControlReset" picontrolreset = "/opt/KUNBUS/piControlReset"
procimg = "/dev/piControl0" 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(): class LogReader():
@@ -304,7 +314,7 @@ class RevPiPlc(Thread):
elif proginit.pargs.logfile is not None: elif proginit.pargs.logfile is not None:
logfile = proginit.pargs.logfile logfile = proginit.pargs.logfile
if not logfile is None: if logfile is not None:
logfile = PipeLogwriter(logfile) logfile = PipeLogwriter(logfile)
proginit.logger.debug("leave RevPiPlc._configureplw()") proginit.logger.debug("leave RevPiPlc._configureplw()")
@@ -333,12 +343,6 @@ class RevPiPlc(Thread):
proginit.logger.debug("leave RevPiPlc._spopen()") proginit.logger.debug("leave RevPiPlc._spopen()")
return sp 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): def newlogfile(self):
"""Konfiguriert die FileHandler auf neue Logdatei.""" """Konfiguriert die FileHandler auf neue Logdatei."""
proginit.logger.debug("enter RevPiPlc.newlogfile()") proginit.logger.debug("enter RevPiPlc.newlogfile()")
@@ -387,7 +391,7 @@ class RevPiPlc(Thread):
) )
) )
if self.zeroonerror: if self.zeroonerror:
self._zeroprocimg() _zeroprocimg()
proginit.logger.warning( proginit.logger.warning(
"set piControl0 to ZERO after PLC program error") "set piControl0 to ZERO after PLC program error")
@@ -395,7 +399,7 @@ class RevPiPlc(Thread):
# PLC Python Programm sauber beendet # PLC Python Programm sauber beendet
proginit.logger.info("plc program did a clean exit") proginit.logger.info("plc program did a clean exit")
if self.zeroonexit: if self.zeroonexit:
self._zeroprocimg() _zeroprocimg()
proginit.logger.info( proginit.logger.info(
"set piControl0 to ZERO after PLC program returns " "set piControl0 to ZERO after PLC program returns "
"clean exitcode") "clean exitcode")
@@ -457,7 +461,7 @@ class RevPiPlc(Thread):
self.exitcode = self._procplc.poll() self.exitcode = self._procplc.poll()
if self.zeroonexit and self.exitcode == 0 \ if self.zeroonexit and self.exitcode == 0 \
or self.zeroonerror and self.exitcode != 0: or self.zeroonerror and self.exitcode != 0:
self._zeroprocimg() _zeroprocimg()
if self._plw is not None: if self._plw is not None:
self._plw.stop() self._plw.stop()
@@ -468,6 +472,132 @@ class RevPiPlc(Thread):
proginit.logger.debug("leave RevPiPlc.stop()") 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(): class RevPiPyLoad():
"""Hauptklasse, die alle Funktionen zur Verfuegung stellt. """Hauptklasse, die alle Funktionen zur Verfuegung stellt.
@@ -606,7 +736,15 @@ class RevPiPyLoad():
def _plcthread(self): def _plcthread(self):
"""Konfiguriert den PLC-Thread fuer die Ausfuehrung. """Konfiguriert den PLC-Thread fuer die Ausfuehrung.
@returns: PLC-Thread Object or None""" @returns: PLC-Thread Object or None"""
th_plc = None
if self.plcslave:
# Slaveausfuehrung übergeben
th_plc = RevPiSlave()
th_plc.zeroonerror = self.zerooneerror
th_plc.zeroonexit = self.zeroonexit
else:
# Prüfen ob Programm existiert # Prüfen ob Programm existiert
if not os.path.exists(os.path.join(self.plcworkdir, self.plcprog)): if not os.path.exists(os.path.join(self.plcworkdir, self.plcprog)):
proginit.logger.error("plc file does not exists {}".format( proginit.logger.error("plc file does not exists {}".format(
@@ -626,6 +764,7 @@ class RevPiPyLoad():
th_plc.zeroonerror = self.zeroonerror th_plc.zeroonerror = self.zeroonerror
th_plc.zeroonexit = self.zeroonexit th_plc.zeroonexit = self.zeroonexit
proginit.logger.debug("created PLC watcher") proginit.logger.debug("created PLC watcher")
return th_plc return th_plc
def _sigexit(self, signum, frame): def _sigexit(self, signum, frame):

View File

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