Skip to content

Commit 26fe6f9

Browse files
committed
Add PcapngReader
1 parent def5945 commit 26fe6f9

File tree

4 files changed

+66
-4
lines changed

4 files changed

+66
-4
lines changed

can/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"MessageSync",
4545
"ModifiableCyclicTaskABC",
4646
"Notifier",
47+
"PcapngReader",
4748
"PcapngWriter",
4849
"Printer",
4950
"RedirectReader",
@@ -110,6 +111,7 @@
110111
Logger,
111112
LogReader,
112113
MessageSync,
114+
PcapngReader,
113115
PcapngWriter,
114116
MF4Reader,
115117
MF4Writer,

can/io/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"MF4Reader",
2121
"MF4Writer",
2222
"MessageSync",
23+
"PcapngReader",
2324
"PcapngWriter",
2425
"Printer",
2526
"SizedRotatingLogger",
@@ -53,7 +54,7 @@
5354
from .canutils import CanutilsLogReader, CanutilsLogWriter
5455
from .csv import CSVReader, CSVWriter
5556
from .mf4 import MF4Reader, MF4Writer
56-
from .pcapng import PcapngWriter
57+
from .pcapng import PcapngReader, PcapngWriter
5758
from .printer import Printer
5859
from .sqlite import SqliteReader, SqliteWriter
5960
from .trc import TRCFileVersion, TRCReader, TRCWriter

can/io/pcapng.py

+60-3
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@
77

88
import logging
99

10-
from typing import Any, BinaryIO, Dict, Union
10+
from typing import Any, BinaryIO, Dict, Generator, Union
1111

1212
from ..message import Message
1313
from ..typechecking import StringPathLike, Channel
14-
from .generic import BinaryIOMessageWriter
15-
from ..socketcan_common import build_can_frame, CAN_FRAME_HEADER_STRUCT_BE
14+
from .generic import BinaryIOMessageWriter, BinaryIOMessageReader
15+
from ..socketcan_common import (
16+
build_can_frame,
17+
parse_can_frame,
18+
CAN_FRAME_HEADER_STRUCT_BE,
19+
)
1620

1721
logger = logging.getLogger("can.io.pcapng")
1822

@@ -109,3 +113,56 @@ def on_message_received(self, msg: Message) -> None:
109113
endianness=">", # big
110114
)
111115
)
116+
117+
118+
class PcapngReader(BinaryIOMessageReader):
119+
"""
120+
Iterator of CAN messages from a Pcapng File.
121+
"""
122+
123+
file: BinaryIO
124+
125+
def __init__(
126+
self,
127+
file: Union[StringPathLike, BinaryIO],
128+
**kwargs: Any,
129+
) -> None:
130+
"""
131+
:param file: a path-like object or as file-like object to read from
132+
If this is a file-like object, is has to opened in binary
133+
read mode, not text read mode.
134+
"""
135+
136+
if pcapng is None:
137+
raise NotImplementedError(
138+
"The python-pcapng package was not found. Install python-can with "
139+
"the optional dependency [pcapng] to use the PcapngReader."
140+
)
141+
142+
super().__init__(file, mode="rb")
143+
self._scanner = pcapng.FileScanner(self.file)
144+
145+
def __iter__(self) -> Generator[Message, None, None]:
146+
for block in self._scanner:
147+
if isinstance(block, blocks.EnhancedPacket):
148+
idn: blocks.InterfaceDescription = block.interface
149+
# We only care about the CAN packets
150+
if idn.link_type != LINKTYPE_CAN_SOCKETCAN:
151+
logger.debug(
152+
"Skipping non-CAN packet, link type: %s", idn.link_type
153+
)
154+
continue
155+
156+
msg = parse_can_frame(
157+
block.packet_data, struct=CAN_FRAME_HEADER_STRUCT_BE
158+
)
159+
160+
timestamp64 = (block.timestamp_high << 32) + block.timestamp_low
161+
msg.timestamp = timestamp64 * idn.timestamp_resolution
162+
163+
if "if_name" in idn.options:
164+
msg.channel = idn.options["if_name"]
165+
else:
166+
msg.channel = block.interface_id
167+
168+
yield msg

can/io/player.py

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from .mf4 import MF4Reader
3030
from .sqlite import SqliteReader
3131
from .trc import TRCReader
32+
from .pcapng import PcapngReader
3233

3334
#: A map of file suffixes to their corresponding
3435
#: :class:`can.io.generic.MessageReader` class
@@ -39,6 +40,7 @@
3940
".db": SqliteReader,
4041
".log": CanutilsLogReader,
4142
".mf4": MF4Reader,
43+
".pcapng": PcapngReader,
4244
".trc": TRCReader,
4345
}
4446

0 commit comments

Comments
 (0)