示例#1
0
    def __parse_route(self, data):
        """
        Parses the given bytearray and returns a route.

        Args:
            data (bytearray): Bytearray with data to parse.

        Returns:
             :class:`.Route`: The route or ``None`` if not found.
        """
        # Bytes 0 - 1: 16-bit destination address (little endian)
        # Byte 2: Setting byte:
        #          * Bits 0 - 2: Route status
        #          * Bit 3: Low-memory concentrator flag
        #          * Bit 4: Destination is a concentrator flag
        #          * Bit 5: Route record message should be sent prior to next transmission flag
        # Bytes 3 - 4: 16 bit next hop address (little endian)
        return Route(
            XBee16BitAddress.from_bytes(data[1], data[0]),
            XBee16BitAddress.from_bytes(data[4], data[3]),
            RouteStatus.get(
                utils.get_int_from_byte(data[2],
                                        self.__class__.__ST_FIELD_OFFSET,
                                        self.__class__.__ST_FIELD_LEN)),
            utils.is_bit_enabled(data[2], self.__class__.__MEM_FIELD_OFFSET),
            utils.is_bit_enabled(data[2], self.__class__.__M2O_FIELD_OFFSET),
            utils.is_bit_enabled(data[2], self.__class__.__RR_FIELD_OFFSET))
示例#2
0
    def parse_raw_io_sample(self):
        """
        Parses the information contained in the IO sample bytes reading the 
        value of each configured DIO and ADC.
        """
        data_index = 3

        # Obtain the digital mask.                                    # Available digital IOs in 802.15.4
        self.__digital_hsb_mask = self.__io_sample_payload[
            1] & 0x01  # 0 0 0 0 0 0 0 1
        self.__digital_lsb_mask = self.__io_sample_payload[
            2] & 0xFF  # 1 1 1 1 1 1 1 1
        # Combine the masks.
        self.__digital_mask = (
            self.__digital_hsb_mask << 8) + self.__digital_lsb_mask
        # Obtain the analog mask.
        self.__analog_mask = ((self.__io_sample_payload[1] << 8
                               )  # Available analog IOs in 802.15.4
                              + self.__io_sample_payload[2]
                              ) & 0x7E00  # 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0

        # Read the digital values (if any). There are 9 possible digital lines in
        # 802.15.4 protocol. The digital mask indicates if there is any digital
        # line enabled to read its value. If 0, no digital values are received.
        if self.__digital_mask > 0:
            # Obtain the digital values.
            self.__digital_hsb_values = self.__io_sample_payload[3] & 0x7F
            self.__digital_lsb_values = self.__io_sample_payload[4] & 0xFF
            # Combine the values.
            self.__digital_values = (
                self.__digital_hsb_values << 8) + self.__digital_lsb_values

            for i in range(16):
                if not utils.is_bit_enabled(self.__digital_mask, i):
                    continue
                if utils.is_bit_enabled(self.__digital_values, i):
                    self.__digital_values_map[IOLine.get(i)] = IOValue.HIGH
                else:
                    self.__digital_values_map[IOLine.get(i)] = IOValue.LOW

            # Increase the data index to read the analog values.
            data_index += 2

        # Read the analog values (if any). There are 6 possible analog lines.
        # The analog mask indicates if there is any analog line enabled to read
        # its value. If 0, no analog values are received.
        adc_index = 9
        while (len(self.__io_sample_payload) -
               data_index) > 1 and adc_index < 16:
            if not (utils.is_bit_enabled(self.__analog_mask, adc_index)):
                adc_index += 1
                continue

            # 802.15.4 protocol does not provide power supply value, so get just the ADC data.
            self.__analog_values_map[IOLine.get(adc_index - 9)] = \
                ((self.__io_sample_payload[data_index] & 0xFF) << 8) + (self.__io_sample_payload[data_index + 1] & 0xFF)
            # Increase the data index to read the next analog values.
            data_index += 2
            adc_index += 1
    def is_broadcast(self):
        """
        Override method.

        .. seealso::
           | :meth:`XBeeAPIPacket.is_broadcast`
        """
        return (utils.is_bit_enabled(self.__receive_options, 1)
                or utils.is_bit_enabled(self.__receive_options, 2))
示例#4
0
    def __parse_io_sample(self):
        """
        Parses the information contained in the IO sample bytes reading the
        value of each configured DIO and ADC.
        """
        data_index = 4

        # Obtain the digital masks.                                   # Available digital IOs
        self.__digital_hsb_mask = self.__io_sample_payload[1] & 0x7F  # 0 1 1 1 1 1 1 1
        self.__digital_lsb_mask = self.__io_sample_payload[2] & 0xFF  # 1 1 1 1 1 1 1 1
        # Combine the masks.
        self.__digital_mask = (self.__digital_hsb_mask << 8) + self.__digital_lsb_mask
        # Obtain the analog mask.                                # Available analog IOs
        self.__analog_mask = self.__io_sample_payload[3] & 0xBF  # 1 0 1 1 1 1 1 1

        # Read the digital values (if any). There are 16 possible digital lines.
        # The digital mask indicates if there is any digital line enabled to read
        # its value. If 0, no digital values are received.
        if self.__digital_mask > 0:
            # Obtain the digital values.
            self.__digital_hsb_values = self.__io_sample_payload[4] & 0x7F
            self.__digital_lsb_values = self.__io_sample_payload[5] & 0xFF
            # Combine the values.
            self.__digital_values = (self.__digital_hsb_values << 8) + self.__digital_lsb_values

            for i in range(16):
                if not utils.is_bit_enabled(self.__digital_mask, i):
                    continue
                if utils.is_bit_enabled(self.__digital_values, i):
                    self.__digital_values_map[IOLine.get(i)] = IOValue.HIGH
                else:
                    self.__digital_values_map[IOLine.get(i)] = IOValue.LOW
            # Increase the data index to read the analog values.
            data_index += 2

        # Read the analog values (if any). There are 6 possible analog lines.
        # The analog mask indicates if there is any analog line enabled to read
        # its value. If 0, no analog values are received.
        adc_index = 0
        while (len(self.__io_sample_payload) - data_index) > 1 and adc_index < 8:
            if not utils.is_bit_enabled(self.__analog_mask, adc_index):
                adc_index += 1
                continue
            # When analog index is 7, it means that the analog value
            # corresponds to the power supply voltage, therefore this value
            # should be stored in a different value.
            if adc_index == 7:
                self.__power_supply_voltage = \
                    (((self.__io_sample_payload[data_index] & 0xFF) << 8)
                     + (self.__io_sample_payload[data_index + 1] & 0xFF))
            else:
                self.__analog_values_map[IOLine.get(adc_index)] = \
                    ((self.__io_sample_payload[data_index] & 0xFF) << 8) + \
                    (self.__io_sample_payload[data_index + 1] & 0xFF)
            # Increase the data index to read the next analog values.
            data_index += 2
            adc_index += 1
示例#5
0
    def __prepare_device(self):
        """
        Performs the local XBee configuration before sending the ZDO command. This saves the
        current AO value and sets it to 1.
        """
        if not self.__configure_ao:
            return

        if not self._xbee.is_remote():
            xb = self._xbee
        else:
            xb = self._xbee.get_local_xbee_device()

        try:
            self.__saved_ao = xb.get_api_output_mode_value()

            # Do not configure AO if it is already
            if utils.is_bit_enabled(self.__saved_ao[0], 0):
                self.__saved_ao = None
                return

            value = APIOutputModeBit.calculate_api_output_mode_value(self._xbee.get_protocol(),
                                                                     {APIOutputModeBit.EXPLICIT})
            xb.set_api_output_mode_value(value)

        except XBeeException as e:
            raise XBeeException("Could not prepare XBee for ZDO: " + str(e))
示例#6
0
    def has_power_supply_value(self):
        """
        Returns whether the IOSample has power supply value or not.

        Returns:
            Boolean. ``True`` if the given IOLine has a power supply value, ``False`` otherwise.
        """
        return utils.is_bit_enabled(self.__analog_mask, 7)
示例#7
0
    def is_broadcast(self):
        """
        Override method.

        .. seealso::
           | :meth:`XBeeAPIPacket.is_broadcast`
        """
        return utils.is_bit_enabled(self.__rx_opts, 1)
示例#8
0
    def _parse_data(self, data):
        """
        Override.

        .. seealso::
           | :meth:`.__ZDOCommand._parse_data`
        """
        # Ensure the 16-bit address received matches the address of the device
        x16 = XBee16BitAddress.from_bytes(data[1], data[0])
        if x16 != self._xbee.get_16bit_addr():
            return False

        # Role field: 3 bits (0, 1, 2) of the next byte
        role = Role.get(utils.get_int_from_byte(data[2], 0, 3))
        # Complex descriptor available: next bit (3) of the same byte
        complex_desc_available = utils.is_bit_enabled(data[2], 3)
        # User descriptor available: next bit (4) of the same byte
        user_desc_available = utils.is_bit_enabled(data[2], 4)

        # Frequency band: 5 bits of the next byte
        freq_band = NodeDescriptorReader.__to_bits(data[3])[-5:]

        # MAC capabilities: next byte
        mac_capabilities = NodeDescriptorReader.__to_bits(data[4])

        # Manufacturer code: next 2 bytes
        manufacturer_code = utils.bytes_to_int([data[6], data[5]])

        # Maximum buffer size: next byte
        max_buffer_size = int(data[7])

        # Maximum incoming transfer size: next 2 bytes
        max_in_transfer_size = utils.bytes_to_int([data[9], data[8]])

        # Maximum outgoing transfer size: next 2 bytes
        max_out_transfer_size = utils.bytes_to_int([data[13], data[12]])

        # Maximum outgoing transfer size: next byte
        desc_capabilities = NodeDescriptorReader.__to_bits(data[14])

        self.__node_descriptor = NodeDescriptor(role, complex_desc_available, user_desc_available,
                                                freq_band, mac_capabilities, manufacturer_code,
                                                max_buffer_size, max_in_transfer_size,
                                                max_out_transfer_size, desc_capabilities)

        return True