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
pyxcp/cpp_ext/daqlist.hpp CHANGED
@@ -8,22 +8,70 @@
8
8
 
9
9
  using flatten_odts_t = std::vector<std::vector<std::tuple<std::string, std::uint32_t, std::uint8_t, std::uint16_t, std::int16_t>>>;
10
10
 
11
- class DaqList {
11
+ class Odt {
12
12
  public:
13
+ using odt_entry_initializer_t = std::tuple<std::string, std::string>;
13
14
 
14
- using daq_list_initialzer_t = std::tuple<std::string, std::uint32_t, std::uint16_t, std::string>;
15
+ Odt(const std::vector<odt_entry_initializer_t>& entries) {
16
+ for (const auto& entry : entries) {
17
+ const auto& [name, dt_name] = entry;
18
+ m_entries.emplace_back(McObject(name, 0, 0, 0, dt_name));
19
+ }
20
+ }
15
21
 
16
- DaqList(
17
- std::string_view meas_name, std::uint16_t event_num, bool stim, bool enable_timestamps,
18
- const std::vector<daq_list_initialzer_t>& measurements, std::uint8_t priority=0x00, std::uint8_t prescaler=0x01
19
- ) :
20
- m_name(meas_name), m_event_num(event_num), m_priority(priority), m_prescaler(prescaler), m_stim(stim), m_enable_timestamps(enable_timestamps) {
21
- for (const auto& measurement : measurements) {
22
- auto const& [name, address, ext, dt_name] = measurement;
23
- m_measurements.emplace_back(McObject(name, address, static_cast<std::uint8_t>(ext), 0, dt_name));
22
+ const std::vector<McObject>& get_entries() const {
23
+ return m_entries;
24
+ }
25
+
26
+ std::string dumps() const {
27
+ std::stringstream ss;
28
+ ss << to_binary(m_entries.size());
29
+ for (const auto& entry : m_entries) {
30
+ ss << entry.dumps();
24
31
  }
32
+ return ss.str();
25
33
  }
26
34
 
35
+ std::string to_string() const {
36
+ std::stringstream ss;
37
+ ss << "Odt(entries=[";
38
+ for (std::size_t i = 0; i < m_entries.size(); ++i) {
39
+ ss << ::to_string(m_entries[i]);
40
+ if (i + 1 < m_entries.size()) {
41
+ ss << ", ";
42
+ }
43
+ }
44
+ ss << "])";
45
+ return ss.str();
46
+ }
47
+
48
+ private:
49
+ std::vector<McObject> m_entries;
50
+ };
51
+
52
+ inline std::string to_string(const Odt& odt) {
53
+ return odt.to_string();
54
+ }
55
+
56
+ class DaqListBase {
57
+ public:
58
+ DaqListBase(std::string_view name, std::uint16_t event_num, bool stim, bool enable_timestamps, std::uint8_t priority, std::uint8_t prescaler) :
59
+ m_name(name),
60
+ m_event_num(event_num),
61
+ m_priority(priority),
62
+ m_prescaler(prescaler),
63
+ m_stim(stim),
64
+ m_enable_timestamps(enable_timestamps),
65
+ m_odt_count(0),
66
+ m_total_entries(0),
67
+ m_total_length(0) {
68
+ }
69
+
70
+ virtual ~DaqListBase() = default;
71
+
72
+ virtual std::string dumps() const = 0;
73
+ virtual std::string to_string() const = 0;
74
+
27
75
  bool get_enable_timestamps() const {
28
76
  return m_enable_timestamps;
29
77
  }
@@ -52,10 +100,6 @@ class DaqList {
52
100
  return m_stim;
53
101
  }
54
102
 
55
- const std::vector<McObject>& get_measurements() const {
56
- return m_measurements;
57
- }
58
-
59
103
  const std::vector<Bin>& get_measurements_opt() const {
60
104
  return m_measurements_opt;
61
105
  }
@@ -86,6 +130,10 @@ class DaqList {
86
130
 
87
131
  void set_measurements_opt(const std::vector<Bin>& measurements_opt) {
88
132
  m_measurements_opt = measurements_opt;
133
+ m_header_names.clear();
134
+ m_headers.clear();
135
+ m_flatten_odts.clear();
136
+
89
137
  auto odt_count = 0u;
90
138
  auto total_entries = 0u;
91
139
  auto total_length = 0u;
@@ -93,31 +141,85 @@ class DaqList {
93
141
  odt_count++;
94
142
  std::vector<std::tuple<std::string, std::uint32_t, std::uint8_t, std::uint16_t, std::int16_t>> flatten_odt{};
95
143
  for (const auto& mc_obj : bin.get_entries()) {
96
- for (const auto& component : mc_obj.get_components()) {
97
- m_header_names.emplace_back(component.get_name());
144
+ const auto& components = mc_obj.get_components();
145
+ if (!components.empty()) {
146
+ for (const auto& component : components) {
147
+ m_header_names.emplace_back(component.get_name());
148
+ flatten_odt.emplace_back(
149
+ component.get_name(), component.get_address(), component.get_ext(), component.get_length(),
150
+ component.get_type_index()
151
+ );
152
+ // TYPE_MAP_REV::at may throw if key is invalid; this indicates a programming error upstream.
153
+ m_headers.emplace_back(component.get_name(), TYPE_MAP_REV.at(static_cast<std::uint16_t>(component.get_type_index())));
154
+ total_entries++;
155
+ total_length += component.get_length();
156
+ }
157
+ } else {
158
+ // Treat the McObject itself as an entry when it has no components.
159
+ m_header_names.emplace_back(mc_obj.get_name());
98
160
  flatten_odt.emplace_back(
99
- component.get_name(), component.get_address(), component.get_ext(), component.get_length(),
100
- component.get_type_index()
161
+ mc_obj.get_name(), mc_obj.get_address(), mc_obj.get_ext(), mc_obj.get_length(), mc_obj.get_type_index()
101
162
  );
102
- m_headers.emplace_back(component.get_name(), TYPE_MAP_REV.at(component.get_type_index()));
163
+ m_headers.emplace_back(mc_obj.get_name(), TYPE_MAP_REV.at(static_cast<std::uint16_t>(mc_obj.get_type_index())));
103
164
  total_entries++;
104
- total_length += component.get_length();
165
+ total_length += mc_obj.get_length();
105
166
  }
106
167
  }
107
- m_flatten_odts.emplace_back(flatten_odt);
168
+ m_flatten_odts.emplace_back(std::move(flatten_odt));
108
169
  }
109
- m_odt_count = odt_count;
110
- m_total_entries = total_entries;
111
- m_total_length = total_length;
170
+ m_odt_count = static_cast<std::uint16_t>(odt_count);
171
+ m_total_entries = static_cast<std::uint16_t>(total_entries);
172
+ m_total_length = static_cast<std::uint16_t>(total_length);
112
173
  }
113
174
 
114
- std::string dumps() const {
175
+ protected:
176
+ std::string m_name;
177
+ std::uint16_t m_event_num;
178
+ std::uint8_t m_priority;
179
+ std::uint8_t m_prescaler;
180
+ bool m_stim;
181
+ bool m_enable_timestamps;
182
+ std::vector<Bin> m_measurements_opt;
183
+ std::vector<std::string> m_header_names;
184
+ std::vector<std::tuple<std::string, std::string>> m_headers;
185
+ std::uint16_t m_odt_count;
186
+ std::uint16_t m_total_entries;
187
+ std::uint16_t m_total_length;
188
+ flatten_odts_t m_flatten_odts;
189
+ };
190
+
191
+ class DaqList : public DaqListBase {
192
+ public:
193
+
194
+ using daq_list_initialzer_t = std::tuple<std::string, std::uint32_t, std::uint16_t, std::string>;
195
+
196
+ DaqList(
197
+ std::string_view meas_name, std::uint16_t event_num, bool stim, bool enable_timestamps,
198
+ const std::vector<daq_list_initialzer_t>& measurements, std::uint8_t priority=0x00, std::uint8_t prescaler=0x01
199
+ ) :
200
+ DaqListBase(meas_name, event_num, stim, enable_timestamps, priority, prescaler) {
201
+ for (const auto& measurement : measurements) {
202
+ auto const& [name, address, ext, dt_name] = measurement;
203
+ m_measurements.emplace_back(McObject(name, address, static_cast<std::uint8_t>(ext), 0, dt_name));
204
+ }
205
+ }
206
+
207
+ const std::vector<McObject>& get_measurements() const {
208
+ return m_measurements;
209
+ }
210
+
211
+ std::string dumps() const override {
115
212
  std::stringstream ss;
116
213
 
214
+ std::uint8_t discr=1;
215
+
216
+ ss << to_binary(discr);
117
217
  ss << to_binary(m_name);
118
218
  ss << to_binary(m_event_num);
119
219
  ss << to_binary(m_stim);
120
220
  ss << to_binary(m_enable_timestamps);
221
+ ss << to_binary(m_priority);
222
+ ss << to_binary(m_prescaler);
121
223
 
122
224
  ss << to_binary(m_odt_count);
123
225
  ss << to_binary(m_total_entries);
@@ -138,47 +240,39 @@ class DaqList {
138
240
  for (const auto& hdr_obj : m_header_names) {
139
241
  ss << to_binary(hdr_obj);
140
242
  }
141
- /////
142
- std::size_t odt_size = m_flatten_odts.size();
143
- ss << to_binary(odt_size);
144
- for (const auto& odt : m_flatten_odts) {
145
- ss << to_binary(odt.size());
146
- for (const auto& odt_entry : odt) {
147
- const auto& [name, address, ext, size, type_index] = odt_entry;
148
- ss << to_binary(name);
149
- ss << to_binary(address);
150
- ss << to_binary(ext);
151
- ss << to_binary(size);
152
- ss << to_binary(type_index);
153
- }
154
- }
155
243
  return ss.str();
156
244
  }
157
245
 
158
- std::string to_string() const {
246
+ std::string to_string() const override {
159
247
  std::stringstream ss;
160
-
161
248
  ss << "DaqList(";
162
- ss << "name=\"" << m_name << "\", ";
249
+ ss << "name='" << m_name << "', ";
163
250
  ss << "event_num=" << static_cast<std::uint16_t>(m_event_num) << ", ";
164
251
  ss << "stim=" << bool_to_string(m_stim) << ", ";
165
- ss << "enable_timestamps" << bool_to_string(m_enable_timestamps) << ", ";
166
- ss << "measurements=[\n";
167
- for (const auto& meas : m_measurements) {
168
- ss << ::to_string(meas) << ",\n";
169
- }
170
- ss << "],\n";
171
- ss << "measurements_opt=[\n";
172
- for (const auto& meas : m_measurements_opt) {
173
- ss << ::to_string(meas) << ",\n";
174
- }
175
- ss << "],\n";
176
- ss << "header_names=[\n";
177
- for (const auto& header : m_header_names) {
178
- ss << "\"" << header << "\",";
179
- }
180
- ss << "\n]";
181
- ss << ")";
252
+ ss << "enable_timestamps=" << bool_to_string(m_enable_timestamps) << ", ";
253
+ ss << "priority=" << static_cast<std::uint16_t>(m_priority) << ", ";
254
+ ss << "prescaler=" << static_cast<std::uint16_t>(m_prescaler) << ", ";
255
+ ss << "odt_count=" << static_cast<std::uint16_t>(m_odt_count) << ", ";
256
+ ss << "total_entries=" << static_cast<std::uint16_t>(m_total_entries) << ", ";
257
+ ss << "total_length=" << static_cast<std::uint16_t>(m_total_length) << ", ";
258
+ ss << "measurements=[";
259
+ for (std::size_t i = 0; i < m_measurements.size(); ++i) {
260
+ ss << ::to_string(m_measurements[i]);
261
+ if (i + 1 < m_measurements.size()) ss << ", ";
262
+ }
263
+ ss << "], ";
264
+ ss << "measurements_opt=[";
265
+ for (std::size_t i = 0; i < m_measurements_opt.size(); ++i) {
266
+ ss << ::to_string(m_measurements_opt[i]);
267
+ if (i + 1 < m_measurements_opt.size()) ss << ", ";
268
+ }
269
+ ss << "], ";
270
+ ss << "header_names=[";
271
+ for (std::size_t i = 0; i < m_header_names.size(); ++i) {
272
+ ss << "'" << m_header_names[i] << "'";
273
+ if (i + 1 < m_header_names.size()) ss << ", ";
274
+ }
275
+ ss << "])";
182
276
  return ss.str();
183
277
  }
184
278
 
@@ -186,21 +280,95 @@ class DaqList {
186
280
  }
187
281
 
188
282
  private:
283
+ std::vector<McObject> m_measurements;
284
+ };
189
285
 
190
- std::string m_name;
191
- std::uint16_t m_event_num;
192
- std::uint8_t m_priority;
193
- std::uint8_t m_prescaler;
194
- bool m_stim;
195
- bool m_enable_timestamps;
196
- std::vector<McObject> m_measurements;
197
- std::vector<Bin> m_measurements_opt;
198
- std::vector<std::string> m_header_names;
199
- std::vector<std::tuple<std::string, std::string>> m_headers;
200
- std::uint16_t m_odt_count;
201
- std::uint16_t m_total_entries;
202
- std::uint16_t m_total_length;
203
- flatten_odts_t m_flatten_odts;
286
+ class PredefinedDaqList : public DaqListBase {
287
+ public:
288
+ using odt_initializer_t = std::vector<Odt::odt_entry_initializer_t>;
289
+ using predefined_daq_list_initializer_t = std::vector<odt_initializer_t>;
290
+
291
+ PredefinedDaqList(
292
+ std::string_view name, std::uint16_t event_num, bool stim, bool enable_timestamps,
293
+ const predefined_daq_list_initializer_t& odts, std::uint8_t priority = 0x00, std::uint8_t prescaler = 0x01) :
294
+ DaqListBase(name, event_num, stim, enable_timestamps, priority, prescaler) {
295
+ std::vector<Bin> bins;
296
+ bins.reserve(odts.size());
297
+ for (const auto& odt_init : odts) {
298
+ Bin bin(0);
299
+ std::uint16_t total_length = 0;
300
+ for (const auto& entry : odt_init) {
301
+ const auto& [name, dt_name] = entry;
302
+ // McObject will validate dt_name and set length accordingly.
303
+ McObject obj(name, 0, 0, 0, dt_name);
304
+ total_length = static_cast<std::uint16_t>(total_length + obj.get_length());
305
+ bin.append(obj);
306
+ }
307
+ // Derive Bin size and residual capacity from sum of entry lengths.
308
+ bin.set_size(total_length);
309
+ bin.set_residual_capacity(total_length);
310
+ bins.emplace_back(std::move(bin));
311
+ }
312
+ set_measurements_opt(bins);
313
+ }
314
+
315
+ std::string dumps() const override {
316
+ std::stringstream ss;
317
+
318
+ std::uint8_t discr=2;
319
+
320
+ ss << to_binary(discr);
321
+
322
+ ss << to_binary(m_name);
323
+ ss << to_binary(m_event_num);
324
+ ss << to_binary(m_stim);
325
+ ss << to_binary(m_enable_timestamps);
326
+ ss << to_binary(m_priority);
327
+ ss << to_binary(m_prescaler);
328
+
329
+ ss << to_binary(m_odt_count);
330
+ ss << to_binary(m_total_entries);
331
+ ss << to_binary(m_total_length);
332
+
333
+ std::size_t meas_opt_size = m_measurements_opt.size();
334
+ ss << to_binary(meas_opt_size);
335
+ for (const auto& mc_obj : m_measurements_opt) {
336
+ ss << mc_obj.dumps();
337
+ }
338
+ std::size_t hname_size = m_header_names.size();
339
+ ss << to_binary(hname_size);
340
+ for (const auto& hdr_obj : m_header_names) {
341
+ ss << to_binary(hdr_obj);
342
+ }
343
+ return ss.str();
344
+ }
345
+
346
+ std::string to_string() const override {
347
+ std::stringstream ss;
348
+ ss << "PredefinedDaqList(";
349
+ ss << "name='" << m_name << "', ";
350
+ ss << "event_num=" << static_cast<std::uint16_t>(m_event_num) << ", ";
351
+ ss << "stim=" << bool_to_string(m_stim) << ", ";
352
+ ss << "enable_timestamps=" << bool_to_string(m_enable_timestamps) << ", ";
353
+ ss << "priority=" << static_cast<std::uint16_t>(m_priority) << ", ";
354
+ ss << "prescaler=" << static_cast<std::uint16_t>(m_prescaler) << ", ";
355
+ ss << "odt_count=" << static_cast<std::uint16_t>(m_odt_count) << ", ";
356
+ ss << "total_entries=" << static_cast<std::uint16_t>(m_total_entries) << ", ";
357
+ ss << "total_length=" << static_cast<std::uint16_t>(m_total_length) << ", ";
358
+ ss << "measurements_opt=[";
359
+ for (std::size_t i = 0; i < m_measurements_opt.size(); ++i) {
360
+ ss << ::to_string(m_measurements_opt[i]);
361
+ if (i + 1 < m_measurements_opt.size()) ss << ", ";
362
+ }
363
+ ss << "], ";
364
+ ss << "header_names=[";
365
+ for (std::size_t i = 0; i < m_header_names.size(); ++i) {
366
+ ss << "'" << m_header_names[i] << "'";
367
+ if (i + 1 < m_header_names.size()) ss << ", ";
368
+ }
369
+ ss << "])";
370
+ return ss.str();
371
+ }
204
372
  };
205
373
 
206
374
  #endif // __DAQ_LIST_HPP
@@ -4,9 +4,11 @@
4
4
  #include <pybind11/numpy.h>
5
5
  #include <pybind11/pybind11.h>
6
6
  #include <pybind11/stl.h>
7
+ #include <memory>
7
8
 
8
9
  #include <cstdint>
9
10
 
11
+ #include "aligned_buffer.hpp"
10
12
  #include "bin.hpp"
11
13
  #include "daqlist.hpp"
12
14
  #include "mcobject.hpp"
@@ -20,6 +22,22 @@ class PyTimestampInfo : public TimestampInfo {
20
22
  using TimestampInfo::TimestampInfo;
21
23
  };
22
24
 
25
+ py::dict mcobject_asdict(const McObject& self) {
26
+ py::dict d;
27
+ d["name"] = self.get_name();
28
+ d["address"] = self.get_address();
29
+ d["ext"] = self.get_ext();
30
+ d["length"] = self.get_length();
31
+ d["data_type"] = self.get_data_type();
32
+ py::list components_list;
33
+ for (const auto& component : self.get_components()) {
34
+ components_list.append(mcobject_asdict(component));
35
+ }
36
+ d["components"] = components_list;
37
+ return d;
38
+ }
39
+
40
+
23
41
  PYBIND11_MODULE(cpp_ext, m) {
24
42
  m.doc() = "C++ extensions for pyXCP.";
25
43
 
@@ -40,6 +58,7 @@ PYBIND11_MODULE(cpp_ext, m) {
40
58
  .def_property_readonly("components", &McObject::get_components)
41
59
 
42
60
  .def("add_component", &McObject::add_component, "component"_a)
61
+ .def("asdict", &mcobject_asdict)
43
62
  .def("__eq__", [](const McObject& self, const McObject& other) { return self == other; })
44
63
  .def("__repr__", [](const McObject& self) { return to_string(self); })
45
64
  .def("__hash__", [](const McObject& self) { return self.get_hash(); })
@@ -51,32 +70,120 @@ PYBIND11_MODULE(cpp_ext, m) {
51
70
  .def_property("residual_capacity", &Bin::get_residual_capacity, &Bin::set_residual_capacity)
52
71
  .def_property("entries", &Bin::get_entries, nullptr)
53
72
  .def("append", &Bin::append)
54
-
73
+ .def("asdict", [](const Bin& self) {
74
+ py::dict d;
75
+ d["size"] = self.get_size();
76
+ d["residual_capacity"] = self.get_residual_capacity();
77
+ py::list entries_list;
78
+ for (const auto& entry : self.get_entries()) {
79
+ entries_list.append(mcobject_asdict(entry));
80
+ }
81
+ d["entries"] = entries_list;
82
+ return d;
83
+ })
55
84
  .def("__repr__", [](const Bin& self) { return to_string(self); })
56
-
57
85
  .def("__eq__", [](const Bin& self, const Bin& other) { return self == other; })
58
-
59
86
  .def("__len__", [](const Bin& self) { return std::size(self.get_entries()); });
60
87
 
61
- py::class_<DaqList>(m, "DaqList")
88
+ py::class_<DaqListBase, std::shared_ptr<DaqListBase>>(m, "DaqListBase")
89
+ .def_property("name", &DaqListBase::get_name, nullptr)
90
+ .def_property("event_num", &DaqListBase::get_event_num, &DaqListBase::set_event_num)
91
+ .def_property("priority", &DaqListBase::get_priority, nullptr)
92
+ .def_property("prescaler", &DaqListBase::get_prescaler, nullptr)
93
+ .def_property("stim", &DaqListBase::get_stim, nullptr)
94
+ .def_property("enable_timestamps", &DaqListBase::get_enable_timestamps, nullptr)
95
+ .def_property("measurements_opt", &DaqListBase::get_measurements_opt, &DaqListBase::set_measurements_opt)
96
+ .def_property("headers", &DaqListBase::get_headers, nullptr)
97
+ .def_property("odt_count", &DaqListBase::get_odt_count, nullptr)
98
+ .def_property("total_entries", &DaqListBase::get_total_entries, nullptr)
99
+ .def_property("total_length", &DaqListBase::get_total_length, nullptr)
100
+ .def("asdict", [](const DaqListBase& self) {
101
+ py::dict d;
102
+ d["name"] = self.get_name();
103
+ d["event_num"] = self.get_event_num();
104
+ d["priority"] = self.get_priority();
105
+ d["prescaler"] = self.get_prescaler();
106
+ d["stim"] = self.get_stim();
107
+ d["enable_timestamps"] = self.get_enable_timestamps();
108
+ d["measurements_opt"] = self.get_measurements_opt();
109
+ d["headers"] = self.get_headers();
110
+ d["odt_count"] = self.get_odt_count();
111
+ d["total_entries"] = self.get_total_entries();
112
+ d["total_length"] = self.get_total_length();
113
+ return d;
114
+ });
115
+
116
+ py::class_<DaqList, DaqListBase, std::shared_ptr<DaqList>>(m, "DaqList")
62
117
  .def(
63
118
  py::init<std::string_view, std::uint16_t, bool, bool, const std::vector<DaqList::daq_list_initialzer_t>&,
64
119
  std::uint8_t, std::uint8_t>(), "name"_a, "event_num"_a, "stim"_a, "enable_timestamps"_a, "measurements"_a,
65
120
  "priority"_a=0, "prescaler"_a=1
66
121
  )
67
122
  .def("__repr__", [](const DaqList& self) { return self.to_string(); })
68
- .def_property("name", &DaqList::get_name, nullptr)
69
- .def_property("event_num", &DaqList::get_event_num, &DaqList::set_event_num)
70
- .def_property("priority", &DaqList::get_priority, nullptr)
71
- .def_property("prescaler", &DaqList::get_prescaler, nullptr)
72
- .def_property("stim", &DaqList::get_stim, nullptr)
73
- .def_property("enable_timestamps", &DaqList::get_enable_timestamps, nullptr)
74
123
  .def_property("measurements", &DaqList::get_measurements, nullptr)
75
- .def_property("measurements_opt", &DaqList::get_measurements_opt, &DaqList::set_measurements_opt)
76
- .def_property("headers", &DaqList::get_headers, nullptr)
77
- .def_property("odt_count", &DaqList::get_odt_count, nullptr)
78
- .def_property("total_entries", &DaqList::get_total_entries, nullptr)
79
- .def_property("total_length", &DaqList::get_total_length, nullptr);
124
+ .def("asdict", [](const DaqList& self) {
125
+ py::dict d;
126
+ d["name"] = self.get_name();
127
+ d["event_num"] = self.get_event_num();
128
+ d["priority"] = self.get_priority();
129
+ d["prescaler"] = self.get_prescaler();
130
+ d["stim"] = self.get_stim();
131
+ d["enable_timestamps"] = self.get_enable_timestamps();
132
+ d["measurements_opt"] = self.get_measurements_opt();
133
+ d["headers"] = self.get_headers();
134
+ d["odt_count"] = self.get_odt_count();
135
+ d["total_entries"] = self.get_total_entries();
136
+ d["total_length"] = self.get_total_length();
137
+ py::list measurements_list;
138
+ for (const auto& measurement : self.get_measurements()) {
139
+ measurements_list.append(mcobject_asdict(measurement));
140
+ }
141
+ d["measurements"] = measurements_list;
142
+ return d;
143
+ });
144
+
145
+ py::class_<PredefinedDaqList, DaqListBase, std::shared_ptr<PredefinedDaqList>>(m, "PredefinedDaqList")
146
+ .def(
147
+ py::init<std::string_view, std::uint16_t, bool, bool, const PredefinedDaqList::predefined_daq_list_initializer_t&,
148
+ std::uint8_t, std::uint8_t>(), "name"_a, "event_num"_a, "stim"_a, "enable_timestamps"_a, "odts"_a,
149
+ "priority"_a=0, "prescaler"_a=1
150
+ )
151
+ .def("__repr__", [](const PredefinedDaqList& self) {
152
+ try {
153
+ return self.to_string();
154
+ } catch (const std::exception& e) {
155
+ return std::string("PredefinedDaqList(<repr error: ") + e.what() + ">)";
156
+ } catch (...) {
157
+ return std::string("PredefinedDaqList(<repr error: unknown>)");
158
+ }
159
+ })
160
+ .def("asdict", [](const PredefinedDaqList& self) {
161
+ py::dict d;
162
+ d["name"] = self.get_name();
163
+ d["event_num"] = self.get_event_num();
164
+ d["priority"] = self.get_priority();
165
+ d["prescaler"] = self.get_prescaler();
166
+ d["stim"] = self.get_stim();
167
+ d["enable_timestamps"] = self.get_enable_timestamps();
168
+ d["measurements_opt"] = self.get_measurements_opt();
169
+ d["headers"] = self.get_headers();
170
+ d["odt_count"] = self.get_odt_count();
171
+ d["total_entries"] = self.get_total_entries();
172
+ d["total_length"] = self.get_total_length();
173
+ return d;
174
+ })
175
+ ;
176
+
177
+ // Aligned buffer utility
178
+ py::class_<AlignedBuffer>(m, "AlignedBuffer")
179
+ .def(py::init<std::size_t>(), py::arg("size") = 0xffff)
180
+ .def("reset", &AlignedBuffer::reset)
181
+ .def("append", &AlignedBuffer::append, py::arg("value"))
182
+ .def("extend", py::overload_cast<const py::bytes&>(&AlignedBuffer::extend))
183
+ .def("extend", py::overload_cast<const std::vector<std::uint8_t>&>(&AlignedBuffer::extend))
184
+ .def("__len__", [](const AlignedBuffer& self) { return self.size(); })
185
+ .def("__getitem__", [](const AlignedBuffer& self, py::object index) { return self.get_item(index); });
186
+
80
187
 
81
188
  py::enum_<TimestampType>(m, "TimestampType")
82
189
  .value("ABSOLUTE_TS", TimestampType::ABSOLUTE_TS)
@@ -97,4 +204,5 @@ PYBIND11_MODULE(cpp_ext, m) {
97
204
  .def_property("utc_offset", &TimestampInfo::get_utc_offset, &TimestampInfo::set_utc_offset)
98
205
  .def_property("dst_offset", &TimestampInfo::get_dst_offset, &TimestampInfo::set_dst_offset)
99
206
  .def_property("timezone", &TimestampInfo::get_timezone, &TimestampInfo::set_timezone);
207
+
100
208
  }