예제 #1
0
def send_bcm(bcm_socket, data):
    """
    Send raw frame to a BCM socket and handle errors.

    :param socket:
    :param data:
    :return:
    """
    try:
        return bcm_socket.send(data)
    except OSError as e:
        base = "Couldn't send CAN BCM frame. OS Error {}: {}\n".format(
            e.errno, os.strerror(e.errno))

        if e.errno == errno.EINVAL:
            raise can.CanError(
                base + "You are probably referring to a non-existing frame.")

        elif e.errno == errno.ENETDOWN:
            raise can.CanError(base + "The CAN interface appears to be down.")

        elif e.errno == errno.EBADF:
            raise can.CanError(base + "The CAN socket appears to be closed.")

        else:
            raise e
예제 #2
0
    def send(self, msg, timeout=None):
        frame = _build_can_frame(msg)

        # Wait for write availability. write will fail below on timeout
        _, ready_send_sockets, _ = select.select([], [self.socket], [],
                                                 timeout)
        if not ready_send_sockets:
            raise can.CanError("Timeout while sending")

        # all sizes & lengths are in bytes
        total_sent = 0
        remaining = ctypes.sizeof(frame)
        while remaining > 0:
            # this might not send the entire frame
            # see: http://man7.org/linux/man-pages/man2/write.2.html
            bytes_sent = libc.write(self.socket,
                                    ctypes.byref(frame, total_sent), remaining)

            if bytes_sent == 0:
                raise can.CanError("Transmit buffer overflow")
            elif bytes_sent == -1:
                error_message = error_code_to_str(ctypes.get_errno())
                raise can.CanError(
                    "can.socketcan_ctypes failed to transmit: {}".format(
                        error_message))

            total_sent += bytes_sent
            remaining -= bytes_sent

        log.debug("Frame transmitted with %s bytes", bytes_sent)
예제 #3
0
    def open(self, configuration, flags):
        """
        Opens a CAN connection using `CanalOpen()`.

        :param str configuration: the configuration: "device_id; baudrate"
        :param int flags: the flags to be set

        :raises can.CanError: if any error occurred
        :returns: Valid handle for CANAL API functions on success
        """
        try:
            # we need to convert this into bytes, since the underlying DLL cannot
            # handle non-ASCII configuration strings
            config_ascii = configuration.encode("ascii", "ignore")
            result = self.__m_dllBasic.CanalOpen(config_ascii, flags)
        except Exception as ex:
            # catch any errors thrown by this call and re-raise
            raise can.CanError(
                'CanalOpen() failed, configuration: "{}", error: {}'.format(
                    configuration, ex))
        else:
            # any greater-than-zero return value indicates a success
            # (see https://grodansparadis.gitbooks.io/the-vscp-daemon/canal_interface_specification.html)
            # raise an error if the return code is <= 0
            if result <= 0:
                raise can.CanError(
                    'CanalOpen() failed, configuration: "{}", return code: {}'.
                    format(configuration, result))
            else:
                return result
예제 #4
0
    def recv(
        self,
        timeout: Optional[float] = None
    ) -> Optional[Tuple[bytes, IP_ADDRESS_INFO, float]]:
        """
        Receive up to **max_buffer** bytes.

        :param timeout: the timeout in seconds after which `None` is returned if no data arrived
        :returns: `None` on timeout, or a 3-tuple comprised of:
            - received data,
            - the sender of the data, and
            - a timestamp in seconds
        """
        # get all sockets that are ready (can be a list with a single value
        # being self.socket or an empty list if self.socket is not ready)
        try:
            # get all sockets that are ready (can be a list with a single value
            # being self.socket or an empty list if self.socket is not ready)
            ready_receive_sockets, _, _ = select.select([self._socket], [], [],
                                                        timeout)
        except socket.error as exc:
            # something bad (not a timeout) happened (e.g. the interface went down)
            raise can.CanError(f"Failed to wait for IP/UDP socket: {exc}")

        if ready_receive_sockets:  # not empty
            # fetch data & source address
            (
                raw_message_data,
                ancillary_data,
                _,  # flags
                sender_address,
            ) = self._socket.recvmsg(self.max_buffer,
                                     self.received_ancillary_buffer_size)

            # fetch timestamp; this is configured in in _create_socket()
            assert len(
                ancillary_data) == 1, "only requested a single extra field"
            cmsg_level, cmsg_type, cmsg_data = ancillary_data[0]
            assert (cmsg_level == socket.SOL_SOCKET
                    and cmsg_type == SO_TIMESTAMPNS
                    ), "received control message type that was not requested"
            # see https://man7.org/linux/man-pages/man3/timespec.3.html -> struct timespec for details
            seconds, nanoseconds = struct.unpack(
                self.received_timestamp_struct, cmsg_data)
            if nanoseconds >= 1e9:
                raise can.CanError(
                    f"Timestamp nanoseconds field was out of range: {nanoseconds} not less than 1e9"
                )
            timestamp = seconds + nanoseconds * 1.0e-9

            return raw_message_data, sender_address, timestamp

        # socket wasn't readable or timeout occurred
        return None
예제 #5
0
    def send(self, msg, timeout=None):
        frame = _build_can_frame(msg)
        if timeout:
            # Wait for write availability. write will fail below on timeout
            select.select([], [self.socket], [], timeout)
        bytes_sent = libc.write(self.socket, ctypes.byref(frame),
                                ctypes.sizeof(frame))
        if bytes_sent == -1:
            log.debug("Error sending frame :-/")
            raise can.CanError("can.socketcan.ctypes failed to transmit")
        elif bytes_sent == 0:
            raise can.CanError("Transmit buffer overflow")

        log.debug("Frame transmitted with %s bytes", bytes_sent)
예제 #6
0
    def send(self, msg: can.Message, timeout: Optional[float] = None):
        """Transmit a message to the CAN bus.

        :param Message msg: A message object.
        :param timeout: timeout is not supported.
            The function won't return until message is sent or exception is raised.

        :raises can.CanError:
            if the message could not be sent
        """
        can_id = msg.arbitration_id

        if msg.is_extended_id:
            can_id = can_id | CAN_EFF_FLAG

        if msg.is_remote_frame:
            can_id = can_id | CAN_RTR_FLAG

        if msg.is_error_frame:
            can_id = can_id | CAN_ERR_FLAG

        # Pad message data
        msg.data.extend([0x00] * (CAN_MAX_DLC - len(msg.data)))

        frame = GsUsbFrame()
        frame.can_id = can_id
        frame.can_dlc = msg.dlc
        frame.timestamp_us = int(msg.timestamp * 1000000)
        frame.data = list(msg.data)

        try:
            self.gs_usb.send(frame)
        except usb.core.USBError:
            raise can.CanError("The message can not be sent")
예제 #7
0
    def __init__(self,
                 channel='vcan0',
                 receive_own_messages=False,
                 *args,
                 **kwargs):
        """
        :param str channel:
            The can interface name with which to create this bus. An example channel
            would be 'vcan0'.
        """

        self.socket = createSocket()
        self.channel = channel

        log.debug("Result of createSocket was %d", self.socket)

        # Add any socket options such as can frame filters
        if 'can_filters' in kwargs and len(kwargs['can_filters']) > 0:
            log.debug("Creating a filtered can bus")
            self.set_filters(kwargs['can_filters'])

        error = bindSocket(self.socket, channel)
        if error < 0:
            m = u'bindSocket failed for channel {} with error {}'.format(
                channel, error)
            raise can.CanError(m)

        if receive_own_messages:
            error1 = recv_own_msgs(self.socket)

        super(SocketcanCtypes_Bus, self).__init__(*args, **kwargs)
예제 #8
0
    def __init__(self, channel, receive_own_messages=False, *args, **kwargs):
        """
        :param str channel:
            The can interface name with which to create this bus. An example channel
            would be 'vcan0' or 'can0'.
        """

        self.socket = createSocket()
        self.channel = channel
        self.channel_info = "ctypes socketcan channel '%s'" % channel

        log.debug("Result of createSocket was %d", self.socket)

        error = bindSocket(self.socket, channel)
        if error < 0:
            m = u'bindSocket failed for channel {} with error {}'.format(
                channel, error)
            raise can.CanError(m)

        if receive_own_messages:
            error1 = recv_own_msgs(self.socket)
            # TODO handle potential error

        self._is_filtered = False
        kwargs.update({'receive_own_messages': receive_own_messages})
        super(SocketcanCtypes_Bus, self).__init__(channel=channel,
                                                  *args,
                                                  **kwargs)
예제 #9
0
 def send(self, handle, msg):
     try:
         res = self.__m_dllBasic.CanalSend(handle, msg)
         return res
     except:
         log.warning('Sending error')
         raise can.CanError("Failed to transmit frame")
예제 #10
0
    def send(self, msg, timeout=None):
        log.debug("We've been asked to write a message to the bus")
        logger_tx = log.getChild("tx")
        logger_tx.debug("sending: %s", msg)
        if timeout:
            # Wait for write availability
            _, ready_send_sockets, _ = select.select([], [self.socket], [],
                                                     timeout)
            if not ready_send_sockets:
                raise can.CanError("Timeout while sending")

        try:
            bytes_sent = self.socket.send(build_can_frame(msg))
        except OSError as exc:
            raise can.CanError("Transmit failed (%s)" % exc)

        if bytes_sent == 0:
            raise can.CanError("Transmit buffer overflow")
예제 #11
0
    def send(self, msg, timeout=None):
        frame = _build_can_frame(msg)
        bytes_sent = libc.write(self.socket, ctypes.byref(frame),
                                ctypes.sizeof(frame))
        if bytes_sent == -1:
            logging.debug("Error sending frame :-/")
            raise can.CanError("can.socketcan.ctypes failed to transmit")

        logging.debug("Frame transmitted with %s bytes", bytes_sent)
예제 #12
0
    def send(self, msg, timeout=None):
        log.debug("We've been asked to write a message to the bus")
        logger_tx = log.getChild("tx")
        logger_tx.debug("sending: %s", msg)

        if timeout:
            # Wait for write availability
            _, ready_send_sockets, _ = select.select([], [self.socket], [],
                                                     timeout)
            if not ready_send_sockets:
                raise can.CanError("Timeout while sending")

        try:
            self.socket.sendall(build_can_frame(msg))
        except OSError as exc:
            error_message = error_code_to_str(exc.errno)
            raise can.CanError(
                "can.socketcan_native failed to transmit: {}".format(
                    error_message))
예제 #13
0
 def _send_once(self, data: bytes, channel: Optional[str] = None) -> int:
     try:
         if self.channel == "" and channel:
             # Message must be addressed to a specific channel
             sent = self.socket.sendto(data, (channel,))
         else:
             sent = self.socket.send(data)
     except socket.error as exc:
         raise can.CanError("Failed to transmit: %s" % exc)
     return sent
예제 #14
0
    def from_buffer(cls, buf):
        try:
            length, = struct.unpack_from('B', buf)
        except struct.error:
            raise NeedMoreDataError()

        if len(buf) - 1 < length:
            raise NeedMoreDataError()

        text = buf[1:1 + length].decode('utf-8')
        return cls(can.CanError(text))
예제 #15
0
 def send(self, msg, timeout=None):
     log.debug("We've been asked to write a message to the bus")
     arbitration_id = msg.arbitration_id
     if msg.id_type:
         log.debug("sending an extended id type message")
         arbitration_id |= 0x80000000
     if msg.is_remote_frame:
         log.debug("requesting a remote frame")
         arbitration_id |= 0x40000000
     if msg.is_error_frame:
         log.warning("Trying to send an error frame - this won't work")
         arbitration_id |= 0x20000000
     log_tx.debug("Sending: %s", msg)
     if timeout:
         # Wait for write availability. send will fail below on timeout
         select.select([], [self.socket], [], timeout)
     try:
         bytes_sent = self.socket.send(
             build_can_frame(arbitration_id, msg.data))
     except OSError as exc:
         raise can.CanError("Transmit failed (%s)" % exc)
     if bytes_sent == 0:
         raise can.CanError("Transmit buffer overflow")
예제 #16
0
 def initialize_nodes(self):
     try:
         # For some reason, reconnect is needed...
         self.connect()
         self.network.scanner.search()
         # Give time to complete the search process
         time.sleep(0.5)
         self.logger.info(
             f"CAN Network scan result: nodes number {self.network.scanner.nodes}"
         )
         for node_id in self.network.scanner.nodes:
             new_node = BaseNode402(node_id, 'LOVATO_VLB3.eds')
             self.network.add_node(new_node)
             new_node.nmt.state = "PRE-OPERATIONAL"
             time.sleep(0.2)
             new_node.rpdo.read()
             new_node.tpdo.read()
             new_node.rpdo[1].enable = True
             new_node.rpdo[1].start(0.05)
             new_node.rpdo[1]['CiA: Controlword'].bits[0] = 1
             new_node.rpdo[1]['CiA: Controlword'].bits[1] = 1
             new_node.rpdo[1]['CiA: Controlword'].bits[3] = 1
             new_node.nmt.state = 'OPERATIONAL'
             new_node.rpdo[1]['CiA: Controlword'].bits[0] = 1
             new_node.rpdo[1]['CiA: Controlword'].bits[1] = 1
             new_node.rpdo[1]['CiA: Controlword'].bits[3] = 1
             time.sleep(0.2)
             self.reset_faulty_node(new_node)
             new_node.rpdo[1][
                 'CiA: Controlword'].raw = self.SWITCH_ON_DISABLED
             self.nodes_list.append(new_node)
         if len(self.nodes_list) > 0:
             self.logger.info(
                 f"Node number {self.nodes_list[0].id} identified")
         else:
             self.logger.warning("No nodes found...")
     except can.CanError:
         self.connected = False
         self.logger.error(
             "Connection was successful but no active node is completing the bus,"
             " meaning that communication is impossible. Please setup a node before"
             " trying to connect again")
         raise can.CanError(
             "Connection was successful but no active node is completing the bus,"
             " meaning that communication is impossible. Please setup a node before"
             " trying to connect again")
     # Wait before setting all to ready
     time.sleep(0.5)
     self.set_network_state(self.SWITCHED_ON)
예제 #17
0
 def connect(self):
     try:
         self.network = canopen.Network()
         self.network.connect(bitrate=self.bitrate,
                              channel=self.interface_name,
                              bustype=self.bustype)
         self.connected = True
     except OSError:
         self.connected = False
         self.logger.error(
             f"Could not connect on  the {self.interface_name} interface."
             " A reboot will probably solve the problem")
         raise can.CanError(
             f"Could not connect on  the {self.interface_name} interface."
             " A reboot will probably solve the problem")
예제 #18
0
 def _send_once(self, data, channel=None):
     try:
         if self.channel == "" and channel:
             # Message must be addressed to a specific channel
             if HAS_NATIVE_SUPPORT:
                 sent = self.socket.sendto(data, (channel, ))
             else:
                 addr = get_addr(self.socket, channel)
                 sent = libc.sendto(self.socket.fileno(), data, len(data),
                                    0, addr, len(addr))
         else:
             sent = self.socket.send(data)
     except socket.error as exc:
         raise can.CanError("Failed to transmit: %s" % exc)
     return sent
예제 #19
0
    def __new__(cls, other, channel, *args, **kwargs):

        config = load_config(config={'channel': channel})

        # Import the correct implementation of CyclicSendTask
        if config['interface'] == 'socketcan_ctypes':
            from can.interfaces.socketcan.socketcan_ctypes import CyclicSendTask as _ctypesCyclicSendTask
            cls = _ctypesCyclicSendTask
        elif config['interface'] == 'socketcan_native':
            from can.interfaces.socketcan.socketcan_native import CyclicSendTask as _nativeCyclicSendTask
            cls = _nativeCyclicSendTask
        else:
            raise can.CanError(
                "Current CAN interface doesn't support CyclicSendTask")

        return cls(config['channel'], *args, **kwargs)
예제 #20
0
    def __init__(self, channel, bus, address, bitrate, can_filters=None, **kwargs):
        """
        :param channel: usb device name
        :param bus: number of the bus that the device is connected to
        :param address: address of the device on the bus it is connected to
        :param can_filters: not supported
        :param bitrate: CAN network bandwidth (bits/s)
        """
        gs_usb = GsUsb.find(bus=bus, address=address)
        if not gs_usb:
            raise can.CanError("Can not find device {}".format(channel))
        self.gs_usb = gs_usb
        self.channel_info = channel

        self.gs_usb.set_bitrate(bitrate)
        self.gs_usb.start()

        super().__init__(channel=channel, can_filters=can_filters, **kwargs)
예제 #21
0
 def send(self, msg, timeout=None):
     log.debug("We've been asked to write a message to the bus")
     arbitration_id = msg.arbitration_id
     if msg.id_type:
         log.debug("sending an extended id type message")
         arbitration_id |= 0x80000000
     if msg.is_remote_frame:
         log.debug("requesting a remote frame")
         arbitration_id |= 0x40000000
     if msg.is_error_frame:
         log.warning("Trying to send an error frame - this won't work")
         arbitration_id |= 0x20000000
     l = log.getChild("tx")
     l.debug("sending: %s", msg)
     try:
         self.socket.send(build_can_frame(arbitration_id, msg.data))
     except OSError:
         l.warning("Failed to send: %s", msg)
         raise can.CanError("can.socketcan.native failed to transmit")
예제 #22
0
def bindSocket(socketID, channel_name):
    """
    Binds the given socket to the given interface.

    :param int socketID:
        The ID of the socket to be bound

    :param str channel_name:
        The interface name to find and bind.

    :return:
        The error code from the bind call.

        +----+----------------------------+
        | 0  |protocol invalid            |
        +----+----------------------------+
        | -1 |socket creation unsuccessful|
        +----+----------------------------+
    """
    log.debug('Binding socket with id %d to channel %s', socketID,
              channel_name)
    socketID = ctypes.c_int(socketID)

    ifr = IFREQ()
    ifr.ifr_name = channel_name.encode('ascii')
    log.debug('calling ioctl SIOCGIFINDEX')
    # ifr.ifr_ifindex gets filled with that device's index
    ret = libc.ioctl(socketID, SIOCGIFINDEX, ctypes.byref(ifr))
    if ret < 0:
        m = u'Failure while getting "{}" interface index.'.format(channel_name)
        raise can.CanError(m)
    log.info('ifr.ifr_ifindex: %d', ifr.ifr_ifindex)

    # select the CAN interface and bind the socket to it
    addr = SOCKADDR_CAN(AF_CAN, ifr.ifr_ifindex)

    error = libc.bind(socketID, ctypes.byref(addr), ctypes.sizeof(addr))

    if error < 0:
        log.error("Couldn't bind socket")
    log.debug('bind returned: %d', error)

    return error
예제 #23
0
    def _recv_internal(
        self, timeout: Optional[float]
    ) -> Tuple[Optional[Message], bool]:
        try:
            # get all sockets that are ready (can be a list with a single value
            # being self.socket or an empty list if self.socket is not ready)
            ready_receive_sockets, _, _ = select.select([self.socket], [], [], timeout)
        except socket.error as exc:
            # something bad happened (e.g. the interface went down)
            raise can.CanError(f"Failed to receive: {exc}")

        if ready_receive_sockets:  # not empty
            get_channel = self.channel == ""
            msg = capture_message(self.socket, get_channel)
            if msg and not msg.channel and self.channel:
                # Default to our own channel
                msg.channel = self.channel
            return msg, self._is_filtered

        # socket wasn't readable or timeout occurred
        return None, self._is_filtered
예제 #24
0
    def __new__(cls, other, channel, *args, **kwargs):

        config = load_config(config={'channel': channel})

        # Import the correct implementation of CyclicSendTask
        if config['interface'] == 'socketcan_ctypes':
            from can.interfaces.socketcan.socketcan_ctypes import CyclicSendTask as _ctypesCyclicSendTask
            cls = _ctypesCyclicSendTask
        elif config['interface'] == 'socketcan_native':
            from can.interfaces.socketcan.socketcan_native import CyclicSendTask as _nativeCyclicSendTask
            cls = _nativeCyclicSendTask
        # CyclicSendTask has not been fully implemented on remote interface yet.
        # Waiting for issue #80 which will change the API to make it easier for
        # interfaces other than socketcan to implement it
        #elif can.rc['interface'] == 'remote':
        #    from can.interfaces.remote import CyclicSendTask as _remoteCyclicSendTask
        #    cls = _remoteCyclicSendTask
        else:
            raise can.CanError(
                "Current CAN interface doesn't support CyclicSendTask")

        return cls(config['channel'], *args, **kwargs)
예제 #25
0
    def send(self, msg: Message, timeout: Optional[float] = None) -> None:
        """Transmit a message to the CAN bus.

        :param msg: A message object.
        :param timeout:
            Wait up to this many seconds for the transmit queue to be ready.
            If not given, the call may fail immediately.

        :raises can.CanError:
            if the message could not be written.
        """
        log.debug("We've been asked to write a message to the bus")
        logger_tx = log.getChild("tx")
        logger_tx.debug("sending: %s", msg)

        started = time.time()
        # If no timeout is given, poll for availability
        if timeout is None:
            timeout = 0
        time_left = timeout
        data = build_can_frame(msg)

        while time_left >= 0:
            # Wait for write availability
            ready = select.select([], [self.socket], [], time_left)[1]
            if not ready:
                # Timeout
                break
            channel = str(msg.channel) if msg.channel else None
            sent = self._send_once(data, channel)
            if sent == len(data):
                return
            # Not all data were sent, try again with remaining data
            data = data[sent:]
            time_left = timeout - (time.time() - started)

        raise can.CanError("Transmit buffer full")
예제 #26
0
def capture_message(sock, get_channel=False):
    """
    Captures a message from given socket.

    :param socket.socket sock:
        The socket to read a message from.
    :param bool get_channel:
        Find out which channel the message comes from.

    :return: The received message, or None on failure.
    """
    # Fetching the Arb ID, DLC and Data
    try:
        if get_channel:
            if HAS_NATIVE_SUPPORT:
                cf, addr = sock.recvfrom(CANFD_MTU)
                channel = addr[0] if isinstance(addr, tuple) else addr
            else:
                data = ctypes.create_string_buffer(CANFD_MTU)
                addr = ctypes.create_string_buffer(32)
                addrlen = ctypes.c_int(len(addr))
                received = libc.recvfrom(sock.fileno(), data, len(data), 0,
                                         addr, ctypes.byref(addrlen))
                cf = data.raw[:received]
                # Figure out the channel name
                family, ifindex = struct.unpack_from("Hi", addr.raw)
                assert family == AF_CAN
                data = struct.pack("16xi", ifindex)
                res = fcntl.ioctl(sock, SIOCGIFNAME, data)
                channel = ctypes.create_string_buffer(res).value.decode()
        else:
            cf = sock.recv(CANFD_MTU)
            channel = None
    except socket.error as exc:
        raise can.CanError("Error receiving: %s" % exc)

    can_id, can_dlc, flags, data = dissect_can_frame(cf)
    #log.debug('Received: can_id=%x, can_dlc=%x, data=%s', can_id, can_dlc, data)

    # Fetching the timestamp
    binary_structure = "@LL"
    res = fcntl.ioctl(sock, SIOCGSTAMP, struct.pack(binary_structure, 0, 0))

    seconds, microseconds = struct.unpack(binary_structure, res)
    timestamp = seconds + microseconds * 1e-6

    # EXT, RTR, ERR flags -> boolean attributes
    #   /* special address description flags for the CAN_ID */
    #   #define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
    #   #define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
    #   #define CAN_ERR_FLAG 0x20000000U /* error frame */
    is_extended_frame_format = bool(can_id & CAN_EFF_FLAG)
    is_remote_transmission_request = bool(can_id & CAN_RTR_FLAG)
    is_error_frame = bool(can_id & CAN_ERR_FLAG)
    is_fd = len(cf) == CANFD_MTU
    bitrate_switch = bool(flags & CANFD_BRS)
    error_state_indicator = bool(flags & CANFD_ESI)

    if is_extended_frame_format:
        #log.debug("CAN: Extended")
        # TODO does this depend on SFF or EFF?
        arbitration_id = can_id & 0x1FFFFFFF
    else:
        #log.debug("CAN: Standard")
        arbitration_id = can_id & 0x000007FF

    msg = Message(timestamp=timestamp,
                  channel=channel,
                  arbitration_id=arbitration_id,
                  is_extended_id=is_extended_frame_format,
                  is_remote_frame=is_remote_transmission_request,
                  is_error_frame=is_error_frame,
                  is_fd=is_fd,
                  bitrate_switch=bitrate_switch,
                  error_state_indicator=error_state_indicator,
                  dlc=can_dlc,
                  data=data)

    #log_rx.debug('Received: %s', msg)

    return msg
예제 #27
0
 def check_status(result, function, arguments):
     if result < 0:
         raise can.CanError(error_code_to_str(ctypes.get_errno()))
     return result
예제 #28
0
 def test_exception(self):
     event1 = events.RemoteException(can.CanError('This is an error'))
     buf = event1.encode()
     event2 = events.RemoteException.from_buffer(buf)
     self.assertEqual(str(event1.exc), str(event2.exc))
     self.assertEqual(len(event2), len(buf))
예제 #29
0
def raise_error(msg):
    raise can.CanError('This is some error')
예제 #30
0
    def _recv_internal(self, timeout):
        if len(self.__message_buffer) != 0:
            can_message = self.__message_buffer.popleft()
            return can_message, False

        try:
            # get all sockets that are ready (can be a list with a single value
            # being self.socket or an empty list if self.socket is not ready)
            ready_receive_sockets, _, _ = select.select([self.__socket], [],
                                                        [], timeout)
        except socket.error as exc:
            # something bad happened (e.g. the interface went down)
            log.error(f"Failed to receive: {exc}")
            raise can.CanError(f"Failed to receive: {exc}")

        try:
            if not ready_receive_sockets:
                # socket wasn't readable or timeout occurred
                log.debug("Socket not ready")
                return None, False

            ascii_msg = self.__socket.recv(1024).decode(
                "ascii")  # may contain multiple messages
            self.__receive_buffer += ascii_msg
            log.debug(f"Received Ascii Message: {ascii_msg}")
            buffer_view = self.__receive_buffer
            chars_processed_successfully = 0
            while True:
                if len(buffer_view) == 0:
                    break

                start = buffer_view.find("<")
                if start == -1:
                    log.warning(
                        f"Bad data: No opening < found => discarding entire buffer '{buffer_view}'"
                    )
                    chars_processed_successfully = len(self.__receive_buffer)
                    break
                end = buffer_view.find(">")
                if end == -1:
                    log.warning(
                        "Got incomplete message => waiting for more data")
                    if len(buffer_view) > 200:
                        log.warning(
                            "Incomplete message exceeds 200 chars => Discarding"
                        )
                        chars_processed_successfully = len(
                            self.__receive_buffer)
                    break
                chars_processed_successfully += end + 1
                single_message = buffer_view[start:end + 1]
                parsed_can_message = convert_ascii_message_to_can_message(
                    single_message)
                if parsed_can_message is None:
                    log.warning(f"Invalid Frame: {single_message}")
                else:
                    self.__message_buffer.append(parsed_can_message)
                buffer_view = buffer_view[end + 1:]

            self.__receive_buffer = self.__receive_buffer[
                chars_processed_successfully + 1:]
            can_message = (None if len(self.__message_buffer) == 0 else
                           self.__message_buffer.popleft())
            return can_message, False

        except Exception as exc:
            log.error(f"Failed to receive: {exc}  {traceback.format_exc()}")
            raise can.CanError(
                f"Failed to receive: {exc}  {traceback.format_exc()}")