def send(self, msg, timeout=None): if not ics.validate_hobject(self.dev): raise CanError("bus not open") message = ics.SpyMessage() flag0 = 0 if msg.is_extended_id: flag0 |= ics.SPY_STATUS_XTD_FRAME if msg.is_remote_frame: flag0 |= ics.SPY_STATUS_REMOTE_FRAME flag3 = 0 if msg.is_fd: message.Protocol = ics.SPY_PROTOCOL_CANFD if msg.bitrate_switch: flag3 |= ics.SPY_STATUS3_CANFD_BRS if msg.error_state_indicator: flag3 |= ics.SPY_STATUS3_CANFD_ESI message.ArbIDOrHeader = msg.arbitration_id msg_data = msg.data message.NumberBytesData = len(msg_data) message.Data = tuple(msg_data[:8]) if msg.is_fd and len(msg_data) > 8: message.ExtraDataPtrEnabled = 1 message.ExtraDataPtr = tuple(msg_data) message.StatusBitField = flag0 message.StatusBitField2 = 0 message.StatusBitField3 = flag3 if msg.channel is not None: message.NetworkID = msg.channel elif len(self.channels) == 1: message.NetworkID = self.channels[0] else: raise ValueError( "msg.channel must be set when using multiple channels.") try: ics.transmit_messages(self.dev, message) except ics.RuntimeError: raise ICSApiError(*ics.get_last_api_error(self.dev))
def send(self, msg, timeout=0): """Transmit a message to the CAN bus. :param Message msg: A message object. :param float timeout: If > 0, wait up to this many seconds for message to be ACK'ed. If timeout is exceeded, an exception will be raised. None blocks indefinitely. :raises can.CanError: if the message could not be sent """ if not ics.validate_hobject(self.dev): raise CanError("bus not open") message = ics.SpyMessage() flag0 = 0 if msg.is_extended_id: flag0 |= ics.SPY_STATUS_XTD_FRAME if msg.is_remote_frame: flag0 |= ics.SPY_STATUS_REMOTE_FRAME flag3 = 0 if msg.is_fd: message.Protocol = ics.SPY_PROTOCOL_CANFD if msg.bitrate_switch: flag3 |= ics.SPY_STATUS3_CANFD_BRS if msg.error_state_indicator: flag3 |= ics.SPY_STATUS3_CANFD_ESI message.ArbIDOrHeader = msg.arbitration_id msg_data = msg.data message.NumberBytesData = len(msg_data) message.Data = tuple(msg_data[:8]) if msg.is_fd and len(msg_data) > 8: message.ExtraDataPtrEnabled = 1 message.ExtraDataPtr = tuple(msg_data) message.StatusBitField = flag0 message.StatusBitField2 = 0 message.StatusBitField3 = flag3 if msg.channel is not None: message.NetworkID = msg.channel elif len(self.channels) == 1: message.NetworkID = self.channels[0] else: raise ValueError( "msg.channel must be set when using multiple channels.") msg_desc_id = next(description_id) message.DescriptionID = msg_desc_id receipt_key = (msg.arbitration_id, msg_desc_id) if timeout != 0: self.message_receipts[receipt_key].clear() try: ics.transmit_messages(self.dev, message) except ics.RuntimeError: raise ICSApiError(*ics.get_last_api_error(self.dev)) # If timeout is set, wait for ACK # This requires a notifier for the bus or # some other thread calling recv periodically if timeout != 0 and not self.message_receipts[receipt_key].wait( timeout): raise CanError("Transmit timeout")