Merge branch 'feature/deviceselect' into srclayout

# Conflicts:
#	src/revpimodio2/modio.py
#	src/revpimodio2/netio.py
This commit is contained in:
2023-01-20 11:18:08 +01:00
3 changed files with 83 additions and 58 deletions

View File

@@ -5,6 +5,7 @@ __copyright__ = "Copyright (C) 2023 Sven Sager"
__license__ = "LGPLv3" __license__ = "LGPLv3"
import warnings import warnings
from collections import namedtuple
from configparser import ConfigParser 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
@@ -24,7 +25,10 @@ from ._internal import acheck, RISING, FALLING, BOTH
from .errors import DeviceNotFoundError from .errors import DeviceNotFoundError
from .io import IOList from .io import IOList
from .io import StructIO from .io import StructIO
from .pictory import ProductType from .pictory import DeviceType, ProductType
DevSelect = namedtuple("DevSelect", ["type", "key", "values"])
"""Leave type, key empty for auto search name and position depending on type in values."""
class RevPiModIO(object): class RevPiModIO(object):
@@ -40,7 +44,7 @@ class RevPiModIO(object):
""" """
__slots__ = "__cleanupfunc", \ __slots__ = "__cleanupfunc", \
"_autorefresh", "_buffedwrite", "_configrsc", "_debug", \ "_autorefresh", "_buffedwrite", "_configrsc", "_debug", "_devselect", \
"_exit", "_exit_level", "_imgwriter", "_ioerror", \ "_exit", "_exit_level", "_imgwriter", "_ioerror", \
"_length", "_looprunning", "_lst_devselect", "_lst_refresh", \ "_length", "_looprunning", "_lst_devselect", "_lst_refresh", \
"_lst_shared", \ "_lst_shared", \
@@ -100,13 +104,13 @@ class RevPiModIO(object):
self.__cleanupfunc = None self.__cleanupfunc = None
self._buffedwrite = False self._buffedwrite = False
self._debug = 1 self._debug = 1
self._devselect = DevSelect("", "", ())
self._exit = Event() self._exit = Event()
self._exit_level = 0 self._exit_level = 0
self._imgwriter = None self._imgwriter = None
self._ioerror = 0 self._ioerror = 0
self._length = 0 self._length = 0
self._looprunning = False self._looprunning = False
self._lst_devselect = []
self._lst_refresh = [] self._lst_refresh = []
self._lst_shared = [] self._lst_shared = []
self._maxioerrors = 0 self._maxioerrors = 0
@@ -206,27 +210,24 @@ class RevPiModIO(object):
# App Klasse instantiieren # App Klasse instantiieren
self.app = appmodule.App(jconfigrsc["App"]) self.app = appmodule.App(jconfigrsc["App"])
# Devicefilter anwenden # Apply device filter
if len(self._lst_devselect) > 0: if self._devselect.values:
lst_found = [] lst_devices = []
if type(self) == RevPiModIODriver \
or type(self) == RevPiNetIODriver:
_searchtype = "VIRTUAL"
else:
_searchtype = None
# Angegebene Devices suchen
for dev in jconfigrsc["Devices"]: for dev in jconfigrsc["Devices"]:
if _searchtype is None or dev["type"] == _searchtype: if self._devselect.type and self._devselect.type != dev["type"]:
if dev["name"] in self._lst_devselect: continue
lst_found.append(dev) if self._devselect.key:
elif dev["position"].isdigit() \ if str(dev[self._devselect.key]) not in self._devselect.values:
and int(dev["position"]) in self._lst_devselect: # The list is always filled with <class 'str'>
lst_found.append(dev) continue
else:
# Auto search depending of value item type
if dev["name"] not in self._devselect.values \
and not (dev["position"].isdigit()
and int(dev["position"]) in self._devselect.values):
continue
# Devices Filter übernehmen lst_devices.append(dev)
lst_devices = lst_found
else: else:
# Devices aus JSON übernehmen # Devices aus JSON übernehmen
lst_devices = jconfigrsc["Devices"] lst_devices = jconfigrsc["Devices"]
@@ -245,7 +246,7 @@ class RevPiModIO(object):
while device["position"] in self.device: while device["position"] in self.device:
device["position"] += 1 device["position"] += 1
if device["type"] == "BASE": if device["type"] == DeviceType.BASE:
# Basedevices # Basedevices
pt = int(device["productType"]) pt = int(device["productType"])
if pt == ProductType.REVPI_CORE: if pt == ProductType.REVPI_CORE:
@@ -277,7 +278,7 @@ class RevPiModIO(object):
dev_new = devicemodule.Base( dev_new = devicemodule.Base(
self, device, simulator=self._simulator self, device, simulator=self._simulator
) )
elif device["type"] == "LEFT_RIGHT": elif device["type"] == DeviceType.LEFT_RIGHT:
# IOs # IOs
pt = int(device["productType"]) pt = int(device["productType"])
if pt == ProductType.DIO or pt == ProductType.DI or pt == ProductType.DO: if pt == ProductType.DIO or pt == ProductType.DI or pt == ProductType.DO:
@@ -290,17 +291,17 @@ class RevPiModIO(object):
dev_new = devicemodule.Device( dev_new = devicemodule.Device(
self, device, simulator=self._simulator self, device, simulator=self._simulator
) )
elif device["type"] == "VIRTUAL": elif device["type"] == DeviceType.VIRTUAL:
# Virtuals # Virtuals
dev_new = devicemodule.Virtual( dev_new = devicemodule.Virtual(
self, device, simulator=self._simulator self, device, simulator=self._simulator
) )
elif device["type"] == "EDGE": elif device["type"] == DeviceType.EDGE:
# Gateways # Gateways
dev_new = devicemodule.Gateway( dev_new = devicemodule.Gateway(
self, device, simulator=self._simulator self, device, simulator=self._simulator
) )
elif device["type"] == "RIGHT": elif device["type"] == DeviceType.RIGHT:
# Connectdevice # Connectdevice
dev_new = None dev_new = None
else: else:
@@ -466,7 +467,7 @@ class RevPiModIO(object):
self.io[parentio].replace_io(name=io, **dict_replace) self.io[parentio].replace_io(name=io, **dict_replace)
except Exception as e: except Exception as e:
# NOTE: Bei Selected/Driver kann nicht geprüft werden # NOTE: Bei Selected/Driver kann nicht geprüft werden
if len(self._lst_devselect) == 0: if len(self._devselect.values) == 0:
raise RuntimeError( raise RuntimeError(
"replace_io_file: can not replace '{0}' with '{1}' " "replace_io_file: can not replace '{0}' with '{1}' "
"| RevPiModIO message: {2}".format(parentio, io, e) "| RevPiModIO message: {2}".format(parentio, io, e)
@@ -1352,19 +1353,27 @@ class RevPiModIOSelected(RevPiModIO):
simulator, debug, replace_io_file, shared_procimg, direct_output simulator, debug, replace_io_file, shared_procimg, direct_output
) )
# Device liste erstellen if type(deviceselection) is not DevSelect:
if type(deviceselection) == list: # Convert to tuple
for dev in deviceselection: if type(deviceselection) in (int, str):
self._lst_devselect.append(dev) deviceselection = (deviceselection,)
else:
self._lst_devselect.append(deviceselection)
for vdev in self._lst_devselect: # Check supported types
if type(vdev) != int and type(vdev) != str: for dev in deviceselection:
raise ValueError( if type(dev) not in (int, str):
"need device position as <class 'int'> or device name as " raise ValueError(
"<class 'str'>" "need device position as <class 'int'> or "
) "device name as <class 'str'>"
)
# Automatic search for name and position depends on type int / str
self._devselect = DevSelect(
"VIRTUAL" if type(self) is RevPiModIODriver else "", "",
tuple(deviceselection),
)
else:
self._devselect = deviceselection
self._configure(self.get_jconfigrsc()) self._configure(self.get_jconfigrsc())
@@ -1377,7 +1386,8 @@ class RevPiModIOSelected(RevPiModIO):
raise DeviceNotFoundError( raise DeviceNotFoundError(
"could not find any given devices in config" "could not find any given devices in config"
) )
elif len(self.device) != len(self._lst_devselect): elif not self._devselect.key \
and len(self.device) != len(self._devselect.values):
if type(self) == RevPiModIODriver: if type(self) == RevPiModIODriver:
raise DeviceNotFoundError( raise DeviceNotFoundError(
"could not find all given VIRTUAL devices in config" "could not find all given VIRTUAL devices in config"
@@ -1454,5 +1464,3 @@ def run_plc(
) )
rpi.handlesignalend() rpi.handlesignalend()
return rpi.cycleloop(func, cycletime) return rpi.cycleloop(func, cycletime)
from .netio import RevPiNetIODriver

View File

@@ -14,8 +14,7 @@ from threading import Event, Lock, Thread
from .device import Device from .device import Device
from .errors import DeviceNotFoundError from .errors import DeviceNotFoundError
from .modio import RevPiModIO as _RevPiModIO from .modio import DevSelect, RevPiModIO as _RevPiModIO
# Synchronisierungsbefehl # Synchronisierungsbefehl
_syssync = b'\x01\x06\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17' _syssync = b'\x01\x06\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17'
# Disconnectbefehl # Disconnectbefehl
@@ -962,19 +961,27 @@ class RevPiNetIOSelected(RevPiNetIO):
replace_io_file, shared_procimg, direct_output replace_io_file, shared_procimg, direct_output
) )
# Device liste erstellen if type(deviceselection) is not DevSelect:
if type(deviceselection) == list: # Convert to tuple
for dev in deviceselection: if type(deviceselection) in (int, str):
self._lst_devselect.append(dev) deviceselection = (deviceselection,)
else:
self._lst_devselect.append(deviceselection)
for vdev in self._lst_devselect: # Check supported types
if type(vdev) != int and type(vdev) != str: for dev in deviceselection:
raise ValueError( if type(dev) not in (int, str):
"need device position as <class 'int'> or device name as " raise ValueError(
"<class 'str'>" "need device position as <class 'int'> or "
) "device name as <class 'str'>"
)
# Automatic search for name and position depends on type int / str
self._devselect = DevSelect(
"VIRTUAL" if type(self) is RevPiNetIODriver else "", "",
tuple(deviceselection),
)
else:
self._devselect = deviceselection
self._configure(self.get_jconfigrsc()) self._configure(self.get_jconfigrsc())
@@ -987,7 +994,8 @@ class RevPiNetIOSelected(RevPiNetIO):
raise DeviceNotFoundError( raise DeviceNotFoundError(
"could not find any given devices in config" "could not find any given devices in config"
) )
elif len(self.device) != len(self._lst_devselect): elif not self._devselect.key \
and len(self.device) != len(self._devselect.values):
if type(self) == RevPiNetIODriver: if type(self) == RevPiNetIODriver:
raise DeviceNotFoundError( raise DeviceNotFoundError(
"could not find all given VIRTUAL devices in config" "could not find all given VIRTUAL devices in config"

View File

@@ -45,6 +45,15 @@ class ProductType:
REVPI_FLAT = 135 REVPI_FLAT = 135
class DeviceType:
"""Module key "type" in piCtory file."""
BASE = "BASE" # Core devices
EDGE = "EDGE" # Gateways
LEFT_RIGHT = "LEFT_RIGHT" # IOs
RIGHT = "RIGHT" # Connect device
VIRTUAL = "VIRTUAL" # All virtual devices
class AIO: class AIO:
"""Memory value mappings for RevPi AIO 1.0 (RevPiAIO_20170301_1_0.rap).""" """Memory value mappings for RevPi AIO 1.0 (RevPiAIO_20170301_1_0.rap)."""
OUT_RANGE_OFF = 0 # Off OUT_RANGE_OFF = 0 # Off