Skip to content

Commit d7d617b

Browse files
driftregiondanielhriscafelixdivozariiii9003hardbyte
authored
Add MF4 support (#1289)
* add extra dependency * add mf4 io writer * update asammdf requirement * changes after initial review * simplify append call * add MF4Reader class * start testing * passes tests * update documentation * update docs and CI scripts * retrigger build * update setup.py according to review * remove debug save file * changes after review * updates after review * add cython requirement * fixes after review: * fix documentation * fix item access on FD_DLC2LEN dict * add compression argument to MF4Writer stop method * add MF4Writer and MF4Reader to logger and player modules * reformat and change setup.py accordingly * cleanup test file * cleanup docs * cleanups and fix linter problems * re-add change to can.io.Logger; it somehow went lost while rebasing * remove leftover __future__ import * fix typing error in can.io's player.py and logger.py * remove diff noise, remove deprecated appveyor CI * run black * Fix import errors * add acquisition source needed by asammdf to extract bus logging * use correct source type, add md5 digest required by asammdf * refactor test_extension_matching tests to use explicit extensions * satiate mypy * update mf4 implementation * fix AttributeError * format black * refactoring * fix bugs and add direction support * add timestamps to avoid ambiguity * set allowed_timestamp_delta to 1e-4 * read into BytesIO * Add restriction to docstring * implement file_size * constrain mf4 dependencies to pass CI tests * format docstring * add mf4 extra * Update doc/listeners.rst * Remove platform specifiers for asammdf * Format code with black * remove unnecessary parenthesis * install asammdf only for CPython <= 3.12 * fix NameError --------- Co-authored-by: danielhrisca <[email protected]> Co-authored-by: Felix Divo <[email protected]> Co-authored-by: zariiii9003 <[email protected]> Co-authored-by: Brian Thorne <[email protected]> Co-authored-by: Brian Thorne <[email protected]> Co-authored-by: hardbyte <[email protected]>
1 parent ccfd7f3 commit d7d617b

File tree

14 files changed

+649
-49
lines changed

14 files changed

+649
-49
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ jobs:
141141
- name: Install dependencies
142142
run: |
143143
python -m pip install --upgrade pip
144-
pip install -e .[canalystii,gs_usb]
144+
pip install -e .[canalystii,gs_usb,mf4]
145145
pip install -r doc/doc-requirements.txt
146146
- name: Build documentation
147147
run: |

.readthedocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ python:
2929
extra_requirements:
3030
- canalystii
3131
- gs_usb
32+
- mf4

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Features
7878
- receiving, sending, and periodically sending messages
7979
- normal and extended arbitration IDs
8080
- `CAN FD <https://en.wikipedia.org/wiki/CAN_FD>`__ support
81-
- many different loggers and readers supporting playback: ASC (CANalyzer format), BLF (Binary Logging Format by Vector), TRC, CSV, SQLite, and Canutils log
81+
- many different loggers and readers supporting playback: ASC (CANalyzer format), BLF (Binary Logging Format by Vector), MF4 (Measurement Data Format v4 by ASAM), TRC, CSV, SQLite, and Canutils log
8282
- efficient in-kernel or in-hardware filtering of messages on supported interfaces
8383
- bus configuration reading from a file or from environment variables
8484
- command line tools for working with CAN buses (see the `docs <https://python-can.readthedocs.io/en/stable/scripts.html>`__)

can/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
"ModifiableCyclicTaskABC",
4242
"Message",
4343
"MessageSync",
44+
"MF4Reader",
45+
"MF4Writer",
4446
"Notifier",
4547
"Printer",
4648
"RedirectReader",
@@ -94,6 +96,8 @@
9496
Logger,
9597
LogReader,
9698
MessageSync,
99+
MF4Reader,
100+
MF4Writer,
97101
Printer,
98102
SizedRotatingLogger,
99103
SqliteReader,

can/io/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
"Logger",
1717
"LogReader",
1818
"MessageSync",
19+
"MF4Reader",
20+
"MF4Writer",
1921
"Printer",
2022
"SizedRotatingLogger",
2123
"SqliteReader",
@@ -36,6 +38,7 @@
3638
from .blf import BLFReader, BLFWriter
3739
from .canutils import CanutilsLogReader, CanutilsLogWriter
3840
from .csv import CSVReader, CSVWriter
41+
from .mf4 import MF4Reader, MF4Writer
3942
from .printer import Printer
4043
from .sqlite import SqliteReader, SqliteWriter
4144
from .trc import TRCFileVersion, TRCReader, TRCWriter

can/io/logger.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from .canutils import CanutilsLogWriter
2222
from .csv import CSVWriter
2323
from .generic import BaseIOHandler, FileIOMessageWriter, MessageWriter
24+
from .mf4 import MF4Writer
2425
from .printer import Printer
2526
from .sqlite import SqliteWriter
2627
from .trc import TRCWriter
@@ -38,6 +39,7 @@ class Logger(MessageWriter):
3839
* .log :class:`can.CanutilsLogWriter`
3940
* .trc :class:`can.TRCWriter`
4041
* .txt :class:`can.Printer`
42+
* .mf4 :class:`can.MF4Writer` (optional, depends on asammdf)
4143
4244
Any of these formats can be used with gzip compression by appending
4345
the suffix .gz (e.g. filename.asc.gz). However, third-party tools might not
@@ -59,6 +61,7 @@ class Logger(MessageWriter):
5961
".csv": CSVWriter,
6062
".db": SqliteWriter,
6163
".log": CanutilsLogWriter,
64+
".mf4": MF4Writer,
6265
".trc": TRCWriter,
6366
".txt": Printer,
6467
}
@@ -68,10 +71,12 @@ def __new__( # type: ignore
6871
cls: Any, filename: Optional[StringPathLike], **kwargs: Any
6972
) -> MessageWriter:
7073
"""
71-
:param filename: the filename/path of the file to write to,
72-
may be a path-like object or None to
73-
instantiate a :class:`~can.Printer`
74-
:raises ValueError: if the filename's suffix is of an unknown file type
74+
:param filename:
75+
the filename/path of the file to write to,
76+
may be a path-like object or None to
77+
instantiate a :class:`~can.Printer`
78+
:raises ValueError:
79+
if the filename's suffix is of an unknown file type
7580
"""
7681
if filename is None:
7782
return Printer(**kwargs)
@@ -92,7 +97,10 @@ def __new__( # type: ignore
9297
suffix, file_or_filename = Logger.compress(filename, **kwargs)
9398

9499
try:
95-
return Logger.message_writers[suffix](file=file_or_filename, **kwargs)
100+
LoggerType = Logger.message_writers[suffix]
101+
if LoggerType is None:
102+
raise ValueError(f'failed to import logger for extension "{suffix}"')
103+
return LoggerType(file=file_or_filename, **kwargs)
96104
except KeyError:
97105
raise ValueError(
98106
f'No write support for this unknown log format "{suffix}"'

0 commit comments

Comments
 (0)