mirror of
https://github.com/naruxde/revpimodio2.git
synced 2026-09-30 23:04:29 +02:00
Merge tag '2.9.0' into pkg/debian
Release version 2.9.0
This commit is contained in:
commit
fcecc9c770
17 files changed
+659
-12
No files matched your search
Generated
-3
@@ -1,9 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="enabledOnReformat" value="true" />
|
|
||||||
<option name="executionMode" value="BINARY" />
|
|
||||||
<option name="pathToExecutable" value="/opt/homebrew/bin/black" />
|
|
||||||
<option name="sdkName" value="Python 3.11 (revpimodio2)" />
|
<option name="sdkName" value="Python 3.11 (revpimodio2)" />
|
||||||
</component>
|
</component>
|
||||||
<component name="JavaScriptSettings">
|
<component name="JavaScriptSettings">
|
||||||
|
|||||||
Generated
+18
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="PyToolsState">
|
||||||
|
<option name="tools">
|
||||||
|
<map>
|
||||||
|
<entry key="black">
|
||||||
|
<value>
|
||||||
|
<ToolEntry>
|
||||||
|
<option name="enabled" value="true" />
|
||||||
|
<option name="discoveryMode" value="PATH" />
|
||||||
|
<option name="customPathToExecutable" value="/opt/homebrew/bin/black" />
|
||||||
|
</ToolEntry>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Metadata of package."""
|
"""Metadata of package."""
|
||||||
|
|
||||||
__author__ = "Sven Sager <akira@revpimodio.org>"
|
__author__ = "Sven Sager <akira@revpimodio.org>"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
__version__ = "2.8.1"
|
__version__ = "2.9.0"
|
||||||
@@ -12,6 +12,7 @@ With the defined names, the desired data is accessed directly.
|
|||||||
The user can register functions as events for all IOs. The module
|
The user can register functions as events for all IOs. The module
|
||||||
executes these when data changes.
|
executes these when data changes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"IOEvent",
|
"IOEvent",
|
||||||
"RevPiModIO",
|
"RevPiModIO",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Internal functions and values for this package."""
|
"""Internal functions and values for this package."""
|
||||||
|
|
||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Maps the App section from piCtory."""
|
"""Maps the App section from piCtory."""
|
||||||
|
|
||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Module for managing devices."""
|
"""Module for managing devices."""
|
||||||
|
|
||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
@@ -354,8 +355,10 @@ class Device(object):
|
|||||||
elif bool(dict_io[key][7]):
|
elif bool(dict_io[key][7]):
|
||||||
# Use IOBase for bit values
|
# Use IOBase for bit values
|
||||||
io_new = IOBase(self, dict_io[key], iotype, "little", False)
|
io_new = IOBase(self, dict_io[key], iotype, "little", False)
|
||||||
elif isinstance(self, DioModule) and dict_io[key][3] in self._lst_counter:
|
elif (isinstance(self, DioModule) or isinstance(self, MioModule)) and dict_io[key][
|
||||||
# Counter IO on a DI or DIO
|
3
|
||||||
|
] in self._lst_counter:
|
||||||
|
# Counter IO on a DI, DIO or MIO module
|
||||||
io_new = IntIOCounter(
|
io_new = IntIOCounter(
|
||||||
self._lst_counter.index(dict_io[key][3]),
|
self._lst_counter.index(dict_io[key][3]),
|
||||||
self,
|
self,
|
||||||
@@ -2030,6 +2033,23 @@ class DioModule(Device):
|
|||||||
super().__init__(parentmodio, dict_device, simulator=simulator)
|
super().__init__(parentmodio, dict_device, simulator=simulator)
|
||||||
|
|
||||||
|
|
||||||
|
class MioModule(Device):
|
||||||
|
"""Represents a MIO module."""
|
||||||
|
|
||||||
|
__slots__ = "_lst_counter"
|
||||||
|
|
||||||
|
def __init__(self, parentmodio, dict_device, simulator=False):
|
||||||
|
"""
|
||||||
|
Extended device class to recognize IntIOCounter.
|
||||||
|
|
||||||
|
:rev: :func:`Device.__init__()`
|
||||||
|
"""
|
||||||
|
# String list of byte addresses that are a counter.
|
||||||
|
self._lst_counter = list(map(str, range(9, 17, 2)))
|
||||||
|
|
||||||
|
super().__init__(parentmodio, dict_device, simulator=simulator)
|
||||||
|
|
||||||
|
|
||||||
class RoModule(Device):
|
class RoModule(Device):
|
||||||
"""Relais output (RO) module with"""
|
"""Relais output (RO) module with"""
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Error classes of RevPiModIO."""
|
"""Error classes of RevPiModIO."""
|
||||||
|
|
||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""RevPiModIO helper classes and tools."""
|
"""RevPiModIO helper classes and tools."""
|
||||||
|
|
||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
|
|||||||
+20
-5
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""RevPiModIO module for managing IOs."""
|
"""RevPiModIO module for managing IOs."""
|
||||||
|
|
||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
@@ -1130,8 +1131,12 @@ class IntIOCounter(IntIO):
|
|||||||
# Load base class
|
# Load base class
|
||||||
super().__init__(parentdevice, valuelist, iotype, byteorder, signed)
|
super().__init__(parentdevice, valuelist, iotype, byteorder, signed)
|
||||||
|
|
||||||
def reset(self) -> None:
|
def reset(self) -> bool:
|
||||||
"""Resets the counter of the input."""
|
"""
|
||||||
|
Resets the counter of the input.
|
||||||
|
|
||||||
|
:return: True if reset was successful, False otherwise
|
||||||
|
"""
|
||||||
if self._parentdevice._modio._monitoring:
|
if self._parentdevice._modio._monitoring:
|
||||||
raise RuntimeError("can not reset counter, while system is in monitoring mode")
|
raise RuntimeError("can not reset counter, while system is in monitoring mode")
|
||||||
if self._parentdevice._modio._simulator:
|
if self._parentdevice._modio._simulator:
|
||||||
@@ -1145,6 +1150,7 @@ class IntIOCounter(IntIO):
|
|||||||
ioctl(self._parentdevice._modio._myfh, 19220, self.__ioctl_arg)
|
ioctl(self._parentdevice._modio._myfh, 19220, self.__ioctl_arg)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._parentdevice._modio._gotioerror("iorst", e)
|
self._parentdevice._modio._gotioerror("iorst", e)
|
||||||
|
return False
|
||||||
|
|
||||||
elif hasattr(self._parentdevice._modio._myfh, "ioctl"):
|
elif hasattr(self._parentdevice._modio._myfh, "ioctl"):
|
||||||
# IOCTL over network
|
# IOCTL over network
|
||||||
@@ -1153,6 +1159,7 @@ class IntIOCounter(IntIO):
|
|||||||
self._parentdevice._modio._myfh.ioctl(19220, self.__ioctl_arg)
|
self._parentdevice._modio._myfh.ioctl(19220, self.__ioctl_arg)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._parentdevice._modio._gotioerror("net_iorst", e)
|
self._parentdevice._modio._gotioerror("net_iorst", e)
|
||||||
|
return False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Simulate IOCTL in file
|
# Simulate IOCTL in file
|
||||||
@@ -1161,6 +1168,9 @@ class IntIOCounter(IntIO):
|
|||||||
self._parentdevice._modio._simulate_ioctl(19220, self.__ioctl_arg)
|
self._parentdevice._modio._simulate_ioctl(19220, self.__ioctl_arg)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._parentdevice._modio._gotioerror("file_iorst", e)
|
self._parentdevice._modio._gotioerror("file_iorst", e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class IntIOReplaceable(IntIO):
|
class IntIOReplaceable(IntIO):
|
||||||
@@ -1275,7 +1285,8 @@ class RelaisOutput(IOBase):
|
|||||||
This function is only available locally on a Revolution Pi. This
|
This function is only available locally on a Revolution Pi. This
|
||||||
function cannot be used via RevPiNetIO.
|
function cannot be used via RevPiNetIO.
|
||||||
|
|
||||||
:return: Integer of switching cycles as single value or tuple of all
|
:return: Integer of switching cycles as single value or tuple of all. The
|
||||||
|
value -1 indicates an error.
|
||||||
"""
|
"""
|
||||||
# Using ioctl request K+29 = 19229
|
# Using ioctl request K+29 = 19229
|
||||||
if self._parentdevice._modio._run_on_pi:
|
if self._parentdevice._modio._run_on_pi:
|
||||||
@@ -1288,10 +1299,14 @@ class RelaisOutput(IOBase):
|
|||||||
self.__ioctl_arg,
|
self.__ioctl_arg,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# If not implemented, we return the max value and set an error
|
|
||||||
ioctl_return_value = b"\xff" * struct.calcsize(self.__ioctl_arg_format)
|
|
||||||
self._parentdevice._modio._gotioerror("rocounter", e)
|
self._parentdevice._modio._gotioerror("rocounter", e)
|
||||||
|
|
||||||
|
# To report an error, return -1 values
|
||||||
|
if self._bitaddress == -1:
|
||||||
|
return -1, -1, -1, -1
|
||||||
|
else:
|
||||||
|
return -1
|
||||||
|
|
||||||
elif hasattr(self._parentdevice._modio._myfh, "ioctl"):
|
elif hasattr(self._parentdevice._modio._myfh, "ioctl"):
|
||||||
# IOCTL over network
|
# IOCTL over network
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""RevPiModIO main class for piControl0 access."""
|
"""RevPiModIO main class for piControl0 access."""
|
||||||
|
|
||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
@@ -403,6 +404,9 @@ class RevPiModIO(object):
|
|||||||
elif pt == ProductType.RO:
|
elif pt == ProductType.RO:
|
||||||
# RO
|
# RO
|
||||||
dev_new = devicemodule.RoModule(self, device, simulator=self._simulator)
|
dev_new = devicemodule.RoModule(self, device, simulator=self._simulator)
|
||||||
|
elif pt == ProductType.MIO:
|
||||||
|
# MIO
|
||||||
|
dev_new = devicemodule.MioModule(self, device, simulator=self._simulator)
|
||||||
else:
|
else:
|
||||||
# All other IO devices
|
# All other IO devices
|
||||||
dev_new = devicemodule.Device(self, device, simulator=self._simulator)
|
dev_new = devicemodule.Device(self, device, simulator=self._simulator)
|
||||||
@@ -1530,7 +1534,15 @@ class RevPiModIODriver(RevPiModIOSelected):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def run_plc(func, cycletime=50, replace_io_file=None, debug=True, procimg=None, configrsc=None):
|
def run_plc(
|
||||||
|
func,
|
||||||
|
cycletime=50,
|
||||||
|
replace_io_file=None,
|
||||||
|
debug=True,
|
||||||
|
procimg=None,
|
||||||
|
configrsc=None,
|
||||||
|
shared_procimg=False,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Run Revoluton Pi as real plc with cycle loop and exclusive IO access.
|
Run Revoluton Pi as real plc with cycle loop and exclusive IO access.
|
||||||
|
|
||||||
@@ -1557,6 +1569,7 @@ def run_plc(func, cycletime=50, replace_io_file=None, debug=True, procimg=None,
|
|||||||
debug=debug,
|
debug=debug,
|
||||||
procimg=procimg,
|
procimg=procimg,
|
||||||
configrsc=configrsc,
|
configrsc=configrsc,
|
||||||
|
shared_procimg=shared_procimg,
|
||||||
)
|
)
|
||||||
rpi.handlesignalend()
|
rpi.handlesignalend()
|
||||||
return rpi.cycleloop(func, cycletime)
|
return rpi.cycleloop(func, cycletime)
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
"""RevPiModIO main class for network access."""
|
"""RevPiModIO main class for network access."""
|
||||||
|
|
||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Pictory aliases for IO values."""
|
"""Pictory aliases for IO values."""
|
||||||
|
|
||||||
__author__ = "Théo Rozier"
|
__author__ = "Théo Rozier"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""Maps the Summary section from piCtory."""
|
"""Maps the Summary section from piCtory."""
|
||||||
|
|
||||||
__author__ = "Sven Sager"
|
__author__ = "Sven Sager"
|
||||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||||
__license__ = "LGPLv2"
|
__license__ = "LGPLv2"
|
||||||
|
|||||||
@@ -0,0 +1,309 @@
|
|||||||
|
{
|
||||||
|
"App": {
|
||||||
|
"name": "PiCtory",
|
||||||
|
"version": "2.17.3",
|
||||||
|
"saveTS": "20260901080641",
|
||||||
|
"language": "en",
|
||||||
|
"layout": {
|
||||||
|
"north": {
|
||||||
|
"size": 70,
|
||||||
|
"initClosed": false,
|
||||||
|
"initHidden": false
|
||||||
|
},
|
||||||
|
"south": {
|
||||||
|
"size": 353,
|
||||||
|
"initClosed": false,
|
||||||
|
"initHidden": false,
|
||||||
|
"children": {
|
||||||
|
"layout1": {
|
||||||
|
"east": {
|
||||||
|
"size": 500,
|
||||||
|
"initClosed": false,
|
||||||
|
"initHidden": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"east": {
|
||||||
|
"size": 70,
|
||||||
|
"initClosed": true,
|
||||||
|
"initHidden": false,
|
||||||
|
"children": {}
|
||||||
|
},
|
||||||
|
"west": {
|
||||||
|
"size": 340,
|
||||||
|
"initClosed": false,
|
||||||
|
"initHidden": false,
|
||||||
|
"children": {
|
||||||
|
"layout1": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Summary": {
|
||||||
|
"inpTotal": 7,
|
||||||
|
"outTotal": 8
|
||||||
|
},
|
||||||
|
"Devices": [
|
||||||
|
{
|
||||||
|
"GUID": "fa3b69a8-77f1-7f15-d9f0-339646253ace",
|
||||||
|
"id": "device_RevPiConnect5_20240315_1_0_001",
|
||||||
|
"type": "BASE",
|
||||||
|
"productType": "138",
|
||||||
|
"position": "0",
|
||||||
|
"name": "RevPi Connect 5",
|
||||||
|
"bmk": "RevPi Connect 5",
|
||||||
|
"inpVariant": 0,
|
||||||
|
"outVariant": 0,
|
||||||
|
"comment": "This is a RevPi Connect 5 Device",
|
||||||
|
"offset": 0,
|
||||||
|
"inp": {
|
||||||
|
"0": [
|
||||||
|
"RevPiStatus",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"0",
|
||||||
|
true,
|
||||||
|
"0000",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"1": [
|
||||||
|
"RevPiIOCycle",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0001",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"2": [
|
||||||
|
"RS485ErrorCnt",
|
||||||
|
"0",
|
||||||
|
"16",
|
||||||
|
"2",
|
||||||
|
false,
|
||||||
|
"0002",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"3": [
|
||||||
|
"Core_Temperature",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"4",
|
||||||
|
false,
|
||||||
|
"0003",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"4": [
|
||||||
|
"Core_Frequency",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"5",
|
||||||
|
false,
|
||||||
|
"0004",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"out": {
|
||||||
|
"0": [
|
||||||
|
"RevPiReservedByte",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"6",
|
||||||
|
false,
|
||||||
|
"0005",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"1": [
|
||||||
|
"RS485ErrorLimit1",
|
||||||
|
"10",
|
||||||
|
"16",
|
||||||
|
"7",
|
||||||
|
false,
|
||||||
|
"0006",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"2": [
|
||||||
|
"RS485ErrorLimit2",
|
||||||
|
"1000",
|
||||||
|
"16",
|
||||||
|
"9",
|
||||||
|
false,
|
||||||
|
"0007",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"3": [
|
||||||
|
"RevPiLED",
|
||||||
|
"0",
|
||||||
|
"16",
|
||||||
|
"11",
|
||||||
|
true,
|
||||||
|
"0008",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mem": {},
|
||||||
|
"extend": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GUID": "53c792e0-ec3d-8047-bb0c-1afa6772873f",
|
||||||
|
"id": "device_RevPiRO_20231018_1_0_001",
|
||||||
|
"type": "LEFT_RIGHT",
|
||||||
|
"productType": "137",
|
||||||
|
"position": "32",
|
||||||
|
"name": "RevPi RO",
|
||||||
|
"bmk": "RevPi RO",
|
||||||
|
"inpVariant": 0,
|
||||||
|
"outVariant": 0,
|
||||||
|
"comment": "",
|
||||||
|
"offset": 13,
|
||||||
|
"inp": {
|
||||||
|
"0": [
|
||||||
|
"Status",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"0",
|
||||||
|
false,
|
||||||
|
"0000",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"out": {
|
||||||
|
"0": [
|
||||||
|
"RelayOutput_1",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0001",
|
||||||
|
"",
|
||||||
|
"0"
|
||||||
|
],
|
||||||
|
"1": [
|
||||||
|
"RelayOutput_2",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0002",
|
||||||
|
"",
|
||||||
|
"1"
|
||||||
|
],
|
||||||
|
"2": [
|
||||||
|
"RelayOutput_3",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0003",
|
||||||
|
"",
|
||||||
|
"2"
|
||||||
|
],
|
||||||
|
"3": [
|
||||||
|
"RelayOutput_4",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0004",
|
||||||
|
"",
|
||||||
|
"3"
|
||||||
|
],
|
||||||
|
"4": [
|
||||||
|
"RelayOutputPadding_5",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0005",
|
||||||
|
"",
|
||||||
|
"4"
|
||||||
|
],
|
||||||
|
"5": [
|
||||||
|
"RelayOutputPadding_6",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0006",
|
||||||
|
"",
|
||||||
|
"5"
|
||||||
|
],
|
||||||
|
"6": [
|
||||||
|
"RelayOutputPadding_7",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0007",
|
||||||
|
"",
|
||||||
|
"6"
|
||||||
|
],
|
||||||
|
"7": [
|
||||||
|
"RelayOutputPadding_8",
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0008",
|
||||||
|
"",
|
||||||
|
"7"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mem": {
|
||||||
|
"0": [
|
||||||
|
"RelayCycleWarningThreshold_1",
|
||||||
|
"0",
|
||||||
|
"32",
|
||||||
|
"2",
|
||||||
|
false,
|
||||||
|
"0009",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"1": [
|
||||||
|
"RelayCycleWarningThreshold_2",
|
||||||
|
"0",
|
||||||
|
"32",
|
||||||
|
"6",
|
||||||
|
false,
|
||||||
|
"0010",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"2": [
|
||||||
|
"RelayCycleWarningThreshold_3",
|
||||||
|
"0",
|
||||||
|
"32",
|
||||||
|
"10",
|
||||||
|
false,
|
||||||
|
"0011",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"3": [
|
||||||
|
"RelayCycleWarningThreshold_4",
|
||||||
|
"0",
|
||||||
|
"32",
|
||||||
|
"14",
|
||||||
|
false,
|
||||||
|
"0012",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"extend": {}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Connections": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
{
|
||||||
|
"App": {
|
||||||
|
"name": "PiCtory",
|
||||||
|
"version": "2.17.3",
|
||||||
|
"saveTS": "20260901080758",
|
||||||
|
"language": "en",
|
||||||
|
"layout": {
|
||||||
|
"north": {
|
||||||
|
"size": 70,
|
||||||
|
"initClosed": false,
|
||||||
|
"initHidden": false
|
||||||
|
},
|
||||||
|
"south": {
|
||||||
|
"size": 353,
|
||||||
|
"initClosed": false,
|
||||||
|
"initHidden": false,
|
||||||
|
"children": {
|
||||||
|
"layout1": {
|
||||||
|
"east": {
|
||||||
|
"size": 500,
|
||||||
|
"initClosed": false,
|
||||||
|
"initHidden": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"east": {
|
||||||
|
"size": 70,
|
||||||
|
"initClosed": true,
|
||||||
|
"initHidden": false,
|
||||||
|
"children": {}
|
||||||
|
},
|
||||||
|
"west": {
|
||||||
|
"size": 340,
|
||||||
|
"initClosed": false,
|
||||||
|
"initHidden": false,
|
||||||
|
"children": {
|
||||||
|
"layout1": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Summary": {
|
||||||
|
"inpTotal": 7,
|
||||||
|
"outTotal": 8
|
||||||
|
},
|
||||||
|
"Devices": [
|
||||||
|
{
|
||||||
|
"GUID": "fa3b69a8-77f1-7f15-d9f0-339646253ace",
|
||||||
|
"id": "device_RevPiConnect5_20240315_1_0_001",
|
||||||
|
"type": "BASE",
|
||||||
|
"productType": "138",
|
||||||
|
"position": "0",
|
||||||
|
"name": "RevPi Connect 5",
|
||||||
|
"bmk": "RevPi Connect 5",
|
||||||
|
"inpVariant": 0,
|
||||||
|
"outVariant": 0,
|
||||||
|
"comment": "This is a RevPi Connect 5 Device",
|
||||||
|
"offset": 0,
|
||||||
|
"inp": {
|
||||||
|
"0": [
|
||||||
|
"RevPiStatus",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"0",
|
||||||
|
true,
|
||||||
|
"0000",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"1": [
|
||||||
|
"RevPiIOCycle",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0001",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"2": [
|
||||||
|
"RS485ErrorCnt",
|
||||||
|
"0",
|
||||||
|
"16",
|
||||||
|
"2",
|
||||||
|
false,
|
||||||
|
"0002",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"3": [
|
||||||
|
"Core_Temperature",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"4",
|
||||||
|
false,
|
||||||
|
"0003",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"4": [
|
||||||
|
"Core_Frequency",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"5",
|
||||||
|
false,
|
||||||
|
"0004",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"out": {
|
||||||
|
"0": [
|
||||||
|
"RevPiReservedByte",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"6",
|
||||||
|
false,
|
||||||
|
"0005",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"1": [
|
||||||
|
"RS485ErrorLimit1",
|
||||||
|
"10",
|
||||||
|
"16",
|
||||||
|
"7",
|
||||||
|
false,
|
||||||
|
"0006",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"2": [
|
||||||
|
"RS485ErrorLimit2",
|
||||||
|
"1000",
|
||||||
|
"16",
|
||||||
|
"9",
|
||||||
|
false,
|
||||||
|
"0007",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"3": [
|
||||||
|
"RevPiLED",
|
||||||
|
"0",
|
||||||
|
"16",
|
||||||
|
"11",
|
||||||
|
true,
|
||||||
|
"0008",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mem": {},
|
||||||
|
"extend": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"GUID": "53c792e0-ec3d-8047-bb0c-1afa6772873f",
|
||||||
|
"id": "device_RevPiRO_20231018_1_0_001",
|
||||||
|
"type": "LEFT_RIGHT",
|
||||||
|
"productType": "137",
|
||||||
|
"position": "32",
|
||||||
|
"name": "RevPi RO",
|
||||||
|
"bmk": "RevPi RO",
|
||||||
|
"inpVariant": 0,
|
||||||
|
"outVariant": 1,
|
||||||
|
"comment": "",
|
||||||
|
"offset": 13,
|
||||||
|
"inp": {
|
||||||
|
"0": [
|
||||||
|
"Status_i02",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"0",
|
||||||
|
false,
|
||||||
|
"0000",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"out": {
|
||||||
|
"0": [
|
||||||
|
"RelayOutputs",
|
||||||
|
"0",
|
||||||
|
"8",
|
||||||
|
"1",
|
||||||
|
true,
|
||||||
|
"0001",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mem": {
|
||||||
|
"0": [
|
||||||
|
"RelayCycleWarningThreshold_1_i02",
|
||||||
|
"0",
|
||||||
|
"32",
|
||||||
|
"2",
|
||||||
|
false,
|
||||||
|
"0002",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"1": [
|
||||||
|
"RelayCycleWarningThreshold_2_i02",
|
||||||
|
"0",
|
||||||
|
"32",
|
||||||
|
"6",
|
||||||
|
false,
|
||||||
|
"0003",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"2": [
|
||||||
|
"RelayCycleWarningThreshold_3_i02",
|
||||||
|
"0",
|
||||||
|
"32",
|
||||||
|
"10",
|
||||||
|
false,
|
||||||
|
"0004",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
"3": [
|
||||||
|
"RelayCycleWarningThreshold_4_i02",
|
||||||
|
"0",
|
||||||
|
"32",
|
||||||
|
"14",
|
||||||
|
false,
|
||||||
|
"0005",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"extend": {}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Connections": []
|
||||||
|
}
|
||||||
@@ -105,3 +105,30 @@ class TestIos(TestRevPiModIO):
|
|||||||
self.assertEqual(rpi.device[65]._ba_devdata[32:38], b"\x20\x00\x00\x00\x00\x00")
|
self.assertEqual(rpi.device[65]._ba_devdata[32:38], b"\x20\x00\x00\x00\x00\x00")
|
||||||
rpi.io.OutBit_48.value = True
|
rpi.io.OutBit_48.value = True
|
||||||
self.assertEqual(rpi.device[65]._ba_devdata[32:38], b"\x20\x00\x00\x00\x00\x80")
|
self.assertEqual(rpi.device[65]._ba_devdata[32:38], b"\x20\x00\x00\x00\x00\x80")
|
||||||
|
|
||||||
|
def test_get_switching_cycles(self):
|
||||||
|
rpi = self.modio(configrsc="config_ro_multi.rsc")
|
||||||
|
self.assertEqual(rpi.io.RelayOutput_1.get_switching_cycles(), 0)
|
||||||
|
self.assertEqual(rpi.io.RelayOutput_2.get_switching_cycles(), 0)
|
||||||
|
self.assertEqual(rpi.io.RelayOutput_3.get_switching_cycles(), 0)
|
||||||
|
self.assertEqual(rpi.io.RelayOutput_4.get_switching_cycles(), 0)
|
||||||
|
|
||||||
|
# This will use ioctl calls
|
||||||
|
rpi._run_on_pi = True
|
||||||
|
|
||||||
|
with self.assertWarnsRegex(RuntimeWarning, r"'rocounter' and count \d"):
|
||||||
|
self.assertEqual(rpi.io.RelayOutput_1.get_switching_cycles(), -1)
|
||||||
|
self.assertEqual(rpi.io.RelayOutput_2.get_switching_cycles(), -1)
|
||||||
|
self.assertEqual(rpi.io.RelayOutput_3.get_switching_cycles(), -1)
|
||||||
|
self.assertEqual(rpi.io.RelayOutput_4.get_switching_cycles(), -1)
|
||||||
|
self.assertEqual(rpi.ioerrors, 4)
|
||||||
|
|
||||||
|
rpi = self.modio(configrsc="config_ro_single.rsc")
|
||||||
|
self.assertEqual(rpi.io.RelayOutputs.get_switching_cycles(), (0, 0, 0, 0))
|
||||||
|
|
||||||
|
# This will use ioctl calls
|
||||||
|
rpi._run_on_pi = True
|
||||||
|
|
||||||
|
with self.assertWarnsRegex(RuntimeWarning, r"'rocounter' and count \d"):
|
||||||
|
self.assertEqual(rpi.io.RelayOutputs.get_switching_cycles(), (-1, -1, -1, -1))
|
||||||
|
self.assertEqual(rpi.ioerrors, 1)
|
||||||
Reference in new issue
Block a user