Skip to content

Commit fe1051e

Browse files
authored
Merge branch 'develop' into vectorbus_recv_refactoring
2 parents 826c393 + 035cedb commit fe1051e

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

can/interfaces/ics_neovi/neovi_bus.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
import logging
1212
import os
1313
import tempfile
14-
from collections import deque
14+
from collections import deque, defaultdict
15+
from itertools import cycle
16+
from threading import Event
1517

1618
from can import Message, CanError, BusABC
1719

@@ -55,6 +57,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
5557
# Use inter-process mutex to prevent concurrent device open.
5658
# When neoVI server is enabled, there is an issue with concurrent device open.
5759
open_lock = FileLock(os.path.join(tempfile.gettempdir(), "neovi.lock"))
60+
description_id = cycle(range(1, 0x8000))
5861

5962

6063
class ICSApiError(CanError):
@@ -176,6 +179,7 @@ def __init__(self, channel, can_filters=None, **kwargs):
176179
logger.info("Using device: {}".format(self.channel_info))
177180

178181
self.rx_buffer = deque()
182+
self.message_receipts = defaultdict(Event)
179183

180184
@staticmethod
181185
def channel_to_netid(channel_name_or_id):
@@ -267,6 +271,9 @@ def _process_msg_queue(self, timeout=0.1):
267271
if is_tx:
268272
if bool(ics_msg.StatusBitField & ics.SPY_STATUS_GLOBAL_ERR):
269273
continue
274+
if ics_msg.DescriptionID:
275+
receipt_key = (ics_msg.ArbIDOrHeader, ics_msg.DescriptionID)
276+
self.message_receipts[receipt_key].set()
270277
if not self._receive_own_messages:
271278
continue
272279

@@ -349,7 +356,19 @@ def _recv_internal(self, timeout=0.1):
349356
return None, False
350357
return msg, False
351358

352-
def send(self, msg, timeout=None):
359+
def send(self, msg, timeout=0):
360+
"""Transmit a message to the CAN bus.
361+
362+
:param Message msg: A message object.
363+
364+
:param float timeout:
365+
If > 0, wait up to this many seconds for message to be ACK'ed.
366+
If timeout is exceeded, an exception will be raised.
367+
None blocks indefinitely.
368+
369+
:raises can.CanError:
370+
if the message could not be sent
371+
"""
353372
if not ics.validate_hobject(self.dev):
354373
raise CanError("bus not open")
355374
message = ics.SpyMessage()
@@ -385,7 +404,20 @@ def send(self, msg, timeout=None):
385404
else:
386405
raise ValueError("msg.channel must be set when using multiple channels.")
387406

407+
msg_desc_id = next(description_id)
408+
message.DescriptionID = msg_desc_id
409+
receipt_key = (msg.arbitration_id, msg_desc_id)
410+
411+
if timeout != 0:
412+
self.message_receipts[receipt_key].clear()
413+
388414
try:
389415
ics.transmit_messages(self.dev, message)
390416
except ics.RuntimeError:
391417
raise ICSApiError(*ics.get_last_api_error(self.dev))
418+
419+
# If timeout is set, wait for ACK
420+
# This requires a notifier for the bus or
421+
# some other thread calling recv periodically
422+
if timeout != 0 and not self.message_receipts[receipt_key].wait(timeout):
423+
raise CanError("Transmit timeout")

0 commit comments

Comments
 (0)