From 62f2bf544fb14500bc314e6472c38233f3ed95c3 Mon Sep 17 00:00:00 2001 From: NaruX Date: Mon, 10 Dec 2018 16:27:38 +0100 Subject: [PATCH] =?UTF-8?q?.core=20wird=20nur=20gesetzt,=20wenn=20g=C3=BCl?= =?UTF-8?q?tiges=20Basedevice=20erkannt=20wurde=20Globalen=20FileHandler?= =?UTF-8?q?=20durch=20Lock=20gesichert=20IOCTL=20=C3=BCber=20das=20Netzwer?= =?UTF-8?q?k=20umgesetzt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/revpimodio2.netio.html | 17 +++++++++++++++++ eric-revpimodio2.api | 1 + revpimodio2/device.py | 17 +++++------------ revpimodio2/io.py | 28 ++++++++++++++++++---------- revpimodio2/modio.py | 19 +++++++++++++++---- revpimodio2/netio.py | 31 +++++++++++++++++++++++++++++++ 6 files changed, 87 insertions(+), 26 deletions(-) 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