ekfsm 1.1.0a15.post1__py3-none-any.whl → 1.2.0a7__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/devices/eeprom.py +17 -0
- ekfsm/devices/ekf_ccu_uc.py +21 -1
- ekfsm/devices/pmbus.py +2 -3
- ekfsm/lock.py +47 -20
- ekfsm/system.py +3 -34
- ekfsm/utils.py +41 -0
- {ekfsm-1.1.0a15.post1.dist-info → ekfsm-1.2.0a7.dist-info}/METADATA +1 -1
- {ekfsm-1.1.0a15.post1.dist-info → ekfsm-1.2.0a7.dist-info}/RECORD +10 -9
- {ekfsm-1.1.0a15.post1.dist-info → ekfsm-1.2.0a7.dist-info}/WHEEL +0 -0
- {ekfsm-1.1.0a15.post1.dist-info → ekfsm-1.2.0a7.dist-info}/entry_points.txt +0 -0
ekfsm/devices/eeprom.py
CHANGED
|
@@ -1067,6 +1067,23 @@ class EKF_CCU_EEPROM(EKF_EEPROM):
|
|
|
1067
1067
|
def write_customer_area(self, data: bytes) -> None:
|
|
1068
1068
|
"""
|
|
1069
1069
|
Write data to CCU EEPROM customer area.
|
|
1070
|
+
|
|
1071
|
+
Parameters
|
|
1072
|
+
----------
|
|
1073
|
+
data
|
|
1074
|
+
The data to write to the customer area of the CCU EEPROM.
|
|
1075
|
+
|
|
1076
|
+
Raises
|
|
1077
|
+
------
|
|
1078
|
+
ValueError
|
|
1079
|
+
If the data exceeds the customer area length.
|
|
1080
|
+
|
|
1081
|
+
Example
|
|
1082
|
+
-------
|
|
1083
|
+
>>> eeprom = EKF_CCU_EEPROM()
|
|
1084
|
+
>>> eeprom.write_customer_area(b"Hello, World!")
|
|
1085
|
+
>>> eeprom.customer_area()
|
|
1086
|
+
b'Hello, World!'
|
|
1070
1087
|
"""
|
|
1071
1088
|
if len(data) > self._customer_area_length:
|
|
1072
1089
|
raise ValueError("Data exceeds customer area length")
|
ekfsm/devices/ekf_ccu_uc.py
CHANGED
|
@@ -54,7 +54,10 @@ class EKFCcuUc(Device):
|
|
|
54
54
|
def temperature(self) -> float:
|
|
55
55
|
"""
|
|
56
56
|
Get the temperature from the CCU thermal/humidity sensor.
|
|
57
|
-
|
|
57
|
+
|
|
58
|
+
Note
|
|
59
|
+
----
|
|
60
|
+
The CCU reads the temperature once per second.
|
|
58
61
|
|
|
59
62
|
Returns
|
|
60
63
|
-------
|
|
@@ -304,6 +307,13 @@ class EKFCcuUc(Device):
|
|
|
304
307
|
progress_callback
|
|
305
308
|
A callback function that is called with the current progress in bytes.
|
|
306
309
|
|
|
310
|
+
Example
|
|
311
|
+
-------
|
|
312
|
+
>>> from ekfsm.devices import EkfCcuUc
|
|
313
|
+
>>> ccu = EkfCcuUc("ccu")
|
|
314
|
+
>>> firmware = open("fw-ccu-1.0.0.bin", "rb").read()
|
|
315
|
+
>>> # Load firmware with progress callback
|
|
316
|
+
>>> ccu.load_firmware(firmware, progress_callback=lambda x: print(f"Progress: {x} bytes"))
|
|
307
317
|
"""
|
|
308
318
|
with Locker(self.name + "-load_firmware").lock():
|
|
309
319
|
offset = 0
|
|
@@ -423,6 +433,8 @@ class EKFCcuUc(Device):
|
|
|
423
433
|
This would load a parameterset with just one parameter, the default fan speed. All other parameters will
|
|
424
434
|
be set to their default values.
|
|
425
435
|
|
|
436
|
+
Important
|
|
437
|
+
---------
|
|
426
438
|
In order to apply the parameterset, the CCU must be restarted.
|
|
427
439
|
|
|
428
440
|
Parameters
|
|
@@ -430,6 +442,14 @@ class EKFCcuUc(Device):
|
|
|
430
442
|
_cfg
|
|
431
443
|
The parameterset in JSON format.
|
|
432
444
|
|
|
445
|
+
Example
|
|
446
|
+
-------
|
|
447
|
+
>>> from ekfsm.devices import EkfCcuUc
|
|
448
|
+
>>> ccu = EkfCcuUc("ccu")
|
|
449
|
+
>>> # Load parameterset
|
|
450
|
+
>>> ccu.load_parameterset('{"version": "1.0.0", "parameters": {"fan-defrpm": "6000"}}')
|
|
451
|
+
>>> # Restart CCU to apply parameterset
|
|
452
|
+
>>> ccu.restart()
|
|
433
453
|
"""
|
|
434
454
|
with Locker(self.name + "-parameterset").lock():
|
|
435
455
|
cfg = _cfg.encode("utf-8")
|
ekfsm/devices/pmbus.py
CHANGED
|
@@ -93,9 +93,8 @@ class PsuStatus(IntFlag):
|
|
|
93
93
|
>>> PsuStatus.OK in status
|
|
94
94
|
True
|
|
95
95
|
>>> # Instead, check if status is OK
|
|
96
|
-
>>> status
|
|
97
|
-
|
|
98
|
-
<PsuStatus.OK: 0>
|
|
96
|
+
>>> status == PsuStatus(0x00)
|
|
97
|
+
False
|
|
99
98
|
>>> PsuStatus.OUTPUT_OVERCURRENT in status
|
|
100
99
|
False
|
|
101
100
|
"""
|
ekfsm/lock.py
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Some devices or device functions don't allow concurrent access.
|
|
3
|
+
The locking mechanism is used to ensure that only one process/thread can
|
|
4
|
+
access the device (function) at a time.
|
|
5
|
+
|
|
6
|
+
Locking granularity is defined by the device.
|
|
7
|
+
It may be at the device level or function level.
|
|
8
|
+
|
|
9
|
+
Application can choose to use the locking mechanism or not.
|
|
10
|
+
By default, the locking mechanism is enabled and uses the default
|
|
11
|
+
lockfile root directory ``/var/lock/ekfsm``.
|
|
12
|
+
|
|
13
|
+
Use :func:`locking_configure` to enable or disable the locking mechanism or to change
|
|
14
|
+
the lockfile root directory.
|
|
15
|
+
"""
|
|
16
|
+
|
|
1
17
|
import fcntl
|
|
2
18
|
import os
|
|
3
19
|
from pathlib import Path
|
|
4
20
|
from contextlib import contextmanager
|
|
5
21
|
|
|
6
|
-
#
|
|
7
|
-
# Some devices or device functions don't allow concurrent access.
|
|
8
|
-
# The locking mechanism is used to ensure that only one process/thread can
|
|
9
|
-
# access the device (function) at a time.
|
|
10
|
-
#
|
|
11
|
-
# Locking granularity is defined by the device.
|
|
12
|
-
# It may be at the device level or function level.
|
|
13
|
-
#
|
|
14
|
-
# Application can choose to use the locking mechanism or not.
|
|
15
|
-
# By default, the locking mechanism is enabled and uses the default
|
|
16
|
-
# lockfile root directory /var/lock/ekfsm.
|
|
17
|
-
#
|
|
18
|
-
# Use locking_configure() to enable or disable the locking mechanism or to change
|
|
19
|
-
# the lockfile root directory.
|
|
20
|
-
|
|
21
22
|
USE_LOCK = True
|
|
22
23
|
LOCKFILE_ROOT = "/var/lock/ekfsm"
|
|
23
24
|
ALL_LOCKERS: list["Locker"] = [] # List of all locker instances
|
|
@@ -27,8 +28,12 @@ def locking_configure(enable: bool, lockfile_root: str = LOCKFILE_ROOT):
|
|
|
27
28
|
"""
|
|
28
29
|
Configures the locking mechanism.
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
enable
|
|
34
|
+
Whether to enable or disable locking.
|
|
35
|
+
lockfile_root
|
|
36
|
+
The root directory for lockfiles.
|
|
32
37
|
"""
|
|
33
38
|
global USE_LOCK, LOCKFILE_ROOT
|
|
34
39
|
USE_LOCK = enable
|
|
@@ -55,9 +60,12 @@ class Locker:
|
|
|
55
60
|
|
|
56
61
|
Example
|
|
57
62
|
-------
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
.. code-block:: python
|
|
64
|
+
|
|
65
|
+
with Locker("mysharedresourcename").lock():
|
|
66
|
+
# Access the shared resource here
|
|
67
|
+
pass
|
|
68
|
+
|
|
61
69
|
"""
|
|
62
70
|
|
|
63
71
|
def __init__(self, module: str):
|
|
@@ -72,6 +80,17 @@ class Locker:
|
|
|
72
80
|
ALL_LOCKERS.append(self)
|
|
73
81
|
|
|
74
82
|
def cleanup(self):
|
|
83
|
+
"""
|
|
84
|
+
Cleans up the lock file and closes the lock file descriptor.
|
|
85
|
+
|
|
86
|
+
Important
|
|
87
|
+
---------
|
|
88
|
+
This method should be called when the lock is no longer needed.
|
|
89
|
+
|
|
90
|
+
Note
|
|
91
|
+
----
|
|
92
|
+
It is automatically called when the context manager exits.
|
|
93
|
+
"""
|
|
75
94
|
if not USE_LOCK:
|
|
76
95
|
return
|
|
77
96
|
if self.lock_fd is not None:
|
|
@@ -84,6 +103,14 @@ class Locker:
|
|
|
84
103
|
|
|
85
104
|
@contextmanager
|
|
86
105
|
def lock(self):
|
|
106
|
+
"""
|
|
107
|
+
Locks the resource for exclusive access.
|
|
108
|
+
|
|
109
|
+
Note
|
|
110
|
+
----
|
|
111
|
+
This method is a context manager that locks the resource when entered
|
|
112
|
+
and releases the lock when exited.
|
|
113
|
+
"""
|
|
87
114
|
if not USE_LOCK:
|
|
88
115
|
yield
|
|
89
116
|
self.lock_fd = os.open(self.lockfile_path, os.O_RDWR)
|
ekfsm/system.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
from typing import Tuple, Any
|
|
1
|
+
from typing import Tuple, Any
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from munch import Munch, munchify
|
|
4
4
|
|
|
5
5
|
from ekfsm.core.components import SysTree
|
|
6
6
|
import yaml
|
|
7
7
|
|
|
8
|
+
from ekfsm.utils import all_board_cfg_files, find_board_config
|
|
9
|
+
|
|
8
10
|
from .core.slots import Slot, SlotType
|
|
9
11
|
|
|
10
12
|
from .config import load_config
|
|
@@ -14,39 +16,6 @@ from .exceptions import ConfigError
|
|
|
14
16
|
from .log import ekfsm_logger
|
|
15
17
|
|
|
16
18
|
|
|
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
19
|
class System(SysTree):
|
|
51
20
|
"""
|
|
52
21
|
A System represents a CPCI system.
|
ekfsm/utils.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from typing import Generator
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
_CFG_DIR = Path(__file__).parent / "boards"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def find_board_config(module_type: str) -> Path | None:
|
|
10
|
+
"""
|
|
11
|
+
Find a matching board config in `boards/oem/` given the module type specified in
|
|
12
|
+
the system configuration file.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
module_type
|
|
17
|
+
Board type specified in the system configuration for a slot.
|
|
18
|
+
It must consist of an OEM and the board type, separated by whitespace. Neither
|
|
19
|
+
part may contain any other whitespace.
|
|
20
|
+
"""
|
|
21
|
+
oem, board = module_type.split(maxsplit=1)
|
|
22
|
+
if (
|
|
23
|
+
path := _CFG_DIR / "oem" / oem.strip().lower() / f"{board.strip().lower()}.yaml"
|
|
24
|
+
).exists():
|
|
25
|
+
return path
|
|
26
|
+
return None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def all_board_cfg_files() -> Generator[Path, None, None]:
|
|
30
|
+
"""
|
|
31
|
+
Generator that recursively yields all *.yaml files in the config directory.
|
|
32
|
+
|
|
33
|
+
Yields
|
|
34
|
+
------
|
|
35
|
+
item: Path
|
|
36
|
+
Path to a config file.
|
|
37
|
+
"""
|
|
38
|
+
path = Path(_CFG_DIR)
|
|
39
|
+
for item in path.rglob("*.yaml"):
|
|
40
|
+
if item.is_file():
|
|
41
|
+
yield item
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ekfsm
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0a7
|
|
4
4
|
Summary: The EKF System Management Library (ekfsm) is a sensor monitoring suite for Compact PCI Serial devices.
|
|
5
5
|
Author-email: Klaus Popp <klaus.popp@ci4rail.com>, Jan Jansen <jan@ekf.de>, Felix Päßler <fp@ekf.de>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -2,11 +2,12 @@ ekfsm/__init__.py,sha256=R12o_igFRTqlHUD9jyrOIPq2nBpTUWuvIPgCytBlVzk,142
|
|
|
2
2
|
ekfsm/cli.py,sha256=JmTO1TyxrTlGTkQo8ndSR7nj0grSGuQdh9ugXx1IeQE,3919
|
|
3
3
|
ekfsm/config.py,sha256=FTk47f3qA05Zv6Cy_L_5XlGmmbC9z_kPdQJKpVoHkWs,924
|
|
4
4
|
ekfsm/exceptions.py,sha256=25P677GxfBTdBWHRngPce0bmhcLg7MFeTtuAvguxd90,1310
|
|
5
|
-
ekfsm/lock.py,sha256=
|
|
5
|
+
ekfsm/lock.py,sha256=XWLu2yhgIs16oSyc_4jdVUobbxyYlYOjZi1EFgHsXVU,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=NkmjvqOym9Wruh0f14Od6gHfEgPMAkxUzMQ-nvzcM3Q,6681
|
|
9
|
-
ekfsm/system.py,sha256=
|
|
9
|
+
ekfsm/system.py,sha256=kBukgVyPJYTh_ilauEEANG2KKqHWOrQBYLhVdG679HM,12028
|
|
10
|
+
ekfsm/utils.py,sha256=IKQrGr8UzUJpqj365uQqIWDRTAgpVC0OUmqIKzt_9T0,1081
|
|
10
11
|
ekfsm/boards/oem/ekf/ccu.yaml,sha256=qgr7YZO0kEddD9K6tv6222NyozkRNuF7NFw6hyX0XgE,2094
|
|
11
12
|
ekfsm/boards/oem/ekf/sc5-festival.yaml,sha256=_0kS5GegfyOt5CTJc9kY6HJbr9yZo4i18sVo6F4KE9c,772
|
|
12
13
|
ekfsm/boards/oem/ekf/sc9-toccata.yaml,sha256=btLgQMSsW0tRipnUYUkVQSIsjzxfKq0NXaQ1fMMyBRI,771
|
|
@@ -26,8 +27,8 @@ ekfsm/core/sysfs.py,sha256=CVGxUEdhmJjRw8ZfnjL3hUwm6oWsp3ZKPG2qGUFYIiY,2283
|
|
|
26
27
|
ekfsm/core/utils.py,sha256=EoPOuRmLlvHvGneDcKjP7Qbjfsc4XlMbLeaSFRObt_E,3145
|
|
27
28
|
ekfsm/devices/__init__.py,sha256=UtFLCtAdpDJ3OaY7fedk13bx90NMsfxhyVAHV13t2U4,936
|
|
28
29
|
ekfsm/devices/coretemp.py,sha256=oco909zpXw9BqkLWV3dJma1_Q23M2EUGsgdcs4QtFjU,1966
|
|
29
|
-
ekfsm/devices/eeprom.py,sha256=
|
|
30
|
-
ekfsm/devices/ekf_ccu_uc.py,sha256=
|
|
30
|
+
ekfsm/devices/eeprom.py,sha256=4UjydeDxZT7w2zXkhZu7GUuHYu8sAidT8xuVtkt4OJw,32389
|
|
31
|
+
ekfsm/devices/ekf_ccu_uc.py,sha256=bVdxaiXtrJC2-tSRv1rGUzm4wOxL20QfTL4NIKdRJE8,16092
|
|
31
32
|
ekfsm/devices/ekf_sur_led.py,sha256=dY2EIqUx4-LV7ipCEIg8DfXWlGxpspRmEtEhVfHY6LI,1871
|
|
32
33
|
ekfsm/devices/generic.py,sha256=9FDj8hhiCQAFmA5tt3lv1JPIZyAb3XCCriDIoR61kcE,10821
|
|
33
34
|
ekfsm/devices/gpio.py,sha256=hlJ3yJ8jSGUIkPpjymani0EcxYJX2iEybGbnV8N0O5E,9552
|
|
@@ -35,11 +36,11 @@ ekfsm/devices/iio.py,sha256=gMOJGdg2PvFbAvlBpLfDTIc_-9i1Z3OLpuabTke6N3I,1480
|
|
|
35
36
|
ekfsm/devices/iio_thermal_humidity.py,sha256=gALZ1B4f1ePGAEL7Q5VxbubgC3CgtC9RBM9F4YWuH4E,1478
|
|
36
37
|
ekfsm/devices/imu.py,sha256=GwJrnC-WztpE5oGnkIp-laFkSp3_gbSp9YpJ8jBsUOs,423
|
|
37
38
|
ekfsm/devices/mux.py,sha256=C2h5w8eXrL4RXXebCSnNY-VShTgeqmYDMvGSunapBqk,1830
|
|
38
|
-
ekfsm/devices/pmbus.py,sha256=
|
|
39
|
+
ekfsm/devices/pmbus.py,sha256=5nIvuUkY20YwXTIpd3lebdu2dU-he_IJ7wLz1EUTrzc,7078
|
|
39
40
|
ekfsm/devices/smbios.py,sha256=gDDYtfCd7njzqxJBKJxIR2BMCK6-uZxUVxC9y0hnz4g,1009
|
|
40
41
|
ekfsm/devices/smbus.py,sha256=zD9b6PehipMw-xoaOMC-oorDVxBoo30hc98gyFxFLs0,500
|
|
41
42
|
ekfsm/devices/utils.py,sha256=4-0Kmvy4ou8R71afNj6RqdBTjLW4SMWPHqVrzB2RUZw,397
|
|
42
|
-
ekfsm-1.
|
|
43
|
-
ekfsm-1.
|
|
44
|
-
ekfsm-1.
|
|
45
|
-
ekfsm-1.
|
|
43
|
+
ekfsm-1.2.0a7.dist-info/METADATA,sha256=VUyieRTVS_l9ZWkP1ctAYgFAK5s9tv3V_mUOTBXkePM,6543
|
|
44
|
+
ekfsm-1.2.0a7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
45
|
+
ekfsm-1.2.0a7.dist-info/entry_points.txt,sha256=WhUR4FzuxPoGrbTOKLsNJO7NAnk2qd4T30fqzN1yLw8,45
|
|
46
|
+
ekfsm-1.2.0a7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|