mirror of
https://github.com/naruxde/revpipyload.git
synced 2025-11-08 15:13:52 +01:00
xml_plcupload um pictory-flags erweitert
docstrings defaultwerte geändert und für deb vorbereitet pythonversion für plc programm kann angegeben werden
This commit is contained in:
@@ -3,5 +3,5 @@
|
|||||||
# Verbose logging add a -v or -vv
|
# Verbose logging add a -v or -vv
|
||||||
DAEMON_ARGS="-d"
|
DAEMON_ARGS="-d"
|
||||||
|
|
||||||
# Codepage of files
|
# Codepage for Python (do not change)
|
||||||
export LANG=C.UTF-8
|
export LANG=C.UTF-8
|
||||||
|
|||||||
@@ -16,11 +16,18 @@
|
|||||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||||
DESC="RevPiPyLoad to run plc program"
|
DESC="RevPiPyLoad to run plc program"
|
||||||
NAME=revpipyload
|
NAME=revpipyload
|
||||||
DAEMON=/usr/share/revpipyload/revpipyload.py
|
|
||||||
DAEMON_ARGS="-d"
|
DAEMON_ARGS="-d"
|
||||||
PIDFILE=/var/run/$NAME.pid
|
PIDFILE=/var/run/$NAME.pid
|
||||||
SCRIPTNAME=/etc/init.d/$NAME
|
SCRIPTNAME=/etc/init.d/$NAME
|
||||||
|
|
||||||
|
# Check install dir
|
||||||
|
if [ -d /usr/local/share/revpipyload ]
|
||||||
|
then
|
||||||
|
DAEMON=/usr/share/revpipyload/revpipyload.py
|
||||||
|
else
|
||||||
|
DAEMON=/usr/share/revpipyload/revpipyload.py
|
||||||
|
fi
|
||||||
|
|
||||||
# Exit if the package is not installed
|
# Exit if the package is not installed
|
||||||
[ -x "$DAEMON" ] || exit 0
|
[ -x "$DAEMON" ] || exit 0
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ autostart=1
|
|||||||
plcworkdir=/var/lib/revpipyload
|
plcworkdir=/var/lib/revpipyload
|
||||||
plcprogram=program.py
|
plcprogram=program.py
|
||||||
plcslave=0
|
plcslave=0
|
||||||
xmlrpc=1
|
pythonversion=3
|
||||||
|
xmlrpc=0
|
||||||
xmlrpcport=55123
|
xmlrpcport=55123
|
||||||
zeroonerror=1
|
zeroonerror=1
|
||||||
zeroonexit=1
|
zeroonexit=1
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
if [ -d /usr/local/share/revpipyload ]
|
||||||
exec "/usr/share/revpipyload/revpipyload.py" "$@"
|
then
|
||||||
|
exec "/usr/local/share/revpipyload/revpipyload.py" "$@"
|
||||||
|
else
|
||||||
|
exec "/usr/share/revpipyload/revpipyload.py" "$@"
|
||||||
|
fi
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import subprocess
|
|||||||
import tarfile
|
import tarfile
|
||||||
import zipfile
|
import zipfile
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from shutil import rmtree
|
from shutil import rmtree, copyfile
|
||||||
from tempfile import mktemp
|
from tempfile import mktemp
|
||||||
from threading import Thread, Event
|
from threading import Thread, Event
|
||||||
from time import sleep, asctime
|
from time import sleep, asctime
|
||||||
@@ -23,6 +23,7 @@ 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"
|
||||||
procimg = "/dev/piControl0"
|
procimg = "/dev/piControl0"
|
||||||
pyloadverion = "0.2.3"
|
pyloadverion = "0.2.3"
|
||||||
|
|
||||||
@@ -49,10 +50,7 @@ class LogReader():
|
|||||||
"""Gibt neue Zeilen ab letzen Aufruf zurueck.
|
"""Gibt neue Zeilen ab letzen Aufruf zurueck.
|
||||||
@returns: list() mit neuen Zeilen"""
|
@returns: list() mit neuen Zeilen"""
|
||||||
if not os.access(proginit.logapp, os.R_OK):
|
if not os.access(proginit.logapp, os.R_OK):
|
||||||
proginit.logger.error(
|
return []
|
||||||
"can not access logfile {}".format(proginit.logapp)
|
|
||||||
)
|
|
||||||
return None
|
|
||||||
else:
|
else:
|
||||||
if self.fhapp is None or self.fhapp.closed:
|
if self.fhapp is None or self.fhapp.closed:
|
||||||
self.fhapp = open(proginit.logapp)
|
self.fhapp = open(proginit.logapp)
|
||||||
@@ -79,7 +77,7 @@ class LogReader():
|
|||||||
proginit.logger.error(
|
proginit.logger.error(
|
||||||
"can not access logfile {}".format(proginit.logapp)
|
"can not access logfile {}".format(proginit.logapp)
|
||||||
)
|
)
|
||||||
return None
|
return ""
|
||||||
else:
|
else:
|
||||||
if self.fhapp is None or self.fhapp.closed:
|
if self.fhapp is None or self.fhapp.closed:
|
||||||
self.fhapp = open(proginit.logapp)
|
self.fhapp = open(proginit.logapp)
|
||||||
@@ -93,7 +91,7 @@ class LogReader():
|
|||||||
proginit.logger.error(
|
proginit.logger.error(
|
||||||
"can not access logfile {}".format(proginit.logplc)
|
"can not access logfile {}".format(proginit.logplc)
|
||||||
)
|
)
|
||||||
return None
|
return []
|
||||||
else:
|
else:
|
||||||
if self.fhplc is None or self.fhplc.closed:
|
if self.fhplc is None or self.fhplc.closed:
|
||||||
self.fhplc = open(proginit.logplc)
|
self.fhplc = open(proginit.logplc)
|
||||||
@@ -120,7 +118,7 @@ class LogReader():
|
|||||||
proginit.logger.error(
|
proginit.logger.error(
|
||||||
"can not access logfile {}".format(proginit.logplc)
|
"can not access logfile {}".format(proginit.logplc)
|
||||||
)
|
)
|
||||||
return None
|
return ""
|
||||||
else:
|
else:
|
||||||
if self.fhplc is None or self.fhplc.closed:
|
if self.fhplc is None or self.fhplc.closed:
|
||||||
self.fhplc = open(proginit.logplc)
|
self.fhplc = open(proginit.logplc)
|
||||||
@@ -130,7 +128,7 @@ class LogReader():
|
|||||||
|
|
||||||
class RevPiPlc(Thread):
|
class RevPiPlc(Thread):
|
||||||
|
|
||||||
def __init__(self, program):
|
def __init__(self, program, pversion):
|
||||||
"""Instantiiert RevPiPlc-Klasse."""
|
"""Instantiiert RevPiPlc-Klasse."""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.autoreload = False
|
self.autoreload = False
|
||||||
@@ -138,6 +136,7 @@ class RevPiPlc(Thread):
|
|||||||
self.exitcode = None
|
self.exitcode = None
|
||||||
self._program = program
|
self._program = program
|
||||||
self._procplc = None
|
self._procplc = None
|
||||||
|
self._pversion = pversion
|
||||||
self.zeroonerror = False
|
self.zeroonerror = False
|
||||||
self.zeroonexit = False
|
self.zeroonexit = False
|
||||||
|
|
||||||
@@ -146,11 +145,13 @@ class RevPiPlc(Thread):
|
|||||||
if os.path.exists("/dev/piControl0"):
|
if os.path.exists("/dev/piControl0"):
|
||||||
f = open("/dev/piControl0", "w+b", 0)
|
f = open("/dev/piControl0", "w+b", 0)
|
||||||
f.write(bytes(4096))
|
f.write(bytes(4096))
|
||||||
proginit.logger.warning("set piControl0 to ZERO")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""Fuehrt PLC-Programm aus und ueberwacht es."""
|
"""Fuehrt PLC-Programm aus und ueberwacht es."""
|
||||||
lst_proc = shlex.split("/usr/bin/env python3 -u " + self._program)
|
if self._pversion == 2:
|
||||||
|
lst_proc = shlex.split("/usr/bin/env python2 -u " + self._program)
|
||||||
|
else:
|
||||||
|
lst_proc = shlex.split("/usr/bin/env python3 -u " + self._program)
|
||||||
|
|
||||||
# Ausgaben konfigurieren und ggf. umleiten
|
# Ausgaben konfigurieren und ggf. umleiten
|
||||||
fh = None
|
fh = None
|
||||||
@@ -169,7 +170,8 @@ class RevPiPlc(Thread):
|
|||||||
# Prozess erstellen
|
# Prozess erstellen
|
||||||
proginit.logger.info("start plc program {}".format(self._program))
|
proginit.logger.info("start plc program {}".format(self._program))
|
||||||
self._procplc = subprocess.Popen(
|
self._procplc = subprocess.Popen(
|
||||||
lst_proc, bufsize=1, stdout=fh, stderr=subprocess.STDOUT
|
lst_proc, cwd=os.path.dirname(self._program),
|
||||||
|
bufsize=1, stdout=fh, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
|
|
||||||
while not self._evt_exit.is_set():
|
while not self._evt_exit.is_set():
|
||||||
@@ -188,18 +190,23 @@ class RevPiPlc(Thread):
|
|||||||
)
|
)
|
||||||
if self.zeroonerror:
|
if self.zeroonerror:
|
||||||
self._zeroprocimg()
|
self._zeroprocimg()
|
||||||
|
proginit.logger.warning(
|
||||||
|
"set piControl0 to ZERO after PLC program error")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# 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()
|
self._zeroprocimg()
|
||||||
|
proginit.logger.info(
|
||||||
|
"set piControl0 to ZERO after PLC program returns "
|
||||||
|
"clean exitcode")
|
||||||
|
|
||||||
if not self._evt_exit.is_set() and self.autoreload:
|
if not self._evt_exit.is_set() and self.autoreload:
|
||||||
# Prozess neu starten
|
# Prozess neu starten
|
||||||
self._procplc = subprocess.Popen(
|
self._procplc = subprocess.Popen(
|
||||||
lst_proc, bufsize=1, stdout=fh,
|
lst_proc, cwd=os.path.dirname(self._program),
|
||||||
stderr=subprocess.STDOUT
|
bufsize=1, stdout=fh, stderr=subprocess.STDOUT
|
||||||
)
|
)
|
||||||
if self.exitcode == 0:
|
if self.exitcode == 0:
|
||||||
proginit.logger.warning(
|
proginit.logger.warning(
|
||||||
@@ -217,6 +224,7 @@ class RevPiPlc(Thread):
|
|||||||
# Prozess beenden
|
# Prozess beenden
|
||||||
count = 0
|
count = 0
|
||||||
proginit.logger.info("term plc program {}".format(self._program))
|
proginit.logger.info("term plc program {}".format(self._program))
|
||||||
|
# TODO: Prüfen ob es überhautp noch läuft
|
||||||
self._procplc.terminate()
|
self._procplc.terminate()
|
||||||
while self._procplc.poll() is None and count < 10:
|
while self._procplc.poll() is None and count < 10:
|
||||||
count += 1
|
count += 1
|
||||||
@@ -288,16 +296,15 @@ class RevPiPyLoad(proginit.ProgInit):
|
|||||||
self.autostart = int(self.globalconfig["DEFAULT"].get("autostart", 0))
|
self.autostart = int(self.globalconfig["DEFAULT"].get("autostart", 0))
|
||||||
self.plcprog = self.globalconfig["DEFAULT"].get("plcprogram", None)
|
self.plcprog = self.globalconfig["DEFAULT"].get("plcprogram", None)
|
||||||
self.plcworkdir = self.globalconfig["DEFAULT"].get(
|
self.plcworkdir = self.globalconfig["DEFAULT"].get(
|
||||||
"plcworkdir", "/var/lib/revpipyload"
|
"plcworkdir", "/var/lib/revpipyload")
|
||||||
)
|
|
||||||
self.plcslave = int(self.globalconfig["DEFAULT"].get("plcslave", 0))
|
self.plcslave = int(self.globalconfig["DEFAULT"].get("plcslave", 0))
|
||||||
|
self.pythonver = int(
|
||||||
|
self.globalconfig["DEFAULT"].get("pythonversion", 3))
|
||||||
self.xmlrpc = int(self.globalconfig["DEFAULT"].get("xmlrpc", 1))
|
self.xmlrpc = int(self.globalconfig["DEFAULT"].get("xmlrpc", 1))
|
||||||
self.zerooneerror = int(
|
self.zerooneerror = int(
|
||||||
self.globalconfig["DEFAULT"].get("zeroonerror", 1)
|
self.globalconfig["DEFAULT"].get("zeroonerror", 1))
|
||||||
)
|
|
||||||
self.zeroonexit = int(
|
self.zeroonexit = int(
|
||||||
self.globalconfig["DEFAULT"].get("zeroonexit", 1)
|
self.globalconfig["DEFAULT"].get("zeroonexit", 1))
|
||||||
)
|
|
||||||
|
|
||||||
# Workdirectory wechseln
|
# Workdirectory wechseln
|
||||||
os.chdir(self.plcworkdir)
|
os.chdir(self.plcworkdir)
|
||||||
@@ -361,7 +368,8 @@ class RevPiPyLoad(proginit.ProgInit):
|
|||||||
return
|
return
|
||||||
|
|
||||||
proginit.logger.debug("create PLC watcher")
|
proginit.logger.debug("create PLC watcher")
|
||||||
th_plc = RevPiPlc(os.path.join(self.plcworkdir, self.plcprog))
|
th_plc = RevPiPlc(
|
||||||
|
os.path.join(self.plcworkdir, self.plcprog), self.pythonver)
|
||||||
th_plc.autoreload = self.autoreload
|
th_plc.autoreload = self.autoreload
|
||||||
th_plc.zeroonerror = self.zerooneerror
|
th_plc.zeroonerror = self.zerooneerror
|
||||||
th_plc.zeroonexit = self.zeroonexit
|
th_plc.zeroonexit = self.zeroonexit
|
||||||
@@ -369,7 +377,7 @@ class RevPiPyLoad(proginit.ProgInit):
|
|||||||
return th_plc
|
return th_plc
|
||||||
|
|
||||||
def _sigexit(self, signum, frame):
|
def _sigexit(self, signum, frame):
|
||||||
"""Signal handler to clean an exit program."""
|
"""Signal handler to clean and exit program."""
|
||||||
proginit.logger.debug("got exit signal")
|
proginit.logger.debug("got exit signal")
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
@@ -378,19 +386,28 @@ class RevPiPyLoad(proginit.ProgInit):
|
|||||||
proginit.logger.debug("got reload config signal")
|
proginit.logger.debug("got reload config signal")
|
||||||
self.evt_loadconfig.set()
|
self.evt_loadconfig.set()
|
||||||
|
|
||||||
def packapp(self, mode="tar"):
|
def packapp(self, mode="tar", pictory=False):
|
||||||
"""Erzeugt aus dem PLC-Programm ein TAR-File."""
|
"""Erzeugt aus dem PLC-Programm ein TAR-File.
|
||||||
|
@param mode: Packart 'tar' oder 'zip'
|
||||||
|
@param pictory: piCtory Konfiguration mit einpacken"""
|
||||||
filename = mktemp(suffix=".packed", prefix="plc")
|
filename = mktemp(suffix=".packed", prefix="plc")
|
||||||
# try:
|
# TODO: Fehlerabfang
|
||||||
if mode == "zip":
|
if mode == "zip":
|
||||||
fh_pack = zipfile.ZipFile(filename, mode="w")
|
fh_pack = zipfile.ZipFile(filename, mode="w")
|
||||||
wd = os.walk("./")
|
wd = os.walk("./")
|
||||||
for tup_dir in wd:
|
for tup_dir in wd:
|
||||||
for file in tup_dir[2]:
|
for file in tup_dir[2]:
|
||||||
fh_pack.write(os.path.join(tup_dir[0], file)[2:])
|
arcname = os.path.join(
|
||||||
|
os.path.basename(self.plcworkdir), tup_dir[0][2:], file)
|
||||||
|
fh_pack.write(os.path.join(tup_dir[0], file), arcname=arcname)
|
||||||
|
if pictory:
|
||||||
|
fh_pack.write(configrsc, arcname="config.rsc")
|
||||||
else:
|
else:
|
||||||
fh_pack = tarfile.open(name=filename, mode="w:gz")
|
fh_pack = tarfile.open(
|
||||||
fh_pack.add(".")
|
name=filename, mode="w:gz", dereference=True)
|
||||||
|
fh_pack.add(".", arcname=os.path.basename(self.plcworkdir))
|
||||||
|
if pictory:
|
||||||
|
fh_pack.add(configrsc, arcname="config.rsc")
|
||||||
fh_pack.close()
|
fh_pack.close()
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
@@ -458,23 +475,25 @@ class RevPiPyLoad(proginit.ProgInit):
|
|||||||
return lst_file
|
return lst_file
|
||||||
|
|
||||||
def xml_getpictoryrsc(self):
|
def xml_getpictoryrsc(self):
|
||||||
"""Gibt die config.rsc Datei von piCotry zurueck."""
|
"""Gibt die config.rsc Datei von piCotry zurueck.
|
||||||
|
@returns: xmlrpc.client.Binary()"""
|
||||||
proginit.logger.debug("xmlrpc call getpictoryrsc")
|
proginit.logger.debug("xmlrpc call getpictoryrsc")
|
||||||
with open(configrsc, "rb") as fh:
|
with open(configrsc, "rb") as fh:
|
||||||
buff = fh.read()
|
buff = fh.read()
|
||||||
return Binary(buff)
|
return Binary(buff)
|
||||||
|
|
||||||
def xml_getprocimg(self):
|
def xml_getprocimg(self):
|
||||||
"""Gibt die Rohdaten aus piControl0 zurueck."""
|
"""Gibt die Rohdaten aus piControl0 zurueck.
|
||||||
|
@returns: xmlrpc.client.Binary()"""
|
||||||
proginit.logger.debug("xmlrpc call getprocimg")
|
proginit.logger.debug("xmlrpc call getprocimg")
|
||||||
with open(procimg, "rb") as fh:
|
with open(procimg, "rb") as fh:
|
||||||
buff = fh.read()
|
buff = fh.read()
|
||||||
return Binary(buff)
|
return Binary(buff)
|
||||||
|
|
||||||
def xml_plcdownload(self, mode="tar"):
|
def xml_plcdownload(self, mode="tar", pictory=False):
|
||||||
proginit.logger.debug("xmlrpc call plcdownload")
|
proginit.logger.debug("xmlrpc call plcdownload")
|
||||||
# TODO: Daten blockweise übertragen
|
# TODO: Daten blockweise übertragen
|
||||||
file = self.packapp(mode)
|
file = self.packapp(mode, pictory)
|
||||||
if os.path.exists(file):
|
if os.path.exists(file):
|
||||||
fh = open(file, "rb")
|
fh = open(file, "rb")
|
||||||
xmldata = Binary(fh.read())
|
xmldata = Binary(fh.read())
|
||||||
@@ -516,7 +535,7 @@ class RevPiPyLoad(proginit.ProgInit):
|
|||||||
else:
|
else:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
def xml_plcupload(self, filedata):
|
def xml_plcupload(self, filedata, pictory=False, reset=False):
|
||||||
proginit.logger.debug("xmlrpc call plcupload")
|
proginit.logger.debug("xmlrpc call plcupload")
|
||||||
# TODO: Daten blockweise annehmen
|
# TODO: Daten blockweise annehmen
|
||||||
if filedata is None:
|
if filedata is None:
|
||||||
@@ -533,17 +552,36 @@ class RevPiPyLoad(proginit.ProgInit):
|
|||||||
if tarfile.is_tarfile(filename):
|
if tarfile.is_tarfile(filename):
|
||||||
fh_pack = tarfile.open(filename)
|
fh_pack = tarfile.open(filename)
|
||||||
elif zipfile.is_zipfile(filename):
|
elif zipfile.is_zipfile(filename):
|
||||||
fh_pack = zipfile.open(filename)
|
fh_pack = zipfile.ZipFile.open(filename)
|
||||||
|
|
||||||
if fh_pack is not None:
|
if fh_pack is not None:
|
||||||
fh_pack.extractall()
|
fh_pack.extractall(".")
|
||||||
fh_pack.close()
|
fh_pack.close()
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
return True
|
|
||||||
|
if pictory and os.path.exists("./config.rsc"):
|
||||||
|
try:
|
||||||
|
# Nur Daten kopieren damit Eigenschaften gleich bleiben
|
||||||
|
copyfile("./config.rsc", configrsc)
|
||||||
|
os.remove("./config.rsc")
|
||||||
|
except:
|
||||||
|
return -3
|
||||||
|
else:
|
||||||
|
if reset:
|
||||||
|
return os.system(picontrolreset)
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
elif pictory:
|
||||||
|
return -2
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Sauber
|
||||||
|
return 0
|
||||||
|
|
||||||
# Kein Archiv
|
# Kein Archiv
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
return False
|
return -1
|
||||||
|
|
||||||
def xml_plcuploadclean(self):
|
def xml_plcuploadclean(self):
|
||||||
proginit.logger.debug("xmlrpc call plcuploadclean")
|
proginit.logger.debug("xmlrpc call plcuploadclean")
|
||||||
@@ -587,7 +625,13 @@ class RevPiPyLoad(proginit.ProgInit):
|
|||||||
self.evt_loadconfig.set()
|
self.evt_loadconfig.set()
|
||||||
|
|
||||||
def xml_setpictoryrsc(self, filebytes, reset=False):
|
def xml_setpictoryrsc(self, filebytes, reset=False):
|
||||||
"""Schreibt die config.rsc Datei von piCotry."""
|
"""Schreibt die config.rsc Datei von piCotry.
|
||||||
|
|
||||||
|
@param filebytes: xmlrpc.client.Binary()-Objekt
|
||||||
|
@param reset: Reset piControl Device
|
||||||
|
@returns: Statuscode
|
||||||
|
|
||||||
|
"""
|
||||||
proginit.logger.debug("xmlrpc call setpictoryrsc")
|
proginit.logger.debug("xmlrpc call setpictoryrsc")
|
||||||
try:
|
try:
|
||||||
with open(configrsc, "wb") as fh:
|
with open(configrsc, "wb") as fh:
|
||||||
@@ -596,7 +640,7 @@ class RevPiPyLoad(proginit.ProgInit):
|
|||||||
return -1
|
return -1
|
||||||
else:
|
else:
|
||||||
if reset:
|
if reset:
|
||||||
return os.system("/opt/KUNBUS/piControlReset")
|
return os.system(picontrolreset)
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -44,7 +44,7 @@ setup(
|
|||||||
long_description=""
|
long_description=""
|
||||||
"Dieses Programm startet beim Systemstart ein angegebenes Python PLC\n"
|
"Dieses Programm startet beim Systemstart ein angegebenes Python PLC\n"
|
||||||
"Programm. Es überwacht das Programm und startet es im Fehlerfall neu.\n"
|
"Programm. Es überwacht das Programm und startet es im Fehlerfall neu.\n"
|
||||||
"Bei Abstruz kann das gesamte /dev/piControl0 auf 0x00 gesettz werden.\n"
|
"Bei Absturz kann das gesamte /dev/piControl0 auf 0x00 gesetzt werden.\n"
|
||||||
"Außerdem stellt es einen XML-RPC Server bereit, über den die Software\n"
|
"Außerdem stellt es einen XML-RPC Server bereit, über den die Software\n"
|
||||||
"auf den RevPi geladen werden kann. Das Prozessabbild kann über ein Tool\n"
|
"auf den RevPi geladen werden kann. Das Prozessabbild kann über ein Tool\n"
|
||||||
"zur Laufzeit überwacht werden.",
|
"zur Laufzeit überwacht werden.",
|
||||||
|
|||||||
Reference in New Issue
Block a user