Conversation
Allow callers to choose between 'absolute' (default, existing behaviour) and 'relative' when creating an ASC log file. The value is written into the 'base hex timestamps ...' header line so that other tools (CANalyzer, CANoe, etc.) can interpret the file correctly. Closes hardbyte#2022
|
You're changing the header, but not the actual timestamps. According to the documentation that is not correct:
|
|
Thank you for the helpful feedback! I'll revisit the implementation and make sure the timestamp values are properly converted as well. |
…ust header Previously, log_event() always subtracted self.started from every timestamp regardless of timestamps_format, meaning "relative" mode only changed the header line while writing identical data to "absolute" mode. Per the ASC format specification: - "absolute": each timestamp is an offset from the start of measurement - "relative": each timestamp is a delta from the preceding event Fix log_event() to compute per-event deltas when timestamps_format="relative", and update self.last_timestamp after each event so the next delta is correct. Also add two tests that verify the actual values written to the file differ between the two modes (3-message uneven spacing exposes the distinction at msg3: absolute writes 1.0, relative writes 0.7). Update changelog fragment to describe the semantic difference accurately.
test/logformats_test.py
Outdated
| for m in msgs: | ||
| writer.on_message_received(m) | ||
|
|
||
| with can.ASCReader(self.test_file_name, relative_timestamp=True) as reader: |
There was a problem hiding this comment.
Instantiate the ASCReader with relative_timestamp=False. For the roundtrip tests i'd prefer to see the same timestamps as in the original messages.
can/io/asc.py
Outdated
| self, | ||
| file: StringPathLike | TextIO, | ||
| channel: int = 1, | ||
| timestamps_format: str = "absolute", |
There was a problem hiding this comment.
| timestamps_format: str = "absolute", | |
| timestamps_format: Literal["absolute", "relative"] = "absolute", |
can/io/asc.py
Outdated
| if self.timestamps_format == "absolute": | ||
| # offsets from the start of measurement | ||
| written_timestamp = ( | ||
| timestamp - self.started if timestamp >= self.started else timestamp |
There was a problem hiding this comment.
I'd simplify this: You can move timestamp = max(timestamp, self.last_timestamp) out of the if-clause.
Then inside of the if-else blocks you only have written_timestamp = timestamp - self.started and written_timestamp = timestamp - self.last_timestamp
Reviewer feedback received (zariiii9003):
1. Use Literal type hint for timestamps_format parameter
- Changed: timestamps_format: str = "absolute"
- To: timestamps_format: Literal["absolute", "relative"] = "absolute"
- Added Literal to typing imports
2. Simplify log_event timestamp computation
- Moved monotonic clamp out of if/else blocks:
timestamp = max(timestamp, self.last_timestamp)
- Each branch now contains only simple arithmetic:
absolute: written_timestamp = timestamp - self.started
relative: written_timestamp = timestamp - self.last_timestamp
3. Use relative_timestamp=False in roundtrip tests
- Updated test_write_relative_timestamp_roundtrip and
test_write_absolute_timestamps_are_offsets_from_start to use
relative_timestamp=False so assertions verify original message
timestamps are recovered (100.0, 100.3, 101.0) rather than
file-stored offsets (0.0, 0.3, 1.0)
Additional issues found and fixed during review:
4. Removed outdated TODO comment in ASCReader
- Removed: "TODO - what is this used for? The ASC Writer only prints
absolute" — no longer accurate since ASCWriter now supports both
"absolute" and "relative" formats
5. Lowered assertAlmostEqual precision from places=5 to places=3
- The datetime triggerblock roundtrip (fromtimestamp -> strftime ->
strptime -> timestamp) only preserves millisecond precision due to
the ".NNN" format. places=5 (5 microseconds) is stricter than what
the format can guarantee; places=3 (0.5 ms) correctly reflects the
actual precision limit. Verified empirically: sub-millisecond
timestamps incur ~0.456 ms error which passes places=3 but fails
places=5.
6. Updated docstrings for both modified roundtrip tests to accurately
describe the new assertion semantics (original timestamp recovery)
|
The CI failures appear to be caused by a coveralls.io outage that has been ongoing since February 25th. I'll retry once the service is restored. Please let me know if there are any other parts of the implementation that need to be reviewed. Thank you for your feedback! |
Summary of Changes
timestamps_formatparameter toASCWriter.__init__()("absolute"or"relative", default"absolute")base hex timestamps ...header line so external tools (CANalyzer, CANoe, etc.) can interpret the file correctlyValueErrorfor unsupported values"absolute"Related Issues / Pull Requests
Type of Change
Checklist
tox).Additional Notes
The
timestamps_formatparameter only affects the header line.The actual per-message timestamp values written by
on_message_received()are not modified — callers are responsible for passing appropriately scaled timestamps.