direct_output in RevPiNetIO übernommen

Eindeutige erkennung des procimg (file or character)
Simulationsfunktionen für IOCTL gegen einfache Datei bei procimg Parameter
IOCTLs werden nun einfacher verarbeitet / umgelenkt
This commit is contained in:
2019-07-14 18:28:42 +02:00
parent d28de43a7d
commit 527a4aa078
6 changed files with 142 additions and 55 deletions

View File

@@ -116,6 +116,9 @@ Methods</h3>
<td><a style="color:#0000FF" href="#RevPiModIO._set_maxioerrors">_set_maxioerrors</a></td> <td><a style="color:#0000FF" href="#RevPiModIO._set_maxioerrors">_set_maxioerrors</a></td>
<td>Setzt Anzahl der maximal erlaubten Fehler bei Prozessabbildzugriff.</td> <td>Setzt Anzahl der maximal erlaubten Fehler bei Prozessabbildzugriff.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#RevPiModIO._simulate_ioctl">_simulate_ioctl</a></td>
<td>Simuliert IOCTL Funktionen auf procimg Datei.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#RevPiModIO.autorefresh_all">autorefresh_all</a></td> <td><a style="color:#0000FF" href="#RevPiModIO.autorefresh_all">autorefresh_all</a></td>
<td>Setzt alle Devices in autorefresh Funktion.</td> <td>Setzt alle Devices in autorefresh Funktion.</td>
</tr><tr> </tr><tr>
@@ -365,6 +368,20 @@ Setzt Anzahl der maximal erlaubten Fehler bei Prozessabbildzugriff.
<dd> <dd>
Anzahl erlaubte Fehler Anzahl erlaubte Fehler
</dd> </dd>
</dl><a NAME="RevPiModIO._simulate_ioctl" ID="RevPiModIO._simulate_ioctl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiModIO._simulate_ioctl</h3>
<b>_simulate_ioctl</b>(<i>request, arg=b''</i>)
<p>
Simuliert IOCTL Funktionen auf procimg Datei.
</p><dl>
<dt><i>request</i></dt>
<dd>
IO Request
</dd><dt><i>arg:</i></dt>
<dd>
Request argument
</dd>
</dl><a NAME="RevPiModIO.autorefresh_all" ID="RevPiModIO.autorefresh_all"></a> </dl><a NAME="RevPiModIO.autorefresh_all" ID="RevPiModIO.autorefresh_all"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiModIO.autorefresh_all</h3> RevPiModIO.autorefresh_all</h3>

View File

@@ -423,7 +423,7 @@ Static Methods</h3>
<a NAME="RevPiNetIO.__init__" ID="RevPiNetIO.__init__"></a> <a NAME="RevPiNetIO.__init__" ID="RevPiNetIO.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiNetIO (Constructor)</h3> RevPiNetIO (Constructor)</h3>
<b>RevPiNetIO</b>(<i>address, autorefresh=False, monitoring=False, syncoutputs=True, simulator=False, debug=False, replace_io_file=None</i>) <b>RevPiNetIO</b>(<i>address, autorefresh=False, monitoring=False, syncoutputs=True, simulator=False, debug=False, replace_io_file=None, direct_output=False</i>)
<p> <p>
Instantiiert die Grundfunktionen. Instantiiert die Grundfunktionen.
</p><dl> </p><dl>
@@ -448,6 +448,9 @@ Gibt bei allen Fehlern komplette Meldungen aus
</dd><dt><i>replace_io_file</i></dt> </dd><dt><i>replace_io_file</i></dt>
<dd> <dd>
Replace IO Konfiguration aus Datei laden Replace IO Konfiguration aus Datei laden
</dd><dt><i>direct_output</i></dt>
<dd>
Write outputs immediately to process image (slow)
</dd> </dd>
</dl><a NAME="RevPiNetIO._create_myfh" ID="RevPiNetIO._create_myfh"></a> </dl><a NAME="RevPiNetIO._create_myfh" ID="RevPiNetIO._create_myfh"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -539,7 +542,7 @@ Static Methods</h3>
<a NAME="RevPiNetIODriver.__init__" ID="RevPiNetIODriver.__init__"></a> <a NAME="RevPiNetIODriver.__init__" ID="RevPiNetIODriver.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiNetIODriver (Constructor)</h3> RevPiNetIODriver (Constructor)</h3>
<b>RevPiNetIODriver</b>(<i>address, virtdev, autorefresh=False, monitoring=False, syncoutputs=True, debug=False, replace_io_file=None</i>) <b>RevPiNetIODriver</b>(<i>address, virtdev, autorefresh=False, monitoring=False, syncoutputs=True, debug=False, replace_io_file=None, direct_output=False</i>)
<p> <p>
Instantiiert die Grundfunktionen. Instantiiert die Grundfunktionen.
</p><p> </p><p>
@@ -602,7 +605,7 @@ Static Methods</h3>
<a NAME="RevPiNetIOSelected.__init__" ID="RevPiNetIOSelected.__init__"></a> <a NAME="RevPiNetIOSelected.__init__" ID="RevPiNetIOSelected.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiNetIOSelected (Constructor)</h3> RevPiNetIOSelected (Constructor)</h3>
<b>RevPiNetIOSelected</b>(<i>address, deviceselection, autorefresh=False, monitoring=False, syncoutputs=True, simulator=False, debug=False, replace_io_file=None</i>) <b>RevPiNetIOSelected</b>(<i>address, deviceselection, autorefresh=False, monitoring=False, syncoutputs=True, simulator=False, debug=False, replace_io_file=None, direct_output=False</i>)
<p> <p>
Instantiiert nur fuer angegebene Devices die Grundfunktionen. Instantiiert nur fuer angegebene Devices die Grundfunktionen.
</p><p> </p><p>

View File

@@ -154,6 +154,7 @@ revpimodio2.modio.RevPiModIO._get_simulator?5()
revpimodio2.modio.RevPiModIO._gotioerror?5(action, e=None) revpimodio2.modio.RevPiModIO._gotioerror?5(action, e=None)
revpimodio2.modio.RevPiModIO._set_cycletime?5(milliseconds) revpimodio2.modio.RevPiModIO._set_cycletime?5(milliseconds)
revpimodio2.modio.RevPiModIO._set_maxioerrors?5(value) revpimodio2.modio.RevPiModIO._set_maxioerrors?5(value)
revpimodio2.modio.RevPiModIO._simulate_ioctl?5(request, arg=b'')
revpimodio2.modio.RevPiModIO.autorefresh_all?4() revpimodio2.modio.RevPiModIO.autorefresh_all?4()
revpimodio2.modio.RevPiModIO.cleanup?4() revpimodio2.modio.RevPiModIO.cleanup?4()
revpimodio2.modio.RevPiModIO.configrsc?7 revpimodio2.modio.RevPiModIO.configrsc?7
@@ -204,9 +205,9 @@ revpimodio2.netio.RevPiNetIO.disconnect?4()
revpimodio2.netio.RevPiNetIO.get_jconfigrsc?4() revpimodio2.netio.RevPiNetIO.get_jconfigrsc?4()
revpimodio2.netio.RevPiNetIO.net_cleardefaultvalues?4(device=None) revpimodio2.netio.RevPiNetIO.net_cleardefaultvalues?4(device=None)
revpimodio2.netio.RevPiNetIO.net_setdefaultvalues?4(device=None) revpimodio2.netio.RevPiNetIO.net_setdefaultvalues?4(device=None)
revpimodio2.netio.RevPiNetIO?1(address, autorefresh=False, monitoring=False, syncoutputs=True, simulator=False, debug=False, replace_io_file=None) revpimodio2.netio.RevPiNetIO?1(address, autorefresh=False, monitoring=False, syncoutputs=True, simulator=False, debug=False, replace_io_file=None, direct_output=False)
revpimodio2.netio.RevPiNetIODriver?1(address, virtdev, autorefresh=False, monitoring=False, syncoutputs=True, debug=False, replace_io_file=None) revpimodio2.netio.RevPiNetIODriver?1(address, virtdev, autorefresh=False, monitoring=False, syncoutputs=True, debug=False, replace_io_file=None, direct_output=False)
revpimodio2.netio.RevPiNetIOSelected?1(address, deviceselection, autorefresh=False, monitoring=False, syncoutputs=True, simulator=False, debug=False, replace_io_file=None) revpimodio2.netio.RevPiNetIOSelected?1(address, deviceselection, autorefresh=False, monitoring=False, syncoutputs=True, simulator=False, debug=False, replace_io_file=None, direct_output=False)
revpimodio2.netio._sysdeldirty?8 revpimodio2.netio._sysdeldirty?8
revpimodio2.netio._sysexit?8 revpimodio2.netio._sysexit?8
revpimodio2.netio._sysflush?8 revpimodio2.netio._sysflush?8

View File

@@ -5,11 +5,9 @@ __copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "LGPLv3" __license__ = "LGPLv3"
import struct import struct
import warnings
from re import match as rematch from re import match as rematch
from threading import Event from threading import Event
from revpimodio2 import RISING, FALLING, BOTH, INP, MEM, consttostr from revpimodio2 import RISING, FALLING, BOTH, INP, MEM, consttostr
from .netio import RevPiNetIO
try: try:
# Funktioniert nur auf Unix # Funktioniert nur auf Unix
from fcntl import ioctl from fcntl import ioctl
@@ -536,21 +534,8 @@ class IOBase(object):
if self._parentdevice._modio._direct_output: if self._parentdevice._modio._direct_output:
# Direktes Schreiben der Outputs # Direktes Schreiben der Outputs
# TODO: Abfragen minimieren für Schreiben der Outputs
if isinstance(self._parentdevice._modio, RevPiNetIO): if self._parentdevice._modio._run_on_pi:
# IOCTL über Netzwerk
with self._parentdevice._modio._myfh_lck:
try:
self._parentdevice._modio._myfh.ioctl(
19216,
self.__bit_ioctl_on if value
else self.__bit_ioctl_off
)
except Exception as e:
self._parentdevice._modio._gotioerror(
"net_ioctl", e)
else:
# IOCTL auf dem RevPi # IOCTL auf dem RevPi
with self._parentdevice._modio._myfh_lck: with self._parentdevice._modio._myfh_lck:
try: try:
@@ -564,6 +549,31 @@ class IOBase(object):
except Exception as e: except Exception as e:
self._parentdevice._modio._gotioerror("ioset", e) self._parentdevice._modio._gotioerror("ioset", e)
elif hasattr(self._parentdevice._modio._myfh, "ioctl"):
# IOCTL über Netzwerk
with self._parentdevice._modio._myfh_lck:
try:
self._parentdevice._modio._myfh.ioctl(
19216,
self.__bit_ioctl_on if value
else self.__bit_ioctl_off
)
except Exception as e:
self._parentdevice._modio._gotioerror(
"net_ioset", e)
else:
# IOCTL in Datei simulieren
try:
# Set value durchführen (Funktion K+16)
self._parentdevice._modio._simulate_ioctl(
19216,
self.__bit_ioctl_on if value
else self.__bit_ioctl_off
)
except Exception as e:
self._parentdevice._modio._gotioerror("file_ioset", e)
else: else:
# Gepuffertes Schreiben der Outputs # Gepuffertes Schreiben der Outputs
@@ -901,24 +911,7 @@ class IntIOCounter(IntIO):
"can not reset counter, while system is in simulator mode" "can not reset counter, while system is in simulator mode"
) )
if isinstance(self._parentdevice._modio, RevPiNetIO): if self._parentdevice._modio._run_on_pi:
# IOCTL über Netzwerk
with self._parentdevice._modio._myfh_lck:
try:
self._parentdevice._modio._myfh.ioctl(
19220, self.__ioctl_arg
)
except Exception as e:
self._parentdevice._modio._gotioerror("net_ioctl", e)
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",
RuntimeWarning
)
else:
# IOCTL auf dem RevPi # IOCTL auf dem RevPi
with self._parentdevice._modio._myfh_lck: with self._parentdevice._modio._myfh_lck:
try: try:
@@ -928,7 +921,27 @@ class IntIOCounter(IntIO):
19220, self.__ioctl_arg 19220, self.__ioctl_arg
) )
except Exception as e: except Exception as e:
self._parentdevice._modio._gotioerror("ioctl", e) self._parentdevice._modio._gotioerror("iorst", e)
elif hasattr(self._parentdevice._modio._myfh, "ioctl"):
# IOCTL über Netzwerk
with self._parentdevice._modio._myfh_lck:
try:
self._parentdevice._modio._myfh.ioctl(
19220, self.__ioctl_arg
)
except Exception as e:
self._parentdevice._modio._gotioerror("net_iorst", e)
else:
# IOCTL in Datei simulieren
try:
# Set value durchführen (Funktion K+20)
self._parentdevice._modio._simulate_ioctl(
19220, self.__ioctl_arg
)
except Exception as e:
self._parentdevice._modio._gotioerror("file_iorst", e)
class IntIOReplaceable(IntIO): class IntIOReplaceable(IntIO):

View File

@@ -9,9 +9,11 @@ from configparser import ConfigParser
from json import load as jload from json import load as jload
from multiprocessing import cpu_count from multiprocessing import cpu_count
from os import access, F_OK, R_OK from os import access, F_OK, R_OK
from os import stat as osstat
from queue import Empty from queue import Empty
from revpimodio2 import acheck from revpimodio2 import acheck
from signal import signal, SIG_DFL, SIGINT, SIGTERM from signal import signal, SIG_DFL, SIGINT, SIGTERM
from stat import S_ISCHR
from threading import Thread, Event, Lock from threading import Thread, Event, Lock
from timeit import default_timer from timeit import default_timer
@@ -35,7 +37,7 @@ class RevPiModIO(object):
"_maxioerrors", "_myfh", "_myfh_lck", "_monitoring", "_procimg", \ "_maxioerrors", "_myfh", "_myfh_lck", "_monitoring", "_procimg", \
"_simulator", "_syncoutputs", "_th_mainloop", "_waitexit", \ "_simulator", "_syncoutputs", "_th_mainloop", "_waitexit", \
"core", "app", "device", "exitsignal", "io", "summary", "_debug", \ "core", "app", "device", "exitsignal", "io", "summary", "_debug", \
"_lck_replace_io", "_replace_io_file" "_lck_replace_io", "_replace_io_file", "_run_on_pi"
def __init__( def __init__(
self, autorefresh=False, monitoring=False, syncoutputs=True, self, autorefresh=False, monitoring=False, syncoutputs=True,
@@ -106,12 +108,10 @@ class RevPiModIO(object):
# Event für Benutzeraktionen # Event für Benutzeraktionen
self.exitsignal = Event() self.exitsignal = Event()
if self._direct_output and not \ try:
(self._procimg == "/dev/piControl0" or self._run_on_pi = S_ISCHR(osstat(self._procimg).st_mode)
isinstance(self, RevPiNetIO)): except Exception:
raise RuntimeError( self._run_on_pi = False
"use direct_output with piControl0 or RevPiNetIO only"
)
# Nur Konfigurieren, wenn nicht vererbt # Nur Konfigurieren, wenn nicht vererbt
if type(self) == RevPiModIO: if type(self) == RevPiModIO:
@@ -471,6 +471,57 @@ class RevPiModIO(object):
else: else:
raise ValueError("value must be 0 or a positive integer") raise ValueError("value must be 0 or a positive integer")
def _simulate_ioctl(self, request, arg=b''):
"""Simuliert IOCTL Funktionen auf procimg Datei.
@param request IO Request
@param arg: Request argument"""
if request == 19216:
# Einzelnes Bit setzen
byte_address = int.from_bytes(arg[:2], byteorder="little")
bit_address = arg[2]
new_value = bool(0 if len(arg) <= 3 else arg[3])
# Simulatonsmodus schreibt direkt in Datei
with self._myfh_lck:
self._myfh.seek(byte_address)
int_byte = int.from_bytes(
self._myfh.read(1), byteorder="little"
)
int_bit = 1 << bit_address
if not bool(int_byte & int_bit) == new_value:
if new_value:
int_byte += int_bit
else:
int_byte -= int_bit
self._myfh.seek(byte_address)
self._myfh.write(int_byte.to_bytes(1, byteorder="little"))
if self._buffedwrite:
self._myfh.flush()
elif request == 19220:
# FIXME: Implement
# Counterwert auf 0 setzen
dev_position = arg[0]
bit_field = int.from_bytes(arg[2:], byteorder="little")
io_byte = -1
for i in range(16):
if bool(bit_field & 1 << i):
io_byte = self.device[dev_position].offset \
+ int(self.device[dev_position]._lst_counter[i])
break
if io_byte == -1:
raise RuntimeError("count not reset counter io in file")
with self._myfh_lck:
self._myfh.seek(io_byte)
self._myfh.write(b'\x00\x00\x00\x00')
if self._buffedwrite:
self._myfh.flush()
def autorefresh_all(self): def autorefresh_all(self):
"""Setzt alle Devices in autorefresh Funktion.""" """Setzt alle Devices in autorefresh Funktion."""
for dev in self.device: for dev in self.device:
@@ -951,7 +1002,6 @@ class RevPiModIO(object):
""" """
if self._direct_output: if self._direct_output:
# TODO: Wie soll das bei direct_output umgesetzt werden?
return True return True
if self._monitoring: if self._monitoring:

View File

@@ -490,7 +490,7 @@ class RevPiNetIO(_RevPiModIO):
def __init__( def __init__(
self, address, autorefresh=False, monitoring=False, self, address, autorefresh=False, monitoring=False,
syncoutputs=True, simulator=False, debug=False, syncoutputs=True, simulator=False, debug=False,
replace_io_file=None): replace_io_file=None, direct_output=False):
"""Instantiiert die Grundfunktionen. """Instantiiert die Grundfunktionen.
@param address: IP-Adresse <class 'str'> / (IP, Port) <class 'tuple'> @param address: IP-Adresse <class 'str'> / (IP, Port) <class 'tuple'>
@@ -500,6 +500,7 @@ class RevPiNetIO(_RevPiModIO):
@param simulator Laedt das Modul als Simulator und vertauscht IOs @param simulator Laedt das Modul als Simulator und vertauscht IOs
@param debug Gibt bei allen Fehlern komplette Meldungen aus @param debug Gibt bei allen Fehlern komplette Meldungen aus
@param replace_io_file Replace IO Konfiguration aus Datei laden @param replace_io_file Replace IO Konfiguration aus Datei laden
@param direct_output Write outputs immediately to process image (slow)
""" """
check_ip = compile( check_ip = compile(
@@ -549,7 +550,8 @@ class RevPiNetIO(_RevPiModIO):
None, None,
simulator, simulator,
debug, debug,
replace_io_file replace_io_file,
direct_output
) )
# Netzwerkfilehandler anlegen # Netzwerkfilehandler anlegen
@@ -661,7 +663,7 @@ class RevPiNetIOSelected(RevPiNetIO):
def __init__( def __init__(
self, address, deviceselection, autorefresh=False, self, address, deviceselection, autorefresh=False,
monitoring=False, syncoutputs=True, simulator=False, debug=False, monitoring=False, syncoutputs=True, simulator=False, debug=False,
replace_io_file=None): replace_io_file=None, direct_output=False):
"""Instantiiert nur fuer angegebene Devices die Grundfunktionen. """Instantiiert nur fuer angegebene Devices die Grundfunktionen.
Der Parameter deviceselection kann eine einzelne Der Parameter deviceselection kann eine einzelne
@@ -675,7 +677,7 @@ class RevPiNetIOSelected(RevPiNetIO):
""" """
super().__init__( super().__init__(
address, autorefresh, monitoring, syncoutputs, simulator, debug, address, autorefresh, monitoring, syncoutputs, simulator, debug,
replace_io_file replace_io_file, direct_output
) )
# Device liste erstellen # Device liste erstellen
@@ -729,7 +731,8 @@ class RevPiNetIODriver(RevPiNetIOSelected):
def __init__( def __init__(
self, address, virtdev, autorefresh=False, monitoring=False, self, address, virtdev, autorefresh=False, monitoring=False,
syncoutputs=True, debug=False, replace_io_file=None): syncoutputs=True, debug=False, replace_io_file=None,
direct_output=False):
"""Instantiiert die Grundfunktionen. """Instantiiert die Grundfunktionen.
Parameter 'monitoring' und 'simulator' stehen hier nicht zur Parameter 'monitoring' und 'simulator' stehen hier nicht zur
@@ -743,5 +746,5 @@ class RevPiNetIODriver(RevPiNetIOSelected):
# Parent mit monitoring=False und simulator=True laden # Parent mit monitoring=False und simulator=True laden
super().__init__( super().__init__(
address, virtdev, autorefresh, False, syncoutputs, True, debug, address, virtdev, autorefresh, False, syncoutputs, True, debug,
replace_io_file replace_io_file, direct_output
) )