def _recv_internal( self, timeout: Optional[float]) -> Tuple[Optional[Message], bool]: """ Read a message from the serial device. :param timeout: .. warning:: This parameter will be ignored. The timeout value of the channel is used. :returns: Received message and `False` (because no filtering as taken place). .. warning:: Flags like is_extended_id, is_remote_frame and is_error_frame will not be set over this function, the flags in the return message are the default values. """ try: rx_byte = self._ser.read() if rx_byte and ord(rx_byte) == 0xAA: s = self._ser.read(4) timestamp = struct.unpack("<I", s)[0] dlc = ord(self._ser.read()) if dlc > 8: raise CanError("received DLC may not exceed 8 bytes") s = self._ser.read(4) arbitration_id = struct.unpack("<I", s)[0] if arbitration_id >= 0x20000000: raise CanError( "received arbitration id may not exceed 2^29 (0x20000000)" ) data = self._ser.read(dlc) delimiter_byte = ord(self._ser.read()) if delimiter_byte == 0xBB: # received message data okay msg = Message( # TODO: We are only guessing that they are milliseconds timestamp=timestamp / 1000, arbitration_id=arbitration_id, dlc=dlc, data=data, ) return msg, False else: raise CanError( f"invalid delimiter byte while reading message: {delimiter_byte}" ) else: return None, False except serial.SerialException as error: raise CanError("could not read from serial") from error
def __init__(self, channel=None, dll="usb2can.dll", flags=0x00000008, *args, bitrate=500000, **kwargs): self.can = Usb2CanAbstractionLayer(dll) # get the serial number of the device device_id = kwargs.get("serial", d=channel) # search for a serial number if the device_id is None or empty if not device_id: devices = find_serial_devices() if not devices: raise CanError("could not automatically find any device") device_id = devices[0] # convert to kb/s and cap: max rate is 1000 kb/s baudrate = min(int(bitrate // 1000), 1000) self.channel_info = "USB2CAN device {}".format(device_id) connector = "{}; {}".format(device_id, baudrate) self.handle = self.can.open(connector, flags_t) super().__init__(channel=channel, dll=dll, flags_t=flags_t, bitrate=bitrate, *args, **kwargs)
def __convert_timestamp(self, value): # The kvaser seems to zero times # Use the current value if the offset has not been set yet if not hasattr(self, 'timer_offset') or self.timer_offset is None: self.timer_offset = value self.pc_time_offset = time.time() if value < self.timer_offset: # Check for overflow MAX_32BIT = 0xFFFFFFFF # The maximum value that the timer reaches on a 32-bit machine MAX_64BIT = 0x9FFFFFFFF # The maximum value that the timer reaches on a 64-bit machine if ctypes.sizeof(ctypes.c_long) == 8: value += MAX_64BIT elif ctypes.sizeof(ctypes.c_long) == 4: value += MAX_32BIT else: raise CanError( 'Unknown platform. Expected a long to be 4 or 8 bytes long but it was %i bytes.' % ctypes.sizeof(ctypes.c_long)) if value <= self.timer_offset: raise OverflowError( 'CAN timestamp overflowed. The timer offset was ' + str(self.timer_offset)) timestamp = float(value - self.timer_offset) / ( 1000000 / TIMESTAMP_RESOLUTION) # Convert into seconds timestamp += self.pc_time_offset lag = time.time() - timestamp if lag < 0: # If we see a timestamp that is quicker than the ever before, update the offset self.pc_time_offset += lag return timestamp
def _check_if_open(self): """Raises CanError if the bus is not open. Has to be called in every method that accesses the bus. """ if not self._open: raise CanError('Operation on closed bus')
def shutdown(self): """ Shuts down connection to the device safely. :raise cam.CanError: is closing the connection did not work """ status = self.can.close(self.handle) if status != CANAL_ERROR_SUCCESS: raise CanError("could not shut down bus: status == {}".format(status))
def send(self, msg, timeout=None): tx = message_convert_tx(msg) if timeout: status = self.can.blocking_send(self.handle, byref(tx), int(timeout * 1000)) else: status = self.can.send(self.handle, byref(tx)) if status != CANAL_ERROR_SUCCESS: raise CanError("could not send message: status == {}".format(status))
def send(self, msg, timeout=None): self._check_if_open() # Create a shallow copy for this channel msg_copy = copy.copy(msg) msg_copy.timestamp = time.time() msg_copy.data = bytearray(msg.data) msg_copy.channel = self.channel_id all_sent = True # Add message to all listening on this channel 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 not all_sent: raise CanError('Could not send message to one or more recipients')
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 # 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 not all_sent: raise CanError("Could not send message to one or more recipients")
def send(self, msg: Message, timeout: Optional[float] = None) -> None: self._check_if_open() timestamp = time.time() # Add message to all listening on this channel all_sent = True for bus_queue in self.channel: 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")
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=None): if not self.dev.IsOpen: raise CanError("bus not open") flags = 0 if msg.is_extended_id: flags |= ics.SPY_STATUS_XTD_FRAME if msg.is_remote_frame: flags |= ics.SPY_STATUS_REMOTE_FRAME message = ics.SpyMessage() message.ArbIDOrHeader = msg.arbitration_id message.NumberBytesData = len(msg.data) message.Data = tuple(msg.data) message.StatusBitField = flags message.StatusBitField2 = 0 message.NetworkID = self.network 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")