Exemplo n.º 1
0
    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
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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
Exemplo n.º 4
0
    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')
Exemplo n.º 5
0
    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))
Exemplo n.º 6
0
    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))
Exemplo n.º 7
0
 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')
Exemplo n.º 8
0
    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")
Exemplo n.º 9
0
    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")
Exemplo n.º 10
0
    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))
Exemplo n.º 11
0
    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))
Exemplo n.º 12
0
    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")