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: