Skip to content
20 changes: 11 additions & 9 deletions can/interfaces/virtual.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,20 @@ def _recv_internal(self, timeout):
def send(self, msg, timeout=None):
self._check_if_open()

msg_copy = deepcopy(msg)
msg_copy.timestamp = time.time()
msg_copy.channel = self.channel_id

timestamp = time.time()
# Add message to all listening on this channel
all_sent = True
for bus_queue in self.channel:
if bus_queue is not self.queue or self.receive_own_messages:
try:
bus_queue.put(msg_copy, block=True, timeout=timeout)
except queue.Full:
all_sent = False
if bus_queue is self.queue and not self.receive_own_messages:
continue
msg_copy = deepcopy(msg)
msg_copy.timestamp = timestamp
msg_copy.channel = self.channel_id
msg_copy.is_rx = bus_queue is not self.queue
try:
bus_queue.put(msg_copy, block=True, timeout=timeout)
except queue.Full:
all_sent = False
if not all_sent:
raise CanError("Could not send message to one or more recipients")

Expand Down
60 changes: 60 additions & 0 deletions test/back2back_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,66 @@ def test_dlc_less_than_eight(self):
msg = can.Message(is_extended_id=False, arbitration_id=0x300, data=[4, 5, 6])
self._send_and_receive(msg)

def test_message_direction(self):
# Verify that own message received has is_rx set to False while message
# received on the other virtual interfaces have is_rx set to True
if self.INTERFACE_1 != "virtual":
raise unittest.SkipTest(
"Message direction not yet implemented for socketcan"
)
bus3 = can.Bus(
channel=self.CHANNEL_2,
bustype=self.INTERFACE_2,
bitrate=self.BITRATE,
fd=TEST_CAN_FD,
single_handle=True,
receive_own_messages=True,
)
try:
msg = can.Message(
is_extended_id=False, arbitration_id=0x300, data=[2, 1, 3]
)
bus3.send(msg)
recv_msg_bus1 = self.bus1.recv(self.TIMEOUT)
recv_msg_bus2 = self.bus2.recv(self.TIMEOUT)
self_recv_msg_bus3 = bus3.recv(self.TIMEOUT)

self.assertTrue(recv_msg_bus1.is_rx)
self.assertTrue(recv_msg_bus2.is_rx)
self.assertFalse(self_recv_msg_bus3.is_rx)
finally:
bus3.shutdown()

def test_unique_message_instances(self):
# Verify that we have a different instances of message for each bus
if self.INTERFACE_1 != "virtual":
raise unittest.SkipTest("Not relevant for socketcan")
bus3 = can.Bus(
channel=self.CHANNEL_2,
bustype=self.INTERFACE_2,
bitrate=self.BITRATE,
fd=TEST_CAN_FD,
single_handle=True,
receive_own_messages=True,
)
try:
msg = can.Message(
is_extended_id=False, arbitration_id=0x300, data=[2, 1, 3]
)
bus3.send(msg)
recv_msg_bus1 = self.bus1.recv(self.TIMEOUT)
recv_msg_bus2 = self.bus2.recv(self.TIMEOUT)
self_recv_msg_bus3 = bus3.recv(self.TIMEOUT)

self._check_received_message(recv_msg_bus1, recv_msg_bus2)
self._check_received_message(recv_msg_bus2, self_recv_msg_bus3)

recv_msg_bus1.data[0] = 4
self.assertNotEqual(recv_msg_bus1.data, recv_msg_bus2.data)
self.assertEqual(recv_msg_bus2.data, self_recv_msg_bus3.data)
finally:
bus3.shutdown()

@unittest.skipUnless(TEST_CAN_FD, "Don't test CAN-FD")
def test_fd_message(self):
msg = can.Message(
Expand Down