diff --git a/can/io/logger.py b/can/io/logger.py index 320c0a68b..a8757f7ee 100644 --- a/can/io/logger.py +++ b/can/io/logger.py @@ -29,6 +29,8 @@ from .sqlite import SqliteWriter from .trc import TRCWriter +#: A map of file suffixes to their corresponding +#: :class:`can.io.generic.MessageWriter` class MESSAGE_WRITERS: Final[Dict[str, Type[MessageWriter]]] = { ".asc": ASCWriter, ".blf": BLFWriter, @@ -85,8 +87,8 @@ def _compress( def Logger(filename: Optional[StringPathLike], **kwargs: Any) -> MessageWriter: - """ - Logs CAN messages to a file. + """Find and return the appropriate :class:`~can.io.generic.MessageWriter` instance + for a given file suffix. The format is determined from the file suffix which can be one of: * .asc: :class:`can.ASCWriter` diff --git a/can/io/player.py b/can/io/player.py index aec756450..1109e1979 100644 --- a/can/io/player.py +++ b/can/io/player.py @@ -30,6 +30,8 @@ from .sqlite import SqliteReader from .trc import TRCReader +#: A map of file suffixes to their corresponding +#: :class:`can.io.generic.MessageReader` class MESSAGE_READERS: Final[Dict[str, Type[MessageReader]]] = { ".asc": ASCReader, ".blf": BLFReader, @@ -77,8 +79,8 @@ def _get_logger_for_suffix(suffix: str) -> Type[MessageReader]: def LogReader(filename: StringPathLike, **kwargs: Any) -> MessageReader: - """ - Replay logged CAN messages from a file. + """Find and return the appropriate :class:`~can.io.generic.MessageReader` instance + for a given file suffix. The format is determined from the file suffix which can be one of: * .asc @@ -142,6 +144,16 @@ def __init__( as the time between messages. :param gap: Minimum time between sent messages in seconds :param skip: Skip periods of inactivity greater than this (in seconds). + + Example:: + + import can + + with can.LogReader("my_logfile.asc") as reader, can.Bus(interface="virtual") as bus: + for msg in can.MessageSync(messages=reader): + print(msg) + bus.send(msg) + """ self.raw_messages = messages self.timestamps = timestamps diff --git a/doc/api.rst b/doc/api.rst index 053bd34a4..50095589c 100644 --- a/doc/api.rst +++ b/doc/api.rst @@ -10,11 +10,12 @@ A form of CAN interface is also required. .. toctree:: - :maxdepth: 1 + :maxdepth: 2 bus message - listeners + notifier + file_io asyncio bcm errors diff --git a/doc/development.rst b/doc/development.rst index fb717a52d..a5cf06f30 100644 --- a/doc/development.rst +++ b/doc/development.rst @@ -9,7 +9,7 @@ Contribute to source code, documentation, examples and report issues: https://github.com/hardbyte/python-can Note that the latest released version on PyPi may be significantly behind the -``develop`` branch. Please open any feature requests against the ``develop`` branch +``main`` branch. Please open any feature requests against the ``main`` branch There is also a `python-can `__ mailing list for development discussion. @@ -100,7 +100,7 @@ The modules in ``python-can`` are: +---------------------------------+------------------------------------------------------+ |:doc:`message ` | Contains the interface independent Message object. | +---------------------------------+------------------------------------------------------+ -|:doc:`io ` | Contains a range of file readers and writers. | +|:doc:`io ` | Contains a range of file readers and writers. | +---------------------------------+------------------------------------------------------+ |:doc:`broadcastmanager ` | Contains interface independent broadcast manager | | | code. | diff --git a/doc/listeners.rst b/doc/file_io.rst similarity index 65% rename from doc/listeners.rst rename to doc/file_io.rst index 110e960d3..ff9431695 100644 --- a/doc/listeners.rst +++ b/doc/file_io.rst @@ -1,110 +1,20 @@ +File IO +======= -Reading and Writing Messages -============================ -.. _notifier: - -Notifier --------- - -The Notifier object is used as a message distributor for a bus. Notifier creates a thread to read messages from the bus and distributes them to listeners. - -.. autoclass:: can.Notifier - :members: - -.. _listeners_doc: - -Listener --------- - -The Listener class is an "abstract" base class for any objects which wish to -register to receive notifications of new messages on the bus. A Listener can -be used in two ways; the default is to **call** the Listener with a new -message, or by calling the method **on_message_received**. - -Listeners are registered with :ref:`notifier` object(s) which ensure they are -notified whenever a new message is received. - -.. literalinclude:: ../examples/print_notifier.py - :language: python - :linenos: - :emphasize-lines: 8,9 - - -Subclasses of Listener that do not override **on_message_received** will cause -:class:`NotImplementedError` to be thrown when a message is received on -the CAN bus. - -.. autoclass:: can.Listener - :members: - -There are some listeners that already ship together with `python-can` -and are listed below. -Some of them allow messages to be written to files, and the corresponding file -readers are also documented here. - -.. note :: - - Please note that writing and the reading a message might not always yield a - completely unchanged message again, since some properties are not (yet) - supported by some file formats. - -.. note :: - - Additional file formats for both reading/writing log files can be added via - a plugin reader/writer. An external package can register a new reader - by using the ``can.io.message_reader`` entry point. Similarly, a writer can - be added using the ``can.io.message_writer`` entry point. - - The format of the entry point is ``reader_name=module:classname`` where ``classname`` - is a :class:`can.io.generic.BaseIOHandler` concrete implementation. - - :: - - entry_points={ - 'can.io.message_reader': [ - '.asc = my_package.io.asc:ASCReader' - ] - }, - - -BufferedReader --------------- - -.. autoclass:: can.BufferedReader - :members: - -.. autoclass:: can.AsyncBufferedReader - :members: - - -RedirectReader --------------- - -.. autoclass:: can.RedirectReader - :members: - - -Logger ------- - -The :class:`can.Logger` uses the following :class:`can.Listener` types to -create log files with different file types of the messages received. - -.. autoclass:: can.Logger - :members: - -.. autoclass:: can.io.BaseRotatingLogger - :members: - -.. autoclass:: can.SizedRotatingLogger - :members: +Reading and Writing Files +------------------------- +.. autofunction:: can.LogReader +.. autofunction:: can.Logger +.. autodata:: can.io.logger.MESSAGE_WRITERS +.. autodata:: can.io.player.MESSAGE_READERS Printer ------- .. autoclass:: can.Printer + :show-inheritance: :members: @@ -112,9 +22,11 @@ CSVWriter --------- .. autoclass:: can.CSVWriter + :show-inheritance: :members: .. autoclass:: can.CSVReader + :show-inheritance: :members: @@ -122,9 +34,11 @@ SqliteWriter ------------ .. autoclass:: can.SqliteWriter + :show-inheritance: :members: .. autoclass:: can.SqliteReader + :show-inheritance: :members: @@ -164,6 +78,7 @@ engineered from existing log files. One description of the format can be found ` .. autoclass:: can.ASCWriter + :show-inheritance: :members: ASCReader reads CAN data from ASCII log files .asc, @@ -172,6 +87,7 @@ as further references can-utils can be used: `log2asc `_. .. autoclass:: can.ASCReader + :show-inheritance: :members: @@ -185,11 +101,13 @@ As specification following references can-utils can be used: .. autoclass:: can.CanutilsLogWriter + :show-inheritance: :members: **CanutilsLogReader** reads CAN data from ASCII log files .log .. autoclass:: can.CanutilsLogReader + :show-inheritance: :members: @@ -204,11 +122,13 @@ The data is stored in a compressed format which makes it very compact. .. note:: Channels will be converted to integers. .. autoclass:: can.BLFWriter + :show-inheritance: :members: The following class can be used to read messages from BLF file: .. autoclass:: can.BLFReader + :show-inheritance: :members: @@ -229,6 +149,7 @@ The data is stored in a compressed format which makes it compact. .. autoclass:: can.MF4Writer + :show-inheritance: :members: The MDF format is very flexible regarding the internal structure and it is used to handle data from multiple sources, not just CAN bus logging. @@ -239,6 +160,7 @@ Therefor MF4Reader can only replay files created with MF4Writer. The following class can be used to read messages from MF4 file: .. autoclass:: can.MF4Reader + :show-inheritance: :members: @@ -252,9 +174,31 @@ Implements basic support for the TRC file format. Comments and contributions are welcome on what file versions might be relevant. .. autoclass:: can.TRCWriter + :show-inheritance: :members: The following class can be used to read messages from TRC file: .. autoclass:: can.TRCReader + :show-inheritance: + :members: + + +Rotating Loggers +---------------- + +.. autoclass:: can.io.BaseRotatingLogger + :show-inheritance: + :members: + +.. autoclass:: can.SizedRotatingLogger + :show-inheritance: :members: + + +Replaying Files +--------------- + +.. autoclass:: can.MessageSync + :members: + diff --git a/doc/internal-api.rst b/doc/internal-api.rst index f4b6f875a..73984bf1a 100644 --- a/doc/internal-api.rst +++ b/doc/internal-api.rst @@ -127,6 +127,7 @@ IO Utilities .. automodule:: can.io.generic :members: + :member-order: bysource diff --git a/doc/notifier.rst b/doc/notifier.rst new file mode 100644 index 000000000..05edbd90d --- /dev/null +++ b/doc/notifier.rst @@ -0,0 +1,86 @@ +Notifier and Listeners +====================== + +.. _notifier: + +Notifier +-------- + +The Notifier object is used as a message distributor for a bus. The Notifier +uses an event loop or creates a thread to read messages from the bus and +distributes them to listeners. + +.. autoclass:: can.Notifier + :members: + +.. _listeners_doc: + +Listener +-------- + +The Listener class is an "abstract" base class for any objects which wish to +register to receive notifications of new messages on the bus. A Listener can +be used in two ways; the default is to **call** the Listener with a new +message, or by calling the method **on_message_received**. + +Listeners are registered with :ref:`notifier` object(s) which ensure they are +notified whenever a new message is received. + +.. literalinclude:: ../examples/print_notifier.py + :language: python + :linenos: + :emphasize-lines: 8,9 + + +Subclasses of Listener that do not override **on_message_received** will cause +:class:`NotImplementedError` to be thrown when a message is received on +the CAN bus. + +.. autoclass:: can.Listener + :members: + +There are some listeners that already ship together with `python-can` +and are listed below. +Some of them allow messages to be written to files, and the corresponding file +readers are also documented here. + +.. note :: + + Please note that writing and the reading a message might not always yield a + completely unchanged message again, since some properties are not (yet) + supported by some file formats. + +.. note :: + + Additional file formats for both reading/writing log files can be added via + a plugin reader/writer. An external package can register a new reader + by using the ``can.io.message_reader`` entry point. Similarly, a writer can + be added using the ``can.io.message_writer`` entry point. + + The format of the entry point is ``reader_name=module:classname`` where ``classname`` + is a :class:`can.io.generic.BaseIOHandler` concrete implementation. + + :: + + entry_points={ + 'can.io.message_reader': [ + '.asc = my_package.io.asc:ASCReader' + ] + }, + + +BufferedReader +-------------- + +.. autoclass:: can.BufferedReader + :members: + +.. autoclass:: can.AsyncBufferedReader + :members: + + +RedirectReader +-------------- + +.. autoclass:: can.RedirectReader + :members: