diff --git a/doc/revpimodio2.netio.html b/doc/revpimodio2.netio.html
index a130ae8..58f6735 100644
--- a/doc/revpimodio2.netio.html
+++ b/doc/revpimodio2.netio.html
@@ -98,6 +98,9 @@ Methods
get_timeout |
Gibt aktuellen Timeout zurueck. |
+| ioctl |
+IOCTL Befehle ueber das Netzwerk senden. |
+
| read |
Daten ueber das Netzwerk lesen. |
@@ -227,6 +230,20 @@ Gibt aktuellen Timeout zurueck.
in Millisekunden
+
+
+NetFH.ioctl
+ioctl(request, arg=b'')
+
+IOCTL Befehle ueber das Netzwerk senden.
+
+- request
+-
+Request as
+
- arg
+-
+Argument as
+
NetFH.read
diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api
index 3ecec16..2a52b49 100644
--- a/eric-revpimodio2.api
+++ b/eric-revpimodio2.api
@@ -183,6 +183,7 @@ revpimodio2.netio.NetFH.flush?4()
revpimodio2.netio.NetFH.get_closed?4()
revpimodio2.netio.NetFH.get_name?4()
revpimodio2.netio.NetFH.get_timeout?4()
+revpimodio2.netio.NetFH.ioctl?4(request, arg=b'')
revpimodio2.netio.NetFH.name?7
revpimodio2.netio.NetFH.read?4(length)
revpimodio2.netio.NetFH.readpictory?4()
diff --git a/revpimodio2/device.py b/revpimodio2/device.py
index e93bd54..8741b46 100644
--- a/revpimodio2/device.py
+++ b/revpimodio2/device.py
@@ -877,17 +877,8 @@ class DioModule(Device):
"""Erweitert Device-Klasse zum Erkennen von IntIOCounter.
@see #Device.__init__ Device.__init__(...)"""
- # Stringliste der Byteadressen
- self._lst_counter = []
-
- # Counter sind 4 Byte lang
- producttype = int(dict_device.get("productType"))
- if producttype == 96:
- # DIO - Counter auf DINT 6 - 66
- self._lst_counter = list(map(str, range(6, 70, 4)))
- elif producttype == 97:
- # DI - Counter auf DINT 4 - 64
- self._lst_counter = list(map(str, range(4, 68, 4)))
+ # Stringliste der Byteadressen (alle Module sind gleich)
+ self._lst_counter = list(map(str, range(6, 70, 4)))
# Basisklasse laden
super().__init__(parentmodio, dict_device, simulator=simulator)
@@ -964,8 +955,8 @@ class Virtual(Gateway):
self._ba_devdata[io._slc_address] = io._defaultvalue
# Outputs auf Bus schreiben
+ self._modio._myfh_lck.acquire()
try:
- # TODO: globalen FileHandler absichern
self._modio._myfh.seek(self._slc_inpoff.start)
self._modio._myfh.write(self._ba_devdata[self._slc_inp])
if self._modio._buffedwrite:
@@ -973,6 +964,8 @@ class Virtual(Gateway):
except IOError:
self._modio._gotioerror("write")
workokay = False
+ finally:
+ self._modio._myfh_lck.release()
self._filelock.release()
return workokay
diff --git a/revpimodio2/io.py b/revpimodio2/io.py
index c53946b..5e7ca21 100644
--- a/revpimodio2/io.py
+++ b/revpimodio2/io.py
@@ -830,22 +830,30 @@ class IntIOCounter(IntIO):
)
if isinstance(self._parentdevice._modio, RevPiNetIO):
- # TODO: NetFH ansprechen und an RevPiPyLoad senden
- warnings.warn("not jet implemented", FutureWarning)
+ # IOCTL über Netzwerk
+ with self._parentdevice._modio._myfh_lck:
+ try:
+ self._parentdevice._modio._myfh.ioctl(
+ 19220, self.__ioctl_arg
+ )
+ except Exception:
+ self._parentdevice._modio._gotioerror("net_ioctl")
elif self._parentdevice._modio._procimg != "/dev/piControl0":
# NOTE: Soll hier eine 0 in den Input geschrieben werden?
warnings.warn("this will work on a revolution pi only")
- elif ioctl is None:
- raise RuntimeError(
- "can not reset counter on this system without ioctl"
- )
-
else:
- # Counter reset durchführen (Funktion K+20)
- # TODO: globalen FileHandler absichern
- ioctl(self._parentdevice._modio._myfh, 19220, self.__ioctl_arg)
+ # IOCTL auf dem RevPi
+ with self._parentdevice._modio._myfh_lck:
+ try:
+ # Counter reset durchführen (Funktion K+20)
+ ioctl(
+ self._parentdevice._modio._myfh,
+ 19220, self.__ioctl_arg
+ )
+ except Exception:
+ self._parentdevice._modio._gotioerror("ioctl")
class IntIOReplaceable(IntIO):
diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py
index a9cbeda..af85b87 100644
--- a/revpimodio2/modio.py
+++ b/revpimodio2/modio.py
@@ -10,7 +10,7 @@ from multiprocessing import cpu_count
from os import access, F_OK, R_OK
from queue import Empty
from signal import signal, SIG_DFL, SIGINT, SIGTERM
-from threading import Thread, Event
+from threading import Thread, Event, Lock
from timeit import default_timer
@@ -30,8 +30,8 @@ class RevPiModIO(object):
__slots__ = "__cleanupfunc", "_autorefresh", "_buffedwrite", \
"_configrsc", "_exit", "_imgwriter", "_ioerror", "_length", \
"_looprunning", "_lst_devselect", "_lst_refresh", "_maxioerrors", \
- "_myfh", "_monitoring", "_procimg", "_simulator", "_syncoutputs", \
- "_th_mainloop", "_waitexit", \
+ "_myfh", "_myfh_lck", "_monitoring", "_procimg", "_simulator", \
+ "_syncoutputs", "_th_mainloop", "_waitexit", \
"core", "app", "device", "exitsignal", "io", "summary"
def __init__(
@@ -68,6 +68,7 @@ class RevPiModIO(object):
self._lst_refresh = []
self._maxioerrors = 0
self._myfh = None
+ self._myfh_lck = Lock()
self._th_mainloop = None
self._waitexit = Event()
@@ -162,17 +163,18 @@ class RevPiModIO(object):
dev_new = devicemodule.Core(
self, device, simulator=self._simulator
)
+ self.core = dev_new
elif pt == 105:
# RevPi Connect
dev_new = devicemodule.Connect(
self, device, simulator=self._simulator
)
+ self.core = dev_new
else:
# Base immer als Fallback verwenden
dev_new = devicemodule.Base(
self, device, simulator=self._simulator
)
- self.core = dev_new
elif device["type"] == "LEFT_RIGHT":
# IOs
pt = int(device["productType"])
@@ -687,12 +689,15 @@ class RevPiModIO(object):
mylist = [dev]
# Daten komplett einlesen
+ self._myfh_lck.acquire()
try:
self._myfh.seek(0)
bytesbuff = self._myfh.read(self._length)
except IOError:
self._gotioerror("read")
return False
+ finally:
+ self._myfh_lck.release()
for dev in mylist:
if not dev._selfupdate:
@@ -761,12 +766,15 @@ class RevPiModIO(object):
)
mylist = [dev]
+ self._myfh_lck.acquire()
try:
self._myfh.seek(0)
bytesbuff = self._myfh.read(self._length)
except IOError:
self._gotioerror("read")
return False
+ finally:
+ self._myfh_lck.release()
for dev in mylist:
if not dev._selfupdate:
@@ -810,11 +818,14 @@ class RevPiModIO(object):
dev._filelock.acquire()
# Outpus auf Bus schreiben
+ self._myfh_lck.acquire()
try:
self._myfh.seek(dev._slc_outoff.start)
self._myfh.write(dev._ba_devdata[dev._slc_out])
except IOError:
workokay = False
+ finally:
+ self._myfh_lck.release()
dev._filelock.release()
diff --git a/revpimodio2/netio.py b/revpimodio2/netio.py
index 1cf02e4..7b231db 100644
--- a/revpimodio2/netio.py
+++ b/revpimodio2/netio.py
@@ -243,6 +243,37 @@ class NetFH(Thread):
@return in Millisekunden"""
return int(self.__timeout * 1000)
+ def ioctl(self, request, arg=b''):
+ """IOCTL Befehle ueber das Netzwerk senden.
+ @param request Request as
+ @param arg Argument as """
+ if self.__sockend:
+ raise ValueError("read of closed file")
+
+ if not (isinstance(arg, bytes) and len(arg) <= 1024):
+ raise ValueError("arg must be ")
+
+ with self.__socklock:
+ self._slavesock.send(
+ b'\x01IC' +
+ request.to_bytes(length=4, byteorder="little") +
+ len(arg).to_bytes(length=2, byteorder="little") +
+ b'\x00\x00\x00\x00\x00\x00\x17'
+ )
+ self._slavesock.sendall(arg)
+
+ # Rückmeldebyte auswerten
+ check = self._slavesock.recv(1)
+ if check != b'\x1e':
+
+ # ACL prüfen und ggf Fehler werfen
+ self.__check_acl(check)
+
+ self.__sockerr.set()
+ raise IOError("ioctl error on network")
+
+ self.__trigger = True
+
def read(self, length):
"""Daten ueber das Netzwerk lesen.
@param length Anzahl der Bytes