コード例 #1
0
ファイル: canlib.py プロジェクト: DawidRosinski/python-can
    def _recv_canfd(self) -> Optional[Message]:
        xl_can_rx_event = xlclass.XLcanRxEvent()
        xldriver.xlCanReceive(self.port_handle, xl_can_rx_event)

        if xl_can_rx_event.tag == xldefine.XL_CANFD_RX_EventTags.XL_CAN_EV_TAG_RX_OK:
            is_rx = True
            data_struct = xl_can_rx_event.tagData.canRxOkMsg
        elif xl_can_rx_event.tag == xldefine.XL_CANFD_RX_EventTags.XL_CAN_EV_TAG_TX_OK:
            is_rx = False
            data_struct = xl_can_rx_event.tagData.canTxOkMsg
        else:
            self.handle_canfd_event(xl_can_rx_event)
            return

        msg_id = data_struct.canId
        dlc = dlc2len(data_struct.dlc)
        flags = data_struct.msgFlags
        timestamp = xl_can_rx_event.timeStamp * 1e-9
        channel = self.index_to_channel.get(xl_can_rx_event.chanIndex)

        msg = Message(
            timestamp=timestamp + self._time_offset,
            arbitration_id=msg_id & 0x1FFFFFFF,
            is_extended_id=bool(
                msg_id & xldefine.XL_MessageFlagsExtended.XL_CAN_EXT_MSG_ID),
            is_remote_frame=bool(
                flags
                & xldefine.XL_CANFD_RX_MessageFlags.XL_CAN_RXMSG_FLAG_RTR),
            is_error_frame=bool(
                flags
                & xldefine.XL_CANFD_RX_MessageFlags.XL_CAN_RXMSG_FLAG_EF),
            is_fd=bool(
                flags
                & xldefine.XL_CANFD_RX_MessageFlags.XL_CAN_RXMSG_FLAG_EDL),
            bitrate_switch=bool(
                flags
                & xldefine.XL_CANFD_RX_MessageFlags.XL_CAN_RXMSG_FLAG_BRS),
            error_state_indicator=bool(
                flags
                & xldefine.XL_CANFD_RX_MessageFlags.XL_CAN_RXMSG_FLAG_ESI),
            is_rx=is_rx,
            channel=channel,
            dlc=dlc,
            data=data_struct.data[:dlc],
        )
        return msg
コード例 #2
0
    def _parse_data(self, data):
        """Optimized inner loop by making local copies of global variables
        and class members and hardcoding some values."""
        unpack_obj_header_base = OBJ_HEADER_BASE_STRUCT.unpack_from
        obj_header_base_size = OBJ_HEADER_BASE_STRUCT.size
        unpack_obj_header_v1 = OBJ_HEADER_V1_STRUCT.unpack_from
        obj_header_v1_size = OBJ_HEADER_V1_STRUCT.size
        unpack_obj_header_v2 = OBJ_HEADER_V2_STRUCT.unpack_from
        obj_header_v2_size = OBJ_HEADER_V2_STRUCT.size
        unpack_can_msg = CAN_MSG_STRUCT.unpack_from
        unpack_can_fd_msg = CAN_FD_MSG_STRUCT.unpack_from
        unpack_can_fd_64_msg = CAN_FD_MSG_64_STRUCT.unpack_from
        can_fd_64_msg_size = CAN_FD_MSG_64_STRUCT.size
        unpack_can_error_ext = CAN_ERROR_EXT_STRUCT.unpack_from

        start_timestamp = self.start_timestamp
        max_pos = len(data)
        pos = 0

        # Loop until a struct unpack raises an exception
        while True:
            self._pos = pos
            # Find next object after padding (depends on object type)
            try:
                pos = data.index(b"LOBJ", pos, pos + 8)
            except ValueError:
                if pos + 8 > max_pos:
                    # Not enough data in container
                    return
                raise BLFParseError("Could not find next object")
            header = unpack_obj_header_base(data, pos)
            # print(header)
            signature, _, header_version, obj_size, obj_type = header
            if signature != b"LOBJ":
                raise BLFParseError()

            # Calculate position of next object
            next_pos = pos + obj_size
            if next_pos > max_pos:
                # This object continues in the next container
                return
            pos += obj_header_base_size

            # Read rest of header
            if header_version == 1:
                flags, _, _, timestamp = unpack_obj_header_v1(data, pos)
                pos += obj_header_v1_size
            elif header_version == 2:
                flags, _, _, timestamp = unpack_obj_header_v2(data, pos)
                pos += obj_header_v2_size
            else:
                LOG.warning("Unknown object header version (%d)",
                            header_version)
                pos = next_pos
                continue

            # Calculate absolute timestamp in seconds
            factor = 1e-5 if flags == 1 else 1e-9
            timestamp = timestamp * factor + start_timestamp

            if obj_type == CAN_MESSAGE or obj_type == CAN_MESSAGE2:
                channel, flags, dlc, can_id, can_data = unpack_can_msg(
                    data, pos)
                yield Message(
                    timestamp=timestamp,
                    arbitration_id=can_id & 0x1FFFFFFF,
                    is_extended_id=bool(can_id & CAN_MSG_EXT),
                    is_remote_frame=bool(flags & REMOTE_FLAG),
                    is_rx=not bool(flags & DIR),
                    dlc=dlc,
                    data=can_data[:dlc],
                    channel=channel - 1,
                )
            elif obj_type == CAN_ERROR_EXT:
                members = unpack_can_error_ext(data, pos)
                channel = members[0]
                dlc = members[5]
                can_id = members[7]
                can_data = members[9]
                yield Message(
                    timestamp=timestamp,
                    is_error_frame=True,
                    is_extended_id=bool(can_id & CAN_MSG_EXT),
                    arbitration_id=can_id & 0x1FFFFFFF,
                    dlc=dlc,
                    data=can_data[:dlc],
                    channel=channel - 1,
                )
            elif obj_type == CAN_FD_MESSAGE:
                members = unpack_can_fd_msg(data, pos)
                (
                    channel,
                    flags,
                    dlc,
                    can_id,
                    _,
                    _,
                    fd_flags,
                    valid_bytes,
                    can_data,
                ) = members
                yield Message(
                    timestamp=timestamp,
                    arbitration_id=can_id & 0x1FFFFFFF,
                    is_extended_id=bool(can_id & CAN_MSG_EXT),
                    is_remote_frame=bool(flags & REMOTE_FLAG),
                    is_fd=bool(fd_flags & 0x1),
                    is_rx=not bool(flags & DIR),
                    bitrate_switch=bool(fd_flags & 0x2),
                    error_state_indicator=bool(fd_flags & 0x4),
                    dlc=dlc2len(dlc),
                    data=can_data[:valid_bytes],
                    channel=channel - 1,
                )
            elif obj_type == CAN_FD_MESSAGE_64:
                members = unpack_can_fd_64_msg(data, pos)[:7]
                channel, dlc, valid_bytes, _, can_id, _, fd_flags = members
                pos += can_fd_64_msg_size
                yield Message(
                    timestamp=timestamp,
                    arbitration_id=can_id & 0x1FFFFFFF,
                    is_extended_id=bool(can_id & CAN_MSG_EXT),
                    is_remote_frame=bool(fd_flags & 0x0010),
                    is_fd=bool(fd_flags & 0x1000),
                    bitrate_switch=bool(fd_flags & 0x2000),
                    error_state_indicator=bool(fd_flags & 0x4000),
                    dlc=dlc2len(dlc),
                    data=data[pos:pos + valid_bytes],
                    channel=channel - 1,
                )

            pos = next_pos
コード例 #3
0
ファイル: canlib.py プロジェクト: bzdegluk/dzida_laserowa
    def _recv_internal(self, timeout):
        end_time = time.time() + timeout if timeout is not None else None

        if self.fd:
            event = vxlapi.XLcanRxEvent()
        else:
            event = vxlapi.XLevent()
            event_count = ctypes.c_uint()

        while True:
            if self.fd:
                try:
                    vxlapi.xlCanReceive(self.port_handle, event)
                except VectorError as exc:
                    if exc.error_code != vxlapi.XL_ERR_QUEUE_IS_EMPTY:
                        raise
                else:
                    if event.tag == vxlapi.XL_CAN_EV_TAG_RX_OK or event.tag == vxlapi.XL_CAN_EV_TAG_TX_OK:
                        msg_id = event.tagData.canRxOkMsg.canId
                        dlc = dlc2len(event.tagData.canRxOkMsg.dlc)
                        flags = event.tagData.canRxOkMsg.msgFlags
                        timestamp = event.timeStamp * 1e-9
                        channel = self.index_to_channel.get(event.chanIndex)
                        msg = Message(
                            timestamp=timestamp + self._time_offset,
                            arbitration_id=msg_id & 0x1FFFFFFF,
                            is_extended_id=bool(msg_id & vxlapi.XL_CAN_EXT_MSG_ID),
                            is_remote_frame=bool(flags & vxlapi.XL_CAN_RXMSG_FLAG_RTR),
                            is_error_frame=bool(flags & vxlapi.XL_CAN_RXMSG_FLAG_EF),
                            is_fd=bool(flags & vxlapi.XL_CAN_RXMSG_FLAG_EDL),
                            error_state_indicator=bool(flags & vxlapi.XL_CAN_RXMSG_FLAG_ESI),
                            bitrate_switch=bool(flags & vxlapi.XL_CAN_RXMSG_FLAG_BRS),
                            dlc=dlc,
                            data=event.tagData.canRxOkMsg.data[:dlc],
                            channel=channel)
                        return msg, self._is_filtered
            else:
                event_count.value = 1
                try:
                    vxlapi.xlReceive(self.port_handle, event_count, event)
                except VectorError as exc:
                    if exc.error_code != vxlapi.XL_ERR_QUEUE_IS_EMPTY:
                        raise
                else:
                    if event.tag == vxlapi.XL_RECEIVE_MSG:
                        msg_id = event.tagData.msg.id
                        dlc = event.tagData.msg.dlc
                        flags = event.tagData.msg.flags
                        timestamp = event.timeStamp * 1e-9
                        channel = self.index_to_channel.get(event.chanIndex)
                        msg = Message(
                            timestamp=timestamp + self._time_offset,
                            arbitration_id=msg_id & 0x1FFFFFFF,
                            is_extended_id=bool(msg_id & vxlapi.XL_CAN_EXT_MSG_ID),
                            is_remote_frame=bool(flags & vxlapi.XL_CAN_MSG_FLAG_REMOTE_FRAME),
                            is_error_frame=bool(flags & vxlapi.XL_CAN_MSG_FLAG_ERROR_FRAME),
                            is_fd=False,
                            dlc=dlc,
                            data=event.tagData.msg.data[:dlc],
                            channel=channel)
                        return msg, self._is_filtered

            if end_time is not None and time.time() > end_time:
                return None, self._is_filtered

            if HAS_EVENTS:
                # Wait for receive event to occur
                if timeout is None:
                    time_left_ms = INFINITE
                else:
                    time_left = end_time - time.time()
                    time_left_ms = max(0, int(time_left * 1000))
                WaitForSingleObject(self.event_handle.value, time_left_ms)
            else:
                # Wait a short time until we try again
                time.sleep(self.poll_interval)
コード例 #4
0
ファイル: blf.py プロジェクト: gauravkuppa/base-drone
    def __iter__(self):
        tail = b""
        while True:
            data = self.file.read(OBJ_HEADER_BASE_STRUCT.size)
            if not data:
                # EOF
                break

            header = OBJ_HEADER_BASE_STRUCT.unpack(data)
            if header[0] != b"LOBJ":
                raise BLFParseError()
            obj_type = header[4]
            obj_data_size = header[3] - OBJ_HEADER_BASE_STRUCT.size
            obj_data = self.file.read(obj_data_size)
            # Read padding bytes
            self.file.read(obj_data_size % 4)

            if obj_type == LOG_CONTAINER:
                method, uncompressed_size = LOG_CONTAINER_STRUCT.unpack_from(
                    obj_data)
                container_data = obj_data[LOG_CONTAINER_STRUCT.size:]
                if method == NO_COMPRESSION:
                    data = container_data
                elif method == ZLIB_DEFLATE:
                    data = zlib.decompress(container_data, 15, uncompressed_size)
                else:
                    # Unknown compression method
                    LOG.warning("Unknown compression method (%d)", method)
                    continue

                if tail:
                    data = tail + data
                pos = 0
                while pos + OBJ_HEADER_BASE_STRUCT.size < len(data):
                    header = OBJ_HEADER_BASE_STRUCT.unpack_from(data, pos)
                    #print(header)
                    if header[0] != b"LOBJ":
                        raise BLFParseError()

                    obj_size = header[3]
                    # Calculate position of next object
                    next_pos = pos + obj_size + (obj_size % 4)
                    if next_pos > len(data):
                        # Object continues in next log container
                        break
                    pos += OBJ_HEADER_BASE_STRUCT.size

                    # Read rest of header
                    header_version = header[2]
                    if header_version == 1:
                        flags, _, _, timestamp = OBJ_HEADER_V1_STRUCT.unpack_from(data, pos)
                        pos += OBJ_HEADER_V1_STRUCT.size
                    elif header_version == 2:
                        flags, _, _, timestamp, _ = OBJ_HEADER_V2_STRUCT.unpack_from(data, pos)
                        pos += OBJ_HEADER_V2_STRUCT.size
                    else:
                        # Unknown header version
                        LOG.warning("Unknown object header version (%d)", header_version)
                        pos = next_pos
                        continue

                    if flags == TIME_TEN_MICS:
                        factor = 10 * 1e-6
                    else:
                        factor = 1e-9
                    timestamp = timestamp * factor + self.start_timestamp

                    obj_type = header[4]
                    # Both CAN message types have the same starting content
                    if obj_type in (CAN_MESSAGE, CAN_MESSAGE2):
                        (channel, flags, dlc, can_id,
                         can_data) = CAN_MSG_STRUCT.unpack_from(data, pos)
                        msg = Message(timestamp=timestamp,
                                      arbitration_id=can_id & 0x1FFFFFFF,
                                      is_extended_id=bool(can_id & CAN_MSG_EXT),
                                      is_remote_frame=bool(flags & REMOTE_FLAG),
                                      dlc=dlc,
                                      data=can_data[:dlc],
                                      channel=channel - 1)
                        yield msg
                    elif obj_type == CAN_FD_MESSAGE:
                        (channel, flags, dlc, can_id, _, _, fd_flags,
                         _, can_data) = CAN_FD_MSG_STRUCT.unpack_from(data, pos)
                        length = dlc2len(dlc)
                        msg = Message(timestamp=timestamp,
                                      arbitration_id=can_id & 0x1FFFFFFF,
                                      is_extended_id=bool(can_id & CAN_MSG_EXT),
                                      is_remote_frame=bool(flags & REMOTE_FLAG),
                                      is_fd=bool(fd_flags & EDL),
                                      bitrate_switch=bool(fd_flags & BRS),
                                      error_state_indicator=bool(fd_flags & ESI),
                                      dlc=length,
                                      data=can_data[:length],
                                      channel=channel - 1)
                        yield msg
                    elif obj_type == CAN_FD_MESSAGE_64:
                        (
                            channel, dlc, _, _, can_id, _, fd_flags
                         ) = CAN_FD_MSG_64_STRUCT.unpack_from(data, pos)[:7]
                        length = dlc2len(dlc)
                        can_data = struct.unpack_from(
                            "<{}s".format(length),
                            data,
                            pos + CAN_FD_MSG_64_STRUCT.size
                        )[0]
                        msg = Message(
                            timestamp=timestamp,
                            arbitration_id=can_id & 0x1FFFFFFF,
                            is_extended_id=bool(can_id & CAN_MSG_EXT),
                            is_remote_frame=bool(fd_flags & REMOTE_FLAG_64),
                            is_fd=bool(fd_flags & EDL_64),
                            bitrate_switch=bool(fd_flags & BRS_64),
                            error_state_indicator=bool(fd_flags & ESI_64),
                            dlc=length,
                            data=can_data[:length],
                            channel=channel - 1
                        )
                        yield msg
                    elif obj_type == CAN_ERROR_EXT:
                        (channel, _, _, _, _, dlc, _, can_id, _,
                         can_data) = CAN_ERROR_EXT_STRUCT.unpack_from(data, pos)
                        msg = Message(timestamp=timestamp,
                                      is_error_frame=True,
                                      is_extended_id=bool(can_id & CAN_MSG_EXT),
                                      arbitration_id=can_id & 0x1FFFFFFF,
                                      dlc=dlc,
                                      data=can_data[:dlc],
                                      channel=channel - 1)
                        yield msg
                    # else:
                    #     LOG.warning("Unknown object type (%d)", obj_type)

                    pos = next_pos

                # save the remaining data that could not be processed
                tail = data[pos:]

        self.stop()
コード例 #5
0
ファイル: pcan.py プロジェクト: nateimig18/python-can
    def _recv_internal(self, timeout):

        if HAS_EVENTS:
            # We will utilize events for the timeout handling
            timeout_ms = int(timeout *
                             1000) if timeout is not None else INFINITE
        elif timeout is not None:
            # Calculate max time
            end_time = timeout_clock() + timeout

        #log.debug("Trying to read a msg")

        result = None
        while result is None:
            if self.fd:
                result = self.m_objPCANBasic.ReadFD(self.m_PcanHandle)
            else:
                result = self.m_objPCANBasic.Read(self.m_PcanHandle)
            if result[0] == PCAN_ERROR_QRCVEMPTY:
                if HAS_EVENTS:
                    result = None
                    val = WaitForSingleObject(self._recv_event, timeout_ms)
                    if val != WAIT_OBJECT_0:
                        return None, False
                elif timeout is not None and timeout_clock() >= end_time:
                    return None, False
                else:
                    result = None
                    time.sleep(0.001)
            elif result[0] & (PCAN_ERROR_BUSLIGHT | PCAN_ERROR_BUSHEAVY):
                log.warning(self._get_formatted_error(result[0]))
                return None, False
            elif result[0] != PCAN_ERROR_OK:
                raise PcanError(self._get_formatted_error(result[0]))

        theMsg = result[1]
        itsTimeStamp = result[2]

        #log.debug("Received a message")

        is_extended_id = (
            theMsg.MSGTYPE
            & PCAN_MESSAGE_EXTENDED.value) == PCAN_MESSAGE_EXTENDED.value
        is_remote_frame = (theMsg.MSGTYPE
                           & PCAN_MESSAGE_RTR.value) == PCAN_MESSAGE_RTR.value
        is_fd = (theMsg.MSGTYPE
                 & PCAN_MESSAGE_FD.value) == PCAN_MESSAGE_FD.value
        bitrate_switch = (theMsg.MSGTYPE
                          & PCAN_MESSAGE_BRS.value) == PCAN_MESSAGE_BRS.value
        error_state_indicator = (
            theMsg.MSGTYPE & PCAN_MESSAGE_ESI.value) == PCAN_MESSAGE_ESI.value
        is_error_frame = (
            theMsg.MSGTYPE
            & PCAN_MESSAGE_ERRFRAME.value) == PCAN_MESSAGE_ERRFRAME.value

        if self.fd:
            dlc = dlc2len(theMsg.DLC)
            timestamp = boottimeEpoch + (itsTimeStamp.value /
                                         (1000.0 * 1000.0))
        else:
            dlc = theMsg.LEN
            timestamp = boottimeEpoch + (
                (itsTimeStamp.micros + 1000 * itsTimeStamp.millis +
                 0x100000000 * 1000 * itsTimeStamp.millis_overflow) /
                (1000.0 * 1000.0))

        rx_msg = Message(timestamp=timestamp,
                         arbitration_id=theMsg.ID,
                         is_extended_id=is_extended_id,
                         is_remote_frame=is_remote_frame,
                         is_error_frame=is_error_frame,
                         dlc=dlc,
                         data=theMsg.DATA[:dlc],
                         is_fd=is_fd,
                         bitrate_switch=bitrate_switch,
                         error_state_indicator=error_state_indicator)

        return rx_msg, False
コード例 #6
0
ファイル: blf.py プロジェクト: XelaRellum/python-can
    def __iter__(self):
        tail = b""
        while True:
            data = self.file.read(OBJ_HEADER_BASE_STRUCT.size)
            if not data:
                # EOF
                break

            header = OBJ_HEADER_BASE_STRUCT.unpack(data)
            if header[0] != b"LOBJ":
                raise BLFParseError()
            obj_type = header[4]
            obj_data_size = header[3] - OBJ_HEADER_BASE_STRUCT.size
            obj_data = self.file.read(obj_data_size)
            # Read padding bytes
            self.file.read(obj_data_size % 4)

            if obj_type == LOG_CONTAINER:
                method, uncompressed_size = LOG_CONTAINER_STRUCT.unpack_from(
                    obj_data)
                container_data = obj_data[LOG_CONTAINER_STRUCT.size:]
                if method == NO_COMPRESSION:
                    data = container_data
                elif method == ZLIB_DEFLATE:
                    data = zlib.decompress(container_data, 15, uncompressed_size)
                else:
                    # Unknown compression method
                    LOG.warning("Unknown compression method (%d)", method)
                    continue

                if tail:
                    data = tail + data
                pos = 0
                while pos + OBJ_HEADER_BASE_STRUCT.size < len(data):
                    header = OBJ_HEADER_BASE_STRUCT.unpack_from(data, pos)
                    #print(header)
                    if header[0] != b"LOBJ":
                        raise BLFParseError()

                    obj_size = header[3]
                    # Calculate position of next object
                    next_pos = pos + obj_size + (obj_size % 4)
                    if next_pos > len(data):
                        # Object continues in next log container
                        break
                    pos += OBJ_HEADER_BASE_STRUCT.size

                    # Read rest of header
                    header_version = header[2]
                    if header_version == 1:
                        flags, _, _, timestamp = OBJ_HEADER_V1_STRUCT.unpack_from(data, pos)
                        pos += OBJ_HEADER_V1_STRUCT.size
                    elif header_version == 2:
                        flags, _, _, timestamp, _ = OBJ_HEADER_V2_STRUCT.unpack_from(data, pos)
                        pos += OBJ_HEADER_V2_STRUCT.size
                    else:
                        # Unknown header version
                        LOG.warning("Unknown object header version (%d)", header_version)
                        pos = next_pos
                        continue

                    if flags == TIME_TEN_MICS:
                        factor = 10 * 1e-6
                    else:
                        factor = 1e-9
                    timestamp = timestamp * factor + self.start_timestamp

                    obj_type = header[4]
                    # Both CAN message types have the same starting content
                    if obj_type in (CAN_MESSAGE, CAN_MESSAGE2):
                        (channel, flags, dlc, can_id,
                         can_data) = CAN_MSG_STRUCT.unpack_from(data, pos)
                        msg = Message(timestamp=timestamp,
                                      arbitration_id=can_id & 0x1FFFFFFF,
                                      extended_id=bool(can_id & CAN_MSG_EXT),
                                      is_remote_frame=bool(flags & REMOTE_FLAG),
                                      dlc=dlc,
                                      data=can_data[:dlc],
                                      channel=channel - 1)
                        yield msg
                    elif obj_type == CAN_FD_MESSAGE:
                        (channel, flags, dlc, can_id, _, _, fd_flags,
                         _, can_data) = CAN_FD_MSG_STRUCT.unpack_from(data, pos)
                        length = dlc2len(dlc)
                        msg = Message(timestamp=timestamp,
                                      arbitration_id=can_id & 0x1FFFFFFF,
                                      extended_id=bool(can_id & CAN_MSG_EXT),
                                      is_remote_frame=bool(flags & REMOTE_FLAG),
                                      is_fd=bool(fd_flags & EDL),
                                      bitrate_switch=bool(fd_flags & BRS),
                                      error_state_indicator=bool(fd_flags & ESI),
                                      dlc=length,
                                      data=can_data[:length],
                                      channel=channel - 1)
                        yield msg
                    elif obj_type == CAN_ERROR_EXT:
                        (channel, _, _, _, _, dlc, _, can_id, _,
                         can_data) = CAN_ERROR_EXT_STRUCT.unpack_from(data, pos)
                        msg = Message(timestamp=timestamp,
                                      is_error_frame=True,
                                      extended_id=bool(can_id & CAN_MSG_EXT),
                                      arbitration_id=can_id & 0x1FFFFFFF,
                                      dlc=dlc,
                                      data=can_data[:dlc],
                                      channel=channel - 1)
                        yield msg

                    pos = next_pos

                # save the remaining data that could not be processed
                tail = data[pos:]

        self.stop()
コード例 #7
0
ファイル: canlib.py プロジェクト: XelaRellum/python-can
    def _recv_internal(self, timeout):
        end_time = time.time() + timeout if timeout is not None else None

        if self.fd:
            event = vxlapi.XLcanRxEvent()
        else:
            event = vxlapi.XLevent()
            event_count = ctypes.c_uint()

        while True:
            if self.fd:
                try:
                    vxlapi.xlCanReceive(self.port_handle, event)
                except VectorError as exc:
                    if exc.error_code != vxlapi.XL_ERR_QUEUE_IS_EMPTY:
                        raise
                else:
                    if event.tag == vxlapi.XL_CAN_EV_TAG_RX_OK or event.tag == vxlapi.XL_CAN_EV_TAG_TX_OK:
                        msg_id = event.tagData.canRxOkMsg.canId
                        dlc = dlc2len(event.tagData.canRxOkMsg.dlc)
                        flags = event.tagData.canRxOkMsg.msgFlags
                        timestamp = event.timeStamp * 1e-9
                        channel = self.index_to_channel.get(event.chanIndex)
                        msg = Message(
                            timestamp=timestamp + self._time_offset,
                            arbitration_id=msg_id & 0x1FFFFFFF,
                            extended_id=bool(msg_id & vxlapi.XL_CAN_EXT_MSG_ID),
                            is_remote_frame=bool(flags & vxlapi.XL_CAN_RXMSG_FLAG_RTR),
                            is_error_frame=bool(flags & vxlapi.XL_CAN_RXMSG_FLAG_EF),
                            is_fd=bool(flags & vxlapi.XL_CAN_RXMSG_FLAG_EDL),
                            error_state_indicator=bool(flags & vxlapi.XL_CAN_RXMSG_FLAG_ESI),
                            bitrate_switch=bool(flags & vxlapi.XL_CAN_RXMSG_FLAG_BRS),
                            dlc=dlc,
                            data=event.tagData.canRxOkMsg.data[:dlc],
                            channel=channel)
                        return msg, self._is_filtered
            else:
                event_count.value = 1
                try:
                    vxlapi.xlReceive(self.port_handle, event_count, event)
                except VectorError as exc:
                    if exc.error_code != vxlapi.XL_ERR_QUEUE_IS_EMPTY:
                        raise
                else:
                    if event.tag == vxlapi.XL_RECEIVE_MSG:
                        msg_id = event.tagData.msg.id
                        dlc = event.tagData.msg.dlc
                        flags = event.tagData.msg.flags
                        timestamp = event.timeStamp * 1e-9
                        channel = self.index_to_channel.get(event.chanIndex)
                        msg = Message(
                            timestamp=timestamp + self._time_offset,
                            arbitration_id=msg_id & 0x1FFFFFFF,
                            extended_id=bool(msg_id & vxlapi.XL_CAN_EXT_MSG_ID),
                            is_remote_frame=bool(flags & vxlapi.XL_CAN_MSG_FLAG_REMOTE_FRAME),
                            is_error_frame=bool(flags & vxlapi.XL_CAN_MSG_FLAG_ERROR_FRAME),
                            is_fd=False,
                            dlc=dlc,
                            data=event.tagData.msg.data[:dlc],
                            channel=channel)
                        return msg, self._is_filtered

            if end_time is not None and time.time() > end_time:
                return None, self._is_filtered

            if HAS_EVENTS:
                # Wait for receive event to occur
                if timeout is None:
                    time_left_ms = INFINITE
                else:
                    time_left = end_time - time.time()
                    time_left_ms = max(0, int(time_left * 1000))
                WaitForSingleObject(self.event_handle.value, time_left_ms)
            else:
                # Wait a short time until we try again
                time.sleep(self.poll_interval)