.core wird nur gesetzt, wenn gültiges Basedevice erkannt wurde

Globalen FileHandler durch Lock gesichert
IOCTL über das Netzwerk umgesetzt
This commit is contained in:
2018-12-10 16:27:38 +01:00
parent fc23394298
commit 62f2bf544f
6 changed files with 87 additions and 26 deletions

View File

@@ -98,6 +98,9 @@ Methods</h3>
<td><a style="color:#0000FF" href="#NetFH.get_timeout">get_timeout</a></td> <td><a style="color:#0000FF" href="#NetFH.get_timeout">get_timeout</a></td>
<td>Gibt aktuellen Timeout zurueck.</td> <td>Gibt aktuellen Timeout zurueck.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#NetFH.ioctl">ioctl</a></td>
<td>IOCTL Befehle ueber das Netzwerk senden.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#NetFH.read">read</a></td> <td><a style="color:#0000FF" href="#NetFH.read">read</a></td>
<td>Daten ueber das Netzwerk lesen.</td> <td>Daten ueber das Netzwerk lesen.</td>
</tr><tr> </tr><tr>
@@ -227,6 +230,20 @@ Gibt aktuellen Timeout zurueck.
<dd> <dd>
<class 'int'> in Millisekunden <class 'int'> in Millisekunden
</dd> </dd>
</dl><a NAME="NetFH.ioctl" ID="NetFH.ioctl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
NetFH.ioctl</h3>
<b>ioctl</b>(<i>request, arg=b''</i>)
<p>
IOCTL Befehle ueber das Netzwerk senden.
</p><dl>
<dt><i>request</i></dt>
<dd>
Request as <class 'int'>
</dd><dt><i>arg</i></dt>
<dd>
Argument as <class 'byte'>
</dd>
</dl><a NAME="NetFH.read" ID="NetFH.read"></a> </dl><a NAME="NetFH.read" ID="NetFH.read"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
NetFH.read</h3> NetFH.read</h3>

View File

@@ -183,6 +183,7 @@ revpimodio2.netio.NetFH.flush?4()
revpimodio2.netio.NetFH.get_closed?4() revpimodio2.netio.NetFH.get_closed?4()
revpimodio2.netio.NetFH.get_name?4() revpimodio2.netio.NetFH.get_name?4()
revpimodio2.netio.NetFH.get_timeout?4() revpimodio2.netio.NetFH.get_timeout?4()
revpimodio2.netio.NetFH.ioctl?4(request, arg=b'')
revpimodio2.netio.NetFH.name?7 revpimodio2.netio.NetFH.name?7
revpimodio2.netio.NetFH.read?4(length) revpimodio2.netio.NetFH.read?4(length)
revpimodio2.netio.NetFH.readpictory?4() revpimodio2.netio.NetFH.readpictory?4()

View File

@@ -877,17 +877,8 @@ class DioModule(Device):
"""Erweitert Device-Klasse zum Erkennen von IntIOCounter. """Erweitert Device-Klasse zum Erkennen von IntIOCounter.
@see #Device.__init__ Device.__init__(...)""" @see #Device.__init__ Device.__init__(...)"""
# Stringliste der Byteadressen # Stringliste der Byteadressen (alle Module sind gleich)
self._lst_counter = [] self._lst_counter = list(map(str, range(6, 70, 4)))
# 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)))
# Basisklasse laden # Basisklasse laden
super().__init__(parentmodio, dict_device, simulator=simulator) super().__init__(parentmodio, dict_device, simulator=simulator)
@@ -964,8 +955,8 @@ class Virtual(Gateway):
self._ba_devdata[io._slc_address] = io._defaultvalue self._ba_devdata[io._slc_address] = io._defaultvalue
# Outputs auf Bus schreiben # Outputs auf Bus schreiben
self._modio._myfh_lck.acquire()
try: try:
# TODO: globalen FileHandler absichern
self._modio._myfh.seek(self._slc_inpoff.start) self._modio._myfh.seek(self._slc_inpoff.start)
self._modio._myfh.write(self._ba_devdata[self._slc_inp]) self._modio._myfh.write(self._ba_devdata[self._slc_inp])
if self._modio._buffedwrite: if self._modio._buffedwrite:
@@ -973,6 +964,8 @@ class Virtual(Gateway):
except IOError: except IOError:
self._modio._gotioerror("write") self._modio._gotioerror("write")
workokay = False workokay = False
finally:
self._modio._myfh_lck.release()
self._filelock.release() self._filelock.release()
return workokay return workokay

View File

@@ -830,22 +830,30 @@ class IntIOCounter(IntIO):
) )
if isinstance(self._parentdevice._modio, RevPiNetIO): if isinstance(self._parentdevice._modio, RevPiNetIO):
# TODO: NetFH ansprechen und an RevPiPyLoad senden # IOCTL über Netzwerk
warnings.warn("not jet implemented", FutureWarning) 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": elif self._parentdevice._modio._procimg != "/dev/piControl0":
# NOTE: Soll hier eine 0 in den Input geschrieben werden? # NOTE: Soll hier eine 0 in den Input geschrieben werden?
warnings.warn("this will work on a revolution pi only") 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: else:
# Counter reset durchführen (Funktion K+20) # IOCTL auf dem RevPi
# TODO: globalen FileHandler absichern with self._parentdevice._modio._myfh_lck:
ioctl(self._parentdevice._modio._myfh, 19220, self.__ioctl_arg) 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): class IntIOReplaceable(IntIO):

View File

@@ -10,7 +10,7 @@ from multiprocessing import cpu_count
from os import access, F_OK, R_OK from os import access, F_OK, R_OK
from queue import Empty from queue import Empty
from signal import signal, SIG_DFL, SIGINT, SIGTERM from signal import signal, SIG_DFL, SIGINT, SIGTERM
from threading import Thread, Event from threading import Thread, Event, Lock
from timeit import default_timer from timeit import default_timer
@@ -30,8 +30,8 @@ class RevPiModIO(object):
__slots__ = "__cleanupfunc", "_autorefresh", "_buffedwrite", \ __slots__ = "__cleanupfunc", "_autorefresh", "_buffedwrite", \
"_configrsc", "_exit", "_imgwriter", "_ioerror", "_length", \ "_configrsc", "_exit", "_imgwriter", "_ioerror", "_length", \
"_looprunning", "_lst_devselect", "_lst_refresh", "_maxioerrors", \ "_looprunning", "_lst_devselect", "_lst_refresh", "_maxioerrors", \
"_myfh", "_monitoring", "_procimg", "_simulator", "_syncoutputs", \ "_myfh", "_myfh_lck", "_monitoring", "_procimg", "_simulator", \
"_th_mainloop", "_waitexit", \ "_syncoutputs", "_th_mainloop", "_waitexit", \
"core", "app", "device", "exitsignal", "io", "summary" "core", "app", "device", "exitsignal", "io", "summary"
def __init__( def __init__(
@@ -68,6 +68,7 @@ class RevPiModIO(object):
self._lst_refresh = [] self._lst_refresh = []
self._maxioerrors = 0 self._maxioerrors = 0
self._myfh = None self._myfh = None
self._myfh_lck = Lock()
self._th_mainloop = None self._th_mainloop = None
self._waitexit = Event() self._waitexit = Event()
@@ -162,17 +163,18 @@ class RevPiModIO(object):
dev_new = devicemodule.Core( dev_new = devicemodule.Core(
self, device, simulator=self._simulator self, device, simulator=self._simulator
) )
self.core = dev_new
elif pt == 105: elif pt == 105:
# RevPi Connect # RevPi Connect
dev_new = devicemodule.Connect( dev_new = devicemodule.Connect(
self, device, simulator=self._simulator self, device, simulator=self._simulator
) )
self.core = dev_new
else: else:
# Base immer als Fallback verwenden # Base immer als Fallback verwenden
dev_new = devicemodule.Base( dev_new = devicemodule.Base(
self, device, simulator=self._simulator self, device, simulator=self._simulator
) )
self.core = dev_new
elif device["type"] == "LEFT_RIGHT": elif device["type"] == "LEFT_RIGHT":
# IOs # IOs
pt = int(device["productType"]) pt = int(device["productType"])
@@ -687,12 +689,15 @@ class RevPiModIO(object):
mylist = [dev] mylist = [dev]
# Daten komplett einlesen # Daten komplett einlesen
self._myfh_lck.acquire()
try: try:
self._myfh.seek(0) self._myfh.seek(0)
bytesbuff = self._myfh.read(self._length) bytesbuff = self._myfh.read(self._length)
except IOError: except IOError:
self._gotioerror("read") self._gotioerror("read")
return False return False
finally:
self._myfh_lck.release()
for dev in mylist: for dev in mylist:
if not dev._selfupdate: if not dev._selfupdate:
@@ -761,12 +766,15 @@ class RevPiModIO(object):
) )
mylist = [dev] mylist = [dev]
self._myfh_lck.acquire()
try: try:
self._myfh.seek(0) self._myfh.seek(0)
bytesbuff = self._myfh.read(self._length) bytesbuff = self._myfh.read(self._length)
except IOError: except IOError:
self._gotioerror("read") self._gotioerror("read")
return False return False
finally:
self._myfh_lck.release()
for dev in mylist: for dev in mylist:
if not dev._selfupdate: if not dev._selfupdate:
@@ -810,11 +818,14 @@ class RevPiModIO(object):
dev._filelock.acquire() dev._filelock.acquire()
# Outpus auf Bus schreiben # Outpus auf Bus schreiben
self._myfh_lck.acquire()
try: try:
self._myfh.seek(dev._slc_outoff.start) self._myfh.seek(dev._slc_outoff.start)
self._myfh.write(dev._ba_devdata[dev._slc_out]) self._myfh.write(dev._ba_devdata[dev._slc_out])
except IOError: except IOError:
workokay = False workokay = False
finally:
self._myfh_lck.release()
dev._filelock.release() dev._filelock.release()

View File

@@ -243,6 +243,37 @@ class NetFH(Thread):
@return <class 'int'> in Millisekunden""" @return <class 'int'> in Millisekunden"""
return int(self.__timeout * 1000) return int(self.__timeout * 1000)
def ioctl(self, request, arg=b''):
"""IOCTL Befehle ueber das Netzwerk senden.
@param request Request as <class 'int'>
@param arg Argument as <class 'byte'>"""
if self.__sockend:
raise ValueError("read of closed file")
if not (isinstance(arg, bytes) and len(arg) <= 1024):
raise ValueError("arg must be <class 'bytes'>")
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): def read(self, length):
"""Daten ueber das Netzwerk lesen. """Daten ueber das Netzwerk lesen.
@param length Anzahl der Bytes @param length Anzahl der Bytes