def get(self, block=True, timeout=None): """ Returns the first element of the queue if there is some element ready before timeout expires, in case of the timeout is not ``None``. If timeout is ``None``, this method is non-blocking. In this case, if there isn't any element available, it returns ``None``, otherwise it returns an :class:`.XBeeAPIPacket`. Args: block (Boolean): ``True`` to block during ``timeout`` waiting for a packet, ``False`` to not block. timeout (Integer, optional): timeout in seconds. Returns: :class:`.XBeeAPIPacket`: a packet if there is any packet available before ``timeout`` expires. If ``timeout`` is ``None``, the returned value may be ``None``. Raises: TimeoutException: if ``timeout`` is not ``None`` and there isn't any packet available before the timeout expires. """ if timeout is None: try: xbee_packet = Queue.get(self, block=False) except (Empty, ValueError): xbee_packet = None return xbee_packet else: try: return Queue.get(self, True, timeout) except Empty: raise TimeoutException()
def send(self): """ Sends the packet and waits for its corresponding response. Returns: :class:`.XBeePacket`: Received response packet. Raises: InvalidOperatingModeException: If the XBee device's operating mode is not API or ESCAPED API. This method only checks the cached value of the operating mode. TimeoutException: If the response is not received in the configured timeout. XBeeException: If the XBee device's communication interface is closed. .. seealso:: | :class:`.XBeePacket` """ # Add the packet received callback. if self._packet.needs_id(): self._xbee.add_packet_received_callback(self._packet_received_cb) try: # Send the packet. self._xbee.send_packet(self._packet, sync=False) if not self._packet.needs_id(): return None # Wait for response or timeout. self._lock.acquire() if self._timeout == -1: self._lock.wait() else: self._lock.wait(self._timeout) self._lock.release() # After waiting check if we received any response, if not throw a # timeout exception. if not self._response_list: raise TimeoutException( message="Response not received in the configured timeout.") # Return the received packet. return self._response_list[0] finally: # Always remove the packet listener from the list. if self._packet.needs_id(): self._xbee.del_packet_received_callback( self._packet_received_cb)
def get_by_remote(self, remote_xbee_device, timeout=None): """ Returns the first element of the queue that had been sent by ``remote_xbee_device``, if there is some in the specified timeout. If timeout is ``None``, this method is non-blocking. In this case, if there isn't any packet sent by ``remote_xbee_device`` in the queue, it returns ``None``, otherwise it returns an :class:`.XBeeAPIPacket`. Args: remote_xbee_device (:class:`.RemoteXBeeDevice`): the remote XBee device to get its firs element from queue. timeout (Integer, optional): timeout in seconds. Returns: :class:`.XBeeAPIPacket`: if there is any packet available before the timeout expires. If timeout is ``None``, the returned value may be ``None``. Raises: TimeoutException: if timeout is not ``None`` and there isn't any packet available that has been sent by ``remote_xbee_device`` before the timeout expires. """ if timeout is None: with self.mutex: for xbee_packet in self.queue: if self.__remote_device_match(xbee_packet, remote_xbee_device): self.queue.remove(xbee_packet) return xbee_packet return None else: xbee_packet = self.get_by_remote(remote_xbee_device, None) dead_line = time.time() + timeout while xbee_packet is None and dead_line > time.time(): time.sleep(0.1) xbee_packet = self.get_by_remote(remote_xbee_device, None) if xbee_packet is None: raise TimeoutException() return xbee_packet
def get_by_id(self, frame_id, timeout=None): """ Returns the first packet from the queue whose frame ID matches the provided one. If timeout is ``None``, this method is non-blocking. In this case, if there isn't any received packet with the provided frame ID in the queue, it returns ``None``, otherwise it returns an :class:`.XBeeAPIPacket`. Args: frame_id (Integer): The frame ID to look for in the list of packets. timeout (Integer, optional): Timeout in seconds. Returns: :class:`.XBeeAPIPacket`: if there is any packet available before the timeout expires. If timeout is ``None``, the returned value may be ``None``. Raises: TimeoutException: if timeout is not ``None`` and there isn't any packet available that matches the provided frame ID before the timeout expires. """ if timeout is None: with self.mutex: for xbee_packet in self.queue: if xbee_packet.needs_id( ) and xbee_packet.frame_id == frame_id: self.queue.remove(xbee_packet) return xbee_packet return None else: xbee_packet = self.get_by_id(frame_id, None) dead_line = time.time() + timeout while xbee_packet is None and dead_line > time.time(): time.sleep(0.1) xbee_packet = self.get_by_id(frame_id, None) if xbee_packet is None: raise TimeoutException() return xbee_packet
def get_by_ip(self, ip_addr, timeout=None): """ Returns the first IP data packet from the queue whose IP address matches the provided address. If timeout is ``None``, this method is non-blocking. In this case, if there isn't any packet sent by ``remote_xbee_device`` in the queue, it returns ``None``, otherwise it returns an :class:`.XBeeAPIPacket`. Args: ip_addr (:class:`ipaddress.IPv4Address`): The IP address to look for in the list of packets. timeout (Integer, optional): Timeout in seconds. Returns: :class:`.XBeeAPIPacket`: if there is any packet available before the timeout expires. If timeout is ``None``, the returned value may be ``None``. Raises: TimeoutException: if timeout is not ``None`` and there isn't any packet available that has been sent by ``remote_xbee_device`` before the timeout expires. """ if timeout is None: with self.mutex: for xbee_packet in self.queue: if self.__ip_addr_match(xbee_packet, ip_addr): self.queue.remove(xbee_packet) return xbee_packet return None else: xbee_packet = self.get_by_ip(ip_addr, None) dead_line = time.time() + timeout while xbee_packet is None and dead_line > time.time(): time.sleep(0.1) xbee_packet = self.get_by_ip(ip_addr, None) if xbee_packet is None: raise TimeoutException() return xbee_packet
def connect(self, address): """ Connects to a remote socket at the given address. Args: address (Tuple): A pair ``(host, port)`` where ``host`` is the domain name or string representation of an IPv4 and ``port`` is the numeric port value. Raises: TimeoutException: if the connect response is not received in the configured timeout. ValueError: if ``address`` is ``None`` or not a pair ``(host, port)``. ValueError: if ``port`` is less than 1 or greater than 65535. XBeeException: if the connection with the XBee device is not open. XBeeSocketException: if the connect status is not ``SUCCESS``. """ # Check address and its contents. if address is None or len(address) != 2: raise ValueError( "Invalid address, it must be a pair (host, port).") host = address[0] port = address[1] if isinstance(host, IPv4Address): host = str(host) if port < 1 or port > 65535: raise ValueError("Port number must be between 1 and 65535.") # If the socket is not created, create it first. if self.__socket_id is None: self.__create_socket() lock = threading.Condition() received_state = list() # Define the socket state received callback. def socket_state_received_callback(socket_id, state): # Check the socket ID. if socket_id != self.__socket_id: return # Add the state to the list and notify the lock. received_state.append(state) lock.acquire() lock.notify() lock.release() # Add the socket state received callback. self.__xbee_device.add_socket_state_received_callback( socket_state_received_callback) try: # Create, send and check the socket connect packet. connect_packet = SocketConnectPacket( self.__xbee_device.get_next_frame_id(), self.__socket_id, port, SocketConnectPacket.DEST_ADDRESS_STRING, host) response_packet = self.__xbee_device.send_packet_sync_and_get_response( connect_packet, timeout=self.__get_timeout()) self.__check_response(response_packet) # Wait until the socket state frame is received confirming the connection. if not received_state: lock.acquire() lock.wait(self.__timeout) lock.release() # Check if the socket state has been received. if not received_state: raise TimeoutException( "Timeout waiting for the socket connection") # Check if the socket is connected successfully. if received_state[0] != SocketState.CONNECTED: raise XBeeSocketException(status=received_state[0]) self.__connected = True # Register internal socket state and data reception callbacks. self.__register_state_callback() self.__register_data_received_callback() finally: # Always remove the socket state callback. self.__xbee_device.del_socket_state_received_callback( socket_state_received_callback)