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>Setzt Anzahl der maximal erlaubten Fehler bei Prozessabbildzugriff.</td>
</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>Setzt alle Devices in autorefresh Funktion.</td>
</tr><tr>
@@ -365,6 +368,20 @@ Setzt Anzahl der maximal erlaubten Fehler bei Prozessabbildzugriff.
<dd>
Anzahl erlaubte Fehler
</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>
<h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiModIO.autorefresh_all</h3>

View File

@@ -423,7 +423,7 @@ Static Methods</h3>
<a NAME="RevPiNetIO.__init__" ID="RevPiNetIO.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
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>
Instantiiert die Grundfunktionen.
</p><dl>
@@ -448,6 +448,9 @@ Gibt bei allen Fehlern komplette Meldungen aus
</dd><dt><i>replace_io_file</i></dt>
<dd>
Replace IO Konfiguration aus Datei laden
</dd><dt><i>direct_output</i></dt>
<dd>
Write outputs immediately to process image (slow)
</dd>
</dl><a NAME="RevPiNetIO._create_myfh" ID="RevPiNetIO._create_myfh"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -539,7 +542,7 @@ Static Methods</h3>
<a NAME="RevPiNetIODriver.__init__" ID="RevPiNetIODriver.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
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>
Instantiiert die Grundfunktionen.
</p><p>
@@ -602,7 +605,7 @@ Static Methods</h3>
<a NAME="RevPiNetIOSelected.__init__" ID="RevPiNetIOSelected.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
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>
Instantiiert nur fuer angegebene Devices die Grundfunktionen.
</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._set_cycletime?5(milliseconds)
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.cleanup?4()
revpimodio2.modio.RevPiModIO.configrsc?7
@@ -204,9 +205,9 @@ revpimodio2.netio.RevPiNetIO.disconnect?4()
revpimodio2.netio.RevPiNetIO.get_jconfigrsc?4()
revpimodio2.netio.RevPiNetIO.net_cleardefaultvalues?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.RevPiNetIODriver?1(address, virtdev, autorefresh=False, monitoring=False, syncoutputs=True, 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)
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, direct_output=False)
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._sysexit?8
revpimodio2.netio._sysflush?8

View File

@@ -5,11 +5,9 @@ __copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "LGPLv3"
import struct
import warnings
from re import match as rematch
from threading import Event
from revpimodio2 import RISING, FALLING, BOTH, INP, MEM, consttostr
from .netio import RevPiNetIO
try:
# Funktioniert nur auf Unix
from fcntl import ioctl
@@ -536,21 +534,8 @@ class IOBase(object):
if self._parentdevice._modio._direct_output:
# Direktes Schreiben der Outputs
# TODO: Abfragen minimieren für Schreiben der Outputs
if isinstance(self._parentdevice._modio, RevPiNetIO):
# 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:
if self._parentdevice._modio._run_on_pi:
# IOCTL auf dem RevPi
with self._parentdevice._modio._myfh_lck:
try:
@@ -564,6 +549,31 @@ class IOBase(object):
except Exception as 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:
# Gepuffertes Schreiben der Outputs
@@ -901,24 +911,7 @@ class IntIOCounter(IntIO):
"can not reset counter, while system is in simulator mode"
)
if isinstance(self._parentdevice._modio, RevPiNetIO):
# 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:
if self._parentdevice._modio._run_on_pi:
# IOCTL auf dem RevPi
with self._parentdevice._modio._myfh_lck:
try:
@@ -928,7 +921,27 @@ class IntIOCounter(IntIO):
19220, self.__ioctl_arg
)
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):

View File

@@ -9,9 +9,11 @@ from configparser import ConfigParser
from json import load as jload
from multiprocessing import cpu_count
from os import access, F_OK, R_OK
from os import stat as osstat
from queue import Empty
from revpimodio2 import acheck
from signal import signal, SIG_DFL, SIGINT, SIGTERM
from stat import S_ISCHR
from threading import Thread, Event, Lock
from timeit import default_timer
@@ -35,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"
"_lck_replace_io", "_replace_io_file", "_run_on_pi"
def __init__(
self, autorefresh=False, monitoring=False, syncoutputs=True,
@@ -106,12 +108,10 @@ class RevPiModIO(object):
# Event für Benutzeraktionen
self.exitsignal = Event()
if self._direct_output and not \
(self._procimg == "/dev/piControl0" or
isinstance(self, RevPiNetIO)):
raise RuntimeError(
"use direct_output with piControl0 or RevPiNetIO only"
)
try:
self._run_on_pi = S_ISCHR(osstat(self._procimg).st_mode)
except Exception:
self._run_on_pi = False
# Nur Konfigurieren, wenn nicht vererbt
if type(self) == RevPiModIO:
@@ -471,6 +471,57 @@ class RevPiModIO(object):
else:
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):
"""Setzt alle Devices in autorefresh Funktion."""
for dev in self.device:
@@ -951,7 +1002,6 @@ class RevPiModIO(object):
"""
if self._direct_output:
# TODO: Wie soll das bei direct_output umgesetzt werden?
return True
if self._monitoring:

View File

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