diff --git a/doc/revpimodio2.modio.html b/doc/revpimodio2.modio.html index 2841f45..30e412e 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. @@ -219,19 +222,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() @@ -249,6 +260,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 4c614a8..bc0c938 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

@@ -110,6 +110,9 @@ Methods readpictory Ruft die piCtory Konfiguration ab. +readreplaceio +Ruft die replace_io Konfiguration ab. + run Handler fuer Synchronisierung. @@ -293,6 +296,17 @@ Ruft die piCtory Konfiguration ab.
piCtory Datei
+ +

+NetFH.readreplaceio

+readreplaceio() +

+Ruft die replace_io Konfiguration ab. +

+
Returns:
+
+ replace_io_file +

NetFH.run

@@ -402,6 +416,9 @@ Methods _create_myfh Erstellt NetworkFileObject. +_get_cpreplaceio +Laed die replace_io Konfiguration ueber das Netzwerk. + disconnect Trennt Verbindungen und beendet autorefresh inkl. @@ -456,7 +473,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 270362a..692878b 100644 --- a/eric-revpimodio2.api +++ b/eric-revpimodio2.api @@ -141,9 +141,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_ioerrors?5() revpimodio2.modio.RevPiModIO._get_length?5() @@ -191,6 +192,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.run?4() revpimodio2.netio.NetFH.seek?4(position) revpimodio2.netio.NetFH.set_dirtybytes?4(position, dirtybytes) @@ -200,6 +202,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.net_cleardefaultvalues?4(device=None) @@ -211,5 +214,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/modio.py b/revpimodio2/modio.py index 589d297..81551bd 100644 --- a/revpimodio2/modio.py +++ b/revpimodio2/modio.py @@ -106,6 +106,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.""" @@ -128,7 +129,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: @@ -252,11 +254,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) @@ -291,88 +288,83 @@ 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() + need_replace_lock = False - 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: self.io[parentio].replace_io(name=io, **dict_replace) + need_replace_lock = True except Exception as e: raise RuntimeError( "replace_io_file: can not replace '{0}' with '{1}' " - "| RevPiModIO message: {2}".format( - parentio, io, e - ) + "| RevPiModIO message: {2}".format(parentio, io, e) ) + # Sperre für weiter .replace_io Aufrufe setzen + self._lck_replace_io = need_replace_lock + def _create_myfh(self): """Erstellt FileObject mit Pfad zum procimg. return FileObject""" @@ -384,6 +376,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""" @@ -1049,6 +1060,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 d8c899f..78bfcaf 100644 --- a/revpimodio2/netio.py +++ b/revpimodio2/netio.py @@ -6,6 +6,7 @@ __license__ = "LGPLv3" import socket import warnings +from configparser import ConfigParser from json import loads as jloads from re import compile from threading import Thread, Event, Lock @@ -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' @@ -330,19 +333,48 @@ class NetFH(Thread): self._slavesock.send(_syspictory) byte_buff = bytearray() - while not self.__sockend: - data = self._slavesock.recv(1024) + 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 byte_buff[:-1] + return bytes(byte_buff[:-1]) self.__sockerr.set() raise IOError("readpictory error on network") self.__trigger = True + 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: @@ -542,14 +574,14 @@ class RevPiNetIO(_RevPiModIO): # Vererben super().__init__( - autorefresh, - monitoring, - syncoutputs, - "{0}:{1}".format(*self._address), - None, - simulator, - debug, - replace_io_file + autorefresh=autorefresh, + monitoring=monitoring, + syncoutputs=syncoutputs, + procimg="{0}:{1}".format(*self._address), + configrsc=None, + simulator=simulator, + debug=debug, + replace_io_file=replace_io_file ) # Netzwerkfilehandler anlegen @@ -558,6 +590,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. @@ -565,6 +598,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() @@ -693,6 +747,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: