mirror of
https://github.com/naruxde/revpimodio2.git
synced 2025-11-08 13:53:53 +01:00
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:
@@ -33,6 +33,9 @@ Classes</h3>
|
|||||||
<td><a style="color:#0000FF" href="#DeviceList">DeviceList</a></td>
|
<td><a style="color:#0000FF" href="#DeviceList">DeviceList</a></td>
|
||||||
<td>Basisklasse fuer direkten Zugriff auf Device Objekte.</td>
|
<td>Basisklasse fuer direkten Zugriff auf Device Objekte.</td>
|
||||||
</tr><tr>
|
</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><a style="color:#0000FF" href="#Gateway">Gateway</a></td>
|
||||||
<td>Klasse fuer die RevPi Gateway-Devices.</td>
|
<td>Klasse fuer die RevPi Gateway-Devices.</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
@@ -1076,6 +1079,51 @@ Attributobjekt
|
|||||||
</dl>
|
</dl>
|
||||||
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
|
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
|
||||||
<hr /><hr />
|
<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>
|
<a NAME="Gateway" ID="Gateway"></a>
|
||||||
<h2 style="background-color:#FFFFFF;color:#0000FF">Gateway</h2>
|
<h2 style="background-color:#FFFFFF;color:#0000FF">Gateway</h2>
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -851,6 +851,9 @@ Class Methods</h3>
|
|||||||
Methods</h3>
|
Methods</h3>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<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><a style="color:#0000FF" href="#IntIOCounter.reset">reset</a></td>
|
||||||
<td>Setzt den Counter des Inputs zurueck.</td>
|
<td>Setzt den Counter des Inputs zurueck.</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -860,7 +863,23 @@ Static Methods</h3>
|
|||||||
<table>
|
<table>
|
||||||
<tr><td>None</td></tr>
|
<tr><td>None</td></tr>
|
||||||
</table>
|
</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">
|
<h3 style="background-color:#FFFFFF;color:#FF0000">
|
||||||
IntIOCounter.reset</h3>
|
IntIOCounter.reset</h3>
|
||||||
<b>reset</b>(<i></i>)
|
<b>reset</b>(<i></i>)
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ revpimodio2.device.Device.syncoutputs?4()
|
|||||||
revpimodio2.device.Device.writeprocimg?4()
|
revpimodio2.device.Device.writeprocimg?4()
|
||||||
revpimodio2.device.Device?1(parentmodio, dict_device, simulator=False)
|
revpimodio2.device.Device?1(parentmodio, dict_device, simulator=False)
|
||||||
revpimodio2.device.DeviceList?1()
|
revpimodio2.device.DeviceList?1()
|
||||||
|
revpimodio2.device.DioModule?1(parentmodio, dict_device, simulator=False)
|
||||||
revpimodio2.device.Gateway.get_rawbytes?4()
|
revpimodio2.device.Gateway.get_rawbytes?4()
|
||||||
revpimodio2.device.Gateway?1(parent, dict_device, simulator=False)
|
revpimodio2.device.Gateway?1(parent, dict_device, simulator=False)
|
||||||
revpimodio2.device.Virtual.writeinputdefaults?4()
|
revpimodio2.device.Virtual.writeinputdefaults?4()
|
||||||
@@ -126,6 +127,7 @@ revpimodio2.io.IntIO.set_intvalue?4(value)
|
|||||||
revpimodio2.io.IntIO.signed?7
|
revpimodio2.io.IntIO.signed?7
|
||||||
revpimodio2.io.IntIO.value?7
|
revpimodio2.io.IntIO.value?7
|
||||||
revpimodio2.io.IntIOCounter.reset?4()
|
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.IntIOReplaceable.replace_io?4(name, frm, **kwargs)
|
||||||
revpimodio2.io.StructIO._get_frm?5()
|
revpimodio2.io.StructIO._get_frm?5()
|
||||||
revpimodio2.io.StructIO._get_signed?5()
|
revpimodio2.io.StructIO._get_signed?5()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
Base Device
|
Base Device
|
||||||
Connect Core
|
Connect Core
|
||||||
Core Base
|
Core Base
|
||||||
|
DioModule Device
|
||||||
EventCallback Thread
|
EventCallback Thread
|
||||||
Gateway Device
|
Gateway Device
|
||||||
IntIO IOBase
|
IntIO IOBase
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE Project SYSTEM "Project-5.1.dtd">
|
<!DOCTYPE Project SYSTEM "Project-5.1.dtd">
|
||||||
<!-- eric project file for project revpimodio2 -->
|
<!-- 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 -->
|
<!-- Copyright (C) 2018 Sven Sager, akira@narux.de -->
|
||||||
<Project version="5.1">
|
<Project version="5.1">
|
||||||
<Language>en_US</Language>
|
<Language>en_US</Language>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<ProgLanguage mixed="0">Python3</ProgLanguage>
|
<ProgLanguage mixed="0">Python3</ProgLanguage>
|
||||||
<ProjectType>Console</ProjectType>
|
<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>
|
<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>
|
<Author>Sven Sager</Author>
|
||||||
<Email>akira@narux.de</Email>
|
<Email>akira@narux.de</Email>
|
||||||
<Eol index="1"/>
|
<Eol index="1"/>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ __author__ = "Sven Sager <akira@revpimodio.org>"
|
|||||||
__copyright__ = "Copyright (C) 2018 Sven Sager"
|
__copyright__ = "Copyright (C) 2018 Sven Sager"
|
||||||
__license__ = "LGPLv3"
|
__license__ = "LGPLv3"
|
||||||
__name__ = "revpimodio2"
|
__name__ = "revpimodio2"
|
||||||
__version__ = "2.2.5"
|
__version__ = "2.3.0"
|
||||||
|
|
||||||
# Global package values
|
# Global package values
|
||||||
OFF = 0
|
OFF = 0
|
||||||
|
|||||||
@@ -258,14 +258,23 @@ class Device(object):
|
|||||||
io_new = IOBase(
|
io_new = IOBase(
|
||||||
self, dict_io[key], iotype, "little", False
|
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:
|
elif isinstance(self, Gateway) and iotype != MEM:
|
||||||
# Ersetzbare IOs erzeugen
|
# Ersetzbare IOs erzeugen
|
||||||
io_new = IntIOReplaceable(
|
io_new = IntIOReplaceable(
|
||||||
self, dict_io[key],
|
self, dict_io[key],
|
||||||
iotype,
|
iotype,
|
||||||
"little",
|
"little",
|
||||||
# Bei AIO (103) signed auf True setzen
|
False
|
||||||
self._producttype == 103
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
io_new = IntIO(
|
io_new = IntIO(
|
||||||
@@ -858,6 +867,32 @@ class Connect(Core):
|
|||||||
wdautotoggle = property(_get_wdtoggle, _set_wdtoggle)
|
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):
|
class Gateway(Device):
|
||||||
|
|
||||||
"""Klasse fuer die RevPi Gateway-Devices.
|
"""Klasse fuer die RevPi Gateway-Devices.
|
||||||
@@ -930,6 +965,7 @@ class Virtual(Gateway):
|
|||||||
|
|
||||||
# Outputs auf Bus schreiben
|
# Outputs auf Bus schreiben
|
||||||
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:
|
||||||
@@ -943,5 +979,5 @@ class Virtual(Gateway):
|
|||||||
|
|
||||||
|
|
||||||
# Nachträglicher Import
|
# Nachträglicher Import
|
||||||
from .io import IOBase, IntIO, IntIOReplaceable
|
from .io import IOBase, IntIO, IntIOCounter, IntIOReplaceable
|
||||||
from revpimodio2 import INP, OUT, MEM
|
from revpimodio2 import INP, OUT, MEM
|
||||||
|
|||||||
@@ -5,9 +5,16 @@ __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, OUT, MEM, consttostr
|
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):
|
class IOEvent(object):
|
||||||
@@ -789,13 +796,56 @@ class IntIOCounter(IntIO):
|
|||||||
|
|
||||||
"""Erweitert die IntIO-Klasse um die .reset() Funktion fuer Counter."""
|
"""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):
|
def reset(self):
|
||||||
"""Setzt den Counter des Inputs zurueck."""
|
"""Setzt den Counter des Inputs zurueck."""
|
||||||
# TODO: Counter ID ermitteln
|
if self._parentdevice._modio._monitoring:
|
||||||
# TODO: Counter reset durchführen
|
raise RuntimeError(
|
||||||
pass
|
"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):
|
class IntIOReplaceable(IntIO):
|
||||||
|
|||||||
@@ -13,12 +13,6 @@ from signal import signal, SIG_DFL, SIGINT, SIGTERM
|
|||||||
from threading import Thread, Event
|
from threading import Thread, Event
|
||||||
from timeit import default_timer
|
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):
|
class RevPiModIO(object):
|
||||||
|
|
||||||
@@ -161,6 +155,7 @@ class RevPiModIO(object):
|
|||||||
device["position"] += 1
|
device["position"] += 1
|
||||||
|
|
||||||
if device["type"] == "BASE":
|
if device["type"] == "BASE":
|
||||||
|
# Basedevices
|
||||||
pt = int(device["productType"])
|
pt = int(device["productType"])
|
||||||
if pt == 95:
|
if pt == 95:
|
||||||
# RevPi Core
|
# RevPi Core
|
||||||
@@ -180,9 +175,17 @@ class RevPiModIO(object):
|
|||||||
self.core = dev_new
|
self.core = dev_new
|
||||||
elif device["type"] == "LEFT_RIGHT":
|
elif device["type"] == "LEFT_RIGHT":
|
||||||
# IOs
|
# IOs
|
||||||
dev_new = devicemodule.Device(
|
pt = int(device["productType"])
|
||||||
self, device, simulator=self._simulator
|
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
|
||||||
|
)
|
||||||
elif device["type"] == "VIRTUAL":
|
elif device["type"] == "VIRTUAL":
|
||||||
# Virtuals
|
# Virtuals
|
||||||
dev_new = devicemodule.Virtual(
|
dev_new = devicemodule.Virtual(
|
||||||
@@ -934,4 +937,10 @@ class RevPiModIODriver(RevPiModIOSelected):
|
|||||||
|
|
||||||
|
|
||||||
# Nachträglicher Import
|
# 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
|
from .netio import RevPiNetIODriver, RevPiNetIO
|
||||||
|
|||||||
Reference in New Issue
Block a user