ekfsm 1.1.0a15.post1__py3-none-any.whl → 1.3.0a26__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/hitron/hdrc-300s.yaml +1 -1
- ekfsm/cli.py +6 -8
- ekfsm/config.py +14 -6
- ekfsm/core/__init__.py +5 -5
- ekfsm/core/components.py +4 -4
- ekfsm/core/slots.py +6 -13
- ekfsm/core/sysfs.py +183 -13
- ekfsm/core/utils.py +104 -64
- ekfsm/devices/__init__.py +8 -7
- ekfsm/devices/coretemp.py +11 -10
- ekfsm/devices/eeprom.py +69 -39
- ekfsm/devices/ekf_ccu_uc.py +58 -47
- ekfsm/devices/ekf_sur_led.py +6 -2
- ekfsm/devices/generic.py +141 -88
- ekfsm/devices/gpio.py +33 -25
- ekfsm/devices/iio.py +15 -31
- ekfsm/devices/iio_thermal_humidity.py +12 -13
- ekfsm/devices/mux.py +11 -6
- ekfsm/devices/pmbus.py +62 -70
- ekfsm/devices/smbios.py +10 -8
- ekfsm/devices/smbus.py +1 -1
- ekfsm/devices/utils.py +0 -9
- ekfsm/exceptions.py +28 -7
- ekfsm/lock.py +48 -21
- ekfsm/simctrl.py +37 -83
- ekfsm/system.py +45 -102
- ekfsm/utils.py +44 -0
- {ekfsm-1.1.0a15.post1.dist-info → ekfsm-1.3.0a26.dist-info}/METADATA +8 -5
- ekfsm-1.3.0a26.dist-info/RECORD +46 -0
- ekfsm-1.1.0a15.post1.dist-info/RECORD +0 -45
- {ekfsm-1.1.0a15.post1.dist-info → ekfsm-1.3.0a26.dist-info}/WHEEL +0 -0
- {ekfsm-1.1.0a15.post1.dist-info → ekfsm-1.3.0a26.dist-info}/entry_points.txt +0 -0
ekfsm/simctrl.py
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import socket
|
|
2
2
|
import struct
|
|
3
|
-
from unittest.mock import patch
|
|
4
3
|
from pathlib import Path
|
|
4
|
+
from typing import List
|
|
5
|
+
from unittest.mock import patch
|
|
5
6
|
|
|
6
|
-
from
|
|
7
|
-
from ekfsm.devices.gpio import EKFIdSimGpio
|
|
8
|
-
from ekfsm.devices.gpio import SimGpio
|
|
9
|
-
from .core.sysfs import set_sysfs_root
|
|
10
|
-
from .core.components import SysTree
|
|
7
|
+
from smbus2 import SMBus
|
|
11
8
|
|
|
9
|
+
from ekfsm.devices.gpio import EKFIdSimGpio, SimGpio
|
|
10
|
+
from ekfsm.devices.smbus import SimSMBus
|
|
11
|
+
|
|
12
|
+
from .core.components import SysTree
|
|
13
|
+
from .core.sysfs import set_sysfs_root
|
|
12
14
|
from .devices import GPIO
|
|
13
|
-
from typing import List
|
|
14
|
-
from smbus2 import SMBus
|
|
15
15
|
|
|
16
16
|
GPIO_SIM_MAPPING: dict[str, SimGpio] = {}
|
|
17
|
-
SMBUS_SIM_MAPPING: dict[str,
|
|
17
|
+
SMBUS_SIM_MAPPING: dict[str, SimSMBus] = {}
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def register_gpio_sim(major: int, minor: int, sim_gpio: SimGpio) -> None:
|
|
@@ -31,14 +31,14 @@ def find_gpio_dev_with_major_minor(major: int, minor: int) -> SimGpio:
|
|
|
31
31
|
return GPIO_SIM_MAPPING[name]
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
def register_smbus_sim(bus_num: int, i2c_addr: int, sim_smbus:
|
|
34
|
+
def register_smbus_sim(bus_num: int, i2c_addr: int, sim_smbus: SimSMBus) -> None:
|
|
35
35
|
name = f"{bus_num}:{i2c_addr}"
|
|
36
36
|
if name in SMBUS_SIM_MAPPING:
|
|
37
37
|
raise ValueError(f"SMBUS_SIM_MAPPING already contains {name}")
|
|
38
38
|
SMBUS_SIM_MAPPING[name] = sim_smbus
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
def find_smbus_dev(bus_num: int, i2c_addr: int) ->
|
|
41
|
+
def find_smbus_dev(bus_num: int, i2c_addr: int) -> SimSMBus:
|
|
42
42
|
name = f"{bus_num}:{i2c_addr}"
|
|
43
43
|
|
|
44
44
|
if name not in SMBUS_SIM_MAPPING:
|
|
@@ -46,7 +46,7 @@ def find_smbus_dev(bus_num: int, i2c_addr: int) -> SimSmbus:
|
|
|
46
46
|
return SMBUS_SIM_MAPPING[name]
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
class
|
|
49
|
+
class GPIOSimulator(GPIO):
|
|
50
50
|
def __init__(
|
|
51
51
|
self,
|
|
52
52
|
name: str,
|
|
@@ -80,7 +80,7 @@ class GpioSimulator(GPIO):
|
|
|
80
80
|
return f"GPIO_SIM({self.name})"
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
class
|
|
83
|
+
class SMBusSimulator:
|
|
84
84
|
def __init__(self, bus_num: int):
|
|
85
85
|
self.bus_num = bus_num
|
|
86
86
|
|
|
@@ -100,73 +100,12 @@ class SmbusSimulator:
|
|
|
100
100
|
find_smbus_dev(self.bus_num, i2c_addr).write_word_data(cmd, data)
|
|
101
101
|
|
|
102
102
|
|
|
103
|
-
def
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
patched_methods.append(
|
|
110
|
-
patch.object(GPIO, "num_lines", new_callable=lambda: GpioSimulator.num_lines)
|
|
111
|
-
)
|
|
112
|
-
patched_methods.append(
|
|
113
|
-
patch.object(GPIO, "set_pin", new_callable=lambda: GpioSimulator.set_pin)
|
|
114
|
-
)
|
|
115
|
-
patched_methods.append(
|
|
116
|
-
patch.object(GPIO, "get_pin", new_callable=lambda: GpioSimulator.get_pin)
|
|
117
|
-
)
|
|
118
|
-
patched_methods.append(
|
|
119
|
-
patch.object(
|
|
120
|
-
GPIO, "set_direction", new_callable=lambda: GpioSimulator.set_direction
|
|
121
|
-
)
|
|
122
|
-
)
|
|
123
|
-
patched_methods.append(
|
|
124
|
-
patch.object(GPIO, "__str__", new_callable=lambda: GpioSimulator.__str__)
|
|
125
|
-
)
|
|
126
|
-
for pm in patched_methods:
|
|
127
|
-
pm.start()
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def enable_smbus_simulation():
|
|
131
|
-
patched_methods = []
|
|
132
|
-
|
|
133
|
-
patched_methods.append(
|
|
134
|
-
patch.object(SMBus, "__init__", new_callable=lambda: SmbusSimulator.__init__)
|
|
135
|
-
)
|
|
136
|
-
patched_methods.append(
|
|
137
|
-
patch.object(
|
|
138
|
-
SMBus, "read_word_data", new_callable=lambda: SmbusSimulator.read_word_data
|
|
139
|
-
)
|
|
140
|
-
)
|
|
141
|
-
patched_methods.append(
|
|
142
|
-
patch.object(
|
|
143
|
-
SMBus,
|
|
144
|
-
"read_block_data",
|
|
145
|
-
new_callable=lambda: SmbusSimulator.read_block_data,
|
|
146
|
-
)
|
|
147
|
-
)
|
|
148
|
-
patched_methods.append(
|
|
149
|
-
patch.object(
|
|
150
|
-
SMBus,
|
|
151
|
-
"write_block_data",
|
|
152
|
-
new_callable=lambda: SmbusSimulator.write_block_data,
|
|
153
|
-
)
|
|
154
|
-
)
|
|
155
|
-
patched_methods.append(
|
|
156
|
-
patch.object(
|
|
157
|
-
SMBus, "write_byte", new_callable=lambda: SmbusSimulator.write_byte
|
|
158
|
-
)
|
|
159
|
-
)
|
|
160
|
-
patched_methods.append(
|
|
161
|
-
patch.object(
|
|
162
|
-
SMBus,
|
|
163
|
-
"write_word_data",
|
|
164
|
-
new_callable=lambda: SmbusSimulator.write_word_data,
|
|
165
|
-
)
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
for pm in patched_methods:
|
|
169
|
-
pm.start()
|
|
103
|
+
def patch_methods(cls, simulator, methods):
|
|
104
|
+
patched = []
|
|
105
|
+
for i, method in enumerate(methods):
|
|
106
|
+
if hasattr(cls, method) and hasattr(simulator, method):
|
|
107
|
+
patched.append(patch.object(cls, method, new_callable=lambda: getattr(simulator, method)))
|
|
108
|
+
patched[i].start()
|
|
170
109
|
|
|
171
110
|
|
|
172
111
|
def enable_simulation(sysfs_path: Path | str) -> None:
|
|
@@ -180,8 +119,23 @@ def enable_simulation(sysfs_path: Path | str) -> None:
|
|
|
180
119
|
sysfs_path = Path(sysfs_path)
|
|
181
120
|
|
|
182
121
|
set_sysfs_root(sysfs_path)
|
|
183
|
-
|
|
184
|
-
|
|
122
|
+
patch_methods(
|
|
123
|
+
GPIO,
|
|
124
|
+
GPIOSimulator,
|
|
125
|
+
["__init__", "num_lines", "set_pin", "get_pin", "set_direction", "__str__"],
|
|
126
|
+
)
|
|
127
|
+
patch_methods(
|
|
128
|
+
SMBus,
|
|
129
|
+
SMBusSimulator,
|
|
130
|
+
[
|
|
131
|
+
"__init__",
|
|
132
|
+
"read_word_data",
|
|
133
|
+
"read_block_data",
|
|
134
|
+
"write_block_data",
|
|
135
|
+
"write_byte",
|
|
136
|
+
"write_word_data",
|
|
137
|
+
],
|
|
138
|
+
)
|
|
185
139
|
|
|
186
140
|
|
|
187
141
|
def register_gpio_simulations():
|
|
@@ -189,7 +143,7 @@ def register_gpio_simulations():
|
|
|
189
143
|
register_gpio_sim(233, 2, EKFIdSimGpio(0x34, 0xA, 0x0, 0x1)) # CCU Rev 0
|
|
190
144
|
|
|
191
145
|
|
|
192
|
-
class SocketSmbus(
|
|
146
|
+
class SocketSmbus(SimSMBus):
|
|
193
147
|
def __init__(self, host: str, port: int) -> None:
|
|
194
148
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
195
149
|
self.sock.connect((host, port))
|
ekfsm/system.py
CHANGED
|
@@ -1,52 +1,19 @@
|
|
|
1
|
-
from typing import Tuple, Any, Generator
|
|
2
1
|
from pathlib import Path
|
|
3
|
-
from
|
|
2
|
+
from typing import Any, Tuple
|
|
4
3
|
|
|
5
|
-
from ekfsm.core.components import SysTree
|
|
6
4
|
import yaml
|
|
5
|
+
from munch import Munch, munchify
|
|
7
6
|
|
|
8
|
-
from .core.
|
|
7
|
+
from ekfsm.core.components import SysTree
|
|
8
|
+
from ekfsm.utils import all_board_cfg_files, find_board_config
|
|
9
9
|
|
|
10
10
|
from .config import load_config
|
|
11
|
-
from .core import
|
|
12
|
-
from .core.slots import Slots
|
|
11
|
+
from .core import HWModule
|
|
12
|
+
from .core.slots import Slot, Slots, SlotType
|
|
13
13
|
from .exceptions import ConfigError
|
|
14
14
|
from .log import ekfsm_logger
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
_CFG_DIR = Path(__file__).parent / "boards"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def find_board_config(module_type: str) -> Path | None:
|
|
21
|
-
"""
|
|
22
|
-
Find a matching board config in `boards/oem/` given the module type specified in
|
|
23
|
-
the system configuration file.
|
|
24
|
-
|
|
25
|
-
Parameters
|
|
26
|
-
----------
|
|
27
|
-
module_type
|
|
28
|
-
Board type specified in the system configuration for a slot.
|
|
29
|
-
It must consist of an OEM and the board type, separated by whitespace. Neither
|
|
30
|
-
part may contain any other whitespace.
|
|
31
|
-
"""
|
|
32
|
-
oem, board = module_type.split(maxsplit=1)
|
|
33
|
-
if (
|
|
34
|
-
path := _CFG_DIR / "oem" / oem.strip().lower() / f"{board.strip().lower()}.yaml"
|
|
35
|
-
).exists():
|
|
36
|
-
return path
|
|
37
|
-
return None
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def all_board_cfg_files() -> Generator[Path, None, None]:
|
|
41
|
-
"""
|
|
42
|
-
Generator that recursively yields all *.yaml files in a directory
|
|
43
|
-
"""
|
|
44
|
-
path = Path(_CFG_DIR)
|
|
45
|
-
for item in path.rglob("*.yaml"):
|
|
46
|
-
if item.is_file():
|
|
47
|
-
yield item
|
|
48
|
-
|
|
49
|
-
|
|
50
17
|
class System(SysTree):
|
|
51
18
|
"""
|
|
52
19
|
A System represents a CPCI system.
|
|
@@ -88,7 +55,7 @@ class System(SysTree):
|
|
|
88
55
|
-------
|
|
89
56
|
>>> from ekfsm.system import System
|
|
90
57
|
>>> system = System("path/to/config.yaml")
|
|
91
|
-
>>> print(system) # Print the system configuration as trees of
|
|
58
|
+
>>> print(system) # Print the system configuration as trees of HWModules
|
|
92
59
|
>>> system.print() # same as above
|
|
93
60
|
>>> cpu = system.cpu # Access the CPU board by its name
|
|
94
61
|
>>> cpu = system[0] # Access the CPU board by its slot index (index as in configuration file)
|
|
@@ -122,7 +89,7 @@ class System(SysTree):
|
|
|
122
89
|
|
|
123
90
|
def _init_system(self, config: Path):
|
|
124
91
|
self.slots: Slots = Slots()
|
|
125
|
-
self.boards: list[
|
|
92
|
+
self.boards: list[HWModule] = []
|
|
126
93
|
|
|
127
94
|
self.master, self.master_slot_number = self._create_master()
|
|
128
95
|
if self.master is None:
|
|
@@ -131,7 +98,7 @@ class System(SysTree):
|
|
|
131
98
|
self.logger.info(f"Master board found in slot {self.master_slot_number}")
|
|
132
99
|
|
|
133
100
|
for i, slot_cfg in enumerate(self.config.system_config.slots):
|
|
134
|
-
hwmod:
|
|
101
|
+
hwmod: HWModule | Slot | None
|
|
135
102
|
if i == self.master_slot_number:
|
|
136
103
|
hwmod = self.master
|
|
137
104
|
else:
|
|
@@ -170,7 +137,7 @@ class System(SysTree):
|
|
|
170
137
|
"""
|
|
171
138
|
self.__init__(self.config_path)
|
|
172
139
|
|
|
173
|
-
def _create_master(self) -> Tuple[
|
|
140
|
+
def _create_master(self) -> Tuple[HWModule | None, int]:
|
|
174
141
|
for i, slot in enumerate(self.config.system_config.slots):
|
|
175
142
|
if "attributes" in slot:
|
|
176
143
|
if "is_master" in slot.attributes:
|
|
@@ -184,10 +151,10 @@ class System(SysTree):
|
|
|
184
151
|
return None, -1 # ???
|
|
185
152
|
|
|
186
153
|
def create_hwmodule(
|
|
187
|
-
self, slot_entry: Munch, slot_number: int, master:
|
|
188
|
-
) -> Tuple[
|
|
154
|
+
self, slot_entry: Munch, slot_number: int, master: HWModule | None
|
|
155
|
+
) -> Tuple[HWModule | None, Slot]:
|
|
189
156
|
"""
|
|
190
|
-
Create
|
|
157
|
+
Create HWModule object for the slot.
|
|
191
158
|
|
|
192
159
|
Parameters
|
|
193
160
|
----------
|
|
@@ -200,23 +167,19 @@ class System(SysTree):
|
|
|
200
167
|
|
|
201
168
|
Returns
|
|
202
169
|
-------
|
|
203
|
-
|
|
170
|
+
HWModule and Slot. HWodule is None if it cannot be created.
|
|
204
171
|
"""
|
|
205
172
|
slot = self._create_slot(slot_entry, slot_number, master)
|
|
206
173
|
board_type = slot_entry.desired_hwmodule_type
|
|
207
174
|
board_name = slot_entry.desired_hwmodule_name
|
|
208
175
|
|
|
209
|
-
self.logger.debug(
|
|
210
|
-
f"Creating hwmodule {board_type} (desired name: {board_name}) in slot {slot.name}"
|
|
211
|
-
)
|
|
176
|
+
self.logger.debug(f"Creating HWModule {board_type} (desired name: {board_name}) in slot {slot.name}")
|
|
212
177
|
|
|
213
178
|
if board_type != "":
|
|
214
179
|
# try to create first the desired board
|
|
215
180
|
path = find_board_config(board_type)
|
|
216
181
|
if path is None:
|
|
217
|
-
self.logger.error(
|
|
218
|
-
f"No board config found for {board_type} (desired name: {board_name})"
|
|
219
|
-
)
|
|
182
|
+
self.logger.error(f"No board config found for {board_type} (desired name: {board_name})")
|
|
220
183
|
return None, slot
|
|
221
184
|
|
|
222
185
|
try:
|
|
@@ -225,26 +188,22 @@ class System(SysTree):
|
|
|
225
188
|
except Exception as e:
|
|
226
189
|
if self.abort:
|
|
227
190
|
self.logger.error(
|
|
228
|
-
f"failed to create desired
|
|
191
|
+
f"failed to create desired HWModule {board_type} (as {board_name}): {e}. Aborting!"
|
|
229
192
|
)
|
|
230
193
|
raise e
|
|
231
194
|
else:
|
|
232
195
|
self.logger.error(
|
|
233
|
-
f"failed to create desired
|
|
196
|
+
f"failed to create desired HWModule {board_type} (as {board_name}): {e}. Leaving slot empty!"
|
|
234
197
|
)
|
|
235
198
|
return None, slot
|
|
236
199
|
|
|
237
200
|
# try to probe desired board type
|
|
238
201
|
if hwmod.probe():
|
|
239
|
-
self.logger.info(
|
|
240
|
-
f"Found desired board type {hwmod.board_type} for slot {slot.name}"
|
|
241
|
-
)
|
|
202
|
+
self.logger.info(f"Found desired board type {hwmod.board_type} for slot {slot.name}")
|
|
242
203
|
return hwmod, slot
|
|
243
204
|
|
|
244
205
|
# try all other boards types. Maybe someone inserted the wrong board
|
|
245
|
-
self.logger.info(
|
|
246
|
-
f"Probing failed. Trying all other board types for slot {slot.name}"
|
|
247
|
-
)
|
|
206
|
+
self.logger.info(f"Probing failed. Trying all other board types for slot {slot.name}")
|
|
248
207
|
for path in all_board_cfg_files():
|
|
249
208
|
try:
|
|
250
209
|
hwmod = self._create_hwmodule_from_cfg_file(slot, board_name, path)
|
|
@@ -253,22 +212,16 @@ class System(SysTree):
|
|
|
253
212
|
# ??? should we log this?
|
|
254
213
|
continue
|
|
255
214
|
except Exception as e:
|
|
256
|
-
self.logger.debug(
|
|
257
|
-
f"failed to create hwmodule {path} for slot {slot.name}: {e}"
|
|
258
|
-
)
|
|
215
|
+
self.logger.debug(f"failed to create HWmodule {path} for slot {slot.name}: {e}")
|
|
259
216
|
continue
|
|
260
217
|
|
|
261
218
|
if hwmod.probe():
|
|
262
|
-
self.logger.info(
|
|
263
|
-
f"Found other board type {hwmod.board_type} for slot {slot.name}"
|
|
264
|
-
)
|
|
219
|
+
self.logger.info(f"Found other board type {hwmod.board_type} for slot {slot.name}")
|
|
265
220
|
return hwmod, slot
|
|
266
221
|
|
|
267
222
|
return None, slot
|
|
268
223
|
|
|
269
|
-
def _create_slot(
|
|
270
|
-
self, slot_entry: Munch, slot_number: int, master: HwModule | None
|
|
271
|
-
) -> Slot:
|
|
224
|
+
def _create_slot(self, slot_entry: Munch, slot_number: int, master: HWModule | None) -> Slot:
|
|
272
225
|
attributes = None
|
|
273
226
|
if "attributes" in slot_entry:
|
|
274
227
|
attributes = slot_entry.attributes
|
|
@@ -284,16 +237,14 @@ class System(SysTree):
|
|
|
284
237
|
attributes,
|
|
285
238
|
)
|
|
286
239
|
|
|
287
|
-
def _create_hwmodule_from_cfg_file(
|
|
288
|
-
self, slot: Slot, board_name: str, path: Path
|
|
289
|
-
) -> HwModule:
|
|
240
|
+
def _create_hwmodule_from_cfg_file(self, slot: Slot, board_name: str, path: Path) -> HWModule:
|
|
290
241
|
"""
|
|
291
|
-
Try to create a
|
|
242
|
+
Try to create a HWModule object from a board config file.
|
|
292
243
|
It does not probe the hardware.
|
|
293
244
|
|
|
294
245
|
Returns
|
|
295
246
|
-------
|
|
296
|
-
|
|
247
|
+
HWModule object.
|
|
297
248
|
|
|
298
249
|
Raises
|
|
299
250
|
------
|
|
@@ -310,11 +261,9 @@ class System(SysTree):
|
|
|
310
261
|
cfg = munchify(yaml_data)
|
|
311
262
|
# only instantiate if slot type matches
|
|
312
263
|
if cfg.slot_type != slot.slot_type.to_string():
|
|
313
|
-
raise ConfigError(
|
|
314
|
-
f"Slot type mismatch for slot {slot.name}: {cfg.slot_type} != {slot.slot_type}"
|
|
315
|
-
)
|
|
264
|
+
raise ConfigError(f"Slot type mismatch for slot {slot.name}: {cfg.slot_type} != {slot.slot_type}")
|
|
316
265
|
|
|
317
|
-
hwmod =
|
|
266
|
+
hwmod = HWModule(
|
|
318
267
|
instance_name=board_name,
|
|
319
268
|
config=yaml_data,
|
|
320
269
|
slot=slot,
|
|
@@ -324,9 +273,9 @@ class System(SysTree):
|
|
|
324
273
|
|
|
325
274
|
return hwmod
|
|
326
275
|
|
|
327
|
-
def get_module_in_slot(self, idx: int) ->
|
|
276
|
+
def get_module_in_slot(self, idx: int) -> HWModule | None:
|
|
328
277
|
"""
|
|
329
|
-
Get the
|
|
278
|
+
Get the HWModule in the given slot.
|
|
330
279
|
|
|
331
280
|
Parameters
|
|
332
281
|
----------
|
|
@@ -334,35 +283,31 @@ class System(SysTree):
|
|
|
334
283
|
The slot index.
|
|
335
284
|
Returns
|
|
336
285
|
-------
|
|
337
|
-
|
|
338
|
-
The
|
|
286
|
+
HWModule
|
|
287
|
+
The HWModule in the given slot.
|
|
339
288
|
None
|
|
340
|
-
If no
|
|
289
|
+
If no HWModule is present in the given slot.
|
|
341
290
|
"""
|
|
342
291
|
return next(
|
|
343
|
-
(
|
|
344
|
-
v.hwmodule
|
|
345
|
-
for k, v in self.slots.items()
|
|
346
|
-
if getattr(v, "number", None) == idx
|
|
347
|
-
),
|
|
292
|
+
(v.hwmodule for k, v in self.slots.items() if getattr(v, "number", None) == idx),
|
|
348
293
|
None,
|
|
349
294
|
)
|
|
350
295
|
|
|
351
|
-
def get_module_by_name(self, name: str) ->
|
|
296
|
+
def get_module_by_name(self, name: str) -> HWModule | None:
|
|
352
297
|
"""
|
|
353
|
-
Get the
|
|
298
|
+
Get the HWModule by its name.
|
|
354
299
|
|
|
355
300
|
Parameters
|
|
356
301
|
----------
|
|
357
302
|
name
|
|
358
|
-
The name of the
|
|
303
|
+
The name of the HWModule.
|
|
359
304
|
|
|
360
305
|
Returns
|
|
361
306
|
-------
|
|
362
|
-
|
|
363
|
-
The
|
|
307
|
+
HWModule
|
|
308
|
+
The HWModule with the given name.
|
|
364
309
|
None
|
|
365
|
-
If no
|
|
310
|
+
If no HWModule is present with the given name.
|
|
366
311
|
"""
|
|
367
312
|
return next(
|
|
368
313
|
(b for b in self.boards if getattr(b, "instance_name", None) == name),
|
|
@@ -372,7 +317,7 @@ class System(SysTree):
|
|
|
372
317
|
def __iter__(self):
|
|
373
318
|
return iter(self.boards)
|
|
374
319
|
|
|
375
|
-
def __getitem__(self, key) ->
|
|
320
|
+
def __getitem__(self, key) -> HWModule:
|
|
376
321
|
if isinstance(key, int):
|
|
377
322
|
value = self.get_module_in_slot(key)
|
|
378
323
|
else:
|
|
@@ -386,12 +331,10 @@ class System(SysTree):
|
|
|
386
331
|
def __getattr__(self, name: str) -> Any:
|
|
387
332
|
"""Access board by attribute using dot notation"""
|
|
388
333
|
# This fixes mypy error: "... has no object ..."
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
raise AttributeError(
|
|
393
|
-
f"'{type(self).__name__}' object has no board with name '{name}'"
|
|
394
|
-
)
|
|
334
|
+
if (hw_module := self.get_module_by_name(name)) is not None:
|
|
335
|
+
return hw_module
|
|
336
|
+
|
|
337
|
+
raise AttributeError(f"'{type(self).__name__}' object has no board with name '{name}'")
|
|
395
338
|
|
|
396
339
|
def __repr__(self):
|
|
397
340
|
return f"System (name={self.name})"
|
ekfsm/utils.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Generator
|
|
3
|
+
|
|
4
|
+
_CFG_DIR = Path(__file__).parent / "boards"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def find_board_config(module_type: str) -> Path | None:
|
|
8
|
+
"""
|
|
9
|
+
Find a matching board config in `boards/oem/` given the module type specified in
|
|
10
|
+
the system configuration file.
|
|
11
|
+
|
|
12
|
+
Parameters
|
|
13
|
+
----------
|
|
14
|
+
module_type
|
|
15
|
+
Board type specified in the system configuration for a slot.
|
|
16
|
+
It must consist of an OEM and the board type, separated by whitespace. Neither
|
|
17
|
+
part may contain any other whitespace.
|
|
18
|
+
"""
|
|
19
|
+
oem, board = module_type.split(maxsplit=1)
|
|
20
|
+
if (path := _CFG_DIR / "oem" / oem.strip().lower() / f"{board.strip().lower()}.yaml").exists():
|
|
21
|
+
return path
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def all_board_cfg_files() -> Generator[Path, None, None]:
|
|
26
|
+
"""
|
|
27
|
+
Generator that recursively yields all *.yaml files in the config directory.
|
|
28
|
+
|
|
29
|
+
Yields
|
|
30
|
+
------
|
|
31
|
+
item: Path
|
|
32
|
+
Path to a config file.
|
|
33
|
+
"""
|
|
34
|
+
path = Path(_CFG_DIR)
|
|
35
|
+
for item in path.rglob("*.yaml"):
|
|
36
|
+
if item.is_file():
|
|
37
|
+
yield item
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def next_or_raise(it, exc):
|
|
41
|
+
value = next(it, None)
|
|
42
|
+
if value is None:
|
|
43
|
+
raise exc
|
|
44
|
+
return value
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ekfsm
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0a26
|
|
4
4
|
Summary: The EKF System Management Library (ekfsm) is a sensor monitoring suite for Compact PCI Serial devices.
|
|
5
|
-
Author-email: Klaus Popp <klaus.popp@ci4rail.com>,
|
|
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
|
|
7
7
|
Requires-Dist: anytree
|
|
8
8
|
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: ipdb>=0.13.13
|
|
12
13
|
Requires-Dist: more-itertools
|
|
13
14
|
Requires-Dist: munch
|
|
15
|
+
Requires-Dist: schema>=0.7.7
|
|
14
16
|
Requires-Dist: smbus2
|
|
17
|
+
Requires-Dist: termcolor>=3.0.1
|
|
15
18
|
Requires-Dist: types-pyyaml>=6.0.12.20241230
|
|
16
19
|
Requires-Dist: yamale
|
|
17
20
|
Description-Content-Type: text/markdown
|
|
@@ -146,9 +149,9 @@ import ekfsm
|
|
|
146
149
|
|
|
147
150
|
system = ekfsm.System("system.yaml")
|
|
148
151
|
|
|
149
|
-
# alternative ways to get the SUR
|
|
150
|
-
sur = system["SER"] # by using the
|
|
151
|
-
sur = system.ser # by using the
|
|
152
|
+
# alternative ways to get the SUR HWModule
|
|
153
|
+
sur = system["SER"] # by using the HWModule name as key
|
|
154
|
+
sur = system.ser # by using the HWmodule name as attribute
|
|
152
155
|
sur = system.slots["SLOT1"].hwmodule # by using the slot name as key
|
|
153
156
|
sur = system.slots.slot1.hwmodule # by using the slot name as attribute
|
|
154
157
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
ekfsm/__init__.py,sha256=R12o_igFRTqlHUD9jyrOIPq2nBpTUWuvIPgCytBlVzk,142
|
|
2
|
+
ekfsm/cli.py,sha256=_z3a4VIw3eW6ajiLN-Nu6dB7G8SBgpTlY9CUFbC1LVE,3934
|
|
3
|
+
ekfsm/config.py,sha256=ezgr1fFAkbePy3cLnKfSpIZJ5nt54ysBHCbdCErYFB0,1186
|
|
4
|
+
ekfsm/exceptions.py,sha256=BELn0182Ixl6kSQ7gkIe3mlsrYXmTU-oSki-Hhrk5Z8,1605
|
|
5
|
+
ekfsm/lock.py,sha256=dnPjLXWfWIRnLcGec8g-imuqbmqqXWza8OGhS9Aqydk,3236
|
|
6
|
+
ekfsm/log.py,sha256=_GC8Y7a4fFV4_DNicbwQ-5rRzNQU6WSotXd2etXSrZk,866
|
|
7
|
+
ekfsm/py.typed,sha256=1gNRtmxvYcVqDDEyAzBLnD8dAOweUfYxW2ZPdJzN1fg,102
|
|
8
|
+
ekfsm/simctrl.py,sha256=WXPpWIju6b8Ch7FZW1PaPrWn7D7fP6gw37-ri-OJERE,5382
|
|
9
|
+
ekfsm/system.py,sha256=mReq8vRD6YGHlw37RzRlvwzsEM3OPjogneCVJ_XmOFU,11646
|
|
10
|
+
ekfsm/utils.py,sha256=eOgr4da-dxoMQ6ymjgx_nyBbea8Ck_LAQ8uLM4JgH3c,1179
|
|
11
|
+
ekfsm/boards/oem/ekf/ccu.yaml,sha256=qgr7YZO0kEddD9K6tv6222NyozkRNuF7NFw6hyX0XgE,2094
|
|
12
|
+
ekfsm/boards/oem/ekf/sc5-festival.yaml,sha256=_0kS5GegfyOt5CTJc9kY6HJbr9yZo4i18sVo6F4KE9c,772
|
|
13
|
+
ekfsm/boards/oem/ekf/sc9-toccata.yaml,sha256=btLgQMSsW0tRipnUYUkVQSIsjzxfKq0NXaQ1fMMyBRI,771
|
|
14
|
+
ekfsm/boards/oem/ekf/se5-club.yaml,sha256=j3u6sDwXMUBM0LNKwVm920w3T3tzjia2BRTQb2rRPZo,1049
|
|
15
|
+
ekfsm/boards/oem/ekf/sn4-djembe.yaml,sha256=ddLDdw7JpPpvR3TmlcTxNVNTOueTl6_A9LSveFrtz3E,1051
|
|
16
|
+
ekfsm/boards/oem/ekf/spv-mystic.yaml,sha256=zcLiNE7wVdXIT4vkwEYSqQ8ff-KEjCHfHnQzzPXJQ4E,1804
|
|
17
|
+
ekfsm/boards/oem/ekf/sq1-track.yaml,sha256=YU83BQjGu-4ejirwnGxd38sJme859kdRovkZyiOJciU,1050
|
|
18
|
+
ekfsm/boards/oem/ekf/sq3-quartet.yaml,sha256=pBB7Tv0IWLkFUYBs3tFvZriA-uqPuPIgzjaN0aHT4e4,1052
|
|
19
|
+
ekfsm/boards/oem/ekf/srf-fan.yaml,sha256=Mcu1Q8B1Ih10hoc_hbkGlppBmbOFcufsVUR42iW4Rwc,1368
|
|
20
|
+
ekfsm/boards/oem/ekf/sur-uart.yaml,sha256=VaNP2BSlNTi1lDco16Ma9smPEAMaVKvx-ZNDcm3QptM,1890
|
|
21
|
+
ekfsm/boards/oem/hitron/hdrc-300s.yaml,sha256=SwBHTWVqENBun_iZattPbvA9koc-LOI_MIXjLahKyyI,548
|
|
22
|
+
ekfsm/core/__init__.py,sha256=xfuU072JY_--561hfSS8ToBM-wgswY4Z-YwDMZkVA6c,348
|
|
23
|
+
ekfsm/core/components.py,sha256=gEChRquC2fEi3Y4BUa_EzvFkO45u95FT1rDg1lEdfHE,3836
|
|
24
|
+
ekfsm/core/probe.py,sha256=DgJvkvMjVk09n0Rzn13ybRvidrmFn_D2PD56XS-KgxU,262
|
|
25
|
+
ekfsm/core/slots.py,sha256=R26kfUnRzuspIPEMHFMBTkhgALu0Tuq7uGgvtfpafGs,6520
|
|
26
|
+
ekfsm/core/sysfs.py,sha256=CWH1BXlanHAFzK6KY23qLuFvBZ7Q9td3X6JLRwb3vu0,7309
|
|
27
|
+
ekfsm/core/utils.py,sha256=D5AcGp7xCsf1qA2hHHWe1bOnrpZlTOaq2srITn6bRkk,4194
|
|
28
|
+
ekfsm/devices/__init__.py,sha256=BYq4a7e3eF0GGpoKeBpoNISLIbAjAVMNqnGM_Taw8dE,937
|
|
29
|
+
ekfsm/devices/coretemp.py,sha256=UEsPTMYm05qNCnqnPtbAoYdIfvVGkDl9rJg3tkAP748,1992
|
|
30
|
+
ekfsm/devices/eeprom.py,sha256=cwcaM2YCKrw6du8d4zT_M3e4oFJh3XNQc5cQM2vqERE,33090
|
|
31
|
+
ekfsm/devices/ekf_ccu_uc.py,sha256=hjs5r7TKsrFhyyGKClgSFBpchQpFcE7fTZeuLrYiflY,15905
|
|
32
|
+
ekfsm/devices/ekf_sur_led.py,sha256=qpCn7qj4v27QjxB5xTC5wIXKfefpveOd3FPK3JElyVk,1997
|
|
33
|
+
ekfsm/devices/generic.py,sha256=LboZ7eanyC2xUnSX3-S7VCA87aTbJenlGtKsUk5JS2Q,12858
|
|
34
|
+
ekfsm/devices/gpio.py,sha256=37P7uu-ncg0TWf0Xs1iZM-PrX7F_09asd4IhWj6z21Y,10058
|
|
35
|
+
ekfsm/devices/iio.py,sha256=1Jyh5wJ53DxvpWNBqYW07kkaAN9446ebWGCMk2UIuWM,1265
|
|
36
|
+
ekfsm/devices/iio_thermal_humidity.py,sha256=KCeEqBlczroxp-hjsiRlXQdmmnJR9Ck3d3ztths5Vvc,1547
|
|
37
|
+
ekfsm/devices/imu.py,sha256=GwJrnC-WztpE5oGnkIp-laFkSp3_gbSp9YpJ8jBsUOs,423
|
|
38
|
+
ekfsm/devices/mux.py,sha256=QpVWsD43Mx1mtCDG_nOxtHeIeU2Cigc62UljJ_utSXQ,1974
|
|
39
|
+
ekfsm/devices/pmbus.py,sha256=fi_kR7TlkcqYhHuB7PA2PjANCYmo3MSPeV-B5ZI_WrQ,7004
|
|
40
|
+
ekfsm/devices/smbios.py,sha256=4P-sxOW27pkzIfVlvFNyVJOcZlYgk2KCTCEUvKf5D94,1067
|
|
41
|
+
ekfsm/devices/smbus.py,sha256=kbtjEnfrVI6lbfqAbojVqO5nnnpa6HanLf0X2iZjgCg,500
|
|
42
|
+
ekfsm/devices/utils.py,sha256=qeDNpTpQ3bLGYERAH5lMsifmOaEcQ32FOwEt8tvmjWU,174
|
|
43
|
+
ekfsm-1.3.0a26.dist-info/METADATA,sha256=tSSeLJ7dUXApngd0_rzISDWKpVLLKI5UPiTBTPW-p34,6634
|
|
44
|
+
ekfsm-1.3.0a26.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
45
|
+
ekfsm-1.3.0a26.dist-info/entry_points.txt,sha256=WhUR4FzuxPoGrbTOKLsNJO7NAnk2qd4T30fqzN1yLw8,45
|
|
46
|
+
ekfsm-1.3.0a26.dist-info/RECORD,,
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
ekfsm/__init__.py,sha256=R12o_igFRTqlHUD9jyrOIPq2nBpTUWuvIPgCytBlVzk,142
|
|
2
|
-
ekfsm/cli.py,sha256=JmTO1TyxrTlGTkQo8ndSR7nj0grSGuQdh9ugXx1IeQE,3919
|
|
3
|
-
ekfsm/config.py,sha256=FTk47f3qA05Zv6Cy_L_5XlGmmbC9z_kPdQJKpVoHkWs,924
|
|
4
|
-
ekfsm/exceptions.py,sha256=25P677GxfBTdBWHRngPce0bmhcLg7MFeTtuAvguxd90,1310
|
|
5
|
-
ekfsm/lock.py,sha256=qmWkW6OA-NLiDrtSsQn-K10tZJ19t-h4iFB5zyL97Vw,2682
|
|
6
|
-
ekfsm/log.py,sha256=_GC8Y7a4fFV4_DNicbwQ-5rRzNQU6WSotXd2etXSrZk,866
|
|
7
|
-
ekfsm/py.typed,sha256=1gNRtmxvYcVqDDEyAzBLnD8dAOweUfYxW2ZPdJzN1fg,102
|
|
8
|
-
ekfsm/simctrl.py,sha256=NkmjvqOym9Wruh0f14Od6gHfEgPMAkxUzMQ-nvzcM3Q,6681
|
|
9
|
-
ekfsm/system.py,sha256=azVFdVK7r-9RWotsD7c18YvyZfCqg-3z5t7SqUSDLh8,12922
|
|
10
|
-
ekfsm/boards/oem/ekf/ccu.yaml,sha256=qgr7YZO0kEddD9K6tv6222NyozkRNuF7NFw6hyX0XgE,2094
|
|
11
|
-
ekfsm/boards/oem/ekf/sc5-festival.yaml,sha256=_0kS5GegfyOt5CTJc9kY6HJbr9yZo4i18sVo6F4KE9c,772
|
|
12
|
-
ekfsm/boards/oem/ekf/sc9-toccata.yaml,sha256=btLgQMSsW0tRipnUYUkVQSIsjzxfKq0NXaQ1fMMyBRI,771
|
|
13
|
-
ekfsm/boards/oem/ekf/se5-club.yaml,sha256=j3u6sDwXMUBM0LNKwVm920w3T3tzjia2BRTQb2rRPZo,1049
|
|
14
|
-
ekfsm/boards/oem/ekf/sn4-djembe.yaml,sha256=ddLDdw7JpPpvR3TmlcTxNVNTOueTl6_A9LSveFrtz3E,1051
|
|
15
|
-
ekfsm/boards/oem/ekf/spv-mystic.yaml,sha256=zcLiNE7wVdXIT4vkwEYSqQ8ff-KEjCHfHnQzzPXJQ4E,1804
|
|
16
|
-
ekfsm/boards/oem/ekf/sq1-track.yaml,sha256=YU83BQjGu-4ejirwnGxd38sJme859kdRovkZyiOJciU,1050
|
|
17
|
-
ekfsm/boards/oem/ekf/sq3-quartet.yaml,sha256=pBB7Tv0IWLkFUYBs3tFvZriA-uqPuPIgzjaN0aHT4e4,1052
|
|
18
|
-
ekfsm/boards/oem/ekf/srf-fan.yaml,sha256=Mcu1Q8B1Ih10hoc_hbkGlppBmbOFcufsVUR42iW4Rwc,1368
|
|
19
|
-
ekfsm/boards/oem/ekf/sur-uart.yaml,sha256=VaNP2BSlNTi1lDco16Ma9smPEAMaVKvx-ZNDcm3QptM,1890
|
|
20
|
-
ekfsm/boards/oem/hitron/hdrc-300s.yaml,sha256=E567QsRPvyAEXpXOeF1OvX2AoQK8BTxI0C7QVBFlT_k,548
|
|
21
|
-
ekfsm/core/__init__.py,sha256=NVgbM5fBDbPhP5HtzMTKfloe9u5xutm47DM9Vt_kbRU,348
|
|
22
|
-
ekfsm/core/components.py,sha256=dh71jM_OJ8QhTzou-5L6RaF3abXgE470KJfxQRqq1CY,3836
|
|
23
|
-
ekfsm/core/probe.py,sha256=DgJvkvMjVk09n0Rzn13ybRvidrmFn_D2PD56XS-KgxU,262
|
|
24
|
-
ekfsm/core/slots.py,sha256=pKBkPUxv-Lz9GxCrlnZu4gR7f59tQ0GW1MBs7nblqaI,6582
|
|
25
|
-
ekfsm/core/sysfs.py,sha256=CVGxUEdhmJjRw8ZfnjL3hUwm6oWsp3ZKPG2qGUFYIiY,2283
|
|
26
|
-
ekfsm/core/utils.py,sha256=EoPOuRmLlvHvGneDcKjP7Qbjfsc4XlMbLeaSFRObt_E,3145
|
|
27
|
-
ekfsm/devices/__init__.py,sha256=UtFLCtAdpDJ3OaY7fedk13bx90NMsfxhyVAHV13t2U4,936
|
|
28
|
-
ekfsm/devices/coretemp.py,sha256=oco909zpXw9BqkLWV3dJma1_Q23M2EUGsgdcs4QtFjU,1966
|
|
29
|
-
ekfsm/devices/eeprom.py,sha256=wj2sy52s8YtsLyfb-_J3cbmI3m-EYdRgSqNZ9_GHVb8,31971
|
|
30
|
-
ekfsm/devices/ekf_ccu_uc.py,sha256=mKOWt3T7uLUZdIzCnZwJPLEKYjN22TgOGZEo6yclnoA,15384
|
|
31
|
-
ekfsm/devices/ekf_sur_led.py,sha256=dY2EIqUx4-LV7ipCEIg8DfXWlGxpspRmEtEhVfHY6LI,1871
|
|
32
|
-
ekfsm/devices/generic.py,sha256=9FDj8hhiCQAFmA5tt3lv1JPIZyAb3XCCriDIoR61kcE,10821
|
|
33
|
-
ekfsm/devices/gpio.py,sha256=hlJ3yJ8jSGUIkPpjymani0EcxYJX2iEybGbnV8N0O5E,9552
|
|
34
|
-
ekfsm/devices/iio.py,sha256=gMOJGdg2PvFbAvlBpLfDTIc_-9i1Z3OLpuabTke6N3I,1480
|
|
35
|
-
ekfsm/devices/iio_thermal_humidity.py,sha256=gALZ1B4f1ePGAEL7Q5VxbubgC3CgtC9RBM9F4YWuH4E,1478
|
|
36
|
-
ekfsm/devices/imu.py,sha256=GwJrnC-WztpE5oGnkIp-laFkSp3_gbSp9YpJ8jBsUOs,423
|
|
37
|
-
ekfsm/devices/mux.py,sha256=C2h5w8eXrL4RXXebCSnNY-VShTgeqmYDMvGSunapBqk,1830
|
|
38
|
-
ekfsm/devices/pmbus.py,sha256=QIs93qv9sXSdWEPyY55k0KVSr-XMPYNJhTux3vYLzAE,7104
|
|
39
|
-
ekfsm/devices/smbios.py,sha256=gDDYtfCd7njzqxJBKJxIR2BMCK6-uZxUVxC9y0hnz4g,1009
|
|
40
|
-
ekfsm/devices/smbus.py,sha256=zD9b6PehipMw-xoaOMC-oorDVxBoo30hc98gyFxFLs0,500
|
|
41
|
-
ekfsm/devices/utils.py,sha256=4-0Kmvy4ou8R71afNj6RqdBTjLW4SMWPHqVrzB2RUZw,397
|
|
42
|
-
ekfsm-1.1.0a15.post1.dist-info/METADATA,sha256=ylfAPwvJBbi31RurwwJQDMo6V3C-EYkeoTn_RjXs14E,6550
|
|
43
|
-
ekfsm-1.1.0a15.post1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
44
|
-
ekfsm-1.1.0a15.post1.dist-info/entry_points.txt,sha256=WhUR4FzuxPoGrbTOKLsNJO7NAnk2qd4T30fqzN1yLw8,45
|
|
45
|
-
ekfsm-1.1.0a15.post1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|