def _is_valid_remote_at_response(self, packet): """ Checks if the provided packet is the remote AT command response packet that matches the sent package. Args: packet (:class:`.XBeeAPIPacket`): Packet to check. Returns: Boolean: `True` if packet is the remote AT command response packet corresponding to the sent package, `False` otherwise. """ # If the sent packet is a remote AT command, verify that the received # one is a remote AT command response and their commands match. return ( packet.get_frame_type() == ApiFrameType.REMOTE_AT_COMMAND_RESPONSE and self._packet.command.upper() == packet.command.upper() and (not XBee64BitAddress.is_known_node_addr( self._packet.x64bit_dest_addr) or self._packet.x64bit_dest_addr == packet.x64bit_source_addr) and (not XBee16BitAddress.is_known_node_addr( self._packet.x16bit_dest_addr) or not XBee16BitAddress.is_known_node_addr(packet.x16bit_source_addr) or self._packet.x16bit_dest_addr == packet.x16bit_source_addr))
def send_packet(self, packet): """ Sends a packet to the XBee. The packet to send is escaped depending on the current operating mode. Args: packet (:class:`.XBeePacket`): The packet to send. 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. XBeeException: if the XBee device's communication interface is closed. .. seealso:: | :class:`.XBeePacket` """ f_type = packet.get_frame_type() # Do not allow to set a non API operating mode in the local XBee if (f_type in (ApiFrameType.AT_COMMAND, ApiFrameType.AT_COMMAND_QUEUE) and packet.parameter and packet.command.upper() == ATStringCommand.AP.command and not self.is_op_mode_valid(packet.parameter)): return comm_iface = self.__xbee.comm_iface op_mode = self.__xbee.operating_mode if self.__xbee._serial_port: self.__xbee._update_tx_stats(packet) out = packet.output(escaped=op_mode == OperatingMode.ESCAPED_API_MODE) comm_iface.write_frame(out) self._log.debug( self._LOG_PATTERN.format(comm_iface=str(comm_iface), event="SENT", opmode=op_mode, content=utils.hex_to_string(out))) # Refresh cached parameters if this method modifies some of them. if self.__xbee.serial_port and f_type in ( ApiFrameType.AT_COMMAND, ApiFrameType.AT_COMMAND_QUEUE, ApiFrameType.REMOTE_AT_COMMAND_REQUEST): node = self.__xbee # Get remote node in case of a remote at command if (f_type == ApiFrameType.REMOTE_AT_COMMAND_REQUEST and XBee64BitAddress.is_known_node_addr( packet.x64bit_dest_addr)): node = self.__xbee.get_network().get_device_by_64( packet.x64bit_dest_addr) # Store the sent AT command packet if node: if not node.get_64bit_addr(): return key = str(node.get_64bit_addr()) if key not in self._at_cmds_sent: self._at_cmds_sent[key] = {} self._at_cmds_sent[key].update({packet.frame_id: packet})
def at_response_received_cb(self, response): """ Callback to deal with AT command responses and update the corresponding node. Only for internal use. Args: response (:class: `.XBeeAPIPacket`): The received API packet. """ f_type = response.get_frame_type() if f_type not in (ApiFrameType.AT_COMMAND_RESPONSE, ApiFrameType.REMOTE_AT_COMMAND_RESPONSE): return node = self.__xbee # Get remote node in case of a remote at command if (f_type == ApiFrameType.REMOTE_AT_COMMAND_RESPONSE and XBee64BitAddress.is_known_node_addr( response.x64bit_source_addr)): node = self.__xbee.get_network().get_device_by_64( response.x64bit_source_addr) if not node: return key = str(node.get_64bit_addr()) requests = self._at_cmds_sent.get(key, {}) req = requests.pop(response.frame_id, None) if not req or response.status != ATCommandStatus.OK: return def is_req_apply(at_req): fr_type = at_req.get_frame_type() return (at_req.command.upper() == ATStringCommand.AC.command or fr_type == ApiFrameType.AT_COMMAND or (fr_type == ApiFrameType.REMOTE_AT_COMMAND_REQUEST and at_req.transmit_options & RemoteATCmdOptions.APPLY_CHANGES.value)) def is_node_info_param(at_pkt): at_cmd = at_pkt.command.upper() return at_cmd in (ATStringCommand.NI.command, ATStringCommand.MY.command) def is_port_param(at_pkt): at_cmd = at_pkt.command.upper() return at_cmd in (ATStringCommand.AP.command, ATStringCommand.BD.command, ATStringCommand.NB.command, ATStringCommand.SB.command) apply = is_req_apply(req) if apply: if key not in self._future_apply: self._future_apply[key] = {} node_fut_apply = self._future_apply.get(key, {}) node_fut_apply.pop(req.command.upper(), None) for key, value in list(node_fut_apply.items()): self._refresh_if_cached(node, key, value, apply=True) if req.parameter and (is_port_param(req) or is_node_info_param(req)): self._refresh_if_cached(node, req.command.upper(), req.parameter, apply=apply)