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))
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))
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
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))
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)
def is_broadcast(self): """ Override method. .. seealso:: | :meth:`XBeeAPIPacket.is_broadcast` """ return utils.is_bit_enabled(self.__rx_opts, 1)
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