diff --git a/can/interfaces/virtual.py b/can/interfaces/virtual.py index a903435ac..ffd5b0241 100644 --- a/can/interfaces/virtual.py +++ b/can/interfaces/virtual.py @@ -59,6 +59,7 @@ def __init__( channel: Any = None, receive_own_messages: bool = False, rx_queue_size: int = 0, + preserve_timestamps: bool = False, **kwargs: Any, ) -> None: super().__init__( @@ -69,6 +70,7 @@ def __init__( self.channel_id = channel self.channel_info = f"Virtual bus channel {self.channel_id}" self.receive_own_messages = receive_own_messages + self.preserve_timestamps = preserve_timestamps self._open = True with channels_lock: @@ -103,7 +105,7 @@ def _recv_internal( def send(self, msg: Message, timeout: Optional[float] = None) -> None: self._check_if_open() - timestamp = time.time() + timestamp = msg.timestamp if self.preserve_timestamps else time.time() # Add message to all listening on this channel all_sent = True for bus_queue in self.channel: diff --git a/doc/interfaces/virtual.rst b/doc/interfaces/virtual.rst index b3fa7b38e..9258c9bbd 100644 --- a/doc/interfaces/virtual.rst +++ b/doc/interfaces/virtual.rst @@ -85,7 +85,7 @@ Example ------- .. code-block:: python - + import can bus1 = can.interface.Bus('test', bustype='virtual') @@ -100,6 +100,33 @@ Example assert msg1.data == msg2.data assert msg1.timestamp != msg2.timestamp +.. code-block:: python + + import can + + bus1 = can.interface.Bus('test', bustype='virtual', preserve_timestamps=True) + bus2 = can.interface.Bus('test', bustype='virtual') + + msg1 = can.Message(timestamp=1639740470.051948, arbitration_id=0xabcde, data=[1,2,3]) + + # Messages sent on bus1 will have their timestamps preserved when received + # on bus2 + bus1.send(msg1) + msg2 = bus2.recv() + + assert msg1.arbitration_id == msg2.arbitration_id + assert msg1.data == msg2.data + assert msg1.timestamp == msg2.timestamp + + # Messages sent on bus2 will not have their timestamps preserved when + # received on bus1 + bus2.send(msg1) + msg3 = bus1.recv() + + assert msg1.arbitration_id == msg3.arbitration_id + assert msg1.data == msg3.data + assert msg1.timestamp != msg3.timestamp + Bus Class Documentation ----------------------- diff --git a/test/test_interface_virtual.py b/test/test_interface_virtual.py new file mode 100644 index 000000000..009722779 --- /dev/null +++ b/test/test_interface_virtual.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# coding: utf-8 + +""" +This module tests :meth:`can.interface.virtual`. +""" + +import unittest + +from can import Bus, Message + +EXAMPLE_MSG1 = Message(timestamp=1639739471.5565314, arbitration_id=0x481, data=b"\x01") + + +class TestMessageFiltering(unittest.TestCase): + def setUp(self): + self.node1 = Bus("test", bustype="virtual", preserve_timestamps=True) + self.node2 = Bus("test", bustype="virtual") + + def tearDown(self): + self.node1.shutdown() + self.node2.shutdown() + + def test_sendmsg(self): + self.node2.send(EXAMPLE_MSG1) + r = self.node1.recv(0.1) + assert r.timestamp != EXAMPLE_MSG1.timestamp + assert r.arbitration_id == EXAMPLE_MSG1.arbitration_id + assert r.data == EXAMPLE_MSG1.data + + def test_sendmsg_preserve_timestamp(self): + self.node1.send(EXAMPLE_MSG1) + r = self.node2.recv(0.1) + assert r.timestamp == EXAMPLE_MSG1.timestamp + assert r.arbitration_id == EXAMPLE_MSG1.arbitration_id + assert r.data == EXAMPLE_MSG1.data + + +if __name__ == "__main__": + unittest.main()