pyxcp 0.23.3__cp312-cp312-win_arm64.whl → 0.25.6__cp312-cp312-win_arm64.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.
Files changed (87) hide show
  1. pyxcp/__init__.py +1 -1
  2. pyxcp/asamkeydll.exe +0 -0
  3. pyxcp/cmdline.py +15 -30
  4. pyxcp/config/__init__.py +73 -20
  5. pyxcp/cpp_ext/aligned_buffer.hpp +168 -0
  6. pyxcp/cpp_ext/bin.hpp +7 -6
  7. pyxcp/cpp_ext/cpp_ext.cp310-win_arm64.pyd +0 -0
  8. pyxcp/cpp_ext/cpp_ext.cp311-win_arm64.pyd +0 -0
  9. pyxcp/cpp_ext/cpp_ext.cp312-win_arm64.pyd +0 -0
  10. pyxcp/cpp_ext/daqlist.hpp +241 -73
  11. pyxcp/cpp_ext/extension_wrapper.cpp +123 -15
  12. pyxcp/cpp_ext/framing.hpp +360 -0
  13. pyxcp/cpp_ext/mcobject.hpp +5 -3
  14. pyxcp/cpp_ext/sxi_framing.hpp +332 -0
  15. pyxcp/daq_stim/__init__.py +182 -45
  16. pyxcp/daq_stim/optimize/binpacking.py +2 -2
  17. pyxcp/daq_stim/scheduler.cpp +8 -8
  18. pyxcp/daq_stim/stim.cp310-win_arm64.pyd +0 -0
  19. pyxcp/daq_stim/stim.cp311-win_arm64.pyd +0 -0
  20. pyxcp/daq_stim/stim.cp312-win_arm64.pyd +0 -0
  21. pyxcp/errormatrix.py +2 -2
  22. pyxcp/examples/run_daq.py +5 -3
  23. pyxcp/examples/xcp_policy.py +6 -6
  24. pyxcp/examples/xcp_read_benchmark.py +2 -2
  25. pyxcp/examples/xcp_skel.py +1 -2
  26. pyxcp/examples/xcp_unlock.py +10 -12
  27. pyxcp/examples/xcp_user_supplied_driver.py +1 -2
  28. pyxcp/examples/xcphello.py +2 -15
  29. pyxcp/examples/xcphello_recorder.py +2 -2
  30. pyxcp/master/__init__.py +1 -0
  31. pyxcp/master/errorhandler.py +248 -13
  32. pyxcp/master/master.py +838 -250
  33. pyxcp/recorder/.idea/.gitignore +8 -0
  34. pyxcp/recorder/.idea/misc.xml +4 -0
  35. pyxcp/recorder/.idea/modules.xml +8 -0
  36. pyxcp/recorder/.idea/recorder.iml +6 -0
  37. pyxcp/recorder/.idea/sonarlint/issuestore/3/8/3808afc69ac1edb9d760000a2f137335b1b99728 +7 -0
  38. pyxcp/recorder/.idea/sonarlint/issuestore/9/a/9a2aa4db38d3115ed60da621e012c0efc0172aae +0 -0
  39. pyxcp/recorder/.idea/sonarlint/issuestore/b/4/b49006702b459496a8e8c94ebe60947108361b91 +0 -0
  40. pyxcp/recorder/.idea/sonarlint/issuestore/index.pb +7 -0
  41. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/3/8/3808afc69ac1edb9d760000a2f137335b1b99728 +0 -0
  42. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/9/a/9a2aa4db38d3115ed60da621e012c0efc0172aae +0 -0
  43. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/b/4/b49006702b459496a8e8c94ebe60947108361b91 +0 -0
  44. pyxcp/recorder/.idea/sonarlint/securityhotspotstore/index.pb +7 -0
  45. pyxcp/recorder/.idea/vcs.xml +10 -0
  46. pyxcp/recorder/__init__.py +5 -10
  47. pyxcp/recorder/converter/__init__.py +4 -10
  48. pyxcp/recorder/reader.hpp +0 -1
  49. pyxcp/recorder/reco.py +1 -0
  50. pyxcp/recorder/rekorder.cp310-win_arm64.pyd +0 -0
  51. pyxcp/recorder/rekorder.cp311-win_arm64.pyd +0 -0
  52. pyxcp/recorder/rekorder.cp312-win_arm64.pyd +0 -0
  53. pyxcp/recorder/unfolder.hpp +129 -107
  54. pyxcp/recorder/wrap.cpp +3 -8
  55. pyxcp/scripts/xcp_fetch_a2l.py +2 -2
  56. pyxcp/scripts/xcp_id_scanner.py +1 -2
  57. pyxcp/scripts/xcp_info.py +66 -51
  58. pyxcp/scripts/xcp_profile.py +1 -2
  59. pyxcp/tests/test_daq.py +1 -1
  60. pyxcp/tests/test_framing.py +262 -0
  61. pyxcp/tests/test_master.py +210 -100
  62. pyxcp/tests/test_transport.py +138 -42
  63. pyxcp/timing.py +1 -1
  64. pyxcp/transport/__init__.py +8 -5
  65. pyxcp/transport/base.py +187 -143
  66. pyxcp/transport/can.py +117 -13
  67. pyxcp/transport/eth.py +55 -20
  68. pyxcp/transport/hdf5_policy.py +167 -0
  69. pyxcp/transport/sxi.py +126 -52
  70. pyxcp/transport/transport_ext.cp310-win_arm64.pyd +0 -0
  71. pyxcp/transport/transport_ext.cp311-win_arm64.pyd +0 -0
  72. pyxcp/transport/transport_ext.cp312-win_arm64.pyd +0 -0
  73. pyxcp/transport/transport_ext.hpp +214 -0
  74. pyxcp/transport/transport_wrapper.cpp +249 -0
  75. pyxcp/transport/usb_transport.py +47 -31
  76. pyxcp/types.py +0 -13
  77. pyxcp/{utils.py → utils/__init__.py} +3 -4
  78. pyxcp/utils/cli.py +78 -0
  79. pyxcp-0.25.6.dist-info/METADATA +341 -0
  80. pyxcp-0.25.6.dist-info/RECORD +153 -0
  81. {pyxcp-0.23.3.dist-info → pyxcp-0.25.6.dist-info}/WHEEL +1 -1
  82. pyxcp/examples/conf_sxi.json +0 -9
  83. pyxcp/examples/conf_sxi.toml +0 -7
  84. pyxcp-0.23.3.dist-info/METADATA +0 -219
  85. pyxcp-0.23.3.dist-info/RECORD +0 -131
  86. {pyxcp-0.23.3.dist-info → pyxcp-0.25.6.dist-info}/entry_points.txt +0 -0
  87. {pyxcp-0.23.3.dist-info → pyxcp-0.25.6.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,8 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
4
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/recorder.iml" filepath="$PROJECT_DIR$/.idea/recorder.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module classpath="CMake" type="CPP_MODULE" version="4">
3
+ <component name="SonarLintModuleSettings">
4
+ <option name="uniqueId" value="ce2142a1-5ccc-4675-8d23-c6ee960ba851" />
5
+ </component>
6
+ </module>
@@ -0,0 +1,7 @@
1
+
2
+ T cpp:S5028"8Replace this macro by "const", "constexpr" or an "enum".(����8�󓀹1
3
+  cpp:S3806""^non-portable path to file '<windows.h>'; specified path differs in case from file name on disk(��������8�����1
4
+ Tcpp:S954�"8Move these 3 #include directives to the top of the file.(���8ﴔ��1
5
+ T cpp:S5028"8Replace this macro by "const", "constexpr" or an "enum".(����8帔��1
6
+  cpp:S3806""^non-portable path to file '<windows.h>'; specified path differs in case from file name on disk(��������8�Ӕ��1
7
+ Tcpp:S954�"8Move these 3 #include directives to the top of the file.(���8�Ԕ��1
@@ -0,0 +1,7 @@
1
+
2
+ >
3
+ CMakeLists.txt,9\a\9a2aa4db38d3115ed60da621e012c0efc0172aae
4
+ 8
5
+ wrap.cpp,b\4\b49006702b459496a8e8c94ebe60947108361b91
6
+ <
7
+ rekorder.hpp,3\8\3808afc69ac1edb9d760000a2f137335b1b99728
@@ -0,0 +1,7 @@
1
+
2
+ >
3
+ CMakeLists.txt,9\a\9a2aa4db38d3115ed60da621e012c0efc0172aae
4
+ 8
5
+ wrap.cpp,b\4\b49006702b459496a8e8c94ebe60947108361b91
6
+ <
7
+ rekorder.hpp,3\8\3808afc69ac1edb9d760000a2f137335b1b99728
@@ -0,0 +1,10 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
5
+ <mapping directory="$PROJECT_DIR$/lz4" vcs="Git" />
6
+ <mapping directory="$PROJECT_DIR$/mio" vcs="Git" />
7
+ <mapping directory="$PROJECT_DIR$/simde" vcs="Git" />
8
+ <mapping directory="$PROJECT_DIR$/simdjson" vcs="Git" />
9
+ </component>
10
+ </project>
@@ -1,11 +1,10 @@
1
1
  #!/usr/bin/env python
2
- """XCP Frame Recording Facility.
3
- """
2
+ """XCP Frame Recording Facility."""
4
3
 
5
4
  from dataclasses import dataclass
6
5
  from typing import Union
7
6
 
8
- from pyxcp.types import FrameCategory
7
+ from pyxcp.transport.base import FrameCategory
9
8
 
10
9
 
11
10
  try:
@@ -16,13 +15,9 @@ else:
16
15
  HAS_PANDAS = True
17
16
 
18
17
  from pyxcp.recorder.rekorder import DaqOnlinePolicy # noqa: F401
19
- from pyxcp.recorder.rekorder import (
20
- DaqRecorderPolicy, # noqa: F401
21
- Deserializer, # noqa: F401
22
- MeasurementParameters, # noqa: F401
23
- ValueHolder, # noqa: F401
24
- )
25
- from pyxcp.recorder.rekorder import XcpLogFileDecoder as _XcpLogFileDecoder
18
+ from pyxcp.recorder.rekorder import DaqRecorderPolicy # noqa: F401
19
+ from pyxcp.recorder.rekorder import Deserializer # noqa: F401
20
+ from pyxcp.recorder.rekorder import MeasurementParameters # noqa: F401
26
21
  from pyxcp.recorder.rekorder import _PyXcpLogFileReader, _PyXcpLogFileWriter, data_types
27
22
 
28
23
 
@@ -1,5 +1,6 @@
1
1
  """Convert pyXCPs .xmraw files to common data formats."""
2
2
 
3
+ from contextlib import suppress
3
4
  import csv
4
5
  import logging
5
6
  import os
@@ -119,10 +120,8 @@ class XcpLogFileDecoder(_XcpLogFileDecoder):
119
120
  self.out_file_suffix = out_file_suffix
120
121
  self.target_type_map = target_type_map or {}
121
122
  if remove_file:
122
- try:
123
+ with suppress(FileNotFoundError):
123
124
  os.unlink(self.out_file_name)
124
- except FileNotFoundError:
125
- pass
126
125
 
127
126
  def initialize(self) -> None:
128
127
  self.on_initialize()
@@ -154,7 +153,6 @@ class XcpLogFileDecoder(_XcpLogFileDecoder):
154
153
 
155
154
 
156
155
  class CollectRows:
157
-
158
156
  def on_daq_list(self, daq_list_num: int, timestamp0: int, timestamp1: int, measurements: list) -> None:
159
157
  storage_container = self.tables[daq_list_num]
160
158
  storage_container.timestamp0.append(timestamp0)
@@ -214,7 +212,6 @@ class ArrowConverter(CollectRows, XcpLogFileDecoder):
214
212
 
215
213
 
216
214
  class CsvConverter(XcpLogFileDecoder):
217
-
218
215
  def __init__(self, recording_file_name: str, target_file_name: str = ""):
219
216
  super().__init__(
220
217
  recording_file_name=recording_file_name, out_file_suffix=".csv", remove_file=False, target_file_name=target_file_name
@@ -242,7 +239,6 @@ class CsvConverter(XcpLogFileDecoder):
242
239
 
243
240
 
244
241
  class ExcelConverter(XcpLogFileDecoder):
245
-
246
242
  def __init__(self, recording_file_name: str, target_file_name: str = ""):
247
243
  super().__init__(recording_file_name=recording_file_name, out_file_suffix=".xlsx", target_file_name=target_file_name)
248
244
 
@@ -273,7 +269,6 @@ class ExcelConverter(XcpLogFileDecoder):
273
269
 
274
270
 
275
271
  class HdfConverter(CollectRows, XcpLogFileDecoder):
276
-
277
272
  def __init__(self, recording_file_name: str, target_file_name: str = ""):
278
273
  super().__init__(recording_file_name=recording_file_name, out_file_suffix=".h5", target_file_name=target_file_name)
279
274
 
@@ -296,7 +291,6 @@ class HdfConverter(CollectRows, XcpLogFileDecoder):
296
291
 
297
292
 
298
293
  class MdfConverter(CollectRows, XcpLogFileDecoder):
299
-
300
294
  def __init__(self, recording_file_name: str, target_file_name: str = ""):
301
295
  super().__init__(
302
296
  recording_file_name=recording_file_name,
@@ -367,8 +361,8 @@ class SqliteConverter(XcpLogFileDecoder):
367
361
  self.create_table(sc)
368
362
  self.logger.info(f"Creating table {sc.name!r}.")
369
363
  self.insert_stmt[sc.name] = (
370
- f"""INSERT INTO {sc.name}({', '.join(['timestamp0', 'timestamp1'] + [r.name for r in sc.arr])})"""
371
- f""" VALUES({', '.join(["?" for _ in range(len(sc.arr) + 2)])})"""
364
+ f"""INSERT INTO {sc.name}({", ".join(["timestamp0", "timestamp1"] + [r.name for r in sc.arr])})"""
365
+ f""" VALUES({", ".join(["?" for _ in range(len(sc.arr) + 2)])})"""
372
366
  )
373
367
 
374
368
  def on_finalize(self) -> None:
pyxcp/recorder/reader.hpp CHANGED
@@ -47,7 +47,6 @@ class XcpLogFileReader {
47
47
  read_bytes(m_offset, sizeof(std::size_t), reinterpret_cast<blob_t *>(&metadata_length));
48
48
 
49
49
  std::copy(ptr(data_start), ptr(data_start + metadata_length), std::back_inserter(m_metadata));
50
- // std::cout << "Metadata: " << m_metadata << std::endl;
51
50
  m_offset += (metadata_length + sizeof(std::size_t));
52
51
  }
53
52
  }
pyxcp/recorder/reco.py CHANGED
@@ -12,6 +12,7 @@ See
12
12
 
13
13
  - ``_ for reading.
14
14
  """
15
+
15
16
  import enum
16
17
  import mmap
17
18
  import struct
Binary file
Binary file
Binary file
@@ -13,6 +13,7 @@
13
13
  #include <stdfloat>
14
14
  #endif
15
15
  #include <variant>
16
+ #include <memory>
16
17
 
17
18
  #include "daqlist.hpp"
18
19
  #include "helper.hpp"
@@ -324,7 +325,7 @@ struct Getter {
324
325
  }
325
326
  }
326
327
 
327
- void set_first_pids(const std::vector<DaqList>& daq_lists, const std::vector<std::uint16_t>& first_pids) {
328
+ void set_first_pids(const std::vector<std::shared_ptr<DaqListBase>>& daq_lists, const std::vector<std::uint16_t>& first_pids) {
328
329
  m_first_pids = first_pids;
329
330
 
330
331
  if (m_id_size == 1) {
@@ -333,7 +334,7 @@ struct Getter {
333
334
  for (const auto& daq_list : daq_lists) {
334
335
  auto first_pid = m_first_pids[daq_list_num];
335
336
 
336
- for (std::uint16_t idx = first_pid; idx < daq_list.get_odt_count() + first_pid; ++idx) {
337
+ for (std::uint16_t idx = first_pid; idx < daq_list->get_odt_count() + first_pid; ++idx) {
337
338
  m_odt_to_daq_map[idx] = { daq_list_num, (idx - first_pid) };
338
339
  }
339
340
  daq_list_num++;
@@ -540,7 +541,7 @@ struct MeasurementParameters {
540
541
  explicit MeasurementParameters(
541
542
  std::uint8_t byte_order, std::uint8_t id_field_size, bool timestamps_supported, bool ts_fixed, bool prescaler_supported,
542
543
  bool selectable_timestamps, double ts_scale_factor, std::uint8_t ts_size, std::uint16_t min_daq,
543
- const TimestampInfo& timestamp_info, const std::vector<DaqList>& daq_lists, const std::vector<std::uint16_t>& first_pids
544
+ const TimestampInfo& timestamp_info, const std::vector<std::shared_ptr<DaqListBase>>& daq_lists, const std::vector<std::uint16_t>& first_pids
544
545
  ) :
545
546
  m_byte_order(byte_order),
546
547
  m_id_field_size(id_field_size),
@@ -578,7 +579,7 @@ struct MeasurementParameters {
578
579
  ////
579
580
 
580
581
  for (const auto& daq_list : m_daq_lists) {
581
- ss << daq_list.dumps();
582
+ ss << daq_list->dumps();
582
583
  }
583
584
 
584
585
  std::size_t fp_count = m_first_pids.size();
@@ -675,7 +676,7 @@ struct MeasurementParameters {
675
676
  std::uint8_t m_ts_size;
676
677
  std::uint16_t m_min_daq;
677
678
  TimestampInfo m_timestamp_info;
678
- std::vector<DaqList> m_daq_lists;
679
+ std::vector<std::shared_ptr<DaqListBase>> m_daq_lists;
679
680
  std::vector<std::uint16_t> m_first_pids;
680
681
  };
681
682
 
@@ -696,7 +697,7 @@ class Deserializer {
696
697
  std::uint8_t ts_size;
697
698
  std::uint16_t min_daq;
698
699
  std::size_t dl_count;
699
- std::vector<DaqList> daq_lists;
700
+ std::vector<std::shared_ptr<DaqListBase>> daq_lists;
700
701
  std::size_t fp_count;
701
702
  std::uint64_t timestamp_ns;
702
703
  std::int16_t utc_offset;
@@ -716,20 +717,21 @@ class Deserializer {
716
717
  min_daq = from_binary<std::uint16_t>();
717
718
  dl_count = from_binary<std::size_t>();
718
719
 
719
- ////
720
720
  timestamp_ns = from_binary<std::uint64_t>();
721
- // std::cout << "TS: " << timestamp_ns << std::endl;
722
721
  timezone = from_binary_str();
723
- // std::cout << "TZ: " << timezone << std::endl;
724
722
  utc_offset = from_binary<std::int16_t>();
725
- // std::cout << "UTC:" << utc_offset << std::endl;
726
723
  dst_offset = from_binary<std::int16_t>();
727
- // std::cout << "DST:" << dst_offset << std::endl;
728
724
 
729
725
  TimestampInfo timestamp_info{ timestamp_ns, timezone, utc_offset, dst_offset };
730
726
 
731
727
  for (std::size_t i = 0; i < dl_count; i++) {
732
- daq_lists.push_back(create_daq_list());
728
+ auto discr = from_binary<std::uint8_t>();
729
+
730
+ if (discr == 1) {
731
+ daq_lists.push_back(create_daq_list());
732
+ } else if (discr == 2) {
733
+ daq_lists.push_back(create_predefined_daq_list());
734
+ }
733
735
  }
734
736
 
735
737
  fp_count = from_binary<std::size_t>();
@@ -745,9 +747,10 @@ class Deserializer {
745
747
 
746
748
  protected:
747
749
 
748
- DaqList create_daq_list() {
750
+ std::shared_ptr<DaqListBase> create_daq_list() {
749
751
  std::string name;
750
752
  std::uint16_t event_num;
753
+ std::uint16_t prescaler;
751
754
  bool stim;
752
755
  bool enable_timestamps;
753
756
  std::vector<McObject> measurements;
@@ -766,6 +769,8 @@ class Deserializer {
766
769
  event_num = from_binary<std::uint16_t>();
767
770
  stim = from_binary<bool>();
768
771
  enable_timestamps = from_binary<bool>();
772
+ std::uint8_t priority = from_binary<std::uint8_t>();
773
+ prescaler = from_binary<std::uint8_t>();
769
774
 
770
775
  odt_count = from_binary<std::uint16_t>(); // not used
771
776
  total_entries = from_binary<std::uint16_t>(); // not used
@@ -773,7 +778,6 @@ class Deserializer {
773
778
 
774
779
  std::size_t meas_size = from_binary<std::size_t>();
775
780
  for (std::size_t i = 0; i < meas_size; ++i) {
776
- // name, address, ext, dt_name
777
781
  auto meas = create_mc_object();
778
782
  measurements.push_back(meas);
779
783
  initializer_list.push_back({ meas.get_name(), meas.get_address(), meas.get_ext(), meas.get_data_type() });
@@ -790,38 +794,68 @@ class Deserializer {
790
794
  header_names.push_back(header);
791
795
  }
792
796
 
793
- auto odts = create_flatten_odts();
794
-
795
- auto result = DaqList(name, event_num, stim, enable_timestamps, initializer_list);
796
- result.set_measurements_opt(measurements_opt);
797
- return result;
797
+ auto dl = std::make_shared<DaqList>(name, event_num, stim, enable_timestamps, initializer_list, priority, prescaler);
798
+ dl->set_measurements_opt(measurements_opt);
799
+ return dl;
798
800
  }
799
801
 
800
- flatten_odts_t create_flatten_odts() {
801
- std::string name;
802
- std::uint32_t address;
803
- std::uint8_t ext;
804
- std::uint16_t size;
805
- std::int16_t type_index;
806
-
807
- flatten_odts_t odts;
808
-
809
- std::size_t odt_count = from_binary<std::size_t>();
810
- for (std::size_t i = 0; i < odt_count; ++i) {
811
- std::vector<std::tuple<std::string, std::uint32_t, std::uint8_t, std::uint16_t, std::int16_t>> flatten_odt{};
812
- std::size_t odt_entry_count = from_binary<std::size_t>();
813
- for (std::size_t j = 0; j < odt_entry_count; ++j) {
814
- name = from_binary_str();
815
- address = from_binary<std::uint32_t>();
816
- ext = from_binary<std::uint8_t>();
817
- size = from_binary<std::uint16_t>();
818
- type_index = from_binary<std::int16_t>();
819
- flatten_odt.push_back(std::make_tuple(name, address, ext, size, type_index));
802
+ std::shared_ptr<DaqListBase> create_predefined_daq_list() {
803
+ std::string name;
804
+ std::uint16_t event_num;
805
+ std::uint8_t priority;
806
+ std::uint8_t prescaler;
807
+ bool stim;
808
+ bool enable_timestamps;
809
+ std::vector<Bin> measurements_opt;
810
+ std::vector<std::string> header_names;
811
+ PredefinedDaqList::predefined_daq_list_initializer_t odts;
812
+ std::uint16_t odt_count;
813
+ std::uint16_t total_entries;
814
+ std::uint16_t total_length;
815
+
816
+ name = from_binary_str();
817
+ event_num = from_binary<std::uint16_t>();
818
+ stim = from_binary<bool>();
819
+ enable_timestamps = from_binary<bool>();
820
+ priority = from_binary<std::uint8_t>();
821
+ prescaler = from_binary<std::uint8_t>();
822
+
823
+ odt_count = from_binary<std::uint16_t>(); // not used
824
+ total_entries = from_binary<std::uint16_t>(); // not used
825
+ total_length = from_binary<std::uint16_t>(); // not used
826
+
827
+ std::size_t meas_opt_size = from_binary<std::size_t>();
828
+ for (std::size_t i = 0; i < meas_opt_size; ++i) {
829
+ measurements_opt.emplace_back(create_bin());
830
+ }
831
+
832
+ std::size_t hname_size = from_binary<std::size_t>();
833
+ for (std::size_t i = 0; i < hname_size; ++i) {
834
+ auto header = from_binary_str();
835
+ header_names.push_back(header);
836
+ }
837
+
838
+ // Build `odts` from `measurements_opt` so the constructor is properly initialized
839
+ odts.clear();
840
+ odts.reserve(measurements_opt.size());
841
+ for (const auto& bin : measurements_opt) {
842
+ PredefinedDaqList::odt_initializer_t odt_init;
843
+ for (const auto& mc_obj : bin.get_entries()) {
844
+ const auto& comps = mc_obj.get_components();
845
+ if (comps.empty()) {
846
+ odt_init.emplace_back(mc_obj.get_name(), mc_obj.get_data_type());
847
+ } else {
848
+ for (const auto& component : comps) {
849
+ odt_init.emplace_back(component.get_name(), component.get_data_type());
850
+ }
851
+ }
820
852
  }
821
- odts.push_back(flatten_odt);
853
+ odts.emplace_back(std::move(odt_init));
822
854
  }
823
855
 
824
- return odts;
856
+ auto dl = std::make_shared<PredefinedDaqList>(name, event_num, stim, enable_timestamps, odts, priority, prescaler);
857
+ dl->set_measurements_opt(measurements_opt);
858
+ return dl;
825
859
  }
826
860
 
827
861
  McObject create_mc_object() {
@@ -1057,8 +1091,8 @@ class DAQProcessor {
1057
1091
  m_getter = Getter(requires_swap(params.m_byte_order), params.m_id_field_size, params.m_ts_size);
1058
1092
  for (std::uint16_t idx = 0; idx < params.m_daq_lists.size(); ++idx) {
1059
1093
  m_state.emplace_back(DaqListState(
1060
- idx, params.m_daq_lists[idx].get_odt_count(), params.m_daq_lists[idx].get_total_entries(),
1061
- params.m_daq_lists[idx].get_enable_timestamps(), params.m_id_field_size, params.m_daq_lists[idx].get_flatten_odts(),
1094
+ idx, params.m_daq_lists[idx]->get_odt_count(), params.m_daq_lists[idx]->get_total_entries(),
1095
+ params.m_daq_lists[idx]->get_enable_timestamps(), params.m_id_field_size, params.m_daq_lists[idx]->get_flatten_odts(),
1062
1096
  m_getter, params
1063
1097
  ));
1064
1098
  }
@@ -1109,8 +1143,9 @@ class DaqRecorderPolicy : public DAQPolicyBase {
1109
1143
  }
1110
1144
 
1111
1145
  void feed(std::uint8_t frame_cat, std::uint16_t counter, std::uint64_t timestamp, const std::string& payload) override {
1112
- if (frame_cat != static_cast<std::uint8_t>(FrameCategory::DAQ)) {
1146
+ if (frame_cat != static_cast<std::uint8_t>(FrameCategory::DAQ) || (!m_initialized)) {
1113
1147
  // Only record DAQ frames for now.
1148
+ // also make sure policy is initialized.
1114
1149
  return;
1115
1150
  }
1116
1151
  m_writer->add_frame(frame_cat, counter, timestamp, static_cast<std::uint16_t>(payload.size()), payload.c_str());
@@ -1139,6 +1174,42 @@ class DaqRecorderPolicy : public DAQPolicyBase {
1139
1174
  bool m_initialized{ false };
1140
1175
  };
1141
1176
 
1177
+ class DaqTimeTracker {
1178
+ public:
1179
+
1180
+ DaqTimeTracker(std::uint64_t overflow_value) : m_overflow_value(overflow_value), m_overflow_counter(0ULL), m_previous_timestamp(0ULL) {
1181
+ m_ts_base_set=false;
1182
+ m_ts0_base=0ULL; m_ts1_base=0ULL;
1183
+ //std::cout << "\tOverflow value: " << overflow_value << "\n";
1184
+ }
1185
+
1186
+ std::pair<std::uint64_t,std::uint64_t> normalize(std::uint64_t ts0, std::uint64_t ts1) noexcept {
1187
+
1188
+ if (m_previous_timestamp > ts1) {
1189
+ m_overflow_counter++;
1190
+ }
1191
+ m_previous_timestamp = ts1;
1192
+
1193
+ if (!m_ts_base_set) {
1194
+ m_ts0_base = ts0;
1195
+ m_ts1_base = ts1;
1196
+ m_ts_base_set = true;
1197
+ // std::cout << "\tSet ts0: " << ts0 << " ts1:" << ts1 << "\n";
1198
+ }
1199
+ // std::cout << "\t\tts0: " << ts0 << " Base: " << m_ts0_base << " ts1: " << ts1 << " Base: " << m_ts1_base << "\n";
1200
+ return {ts0 - m_ts0_base, (ts1 - m_ts1_base) + (m_overflow_value * m_overflow_counter) };
1201
+ }
1202
+ private:
1203
+
1204
+ std::uint64_t m_overflow_value{};
1205
+ std::uint64_t m_overflow_counter{};
1206
+ std::uint64_t m_previous_timestamp{};
1207
+ bool m_ts_base_set{false};
1208
+ std::uint64_t m_ts0_base{0ULL};
1209
+ std::uint64_t m_ts1_base{0ULL};
1210
+ };
1211
+
1212
+
1142
1213
  class DaqOnlinePolicy : public DAQPolicyBase {
1143
1214
  public:
1144
1215
 
@@ -1149,6 +1220,9 @@ class DaqOnlinePolicy : public DAQPolicyBase {
1149
1220
 
1150
1221
  void set_parameters(const MeasurementParameters& params) noexcept {
1151
1222
  m_decoder = std::make_unique<DAQProcessor>(params);
1223
+ for (auto idx=0; idx < params.get_daq_lists().size(); ++idx) {
1224
+ m_overflows.emplace_back(DaqTimeTracker(params.get_overflow_value()));
1225
+ }
1152
1226
  DAQPolicyBase::set_parameters(params);
1153
1227
  }
1154
1228
 
@@ -1164,7 +1238,11 @@ class DaqOnlinePolicy : public DAQPolicyBase {
1164
1238
  auto result = m_decoder->feed(timestamp, payload);
1165
1239
  if (result) {
1166
1240
  const auto& [daq_list, ts0, ts1, meas] = *result;
1167
- on_daq_list(daq_list, ts0, ts1, meas);
1241
+ auto& overflow = m_overflows[daq_list];
1242
+
1243
+ auto [norm_ts0, norm_ts1] = overflow.normalize(ts0, ts1);
1244
+
1245
+ on_daq_list(daq_list, norm_ts0, norm_ts1, meas);
1168
1246
  }
1169
1247
  }
1170
1248
 
@@ -1177,58 +1255,9 @@ class DaqOnlinePolicy : public DAQPolicyBase {
1177
1255
  private:
1178
1256
 
1179
1257
  std::unique_ptr<DAQProcessor> m_decoder;
1258
+ std::vector<DaqTimeTracker> m_overflows;
1180
1259
  };
1181
1260
 
1182
- struct ValueHolder {
1183
- ValueHolder() = delete;
1184
- ValueHolder(const ValueHolder&) = default;
1185
-
1186
- ValueHolder(const std::any& value) : m_value(value) {
1187
- }
1188
-
1189
- ValueHolder(std::any&& value) : m_value(std::move(value)) {
1190
- }
1191
-
1192
- std::any get_value() const noexcept {
1193
- return m_value;
1194
- }
1195
-
1196
- private:
1197
-
1198
- std::any m_value;
1199
- };
1200
-
1201
- class Overflow {
1202
- public:
1203
-
1204
- Overflow(std::uint64_t overflow_value) : m_overflow_value(overflow_value), m_overflow_counter(0ULL), m_previous_timestamp(0ULL) {
1205
- }
1206
-
1207
- auto get_previous_timestamp() const noexcept {
1208
- return m_previous_timestamp;
1209
- }
1210
-
1211
- void set_previous_timestamp(std::uint64_t timestamp) noexcept {
1212
- m_previous_timestamp = timestamp;
1213
- }
1214
-
1215
- void inc_overflow_counter() noexcept {
1216
- m_overflow_counter++;
1217
- }
1218
-
1219
- auto get_overflow_counter() const noexcept {
1220
- return m_overflow_counter;
1221
- }
1222
-
1223
- auto get_value() const noexcept {
1224
- return m_overflow_value * m_overflow_counter;
1225
- }
1226
-
1227
- private:
1228
- std::uint64_t m_overflow_value{};
1229
- std::uint64_t m_overflow_counter{};
1230
- std::uint64_t m_previous_timestamp{};
1231
- };
1232
1261
 
1233
1262
  class XcpLogFileDecoder {
1234
1263
  public:
@@ -1240,12 +1269,12 @@ class XcpLogFileDecoder {
1240
1269
  m_params = des.run();
1241
1270
 
1242
1271
  for (auto idx=0; idx < m_params.get_daq_lists().size(); ++idx) {
1243
- m_overflows.emplace_back(Overflow(m_params.get_overflow_value()));
1272
+ m_overflows.emplace_back(DaqTimeTracker(m_params.get_overflow_value()));
1244
1273
  }
1245
1274
 
1246
1275
  m_decoder = std::make_unique<DAQProcessor>(m_params);
1247
1276
  } else {
1248
- // cannot proceed!!!
1277
+ throw std::runtime_error("XcpLogFileDecoder: missing metadata.");
1249
1278
  }
1250
1279
  }
1251
1280
 
@@ -1286,18 +1315,11 @@ class XcpLogFileDecoder {
1286
1315
  auto result = m_decoder->feed(timestamp, str_data);
1287
1316
  if (result) {
1288
1317
  const auto& [daq_list, ts0, ts1, meas] = *result;
1289
-
1290
1318
  auto& overflow = m_overflows[daq_list];
1291
1319
 
1292
- if (overflow.get_previous_timestamp() > ts1) {
1293
- overflow.inc_overflow_counter();
1294
- // Maybe on debug-level?
1295
- // std::cout << "Overflow detected, counter: " << overflow.get_overflow_counter() << " " << overflow.get_previous_timestamp() << " " << ts1 << std::endl;
1296
- }
1297
-
1298
- on_daq_list(daq_list, ts0, ts1 + overflow.get_value(), meas);
1320
+ auto [norm_ts0, norm_ts1] = overflow.normalize(ts0, ts1);
1299
1321
 
1300
- overflow.set_previous_timestamp(ts1);
1322
+ on_daq_list(daq_list, norm_ts0, norm_ts1, meas);
1301
1323
  }
1302
1324
  }
1303
1325
  }
@@ -1326,7 +1348,7 @@ class XcpLogFileDecoder {
1326
1348
  XcpLogFileReader m_reader;
1327
1349
  std::unique_ptr<DAQProcessor> m_decoder;
1328
1350
  MeasurementParameters m_params;
1329
- std::vector<Overflow> m_overflows;
1351
+ std::vector<DaqTimeTracker> m_overflows;
1330
1352
  };
1331
1353
 
1332
1354
  #endif // RECORDER_UNFOLDER_HPP
pyxcp/recorder/wrap.cpp CHANGED
@@ -3,6 +3,7 @@
3
3
  #include <pybind11/numpy.h>
4
4
  #include <pybind11/pybind11.h>
5
5
  #include <pybind11/stl.h>
6
+ #include <memory>
6
7
 
7
8
  #include <cstdint>
8
9
 
@@ -11,7 +12,6 @@
11
12
  namespace py = pybind11;
12
13
  using namespace pybind11::literals;
13
14
 
14
- PYBIND11_MAKE_OPAQUE(ValueHolder);
15
15
 
16
16
  class PyDaqOnlinePolicy : public DaqOnlinePolicy {
17
17
  public:
@@ -112,7 +112,7 @@ PYBIND11_MODULE(rekorder, m) {
112
112
  py::class_<MeasurementParameters>(m, "MeasurementParameters")
113
113
  .def(py::init<
114
114
  std::uint8_t, std::uint8_t, bool, bool, bool, bool, double, std::uint8_t, std::uint16_t, const TimestampInfo&,
115
- const std::vector<DaqList>&, const std::vector<std::uint16_t>&>())
115
+ const std::vector<std::shared_ptr<DaqListBase>>&, const std::vector<std::uint16_t>&>())
116
116
  .def("dumps", [](const MeasurementParameters& self) { return py::bytes(self.dumps()); })
117
117
  .def(
118
118
  "__repr__",
@@ -131,7 +131,7 @@ PYBIND11_MODULE(rekorder, m) {
131
131
  ss << "timestamp_info=" << self.get_timestamp_info().to_string() << ", ";
132
132
  ss << "daq_lists=[\n";
133
133
  for (const auto& dl : self.m_daq_lists) {
134
- ss << dl.to_string() << ",\n";
134
+ ss << dl->to_string() << ",\n";
135
135
  }
136
136
  ss << "],\n";
137
137
  ss << "first_pids=[";
@@ -181,9 +181,4 @@ PYBIND11_MODULE(rekorder, m) {
181
181
  .def("get_header", &XcpLogFileDecoder::get_header)
182
182
  .def("initialize", &XcpLogFileDecoder::initialize)
183
183
  .def("finalize", &XcpLogFileDecoder::finalize);
184
-
185
- py::class_<ValueHolder>(m, "ValueHolder")
186
- //.def(py::init<const ValueHolder&>())
187
- .def(py::init<const std::any&>())
188
- .def_property_readonly("value", &ValueHolder::get_value);
189
184
  }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python
2
- """Fetch A2L file from XCP slave (if supported).
3
- """
2
+ """Fetch A2L file from XCP slave (if supported)."""
3
+
4
4
  import sys
5
5
  from pathlib import Path
6
6