shepherd-core 2024.7.2__tar.gz → 2024.7.4__tar.gz

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.
Files changed (140) hide show
  1. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/PKG-INFO +9 -7
  2. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/README.md +8 -6
  3. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/experiment_generic_var1.py +6 -8
  4. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/experiment_generic_var2.py +6 -8
  5. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/experiment_models.py +6 -8
  6. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/firmware_model.py +2 -4
  7. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/vharvester_simulation.py +0 -12
  8. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/vsource_simulation.py +6 -8
  9. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/pyproject.toml +1 -1
  10. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/__init__.py +4 -5
  11. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/calibration_hw_def.py +15 -12
  12. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/base/calibration.py +4 -3
  13. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/base/wrapper.py +4 -0
  14. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/content/energy_environment.py +1 -1
  15. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/content/firmware.py +1 -0
  16. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/experiment/experiment.py +8 -7
  17. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/task/testbed_tasks.py +3 -2
  18. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/testbed.py +9 -0
  19. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/testbed_client/__init__.py +3 -1
  20. shepherd_core-2024.7.4/shepherd_core/testbed_client/client_abc_fix.py +126 -0
  21. shepherd_core-2024.7.4/shepherd_core/testbed_client/client_web.py +157 -0
  22. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/testbed_client/fixtures.py +14 -8
  23. shepherd_core-2024.7.4/shepherd_core/version.py +3 -0
  24. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core.egg-info/PKG-INFO +9 -7
  25. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core.egg-info/SOURCES.txt +3 -1
  26. shepherd_core-2024.7.2/shepherd_core/testbed_client/client.py +0 -161
  27. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/experiment_from_yaml.yaml +0 -0
  28. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/firmware_modification.py +0 -0
  29. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/inventory.py +0 -0
  30. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/uart_decode_waveform.py +0 -0
  31. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/examples/uart_raw2.csv +0 -0
  32. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/setup.cfg +0 -0
  33. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/commons.py +0 -0
  34. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/__init__.py +0 -0
  35. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/base/__init__.py +0 -0
  36. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/base/cal_measurement.py +0 -0
  37. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/base/content.py +0 -0
  38. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/base/shepherd.py +0 -0
  39. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/base/timezone.py +0 -0
  40. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/content/__init__.py +0 -0
  41. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/content/_external_fixtures.yaml +0 -0
  42. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/content/energy_environment_fixture.yaml +0 -0
  43. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/content/firmware_datatype.py +0 -0
  44. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/content/virtual_harvester.py +0 -0
  45. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/content/virtual_harvester_fixture.yaml +0 -0
  46. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/content/virtual_source.py +0 -0
  47. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/content/virtual_source_fixture.yaml +0 -0
  48. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/experiment/__init__.py +0 -0
  49. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/experiment/observer_features.py +0 -0
  50. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/experiment/target_config.py +0 -0
  51. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/readme.md +0 -0
  52. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/task/__init__.py +0 -0
  53. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/task/emulation.py +0 -0
  54. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/task/firmware_mod.py +0 -0
  55. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/task/harvest.py +0 -0
  56. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/task/observer_tasks.py +0 -0
  57. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/task/programming.py +0 -0
  58. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/__init__.py +0 -0
  59. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/cape.py +0 -0
  60. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/cape_fixture.yaml +0 -0
  61. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/gpio.py +0 -0
  62. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/gpio_fixture.yaml +0 -0
  63. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/mcu.py +0 -0
  64. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/mcu_fixture.yaml +0 -0
  65. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/observer.py +0 -0
  66. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/observer_fixture.yaml +0 -0
  67. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/target.py +0 -0
  68. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/target_fixture.yaml +0 -0
  69. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/testbed/testbed_fixture.yaml +0 -0
  70. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/data_models/virtual_source_doc.txt +0 -0
  71. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/decoder_waveform/__init__.py +0 -0
  72. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/decoder_waveform/uart.py +0 -0
  73. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/fw_tools/__init__.py +0 -0
  74. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/fw_tools/converter.py +0 -0
  75. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/fw_tools/converter_elf.py +0 -0
  76. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/fw_tools/patcher.py +0 -0
  77. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/fw_tools/validation.py +0 -0
  78. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/inventory/__init__.py +0 -0
  79. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/inventory/python.py +0 -0
  80. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/inventory/system.py +0 -0
  81. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/inventory/target.py +0 -0
  82. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/logger.py +0 -0
  83. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/reader.py +0 -0
  84. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/testbed_client/cache_path.py +0 -0
  85. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/testbed_client/user_model.py +0 -0
  86. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/vsource/__init__.py +0 -0
  87. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/vsource/virtual_converter_model.py +0 -0
  88. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/vsource/virtual_harvester_model.py +0 -0
  89. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/vsource/virtual_source_model.py +0 -0
  90. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core/writer.py +0 -0
  91. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core.egg-info/dependency_links.txt +0 -0
  92. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core.egg-info/requires.txt +0 -0
  93. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core.egg-info/top_level.txt +0 -0
  94. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/shepherd_core.egg-info/zip-safe +0 -0
  95. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/__init__.py +0 -0
  96. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/conftest.py +0 -0
  97. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/__init__.py +0 -0
  98. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/conftest.py +0 -0
  99. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_cal_data.yaml +0 -0
  100. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_cal_data_faulty.yaml +0 -0
  101. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_cal_meas.yaml +0 -0
  102. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_cal_meas_faulty1.yaml +0 -0
  103. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_cal_meas_faulty2.yaml +0 -0
  104. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_config_emulator.yaml +0 -0
  105. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_config_experiment.yaml +0 -0
  106. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_config_experiment_alternative.yaml +0 -0
  107. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_config_harvester.yaml +0 -0
  108. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_config_testbed.yaml +0 -0
  109. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/example_config_virtsource.yaml +0 -0
  110. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/test_base_models.py +0 -0
  111. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/test_content_fixtures.py +0 -0
  112. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/test_content_models.py +0 -0
  113. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/test_examples.py +0 -0
  114. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/test_experiment_models.py +0 -0
  115. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/test_task_generation.py +0 -0
  116. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/test_task_models.py +0 -0
  117. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/test_testbed_fixtures.py +0 -0
  118. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/data_models/test_testbed_models.py +0 -0
  119. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/decoder_waveform/__init__.py +0 -0
  120. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/decoder_waveform/test_decoder.py +0 -0
  121. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/fw_tools/__init__.py +0 -0
  122. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/fw_tools/build_msp.elf +0 -0
  123. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/fw_tools/build_nrf.elf +0 -0
  124. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/fw_tools/conftest.py +0 -0
  125. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/fw_tools/test_converter.py +0 -0
  126. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/fw_tools/test_patcher.py +0 -0
  127. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/fw_tools/test_validation.py +0 -0
  128. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/inventory/__init__.py +0 -0
  129. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/inventory/test_inventory.py +0 -0
  130. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/test_cal_hw.py +0 -0
  131. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/test_examples.py +0 -0
  132. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/test_logger.py +0 -0
  133. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/test_reader.py +0 -0
  134. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/test_writer.py +0 -0
  135. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/testbed_client/__init__.py +0 -0
  136. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/vsource/__init__.py +0 -0
  137. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/vsource/conftest.py +0 -0
  138. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/vsource/test_converter.py +0 -0
  139. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/vsource/test_harvester.py +0 -0
  140. {shepherd_core-2024.7.2 → shepherd_core-2024.7.4}/tests/vsource/test_z.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: shepherd_core
3
- Version: 2024.7.2
3
+ Version: 2024.7.4
4
4
  Summary: Programming- and CLI-Interface for the h5-dataformat of the Shepherd-Testbed
5
5
  Author-email: Ingmar Splitt <ingmar.splitt@tu-dresden.de>
6
6
  Maintainer-email: Ingmar Splitt <ingmar.splitt@tu-dresden.de>
@@ -136,28 +136,30 @@ Notes:
136
136
  The Library is available via PyPI and can be installed with
137
137
 
138
138
  ```shell
139
- pip install shepherd-core -U
139
+ pip install shepherd-core -U
140
140
 
141
- # or for the full experience (includes core)
142
- pip install shepherd-data -U
141
+ # or for the full experience (includes core)
142
+ pip install shepherd-data -U
143
143
  ```
144
144
 
145
145
  For bleeding-edge-features or dev-work it is possible to install directly from GitHub-Sources (here `dev`-branch):
146
146
 
147
147
  ```Shell
148
148
  pip install git+https://github.com/orgua/shepherd-datalib.git@dev#subdirectory=shepherd_core -U
149
+ # and on sheep with newer debian
150
+ pip install git+https://github.com/orgua/shepherd-datalib.git@dev#subdirectory=shepherd_core -U --break-system-packages
149
151
  ```
150
152
 
151
153
  If you are working with ``.elf``-files (embedding into experiments) you make "objcopy" accessible to python. In Ubuntu, you can either install ``build-essential`` or ``binutils-$ARCH`` with arch being ``msp430`` or ``arm-none-eabi`` for the nRF52.
152
154
 
153
155
  ```shell
154
- sudo apt install build-essential
156
+ sudo apt install build-essential
155
157
  ```
156
158
 
157
159
  For more advanced work with ``.elf``-files (modify value of symbols / target-ID) you should install
158
160
 
159
161
  ```shell
160
- pip install shepherd-core[elf]
162
+ pip install shepherd-core[elf]
161
163
  ```
162
164
 
163
165
  and also make sure the prereqs for the [pwntools](https://docs.pwntools.com/en/stable/install.html) are met.
@@ -165,7 +167,7 @@ and also make sure the prereqs for the [pwntools](https://docs.pwntools.com/en/s
165
167
  For creating an inventory of the host-system you should install
166
168
 
167
169
  ```shell
168
- pip install shepherd-core[inventory]
170
+ pip install shepherd-core[inventory]
169
171
  ```
170
172
 
171
173
  ## Unittests
@@ -80,28 +80,30 @@ Notes:
80
80
  The Library is available via PyPI and can be installed with
81
81
 
82
82
  ```shell
83
- pip install shepherd-core -U
83
+ pip install shepherd-core -U
84
84
 
85
- # or for the full experience (includes core)
86
- pip install shepherd-data -U
85
+ # or for the full experience (includes core)
86
+ pip install shepherd-data -U
87
87
  ```
88
88
 
89
89
  For bleeding-edge-features or dev-work it is possible to install directly from GitHub-Sources (here `dev`-branch):
90
90
 
91
91
  ```Shell
92
92
  pip install git+https://github.com/orgua/shepherd-datalib.git@dev#subdirectory=shepherd_core -U
93
+ # and on sheep with newer debian
94
+ pip install git+https://github.com/orgua/shepherd-datalib.git@dev#subdirectory=shepherd_core -U --break-system-packages
93
95
  ```
94
96
 
95
97
  If you are working with ``.elf``-files (embedding into experiments) you make "objcopy" accessible to python. In Ubuntu, you can either install ``build-essential`` or ``binutils-$ARCH`` with arch being ``msp430`` or ``arm-none-eabi`` for the nRF52.
96
98
 
97
99
  ```shell
98
- sudo apt install build-essential
100
+ sudo apt install build-essential
99
101
  ```
100
102
 
101
103
  For more advanced work with ``.elf``-files (modify value of symbols / target-ID) you should install
102
104
 
103
105
  ```shell
104
- pip install shepherd-core[elf]
106
+ pip install shepherd-core[elf]
105
107
  ```
106
108
 
107
109
  and also make sure the prereqs for the [pwntools](https://docs.pwntools.com/en/stable/install.html) are met.
@@ -109,7 +111,7 @@ and also make sure the prereqs for the [pwntools](https://docs.pwntools.com/en/s
109
111
  For creating an inventory of the host-system you should install
110
112
 
111
113
  ```shell
112
- pip install shepherd-core[inventory]
114
+ pip install shepherd-core[inventory]
113
115
  ```
114
116
 
115
117
  ## Unittests
@@ -15,7 +15,7 @@ What the code does:
15
15
 
16
16
  from pathlib import Path
17
17
 
18
- from shepherd_core import TestbedClient
18
+ from shepherd_core import WebClient
19
19
  from shepherd_core.data_models import FirmwareDType
20
20
  from shepherd_core.data_models import GpioTracing
21
21
  from shepherd_core.data_models.content import EnergyEnvironment
@@ -25,16 +25,14 @@ from shepherd_core.data_models.experiment import TargetConfig
25
25
  from shepherd_core.data_models.task import TestbedTasks
26
26
  from shepherd_core.data_models.testbed import MCU
27
27
 
28
- # for online-queries the lib can be connected to the testbed-server
28
+ # For online-queries the lib can be connected to the testbed-server.
29
29
  # NOTE: there are 3 states:
30
- # - unconnected -> demo-fixture is queried (locally)
31
- # - connected -> publicly available data is queried online
32
- # - logged in with token -> also private data is queried online
33
- tb_client = TestbedClient()
30
+ # - unconnected -> demo-fixtures are queried (locally)
31
+ # - connected -> publicly available data is queried online
32
+ # - logged in with valid token -> also private data is queried online
34
33
  do_connect = False
35
-
36
34
  if do_connect:
37
- tb_client.connect()
35
+ WebClient()
38
36
 
39
37
  xp = Experiment(
40
38
  id="4567",
@@ -14,7 +14,7 @@
14
14
 
15
15
  from pathlib import Path
16
16
 
17
- from shepherd_core import TestbedClient
17
+ from shepherd_core import WebClient
18
18
  from shepherd_core.data_models import GpioTracing
19
19
  from shepherd_core.data_models.content import EnergyEnvironment
20
20
  from shepherd_core.data_models.content import Firmware
@@ -22,16 +22,14 @@ from shepherd_core.data_models.experiment import Experiment
22
22
  from shepherd_core.data_models.experiment import TargetConfig
23
23
  from shepherd_core.data_models.task import TestbedTasks
24
24
 
25
- # for online-queries the lib can be connected to the testbed-server
25
+ # For online-queries the lib can be connected to the testbed-server.
26
26
  # NOTE: there are 3 states:
27
- # - unconnected -> demo-fixture is queried (locally)
28
- # - connected -> publicly available data is queried online
29
- # - logged in with token -> also private data is queried online
30
- tb_client = TestbedClient()
27
+ # - unconnected -> demo-fixtures are queried (locally)
28
+ # - connected -> publicly available data is queried online
29
+ # - logged in with valid token -> also private data is queried online
31
30
  do_connect = False
32
-
33
31
  if do_connect:
34
- tb_client.connect()
32
+ WebClient()
35
33
 
36
34
  xp = Experiment(
37
35
  id="4567",
@@ -18,7 +18,7 @@ How to define an experiment:
18
18
 
19
19
  """
20
20
 
21
- from shepherd_core import TestbedClient
21
+ from shepherd_core import WebClient
22
22
  from shepherd_core.data_models.content import EnergyEnvironment
23
23
  from shepherd_core.data_models.content import Firmware
24
24
  from shepherd_core.data_models.content import VirtualHarvesterConfig
@@ -30,16 +30,14 @@ from shepherd_core.data_models.task import TestbedTasks
30
30
  # generate description for all parameters -> base for web-forms
31
31
  Experiment.schema_to_file("experiment_schema.yaml")
32
32
 
33
- # for online-queries the lib can be connected to the testbed-server
33
+ # For online-queries the lib can be connected to the testbed-server.
34
34
  # NOTE: there are 3 states:
35
- # - unconnected -> demo-fixture is queried (locally)
36
- # - connected -> publicly available data is queried online
37
- # - logged in with token -> also private data is queried online
38
- tb_client = TestbedClient()
35
+ # - unconnected -> demo-fixtures are queried (locally)
36
+ # - connected -> publicly available data is queried online
37
+ # - logged in with valid token -> also private data is queried online
39
38
  do_connect = False
40
-
41
39
  if do_connect:
42
- tb_client.connect()
40
+ WebClient()
43
41
 
44
42
  # Defining an Experiment in Python
45
43
  hrv = VirtualHarvesterConfig(name="mppt_bq_thermoelectric")
@@ -6,7 +6,7 @@ or shepherd-core[elf].
6
6
 
7
7
  from pathlib import Path
8
8
 
9
- from shepherd_core import TestbedClient
9
+ from shepherd_core import WebClient
10
10
  from shepherd_core import fw_tools
11
11
  from shepherd_core.data_models import Firmware
12
12
  from shepherd_core.data_models import FirmwareDType
@@ -41,9 +41,7 @@ print(f"stored firmware to '{path_elf2.name}'")
41
41
 
42
42
  # Option 3 - fully automatic (with login) -> owner and group get prefilled
43
43
 
44
- tb_client = TestbedClient()
45
44
  do_connect = False
46
-
47
45
  if do_connect:
48
- tb_client.connect(token="your_personal_login_token") # noqa: S106
46
+ WebClient(token="your_personal_login_token") # noqa: S106
49
47
  fw3 = Firmware.from_firmware(file=path_elf, name="msp_deep_sleep3")
@@ -9,7 +9,6 @@
9
9
  from pathlib import Path
10
10
 
11
11
  from shepherd_core import Reader
12
- from shepherd_core import TestbedClient
13
12
  from shepherd_core.data_models import VirtualHarvesterConfig
14
13
  from shepherd_core.data_models.content.virtual_harvester import HarvesterPRUConfig
15
14
  from shepherd_core.vsource import VirtualHarvesterModel
@@ -33,17 +32,6 @@ hrv_list = [
33
32
  "mppt_opt",
34
33
  ]
35
34
 
36
- # for online-queries the lib can be connected to the testbed-server
37
- # NOTE: there are 3 states:
38
- # - unconnected -> demo-fixture is queried (locally)
39
- # - connected -> publicly available data is queried online
40
- # - logged in with token -> also private data is queried online
41
- tb_client = TestbedClient()
42
- do_connect = False
43
-
44
- if do_connect:
45
- tb_client.connect()
46
-
47
35
  # convert IVonne to IVCurve
48
36
  if not file_ivcurve.exists():
49
37
  with ivonne.Reader(file_ivonne) as db:
@@ -16,7 +16,7 @@ import matplotlib.pyplot as plt
16
16
  import numpy as np
17
17
 
18
18
  from shepherd_core import CalibrationEmulator
19
- from shepherd_core import TestbedClient
19
+ from shepherd_core import WebClient
20
20
  from shepherd_core.data_models import VirtualSourceConfig
21
21
  from shepherd_core.vsource import VirtualSourceModel
22
22
 
@@ -38,16 +38,14 @@ src_list = [
38
38
  I_mcu_sleep_A = 200e-9
39
39
  I_mcu_active_A = 1e-3
40
40
 
41
- # for online-queries the lib can be connected to the testbed-server
41
+ # For online-queries the lib can be connected to the testbed-server.
42
42
  # NOTE: there are 3 states:
43
- # - unconnected -> demo-fixture is queried (locally)
44
- # - connected -> publicly available data is queried online
45
- # - logged in with token -> also private data is queried online
46
- tb_client = TestbedClient()
43
+ # - unconnected -> demo-fixtures are queried (locally)
44
+ # - connected -> publicly available data is queried online
45
+ # - logged in with valid token -> also private data is queried online
47
46
  do_connect = False
48
-
49
47
  if do_connect:
50
- tb_client.connect()
48
+ WebClient()
51
49
 
52
50
  for vs_name, v_hrv_mV, samples in product(src_list, v_hrv_mV_list, sample_dur_list):
53
51
  # prepare simulation
@@ -94,7 +94,7 @@ shepherd_core = [
94
94
  ]
95
95
 
96
96
  [tool.setuptools.dynamic]
97
- version = {attr = "shepherd_core.__version__"}
97
+ version = {attr = "shepherd_core.version.version"}
98
98
 
99
99
  [tool.pytest.ini_options]
100
100
  markers = [
@@ -19,11 +19,11 @@ from .logger import get_verbose_level
19
19
  from .logger import increase_verbose_level
20
20
  from .logger import logger
21
21
  from .reader import Reader
22
- from .testbed_client.client import TestbedClient
23
- from .testbed_client.client import tb_client
22
+ from .testbed_client.client_web import WebClient
23
+ from .version import version
24
24
  from .writer import Writer
25
25
 
26
- __version__ = "2024.7.2"
26
+ __version__ = version
27
27
 
28
28
  __all__ = [
29
29
  "Reader",
@@ -40,7 +40,6 @@ __all__ = [
40
40
  "local_now",
41
41
  "Calc_t",
42
42
  "Compression",
43
- "TestbedClient",
44
- "tb_client", # using this (instead of the Class) is the cleaner, but less pythonic way
43
+ "WebClient",
45
44
  "Inventory",
46
45
  ]
@@ -32,45 +32,48 @@ RAW_MAX_ADC = 2**M_ADC - 1
32
32
  RAW_MAX_DAC = 2**M_DAC - 1
33
33
 
34
34
 
35
- def adc_current_to_raw(current: float) -> int:
35
+ def adc_current_to_raw(current: float, *, limited: bool = True) -> int:
36
36
  """Convert back a current [A] to raw ADC value."""
37
37
  # voltage on input of adc
38
38
  val_adc = G_INST_AMP * R_SHT * current
39
39
  # digital value according to ADC gain
40
40
  val_raw = int(val_adc * (2**M_ADC) / (G_ADC_I * V_REF_ADC))
41
- return min(max(val_raw, 0), 2**M_ADC - 1)
41
+ return min(max(val_raw, 0), 2**M_ADC - 1) if limited else val_raw
42
42
 
43
43
 
44
- def adc_raw_to_current(value: int) -> float:
44
+ def adc_raw_to_current(value: int, *, limited: bool = True) -> float:
45
45
  """Convert a raw ADC value to a current [A]."""
46
- value = min(max(value, 0), 2**M_ADC - 1)
46
+ if limited:
47
+ value = min(max(value, 0), 2**M_ADC - 1)
47
48
  # voltage on input of adc
48
49
  val_adc = float(value) * (G_ADC_I * V_REF_ADC) / (2**M_ADC)
49
50
  # current according to adc value
50
51
  return val_adc / (R_SHT * G_INST_AMP)
51
52
 
52
53
 
53
- def adc_voltage_to_raw(voltage: float) -> int:
54
+ def adc_voltage_to_raw(voltage: float, *, limited: bool = True) -> int:
54
55
  """Convert back a voltage [V] to raw ADC value."""
55
56
  # digital value according to ADC gain
56
57
  val_raw = int(voltage * (2**M_ADC) / (G_ADC_V * V_REF_ADC))
57
- return min(max(val_raw, 0), 2**M_ADC - 1)
58
+ return min(max(val_raw, 0), 2**M_ADC - 1) if limited else val_raw
58
59
 
59
60
 
60
- def adc_raw_to_voltage(value: int) -> float:
61
+ def adc_raw_to_voltage(value: int, *, limited: bool = True) -> float:
61
62
  """Convert a raw ADC value to a voltage [V]."""
62
- value = min(max(value, 0), 2**M_ADC - 1)
63
+ if limited:
64
+ value = min(max(value, 0), 2**M_ADC - 1)
63
65
  # voltage according to ADC value
64
66
  return float(value) * (G_ADC_V * V_REF_ADC) / (2**M_ADC)
65
67
 
66
68
 
67
- def dac_raw_to_voltage(value: int) -> float:
69
+ def dac_raw_to_voltage(value: int, *, limited: bool = True) -> float:
68
70
  """Convert back a raw DAC value to a voltage [V]."""
69
- value = min(max(value, 0), 2**M_DAC - 1)
71
+ if limited:
72
+ value = min(max(value, 0), 2**M_DAC - 1)
70
73
  return float(value) * (V_REF_DAC * G_DAC) / (2**M_DAC)
71
74
 
72
75
 
73
- def dac_voltage_to_raw(voltage: float) -> int:
76
+ def dac_voltage_to_raw(voltage: float, *, limited: bool = True) -> int:
74
77
  """Convert a voltage [V] to raw DAC value."""
75
78
  val_raw = int(voltage * (2**M_DAC) / (V_REF_DAC * G_DAC))
76
- return min(max(val_raw, 0), 2**M_DAC - 1)
79
+ return min(max(val_raw, 0), 2**M_DAC - 1) if limited else val_raw
@@ -51,6 +51,7 @@ class CalibrationPair(ShpModel):
51
51
 
52
52
  gain: PositiveFloat
53
53
  offset: float = 0
54
+ # TODO: add unit
54
55
 
55
56
  def raw_to_si(self, values_raw: Calc_t, *, allow_negative: bool = True) -> Calc_t:
56
57
  """Convert between physical units and raw unsigned integers."""
@@ -79,8 +80,8 @@ class CalibrationPair(ShpModel):
79
80
  @classmethod
80
81
  def from_fn(cls, fn: Callable) -> Self:
81
82
  """Probe linear function to determine scaling values."""
82
- offset = fn(0)
83
- gain_inv = fn(1.0) - offset
83
+ offset = fn(0, limited=False)
84
+ gain_inv = fn(1.0, limited=False) - offset
84
85
  return cls(
85
86
  gain=1.0 / float(gain_inv),
86
87
  offset=-float(offset) / gain_inv,
@@ -274,7 +275,7 @@ class CalibrationSeries(ShpModel):
274
275
  emu_port_a: bool = True,
275
276
  ) -> Self:
276
277
  if isinstance(cal, CalibrationHarvester):
277
- return cls(voltage=cal.adc_V_Sense, current=cal.dac_V_Hrv)
278
+ return cls(voltage=cal.adc_V_Sense, current=cal.adc_C_Hrv)
278
279
  if emu_port_a:
279
280
  return cls(voltage=cal.dac_V_A, current=cal.adc_C_A)
280
281
  return cls(voltage=cal.dac_V_B, current=cal.adc_C_B)
@@ -7,6 +7,8 @@ from pydantic import BaseModel
7
7
  from pydantic import StringConstraints
8
8
  from typing_extensions import Annotated
9
9
 
10
+ from ...version import version
11
+
10
12
  SafeStrClone = Annotated[str, StringConstraints(pattern=r"^[ -~]+$")]
11
13
  # ⤷ copy avoids circular import
12
14
 
@@ -19,5 +21,7 @@ class Wrapper(BaseModel):
19
21
  comment: Optional[SafeStrClone] = None
20
22
  created: Optional[datetime] = None
21
23
  # ⤷ Optional metadata
24
+ lib_ver: Optional[str] = version
25
+ # ⤷ for debug-purposes and later comp-checks
22
26
  parameters: dict
23
27
  # ⤷ ShpModel
@@ -35,7 +35,7 @@ class EnergyEnvironment(ContentModel):
35
35
 
36
36
  # TODO: scale up/down voltage/current
37
37
 
38
- # additional descriptive metadata
38
+ # additional descriptive metadata, TODO: these are very solar-centered -> generalize
39
39
  light_source: Optional[str] = None
40
40
  weather_conditions: Optional[str] = None
41
41
  indoor: Optional[bool] = None
@@ -152,6 +152,7 @@ class Firmware(ContentModel, title="Firmware of Target"):
152
152
 
153
153
  if not match:
154
154
  logger.warning("FW-Hash does not match with stored value!")
155
+ # TODO: it might be more appropriate to raise here
155
156
  return match
156
157
 
157
158
  @validate_call
@@ -13,6 +13,7 @@ from pydantic import model_validator
13
13
  from typing_extensions import Annotated
14
14
  from typing_extensions import Self
15
15
 
16
+ from ...version import version
16
17
  from ..base.content import IdInt
17
18
  from ..base.content import NameStr
18
19
  from ..base.content import SafeStr
@@ -54,18 +55,20 @@ class Experiment(ShpModel, title="Config of an Experiment"):
54
55
  # targets
55
56
  target_configs: Annotated[List[TargetConfig], Field(min_length=1, max_length=128)]
56
57
 
57
- # TODO: we probably need to remember the lib-version for content &| experiment
58
+ # for debug-purposes and later comp-checks
59
+ lib_ver: Optional[str] = version
58
60
 
59
61
  @model_validator(mode="after")
60
62
  def post_validation(self) -> Self:
61
- self.validate_targets(self.target_configs)
62
- self.validate_observers(self.target_configs)
63
+ testbed = Testbed() # this will query the first (and only) entry of client
64
+ self._validate_targets(self.target_configs)
65
+ self._validate_observers(self.target_configs, testbed)
63
66
  if self.duration and self.duration.total_seconds() < 0:
64
67
  raise ValueError("Duration of experiment can't be negative.")
65
68
  return self
66
69
 
67
70
  @staticmethod
68
- def validate_targets(configs: List[TargetConfig]) -> None:
71
+ def _validate_targets(configs: List[TargetConfig]) -> None:
69
72
  target_ids = []
70
73
  custom_ids = []
71
74
  for _config in configs:
@@ -83,10 +86,8 @@ class Experiment(ShpModel, title="Config of an Experiment"):
83
86
  raise ValueError("Custom Target-ID are faulty (some form of id-collisions)!")
84
87
 
85
88
  @staticmethod
86
- def validate_observers(configs: List[TargetConfig]) -> None:
89
+ def _validate_observers(configs: List[TargetConfig], testbed: Testbed) -> None:
87
90
  target_ids = [_id for _config in configs for _id in _config.target_IDs]
88
-
89
- testbed = Testbed(name="shepherd_tud_nes")
90
91
  obs_ids = [testbed.get_observer(_id).id for _id in target_ids]
91
92
  if len(target_ids) > len(set(obs_ids)):
92
93
  raise ValueError(
@@ -32,8 +32,9 @@ class TestbedTasks(ShpModel):
32
32
  @validate_call
33
33
  def from_xp(cls, xp: Experiment, tb: Optional[Testbed] = None) -> Self:
34
34
  if tb is None:
35
- # TODO: just for testing OK
36
- tb = Testbed(name="shepherd_tud_nes")
35
+ # TODO: is tb-argument really needed? prob. not
36
+ tb = Testbed() # this will query the first (and only) entry of client
37
+
37
38
  tgt_ids = xp.get_target_ids()
38
39
  obs_tasks = [ObserverTasks.from_xp(xp, tb, _id) for _id in tgt_ids]
39
40
  return cls(
@@ -11,6 +11,7 @@ from pydantic import model_validator
11
11
  from typing_extensions import Annotated
12
12
  from typing_extensions import Self
13
13
 
14
+ from ... import logger
14
15
  from ...testbed_client import tb_client
15
16
  from ..base.content import IdInt
16
17
  from ..base.content import NameStr
@@ -42,6 +43,14 @@ class Testbed(ShpModel):
42
43
  @model_validator(mode="before")
43
44
  @classmethod
44
45
  def query_database(cls, values: dict) -> dict:
46
+ # allow instantiating an empty Testbed
47
+ # -> query the first (and only) entry of client
48
+ if len(values) == 0:
49
+ ids = tb_client.query_ids(cls.__name__)
50
+ if len(ids) > 1:
51
+ logger.warning("More than one testbed defined?!?")
52
+ values = {"id": ids[0]}
53
+
45
54
  values, _ = tb_client.try_completing_model(cls.__name__, values)
46
55
  return values
47
56
 
@@ -1,9 +1,11 @@
1
1
  """Client to access a testbed-instance for controlling experiments."""
2
2
 
3
- from .client import tb_client
3
+ from .client_abc_fix import tb_client
4
+ from .client_web import WebClient
4
5
  from .user_model import User
5
6
 
6
7
  __all__ = [
7
8
  "tb_client",
9
+ "WebClient",
8
10
  "User",
9
11
  ]
@@ -0,0 +1,126 @@
1
+ """AbstractBase-Class & Client-Class to access the file based fixtures.
2
+
3
+ Fixtures == OffLineDemoInstances
4
+ offline: core - fixtClient
5
+ webDev: core - webClient <-> webSrv - fixtClient
6
+ webUser: core - webClient <-> webSrv - DbClient
7
+ webInfra: core - webClient+ <-> webSrv - DbClient
8
+
9
+ Users, Sheep and ServerApps should have access to the same DB via WebClient
10
+
11
+ Note: ABC and FixClient can't be in separate files when tb_client should
12
+ default to FixClient (circular import)
13
+
14
+ TODO: Comfort functions missing
15
+ - fixtures to DB, and vice versa
16
+ """
17
+
18
+ from abc import ABC
19
+ from abc import abstractmethod
20
+ from typing import List
21
+ from typing import Optional
22
+
23
+ from ..data_models.base.shepherd import ShpModel
24
+ from ..data_models.base.wrapper import Wrapper
25
+ from .fixtures import Fixtures
26
+
27
+
28
+ class AbcClient(ABC):
29
+ """AbstractBase-Class to access a testbed instance."""
30
+
31
+ def __init__(self) -> None:
32
+ global tb_client # noqa: PLW0603
33
+ tb_client = self
34
+
35
+ @abstractmethod
36
+ def insert(self, data: ShpModel) -> bool:
37
+ """Insert (and probably replace) entry.
38
+
39
+ TODO: fixtures get replaced, but is that wanted for web?
40
+ """
41
+
42
+ @abstractmethod
43
+ def query_ids(self, model_type: str) -> List[int]:
44
+ pass
45
+
46
+ @abstractmethod
47
+ def query_names(self, model_type: str) -> List[str]:
48
+ pass
49
+
50
+ @abstractmethod
51
+ def query_item(
52
+ self, model_type: str, uid: Optional[int] = None, name: Optional[str] = None
53
+ ) -> dict:
54
+ pass
55
+
56
+ @abstractmethod
57
+ def try_inheritance(self, model_type: str, values: dict) -> (dict, list):
58
+ # TODO: maybe internal? yes
59
+ pass
60
+
61
+ def try_completing_model(self, model_type: str, values: dict) -> (dict, list):
62
+ """Init by name/id, for none existing instances raise Exception.
63
+
64
+ This is the main entry-point for querying a model (used be the core-lib).
65
+ """
66
+ if len(values) == 1 and next(iter(values.keys())) in {"id", "name"}:
67
+ try:
68
+ values = self.query_item(model_type, name=values.get("name"), uid=values.get("id"))
69
+ except ValueError as err:
70
+ raise ValueError(
71
+ "Query %s by name / ID failed - %s is unknown!", model_type, values
72
+ ) from err
73
+ return self.try_inheritance(model_type, values)
74
+
75
+ @abstractmethod
76
+ def fill_in_user_data(self, values: dict) -> dict:
77
+ # TODO: is it really helpful and needed?
78
+ pass
79
+
80
+
81
+ class FixturesClient(AbcClient):
82
+ """Client-Class to access the file based fixtures."""
83
+
84
+ def __init__(self) -> None:
85
+ super().__init__()
86
+ self._fixtures: Optional[Fixtures] = Fixtures()
87
+
88
+ def insert(self, data: ShpModel) -> bool:
89
+ wrap = Wrapper(
90
+ datatype=type(data).__name__,
91
+ parameters=data.model_dump(),
92
+ )
93
+ self._fixtures.insert_model(wrap)
94
+ return True
95
+
96
+ def query_ids(self, model_type: str) -> List[int]:
97
+ return list(self._fixtures[model_type].elements_by_id.keys())
98
+
99
+ def query_names(self, model_type: str) -> List[str]:
100
+ return list(self._fixtures[model_type].elements_by_name.keys())
101
+
102
+ def query_item(
103
+ self, model_type: str, uid: Optional[int] = None, name: Optional[str] = None
104
+ ) -> dict:
105
+ if uid is not None:
106
+ return self._fixtures[model_type].query_id(uid)
107
+ if name is not None:
108
+ return self._fixtures[model_type].query_name(name)
109
+ raise ValueError("Query needs either uid or name of object")
110
+
111
+ def try_inheritance(self, model_type: str, values: dict) -> (dict, list):
112
+ return self._fixtures[model_type].inheritance(values)
113
+
114
+ def fill_in_user_data(self, values: dict) -> dict:
115
+ """Add fake user-data when offline-client is used.
116
+
117
+ Hotfix until WebClient is working.
118
+ """
119
+ if values.get("owner") is None:
120
+ values["owner"] = "unknown"
121
+ if values.get("group") is None:
122
+ values["group"] = "unknown"
123
+ return values
124
+
125
+
126
+ tb_client: AbcClient = FixturesClient()