예제 #1
0
    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))
예제 #2
0
    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})
예제 #3
0
    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)