shepherd-core 2025.4.1__py3-none-any.whl → 2025.4.2__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.
- shepherd_core/calibration_hw_def.py +11 -11
- shepherd_core/commons.py +4 -4
- shepherd_core/data_models/base/cal_measurement.py +10 -11
- shepherd_core/data_models/base/calibration.py +7 -6
- shepherd_core/data_models/base/content.py +1 -1
- shepherd_core/data_models/base/shepherd.py +6 -7
- shepherd_core/data_models/base/wrapper.py +2 -2
- shepherd_core/data_models/content/energy_environment.py +4 -3
- shepherd_core/data_models/content/firmware.py +9 -7
- shepherd_core/data_models/content/virtual_harvester.py +30 -22
- shepherd_core/data_models/content/virtual_source.py +16 -15
- shepherd_core/data_models/experiment/experiment.py +13 -13
- shepherd_core/data_models/experiment/observer_features.py +7 -8
- shepherd_core/data_models/experiment/target_config.py +12 -12
- shepherd_core/data_models/task/__init__.py +5 -5
- shepherd_core/data_models/task/emulation.py +13 -14
- shepherd_core/data_models/task/firmware_mod.py +11 -11
- shepherd_core/data_models/task/harvest.py +7 -6
- shepherd_core/data_models/task/observer_tasks.py +7 -7
- shepherd_core/data_models/task/programming.py +11 -11
- shepherd_core/data_models/task/testbed_tasks.py +8 -8
- shepherd_core/data_models/testbed/cape.py +7 -6
- shepherd_core/data_models/testbed/gpio.py +8 -7
- shepherd_core/data_models/testbed/mcu.py +8 -7
- shepherd_core/data_models/testbed/observer.py +9 -7
- shepherd_core/data_models/testbed/target.py +9 -7
- shepherd_core/data_models/testbed/testbed.py +11 -10
- shepherd_core/decoder_waveform/uart.py +5 -5
- shepherd_core/fw_tools/converter.py +4 -3
- shepherd_core/fw_tools/patcher.py +14 -15
- shepherd_core/fw_tools/validation.py +3 -2
- shepherd_core/inventory/__init__.py +6 -6
- shepherd_core/inventory/python.py +1 -1
- shepherd_core/inventory/system.py +11 -8
- shepherd_core/inventory/target.py +3 -3
- shepherd_core/logger.py +2 -2
- shepherd_core/reader.py +37 -39
- shepherd_core/testbed_client/client_abc_fix.py +20 -13
- shepherd_core/testbed_client/client_web.py +18 -11
- shepherd_core/testbed_client/fixtures.py +19 -16
- shepherd_core/testbed_client/user_model.py +6 -5
- shepherd_core/version.py +1 -1
- shepherd_core/vsource/target_model.py +3 -3
- shepherd_core/vsource/virtual_converter_model.py +3 -3
- shepherd_core/vsource/virtual_harvester_model.py +7 -9
- shepherd_core/vsource/virtual_harvester_simulation.py +6 -5
- shepherd_core/vsource/virtual_source_model.py +6 -5
- shepherd_core/vsource/virtual_source_simulation.py +7 -6
- shepherd_core/writer.py +32 -34
- {shepherd_core-2025.4.1.dist-info → shepherd_core-2025.4.2.dist-info}/METADATA +2 -3
- shepherd_core-2025.4.2.dist-info/RECORD +81 -0
- {shepherd_core-2025.4.1.dist-info → shepherd_core-2025.4.2.dist-info}/WHEEL +1 -1
- shepherd_core-2025.4.1.dist-info/RECORD +0 -81
- {shepherd_core-2025.4.1.dist-info → shepherd_core-2025.4.2.dist-info}/top_level.txt +0 -0
- {shepherd_core-2025.4.1.dist-info → shepherd_core-2025.4.2.dist-info}/zip-safe +0 -0
|
@@ -4,15 +4,15 @@ These models import externally from all other model-modules!
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from typing import List
|
|
8
7
|
from typing import Optional
|
|
9
8
|
from typing import Union
|
|
10
9
|
|
|
11
10
|
import yaml
|
|
12
11
|
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
12
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
13
|
+
from shepherd_core.data_models.base.wrapper import Wrapper
|
|
14
|
+
from shepherd_core.logger import logger
|
|
15
|
+
|
|
16
16
|
from .emulation import Compression
|
|
17
17
|
from .emulation import EmulationTask
|
|
18
18
|
from .firmware_mod import FirmwareModTask
|
|
@@ -74,7 +74,7 @@ def prepare_task(config: Union[ShpModel, Path, str], observer: Optional[str] = N
|
|
|
74
74
|
return shp_wrap
|
|
75
75
|
|
|
76
76
|
|
|
77
|
-
def extract_tasks(shp_wrap: Wrapper, *, no_task_sets: bool = True) ->
|
|
77
|
+
def extract_tasks(shp_wrap: Wrapper, *, no_task_sets: bool = True) -> list[ShpModel]:
|
|
78
78
|
"""Make the individual task-sets usable for each observer."""
|
|
79
79
|
if shp_wrap.datatype == ObserverTasks.__name__:
|
|
80
80
|
obt = ObserverTasks(**shp_wrap.parameters)
|
|
@@ -5,26 +5,26 @@ from datetime import datetime
|
|
|
5
5
|
from datetime import timedelta
|
|
6
6
|
from enum import Enum
|
|
7
7
|
from pathlib import Path
|
|
8
|
+
from typing import Annotated
|
|
8
9
|
from typing import Optional
|
|
9
10
|
from typing import Union
|
|
10
11
|
|
|
11
12
|
from pydantic import Field
|
|
12
13
|
from pydantic import model_validator
|
|
13
14
|
from pydantic import validate_call
|
|
14
|
-
from typing_extensions import Annotated
|
|
15
15
|
from typing_extensions import Self
|
|
16
16
|
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from
|
|
22
|
-
from
|
|
23
|
-
from
|
|
24
|
-
from
|
|
25
|
-
from
|
|
26
|
-
from
|
|
27
|
-
from
|
|
17
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
18
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
19
|
+
from shepherd_core.data_models.base.timezone import local_tz
|
|
20
|
+
from shepherd_core.data_models.content.virtual_source import VirtualSourceConfig
|
|
21
|
+
from shepherd_core.data_models.experiment.experiment import Experiment
|
|
22
|
+
from shepherd_core.data_models.experiment.observer_features import GpioActuation
|
|
23
|
+
from shepherd_core.data_models.experiment.observer_features import GpioTracing
|
|
24
|
+
from shepherd_core.data_models.experiment.observer_features import PowerTracing
|
|
25
|
+
from shepherd_core.data_models.experiment.observer_features import SystemLogging
|
|
26
|
+
from shepherd_core.data_models.testbed import Testbed
|
|
27
|
+
from shepherd_core.data_models.testbed.cape import TargetPort
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class Compression(str, Enum):
|
|
@@ -111,9 +111,8 @@ class EmulationTask(ShpModel):
|
|
|
111
111
|
@model_validator(mode="after")
|
|
112
112
|
def post_validation(self) -> Self:
|
|
113
113
|
# TODO: limit paths
|
|
114
|
-
has_time = self.time_start is not None
|
|
115
114
|
time_now = datetime.now().astimezone()
|
|
116
|
-
if
|
|
115
|
+
if self.time_start is not None and self.time_start < time_now:
|
|
117
116
|
msg = (
|
|
118
117
|
"Start-Time for Emulation can't be in the past "
|
|
119
118
|
f"('{self.time_start}' vs '{time_now}'."
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import copy
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import Annotated
|
|
5
6
|
from typing import Optional
|
|
6
7
|
from typing import TypedDict
|
|
7
8
|
from typing import Union
|
|
@@ -9,20 +10,19 @@ from typing import Union
|
|
|
9
10
|
from pydantic import Field
|
|
10
11
|
from pydantic import model_validator
|
|
11
12
|
from pydantic import validate_call
|
|
12
|
-
from typing_extensions import Annotated
|
|
13
13
|
from typing_extensions import Self
|
|
14
14
|
from typing_extensions import Unpack
|
|
15
15
|
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from
|
|
22
|
-
from
|
|
23
|
-
from
|
|
24
|
-
from
|
|
25
|
-
from
|
|
16
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
17
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
18
|
+
from shepherd_core.data_models.content.firmware import Firmware
|
|
19
|
+
from shepherd_core.data_models.content.firmware import FirmwareDType
|
|
20
|
+
from shepherd_core.data_models.content.firmware import FirmwareStr
|
|
21
|
+
from shepherd_core.data_models.experiment.experiment import Experiment
|
|
22
|
+
from shepherd_core.data_models.testbed import Testbed
|
|
23
|
+
from shepherd_core.data_models.testbed.target import IdInt16
|
|
24
|
+
from shepherd_core.data_models.testbed.target import MCUPort
|
|
25
|
+
from shepherd_core.logger import logger
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
class FirmwareModTask(ShpModel):
|
|
@@ -3,18 +3,19 @@
|
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from datetime import timedelta
|
|
5
5
|
from pathlib import Path
|
|
6
|
+
from typing import Annotated
|
|
6
7
|
from typing import Optional
|
|
7
8
|
|
|
8
9
|
from pydantic import Field
|
|
9
10
|
from pydantic import model_validator
|
|
10
|
-
from typing_extensions import Annotated
|
|
11
11
|
from typing_extensions import Self
|
|
12
12
|
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
13
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
14
|
+
from shepherd_core.data_models.base.timezone import local_tz
|
|
15
|
+
from shepherd_core.data_models.content.virtual_harvester import VirtualHarvesterConfig
|
|
16
|
+
from shepherd_core.data_models.experiment.observer_features import PowerTracing
|
|
17
|
+
from shepherd_core.data_models.experiment.observer_features import SystemLogging
|
|
18
|
+
|
|
18
19
|
from .emulation import Compression
|
|
19
20
|
|
|
20
21
|
|
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from datetime import timedelta
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import List
|
|
7
6
|
from typing import Optional
|
|
8
7
|
|
|
9
8
|
from pydantic import validate_call
|
|
10
9
|
from typing_extensions import Self
|
|
11
10
|
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
11
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
12
|
+
from shepherd_core.data_models.base.content import NameStr
|
|
13
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
14
|
+
from shepherd_core.data_models.experiment.experiment import Experiment
|
|
15
|
+
from shepherd_core.data_models.testbed.testbed import Testbed
|
|
16
|
+
|
|
17
17
|
from .emulation import EmulationTask
|
|
18
18
|
from .firmware_mod import FirmwareModTask
|
|
19
19
|
from .programming import ProgrammingTask
|
|
@@ -78,7 +78,7 @@ class ObserverTasks(ShpModel):
|
|
|
78
78
|
emulation=EmulationTask.from_xp(xp, tb, tgt_id, root_path),
|
|
79
79
|
)
|
|
80
80
|
|
|
81
|
-
def get_tasks(self) ->
|
|
81
|
+
def get_tasks(self) -> list[ShpModel]:
|
|
82
82
|
task_names = ["fw1_mod", "fw2_mod", "fw1_prog", "fw2_prog", "emulation"]
|
|
83
83
|
tasks = []
|
|
84
84
|
|
|
@@ -2,24 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
import copy
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import Annotated
|
|
5
6
|
from typing import Optional
|
|
6
7
|
|
|
7
8
|
from pydantic import Field
|
|
8
9
|
from pydantic import model_validator
|
|
9
10
|
from pydantic import validate_call
|
|
10
|
-
from typing_extensions import Annotated
|
|
11
11
|
from typing_extensions import Self
|
|
12
12
|
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from
|
|
20
|
-
from
|
|
21
|
-
from
|
|
22
|
-
from
|
|
13
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
14
|
+
from shepherd_core.data_models.base.content import SafeStr
|
|
15
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
16
|
+
from shepherd_core.data_models.content.firmware import suffix_to_DType
|
|
17
|
+
from shepherd_core.data_models.content.firmware_datatype import FirmwareDType
|
|
18
|
+
from shepherd_core.data_models.experiment.experiment import Experiment
|
|
19
|
+
from shepherd_core.data_models.testbed.cape import TargetPort
|
|
20
|
+
from shepherd_core.data_models.testbed.mcu import ProgrammerProtocol
|
|
21
|
+
from shepherd_core.data_models.testbed.target import MCUPort
|
|
22
|
+
from shepherd_core.data_models.testbed.testbed import Testbed
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class ProgrammingTask(ShpModel):
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"""Collection of tasks for all observers included in experiment."""
|
|
2
2
|
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Annotated
|
|
4
4
|
from typing import Optional
|
|
5
5
|
|
|
6
6
|
from pydantic import Field
|
|
7
7
|
from pydantic import validate_call
|
|
8
|
-
from typing_extensions import Annotated
|
|
9
8
|
from typing_extensions import Self
|
|
10
9
|
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
10
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
11
|
+
from shepherd_core.data_models.base.content import NameStr
|
|
12
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
13
|
+
from shepherd_core.data_models.experiment.experiment import Experiment
|
|
14
|
+
from shepherd_core.data_models.testbed.testbed import Testbed
|
|
15
|
+
|
|
16
16
|
from .observer_tasks import ObserverTasks
|
|
17
17
|
|
|
18
18
|
|
|
@@ -20,7 +20,7 @@ class TestbedTasks(ShpModel):
|
|
|
20
20
|
"""Collection of tasks for all observers included in experiment."""
|
|
21
21
|
|
|
22
22
|
name: NameStr
|
|
23
|
-
observer_tasks: Annotated[
|
|
23
|
+
observer_tasks: Annotated[list[ObserverTasks], Field(min_length=1, max_length=128)]
|
|
24
24
|
|
|
25
25
|
# POST PROCESS
|
|
26
26
|
email_results: bool = False
|
|
@@ -3,17 +3,18 @@
|
|
|
3
3
|
from datetime import date
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from enum import Enum
|
|
6
|
+
from typing import Any
|
|
6
7
|
from typing import Optional
|
|
7
8
|
from typing import Union
|
|
8
9
|
|
|
9
10
|
from pydantic import Field
|
|
10
11
|
from pydantic import model_validator
|
|
11
12
|
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
13
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
14
|
+
from shepherd_core.data_models.base.content import NameStr
|
|
15
|
+
from shepherd_core.data_models.base.content import SafeStr
|
|
16
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
17
|
+
from shepherd_core.testbed_client import tb_client
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class TargetPort(str, Enum):
|
|
@@ -42,6 +43,6 @@ class Cape(ShpModel, title="Shepherd-Cape"):
|
|
|
42
43
|
|
|
43
44
|
@model_validator(mode="before")
|
|
44
45
|
@classmethod
|
|
45
|
-
def query_database(cls, values: dict) -> dict:
|
|
46
|
+
def query_database(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
46
47
|
values, _ = tb_client.try_completing_model(cls.__name__, values)
|
|
47
48
|
return values
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
"""meta-data representation of a testbed-component (physical object)."""
|
|
2
2
|
|
|
3
3
|
from enum import Enum
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
from typing import Any
|
|
4
6
|
from typing import Optional
|
|
5
7
|
|
|
6
8
|
from pydantic import Field
|
|
7
9
|
from pydantic import StringConstraints
|
|
8
10
|
from pydantic import model_validator
|
|
9
|
-
from typing_extensions import Annotated
|
|
10
11
|
from typing_extensions import Self
|
|
11
12
|
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
13
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
14
|
+
from shepherd_core.data_models.base.content import NameStr
|
|
15
|
+
from shepherd_core.data_models.base.content import SafeStr
|
|
16
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
17
|
+
from shepherd_core.testbed_client import tb_client
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class Direction(str, Enum):
|
|
@@ -45,7 +46,7 @@ class GPIO(ShpModel, title="GPIO of Observer Node"):
|
|
|
45
46
|
|
|
46
47
|
@model_validator(mode="before")
|
|
47
48
|
@classmethod
|
|
48
|
-
def query_database(cls, values: dict) -> dict:
|
|
49
|
+
def query_database(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
49
50
|
values, _ = tb_client.try_completing_model(cls.__name__, values)
|
|
50
51
|
return values
|
|
51
52
|
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
"""meta-data representation of a testbed-component (physical object)."""
|
|
2
2
|
|
|
3
3
|
from enum import Enum
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
from typing import Any
|
|
4
6
|
from typing import Optional
|
|
5
7
|
|
|
6
8
|
from pydantic import Field
|
|
7
9
|
from pydantic import model_validator
|
|
8
|
-
from typing_extensions import Annotated
|
|
9
10
|
|
|
10
|
-
from
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
11
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
12
|
+
from shepherd_core.data_models.base.content import NameStr
|
|
13
|
+
from shepherd_core.data_models.base.content import SafeStr
|
|
14
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
15
|
+
from shepherd_core.testbed_client import tb_client
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class ProgrammerProtocol(str, Enum):
|
|
@@ -45,6 +46,6 @@ class MCU(ShpModel, title="Microcontroller of the Target Node"):
|
|
|
45
46
|
|
|
46
47
|
@model_validator(mode="before")
|
|
47
48
|
@classmethod
|
|
48
|
-
def query_database(cls, values: dict) -> dict:
|
|
49
|
+
def query_database(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
49
50
|
values, _ = tb_client.try_completing_model(cls.__name__, values)
|
|
50
51
|
return values
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
"""meta-data representation of a testbed-component (physical object)."""
|
|
2
2
|
|
|
3
3
|
from datetime import datetime
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
from typing import Any
|
|
4
6
|
from typing import Optional
|
|
5
7
|
|
|
6
8
|
from pydantic import Field
|
|
7
9
|
from pydantic import IPvAnyAddress
|
|
8
10
|
from pydantic import StringConstraints
|
|
9
11
|
from pydantic import model_validator
|
|
10
|
-
from typing_extensions import Annotated
|
|
11
12
|
from typing_extensions import Self
|
|
12
13
|
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
14
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
15
|
+
from shepherd_core.data_models.base.content import NameStr
|
|
16
|
+
from shepherd_core.data_models.base.content import SafeStr
|
|
17
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
18
|
+
from shepherd_core.testbed_client import tb_client
|
|
19
|
+
|
|
18
20
|
from .cape import Cape
|
|
19
21
|
from .cape import TargetPort
|
|
20
22
|
from .target import Target
|
|
@@ -56,7 +58,7 @@ class Observer(ShpModel, title="Shepherd-Sheep"):
|
|
|
56
58
|
|
|
57
59
|
@model_validator(mode="before")
|
|
58
60
|
@classmethod
|
|
59
|
-
def query_database(cls, values: dict) -> dict:
|
|
61
|
+
def query_database(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
60
62
|
values, _ = tb_client.try_completing_model(cls.__name__, values)
|
|
61
63
|
return values
|
|
62
64
|
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
"""meta-data representation of a testbed-component (physical object)."""
|
|
2
2
|
|
|
3
3
|
from datetime import datetime
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
from typing import Any
|
|
4
6
|
from typing import Optional
|
|
5
7
|
from typing import Union
|
|
6
8
|
|
|
7
9
|
from pydantic import Field
|
|
8
10
|
from pydantic import model_validator
|
|
9
|
-
from typing_extensions import Annotated
|
|
10
11
|
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
12
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
13
|
+
from shepherd_core.data_models.base.content import NameStr
|
|
14
|
+
from shepherd_core.data_models.base.content import SafeStr
|
|
15
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
16
|
+
from shepherd_core.testbed_client import tb_client
|
|
17
|
+
|
|
16
18
|
from .mcu import MCU
|
|
17
19
|
|
|
18
20
|
IdInt16 = Annotated[int, Field(ge=0, lt=2**16)]
|
|
@@ -45,7 +47,7 @@ class Target(ShpModel, title="Target Node (DuT)"):
|
|
|
45
47
|
|
|
46
48
|
@model_validator(mode="before")
|
|
47
49
|
@classmethod
|
|
48
|
-
def query_database(cls, values: dict) -> dict:
|
|
50
|
+
def query_database(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
49
51
|
values, _ = tb_client.try_completing_model(cls.__name__, values)
|
|
50
52
|
|
|
51
53
|
# post correction
|
|
@@ -2,21 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
from datetime import timedelta
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Annotated
|
|
6
|
+
from typing import Any
|
|
6
7
|
from typing import Optional
|
|
7
8
|
|
|
8
9
|
from pydantic import Field
|
|
9
10
|
from pydantic import HttpUrl
|
|
10
11
|
from pydantic import model_validator
|
|
11
|
-
from typing_extensions import Annotated
|
|
12
12
|
from typing_extensions import Self
|
|
13
13
|
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from
|
|
14
|
+
from shepherd_core.data_models.base.content import IdInt
|
|
15
|
+
from shepherd_core.data_models.base.content import NameStr
|
|
16
|
+
from shepherd_core.data_models.base.content import SafeStr
|
|
17
|
+
from shepherd_core.data_models.base.shepherd import ShpModel
|
|
18
|
+
from shepherd_core.logger import logger
|
|
19
|
+
from shepherd_core.testbed_client import tb_client
|
|
20
|
+
|
|
20
21
|
from .observer import Observer
|
|
21
22
|
|
|
22
23
|
|
|
@@ -30,7 +31,7 @@ class Testbed(ShpModel):
|
|
|
30
31
|
|
|
31
32
|
url: Optional[HttpUrl] = None
|
|
32
33
|
|
|
33
|
-
observers: Annotated[
|
|
34
|
+
observers: Annotated[list[Observer], Field(min_length=1, max_length=128)]
|
|
34
35
|
|
|
35
36
|
shared_storage: bool = True
|
|
36
37
|
data_on_server: Path
|
|
@@ -42,7 +43,7 @@ class Testbed(ShpModel):
|
|
|
42
43
|
|
|
43
44
|
@model_validator(mode="before")
|
|
44
45
|
@classmethod
|
|
45
|
-
def query_database(cls, values: dict) -> dict:
|
|
46
|
+
def query_database(cls, values: dict[str, Any]) -> dict[str, Any]:
|
|
46
47
|
# allow instantiating an empty Testbed
|
|
47
48
|
# -> query the first (and only) entry of client
|
|
48
49
|
if len(values) == 0:
|
|
@@ -28,7 +28,7 @@ from typing import Union
|
|
|
28
28
|
|
|
29
29
|
import numpy as np
|
|
30
30
|
|
|
31
|
-
from
|
|
31
|
+
from shepherd_core.logger import logger
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
class Parity(str, Enum):
|
|
@@ -208,10 +208,10 @@ class Uart:
|
|
|
208
208
|
if self.events_symbols is not None:
|
|
209
209
|
return self.events_symbols
|
|
210
210
|
|
|
211
|
-
pos_df = None
|
|
212
|
-
symbol = 0
|
|
213
|
-
t_start = None
|
|
214
|
-
content = []
|
|
211
|
+
pos_df: Optional[int] = None
|
|
212
|
+
symbol: int = 0
|
|
213
|
+
t_start: Optional[float] = None
|
|
214
|
+
content: list = []
|
|
215
215
|
|
|
216
216
|
for time, value, steps in self.events_sig:
|
|
217
217
|
if steps > self.frame_length:
|
|
@@ -9,7 +9,8 @@ from typing import Union
|
|
|
9
9
|
import zstandard as zstd
|
|
10
10
|
from pydantic import validate_call
|
|
11
11
|
|
|
12
|
-
from
|
|
12
|
+
from shepherd_core.data_models.content.firmware_datatype import FirmwareDType
|
|
13
|
+
|
|
13
14
|
from .converter_elf import elf_to_hex
|
|
14
15
|
from .validation import is_elf
|
|
15
16
|
from .validation import is_hex
|
|
@@ -85,10 +86,10 @@ def extract_firmware(data: Union[str, Path], data_type: FirmwareDType, file_path
|
|
|
85
86
|
- base64-string will be transformed to file
|
|
86
87
|
- if data is a path the file will be copied to the destination.
|
|
87
88
|
"""
|
|
88
|
-
if data_type == FirmwareDType.base64_elf:
|
|
89
|
+
if data_type == FirmwareDType.base64_elf and isinstance(data, str):
|
|
89
90
|
file = file_path.with_suffix(".elf")
|
|
90
91
|
base64_to_file(data, file)
|
|
91
|
-
elif data_type == FirmwareDType.base64_hex:
|
|
92
|
+
elif data_type == FirmwareDType.base64_hex and isinstance(data, str):
|
|
92
93
|
file = file_path.with_suffix(".hex")
|
|
93
94
|
base64_to_file(data, file)
|
|
94
95
|
elif isinstance(data, (Path, str)):
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
"""Read and modify symbols in ELF-files."""
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import Annotated
|
|
4
5
|
from typing import Optional
|
|
5
6
|
|
|
6
7
|
from pydantic import Field
|
|
7
8
|
from pydantic import validate_call
|
|
8
|
-
from typing_extensions import Annotated
|
|
9
9
|
|
|
10
|
-
from
|
|
11
|
-
from
|
|
12
|
-
from
|
|
10
|
+
from shepherd_core.commons import UID_NAME
|
|
11
|
+
from shepherd_core.commons import UID_SIZE
|
|
12
|
+
from shepherd_core.logger import logger
|
|
13
|
+
|
|
13
14
|
from .validation import is_elf
|
|
14
15
|
|
|
15
16
|
try:
|
|
@@ -49,7 +50,7 @@ def find_symbol(file_elf: Path, symbol: str) -> bool:
|
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
@validate_call
|
|
52
|
-
def read_symbol(file_elf: Path, symbol: str, length: int =
|
|
53
|
+
def read_symbol(file_elf: Path, symbol: str, length: int = UID_SIZE) -> Optional[int]:
|
|
53
54
|
"""Read value of symbol in ELF-File.
|
|
54
55
|
|
|
55
56
|
Will be interpreted as int.
|
|
@@ -67,7 +68,7 @@ def read_symbol(file_elf: Path, symbol: str, length: int = uid_len_default) -> O
|
|
|
67
68
|
|
|
68
69
|
def read_uid(file_elf: Path) -> Optional[int]:
|
|
69
70
|
"""Read value of UID-symbol for shepherd testbed."""
|
|
70
|
-
return read_symbol(file_elf, symbol=
|
|
71
|
+
return read_symbol(file_elf, symbol=UID_NAME, length=UID_SIZE)
|
|
71
72
|
|
|
72
73
|
|
|
73
74
|
def read_arch(file_elf: Path) -> Optional[str]:
|
|
@@ -87,7 +88,7 @@ def read_arch(file_elf: Path) -> Optional[str]:
|
|
|
87
88
|
def modify_symbol_value(
|
|
88
89
|
file_elf: Path,
|
|
89
90
|
symbol: str,
|
|
90
|
-
value: Annotated[int, Field(ge=0, lt=2 ** (8 *
|
|
91
|
+
value: Annotated[int, Field(ge=0, lt=2 ** (8 * UID_SIZE))],
|
|
91
92
|
*,
|
|
92
93
|
overwrite: bool = False,
|
|
93
94
|
) -> Optional[Path]:
|
|
@@ -105,20 +106,18 @@ def modify_symbol_value(
|
|
|
105
106
|
raise RuntimeError(elf_error_text)
|
|
106
107
|
elf = ELF(path=file_elf)
|
|
107
108
|
addr = elf.symbols[symbol]
|
|
108
|
-
value_raw = elf.read(address=addr, count=
|
|
109
|
+
value_raw = elf.read(address=addr, count=UID_SIZE)[-UID_SIZE:]
|
|
109
110
|
# ⤷ cutting needed -> msp produces 4b instead of 2
|
|
110
111
|
value_old = int.from_bytes(bytes=value_raw, byteorder=elf.endian, signed=False)
|
|
111
|
-
value_raw = value.to_bytes(length=
|
|
112
|
+
value_raw = value.to_bytes(length=UID_SIZE, byteorder=elf.endian, signed=False)
|
|
113
|
+
|
|
112
114
|
try:
|
|
113
115
|
elf.write(address=addr, data=value_raw)
|
|
114
116
|
except AttributeError:
|
|
115
117
|
logger.warning("ELF-Modifier failed @%s for symbol '%s'", f"0x{addr:X}", symbol)
|
|
116
118
|
return None
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
else:
|
|
120
|
-
file_new = file_elf.with_name(file_elf.stem + "_" + str(value) + file_elf.suffix)
|
|
121
|
-
# could be simplified, but py3.8-- doesn't know .with_stem()
|
|
119
|
+
|
|
120
|
+
file_new = file_elf if overwrite else file_elf.with_stem(file_elf.stem + "_" + str(value))
|
|
122
121
|
elf.save(path=file_new)
|
|
123
122
|
elf.close()
|
|
124
123
|
logger.debug(
|
|
@@ -133,4 +132,4 @@ def modify_symbol_value(
|
|
|
133
132
|
|
|
134
133
|
def modify_uid(file_elf: Path, value: int) -> Optional[Path]:
|
|
135
134
|
"""Replace value of UID-symbol for shepherd testbed."""
|
|
136
|
-
return modify_symbol_value(file_elf, symbol=
|
|
135
|
+
return modify_symbol_value(file_elf, symbol=UID_NAME, value=value, overwrite=True)
|
|
@@ -12,8 +12,9 @@ from intelhex import IntelHex
|
|
|
12
12
|
from intelhex import IntelHexError
|
|
13
13
|
from pydantic import validate_call
|
|
14
14
|
|
|
15
|
-
from
|
|
16
|
-
from
|
|
15
|
+
from shepherd_core.data_models.content.firmware_datatype import FirmwareDType
|
|
16
|
+
from shepherd_core.logger import logger
|
|
17
|
+
|
|
17
18
|
from .converter_elf import elf_to_hex
|
|
18
19
|
|
|
19
20
|
try:
|
|
@@ -9,13 +9,13 @@ This will collect:
|
|
|
9
9
|
from datetime import datetime
|
|
10
10
|
from datetime import timedelta
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import
|
|
12
|
+
from typing import Annotated
|
|
13
13
|
|
|
14
14
|
from pydantic import Field
|
|
15
|
-
from typing_extensions import Annotated
|
|
16
15
|
from typing_extensions import Self
|
|
17
16
|
|
|
18
|
-
from
|
|
17
|
+
from shepherd_core.data_models import ShpModel
|
|
18
|
+
|
|
19
19
|
from .python import PythonInventory
|
|
20
20
|
from .system import SystemInventory
|
|
21
21
|
from .target import TargetInventory
|
|
@@ -55,7 +55,7 @@ class Inventory(PythonInventory, SystemInventory, TargetInventory):
|
|
|
55
55
|
class InventoryList(ShpModel):
|
|
56
56
|
"""Collection of inventories for several devices."""
|
|
57
57
|
|
|
58
|
-
elements: Annotated[
|
|
58
|
+
elements: Annotated[list[Inventory], Field(min_length=1)]
|
|
59
59
|
|
|
60
60
|
def to_csv(self, path: Path) -> None:
|
|
61
61
|
"""Generate a CSV.
|
|
@@ -82,8 +82,8 @@ class InventoryList(ShpModel):
|
|
|
82
82
|
if (_e.created.timestamp() - ts_earl) > 10:
|
|
83
83
|
warnings["time_delta"] = f"[{self.hostname}] time-sync has failed"
|
|
84
84
|
|
|
85
|
-
# turn
|
|
86
|
-
# to
|
|
85
|
+
# turn dict[hostname][type] = val
|
|
86
|
+
# to dict[type][val] = list[hostnames]
|
|
87
87
|
_inp = {
|
|
88
88
|
_e.hostname: _e.model_dump(exclude_unset=True, exclude_defaults=True)
|
|
89
89
|
for _e in self.elements
|