pyxcp 0.25.4__cp313-cp313-win_amd64.whl → 0.25.8__cp313-cp313-win_amd64.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.
- pyxcp/__init__.py +2 -2
- pyxcp/asamkeydll.exe +0 -0
- pyxcp/cmdline.py +1 -3
- pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp312-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp313-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/extension_wrapper.cpp +79 -2
- pyxcp/daq_stim/__init__.py +79 -1
- pyxcp/daq_stim/stim.cp310-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp311-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp312-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp313-win_amd64.pyd +0 -0
- pyxcp/master/master.py +53 -59
- pyxcp/recorder/rekorder.cp310-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp311-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp312-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp313-win_amd64.pyd +0 -0
- pyxcp/scripts/xcp_daq_recorder.py +54 -0
- pyxcp/transport/hdf5_policy.py +43 -5
- pyxcp/transport/transport_ext.cp310-win_amd64.pyd +0 -0
- pyxcp/transport/transport_ext.cp311-win_amd64.pyd +0 -0
- pyxcp/transport/transport_ext.cp312-win_amd64.pyd +0 -0
- pyxcp/transport/transport_ext.cp313-win_amd64.pyd +0 -0
- {pyxcp-0.25.4.dist-info → pyxcp-0.25.8.dist-info}/METADATA +1 -1
- {pyxcp-0.25.4.dist-info → pyxcp-0.25.8.dist-info}/RECORD +29 -28
- {pyxcp-0.25.4.dist-info → pyxcp-0.25.8.dist-info}/WHEEL +1 -1
- {pyxcp-0.25.4.dist-info → pyxcp-0.25.8.dist-info}/entry_points.txt +0 -0
- {pyxcp-0.25.4.dist-info → pyxcp-0.25.8.dist-info}/licenses/LICENSE +0 -0
pyxcp/__init__.py
CHANGED
|
@@ -16,5 +16,5 @@ console = Console()
|
|
|
16
16
|
tb_install(show_locals=True, max_frames=3) # Install custom exception handler.
|
|
17
17
|
|
|
18
18
|
# if you update this manually, do not forget to update
|
|
19
|
-
#
|
|
20
|
-
__version__ = "0.25.
|
|
19
|
+
# pyproject.toml.
|
|
20
|
+
__version__ = "0.25.8"
|
pyxcp/asamkeydll.exe
CHANGED
|
Binary file
|
pyxcp/cmdline.py
CHANGED
|
@@ -37,7 +37,7 @@ class ArgumentParser:
|
|
|
37
37
|
self._parser = StrippingParser(parser)
|
|
38
38
|
self._callout = user_parser
|
|
39
39
|
self._description = description
|
|
40
|
-
self.args =
|
|
40
|
+
self.args = self._parser.parse_and_strip()
|
|
41
41
|
|
|
42
42
|
def run(self, policy=None, transport_layer_interface=None):
|
|
43
43
|
"""Create and configure a synchronous master instance.
|
|
@@ -49,8 +49,6 @@ class ArgumentParser:
|
|
|
49
49
|
Returns:
|
|
50
50
|
A configured master instance
|
|
51
51
|
"""
|
|
52
|
-
self.args = self._parser.parse_and_strip()
|
|
53
|
-
|
|
54
52
|
# Create the application with custom arguments and callout
|
|
55
53
|
application = get_application(options=[], callout=self._callout)
|
|
56
54
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -22,6 +22,21 @@ class PyTimestampInfo : public TimestampInfo {
|
|
|
22
22
|
using TimestampInfo::TimestampInfo;
|
|
23
23
|
};
|
|
24
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
|
+
|
|
25
40
|
|
|
26
41
|
PYBIND11_MODULE(cpp_ext, m) {
|
|
27
42
|
m.doc() = "C++ extensions for pyXCP.";
|
|
@@ -43,6 +58,7 @@ PYBIND11_MODULE(cpp_ext, m) {
|
|
|
43
58
|
.def_property_readonly("components", &McObject::get_components)
|
|
44
59
|
|
|
45
60
|
.def("add_component", &McObject::add_component, "component"_a)
|
|
61
|
+
.def("asdict", &mcobject_asdict)
|
|
46
62
|
.def("__eq__", [](const McObject& self, const McObject& other) { return self == other; })
|
|
47
63
|
.def("__repr__", [](const McObject& self) { return to_string(self); })
|
|
48
64
|
.def("__hash__", [](const McObject& self) { return self.get_hash(); })
|
|
@@ -54,6 +70,17 @@ PYBIND11_MODULE(cpp_ext, m) {
|
|
|
54
70
|
.def_property("residual_capacity", &Bin::get_residual_capacity, &Bin::set_residual_capacity)
|
|
55
71
|
.def_property("entries", &Bin::get_entries, nullptr)
|
|
56
72
|
.def("append", &Bin::append)
|
|
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
|
+
})
|
|
57
84
|
.def("__repr__", [](const Bin& self) { return to_string(self); })
|
|
58
85
|
.def("__eq__", [](const Bin& self, const Bin& other) { return self == other; })
|
|
59
86
|
.def("__len__", [](const Bin& self) { return std::size(self.get_entries()); });
|
|
@@ -69,7 +96,22 @@ PYBIND11_MODULE(cpp_ext, m) {
|
|
|
69
96
|
.def_property("headers", &DaqListBase::get_headers, nullptr)
|
|
70
97
|
.def_property("odt_count", &DaqListBase::get_odt_count, nullptr)
|
|
71
98
|
.def_property("total_entries", &DaqListBase::get_total_entries, nullptr)
|
|
72
|
-
.def_property("total_length", &DaqListBase::get_total_length, 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
|
+
});
|
|
73
115
|
|
|
74
116
|
py::class_<DaqList, DaqListBase, std::shared_ptr<DaqList>>(m, "DaqList")
|
|
75
117
|
.def(
|
|
@@ -78,7 +120,27 @@ PYBIND11_MODULE(cpp_ext, m) {
|
|
|
78
120
|
"priority"_a=0, "prescaler"_a=1
|
|
79
121
|
)
|
|
80
122
|
.def("__repr__", [](const DaqList& self) { return self.to_string(); })
|
|
81
|
-
.def_property("measurements", &DaqList::get_measurements, nullptr)
|
|
123
|
+
.def_property("measurements", &DaqList::get_measurements, 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
|
+
});
|
|
82
144
|
|
|
83
145
|
py::class_<PredefinedDaqList, DaqListBase, std::shared_ptr<PredefinedDaqList>>(m, "PredefinedDaqList")
|
|
84
146
|
.def(
|
|
@@ -94,6 +156,21 @@ PYBIND11_MODULE(cpp_ext, m) {
|
|
|
94
156
|
} catch (...) {
|
|
95
157
|
return std::string("PredefinedDaqList(<repr error: unknown>)");
|
|
96
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;
|
|
97
174
|
})
|
|
98
175
|
;
|
|
99
176
|
|
pyxcp/daq_stim/__init__.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
|
|
3
3
|
from contextlib import suppress
|
|
4
|
+
import json
|
|
4
5
|
from time import time_ns
|
|
5
|
-
from typing import Dict, List, Optional, TextIO, Union
|
|
6
|
+
from typing import Any, Dict, List, Optional, TextIO, Tuple, Union
|
|
6
7
|
|
|
7
8
|
from pyxcp.cpp_ext.cpp_ext import DaqList, PredefinedDaqList
|
|
8
9
|
|
|
@@ -29,6 +30,83 @@ DAQ_TIMESTAMP_SIZE = {
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
|
|
33
|
+
def load_daq_lists_from_json(file_path: str) -> List[DaqList]:
|
|
34
|
+
"""Load and validate DAQ-list from JSON file."""
|
|
35
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
36
|
+
config = json.load(f)
|
|
37
|
+
|
|
38
|
+
if not isinstance(config, list):
|
|
39
|
+
raise ValueError("DAQ configuration must be a JSON array (list)")
|
|
40
|
+
|
|
41
|
+
daq_lists: List[DaqList] = []
|
|
42
|
+
for idx, entry in enumerate(config):
|
|
43
|
+
if not isinstance(entry, dict):
|
|
44
|
+
raise TypeError(f"Entry {idx} must be an object/dict")
|
|
45
|
+
|
|
46
|
+
required = {"name", "event_num", "stim", "enable_timestamps", "measurements", "priority", "prescaler"}
|
|
47
|
+
missing = required - set(entry.keys())
|
|
48
|
+
if missing:
|
|
49
|
+
raise ValueError(f"Entry {idx} missing required keys: {missing}")
|
|
50
|
+
|
|
51
|
+
# Basic type conversions / checks
|
|
52
|
+
name = entry["name"]
|
|
53
|
+
if not isinstance(name, str):
|
|
54
|
+
raise TypeError(f"Entry {idx} 'name' must be a string")
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
event_num = int(entry["event_num"])
|
|
58
|
+
except Exception as e:
|
|
59
|
+
raise TypeError(f"Entry {idx} 'event_num' must be an integer") from e
|
|
60
|
+
|
|
61
|
+
stim = bool(entry["stim"])
|
|
62
|
+
enable_timestamps = bool(entry["enable_timestamps"])
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
priority = int(entry["priority"])
|
|
66
|
+
prescaler = int(entry["prescaler"])
|
|
67
|
+
except Exception as e:
|
|
68
|
+
raise TypeError(f"Entry {idx} 'priority' and 'prescaler' must be integers") from e
|
|
69
|
+
|
|
70
|
+
measurements_raw = entry["measurements"]
|
|
71
|
+
if not isinstance(measurements_raw, list):
|
|
72
|
+
raise TypeError(f"Entry {idx} 'measurements' must be a list")
|
|
73
|
+
|
|
74
|
+
measurements: List[Tuple[str, int, int, str]] = []
|
|
75
|
+
for m_idx, m in enumerate(measurements_raw):
|
|
76
|
+
if not (isinstance(m, (list, tuple)) and len(m) == 4):
|
|
77
|
+
raise ValueError(f"Entry {idx} measurement {m_idx} must be a 4-element list/tuple")
|
|
78
|
+
m_name, m_addr, m_offset, m_type = m
|
|
79
|
+
|
|
80
|
+
if not isinstance(m_name, str):
|
|
81
|
+
raise TypeError(f"Entry {idx} measurement {m_idx} name must be a string")
|
|
82
|
+
try:
|
|
83
|
+
m_addr = int(m_addr)
|
|
84
|
+
except Exception as e:
|
|
85
|
+
raise TypeError(f"Entry {idx} measurement {m_idx} address must be an integer") from e
|
|
86
|
+
try:
|
|
87
|
+
m_offset = int(m_offset)
|
|
88
|
+
except Exception as e:
|
|
89
|
+
raise TypeError(f"Entry {idx} measurement {m_idx} offset must be an integer") from e
|
|
90
|
+
if not isinstance(m_type, str):
|
|
91
|
+
raise TypeError(f"Entry {idx} measurement {m_idx} type must be a string")
|
|
92
|
+
|
|
93
|
+
measurements.append((m_name, m_addr, m_offset, m_type))
|
|
94
|
+
|
|
95
|
+
daq_kwargs: Dict[str, Any] = {
|
|
96
|
+
"name": name,
|
|
97
|
+
"event_num": event_num,
|
|
98
|
+
"stim": stim,
|
|
99
|
+
"enable_timestamps": enable_timestamps,
|
|
100
|
+
"measurements": measurements,
|
|
101
|
+
"priority": priority,
|
|
102
|
+
"prescaler": prescaler,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
daq_lists.append(DaqList(**daq_kwargs))
|
|
106
|
+
|
|
107
|
+
return daq_lists
|
|
108
|
+
|
|
109
|
+
|
|
32
110
|
class DaqProcessor:
|
|
33
111
|
def __init__(self, daq_lists: List[Union[DaqList, PredefinedDaqList]]):
|
|
34
112
|
self.daq_lists = daq_lists
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
pyxcp/master/master.py
CHANGED
|
@@ -13,7 +13,7 @@ import struct
|
|
|
13
13
|
import traceback
|
|
14
14
|
import warnings
|
|
15
15
|
from contextlib import suppress
|
|
16
|
-
from typing import Any, Callable, Collection,
|
|
16
|
+
from typing import Any, Callable, Collection, TypeVar
|
|
17
17
|
|
|
18
18
|
from pyxcp.daq_stim.stim import DaqEventInfo, Stim
|
|
19
19
|
|
|
@@ -133,8 +133,7 @@ class Master:
|
|
|
133
133
|
Custom transport layer interface, by default None
|
|
134
134
|
"""
|
|
135
135
|
|
|
136
|
-
def __init__(self, transport_name: str | None, config: Any, policy: Any = None,
|
|
137
|
-
transport_layer_interface: Any = None) -> None:
|
|
136
|
+
def __init__(self, transport_name: str | None, config: Any, policy: Any = None, transport_layer_interface: Any = None) -> None:
|
|
138
137
|
"""Initialize a new Master instance.
|
|
139
138
|
|
|
140
139
|
Parameters
|
|
@@ -168,8 +167,7 @@ class Master:
|
|
|
168
167
|
# Set up transport layer
|
|
169
168
|
self.transport_name: str = transport_name.lower()
|
|
170
169
|
transport_config: Any = config.transport
|
|
171
|
-
self.transport: BaseTransport = create_transport(transport_name, transport_config, policy,
|
|
172
|
-
transport_layer_interface)
|
|
170
|
+
self.transport: BaseTransport = create_transport(transport_name, transport_config, policy, transport_layer_interface)
|
|
173
171
|
|
|
174
172
|
# Set up STIM (stimulation) support
|
|
175
173
|
self.stim: Stim = Stim(self.config.stim_support)
|
|
@@ -227,10 +225,7 @@ class Master:
|
|
|
227
225
|
self.transport.connect()
|
|
228
226
|
return self
|
|
229
227
|
|
|
230
|
-
def __exit__(
|
|
231
|
-
self, exc_type: type[BaseException] | None, exc_val: BaseException | None,
|
|
232
|
-
exc_tb
|
|
233
|
-
) -> None:
|
|
228
|
+
def __exit__(self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb) -> None:
|
|
234
229
|
"""Context manager exit part.
|
|
235
230
|
|
|
236
231
|
This method is called when exiting a context manager block.
|
|
@@ -750,11 +745,11 @@ class Master:
|
|
|
750
745
|
# Larger sizes will send in multiple CAN messages
|
|
751
746
|
# Each valid message will start with 0xFF followed by the upload bytes
|
|
752
747
|
# The last message might be padded to the required DLC
|
|
753
|
-
remaining_bytes = byte_count - len(response)
|
|
754
|
-
while remaining_bytes:
|
|
748
|
+
remaining_bytes = byte_count - len(response) # NOTE: Due to padding the result may negative!
|
|
749
|
+
while remaining_bytes > 0:
|
|
755
750
|
if len(self.transport.resQueue):
|
|
756
751
|
data = self.transport.resQueue.popleft()
|
|
757
|
-
response += data[1: remaining_bytes + 1]
|
|
752
|
+
response += data[1 : remaining_bytes + 1]
|
|
758
753
|
remaining_bytes = byte_count - len(response)
|
|
759
754
|
else:
|
|
760
755
|
short_sleep()
|
|
@@ -1064,17 +1059,17 @@ class Master:
|
|
|
1064
1059
|
)
|
|
1065
1060
|
|
|
1066
1061
|
def _generalized_downloader(
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1062
|
+
self,
|
|
1063
|
+
address: int,
|
|
1064
|
+
address_ext: int,
|
|
1065
|
+
data: bytes,
|
|
1066
|
+
maxCto: int,
|
|
1067
|
+
maxBs: int,
|
|
1068
|
+
minSt: int,
|
|
1069
|
+
master_block_mode: bool,
|
|
1070
|
+
dl_func: Callable[[bytes, int, bool], Any],
|
|
1071
|
+
dl_next_func: Callable[[bytes, int, bool], Any],
|
|
1072
|
+
callback: Callable[[int], None] | None = None,
|
|
1078
1073
|
) -> None:
|
|
1079
1074
|
"""Generic implementation for downloading data to the slave.
|
|
1080
1075
|
|
|
@@ -1138,13 +1133,13 @@ class Master:
|
|
|
1138
1133
|
self._download_normal_mode(data, total_length, max_payload, offset, dl_func, callback)
|
|
1139
1134
|
|
|
1140
1135
|
def _download_master_block_mode(
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1136
|
+
self,
|
|
1137
|
+
data: bytes,
|
|
1138
|
+
total_length: int,
|
|
1139
|
+
max_payload: int,
|
|
1140
|
+
offset: int,
|
|
1141
|
+
block_downloader: Callable[[bytes], Any],
|
|
1142
|
+
callback: Callable[[int], None] | None = None,
|
|
1148
1143
|
) -> None:
|
|
1149
1144
|
"""Download data using master block mode.
|
|
1150
1145
|
|
|
@@ -1171,7 +1166,7 @@ class Master:
|
|
|
1171
1166
|
|
|
1172
1167
|
# Process full blocks
|
|
1173
1168
|
for _ in blocks:
|
|
1174
|
-
block = data[offset: offset + max_payload]
|
|
1169
|
+
block = data[offset : offset + max_payload]
|
|
1175
1170
|
block_downloader(block)
|
|
1176
1171
|
offset += max_payload
|
|
1177
1172
|
remaining -= max_payload
|
|
@@ -1183,19 +1178,19 @@ class Master:
|
|
|
1183
1178
|
|
|
1184
1179
|
# Process remaining partial block
|
|
1185
1180
|
if remaining_block_size:
|
|
1186
|
-
block = data[offset: offset + remaining_block_size]
|
|
1181
|
+
block = data[offset : offset + remaining_block_size]
|
|
1187
1182
|
block_downloader(block)
|
|
1188
1183
|
if callback:
|
|
1189
1184
|
callback(percent_complete)
|
|
1190
1185
|
|
|
1191
1186
|
def _download_normal_mode(
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1187
|
+
self,
|
|
1188
|
+
data: bytes,
|
|
1189
|
+
total_length: int,
|
|
1190
|
+
max_payload: int,
|
|
1191
|
+
offset: int,
|
|
1192
|
+
dl_func: Callable[[bytes, int, bool], Any],
|
|
1193
|
+
callback: Callable[[int], None] | None = None,
|
|
1199
1194
|
) -> None:
|
|
1200
1195
|
"""Download data using normal mode.
|
|
1201
1196
|
|
|
@@ -1223,7 +1218,7 @@ class Master:
|
|
|
1223
1218
|
|
|
1224
1219
|
# Process full chunks
|
|
1225
1220
|
for _ in chunks:
|
|
1226
|
-
block = data[offset: offset + max_payload]
|
|
1221
|
+
block = data[offset : offset + max_payload]
|
|
1227
1222
|
dl_func(block, max_payload, last=False)
|
|
1228
1223
|
offset += max_payload
|
|
1229
1224
|
callback_remaining -= chunk_size
|
|
@@ -1235,17 +1230,17 @@ class Master:
|
|
|
1235
1230
|
|
|
1236
1231
|
# Process remaining partial chunk
|
|
1237
1232
|
if remaining:
|
|
1238
|
-
block = data[offset: offset + remaining]
|
|
1233
|
+
block = data[offset : offset + remaining]
|
|
1239
1234
|
dl_func(block, remaining, last=True)
|
|
1240
1235
|
if callback:
|
|
1241
1236
|
callback(percent_complete)
|
|
1242
1237
|
|
|
1243
1238
|
def _block_downloader(
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1239
|
+
self,
|
|
1240
|
+
data: bytes,
|
|
1241
|
+
dl_func: Callable[[bytes, int, bool], Any] | None = None,
|
|
1242
|
+
dl_next_func: Callable[[bytes, int, bool], Any] | None = None,
|
|
1243
|
+
minSt: float = 0.0,
|
|
1249
1244
|
) -> None:
|
|
1250
1245
|
"""Re-usable block downloader for transferring data in blocks.
|
|
1251
1246
|
|
|
@@ -1279,7 +1274,7 @@ class Master:
|
|
|
1279
1274
|
index = 0
|
|
1280
1275
|
for index in packets:
|
|
1281
1276
|
# Extract packet data
|
|
1282
|
-
packet_data = data[offset: offset + max_packet_size]
|
|
1277
|
+
packet_data = data[offset : offset + max_packet_size]
|
|
1283
1278
|
|
|
1284
1279
|
# Determine if this is the last packet
|
|
1285
1280
|
last = (remaining_block_size - max_packet_size) == 0
|
|
@@ -1302,7 +1297,7 @@ class Master:
|
|
|
1302
1297
|
# Process remaining partial packet
|
|
1303
1298
|
if remaining:
|
|
1304
1299
|
# Extract remaining data
|
|
1305
|
-
packet_data = data[offset: offset + remaining]
|
|
1300
|
+
packet_data = data[offset : offset + remaining]
|
|
1306
1301
|
|
|
1307
1302
|
# Send packet using appropriate function
|
|
1308
1303
|
if index == 0:
|
|
@@ -1745,8 +1740,7 @@ class Master:
|
|
|
1745
1740
|
|
|
1746
1741
|
@wrapped
|
|
1747
1742
|
def setDaqPackedMode(
|
|
1748
|
-
|
|
1749
|
-
dpm_sample_count: int = None
|
|
1743
|
+
self, daq_list_number: int, daq_packed_mode: int, dpm_timestamp_mode: int = None, dpm_sample_count: int = None
|
|
1750
1744
|
):
|
|
1751
1745
|
"""Set DAQ List Packed Mode.
|
|
1752
1746
|
|
|
@@ -1921,8 +1915,7 @@ class Master:
|
|
|
1921
1915
|
return self.transport.request(types.Command.PROGRAM_PREPARE, 0x00, *cs)
|
|
1922
1916
|
|
|
1923
1917
|
@wrapped
|
|
1924
|
-
def programFormat(self, compression_method: int, encryption_method: int, programming_method: int,
|
|
1925
|
-
access_method: int):
|
|
1918
|
+
def programFormat(self, compression_method: int, encryption_method: int, programming_method: int, access_method: int):
|
|
1926
1919
|
return self.transport.request(
|
|
1927
1920
|
types.Command.PROGRAM_FORMAT,
|
|
1928
1921
|
compression_method,
|
|
@@ -2190,8 +2183,7 @@ class Master:
|
|
|
2190
2183
|
@wrapped
|
|
2191
2184
|
def timeCorrelationProperties(self, set_properties: int, get_properties_request: int, cluster_id: int):
|
|
2192
2185
|
response = self.transport.request(
|
|
2193
|
-
types.Command.TIME_CORRELATION_PROPERTIES, set_properties, get_properties_request, 0,
|
|
2194
|
-
*self.WORD_pack(cluster_id)
|
|
2186
|
+
types.Command.TIME_CORRELATION_PROPERTIES, set_properties, get_properties_request, 0, *self.WORD_pack(cluster_id)
|
|
2195
2187
|
)
|
|
2196
2188
|
return types.TimeCorrelationPropertiesResponse.parse(response, byteOrder=self.slaveProperties.byteOrder)
|
|
2197
2189
|
|
|
@@ -2327,7 +2319,7 @@ class Master:
|
|
|
2327
2319
|
if self.currentProtectionStatus is None:
|
|
2328
2320
|
try:
|
|
2329
2321
|
status = self.getStatus()
|
|
2330
|
-
except Exception
|
|
2322
|
+
except Exception: # may temporary ERR_OUT_OF_RANGE
|
|
2331
2323
|
return {"dbg": None, "pgm": None, "stim": None, "daq": None, "calpag": None}
|
|
2332
2324
|
self._setProtectionStatus(status.resourceProtectionStatus)
|
|
2333
2325
|
return self.currentProtectionStatus
|
|
@@ -2372,8 +2364,7 @@ class Master:
|
|
|
2372
2364
|
|
|
2373
2365
|
protection_status = self.getCurrentProtectionStatus()
|
|
2374
2366
|
if any(protection_status.values()) and (not (self.seed_n_key_dll or self.seed_n_key_function)):
|
|
2375
|
-
raise RuntimeError(
|
|
2376
|
-
"Neither seed-and-key DLL nor function specified, cannot proceed.") # TODO: ConfigurationError
|
|
2367
|
+
raise RuntimeError("Neither seed-and-key DLL nor function specified, cannot proceed.") # TODO: ConfigurationError
|
|
2377
2368
|
if resources is None:
|
|
2378
2369
|
result = []
|
|
2379
2370
|
if self.slaveProperties["supportsCalpag"]:
|
|
@@ -2501,7 +2492,10 @@ class Master:
|
|
|
2501
2492
|
name = STD_IDS[id_value]
|
|
2502
2493
|
else:
|
|
2503
2494
|
name = f"USER_{idx}"
|
|
2504
|
-
yield
|
|
2495
|
+
yield (
|
|
2496
|
+
id_value,
|
|
2497
|
+
name,
|
|
2498
|
+
)
|
|
2505
2499
|
|
|
2506
2500
|
return generate()
|
|
2507
2501
|
|
|
@@ -2623,7 +2617,7 @@ def make_tick_converter(resolution):
|
|
|
2623
2617
|
"""
|
|
2624
2618
|
exponent = types.DAQ_TIMESTAMP_UNIT_TO_EXP[resolution.timestampMode.unit]
|
|
2625
2619
|
tick_resolution = resolution.timestampTicks
|
|
2626
|
-
base = (10
|
|
2620
|
+
base = (10**exponent) * tick_resolution
|
|
2627
2621
|
|
|
2628
2622
|
def ticks_to_seconds(ticks):
|
|
2629
2623
|
"""Convert DAQ timestamp/tick value to seconds.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import sys
|
|
6
|
+
import time
|
|
7
|
+
|
|
8
|
+
from pyxcp.cmdline import ArgumentParser
|
|
9
|
+
from pyxcp.daq_stim import DaqList, DaqRecorder, DaqToCsv, load_daq_lists_from_json # noqa: F401
|
|
10
|
+
from pyxcp.types import XcpTimeoutError
|
|
11
|
+
|
|
12
|
+
parser = argparse.ArgumentParser(description="XCP DAQ list recorder")
|
|
13
|
+
parser.add_argument(
|
|
14
|
+
"DAQ_configuration_file",
|
|
15
|
+
type=str,
|
|
16
|
+
default=None,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
ap = ArgumentParser(description="XCP DAQ list recorder", user_parser=parser)
|
|
20
|
+
|
|
21
|
+
args = ap.args
|
|
22
|
+
DAQ_LISTS = load_daq_lists_from_json(args.DAQ_configuration_file)
|
|
23
|
+
|
|
24
|
+
# daq_parser = DaqToCsv(DAQ_LISTS) # Record to CSV file(s).
|
|
25
|
+
daq_parser = DaqRecorder(DAQ_LISTS, "run_daq_21092025_01", 8) # Record to ".xmraw" file.
|
|
26
|
+
|
|
27
|
+
with ap.run(policy=daq_parser) as x:
|
|
28
|
+
try:
|
|
29
|
+
x.connect()
|
|
30
|
+
except XcpTimeoutError:
|
|
31
|
+
sys.exit(2)
|
|
32
|
+
|
|
33
|
+
if x.slaveProperties.optionalCommMode:
|
|
34
|
+
x.getCommModeInfo()
|
|
35
|
+
|
|
36
|
+
x.cond_unlock("DAQ") # DAQ resource is locked in many cases.
|
|
37
|
+
|
|
38
|
+
print("setup DAQ lists.")
|
|
39
|
+
daq_parser.setup() # Execute setup procedures.
|
|
40
|
+
print("start DAQ lists.")
|
|
41
|
+
daq_parser.start() # Start DAQ lists.
|
|
42
|
+
|
|
43
|
+
time.sleep(0.25 * 60.0 * 60.0) # Run for 15 minutes.
|
|
44
|
+
|
|
45
|
+
print("Stop DAQ....")
|
|
46
|
+
daq_parser.stop() # Stop DAQ lists.
|
|
47
|
+
print("finalize DAQ lists.\n")
|
|
48
|
+
x.disconnect()
|
|
49
|
+
|
|
50
|
+
if hasattr(daq_parser, "files"): # `files` attribute is specific to `DaqToCsv`.
|
|
51
|
+
print("Data written to:")
|
|
52
|
+
print("================")
|
|
53
|
+
for fl in daq_parser.files.values():
|
|
54
|
+
print(fl.name)
|
pyxcp/transport/hdf5_policy.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
|
|
3
|
+
import datetime
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
from typing import List, Dict
|
|
5
6
|
|
|
6
7
|
import h5py
|
|
7
8
|
import numpy as np
|
|
8
9
|
from pyxcp.daq_stim import DaqOnlinePolicy, DaqList
|
|
9
|
-
|
|
10
|
+
from pyxcp import __version__ as pyxcp_version
|
|
10
11
|
|
|
11
12
|
BATCH_SIZE = 4096
|
|
12
13
|
|
|
@@ -25,6 +26,21 @@ MAP_TO_NP = {
|
|
|
25
26
|
"BF16": np.float16,
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
MAP_TO_ASAM_HO = {
|
|
30
|
+
"U8": "A_UINT8",
|
|
31
|
+
"I8": "A_INT8",
|
|
32
|
+
"U16": "A_UINT16",
|
|
33
|
+
"I16": "A_INT16",
|
|
34
|
+
"U32": "A_UINT32",
|
|
35
|
+
"I32": "A_INT32",
|
|
36
|
+
"U64": "A_UINT64",
|
|
37
|
+
"I64": "A_INT64",
|
|
38
|
+
"F32": "A_FLOAT32",
|
|
39
|
+
"F64": "A_FLOAT64",
|
|
40
|
+
"F16": "A_FLOAT16",
|
|
41
|
+
"BF16": "A_FLOAT16",
|
|
42
|
+
}
|
|
43
|
+
|
|
28
44
|
|
|
29
45
|
class BufferedDataset:
|
|
30
46
|
def __init__(self, dataset: h5py.Dataset):
|
|
@@ -72,22 +88,35 @@ class DatasetGroup:
|
|
|
72
88
|
|
|
73
89
|
|
|
74
90
|
def create_timestamp_column(hdf_file: h5py.File, group_name: str, num: int) -> h5py.Dataset:
|
|
75
|
-
|
|
91
|
+
result = hdf_file.create_dataset(
|
|
76
92
|
f"/{group_name}/timestamp{num}",
|
|
77
93
|
shape=(0,),
|
|
78
94
|
maxshape=(None,),
|
|
79
95
|
dtype=np.uint64,
|
|
80
96
|
chunks=True,
|
|
81
97
|
)
|
|
98
|
+
result.attrs["asam_data_type"] = "A_UINT64"
|
|
99
|
+
result.attrs["resolution"] = ("1 nanosecond",)
|
|
100
|
+
return result
|
|
82
101
|
|
|
83
102
|
|
|
84
103
|
class Hdf5OnlinePolicy(DaqOnlinePolicy):
|
|
85
|
-
def __init__(self, file_name: str | Path, daq_lists: List[DaqList]):
|
|
104
|
+
def __init__(self, file_name: str | Path, daq_lists: List[DaqList], **metadata):
|
|
86
105
|
super().__init__(daq_lists=daq_lists)
|
|
87
106
|
path = Path(file_name)
|
|
88
107
|
if path.suffix != ".h5":
|
|
89
108
|
path = path.with_suffix(".h5")
|
|
90
109
|
self.hdf = h5py.File(path, "w", libver="latest")
|
|
110
|
+
self.metadata = self.set_metadata(**metadata)
|
|
111
|
+
|
|
112
|
+
def set_metadata(self, **metadata):
|
|
113
|
+
basic = {
|
|
114
|
+
"tool_name": "pyXCP",
|
|
115
|
+
"tool_version": f"{pyxcp_version}",
|
|
116
|
+
"created": f"{datetime.datetime.now().astimezone().isoformat()}",
|
|
117
|
+
}
|
|
118
|
+
for k, v in (basic | metadata).items():
|
|
119
|
+
self.hdf.attrs[k] = v
|
|
91
120
|
|
|
92
121
|
def initialize(self):
|
|
93
122
|
self.log.debug("Hdf5OnlinePolicy::Initialize()")
|
|
@@ -95,7 +124,12 @@ class Hdf5OnlinePolicy(DaqOnlinePolicy):
|
|
|
95
124
|
for num, daq_list in enumerate(self.daq_lists):
|
|
96
125
|
if daq_list.stim:
|
|
97
126
|
continue
|
|
98
|
-
self.hdf.create_group(daq_list.name)
|
|
127
|
+
grp = self.hdf.create_group(daq_list.name)
|
|
128
|
+
grp.attrs["event_num"] = daq_list.event_num
|
|
129
|
+
grp.attrs["enable_timestamps"] = daq_list.enable_timestamps
|
|
130
|
+
grp.attrs["prescaler"] = daq_list.prescaler
|
|
131
|
+
grp.attrs["priority"] = daq_list.priority
|
|
132
|
+
grp.attrs["direction"] = "STIM" if daq_list.stim else "DAQ"
|
|
99
133
|
ts0 = BufferedDataset(create_timestamp_column(self.hdf, daq_list.name, 0))
|
|
100
134
|
ts1 = BufferedDataset(create_timestamp_column(self.hdf, daq_list.name, 1))
|
|
101
135
|
meas_map = {m.name: m for m in self.daq_lists[num].measurements}
|
|
@@ -103,12 +137,16 @@ class Hdf5OnlinePolicy(DaqOnlinePolicy):
|
|
|
103
137
|
for name, _ in daq_list.headers:
|
|
104
138
|
meas = meas_map[name]
|
|
105
139
|
dataset = self.hdf.create_dataset(
|
|
106
|
-
f"/{daq_list.name}/{meas.name}",
|
|
140
|
+
f"/{daq_list.name}/{meas.name}/raw",
|
|
107
141
|
shape=(0,),
|
|
108
142
|
maxshape=(None,),
|
|
109
143
|
dtype=MAP_TO_NP[meas.data_type],
|
|
110
144
|
chunks=(1024,),
|
|
111
145
|
)
|
|
146
|
+
sub_group = dataset.parent
|
|
147
|
+
sub_group.attrs["asam_data_type"] = MAP_TO_ASAM_HO.get(meas.data_type, "n/a")
|
|
148
|
+
dataset.attrs["ecu_address"] = meas.address
|
|
149
|
+
dataset.attrs["ecu_address_extension"] = meas.ext
|
|
112
150
|
dsets.append(BufferedDataset(dataset))
|
|
113
151
|
self.datasets[num] = DatasetGroup(ts0_ds=ts0, ts1_ds=ts1, datasets=dsets)
|
|
114
152
|
self.hdf.flush()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
pyxcp/__init__.py,sha256=
|
|
1
|
+
pyxcp/__init__.py,sha256=Bm5vH6ppREERjuTwbs9IGEjoHsSTUs15ypEoXyNb5YM,526
|
|
2
2
|
pyxcp/aml/EtasCANMonitoring.a2l,sha256=EJYwe3Z3H24vyWAa6lUgcdKnQY8pwFxjyCN6ZU1ST8w,1509
|
|
3
3
|
pyxcp/aml/EtasCANMonitoring.aml,sha256=xl0DdyeiIaLW0mmmJNAyJS0CQdOLSxt9dxfgrdSlU8Y,2405
|
|
4
4
|
pyxcp/aml/ifdata_CAN.a2l,sha256=NCUnCUEEgRbZYSLGtUGwL2e7zJ8hrp0SbmLHGv8uY58,612
|
|
@@ -15,10 +15,10 @@ pyxcp/aml/XCPonUSB.aml,sha256=Xcu52ZckyuEX0v5rwYQxz8gJCAs4qyepXmd_bkCJVlA,4953
|
|
|
15
15
|
pyxcp/asam/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
pyxcp/asam/types.py,sha256=_gKcpBF5mon_SDWZBUW0PGBMcb37yrvhhEuk1wslg-s,2441
|
|
17
17
|
pyxcp/asamkeydll.c,sha256=dVEvU0S1kgIo62S0La-T8xHSw668LM_DYc_fiQ0No6g,2952
|
|
18
|
-
pyxcp/asamkeydll.exe,sha256=
|
|
18
|
+
pyxcp/asamkeydll.exe,sha256=7m3EYufxBx3y-tz_ACPqHnd-vr-Ab8B7JkCHcjf_FPk,11264
|
|
19
19
|
pyxcp/asamkeydll.sh,sha256=DC2NKUMwvi39OQgJ6514Chr4wc1LYbTmQHmMq9jAHHs,59
|
|
20
20
|
pyxcp/checksum.py,sha256=hO2JW_eiO9I0A4eiqovMV9d_y5oidq_w8jKdAE4FeOo,11899
|
|
21
|
-
pyxcp/cmdline.py,sha256=
|
|
21
|
+
pyxcp/cmdline.py,sha256=PltxEwPp6KnXkStI3u3_K9fLNAfCDQauIxMktMzMhxA,2357
|
|
22
22
|
pyxcp/config/__init__.py,sha256=kZ-6hotQYuVa4C6cEGUSqga6CTezKCC2HRa89yVQtXM,48272
|
|
23
23
|
pyxcp/config/legacy.py,sha256=4QdDheX8DbBKv5JVT72_C_cjCgKvZmhN3tJ6hsvBEtI,5220
|
|
24
24
|
pyxcp/constants.py,sha256=9yGfujC0ImTYQWfn41wyw8pluJTSrhMGWIVeIZTgsLg,1160
|
|
@@ -26,27 +26,27 @@ pyxcp/cpp_ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
26
26
|
pyxcp/cpp_ext/aligned_buffer.hpp,sha256=KoUYDjvIJRc2IDOSQXbbSfQ6pdhnBcCi_bxZFC9C6Ko,5448
|
|
27
27
|
pyxcp/cpp_ext/bin.hpp,sha256=WF7ljBEbATQ3wplk7pna4qWtM0MJVHRs5pnILxfkbGU,2673
|
|
28
28
|
pyxcp/cpp_ext/blockmem.hpp,sha256=ysaJwmTWGTfE54Outk3gJYOfAVFd_QaonBMtXLcXwCc,1242
|
|
29
|
-
pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd,sha256=
|
|
30
|
-
pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd,sha256=
|
|
31
|
-
pyxcp/cpp_ext/cpp_ext.cp312-win_amd64.pyd,sha256=
|
|
32
|
-
pyxcp/cpp_ext/cpp_ext.cp313-win_amd64.pyd,sha256=
|
|
29
|
+
pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd,sha256=oxbCxPamWQByLooFc2PAnP_1JVtV-WvsWhNv1g5-kU8,342528
|
|
30
|
+
pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd,sha256=8x-Ymd8Ek7CftpyKM9KWCAETzNz7_8Rh4_wfSOLnVKM,344576
|
|
31
|
+
pyxcp/cpp_ext/cpp_ext.cp312-win_amd64.pyd,sha256=6o16PiwJffaKI_GXaO1zSh4GfcmdCFFsY3vD5nMBuxw,351232
|
|
32
|
+
pyxcp/cpp_ext/cpp_ext.cp313-win_amd64.pyd,sha256=JoCqAjBO2804zgWVwe76RUKbNQY8lre8kgzHGP4Drls,351232
|
|
33
33
|
pyxcp/cpp_ext/daqlist.hpp,sha256=Dv5v9JvaP3Xhe4uTrYfdBsySElIRO50H9Bu4Xl92yfQ,13996
|
|
34
34
|
pyxcp/cpp_ext/event.hpp,sha256=Z-1yxsEKsr81NnLVEWJ2ANA8FV7YsM7EbNxaw-elheE,1200
|
|
35
|
-
pyxcp/cpp_ext/extension_wrapper.cpp,sha256=
|
|
35
|
+
pyxcp/cpp_ext/extension_wrapper.cpp,sha256=TRrhjinnKkaH9wcY9Tx16kMoVEwSwAFoRVZ2Uot1hao,9852
|
|
36
36
|
pyxcp/cpp_ext/framing.hpp,sha256=8k2juQO0FJvMIiEXjZRMh4CtJdjRBBgH2N3CY57hbyY,11660
|
|
37
37
|
pyxcp/cpp_ext/helper.hpp,sha256=ONAsVupIqqmNDp8bgGWS0TfSYeCFkk3kwwZbbqsh0HQ,7813
|
|
38
38
|
pyxcp/cpp_ext/mcobject.hpp,sha256=t_sjka8_TaWF0EG7mIx8feWAF6uf_CyMtuvCmhE4DB4,6522
|
|
39
39
|
pyxcp/cpp_ext/sxi_framing.hpp,sha256=FvaDOFD5zK8AJUn6yBVoTr-pclstmr478_q_W6COANo,11837
|
|
40
40
|
pyxcp/cpp_ext/tsqueue.hpp,sha256=FWMemzXNgV5dQ7gYmTCzC0QYfgl0VI9JCybYelBcCHU,1026
|
|
41
|
-
pyxcp/daq_stim/__init__.py,sha256=
|
|
41
|
+
pyxcp/daq_stim/__init__.py,sha256=mWHeLkq9fuoylNypGz_CCKShYN_3c3Su6IEB76Z4U2M,16509
|
|
42
42
|
pyxcp/daq_stim/optimize/__init__.py,sha256=FUWK0GkNpNT-sUlhibp7xa2aSYpm6Flh5yA2w2IOJqg,2520
|
|
43
43
|
pyxcp/daq_stim/optimize/binpacking.py,sha256=RcRTMNmcb5oIAY2G5RHygb_g0GgNf35-cp3utIeUA9w,1257
|
|
44
44
|
pyxcp/daq_stim/scheduler.cpp,sha256=uUR4RUpukE5qZpJNbT_1ARFslAbWupGv0TQJHO_OM0s,1466
|
|
45
45
|
pyxcp/daq_stim/scheduler.hpp,sha256=U_6tUbebmzX5vVZS0EFSgTaPsyxMg6yRXHG_aPWA0x4,1884
|
|
46
|
-
pyxcp/daq_stim/stim.cp310-win_amd64.pyd,sha256=
|
|
47
|
-
pyxcp/daq_stim/stim.cp311-win_amd64.pyd,sha256=
|
|
48
|
-
pyxcp/daq_stim/stim.cp312-win_amd64.pyd,sha256=
|
|
49
|
-
pyxcp/daq_stim/stim.cp313-win_amd64.pyd,sha256=
|
|
46
|
+
pyxcp/daq_stim/stim.cp310-win_amd64.pyd,sha256=HURS8tDC0S4JggbfuEiTvsGN3Gsgb2tLn_D1DpnyAcA,208896
|
|
47
|
+
pyxcp/daq_stim/stim.cp311-win_amd64.pyd,sha256=eQtJ1HMQ07UJsZHzOZLreonxBg6PUooe3wveagBC_5k,210432
|
|
48
|
+
pyxcp/daq_stim/stim.cp312-win_amd64.pyd,sha256=TsjOX1kV4IGmo33aExy8XMd5irjZqcKYaa-VMP0U8sI,214528
|
|
49
|
+
pyxcp/daq_stim/stim.cp313-win_amd64.pyd,sha256=6z9yU9qUNAq0JboTFnCV3Y-k55lPfmwwEmJH2atFKY0,214528
|
|
50
50
|
pyxcp/daq_stim/stim.cpp,sha256=F2OG67W4KKwTTiUCxm-9egIv3TLFdOkRunX6xf7YOtc,177
|
|
51
51
|
pyxcp/daq_stim/stim.hpp,sha256=U-uInRrA6OCdMl1l1SWbQ_KEPpnNYrWut924IvbW6R0,18508
|
|
52
52
|
pyxcp/daq_stim/stim_wrapper.cpp,sha256=iT2yxJ3LRG7HoYC1bwhM3tCAxF9X_HHierBNsLRmTJg,1995
|
|
@@ -69,7 +69,7 @@ pyxcp/examples/xcphello.py,sha256=6hLOzeqPyNERxQn94_Vup87FbGeRjmjPBe4ZLl6tkmU,23
|
|
|
69
69
|
pyxcp/examples/xcphello_recorder.py,sha256=c7ldGXpjyHe7DCit_S8D5AkqVX81pleLEvLDugcdCeU,3409
|
|
70
70
|
pyxcp/master/__init__.py,sha256=RbMGgWZWRMEpembwgV-kkdSfQxuUZeXsybcspAhMzj0,320
|
|
71
71
|
pyxcp/master/errorhandler.py,sha256=Hyn6geDgrH7EJdpgPWuQYbe_fDOQ2zzYFqRnHFny1Fw,26628
|
|
72
|
-
pyxcp/master/master.py,sha256=
|
|
72
|
+
pyxcp/master/master.py,sha256=DgAUzBo2RnglbUWxdwPGnuJ8mbN1y27vRu0WlewYTrk,101515
|
|
73
73
|
pyxcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
74
74
|
pyxcp/recorder/.idea/.gitignore,sha256=G_3s42Re2O01YDDyLMIATcP0Af8GCsPSTegRw7zYLhY,184
|
|
75
75
|
pyxcp/recorder/.idea/misc.xml,sha256=XfcpM2YHByf1o3XaftWMr5UIaGSVc9LMzRnZmUp1ynM,142
|
|
@@ -99,10 +99,10 @@ pyxcp/recorder/mio.hpp,sha256=5ASJLKSEykH0deAQD5uak-_yAgd5p2n8t06315GSGrg,63346
|
|
|
99
99
|
pyxcp/recorder/reader.hpp,sha256=ssdaAaG_fHKrJMuMo_tfcCaCjFrIC5HQGNXgR343bVY,5131
|
|
100
100
|
pyxcp/recorder/reco.py,sha256=2CPKxIZNSr6BhjfPrWtxdt81zaJlgU-e73RneG9IsJA,8727
|
|
101
101
|
pyxcp/recorder/recorder.rst,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
102
|
-
pyxcp/recorder/rekorder.cp310-win_amd64.pyd,sha256=
|
|
103
|
-
pyxcp/recorder/rekorder.cp311-win_amd64.pyd,sha256=
|
|
104
|
-
pyxcp/recorder/rekorder.cp312-win_amd64.pyd,sha256=
|
|
105
|
-
pyxcp/recorder/rekorder.cp313-win_amd64.pyd,sha256=
|
|
102
|
+
pyxcp/recorder/rekorder.cp310-win_amd64.pyd,sha256=VAcmnVoAKV0U22EpKVWl3j8mIBJ_IKWH-imcfwt_68E,396800
|
|
103
|
+
pyxcp/recorder/rekorder.cp311-win_amd64.pyd,sha256=JCqn8UGpWFbaNvjWDEowiWK2kX8RFvK8-aTntqrofJ0,398336
|
|
104
|
+
pyxcp/recorder/rekorder.cp312-win_amd64.pyd,sha256=LMusSqBjJ14FhuNhDnN-kT3jcxpY_1dvFGTpNSbk6eA,404480
|
|
105
|
+
pyxcp/recorder/rekorder.cp313-win_amd64.pyd,sha256=fmru0QrN9WOdoanDbGVTIzkqv0f6ffgLuWLVI8MTuJQ,404480
|
|
106
106
|
pyxcp/recorder/rekorder.cpp,sha256=U0LMyk8pZXx9emgS_WPVthvn_9IpgE7JGrh4kg-8CX4,1900
|
|
107
107
|
pyxcp/recorder/rekorder.hpp,sha256=sWvRch9bVt6mmgrFHp5mwWhap7HoFG4geeb7UqEIzio,7638
|
|
108
108
|
pyxcp/recorder/setup.py,sha256=_99XFPQAd5V4LcJaSGJwdnbxgxJ7kl8DEXfHsnKO1Yg,998
|
|
@@ -112,6 +112,7 @@ pyxcp/recorder/wrap.cpp,sha256=oCsEOnRsvLlaWjyN09X7mcHLzzqCyLskREKb6kmyqNE,8707
|
|
|
112
112
|
pyxcp/recorder/writer.hpp,sha256=rNjtRTtJes5z-BzKR2K56P_Kvc9MEVQgycu8J0wKf1g,11284
|
|
113
113
|
pyxcp/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
114
114
|
pyxcp/scripts/pyxcp_probe_can_drivers.py,sha256=P_gscDTAofbSVA_Wd1GATrnyWGTf1-Dz_oPdlRFfjuk,567
|
|
115
|
+
pyxcp/scripts/xcp_daq_recorder.py,sha256=Gwg03TWvqZWPSeynHy0pTqoPL6SmTvNpmg1yd-pcus0,1585
|
|
115
116
|
pyxcp/scripts/xcp_examples.py,sha256=q2wNXHVZu4GjcIlZwp2j9Sqm5QH39Olro4BQaLoIqiM,2583
|
|
116
117
|
pyxcp/scripts/xcp_fetch_a2l.py,sha256=mRS42707lEFjH9q9ip2TgIOstc6QBnZ3IMMkf7GtEtk,1239
|
|
117
118
|
pyxcp/scripts/xcp_id_scanner.py,sha256=zsqjEJko8OtzRtHZT6YVVanD7hbaGPv0qsC_jK1Gzig,419
|
|
@@ -136,12 +137,12 @@ pyxcp/transport/base.py,sha256=Eb5qLeAP-VXQwHcX2M58Rdl0jZ8K_RFYSoE-Pq6kW64,18784
|
|
|
136
137
|
pyxcp/transport/base_transport.hpp,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
137
138
|
pyxcp/transport/can.py,sha256=JeASLHW2A66Zaq6X5XG9vdfX-eXdhWbttbaMR0Zow20,24032
|
|
138
139
|
pyxcp/transport/eth.py,sha256=8QRzHIQIzzM9T5fbAIMk7FLSQLkMsCJa3UPW_61rXDw,10530
|
|
139
|
-
pyxcp/transport/hdf5_policy.py,sha256=
|
|
140
|
+
pyxcp/transport/hdf5_policy.py,sha256=KIewRq5AI-EPNPzw-MHb5lriF-K4Jt5cuaxYFvreonU,5544
|
|
140
141
|
pyxcp/transport/sxi.py,sha256=P3ppV-MzuvLMGPldm8sB_nXKyTCRJeqraQj8yzRwmqI,7379
|
|
141
|
-
pyxcp/transport/transport_ext.cp310-win_amd64.pyd,sha256=
|
|
142
|
-
pyxcp/transport/transport_ext.cp311-win_amd64.pyd,sha256=
|
|
143
|
-
pyxcp/transport/transport_ext.cp312-win_amd64.pyd,sha256=
|
|
144
|
-
pyxcp/transport/transport_ext.cp313-win_amd64.pyd,sha256=
|
|
142
|
+
pyxcp/transport/transport_ext.cp310-win_amd64.pyd,sha256=T3jOQqkf_RrbIX1KXuJl2XshwBT0ckZzJMRoMikMfC4,386048
|
|
143
|
+
pyxcp/transport/transport_ext.cp311-win_amd64.pyd,sha256=Lq5_QlaQb0_wjkWVOe7oxdNVlDNeDHdmrpmpi0bb8tc,388096
|
|
144
|
+
pyxcp/transport/transport_ext.cp312-win_amd64.pyd,sha256=pnjkJiLbmrK_rHa67MZnyyBYV5KtORpxBojHz50Q0kE,395776
|
|
145
|
+
pyxcp/transport/transport_ext.cp313-win_amd64.pyd,sha256=XRMdq2FEYFDAFYRO31G1zwtb_mLxdtQZyLAghNonpmM,396288
|
|
145
146
|
pyxcp/transport/transport_ext.hpp,sha256=ABxcvoDPua_IUJ9NhrmxcSoTr3ofLVXlezHtN_bHY5w,6511
|
|
146
147
|
pyxcp/transport/transport_wrapper.cpp,sha256=fJmsiGrH4WZvDri2rJpwTosTHTqlANpWi4kHu7vda8M,12485
|
|
147
148
|
pyxcp/transport/usb_transport.py,sha256=K_tAESxgSVllJinoYanJbFB_j28yOId6m5EgdXvPItQ,8902
|
|
@@ -150,8 +151,8 @@ pyxcp/utils/__init__.py,sha256=d4QmrEZiK7xtdCThhZapV2Zbyi0YB_ELNDL49mkji5Y,3509
|
|
|
150
151
|
pyxcp/utils/cli.py,sha256=BnwQvMk8GERns4B-2I0hDuBk9pE-krc_o36NkBsezB8,3027
|
|
151
152
|
pyxcp/vector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
152
153
|
pyxcp/vector/map.py,sha256=7Gnhvr79geMeqqGVIJPxODXGwABdNDinnqzhpooN5TE,2306
|
|
153
|
-
pyxcp-0.25.
|
|
154
|
-
pyxcp-0.25.
|
|
155
|
-
pyxcp-0.25.
|
|
156
|
-
pyxcp-0.25.
|
|
157
|
-
pyxcp-0.25.
|
|
154
|
+
pyxcp-0.25.8.dist-info/entry_points.txt,sha256=LkHsEwubm30s4oiyCy0cKj6k97ALvQ6KjAVdyEcqu7g,358
|
|
155
|
+
pyxcp-0.25.8.dist-info/licenses/LICENSE,sha256=fTqV5eBpeAZO0_jit8j4Ref9ikBSlHJ8xwj5TLg7gFk,7817
|
|
156
|
+
pyxcp-0.25.8.dist-info/METADATA,sha256=RsFpqcTgWLDZcfvJlhNtnrEZprtf9LSfpJW6FbysG8E,12775
|
|
157
|
+
pyxcp-0.25.8.dist-info/WHEEL,sha256=mbhp6OISYNyQV0z23S-pvC1L-suhijlWHyj3c994WU4,98
|
|
158
|
+
pyxcp-0.25.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|