diff --git a/doc/revpimodio2.modio.html b/doc/revpimodio2.modio.html index b3e68b9..4fef3d2 100644 --- a/doc/revpimodio2.modio.html +++ b/doc/revpimodio2.modio.html @@ -86,6 +86,9 @@ Methods _get_configrsc Getter function. +_get_cpreplaceio +Laed die replace_io_file Konfiguration und verarbeitet sie. + _get_cycletime Gibt Aktualisierungsrate in ms der Prozessabbildsynchronisierung aus. @@ -231,19 +234,27 @@ RevPiModIO._configure _configure(jconfigrsc)

Verarbeitet die piCtory Konfigurationsdatei. -

+

+
jconfigrsc:
+
+Data to build IOs as of JSON +
+

RevPiModIO._configure_replace_io

-_configure_replace_io() +_configure_replace_io(creplaceio)

Importiert ersetzte IOs in diese Instanz.

Importiert ersetzte IOs, welche vorher mit .export_replaced_ios(...) in eine Datei exportiert worden sind. Diese IOs werden in dieser Instanz wiederhergestellt. -

- -

+

+
ireplaceio:
+
+Data to replace ios as +
+

RevPiModIO._create_myfh

_create_myfh() @@ -261,6 +272,17 @@ Getter function.
Pfad der verwendeten piCtory Konfiguration
+ +

+RevPiModIO._get_cpreplaceio

+_get_cpreplaceio() +

+Laed die replace_io_file Konfiguration und verarbeitet sie. +

+
Returns:
+
+ der replace io daten +

RevPiModIO._get_cycletime

diff --git a/doc/revpimodio2.netio.html b/doc/revpimodio2.netio.html index f92c724..b0478a0 100644 --- a/doc/revpimodio2.netio.html +++ b/doc/revpimodio2.netio.html @@ -12,7 +12,7 @@ RevPiModIO Hauptklasse fuer Netzwerkzugriff.

Global Attributes

- +
__author__
__copyright__
__license__
_sysdeldirty
_sysexit
_sysflush
_syspictory
_syssync
__author__
__copyright__
__license__
_sysdeldirty
_sysexit
_sysflush
_syspictory
_sysreplaceio
_syssync

Classes

@@ -147,6 +147,9 @@ Methods readpictory Ruft die piCtory Konfiguration ab. +readreplaceio +Ruft die replace_io Konfiguration ab. + run Handler fuer Synchronisierung. @@ -341,6 +344,17 @@ Ruft die piCtory Konfiguration ab.
piCtory Datei
+ +

+NetFH.readreplaceio

+readreplaceio() +

+Ruft die replace_io Konfiguration ab. +

+
Returns:
+
+ replace_io_file +

NetFH.run

@@ -450,6 +464,9 @@ Methods _create_myfh Erstellt NetworkFileObject. +_get_cpreplaceio +Laed die replace_io Konfiguration ueber das Netzwerk. + disconnect Trennt Verbindungen und beendet autorefresh inkl. @@ -510,7 +527,18 @@ RevPiNetIO._create_myfh

Erstellt NetworkFileObject. return FileObject -

+

+

+RevPiNetIO._get_cpreplaceio

+_get_cpreplaceio() +

+Laed die replace_io Konfiguration ueber das Netzwerk. +

+
Returns:
+
+ der replace io daten +
+

RevPiNetIO.disconnect

disconnect() diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api index 6316765..e9edf68 100644 --- a/eric-revpimodio2.api +++ b/eric-revpimodio2.api @@ -142,9 +142,10 @@ revpimodio2.io.StructIO.signed?7 revpimodio2.io.StructIO.value?7 revpimodio2.io.StructIO?1(parentio, name, frm, **kwargs) revpimodio2.modio.RevPiModIO._configure?5(jconfigrsc) -revpimodio2.modio.RevPiModIO._configure_replace_io?5() +revpimodio2.modio.RevPiModIO._configure_replace_io?5(creplaceio) revpimodio2.modio.RevPiModIO._create_myfh?5() revpimodio2.modio.RevPiModIO._get_configrsc?5() +revpimodio2.modio.RevPiModIO._get_cpreplaceio?5() revpimodio2.modio.RevPiModIO._get_cycletime?5() revpimodio2.modio.RevPiModIO._get_debug?5() revpimodio2.modio.RevPiModIO._get_ioerrors?5() @@ -198,6 +199,7 @@ revpimodio2.netio.NetFH.ioctl?4(request, arg=b'') revpimodio2.netio.NetFH.name?7 revpimodio2.netio.NetFH.read?4(length) revpimodio2.netio.NetFH.readpictory?4() +revpimodio2.netio.NetFH.readreplaceio?4() revpimodio2.netio.NetFH.reconnecting?7 revpimodio2.netio.NetFH.run?4() revpimodio2.netio.NetFH.seek?4(position) @@ -208,6 +210,7 @@ revpimodio2.netio.NetFH.timeout?7 revpimodio2.netio.NetFH.write?4(bytebuff) revpimodio2.netio.NetFH?1(address, timeout=500) revpimodio2.netio.RevPiNetIO._create_myfh?5() +revpimodio2.netio.RevPiNetIO._get_cpreplaceio?5() revpimodio2.netio.RevPiNetIO.disconnect?4() revpimodio2.netio.RevPiNetIO.get_jconfigrsc?4() revpimodio2.netio.RevPiNetIO.get_reconnecting?4() @@ -221,5 +224,6 @@ revpimodio2.netio._sysdeldirty?8 revpimodio2.netio._sysexit?8 revpimodio2.netio._sysflush?8 revpimodio2.netio._syspictory?8 +revpimodio2.netio._sysreplaceio?8 revpimodio2.netio._syssync?8 revpimodio2.summary.Summary?1(summary) diff --git a/revpimodio2/io.py b/revpimodio2/io.py index 0ca6e7d..b5e766d 100644 --- a/revpimodio2/io.py +++ b/revpimodio2/io.py @@ -1000,13 +1000,6 @@ class IntIOReplaceable(IntIO): >Python3 struct """ - # Sperre prüfen - if self._parentdevice._modio._lck_replace_io: - raise RuntimeError( - "can not use this function while using an external " - "replace_io_file" - ) - # StructIO erzeugen io_new = StructIO( self, diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py index b80f101..0022721 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -37,7 +37,7 @@ class RevPiModIO(object): "_maxioerrors", "_myfh", "_myfh_lck", "_monitoring", "_procimg", \ "_simulator", "_syncoutputs", "_th_mainloop", "_waitexit", \ "core", "app", "device", "exitsignal", "io", "summary", "_debug", \ - "_lck_replace_io", "_replace_io_file", "_run_on_pi" + "_replace_io_file", "_run_on_pi" def __init__( self, autorefresh=False, monitoring=False, syncoutputs=True, @@ -85,7 +85,6 @@ class RevPiModIO(object): self._imgwriter = None self._ioerror = 0 self._length = 0 - self._lck_replace_io = False self._looprunning = False self._lst_devselect = [] self._lst_refresh = [] @@ -116,6 +115,7 @@ class RevPiModIO(object): # Nur Konfigurieren, wenn nicht vererbt if type(self) == RevPiModIO: self._configure(self.get_jconfigrsc()) + self._configure_replace_io(self._get_cpreplaceio()) def __del__(self): """Zerstoert alle Klassen um aufzuraeumen.""" @@ -138,7 +138,8 @@ class RevPiModIO(object): self.writeprocimg() def _configure(self, jconfigrsc): - """Verarbeitet die piCtory Konfigurationsdatei.""" + """Verarbeitet die piCtory Konfigurationsdatei. + @param jconfigrsc: Data to build IOs as of JSON""" # Filehandler konfigurieren, wenn er noch nicht existiert if self._myfh is None: @@ -262,11 +263,6 @@ class RevPiModIO(object): Warning ) - # Replace IO aus Datei verarbeiten - if self._replace_io_file is not None: - self._configure_replace_io() - self._lck_replace_io = True - # ImgWriter erstellen self._imgwriter = helpermodule.ProcimgWriter(self) @@ -301,76 +297,67 @@ class RevPiModIO(object): # Summary Klasse instantiieren self.summary = summarymodule.Summary(jconfigrsc["Summary"]) - def _configure_replace_io(self): + def _configure_replace_io(self, creplaceio): """Importiert ersetzte IOs in diese Instanz. Importiert ersetzte IOs, welche vorher mit .export_replaced_ios(...) in eine Datei exportiert worden sind. Diese IOs werden in dieser Instanz wiederhergestellt. + @param ireplaceio: Data to replace ios as + """ - cp = ConfigParser() - - try: - with open(self._replace_io_file, "r") as fh: - cp.read_file(fh) - except Exception as e: - raise RuntimeError( - "replace_io_file: could not read file '{0}' | {1}" - "".format(self._replace_io_file, e) - ) - - for io in cp: + for io in creplaceio: if io == "DEFAULT": continue # IO prüfen - parentio = cp[io].get("replace", "") + parentio = creplaceio[io].get("replace", "") # Funktionsaufruf vorbereiten dict_replace = { - "frm": cp[io].get("frm"), + "frm": creplaceio[io].get("frm"), } # Convert defaultvalue from config file - if "defaultvalue" in cp[io]: + if "defaultvalue" in creplaceio[io]: if dict_replace["frm"] == "?": try: dict_replace["defaultvalue"] = \ - cp[io].getboolean("defaultvalue") + creplaceio[io].getboolean("defaultvalue") except Exception: raise ValueError( "replace_io_file: could not convert '{0}' " "defaultvalue '{1}' to boolean" - "".format(io, cp[io].get("defaultvalue")) + "".format(io, creplaceio[io].get("defaultvalue")) ) else: try: dict_replace["defaultvalue"] = \ - cp[io].getint("defaultvalue") + creplaceio[io].getint("defaultvalue") except Exception: raise ValueError( "replace_io_file: could not convert '{0}' " "defaultvalue '{1}' to integer" - "".format(io, cp[io].get("bit")) + "".format(io, creplaceio[io].get("bit")) ) # Get bitaddress from config file - if "bit" in cp[io]: + if "bit" in creplaceio[io]: try: - dict_replace["bit"] = cp[io].getint("bit", 0) + dict_replace["bit"] = creplaceio[io].getint("bit", 0) except Exception: raise ValueError( "replace_io_file: could not convert '{0}' " "bit '{1}' to integer" - "".format(io, cp[io].get("bit")) + "".format(io, creplaceio[io].get("bit")) ) # Sonstige Werte laden, wenn vorhanden - if "bmk" in cp[io]: - dict_replace["bmk"] = cp[io].get("bmk") - if "byteorder" in cp[io]: - dict_replace["byteorder"] = cp[io].get("byteorder") + if "bmk" in creplaceio[io]: + dict_replace["bmk"] = creplaceio[io].get("bmk") + if "byteorder" in creplaceio[io]: + dict_replace["byteorder"] = creplaceio[io].get("byteorder") # IO ersetzen try: @@ -392,6 +379,25 @@ class RevPiModIO(object): @return Pfad der verwendeten piCtory Konfiguration""" return self._configrsc + def _get_cpreplaceio(self): + """Laed die replace_io_file Konfiguration und verarbeitet sie. + @return der replace io daten""" + cp = ConfigParser() + + # TODO: verfeinern! + + if self._replace_io_file: + try: + with open(self._replace_io_file, "r") as fh: + cp.read_file(fh) + except Exception as e: + raise RuntimeError( + "replace_io_file: could not read/parse file '{0}' | {1}" + "".format(self._replace_io_file, e) + ) + + return cp + def _get_cycletime(self): """Gibt Aktualisierungsrate in ms der Prozessabbildsynchronisierung aus. @return Millisekunden""" @@ -1141,6 +1147,7 @@ class RevPiModIOSelected(RevPiModIO): ) self._configure(self.get_jconfigrsc()) + self._configure_replace_io(self._get_cpreplaceio()) if len(self.device) == 0: if type(self) == RevPiModIODriver: diff --git a/revpimodio2/netio.py b/revpimodio2/netio.py index e0a9363..dee129f 100644 --- a/revpimodio2/netio.py +++ b/revpimodio2/netio.py @@ -5,6 +5,7 @@ __copyright__ = "Copyright (C) 2018 Sven Sager" __license__ = "LGPLv3" import socket import warnings +from configparser import ConfigParser from json import loads as jloads from re import compile from revpimodio2 import DeviceNotFoundError @@ -21,6 +22,8 @@ _sysexit = b'\x01EX\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17' _sysdeldirty = b'\x01EY\x00\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x17' # piCtory Konfiguration laden _syspictory = b'\x01PI\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17' +# ReplaceIO Konfiguration laden +_sysreplaceio = b'\x01RP\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17' # Übertragene Bytes schreiben _sysflush = b'\x01SD\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x17' @@ -358,19 +361,48 @@ class NetFH(Thread): self._slavesock.send(_syspictory) byte_buff = bytearray() - while not self.__sockend.is_set(): - data = self._slavesock.recv(256) + zero_byte = 0 + while not self.__sockend.is_set() and zero_byte < 100: + data = self._slavesock.recv(128) + if data == b'': + zero_byte += 1 byte_buff += data if data.find(b'\x04') >= 0: self.__trigger = True # NOTE: Nur suchen oder Ende prüfen? - return byte_buff[:-1] + return bytes(byte_buff[:-1]) self.__sockerr.set() raise IOError("readpictory error on network") + def readreplaceio(self): + """Ruft die replace_io Konfiguration ab. + @return replace_io_file""" + if self.__sockend: + raise ValueError("read of closed file") + + with self.__socklock: + self._slavesock.send(_sysreplaceio) + + byte_buff = bytearray() + zero_byte = 0 + while not self.__sockend and zero_byte < 100: + data = self._slavesock.recv(128) + if data == b'': + zero_byte += 1 + + byte_buff += data + if data.find(b'\x04') >= 0: + # NOTE: Nur suchen oder Ende prüfen? + return bytes(byte_buff[:-1]) + + self.__sockerr.set() + raise IOError("readreplaceio error on network") + + self.__trigger = True + def run(self): """Handler fuer Synchronisierung.""" while not self.__sockend.is_set(): @@ -592,15 +624,15 @@ class RevPiNetIO(_RevPiModIO): # Vererben super().__init__( - autorefresh, - monitoring, - syncoutputs, - "{0}:{1}".format(*self._address), - None, - simulator, - debug, - replace_io_file, - direct_output + autorefresh=autorefresh, + monitoring=monitoring, + syncoutputs=syncoutputs, + procimg="{0}:{1}".format(*self._address), + configrsc=None, + simulator=simulator, + debug=debug, + replace_io_file=replace_io_file, + direct_output=direct_output, ) # Netzwerkfilehandler anlegen @@ -609,6 +641,7 @@ class RevPiNetIO(_RevPiModIO): # Nur Konfigurieren, wenn nicht vererbt if type(self) == RevPiNetIO: self._configure(self.get_jconfigrsc()) + self._configure_replace_io(self._get_cpreplaceio()) def _create_myfh(self): """Erstellt NetworkFileObject. @@ -616,6 +649,27 @@ class RevPiNetIO(_RevPiModIO): self._buffedwrite = True return NetFH(self._address) + def _get_cpreplaceio(self): + """Laed die replace_io Konfiguration ueber das Netzwerk. + @return der replace io daten""" + + # Normale Verwendung über Elternklasse erledigen + if self._replace_io_file != ":network:": + return super()._get_cpreplaceio() + + # Replace IO Daten über das Netzwerk beziehen + byte_buff = self._myfh.readreplaceio() + + cp = ConfigParser() + try: + cp.read_string(byte_buff.decode("utf-8")) + except Exception as e: + raise RuntimeError( + "replace_io_file: could not read/parse network data | {0}" + "".format(e) + ) + return cp + def disconnect(self): """Trennt Verbindungen und beendet autorefresh inkl. alle Threads.""" self.cleanup() @@ -751,6 +805,7 @@ class RevPiNetIOSelected(RevPiNetIO): ) self._configure(self.get_jconfigrsc()) + self._configure_replace_io(self._get_cpreplaceio()) if len(self.device) == 0: if type(self) == RevPiNetIODriver: