ekfsm 1.3.0a32__py3-none-any.whl → 1.4.0a37__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ekfsm might be problematic. Click here for more details.
- ekfsm/boards/oem/ekf/sq3-quartet.yaml +51 -37
- ekfsm/boards/oem/ekf/z1010.yaml +87 -0
- ekfsm/core/components.py +3 -4
- ekfsm/core/slots.py +7 -2
- ekfsm/core/utils.py +33 -10
- ekfsm/devices/__init__.py +16 -0
- ekfsm/devices/button.py +45 -0
- ekfsm/devices/buttonArray.py +84 -0
- ekfsm/devices/colorLed.py +51 -0
- ekfsm/devices/io4edge.py +94 -0
- ekfsm/devices/ledArray.py +36 -0
- ekfsm/devices/pixelDisplay.py +88 -0
- ekfsm/devices/thermal_humidity.py +44 -0
- ekfsm/devices/watchdog.py +44 -0
- ekfsm/system.py +41 -12
- {ekfsm-1.3.0a32.dist-info → ekfsm-1.4.0a37.dist-info}/METADATA +4 -1
- {ekfsm-1.3.0a32.dist-info → ekfsm-1.4.0a37.dist-info}/RECORD +19 -10
- {ekfsm-1.3.0a32.dist-info → ekfsm-1.4.0a37.dist-info}/WHEEL +0 -0
- {ekfsm-1.3.0a32.dist-info → ekfsm-1.4.0a37.dist-info}/entry_points.txt +0 -0
|
@@ -2,40 +2,54 @@ id: 69
|
|
|
2
2
|
name: "EKF SQ3-QUARTET"
|
|
3
3
|
slot_type: CPCI_S0_PER
|
|
4
4
|
children:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
5
|
+
- device_type: IO4Edge
|
|
6
|
+
name: "BMC"
|
|
7
|
+
children:
|
|
8
|
+
- device_type: PixelDisplay
|
|
9
|
+
name: "display"
|
|
10
|
+
- device_type: ButtonArray
|
|
11
|
+
name: "buttons"
|
|
12
|
+
children:
|
|
13
|
+
- device_type: Button
|
|
14
|
+
name: "up"
|
|
15
|
+
channel_id: 0
|
|
16
|
+
- device_type: Button
|
|
17
|
+
name: "down"
|
|
18
|
+
channel_id: 1
|
|
19
|
+
- device_type: I2CMux
|
|
20
|
+
name: "MUX"
|
|
21
|
+
addr: 0x70
|
|
22
|
+
slot_coding_mask: 0x07
|
|
23
|
+
children:
|
|
24
|
+
- device_type: MuxChannel
|
|
25
|
+
name: "CH00"
|
|
26
|
+
channel_id: 0
|
|
27
|
+
children:
|
|
28
|
+
- device_type: EKFIdentificationIOExpander
|
|
29
|
+
name: "GPIO"
|
|
30
|
+
addr: 0x3D
|
|
31
|
+
provides:
|
|
32
|
+
inventory:
|
|
33
|
+
- revision
|
|
34
|
+
- device_type: EKF_EEPROM
|
|
35
|
+
name: "EEPROM"
|
|
36
|
+
addr: 0x55
|
|
37
|
+
provides:
|
|
38
|
+
inventory:
|
|
39
|
+
- vendor
|
|
40
|
+
- serial
|
|
41
|
+
- model
|
|
42
|
+
- repaired_at
|
|
43
|
+
- manufactured_at
|
|
44
|
+
- device_type: MuxChannel
|
|
45
|
+
name: "CH01"
|
|
46
|
+
channel_id: 1
|
|
47
|
+
children:
|
|
48
|
+
- device_type: MuxChannel
|
|
49
|
+
name: "CH02"
|
|
50
|
+
channel_id: 2
|
|
51
|
+
children:
|
|
52
|
+
- device_type: MuxChannel
|
|
53
|
+
name: "CH03"
|
|
54
|
+
channel_id: 3
|
|
55
|
+
children:
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
id: 112
|
|
2
|
+
name: "EKF Z1010"
|
|
3
|
+
slot_type: CPCI_S0_UTILITY
|
|
4
|
+
children:
|
|
5
|
+
- device_type: I2CMux
|
|
6
|
+
name: "MUX"
|
|
7
|
+
addr: 0x70
|
|
8
|
+
slot_coding_mask: 0x0
|
|
9
|
+
children:
|
|
10
|
+
- device_type: MuxChannel
|
|
11
|
+
name: "CH00"
|
|
12
|
+
channel_id: 0
|
|
13
|
+
children:
|
|
14
|
+
- device_type: EKFIdentificationIOExpander
|
|
15
|
+
name: "GPIO"
|
|
16
|
+
addr: 0x3D
|
|
17
|
+
provides:
|
|
18
|
+
inventory:
|
|
19
|
+
- revision
|
|
20
|
+
- device_type: EKF_EEPROM
|
|
21
|
+
name: "EEPROM"
|
|
22
|
+
addr: 0x55
|
|
23
|
+
provides:
|
|
24
|
+
inventory:
|
|
25
|
+
- vendor
|
|
26
|
+
- serial
|
|
27
|
+
- model
|
|
28
|
+
- repaired_at
|
|
29
|
+
- manufactured_at
|
|
30
|
+
# chassis_inventory:
|
|
31
|
+
# - revision: crevision
|
|
32
|
+
# - write_revision: write_crevision
|
|
33
|
+
# - vendor: cvendor
|
|
34
|
+
# - write_vendor: write_cvendor
|
|
35
|
+
# - serial: cserial
|
|
36
|
+
# - write_serial: write_cserial
|
|
37
|
+
# - model: cmodel
|
|
38
|
+
# - write_model: write_cmodel
|
|
39
|
+
# - unit
|
|
40
|
+
# - write_unit
|
|
41
|
+
# custom_eeprom:
|
|
42
|
+
# - write: write_customer_area
|
|
43
|
+
# - read: customer_area
|
|
44
|
+
- device_type: IO4Edge
|
|
45
|
+
name: "SMC"
|
|
46
|
+
provides:
|
|
47
|
+
management:
|
|
48
|
+
- identify_firmware
|
|
49
|
+
- load_firmware
|
|
50
|
+
- load_parameter
|
|
51
|
+
- get_parameter
|
|
52
|
+
- restart
|
|
53
|
+
children:
|
|
54
|
+
- device_type: LEDArray
|
|
55
|
+
name: "leds"
|
|
56
|
+
children:
|
|
57
|
+
- device_type: ColorLED
|
|
58
|
+
name: "led0"
|
|
59
|
+
channel_id: 0
|
|
60
|
+
- device_type: ColorLED
|
|
61
|
+
name: "led1"
|
|
62
|
+
channel_id: 1
|
|
63
|
+
- device_type: ColorLED
|
|
64
|
+
name: "led2"
|
|
65
|
+
channel_id: 2
|
|
66
|
+
- device_type: ColorLED
|
|
67
|
+
name: "led3"
|
|
68
|
+
channel_id: 3
|
|
69
|
+
- device_type: ColorLED
|
|
70
|
+
name: "led4"
|
|
71
|
+
channel_id: 4
|
|
72
|
+
- device_type: ColorLED
|
|
73
|
+
name: "led5"
|
|
74
|
+
channel_id: 5
|
|
75
|
+
- device_type: ColorLED
|
|
76
|
+
name: "led6"
|
|
77
|
+
channel_id: 6
|
|
78
|
+
- device_type: ColorLED
|
|
79
|
+
name: "led7"
|
|
80
|
+
channel_id: 7
|
|
81
|
+
- device_type: Watchdog
|
|
82
|
+
name: "watchdog"
|
|
83
|
+
provides:
|
|
84
|
+
sysstate:
|
|
85
|
+
- kick
|
|
86
|
+
- device_type: ThermalHumidity
|
|
87
|
+
name: "th"
|
ekfsm/core/components.py
CHANGED
|
@@ -51,7 +51,7 @@ class HWModule(SysTree):
|
|
|
51
51
|
*args,
|
|
52
52
|
**kwargs,
|
|
53
53
|
) -> None:
|
|
54
|
-
from ekfsm.core.utils import deserialize_hardware_tree
|
|
54
|
+
from ekfsm.core.utils import deserialize_hardware_tree, deserialize_module
|
|
55
55
|
|
|
56
56
|
from .slots import SlotType
|
|
57
57
|
|
|
@@ -59,9 +59,8 @@ class HWModule(SysTree):
|
|
|
59
59
|
self._slot: Slot = slot
|
|
60
60
|
self.config = config
|
|
61
61
|
|
|
62
|
-
self.id, self.board_type, slot_type
|
|
63
|
-
|
|
64
|
-
)
|
|
62
|
+
self.id, self.board_type, slot_type = deserialize_module(self.logger, config)
|
|
63
|
+
self.children = deserialize_hardware_tree(self.logger, self.config, parent=self)
|
|
65
64
|
|
|
66
65
|
self.slot_type = SlotType.from_string(slot_type)
|
|
67
66
|
|
ekfsm/core/slots.py
CHANGED
|
@@ -102,7 +102,9 @@ class Slot:
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
def __repr__(self) -> str:
|
|
105
|
-
return
|
|
105
|
+
return (
|
|
106
|
+
f"{self.__class__.__name__}(name={self._name}, slot_type={self.slot_type})"
|
|
107
|
+
)
|
|
106
108
|
|
|
107
109
|
@property
|
|
108
110
|
def name(self) -> str:
|
|
@@ -123,7 +125,10 @@ class Slot:
|
|
|
123
125
|
"""
|
|
124
126
|
Return True if the slot is populated with the desired hardware module type, False otherwise.
|
|
125
127
|
"""
|
|
126
|
-
return
|
|
128
|
+
return (
|
|
129
|
+
self.hwmodule is not None
|
|
130
|
+
and self.hwmodule.board_type.lower() == self._desired_hwmodule_type.lower()
|
|
131
|
+
)
|
|
127
132
|
|
|
128
133
|
|
|
129
134
|
class Slots(Munch):
|
ekfsm/core/utils.py
CHANGED
|
@@ -55,10 +55,14 @@ def import_board(logger: logging.Logger, data, parent=None, abort: bool = False)
|
|
|
55
55
|
import_board(logger, data=child, parent=node, abort=abort)
|
|
56
56
|
except Exception as e:
|
|
57
57
|
if abort:
|
|
58
|
-
logger.error(
|
|
58
|
+
logger.error(
|
|
59
|
+
f"Failed to import sub device {pformat(child)}: {e}. Aborting."
|
|
60
|
+
)
|
|
59
61
|
raise e
|
|
60
62
|
else:
|
|
61
|
-
logger.error(
|
|
63
|
+
logger.error(
|
|
64
|
+
f"Failed to import sub device {pformat(child)}: {e}. Continuing anyway."
|
|
65
|
+
)
|
|
62
66
|
return node
|
|
63
67
|
|
|
64
68
|
|
|
@@ -69,7 +73,9 @@ def provides_validator(x: Any) -> Any:
|
|
|
69
73
|
key, value = next(iter(x.items()))
|
|
70
74
|
if isinstance(key, str) and isinstance(value, str):
|
|
71
75
|
return x
|
|
72
|
-
raise SchemaError(
|
|
76
|
+
raise SchemaError(
|
|
77
|
+
"Each provides item must be either a string or a dictionary with one string key/value pair"
|
|
78
|
+
)
|
|
73
79
|
|
|
74
80
|
|
|
75
81
|
device_schema = Schema({})
|
|
@@ -81,6 +87,7 @@ _device_structure = Schema(
|
|
|
81
87
|
Optional("addr"): int,
|
|
82
88
|
Optional("slot_coding_mask"): int,
|
|
83
89
|
Optional("channel_id"): int,
|
|
90
|
+
Optional("service_suffix"): str,
|
|
84
91
|
Optional("provides"): {
|
|
85
92
|
Optional(str): [Use(provides_validator)],
|
|
86
93
|
},
|
|
@@ -103,30 +110,46 @@ module_schema = Schema(
|
|
|
103
110
|
)
|
|
104
111
|
|
|
105
112
|
|
|
113
|
+
def deserialize_module(logger: logging.Logger, data: dict) -> tuple[str, str, str]:
|
|
114
|
+
"""
|
|
115
|
+
docstring
|
|
116
|
+
"""
|
|
117
|
+
module_schema.validate(data)
|
|
118
|
+
|
|
119
|
+
id, name, slot_type = (data[key] for key in ["id", "name", "slot_type"])
|
|
120
|
+
logger.debug(colored(f"Importing top level module {pformat(name)}", "green"))
|
|
121
|
+
|
|
122
|
+
return id, name, slot_type
|
|
123
|
+
|
|
124
|
+
|
|
106
125
|
def deserialize_hardware_tree(
|
|
107
126
|
logger: logging.Logger, data: dict, parent: "HWModule"
|
|
108
|
-
) ->
|
|
127
|
+
) -> list["Device"]:
|
|
109
128
|
abort = parent.abort
|
|
110
129
|
|
|
111
130
|
module_schema.validate(data)
|
|
112
131
|
|
|
113
|
-
id, name, slot_type = (data.pop(key) for key in ["id", "name", "slot_type"])
|
|
114
|
-
|
|
115
132
|
children = data.pop("children", None)
|
|
116
133
|
if not children:
|
|
117
|
-
return
|
|
134
|
+
return []
|
|
118
135
|
|
|
119
136
|
devices = []
|
|
120
137
|
for child in children:
|
|
121
138
|
try:
|
|
122
|
-
logger.debug(
|
|
139
|
+
logger.debug(
|
|
140
|
+
colored(f"Importing top level device {pformat(child)}", "green")
|
|
141
|
+
)
|
|
123
142
|
|
|
124
143
|
node = import_board(logger, child, parent=parent, abort=abort)
|
|
125
144
|
devices.append(node)
|
|
126
145
|
except Exception as e:
|
|
127
|
-
logger.error(
|
|
146
|
+
logger.error(
|
|
147
|
+
colored(
|
|
148
|
+
f"Failed to import top-level device {pformat(child)}: {e}", "red"
|
|
149
|
+
)
|
|
150
|
+
)
|
|
128
151
|
logger.error(colored("Aborting." if abort else "Continuing anyway", "red"))
|
|
129
152
|
if abort:
|
|
130
153
|
raise
|
|
131
154
|
|
|
132
|
-
return
|
|
155
|
+
return devices
|
ekfsm/devices/__init__.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from ekfsm.devices.coretemp import CoreTemp
|
|
2
2
|
from ekfsm.devices.generic import Device
|
|
3
3
|
from ekfsm.devices.smbios import SMBIOS
|
|
4
|
+
from ekfsm.devices.thermal_humidity import ThermalHumidity
|
|
4
5
|
|
|
5
6
|
from .eeprom import EEPROM, EKF_CCU_EEPROM, EKF_EEPROM
|
|
6
7
|
from .ekf_ccu_uc import EKFCcuUc
|
|
@@ -9,6 +10,13 @@ from .gpio import GPIO, EKFIdentificationIOExpander, GPIOExpander
|
|
|
9
10
|
from .iio_thermal_humidity import IIOThermalHumidity
|
|
10
11
|
from .mux import I2CMux, MuxChannel
|
|
11
12
|
from .pmbus import PMBus, PSUStatus
|
|
13
|
+
from .io4edge import IO4Edge
|
|
14
|
+
from .pixelDisplay import PixelDisplay
|
|
15
|
+
from .buttonArray import ButtonArray
|
|
16
|
+
from .button import Button
|
|
17
|
+
from .colorLed import ColorLED
|
|
18
|
+
from .ledArray import LEDArray
|
|
19
|
+
from .watchdog import Watchdog
|
|
12
20
|
|
|
13
21
|
CLASS_MAP = {
|
|
14
22
|
"GenericDevice": Device,
|
|
@@ -27,4 +35,12 @@ CLASS_MAP = {
|
|
|
27
35
|
"HWMON": CoreTemp,
|
|
28
36
|
"EKFSurLed": EKFSurLed,
|
|
29
37
|
"IIOThermalHumidity": IIOThermalHumidity,
|
|
38
|
+
"ThermalHumidity": ThermalHumidity,
|
|
39
|
+
"IO4Edge": IO4Edge,
|
|
40
|
+
"PixelDisplay": PixelDisplay,
|
|
41
|
+
"ButtonArray": ButtonArray,
|
|
42
|
+
"Button": Button,
|
|
43
|
+
"ColorLED": ColorLED,
|
|
44
|
+
"LEDArray": LEDArray,
|
|
45
|
+
"Watchdog": Watchdog,
|
|
30
46
|
}
|
ekfsm/devices/button.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from typing import Callable
|
|
2
|
+
from ekfsm.devices.generic import Device
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Button(Device):
|
|
6
|
+
"""
|
|
7
|
+
Device class for handling a button array.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
name: str,
|
|
13
|
+
parent: Device,
|
|
14
|
+
children: list[Device] | None = None,
|
|
15
|
+
abort: bool = False,
|
|
16
|
+
channel_id: int = 0,
|
|
17
|
+
*args,
|
|
18
|
+
**kwargs,
|
|
19
|
+
):
|
|
20
|
+
|
|
21
|
+
super().__init__(name, parent, children, abort, *args, **kwargs)
|
|
22
|
+
|
|
23
|
+
self.channel_id = channel_id
|
|
24
|
+
|
|
25
|
+
self._handler: Callable | None = None
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def handler(self):
|
|
29
|
+
"""
|
|
30
|
+
Handle button events with a callback function.
|
|
31
|
+
"""
|
|
32
|
+
return self._handler
|
|
33
|
+
|
|
34
|
+
@handler.setter
|
|
35
|
+
def handler(self, func: Callable | None, *args, **kwargs):
|
|
36
|
+
"""
|
|
37
|
+
Handle button events with a callback function.
|
|
38
|
+
"""
|
|
39
|
+
if callable(func):
|
|
40
|
+
self._handler = func
|
|
41
|
+
else:
|
|
42
|
+
self._handler = None
|
|
43
|
+
|
|
44
|
+
def __repr__(self):
|
|
45
|
+
return f"{self.name}; Channel ID: {self.channel_id}"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from ekfsm.devices.button import Button
|
|
3
|
+
from ekfsm.devices.generic import Device
|
|
4
|
+
from ekfsm.devices.io4edge import IO4Edge
|
|
5
|
+
import io4edge_client.binaryiotypeb as binio
|
|
6
|
+
import io4edge_client.functionblock as fb
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ButtonArray(Device):
|
|
10
|
+
"""
|
|
11
|
+
Device class for handling a button array.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
name: str,
|
|
17
|
+
parent: IO4Edge,
|
|
18
|
+
children: list[Device] | None = None,
|
|
19
|
+
abort: bool = False,
|
|
20
|
+
service_suffix: str | None = None,
|
|
21
|
+
*args,
|
|
22
|
+
**kwargs,
|
|
23
|
+
):
|
|
24
|
+
|
|
25
|
+
super().__init__(name, parent, children, abort, *args, **kwargs)
|
|
26
|
+
|
|
27
|
+
self.name = name
|
|
28
|
+
|
|
29
|
+
if service_suffix is not None:
|
|
30
|
+
self.service_suffix = service_suffix
|
|
31
|
+
else:
|
|
32
|
+
self.service_suffix = name
|
|
33
|
+
|
|
34
|
+
self.service_addr = f"{parent.deviceId}-{self.service_suffix}"
|
|
35
|
+
|
|
36
|
+
self.client = binio.Client(self.service_addr)
|
|
37
|
+
|
|
38
|
+
self.subscriptionType = binio.Pb.SubscriptionType.BINARYIOTYPEB_ON_RISING_EDGE
|
|
39
|
+
self.stream_cfg = fb.Pb.StreamControlStart(
|
|
40
|
+
bucketSamples=1, # 1 sample per bucket, also ein event pro bucket
|
|
41
|
+
keepaliveInterval=10000, # rueckmeldung auch ohne events alle 10 Sekunden
|
|
42
|
+
bufferedSamples=2, # 2 samples werden gepuffert
|
|
43
|
+
low_latency_mode=True, # schickt soweit moeglich sofort die Events
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def read(self, stop_event: threading.Event | None = None, timeout: float = 0.1):
|
|
47
|
+
"""
|
|
48
|
+
Read all button events and dispatch to handlers.
|
|
49
|
+
"""
|
|
50
|
+
self.client.start_stream(
|
|
51
|
+
binio.Pb.StreamControlStart(
|
|
52
|
+
subscribeChannel=tuple(
|
|
53
|
+
binio.Pb.SubscribeChannel(
|
|
54
|
+
channel=button.channel_id,
|
|
55
|
+
subscriptionType=self.subscriptionType,
|
|
56
|
+
)
|
|
57
|
+
for button in self.children
|
|
58
|
+
if isinstance(button, Button)
|
|
59
|
+
)
|
|
60
|
+
),
|
|
61
|
+
self.stream_cfg,
|
|
62
|
+
)
|
|
63
|
+
try:
|
|
64
|
+
while not (stop_event and stop_event.is_set()):
|
|
65
|
+
try:
|
|
66
|
+
_, samples = self.client.read_stream(timeout=timeout)
|
|
67
|
+
for sample in samples.samples:
|
|
68
|
+
for button in self.children:
|
|
69
|
+
if isinstance(button, Button):
|
|
70
|
+
pressed = bool(sample.inputs & (1 << button.channel_id))
|
|
71
|
+
if pressed and button.handler:
|
|
72
|
+
button.handler()
|
|
73
|
+
except TimeoutError:
|
|
74
|
+
continue
|
|
75
|
+
finally:
|
|
76
|
+
try:
|
|
77
|
+
if stop_event:
|
|
78
|
+
stop_event.clear()
|
|
79
|
+
self.client.stop_stream()
|
|
80
|
+
except TimeoutError:
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
def __repr__(self):
|
|
84
|
+
return f"{self.name}; Service Address: {self.service_addr}"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from ekfsm.devices.generic import Device
|
|
2
|
+
from ekfsm.devices.ledArray import LEDArray
|
|
3
|
+
from io4edge_client.api.colorLED.python.colorLED.v1alpha1.colorLED_pb2 import Color
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ColorLED(Device):
|
|
7
|
+
"""
|
|
8
|
+
Device class for handling a color LED.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
name: str,
|
|
14
|
+
parent: LEDArray,
|
|
15
|
+
children: list[Device] | None = None,
|
|
16
|
+
abort: bool = False,
|
|
17
|
+
channel_id: int = 0,
|
|
18
|
+
*args,
|
|
19
|
+
**kwargs,
|
|
20
|
+
):
|
|
21
|
+
|
|
22
|
+
super().__init__(name, parent, children, abort, *args, **kwargs)
|
|
23
|
+
|
|
24
|
+
self.name = name
|
|
25
|
+
self.channel_id = channel_id
|
|
26
|
+
|
|
27
|
+
self.client = parent.client
|
|
28
|
+
|
|
29
|
+
def describe(self):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
def get(self) -> tuple[Color, bool]:
|
|
33
|
+
"""
|
|
34
|
+
Get color LED state.
|
|
35
|
+
@raises RuntimeError: if the command fails
|
|
36
|
+
@raises TimeoutError: if the command times out
|
|
37
|
+
"""
|
|
38
|
+
return self.client.get(self.channel_id)
|
|
39
|
+
|
|
40
|
+
def set(self, color: Color, blink: bool) -> None:
|
|
41
|
+
"""
|
|
42
|
+
Set the color of the color LED.
|
|
43
|
+
@param Color: The color to set the LED to.
|
|
44
|
+
@param blink: Whether to blink the LED.
|
|
45
|
+
@raises RuntimeError: if the command fails
|
|
46
|
+
@raises TimeoutError: if the command times out
|
|
47
|
+
"""
|
|
48
|
+
self.client.set(self.channel_id, color, blink)
|
|
49
|
+
|
|
50
|
+
def __repr__(self):
|
|
51
|
+
return f"{self.name}; Channel ID: {self.channel_id}"
|
ekfsm/devices/io4edge.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
from typing import Callable, Optional
|
|
2
|
+
from ekfsm.core.components import HWModule
|
|
3
|
+
from ekfsm.devices.generic import Device
|
|
4
|
+
import io4edge_client.core.coreclient as Client
|
|
5
|
+
|
|
6
|
+
from re import sub
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IO4Edge(Device):
|
|
10
|
+
"""
|
|
11
|
+
Device class for handling IO4Edge devices.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
name: str,
|
|
17
|
+
parent: HWModule | None = None,
|
|
18
|
+
children: list[Device] | None = None,
|
|
19
|
+
abort: bool = False,
|
|
20
|
+
*args,
|
|
21
|
+
**kwargs,
|
|
22
|
+
):
|
|
23
|
+
|
|
24
|
+
super().__init__(name, parent, children, abort, *args, **kwargs)
|
|
25
|
+
|
|
26
|
+
attr = self.hw_module.slot.attributes
|
|
27
|
+
if (
|
|
28
|
+
attr is None
|
|
29
|
+
or not hasattr(attr, "slot_coding")
|
|
30
|
+
or getattr(attr, "slot_coding") is None
|
|
31
|
+
):
|
|
32
|
+
raise ValueError(
|
|
33
|
+
f"Slot attributes for {self.hw_module.slot.name} are not set or do not contain 'slot_coding'."
|
|
34
|
+
)
|
|
35
|
+
else:
|
|
36
|
+
geoaddr = int(attr.slot_coding)
|
|
37
|
+
self._geoaddr = geoaddr
|
|
38
|
+
|
|
39
|
+
_, module_name = sub(r"-.*$", "", self.hw_module.board_type).split(maxsplit=1)
|
|
40
|
+
self._module_name = module_name
|
|
41
|
+
self.client = Client.new_core_client(self.deviceId)
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def deviceId(self) -> str:
|
|
45
|
+
"""
|
|
46
|
+
Returns the device ID for the IO4Edge device.
|
|
47
|
+
The device ID is a combination of the module name and the geo address.
|
|
48
|
+
"""
|
|
49
|
+
return f"{self._module_name}-geo_addr{self._geoaddr:02d}"
|
|
50
|
+
|
|
51
|
+
def identify_firmware(self) -> tuple[str, str]:
|
|
52
|
+
return (
|
|
53
|
+
self.client.identify_firmware().title,
|
|
54
|
+
self.client.identify_firmware().version,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def load_firmware(
|
|
58
|
+
self, cfg: bytes, progress_callback: Optional[Callable[[float], None]] = None
|
|
59
|
+
) -> None:
|
|
60
|
+
"""
|
|
61
|
+
Load firmware onto the IO4Edge device.
|
|
62
|
+
|
|
63
|
+
cfg
|
|
64
|
+
Firmware configuration bytes.
|
|
65
|
+
progress_callback
|
|
66
|
+
Optional callback for progress updates.
|
|
67
|
+
"""
|
|
68
|
+
self.client.load_firmware(cfg, progress_callback)
|
|
69
|
+
|
|
70
|
+
def restart(self) -> None:
|
|
71
|
+
self.client.restart()
|
|
72
|
+
|
|
73
|
+
def load_parameter(self, name: str, value: str) -> None:
|
|
74
|
+
"""
|
|
75
|
+
Set a parameter onto the IO4Edge device.
|
|
76
|
+
|
|
77
|
+
cfg
|
|
78
|
+
The name of the parameter to load.
|
|
79
|
+
value
|
|
80
|
+
The value to set for the parameter.
|
|
81
|
+
"""
|
|
82
|
+
self.client.set_persistent_parameter(name, value)
|
|
83
|
+
|
|
84
|
+
def get_parameter(self, name: str) -> str:
|
|
85
|
+
"""
|
|
86
|
+
Get a parameter value from the IO4Edge device.
|
|
87
|
+
|
|
88
|
+
Returns
|
|
89
|
+
The value of the requested parameter.
|
|
90
|
+
"""
|
|
91
|
+
return self.client.get_persistent_parameter(name)
|
|
92
|
+
|
|
93
|
+
def __repr__(self):
|
|
94
|
+
return f"{self.name}; DeviceId: {self.deviceId}"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from ekfsm.devices.generic import Device
|
|
2
|
+
from ekfsm.devices.io4edge import IO4Edge
|
|
3
|
+
from io4edge_client.colorLED import Client
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LEDArray(Device):
|
|
7
|
+
"""
|
|
8
|
+
Device class for handling a LED array.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
name: str,
|
|
14
|
+
parent: IO4Edge,
|
|
15
|
+
children: list[Device] | None = None,
|
|
16
|
+
abort: bool = False,
|
|
17
|
+
service_suffix: str | None = None,
|
|
18
|
+
*args,
|
|
19
|
+
**kwargs,
|
|
20
|
+
):
|
|
21
|
+
|
|
22
|
+
super().__init__(name, parent, children, abort, *args, **kwargs)
|
|
23
|
+
|
|
24
|
+
self.name = name
|
|
25
|
+
|
|
26
|
+
if service_suffix is not None:
|
|
27
|
+
self.service_suffix = service_suffix
|
|
28
|
+
else:
|
|
29
|
+
self.service_suffix = name
|
|
30
|
+
|
|
31
|
+
self.service_addr = f"{parent.deviceId}-{self.service_suffix}"
|
|
32
|
+
|
|
33
|
+
self.client = Client(self.service_addr)
|
|
34
|
+
|
|
35
|
+
def __repr__(self):
|
|
36
|
+
return f"{self.name}; Service Address: {self.service_addr}"
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
from ekfsm.devices.generic import Device
|
|
2
|
+
from ekfsm.devices.io4edge import IO4Edge
|
|
3
|
+
from io4edge_client.pixelDisplay import Client
|
|
4
|
+
from PIL import Image
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PixelDisplay(Device):
|
|
8
|
+
"""
|
|
9
|
+
Device class for handling a pixel display.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
name: str,
|
|
15
|
+
parent: IO4Edge,
|
|
16
|
+
children: list[Device] | None = None,
|
|
17
|
+
abort: bool = False,
|
|
18
|
+
service_suffix: str | None = None,
|
|
19
|
+
*args,
|
|
20
|
+
**kwargs,
|
|
21
|
+
):
|
|
22
|
+
|
|
23
|
+
super().__init__(name, parent, children, abort, *args, **kwargs)
|
|
24
|
+
|
|
25
|
+
self.name = name
|
|
26
|
+
|
|
27
|
+
if service_suffix is not None:
|
|
28
|
+
self.service_suffix = service_suffix
|
|
29
|
+
else:
|
|
30
|
+
self.service_suffix = name
|
|
31
|
+
|
|
32
|
+
self.service_addr = f"{parent.deviceId}-{self.service_suffix}"
|
|
33
|
+
|
|
34
|
+
self.client = Client(self.service_addr)
|
|
35
|
+
|
|
36
|
+
def describe(self) -> dict:
|
|
37
|
+
"""
|
|
38
|
+
Returns a description of the pixel display.
|
|
39
|
+
"""
|
|
40
|
+
describe = self.client.describe()
|
|
41
|
+
desc = {
|
|
42
|
+
"height": describe.height_pixel,
|
|
43
|
+
"width": describe.width_pixel,
|
|
44
|
+
"max_num_of_pixel": describe.max_num_of_pixel,
|
|
45
|
+
}
|
|
46
|
+
return desc
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def height(self) -> int:
|
|
50
|
+
"""
|
|
51
|
+
Returns the height of the pixel display in pixels.
|
|
52
|
+
"""
|
|
53
|
+
return self.describe()["height"]
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def width(self) -> int:
|
|
57
|
+
"""
|
|
58
|
+
Returns the width of the pixel display in pixels.
|
|
59
|
+
"""
|
|
60
|
+
return self.describe()["width"]
|
|
61
|
+
|
|
62
|
+
def off(self) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Turn off the pixel display.
|
|
65
|
+
@raises RuntimeError: if the command fails
|
|
66
|
+
@raises TimeoutError: if the command times out
|
|
67
|
+
"""
|
|
68
|
+
self.client.set_display_off()
|
|
69
|
+
|
|
70
|
+
def display_image(self, path: str) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Display an image on the pixel display.
|
|
73
|
+
@raises RuntimeError: if the command fails
|
|
74
|
+
@raises TimeoutError: if the command times out
|
|
75
|
+
"""
|
|
76
|
+
with Image.open(path) as img:
|
|
77
|
+
img = img.convert("RGB")
|
|
78
|
+
pix = img.load()
|
|
79
|
+
|
|
80
|
+
for i in range(0, 320, 16):
|
|
81
|
+
pix_area = []
|
|
82
|
+
for k in range(0, 16):
|
|
83
|
+
for j in range(0, 240):
|
|
84
|
+
pix_area.append(pix[j, i + k])
|
|
85
|
+
self.client.set_pixel_area(0, i, 239, pix_area)
|
|
86
|
+
|
|
87
|
+
def __repr__(self):
|
|
88
|
+
return f"{self.name}; Service Address: {self.service_addr}"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from ekfsm.devices.generic import Device
|
|
2
|
+
from ekfsm.devices.io4edge import IO4Edge
|
|
3
|
+
from io4edge_client.analogintypea import Client
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ThermalHumidity(Device):
|
|
7
|
+
"""
|
|
8
|
+
Device class for handling a thermal humidity sensor.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
name: str,
|
|
14
|
+
parent: IO4Edge,
|
|
15
|
+
children: list[Device] | None = None,
|
|
16
|
+
abort: bool = False,
|
|
17
|
+
service_suffix: str | None = None,
|
|
18
|
+
*args,
|
|
19
|
+
**kwargs,
|
|
20
|
+
):
|
|
21
|
+
|
|
22
|
+
super().__init__(name, parent, children, abort, *args, **kwargs)
|
|
23
|
+
|
|
24
|
+
self.name = name
|
|
25
|
+
|
|
26
|
+
if service_suffix is not None:
|
|
27
|
+
self.service_suffix = service_suffix
|
|
28
|
+
else:
|
|
29
|
+
self.service_suffix = name
|
|
30
|
+
|
|
31
|
+
self.service_addr = f"{parent.deviceId}-{self.service_suffix}"
|
|
32
|
+
|
|
33
|
+
self.client = Client(self.service_addr)
|
|
34
|
+
|
|
35
|
+
def __repr__(self):
|
|
36
|
+
return f"{self.name}; Service Address: {self.service_addr}"
|
|
37
|
+
|
|
38
|
+
def temperature(self) -> float:
|
|
39
|
+
"""
|
|
40
|
+
Get the temperature in Celsius.
|
|
41
|
+
@raises RuntimeError: if the command fails
|
|
42
|
+
@raises TimeoutError: if the command times out
|
|
43
|
+
"""
|
|
44
|
+
return self.client.value()
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from ekfsm.devices.generic import Device
|
|
2
|
+
from ekfsm.devices.io4edge import IO4Edge
|
|
3
|
+
from io4edge_client.watchdog import Client
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Watchdog(Device):
|
|
7
|
+
"""
|
|
8
|
+
Device class for handling a color LED.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
name: str,
|
|
14
|
+
parent: IO4Edge,
|
|
15
|
+
children: list[Device] | None = None,
|
|
16
|
+
abort: bool = False,
|
|
17
|
+
service_suffix: str | None = None,
|
|
18
|
+
*args,
|
|
19
|
+
**kwargs,
|
|
20
|
+
):
|
|
21
|
+
|
|
22
|
+
super().__init__(name, parent, children, abort, *args, **kwargs)
|
|
23
|
+
|
|
24
|
+
self.name = name
|
|
25
|
+
|
|
26
|
+
if service_suffix is not None:
|
|
27
|
+
self.service_suffix = service_suffix
|
|
28
|
+
else:
|
|
29
|
+
self.service_suffix = name
|
|
30
|
+
|
|
31
|
+
self.service_addr = f"{parent.deviceId}-{self.service_suffix}"
|
|
32
|
+
|
|
33
|
+
self.client = Client(self.service_addr)
|
|
34
|
+
|
|
35
|
+
def describe(self):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
def kick(self) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Kick the watchdog.
|
|
41
|
+
@raises RuntimeError: if the command fails
|
|
42
|
+
@raises TimeoutError: if the command times out
|
|
43
|
+
"""
|
|
44
|
+
self.client.kick()
|
ekfsm/system.py
CHANGED
|
@@ -173,13 +173,17 @@ class System(SysTree):
|
|
|
173
173
|
board_type = slot_entry.desired_hwmodule_type
|
|
174
174
|
board_name = slot_entry.desired_hwmodule_name
|
|
175
175
|
|
|
176
|
-
self.logger.debug(
|
|
176
|
+
self.logger.debug(
|
|
177
|
+
f"Creating HWModule {board_type} (desired name: {board_name}) in slot {slot.name}"
|
|
178
|
+
)
|
|
177
179
|
|
|
178
180
|
if board_type != "":
|
|
179
181
|
# try to create first the desired board
|
|
180
182
|
path = find_board_config(board_type)
|
|
181
183
|
if path is None:
|
|
182
|
-
self.logger.error(
|
|
184
|
+
self.logger.error(
|
|
185
|
+
f"No board config found for {board_type} (desired name: {board_name})"
|
|
186
|
+
)
|
|
183
187
|
return None, slot
|
|
184
188
|
|
|
185
189
|
try:
|
|
@@ -199,11 +203,15 @@ class System(SysTree):
|
|
|
199
203
|
|
|
200
204
|
# try to probe desired board type
|
|
201
205
|
if hwmod.probe():
|
|
202
|
-
self.logger.info(
|
|
206
|
+
self.logger.info(
|
|
207
|
+
f"Found desired board type {hwmod.board_type} for slot {slot.name}"
|
|
208
|
+
)
|
|
203
209
|
return hwmod, slot
|
|
204
210
|
|
|
205
211
|
# try all other boards types. Maybe someone inserted the wrong board
|
|
206
|
-
self.logger.info(
|
|
212
|
+
self.logger.info(
|
|
213
|
+
f"Probing failed. Trying all other board types for slot {slot.name}"
|
|
214
|
+
)
|
|
207
215
|
for path in all_board_cfg_files():
|
|
208
216
|
try:
|
|
209
217
|
hwmod = self._create_hwmodule_from_cfg_file(slot, board_name, path)
|
|
@@ -212,16 +220,22 @@ class System(SysTree):
|
|
|
212
220
|
# ??? should we log this?
|
|
213
221
|
continue
|
|
214
222
|
except Exception as e:
|
|
215
|
-
self.logger.debug(
|
|
223
|
+
self.logger.debug(
|
|
224
|
+
f"failed to create HWmodule {path} for slot {slot.name}: {e}"
|
|
225
|
+
)
|
|
216
226
|
continue
|
|
217
227
|
|
|
218
228
|
if hwmod.probe():
|
|
219
|
-
self.logger.info(
|
|
229
|
+
self.logger.info(
|
|
230
|
+
f"Found other board type {hwmod.board_type} for slot {slot.name}"
|
|
231
|
+
)
|
|
220
232
|
return hwmod, slot
|
|
221
233
|
|
|
222
234
|
return None, slot
|
|
223
235
|
|
|
224
|
-
def _create_slot(
|
|
236
|
+
def _create_slot(
|
|
237
|
+
self, slot_entry: Munch, slot_number: int, master: HWModule | None
|
|
238
|
+
) -> Slot:
|
|
225
239
|
attributes = None
|
|
226
240
|
if "attributes" in slot_entry:
|
|
227
241
|
attributes = slot_entry.attributes
|
|
@@ -237,7 +251,9 @@ class System(SysTree):
|
|
|
237
251
|
attributes,
|
|
238
252
|
)
|
|
239
253
|
|
|
240
|
-
def _create_hwmodule_from_cfg_file(
|
|
254
|
+
def _create_hwmodule_from_cfg_file(
|
|
255
|
+
self, slot: Slot, board_name: str, path: Path
|
|
256
|
+
) -> HWModule:
|
|
241
257
|
"""
|
|
242
258
|
Try to create a HWModule object from a board config file.
|
|
243
259
|
It does not probe the hardware.
|
|
@@ -261,7 +277,9 @@ class System(SysTree):
|
|
|
261
277
|
cfg = munchify(yaml_data)
|
|
262
278
|
# only instantiate if slot type matches
|
|
263
279
|
if cfg.slot_type != slot.slot_type.to_string():
|
|
264
|
-
raise ConfigError(
|
|
280
|
+
raise ConfigError(
|
|
281
|
+
f"Slot type mismatch for slot {slot.name}: {cfg.slot_type} != {slot.slot_type}"
|
|
282
|
+
)
|
|
265
283
|
|
|
266
284
|
hwmod = HWModule(
|
|
267
285
|
instance_name=board_name,
|
|
@@ -289,7 +307,11 @@ class System(SysTree):
|
|
|
289
307
|
If no HWModule is present in the given slot.
|
|
290
308
|
"""
|
|
291
309
|
return next(
|
|
292
|
-
(
|
|
310
|
+
(
|
|
311
|
+
v.hwmodule
|
|
312
|
+
for k, v in self.slots.items()
|
|
313
|
+
if getattr(v, "number", None) == idx
|
|
314
|
+
),
|
|
293
315
|
None,
|
|
294
316
|
)
|
|
295
317
|
|
|
@@ -310,7 +332,12 @@ class System(SysTree):
|
|
|
310
332
|
If no HWModule is present with the given name.
|
|
311
333
|
"""
|
|
312
334
|
return next(
|
|
313
|
-
(
|
|
335
|
+
(
|
|
336
|
+
b
|
|
337
|
+
for b in self.boards
|
|
338
|
+
if getattr(b, "instance_name", None) is not None
|
|
339
|
+
and getattr(b, "instance_name").lower() == name.lower()
|
|
340
|
+
),
|
|
314
341
|
None,
|
|
315
342
|
)
|
|
316
343
|
|
|
@@ -334,7 +361,9 @@ class System(SysTree):
|
|
|
334
361
|
if (hw_module := self.get_module_by_name(name)) is not None:
|
|
335
362
|
return hw_module
|
|
336
363
|
|
|
337
|
-
raise AttributeError(
|
|
364
|
+
raise AttributeError(
|
|
365
|
+
f"'{type(self).__name__}' object has no board with name '{name}'"
|
|
366
|
+
)
|
|
338
367
|
|
|
339
368
|
def __repr__(self):
|
|
340
369
|
return f"System (name={self.name})"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ekfsm
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0a37
|
|
4
4
|
Summary: The EKF System Management Library (ekfsm) is a sensor monitoring suite for Compact PCI Serial devices.
|
|
5
5
|
Author-email: Jan Jansen <jan@ekf.de>, Klaus Popp <klaus.popp@ci4rail.com>, Felix Päßler <fp@ekf.de>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -9,9 +9,12 @@ Requires-Dist: click>=8.0.1
|
|
|
9
9
|
Requires-Dist: crcmod
|
|
10
10
|
Requires-Dist: gpiod>=2.1.0
|
|
11
11
|
Requires-Dist: hexdump
|
|
12
|
+
Requires-Dist: io4edge-client>=1.6.2
|
|
12
13
|
Requires-Dist: ipdb>=0.13.13
|
|
13
14
|
Requires-Dist: more-itertools
|
|
14
15
|
Requires-Dist: munch
|
|
16
|
+
Requires-Dist: pillow
|
|
17
|
+
Requires-Dist: protobuf
|
|
15
18
|
Requires-Dist: schema>=0.7.7
|
|
16
19
|
Requires-Dist: smbus2
|
|
17
20
|
Requires-Dist: termcolor>=3.0.1
|
|
@@ -6,7 +6,7 @@ ekfsm/lock.py,sha256=dnPjLXWfWIRnLcGec8g-imuqbmqqXWza8OGhS9Aqydk,3236
|
|
|
6
6
|
ekfsm/log.py,sha256=_GC8Y7a4fFV4_DNicbwQ-5rRzNQU6WSotXd2etXSrZk,866
|
|
7
7
|
ekfsm/py.typed,sha256=1gNRtmxvYcVqDDEyAzBLnD8dAOweUfYxW2ZPdJzN1fg,102
|
|
8
8
|
ekfsm/simctrl.py,sha256=WXPpWIju6b8Ch7FZW1PaPrWn7D7fP6gw37-ri-OJERE,5382
|
|
9
|
-
ekfsm/system.py,sha256=
|
|
9
|
+
ekfsm/system.py,sha256=c3jbQa_DxZVur8MsD8gYgK6jkAV55U19MipiDqemzRg,12130
|
|
10
10
|
ekfsm/utils.py,sha256=eOgr4da-dxoMQ6ymjgx_nyBbea8Ck_LAQ8uLM4JgH3c,1179
|
|
11
11
|
ekfsm/boards/oem/ekf/ccu.yaml,sha256=qgr7YZO0kEddD9K6tv6222NyozkRNuF7NFw6hyX0XgE,2094
|
|
12
12
|
ekfsm/boards/oem/ekf/sc5-festival.yaml,sha256=_0kS5GegfyOt5CTJc9kY6HJbr9yZo4i18sVo6F4KE9c,772
|
|
@@ -15,17 +15,21 @@ ekfsm/boards/oem/ekf/se5-club.yaml,sha256=j3u6sDwXMUBM0LNKwVm920w3T3tzjia2BRTQb2
|
|
|
15
15
|
ekfsm/boards/oem/ekf/sn4-djembe.yaml,sha256=ddLDdw7JpPpvR3TmlcTxNVNTOueTl6_A9LSveFrtz3E,1051
|
|
16
16
|
ekfsm/boards/oem/ekf/spv-mystic.yaml,sha256=zcLiNE7wVdXIT4vkwEYSqQ8ff-KEjCHfHnQzzPXJQ4E,1804
|
|
17
17
|
ekfsm/boards/oem/ekf/sq1-track.yaml,sha256=YU83BQjGu-4ejirwnGxd38sJme859kdRovkZyiOJciU,1050
|
|
18
|
-
ekfsm/boards/oem/ekf/sq3-quartet.yaml,sha256=
|
|
18
|
+
ekfsm/boards/oem/ekf/sq3-quartet.yaml,sha256=JaHJn_lph2iwLz6cwXu0bjRMgj33OXt1-VBNGFu0U3s,1330
|
|
19
19
|
ekfsm/boards/oem/ekf/srf-fan.yaml,sha256=Mcu1Q8B1Ih10hoc_hbkGlppBmbOFcufsVUR42iW4Rwc,1368
|
|
20
20
|
ekfsm/boards/oem/ekf/sur-uart.yaml,sha256=VaNP2BSlNTi1lDco16Ma9smPEAMaVKvx-ZNDcm3QptM,1890
|
|
21
|
+
ekfsm/boards/oem/ekf/z1010.yaml,sha256=Z0m0AaRnBFL3QYvSnzHVauXm3laN4lrVv6ewccyY6Hk,2369
|
|
21
22
|
ekfsm/boards/oem/hitron/hdrc-300s.yaml,sha256=SwBHTWVqENBun_iZattPbvA9koc-LOI_MIXjLahKyyI,548
|
|
22
23
|
ekfsm/core/__init__.py,sha256=xfuU072JY_--561hfSS8ToBM-wgswY4Z-YwDMZkVA6c,348
|
|
23
|
-
ekfsm/core/components.py,sha256=
|
|
24
|
+
ekfsm/core/components.py,sha256=iTetqtzNjEEj6FDJNfvXxW_cNNRlLX5_WgB5z3g3zqg,3883
|
|
24
25
|
ekfsm/core/probe.py,sha256=DgJvkvMjVk09n0Rzn13ybRvidrmFn_D2PD56XS-KgxU,262
|
|
25
|
-
ekfsm/core/slots.py,sha256=
|
|
26
|
+
ekfsm/core/slots.py,sha256=qmxfssVitsMFZYbJRCpOOsvEGqh8JVYdRS-_5BliOF4,6580
|
|
26
27
|
ekfsm/core/sysfs.py,sha256=CWH1BXlanHAFzK6KY23qLuFvBZ7Q9td3X6JLRwb3vu0,7309
|
|
27
|
-
ekfsm/core/utils.py,sha256=
|
|
28
|
-
ekfsm/devices/__init__.py,sha256=
|
|
28
|
+
ekfsm/core/utils.py,sha256=slSgFNmSvwWL5qlDQE9WXGv9u9skojlGtUM_B-WumsY,4634
|
|
29
|
+
ekfsm/devices/__init__.py,sha256=EDFzBuUHt_3_6JD4cageHWZfoMn3WUIIDZk4yEOWgfg,1451
|
|
30
|
+
ekfsm/devices/button.py,sha256=tPGBWi2ZxZDQX_WojQG3lKdsKcCTXRYQjRwRjcIv460,1036
|
|
31
|
+
ekfsm/devices/buttonArray.py,sha256=bKNstHsmc6SM09BaQiQV09wRbgnb5I6KK7JTgCk6PnU,2910
|
|
32
|
+
ekfsm/devices/colorLed.py,sha256=PrA3WsuMs-vi2DxxsW4hRIJh_ZWqs_hW2QmFeijsCxA,1410
|
|
29
33
|
ekfsm/devices/coretemp.py,sha256=UEsPTMYm05qNCnqnPtbAoYdIfvVGkDl9rJg3tkAP748,1992
|
|
30
34
|
ekfsm/devices/eeprom.py,sha256=cwcaM2YCKrw6du8d4zT_M3e4oFJh3XNQc5cQM2vqERE,33090
|
|
31
35
|
ekfsm/devices/ekf_ccu_uc.py,sha256=hjs5r7TKsrFhyyGKClgSFBpchQpFcE7fTZeuLrYiflY,15905
|
|
@@ -35,12 +39,17 @@ ekfsm/devices/gpio.py,sha256=37P7uu-ncg0TWf0Xs1iZM-PrX7F_09asd4IhWj6z21Y,10058
|
|
|
35
39
|
ekfsm/devices/iio.py,sha256=1Jyh5wJ53DxvpWNBqYW07kkaAN9446ebWGCMk2UIuWM,1265
|
|
36
40
|
ekfsm/devices/iio_thermal_humidity.py,sha256=KCeEqBlczroxp-hjsiRlXQdmmnJR9Ck3d3ztths5Vvc,1547
|
|
37
41
|
ekfsm/devices/imu.py,sha256=GwJrnC-WztpE5oGnkIp-laFkSp3_gbSp9YpJ8jBsUOs,423
|
|
42
|
+
ekfsm/devices/io4edge.py,sha256=hk_EzcXVR0-sD2zn6pMuO2txYNnTDKmMaaXS2N__8E4,2743
|
|
43
|
+
ekfsm/devices/ledArray.py,sha256=6DCHs1nJz12aHQNPytaM_KIasQYdB29ZN7GzPb_EcJ4,902
|
|
38
44
|
ekfsm/devices/mux.py,sha256=QpVWsD43Mx1mtCDG_nOxtHeIeU2Cigc62UljJ_utSXQ,1974
|
|
45
|
+
ekfsm/devices/pixelDisplay.py,sha256=68SANN4S15_NncuDvu0hyjjdqhpxYn14cmxjXwfGqgU,2425
|
|
39
46
|
ekfsm/devices/pmbus.py,sha256=fi_kR7TlkcqYhHuB7PA2PjANCYmo3MSPeV-B5ZI_WrQ,7004
|
|
40
47
|
ekfsm/devices/smbios.py,sha256=4P-sxOW27pkzIfVlvFNyVJOcZlYgk2KCTCEUvKf5D94,1067
|
|
41
48
|
ekfsm/devices/smbus.py,sha256=kbtjEnfrVI6lbfqAbojVqO5nnnpa6HanLf0X2iZjgCg,500
|
|
49
|
+
ekfsm/devices/thermal_humidity.py,sha256=OVr1zaCGGutfk1WYZ3509wx6qHqjjF2nFE9QYM_bWtE,1170
|
|
42
50
|
ekfsm/devices/utils.py,sha256=qeDNpTpQ3bLGYERAH5lMsifmOaEcQ32FOwEt8tvmjWU,174
|
|
43
|
-
ekfsm
|
|
44
|
-
ekfsm-1.
|
|
45
|
-
ekfsm-1.
|
|
46
|
-
ekfsm-1.
|
|
51
|
+
ekfsm/devices/watchdog.py,sha256=-us3IMKsvTR7LzRCszHR19q0jsCGPZUIN_FWN-h8844,1060
|
|
52
|
+
ekfsm-1.4.0a37.dist-info/METADATA,sha256=fz_N76MjDbeGbpB1dHKlmzLEwLb_qLPC6ov2pKLFPQ4,6717
|
|
53
|
+
ekfsm-1.4.0a37.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
54
|
+
ekfsm-1.4.0a37.dist-info/entry_points.txt,sha256=WhUR4FzuxPoGrbTOKLsNJO7NAnk2qd4T30fqzN1yLw8,45
|
|
55
|
+
ekfsm-1.4.0a37.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|