mirror of
https://github.com/naruxde/revpipyload.git
synced 2025-11-08 15:13:52 +01:00
bindip für PlcSlave wird jetzt verarbeitet
Fehlerabfang bei piCtory-Übertragung IOCTL über das Netzwerk implementiert Parameter --developermode implementiert
This commit is contained in:
@@ -5,6 +5,7 @@ __copyright__ = "Copyright (C) 2018 Sven Sager"
|
|||||||
__license__ = "GPLv3"
|
__license__ = "GPLv3"
|
||||||
import proginit
|
import proginit
|
||||||
import socket
|
import socket
|
||||||
|
from fcntl import ioctl
|
||||||
from shared.ipaclmanager import IpAclManager
|
from shared.ipaclmanager import IpAclManager
|
||||||
from threading import Event, Thread
|
from threading import Event, Thread
|
||||||
from timeit import default_timer
|
from timeit import default_timer
|
||||||
@@ -16,23 +17,32 @@ class RevPiSlave(Thread):
|
|||||||
"""RevPi PLC-Server.
|
"""RevPi PLC-Server.
|
||||||
|
|
||||||
Diese Klasste stellt den RevPi PLC-Server zur verfuegung und akzeptiert
|
Diese Klasste stellt den RevPi PLC-Server zur verfuegung und akzeptiert
|
||||||
neue Verbindungen. Dieser werden dann als RevPiSlaveDev abgebildet.
|
neue Verbindungen. Diese werden dann als RevPiSlaveDev abgebildet.
|
||||||
|
|
||||||
Ueber die angegebenen ACLs koennen Zugriffsbeschraenkungen vergeben werden.
|
Ueber die angegebenen ACLs koennen Zugriffsbeschraenkungen vergeben werden.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, ipacl, port=55234):
|
def __init__(self, ipacl, port=55234, bindip=""):
|
||||||
"""Instantiiert RevPiSlave-Klasse.
|
"""Instantiiert RevPiSlave-Klasse.
|
||||||
|
|
||||||
@param ipacl AclManager <class 'IpAclManager'>
|
@param ipacl AclManager <class 'IpAclManager'>
|
||||||
@param port Listen Port fuer plc Slaveserver"""
|
@param port Listen Port fuer plc Slaveserver
|
||||||
if not type(ipacl) == IpAclManager:
|
@param bindip IP-Adresse an die der Dienst gebunden wird (leer=alle)
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not isinstance(ipacl, IpAclManager):
|
||||||
raise ValueError("parameter ipacl must be <class 'IpAclManager'>")
|
raise ValueError("parameter ipacl must be <class 'IpAclManager'>")
|
||||||
if not type(port) == int:
|
if not (isinstance(port, int) and 0 < port <= 65535):
|
||||||
raise ValueError("parameter port must be <class 'int'>")
|
raise ValueError(
|
||||||
|
"parameter port must be <class 'int'> and in range 1 - 65535"
|
||||||
|
)
|
||||||
|
if not isinstance(bindip, str):
|
||||||
|
raise ValueError("parameter bindip must be <class 'str'>")
|
||||||
|
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.__ipacl = ipacl
|
self.__ipacl = ipacl
|
||||||
|
self._bindip = bindip
|
||||||
self._evt_exit = Event()
|
self._evt_exit = Event()
|
||||||
self.exitcode = None
|
self.exitcode = None
|
||||||
self._port = port
|
self._port = port
|
||||||
@@ -68,17 +78,19 @@ class RevPiSlave(Thread):
|
|||||||
"""Startet Serverkomponente fuer die Annahme neuer Verbindungen."""
|
"""Startet Serverkomponente fuer die Annahme neuer Verbindungen."""
|
||||||
proginit.logger.debug("enter RevPiSlave.run()")
|
proginit.logger.debug("enter RevPiSlave.run()")
|
||||||
|
|
||||||
# Socket öffnen und konfigurieren
|
# Socket öffnen und konfigurieren bis Erfolg oder Ende
|
||||||
self.so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
while not self._evt_exit.is_set():
|
while not self._evt_exit.is_set():
|
||||||
try:
|
try:
|
||||||
self.so.bind(("", self._port))
|
self.so.bind((self._bindip, self._port))
|
||||||
except Exception:
|
except Exception as e:
|
||||||
proginit.logger.warning("can not bind socket - retry")
|
proginit.logger.warning(
|
||||||
|
"can not bind socket: {0} - retry".format(e)
|
||||||
|
)
|
||||||
self._evt_exit.wait(1)
|
self._evt_exit.wait(1)
|
||||||
else:
|
else:
|
||||||
|
self.so.listen(15)
|
||||||
break
|
break
|
||||||
self.so.listen(15)
|
|
||||||
|
|
||||||
# Mit Socket arbeiten
|
# Mit Socket arbeiten
|
||||||
while not self._evt_exit.is_set():
|
while not self._evt_exit.is_set():
|
||||||
@@ -156,6 +168,7 @@ class RevPiSlaveDev(Thread):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
self.__doerror = False
|
||||||
self._acl = acl
|
self._acl = acl
|
||||||
self.daemon = True
|
self.daemon = True
|
||||||
self._deadtime = None
|
self._deadtime = None
|
||||||
@@ -273,7 +286,7 @@ class RevPiSlaveDev(Thread):
|
|||||||
proginit.logger.error("can not convert timeout value")
|
proginit.logger.error("can not convert timeout value")
|
||||||
break
|
break
|
||||||
|
|
||||||
if 0 < timeoutms < 65535:
|
if 0 < timeoutms <= 65535:
|
||||||
self._deadtime = timeoutms / 1000
|
self._deadtime = timeoutms / 1000
|
||||||
self._devcon.settimeout(self._deadtime)
|
self._devcon.settimeout(self._deadtime)
|
||||||
proginit.logger.debug(
|
proginit.logger.debug(
|
||||||
@@ -300,12 +313,14 @@ class RevPiSlaveDev(Thread):
|
|||||||
length = int.from_bytes(netcmd[5:7], byteorder="little")
|
length = int.from_bytes(netcmd[5:7], byteorder="little")
|
||||||
control = netcmd[7:8]
|
control = netcmd[7:8]
|
||||||
|
|
||||||
|
ok_byte = b'\xff' if self.__doerror else b'\x1e'
|
||||||
|
|
||||||
if control == b'\xff':
|
if control == b'\xff':
|
||||||
# Alle Dirtybytes löschen
|
# Alle Dirtybytes löschen
|
||||||
self.ey_dict = {}
|
self.ey_dict = {}
|
||||||
|
|
||||||
# Record seperator character
|
# Record seperator character
|
||||||
self._devcon.send(b'\x1e')
|
self._devcon.send(ok_byte)
|
||||||
proginit.logger.info("cleared all dirty bytes")
|
proginit.logger.info("cleared all dirty bytes")
|
||||||
|
|
||||||
elif control == b'\xfe':
|
elif control == b'\xfe':
|
||||||
@@ -315,7 +330,7 @@ class RevPiSlaveDev(Thread):
|
|||||||
del self.ey_dict[position]
|
del self.ey_dict[position]
|
||||||
|
|
||||||
# Record seperator character
|
# Record seperator character
|
||||||
self._devcon.send(b'\x1e')
|
self._devcon.send(ok_byte)
|
||||||
proginit.logger.info(
|
proginit.logger.info(
|
||||||
"cleared dirty bytes on position {0}"
|
"cleared dirty bytes on position {0}"
|
||||||
"".format(position)
|
"".format(position)
|
||||||
@@ -344,7 +359,7 @@ class RevPiSlaveDev(Thread):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# Record seperator character
|
# Record seperator character
|
||||||
self._devcon.send(b'\x1e')
|
self._devcon.send(ok_byte)
|
||||||
proginit.logger.info(
|
proginit.logger.info(
|
||||||
"got dirty bytes to write on error on position {0}"
|
"got dirty bytes to write on error on position {0}"
|
||||||
"".format(position)
|
"".format(position)
|
||||||
@@ -356,19 +371,20 @@ class RevPiSlaveDev(Thread):
|
|||||||
"transfair pictory configuration: {0}"
|
"transfair pictory configuration: {0}"
|
||||||
"".format(proginit.pargs.configrsc)
|
"".format(proginit.pargs.configrsc)
|
||||||
)
|
)
|
||||||
fh_pic = open(proginit.pargs.configrsc, "rb")
|
try:
|
||||||
while True:
|
with open(proginit.pargs.configrsc, "rb") as fh_pic:
|
||||||
data = fh_pic.read(1024)
|
# Komplette piCtory Datei senden
|
||||||
if data:
|
self._devcon.sendall(fh_pic.read())
|
||||||
# FIXME: Fehler fangen
|
except Exception as e:
|
||||||
self._devcon.send(data)
|
proginit.logger.error(
|
||||||
else:
|
"error on pictory transfair: {0}".format(e)
|
||||||
fh_pic.close()
|
)
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
# End-of-Transmission character
|
continue
|
||||||
self._devcon.send(b'\x04')
|
finally:
|
||||||
continue
|
# End-of-Transmission character immer senden
|
||||||
|
self._devcon.send(b'\x04')
|
||||||
|
|
||||||
elif cmd == b'EX':
|
elif cmd == b'EX':
|
||||||
# Sauber Verbindung verlassen
|
# Sauber Verbindung verlassen
|
||||||
@@ -376,8 +392,68 @@ class RevPiSlaveDev(Thread):
|
|||||||
self._evt_exit.set()
|
self._evt_exit.set()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
elif cmd == b'IC':
|
||||||
|
# Net-IOCTL ausführen
|
||||||
|
# bCMiiiiii000000b = 16
|
||||||
|
|
||||||
|
request = int.from_bytes(netcmd[3:7], byteorder="little")
|
||||||
|
length = int.from_bytes(netcmd[7:9], byteorder="little")
|
||||||
|
|
||||||
|
arg = self._devcon.recv(length)
|
||||||
|
|
||||||
|
# Berechtigung prüfen und ggf. trennen
|
||||||
|
if self._acl < 1:
|
||||||
|
self._devcon.send(b'\x18')
|
||||||
|
break
|
||||||
|
|
||||||
|
try:
|
||||||
|
if proginit.pargs.procimg == "/dev/piControl0":
|
||||||
|
# Läuft auf RevPi
|
||||||
|
ioctl(fh_proc, request, arg)
|
||||||
|
proginit.logger.debug(
|
||||||
|
"ioctl {0} with {1} successful"
|
||||||
|
"".format(request, arg)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Simulation
|
||||||
|
proginit.logger.warning(
|
||||||
|
"ioctl {0} with {1} simulated".format(request, arg)
|
||||||
|
)
|
||||||
|
except Exception as ex:
|
||||||
|
proginit.logger.error(ex)
|
||||||
|
self._devcon.send(b'\xff')
|
||||||
|
else:
|
||||||
|
self._devcon.send(b'\x1e')
|
||||||
|
|
||||||
|
elif proginit.pargs.developermode and cmd == b'DV':
|
||||||
|
# Development options
|
||||||
|
# bCMc00000000000b = 16
|
||||||
|
if self._acl < 9:
|
||||||
|
# Spezieller ACL-Wert für Entwicklung
|
||||||
|
self._devcon.send(b'\x18')
|
||||||
|
break
|
||||||
|
|
||||||
|
c = netcmd[3:4]
|
||||||
|
if c == b'a':
|
||||||
|
# CMD a = Switch ACL to 0
|
||||||
|
self._acl = 0
|
||||||
|
proginit.logger.warning("DV: set acl to 0")
|
||||||
|
self._devcon.send(b'\x1e')
|
||||||
|
elif c == b'b':
|
||||||
|
# CMD b = Aktiviert/Deaktiviert den Fehlermodus
|
||||||
|
if netcmd[4:5] == b'\x01':
|
||||||
|
self.__doerror = True
|
||||||
|
proginit.logger.warning("DV: set do_error")
|
||||||
|
else:
|
||||||
|
self.__doerror = False
|
||||||
|
proginit.logger.warning("DV: reset do_error")
|
||||||
|
self._devcon.send(b'\x1e')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Kein gültiges CMD gefunden, abbruch!
|
# Kein gültiges CMD gefunden, abbruch!
|
||||||
|
proginit.logger.error(
|
||||||
|
"found unknown net cmd: {0}".format(cmd)
|
||||||
|
)
|
||||||
break
|
break
|
||||||
|
|
||||||
# Verarbeitungszeit prüfen
|
# Verarbeitungszeit prüfen
|
||||||
|
|||||||
@@ -65,7 +65,11 @@ def configure():
|
|||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-v", "--verbose", action="count", dest="verbose",
|
"-v", "--verbose", action="count", dest="verbose",
|
||||||
help="Switch on verbose logging"
|
help="Switch on verbose logging: info -v debug -vv"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--developermode", action="store_true", dest="developermode",
|
||||||
|
default=False
|
||||||
)
|
)
|
||||||
global pargs
|
global pargs
|
||||||
pargs = parser.parse_args()
|
pargs = parser.parse_args()
|
||||||
|
|||||||
@@ -73,8 +73,12 @@ class RevPiPyLoad():
|
|||||||
self.xml_ps = None
|
self.xml_ps = None
|
||||||
|
|
||||||
# Berechtigungsmanger
|
# Berechtigungsmanger
|
||||||
self.plcslaveacl = IpAclManager(minlevel=0, maxlevel=1)
|
if proginit.pargs.developermode:
|
||||||
self.xmlrpcacl = IpAclManager(minlevel=0, maxlevel=4)
|
self.plcslaveacl = IpAclManager(minlevel=0, maxlevel=9)
|
||||||
|
self.xmlrpcacl = IpAclManager(minlevel=0, maxlevel=9)
|
||||||
|
else:
|
||||||
|
self.plcslaveacl = IpAclManager(minlevel=0, maxlevel=1)
|
||||||
|
self.xmlrpcacl = IpAclManager(minlevel=0, maxlevel=4)
|
||||||
|
|
||||||
# Threads/Prozesse
|
# Threads/Prozesse
|
||||||
self.th_plcmqtt = None
|
self.th_plcmqtt = None
|
||||||
@@ -519,7 +523,7 @@ class RevPiPyLoad():
|
|||||||
|
|
||||||
if self.plcslave:
|
if self.plcslave:
|
||||||
th_plc = picontrolserver.RevPiSlave(
|
th_plc = picontrolserver.RevPiSlave(
|
||||||
self.plcslaveacl, self.plcslaveport
|
self.plcslaveacl, self.plcslaveport, self.plcslavebindip
|
||||||
)
|
)
|
||||||
|
|
||||||
proginit.logger.debug("leave RevPiPyLoad._plcslave()")
|
proginit.logger.debug("leave RevPiPyLoad._plcslave()")
|
||||||
|
|||||||
Reference in New Issue
Block a user