diff --git a/doc/revpimodio2.modio.html b/doc/revpimodio2.modio.html index 09665ce..69dfa04 100644 --- a/doc/revpimodio2.modio.html +++ b/doc/revpimodio2.modio.html @@ -116,6 +116,9 @@ Methods
+Simuliert IOCTL Funktionen auf procimg Datei. +
Instantiiert die Grundfunktionen.
Instantiiert die Grundfunktionen.
@@ -602,7 +605,7 @@ Static Methods
Instantiiert nur fuer angegebene Devices die Grundfunktionen.
diff --git a/eric-revpimodio2.api b/eric-revpimodio2.api
index fcae3d2..a088155 100644
--- a/eric-revpimodio2.api
+++ b/eric-revpimodio2.api
@@ -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
diff --git a/revpimodio2/io.py b/revpimodio2/io.py
index 9f01b42..9829185 100644
--- a/revpimodio2/io.py
+++ b/revpimodio2/io.py
@@ -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):
diff --git a/revpimodio2/modio.py b/revpimodio2/modio.py
index 4b850e5..3ddbe77 100644
--- a/revpimodio2/modio.py
+++ b/revpimodio2/modio.py
@@ -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:
diff --git a/revpimodio2/netio.py b/revpimodio2/netio.py
index d8c899f..97cd5b4 100644
--- a/revpimodio2/netio.py
+++ b/revpimodio2/netio.py
@@ -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