shepherd-core 2024.11.2__tar.gz → 2025.2.1__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 (145) hide show
  1. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/PKG-INFO +2 -2
  2. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/content/virtual_harvester.py +24 -4
  3. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/task/__init__.py +1 -2
  4. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/inventory/system.py +1 -1
  5. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/reader.py +28 -1
  6. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/testbed_client/client_web.py +1 -1
  7. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/version.py +1 -1
  8. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/vsource/virtual_harvester_simulation.py +1 -0
  9. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/vsource/virtual_source_model.py +2 -0
  10. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/vsource/virtual_source_simulation.py +1 -0
  11. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core.egg-info/PKG-INFO +2 -2
  12. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/vsource/test_converter.py +14 -6
  13. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/vsource/test_harvester.py +31 -1
  14. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/README.md +0 -0
  15. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/eenv_generator.py +0 -0
  16. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/experiment_from_yaml.yaml +0 -0
  17. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/experiment_generic_var1.py +0 -0
  18. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/experiment_generic_var2.py +0 -0
  19. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/experiment_models.py +0 -0
  20. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/firmware_model.py +0 -0
  21. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/firmware_modification.py +0 -0
  22. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/inventory.py +0 -0
  23. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/simulate_vharvester.py +0 -0
  24. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/simulate_vsource.py +0 -0
  25. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/uart_decode_waveform.py +0 -0
  26. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/uart_raw2.csv +0 -0
  27. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/examples/vsource_debug_sim.py +0 -0
  28. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/pyproject.toml +0 -0
  29. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/setup.cfg +0 -0
  30. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/__init__.py +0 -0
  31. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/calibration_hw_def.py +0 -0
  32. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/commons.py +0 -0
  33. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/__init__.py +0 -0
  34. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/base/__init__.py +0 -0
  35. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/base/cal_measurement.py +0 -0
  36. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/base/calibration.py +0 -0
  37. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/base/content.py +0 -0
  38. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/base/shepherd.py +0 -0
  39. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/base/timezone.py +0 -0
  40. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/base/wrapper.py +0 -0
  41. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/content/__init__.py +0 -0
  42. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/content/_external_fixtures.yaml +0 -0
  43. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/content/energy_environment.py +0 -0
  44. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/content/energy_environment_fixture.yaml +0 -0
  45. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/content/firmware.py +0 -0
  46. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/content/firmware_datatype.py +0 -0
  47. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/content/virtual_harvester_fixture.yaml +0 -0
  48. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/content/virtual_source.py +0 -0
  49. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/content/virtual_source_fixture.yaml +0 -0
  50. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/experiment/__init__.py +0 -0
  51. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/experiment/experiment.py +0 -0
  52. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/experiment/observer_features.py +0 -0
  53. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/experiment/target_config.py +0 -0
  54. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/readme.md +0 -0
  55. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/task/emulation.py +0 -0
  56. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/task/firmware_mod.py +0 -0
  57. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/task/harvest.py +0 -0
  58. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/task/observer_tasks.py +0 -0
  59. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/task/programming.py +0 -0
  60. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/task/testbed_tasks.py +0 -0
  61. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/__init__.py +0 -0
  62. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/cape.py +0 -0
  63. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/cape_fixture.yaml +0 -0
  64. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/gpio.py +0 -0
  65. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/gpio_fixture.yaml +0 -0
  66. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/mcu.py +0 -0
  67. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/mcu_fixture.yaml +0 -0
  68. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/observer.py +0 -0
  69. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/observer_fixture.yaml +0 -0
  70. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/target.py +0 -0
  71. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/target_fixture.old1 +0 -0
  72. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/target_fixture.yaml +0 -0
  73. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/testbed.py +0 -0
  74. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/testbed/testbed_fixture.yaml +0 -0
  75. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/data_models/virtual_source_doc.txt +0 -0
  76. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/decoder_waveform/__init__.py +0 -0
  77. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/decoder_waveform/uart.py +0 -0
  78. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/fw_tools/__init__.py +0 -0
  79. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/fw_tools/converter.py +0 -0
  80. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/fw_tools/converter_elf.py +0 -0
  81. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/fw_tools/patcher.py +0 -0
  82. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/fw_tools/validation.py +0 -0
  83. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/inventory/__init__.py +0 -0
  84. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/inventory/python.py +0 -0
  85. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/inventory/target.py +0 -0
  86. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/logger.py +0 -0
  87. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/testbed_client/__init__.py +0 -0
  88. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/testbed_client/cache_path.py +0 -0
  89. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/testbed_client/client_abc_fix.py +0 -0
  90. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/testbed_client/fixtures.py +0 -0
  91. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/testbed_client/user_model.py +0 -0
  92. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/vsource/__init__.py +0 -0
  93. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/vsource/target_model.py +0 -0
  94. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/vsource/virtual_converter_model.py +0 -0
  95. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/vsource/virtual_harvester_model.py +0 -0
  96. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core/writer.py +0 -0
  97. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core.egg-info/SOURCES.txt +0 -0
  98. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core.egg-info/dependency_links.txt +0 -0
  99. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core.egg-info/requires.txt +0 -0
  100. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core.egg-info/top_level.txt +0 -0
  101. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/shepherd_core.egg-info/zip-safe +0 -0
  102. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/__init__.py +0 -0
  103. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/conftest.py +0 -0
  104. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/__init__.py +0 -0
  105. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/conftest.py +0 -0
  106. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_cal_data.yaml +0 -0
  107. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_cal_data_faulty.yaml +0 -0
  108. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_cal_meas.yaml +0 -0
  109. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_cal_meas_faulty1.yaml +0 -0
  110. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_cal_meas_faulty2.yaml +0 -0
  111. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_config_emulator.yaml +0 -0
  112. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_config_experiment.yaml +0 -0
  113. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_config_experiment_alternative.yaml +0 -0
  114. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_config_harvester.yaml +0 -0
  115. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_config_testbed.yaml +0 -0
  116. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/example_config_virtsource.yaml +0 -0
  117. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/test_base_models.py +0 -0
  118. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/test_content_fixtures.py +0 -0
  119. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/test_content_models.py +0 -0
  120. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/test_examples.py +0 -0
  121. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/test_experiment_models.py +0 -0
  122. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/test_task_generation.py +0 -0
  123. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/test_task_models.py +0 -0
  124. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/test_testbed_fixtures.py +0 -0
  125. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/data_models/test_testbed_models.py +0 -0
  126. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/decoder_waveform/__init__.py +0 -0
  127. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/decoder_waveform/test_decoder.py +0 -0
  128. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/fw_tools/__init__.py +0 -0
  129. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/fw_tools/build_msp.elf +0 -0
  130. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/fw_tools/build_nrf.elf +0 -0
  131. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/fw_tools/conftest.py +0 -0
  132. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/fw_tools/test_converter.py +0 -0
  133. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/fw_tools/test_patcher.py +0 -0
  134. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/fw_tools/test_validation.py +0 -0
  135. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/inventory/__init__.py +0 -0
  136. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/inventory/test_inventory.py +0 -0
  137. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/test_cal_hw.py +0 -0
  138. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/test_examples.py +0 -0
  139. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/test_logger.py +0 -0
  140. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/test_reader.py +0 -0
  141. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/test_writer.py +0 -0
  142. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/testbed_client/__init__.py +0 -0
  143. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/vsource/__init__.py +0 -0
  144. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/vsource/conftest.py +0 -0
  145. {shepherd_core-2024.11.2 → shepherd_core-2025.2.1}/tests/vsource/test_z.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: shepherd_core
3
- Version: 2024.11.2
3
+ Version: 2025.2.1
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>
@@ -239,6 +239,7 @@ class HarvesterPRUConfig(ShpModel):
239
239
  data: VirtualHarvesterConfig,
240
240
  dtype_in: Optional[EnergyDType] = EnergyDType.ivsample,
241
241
  window_size: Optional[u32] = None,
242
+ voltage_step_V: Optional[float] = None,
242
243
  *,
243
244
  for_emu: bool = False,
244
245
  ) -> Self:
@@ -247,17 +248,36 @@ class HarvesterPRUConfig(ShpModel):
247
248
  if for_emu and dtype_in not in {EnergyDType.ivsample, EnergyDType.ivcurve}:
248
249
  raise NotImplementedError
249
250
 
251
+ if for_emu and dtype_in == EnergyDType.ivcurve and voltage_step_V is None:
252
+ raise ValueError(
253
+ "For correct emulation specify voltage_step used by harvester "
254
+ "e.g. via file_src.get_voltage_step()"
255
+ )
256
+
257
+ if for_emu and dtype_in == EnergyDType.ivcurve and window_size is None:
258
+ raise ValueError(
259
+ "For correct emulation specify window_size used by harvester "
260
+ "e.g. via file_src.get_window_size()"
261
+ )
262
+
250
263
  interval_ms, duration_ms = data.calc_timings_ms(for_emu=for_emu)
264
+ window_size = (
265
+ window_size
266
+ if window_size is not None
267
+ else data.calc_window_size(dtype_in, for_emu=for_emu)
268
+ )
269
+ voltage_step_mV = (
270
+ 1e3 * voltage_step_V if voltage_step_V is not None else data.voltage_step_mV
271
+ )
272
+
251
273
  return cls(
252
274
  algorithm=data.calc_algorithm_num(for_emu=for_emu),
253
275
  hrv_mode=data.calc_hrv_mode(for_emu=for_emu),
254
- window_size=window_size
255
- if window_size is not None
256
- else data.calc_window_size(dtype_in, for_emu=for_emu),
276
+ window_size=window_size,
257
277
  voltage_uV=round(data.voltage_mV * 10**3),
258
278
  voltage_min_uV=round(data.voltage_min_mV * 10**3),
259
279
  voltage_max_uV=round(data.voltage_max_mV * 10**3),
260
- voltage_step_uV=round(data.voltage_step_mV * 10**3),
280
+ voltage_step_uV=round(voltage_step_mV * 10**3),
261
281
  current_limit_nA=round(data.current_limit_uA * 10**3),
262
282
  setpoint_n8=round(min(255, data.setpoint_n * 2**8)),
263
283
  interval_n=round(interval_ms * samplerate_sps_default * 1e-3),
@@ -59,8 +59,7 @@ def prepare_task(config: Union[ShpModel, Path, str], observer: Optional[str] = N
59
59
  if shp_wrap.datatype == TestbedTasks.__name__:
60
60
  if observer is None:
61
61
  logger.debug(
62
- "Task-Set contained TestbedTasks & no observer was provided "
63
- "-> will return TB-Tasks"
62
+ "Task-Set contained TestbedTasks & no observer was provided -> will return TB-Tasks"
64
63
  )
65
64
  return shp_wrap
66
65
  tbt = TestbedTasks(**shp_wrap.parameters)
@@ -93,7 +93,7 @@ class SystemInventory(ShpModel):
93
93
  reply = subprocess.run( # noqa: S603
94
94
  ptp_cmd, timeout=30, capture_output=True, check=False
95
95
  )
96
- ptp_out = f"{ reply.stdout }, { reply.stderr }"
96
+ ptp_out = f"{reply.stdout}, {reply.stderr}"
97
97
  # alternative: check_output - seems to be lighter
98
98
 
99
99
  model_dict = {
@@ -172,7 +172,10 @@ class Reader:
172
172
  """Update internal states, helpful after resampling or other changes in data-group."""
173
173
  self.h5file.flush()
174
174
  sample_count = self.ds_time.shape[0]
175
- duration_raw = self.ds_time[sample_count - 1] - self.ds_time[0] if sample_count > 0 else 0
175
+ duration_raw = (
176
+ (int(self.ds_time[sample_count - 1]) - int(self.ds_time[0])) if sample_count > 0 else 0
177
+ )
178
+ # above's typecasting prevents overflow in u64-format
176
179
  if (sample_count > 0) and (duration_raw > 0):
177
180
  # this assumes iso-chronous sampling
178
181
  duration_s = self._cal.time.raw_to_si(duration_raw)
@@ -270,6 +273,29 @@ class Reader:
270
273
  else:
271
274
  return None
272
275
 
276
+ def get_voltage_step(self) -> Optional[float]:
277
+ """Informs about the voltage step (in volts) used during harvesting the ivcurve.
278
+
279
+ Options for figuring out the real step:
280
+ - look into config (if available)
281
+ - analyze recorded data for most often used delta
282
+ - calculate with 'steps_n * (1 + wait_cycles)' (done for calculating window_size)
283
+ """
284
+ voltage_step: Optional[float] = (
285
+ self.get_config().get("virtual_harvester", {}).get("voltage_step_mV", None)
286
+ )
287
+ if voltage_step is None:
288
+ dsv = self.ds_voltage[0:2000]
289
+ diffs_np = np.unique(dsv[1:] - dsv[0:-1], return_counts=False)
290
+ diffs_ls = [_e for _e in list(np.array(diffs_np)) if _e > 0]
291
+ # static voltages have 0 steps, so
292
+ if len(diffs_ls) == 0:
293
+ return None # or is 0 better? that may provoke div0
294
+ voltage_step = min(diffs_ls)
295
+ if voltage_step is not None:
296
+ voltage_step = 1e-3 * voltage_step
297
+ return voltage_step
298
+
273
299
  def get_hrv_config(self) -> dict:
274
300
  """Essential info for harvester.
275
301
 
@@ -278,6 +304,7 @@ class Reader:
278
304
  return {
279
305
  "datatype": self.get_datatype(),
280
306
  "window_samples": self.get_window_samples(),
307
+ "voltage_step_V": self.get_voltage_step(),
281
308
  }
282
309
 
283
310
  def is_valid(self) -> bool:
@@ -36,7 +36,7 @@ class WebClient(AbcClient):
36
36
  super().__init__()
37
37
  if not hasattr(self, "_token"):
38
38
  # add default values
39
- self._token: str = "basic_public_access"
39
+ self._token: str = "basic_public_access" # noqa: S105
40
40
  self._server: str = testbed_server_default
41
41
  self._user: Optional[User] = None
42
42
  self._key: Optional[str] = None
@@ -1,3 +1,3 @@
1
1
  """Separated string avoids circular imports."""
2
2
 
3
- version: str = "2024.11.2"
3
+ version: str = "2025.02.1"
@@ -47,6 +47,7 @@ def simulate_harvester(
47
47
  for_emu=True,
48
48
  dtype_in=file_inp.get_datatype(),
49
49
  window_size=file_inp.get_window_samples(),
50
+ voltage_step_V=file_inp.get_voltage_step(),
50
51
  )
51
52
  hrv = VirtualHarvesterModel(hrv_pru)
52
53
  e_out_Ws = 0.0
@@ -31,6 +31,7 @@ class VirtualSourceModel:
31
31
  cal_emu: CalibrationEmulator,
32
32
  dtype_in: EnergyDType = EnergyDType.ivsample,
33
33
  window_size: Optional[int] = None,
34
+ voltage_step_V: Optional[float] = None,
34
35
  *,
35
36
  log_intermediate: bool = False,
36
37
  ) -> None:
@@ -50,6 +51,7 @@ class VirtualSourceModel:
50
51
  for_emu=True,
51
52
  dtype_in=dtype_in,
52
53
  window_size=window_size,
54
+ voltage_step_V=voltage_step_V,
53
55
  )
54
56
 
55
57
  self.hrv: VirtualHarvesterModel = VirtualHarvesterModel(hrv_config)
@@ -56,6 +56,7 @@ def simulate_source(
56
56
  dtype_in=file_inp.get_datatype(),
57
57
  log_intermediate=False,
58
58
  window_size=file_inp.get_window_samples(),
59
+ voltage_step_V=file_inp.get_voltage_step(),
59
60
  )
60
61
  i_out_nA = 0
61
62
  e_out_Ws = 0.0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: shepherd_core
3
- Version: 2024.11.2
3
+ Version: 2025.2.1
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>
@@ -26,6 +26,7 @@ def src_model(
26
26
  name: str,
27
27
  dtype_in: EnergyDType = EnergyDType.ivsample,
28
28
  window_size: Optional[int] = None,
29
+ voltage_step_V: Optional[float] = None,
29
30
  ) -> VirtualSourceModel:
30
31
  src_config = VirtualSourceConfig(name=name, V_intermediate_init_mV=2000)
31
32
  cal_emu = CalibrationEmulator()
@@ -35,6 +36,7 @@ def src_model(
35
36
  log_intermediate=False,
36
37
  dtype_in=dtype_in,
37
38
  window_size=window_size,
39
+ voltage_step_V=voltage_step_V,
38
40
  )
39
41
 
40
42
 
@@ -145,9 +147,12 @@ def test_vsource_vsrc_create_files(
145
147
  @pytest.mark.parametrize("src_name", src_list)
146
148
  def test_vsource_vsrc_sim_curve(src_name: str, file_ivcurve: Path) -> None:
147
149
  with Reader(file_ivcurve) as file:
148
- window_size = file.get_window_samples()
149
- dtype = file.get_datatype()
150
- src = src_model("BQ25504s", dtype_in=dtype, window_size=window_size)
150
+ src = src_model(
151
+ "BQ25504s",
152
+ dtype_in=file.get_datatype(),
153
+ window_size=file.get_window_samples(),
154
+ voltage_step_V=file.get_voltage_step(),
155
+ )
151
156
  for _t, _v, _i in file.read_buffers():
152
157
  length = max(_v.size, _i.size)
153
158
  for _n in range(length):
@@ -157,9 +162,12 @@ def test_vsource_vsrc_sim_curve(src_name: str, file_ivcurve: Path) -> None:
157
162
  @pytest.mark.parametrize("src_name", src_list)
158
163
  def test_vsource_vsrc_sim_sample(src_name: str, file_ivsample: Path) -> None:
159
164
  with Reader(file_ivsample) as file:
160
- window_size = file.get_window_samples()
161
- dtype = file.get_datatype()
162
- src = src_model("BQ25504s", dtype_in=dtype, window_size=window_size)
165
+ src = src_model(
166
+ "BQ25504s",
167
+ dtype_in=file.get_datatype(),
168
+ window_size=file.get_window_samples(),
169
+ voltage_step_V=file.get_voltage_step(),
170
+ )
163
171
  for _t, _v, _i in file.read_buffers():
164
172
  length = max(_v.size, _i.size)
165
173
  for _n in range(length):
@@ -39,7 +39,13 @@ def test_vsource_hrv_fail_ivcurve(hrv_name: str) -> None:
39
39
  # the first algos are not usable for ivcurve
40
40
  hrv_config = VirtualHarvesterConfig(name=hrv_name)
41
41
  with pytest.raises(ValueError): # noqa: PT011
42
- _ = HarvesterPRUConfig.from_vhrv(hrv_config, for_emu=True, dtype_in=EnergyDType.ivcurve)
42
+ _ = HarvesterPRUConfig.from_vhrv(
43
+ hrv_config,
44
+ for_emu=True,
45
+ dtype_in=EnergyDType.ivcurve,
46
+ window_size=100,
47
+ voltage_step_V=0.1,
48
+ )
43
49
 
44
50
 
45
51
  @pytest.mark.parametrize("hrv_name", hrv_list[3:])
@@ -51,6 +57,7 @@ def test_vsource_hrv_sim(hrv_name: str, file_ivcurve: Path) -> None:
51
57
  for_emu=True,
52
58
  dtype_in=file.get_datatype(),
53
59
  window_size=file.get_window_samples(),
60
+ voltage_step_V=file.get_voltage_step(),
54
61
  )
55
62
  hrv = VirtualHarvesterModel(hrv_pru)
56
63
  for _t, _v, _i in file.read_buffers():
@@ -71,3 +78,26 @@ def test_vsource_hrv_fail_unknown_type() -> None:
71
78
  hrv_config = VirtualHarvesterConfig(name="mppt_voc")
72
79
  with pytest.raises(KeyError):
73
80
  _ = HarvesterPRUConfig.from_vhrv(hrv_config, for_emu=True, dtype_in="xyz")
81
+
82
+
83
+ def test_vsource_hrv_adapt_voltage_step() -> None:
84
+ hrv_config = VirtualHarvesterConfig(name="mppt_bq")
85
+ # first case without setting step-size
86
+ pru_config1 = HarvesterPRUConfig.from_vhrv(
87
+ hrv_config,
88
+ for_emu=True,
89
+ dtype_in=EnergyDType.ivcurve,
90
+ window_size=1000,
91
+ voltage_step_V=1e-3 * hrv_config.voltage_step_mV,
92
+ )
93
+ step_expected_uV = (pru_config1.voltage_max_uV - pru_config1.voltage_min_uV) / (1000 - 1)
94
+ assert pru_config1.voltage_step_uV > 2 * step_expected_uV
95
+ # now it gets set
96
+ pru_config2 = HarvesterPRUConfig.from_vhrv(
97
+ hrv_config,
98
+ for_emu=True,
99
+ dtype_in=EnergyDType.ivcurve,
100
+ window_size=1000,
101
+ voltage_step_V=1e-6 * step_expected_uV,
102
+ )
103
+ assert pru_config2.voltage_step_uV < 2 * step_expected_uV