IntIOCounter Klasse erweitert mit ioctl Aufruf

Devices erzeugen IntIOCounter-Objekt, wenn Counteradresse gefunden wird
DioModule Klasse wird für DIO / DI / DO verwendet und ermöglicht Counterreset
This commit is contained in:
2018-12-08 20:29:50 +01:00
parent 1e309091e8
commit fc23394298
10 changed files with 186 additions and 21 deletions

View File

@@ -33,6 +33,9 @@ Classes</h3>
<td><a style="color:#0000FF" href="#DeviceList">DeviceList</a></td>
<td>Basisklasse fuer direkten Zugriff auf Device Objekte.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#DioModule">DioModule</a></td>
<td>Stellt ein DIO / DI / DO Modul dar.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#Gateway">Gateway</a></td>
<td>Klasse fuer die RevPi Gateway-Devices.</td>
</tr><tr>
@@ -1076,6 +1079,51 @@ Attributobjekt
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="DioModule" ID="DioModule"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">DioModule</h2>
<p>
Stellt ein DIO / DI / DO Modul dar.
</p>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Derived from</h3>
Device
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Attributes</h3>
<table>
<tr><td>__slots__</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Class Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Methods</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#DioModule.__init__">DioModule</a></td>
<td>Erweitert Device-Klasse zum Erkennen von IntIOCounter.</td>
</tr>
</table>
<h3 style="background-color:#FFFFFF;color:#FF0000">
Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="DioModule.__init__" ID="DioModule.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
DioModule (Constructor)</h3>
<b>DioModule</b>(<i>parentmodio, dict_device, simulator=False</i>)
<p>
Erweitert Device-Klasse zum Erkennen von IntIOCounter.
</p><dl>
<dt><b>See Also:</b></dt>
<dd>
<a style="color:#0000FF" href="#Device.__init__">Device.__init__(...)</a>
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="Gateway" ID="Gateway"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">Gateway</h2>
<p>

View File

@@ -851,6 +851,9 @@ Class Methods</h3>
Methods</h3>
<table>
<tr>
<td><a style="color:#0000FF" href="#IntIOCounter.__init__">IntIOCounter</a></td>
<td>Instantiierung der IntIOCounter-Klasse.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#IntIOCounter.reset">reset</a></td>
<td>Setzt den Counter des Inputs zurueck.</td>
</tr>
@@ -860,7 +863,23 @@ Static Methods</h3>
<table>
<tr><td>None</td></tr>
</table>
<a NAME="IntIOCounter.reset" ID="IntIOCounter.reset"></a>
<a NAME="IntIOCounter.__init__" ID="IntIOCounter.__init__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IntIOCounter (Constructor)</h3>
<b>IntIOCounter</b>(<i>counter_id, parentdevice, valuelist, iotype, byteorder, signed</i>)
<p>
Instantiierung der IntIOCounter-Klasse.
</p><dl>
<dt><i>counter_id</i></dt>
<dd>
ID fuer den Counter, zu dem der IO gehoert (0-15)
</dd>
</dl><dl>
<dt><b>See Also:</b></dt>
<dd>
<a style="color:#0000FF" href="#IOBase.__init__">IOBase.__init__(...)</a>
</dd>
</dl><a NAME="IntIOCounter.reset" ID="IntIOCounter.reset"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
IntIOCounter.reset</h3>
<b>reset</b>(<i></i>)

View File

@@ -58,6 +58,7 @@ revpimodio2.device.Device.syncoutputs?4()
revpimodio2.device.Device.writeprocimg?4()
revpimodio2.device.Device?1(parentmodio, dict_device, simulator=False)
revpimodio2.device.DeviceList?1()
revpimodio2.device.DioModule?1(parentmodio, dict_device, simulator=False)
revpimodio2.device.Gateway.get_rawbytes?4()
revpimodio2.device.Gateway?1(parent, dict_device, simulator=False)
revpimodio2.device.Virtual.writeinputdefaults?4()
@@ -126,6 +127,7 @@ revpimodio2.io.IntIO.set_intvalue?4(value)
revpimodio2.io.IntIO.signed?7
revpimodio2.io.IntIO.value?7
revpimodio2.io.IntIOCounter.reset?4()
revpimodio2.io.IntIOCounter?1(counter_id, parentdevice, valuelist, iotype, byteorder, signed)
revpimodio2.io.IntIOReplaceable.replace_io?4(name, frm, **kwargs)
revpimodio2.io.StructIO._get_frm?5()
revpimodio2.io.StructIO._get_signed?5()

View File

@@ -1,6 +1,7 @@
Base Device
Connect Core
Core Base
DioModule Device
EventCallback Thread
Gateway Device
IntIO IOBase

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-5.1.dtd">
<!-- eric project file for project revpimodio2 -->
<!-- Saved: 2018-09-30, 14:26:41 -->
<!-- Saved: 2018-12-08, 20:13:17 -->
<!-- Copyright (C) 2018 Sven Sager, akira@narux.de -->
<Project version="5.1">
<Language>en_US</Language>
@@ -9,7 +9,7 @@
<ProgLanguage mixed="0">Python3</ProgLanguage>
<ProjectType>Console</ProjectType>
<Description>Das Modul stellt alle Devices und IOs aus der piCtory Konfiguration in Python3 zur Verfügung. Es ermöglicht den direkten Zugriff auf die Werte über deren vergebenen Namen. Lese- und Schreibaktionen mit dem Prozessabbild werden von dem Modul selbst verwaltet, ohne dass sich der Programmierer um Offsets und Adressen kümmern muss. Für die Gatewaymodule wie ModbusTCP oder Profinet sind eigene 'Inputs' und 'Outputs' über einen bestimmten Adressbereich definierbar. Auf diese IOs kann mit Python3 über den Namen direkt auf die Werte zugegriffen werden.</Description>
<Version>2.2.5</Version>
<Version>2.3.0</Version>
<Author>Sven Sager</Author>
<Email>akira@narux.de</Email>
<Eol index="1"/>

View File

@@ -22,7 +22,7 @@ __author__ = "Sven Sager <akira@revpimodio.org>"
__copyright__ = "Copyright (C) 2018 Sven Sager"
__license__ = "LGPLv3"
__name__ = "revpimodio2"
__version__ = "2.2.5"
__version__ = "2.3.0"
# Global package values
OFF = 0

View File

@@ -258,14 +258,23 @@ class Device(object):
io_new = IOBase(
self, dict_io[key], iotype, "little", False
)
elif isinstance(self, DioModule) and \
dict_io[key][3] in self._lst_counter:
# Counter IO auf einem DI oder DIO
io_new = IntIOCounter(
self._lst_counter.index(dict_io[key][3]),
self, dict_io[key],
iotype,
"little",
False
)
elif isinstance(self, Gateway) and iotype != MEM:
# Ersetzbare IOs erzeugen
io_new = IntIOReplaceable(
self, dict_io[key],
iotype,
"little",
# Bei AIO (103) signed auf True setzen
self._producttype == 103
False
)
else:
io_new = IntIO(
@@ -858,6 +867,32 @@ class Connect(Core):
wdautotoggle = property(_get_wdtoggle, _set_wdtoggle)
class DioModule(Device):
"""Stellt ein DIO / DI / DO Modul dar."""
__slots__ = ("_lst_counter")
def __init__(self, parentmodio, dict_device, simulator=False):
"""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)))
# Basisklasse laden
super().__init__(parentmodio, dict_device, simulator=simulator)
class Gateway(Device):
"""Klasse fuer die RevPi Gateway-Devices.
@@ -930,6 +965,7 @@ class Virtual(Gateway):
# Outputs auf Bus schreiben
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:
@@ -943,5 +979,5 @@ class Virtual(Gateway):
# Nachträglicher Import
from .io import IOBase, IntIO, IntIOReplaceable
from .io import IOBase, IntIO, IntIOCounter, IntIOReplaceable
from revpimodio2 import INP, OUT, MEM

View File

@@ -5,9 +5,16 @@ __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, OUT, MEM, consttostr
from .netio import RevPiNetIO
try:
# Funktioniert nur auf Unix
from fcntl import ioctl
except Exception:
ioctl = None
class IOEvent(object):
@@ -789,13 +796,56 @@ class IntIOCounter(IntIO):
"""Erweitert die IntIO-Klasse um die .reset() Funktion fuer Counter."""
__slots__ = ()
__slots__ = ("__ioctl_arg")
def __init__(
self, counter_id,
parentdevice, valuelist, iotype, byteorder, signed):
"""Instantiierung der IntIOCounter-Klasse.
@param counter_id ID fuer den Counter, zu dem der IO gehoert (0-15)
@see #IOBase.__init__ IOBase.__init__(...)
"""
if not (isinstance(counter_id, int) and 0 <= counter_id <= 15):
raise ValueError("counter_id must be <class 'int'> and 0 - 15")
# Deviceposition + Counter_ID
self.__ioctl_arg = \
parentdevice._position.to_bytes(1, "little") + \
(1 << counter_id).to_bytes(2, "big")
# Basisklasse laden
super().__init__(parentdevice, valuelist, iotype, byteorder, signed)
def reset(self):
"""Setzt den Counter des Inputs zurueck."""
# TODO: Counter ID ermitteln
# TODO: Counter reset durchführen
pass
if self._parentdevice._modio._monitoring:
raise RuntimeError(
"can not reset counter, while system is in monitoring mode"
)
if self._parentdevice._modio._simulator:
raise AttributeError(
"can not reset counter, while system is in simulator mode"
)
if isinstance(self._parentdevice._modio, RevPiNetIO):
# TODO: NetFH ansprechen und an RevPiPyLoad senden
warnings.warn("not jet implemented", FutureWarning)
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)
class IntIOReplaceable(IntIO):

View File

@@ -13,12 +13,6 @@ from signal import signal, SIG_DFL, SIGINT, SIGTERM
from threading import Thread, Event
from timeit import default_timer
from . import app as appmodule
from . import device as devicemodule
from . import helper as helpermodule
from . import summary as summarymodule
from .io import IOList
class RevPiModIO(object):
@@ -161,6 +155,7 @@ class RevPiModIO(object):
device["position"] += 1
if device["type"] == "BASE":
# Basedevices
pt = int(device["productType"])
if pt == 95:
# RevPi Core
@@ -180,6 +175,14 @@ class RevPiModIO(object):
self.core = dev_new
elif device["type"] == "LEFT_RIGHT":
# IOs
pt = int(device["productType"])
if pt == 96 or pt == 97 or pt == 98:
# DIO / DI / DO
dev_new = devicemodule.DioModule(
self, device, simulator=self._simulator
)
else:
# Alle anderen IO-Devices
dev_new = devicemodule.Device(
self, device, simulator=self._simulator
)
@@ -934,4 +937,10 @@ class RevPiModIODriver(RevPiModIOSelected):
# Nachträglicher Import
from . import app as appmodule
from . import device as devicemodule
from . import helper as helpermodule
from . import summary as summarymodule
from .io import IOList
from .netio import RevPiNetIODriver, RevPiNetIO

View File

@@ -17,7 +17,7 @@ setup(
license="LGPLv3",
name="revpimodio2",
version="2.2.5",
version="2.3.0",
packages=["revpimodio2"],
python_requires="~=3.2",