def __is_sleep_mode_available(self): # Special case: if this is a ZB network we need to check if the # firmware version is less than 0x2x60. If it is less than this, # then sleep mode is not supported on router modules (0x2260): xbee_dd_ddo_value = \ AbstractXBeeConfigBlockDDO.configurator_get(self).ddo_get_param( AbstractXBeeConfigBlockDDO.ext_addr_get(self), 'DD', retries=DDO_RETRY_ATTEMPTS, use_cache=True) module_id, product_id = parse_dd(xbee_dd_ddo_value) if module_id not in (MOD_XB_ZNET25, MOD_XB_ZB, MOD_XB_S2C_ZB): # Sleep unsupported return False if module_id == MOD_XB_ZB or module_id == MOD_XB_S2C_ZB: xbee_vr_ddo_value = \ AbstractXBeeConfigBlockDDO.configurator_get(self).ddo_get_param( AbstractXBeeConfigBlockDDO.ext_addr_get(self), 'VR', retries=DDO_RETRY_ATTEMPTS, use_cache=True) fw_funcset, fw_version = parse_vr(xbee_vr_ddo_value) if (fw_funcset in UNSUPPORTED_ZB_FW_FUNCSETS and fw_version < UNSUPPORTED_ZB_LT_FW_VERSION): self.__tracer.warning("'%s' FW version is %s < %s, " + "sleep mode configuration unavailable.", AbstractXBeeConfigBlockDDO.ext_addr_get(self), hex(fw_version), hex(UNSUPPORTED_ZB_LT_FW_VERSION)) return False return True
def __prepare_network_update_param(self, ext_addr, param): """Internal helper function used to update node parameters.""" minimum_sp_value = MINIMUM_ZB_RTR_SP_VALUE self.__tracer.debug("Fetching '%s' from '%s'", param, ext_addr) try: network_param = ( AbstractXBeeConfigBlockDDO.configurator_get(self) .ddo_get_param(ext_addr, param, retries=DDO_RETRY_ATTEMPTS, use_cache=True)) # All params used here are 16-bit unsigned ints: network_param = struct.unpack('H', network_param)[0] except Exception, e: self.__tracer.warning("Could not fetch param " + "'%s' from '%s': %s", param, ext_addr, str(e)) self.__tracer.debug("Removing '%s' from cache", ext_addr) (AbstractXBeeConfigBlockDDO .xbee_device_manager_get(self) ._xbee_remove_node_from_list(ext_addr)) raise e
# no update necessary, continue continue except Exception, e: self.__tracer.warning('Could not prepare network for ' 'sleeping node %s... will ' 'try again later.' % self._ext_addr) return False write_list.append(network_node) for network_node in write_list: # Attempt to write parameter values to non-volatile memory # for the coordinator and router nodes so that parameter # modifications persist through subsequent resets. try: (AbstractXBeeConfigBlockDDO.configurator_get( self).ddo_set_param(network_node, 'WR', '')) except Exception, e: self.__tracer.warning( 'couldn\'t write config ' 'to \'%s\': %s', network_node, str(e)) # Ignore this failure, it is non-fatal to network # performance continue # Signal to XBeeDeviceManager that network preparation was successful return True def apply_config(self): ''' Apply the configuration actions to the node targeted by this object. After this method has been called the
def apply_config(self): """\ Apply the configuration actions to the node targeted by this object. After this method has been called the :py:meth:`~devices.xbee.xbee_config_blocks.xbee_config_block.XBeeConfigBlock.is_complete` method will return True. See :py:class:`~devices.xbee.xbee_config_blocks.xbee_config_block.XBeeConfigBlock`. """ try: if not AbstractXBeeConfigBlockDDO._is_applicable(self): # If the block is not applicable, mark this block as complete: return AbstractXBeeConfigBlockDDO.apply_config(self) except: # Trace messages handled by _is_applicable() and apply_config() return False # Special case: # # Check if sleep mode is unavailable on this module/firmware # combination: if not self.__is_sleep_mode_available(): if self.__sleep_mode == SM_DISABLED: # This sleep block has been filled out with sleeping # disabled however sleep configuration is not available: # mark this block as complete. self.__tracer.debug("sleep mode unsupported and SM_DISABLED" + " given, block complete.") return AbstractXBeeConfigBlockDDO.apply_config(self) else: # We are unable to apply this block, mark it as a # block application failure: self.__tracer.warning("sleep mode unsupported" + " but sleep parameters given," + " block FAILED. Please disable " + "sleeping on this" + " device.") return False # Configure the node: pending_mnemonics = self.__pending_parameters.keys() for mnemonic in pending_mnemonics: # NOTE: this message is duplicated in the XBeeConfigBlockDDO source self.__tracer.debug("Apply_config: trying '%s' = '%s' to '%s'", mnemonic, format_hexrepr( self.__pending_parameters[mnemonic]), AbstractXBeeConfigBlockDDO.ext_addr_get(self)) try: AbstractXBeeConfigBlockDDO.configurator_get(self).ddo_set_param( AbstractXBeeConfigBlockDDO.ext_addr_get(self), mnemonic, self.__pending_parameters[mnemonic], retries=DDO_RETRY_ATTEMPTS) except Exception, e: self.__tracer.error("'%s' = '%s' to '%s' failed (%s)", mnemonic, format_hexrepr( self.__pending_parameters[mnemonic]), AbstractXBeeConfigBlockDDO.ext_addr_get(self), str(e)) return False del(self.__pending_parameters[mnemonic])
def prepare_network(self): """\ Setup the network to handle this node. It is important that all routers and the coordinator be prepared to reach a node with sleeping parameters. Without preparing the network first, reaching the node to configure it (if it has been preconfigured, for instance) may leave the node unreachable! This method will be called as a special case from the XBeeDeviceManager at the appropriate time. Return type: * bool """ if self.__sleep_mode == SM_DISABLED: return # Test local node for sleep fitness: if not self.__is_sleep_mode_available(): return False # If we are setting up a node for cyclic sleep, we must set # appropriate values for SP and SN (if the values are not already # large enough) network wide so the network may buffer requests # long enough for our sleeping nodes: router_list = (AbstractXBeeConfigBlockDDO.xbee_device_manager_get(self) .xbee_get_node_list(refresh=False)) router_list = filter(lambda n: (n.type == 'router' or n.type == 'coordinator'), router_list) router_list = map(lambda n: n.addr_extended, router_list) write_list = [ ] xbee_dd_ddo_value = \ AbstractXBeeConfigBlockDDO.configurator_get(self).ddo_get_param( AbstractXBeeConfigBlockDDO.ext_addr_get(self), 'DD', retries=DDO_RETRY_ATTEMPTS, use_cache=True) module_id, product_id = parse_dd(xbee_dd_ddo_value) applicable_params = None if module_id == MOD_XB_ZNET25: # Only SP is valid network wide: applicable_params = ( 'SP', ) elif module_id == MOD_XB_ZB or module_id == MOD_XB_S2C_ZB: applicable_params = ( 'SP', 'SN' ) for param in applicable_params: if param in self.__pending_parameters: network_param = None for network_node in router_list: try: if not self.__prepare_network_update_param( network_node, param): # no update necessary, continue continue except Exception, e: # signal to XBeeDeviceManager that network preparation # needs to be retried: # print "XDCBS: Error updating parameter: %s" % repr(e) # print "-" * 60 # traceback.print_exc(file=sys.stdout) # print "-" * 60 return False write_list.append(network_node)
# needs to be retried: # print "XDCBS: Error updating parameter: %s" % repr(e) # print "-" * 60 # traceback.print_exc(file=sys.stdout) # print "-" * 60 return False write_list.append(network_node) for network_node in write_list: # Attempt to write parameter values to non-volatile memory for the # coordinator and router nodes so that parameter modifications # persist through subsequent resets. try: (AbstractXBeeConfigBlockDDO.configurator_get(self) .ddo_set_param(network_node, 'WR','')) except Exception, e: self.__tracer.warning("couldn't write config " + "to '%s': %s", network_node, str(e)) # Ignore this failure, it is non-fatal to network performance continue # Signal to XBeeDeviceManager that network preparation was successful return True def apply_config(self): """\ Apply the configuration actions to the node targeted by this object. After this method has been called the
class XBeeConfigBlockWakeup(AbstractXBeeConfigBlockDDO): """\ XBee DDO Configuration Block Implements an :py:class:`~devices.xbee.xbee_config_blocks.xbee_config_block_ddo.AbstractXBeeConfigBlockDDO` for proper sequencing by the :py:class:`~devices.xbee.xbee_device_manager.xbee_device_manager.XBeeDeviceManager`. This class will automatically be placed at the beginning of the chain of :py:class:`~devices.xbee.xbee_config_blocks.xbee_config_block.XBeeConfigBlock` objects by the :py:class:`~devices.xbee.xbee_device_manager.xbee_device_manager.XBeeDeviceManager`. It's purpose is to perform a commissioning button press on a node that is about to be fully configured. This should result in the node being awake for 30 seconds. If this is a sleeping node, this increased window of wake time increases the ability to fully configure nodes. """ def __init__(self, ext_addr): """\ Create an XBeeConfigBlockWakeup object. See :py:class:`~devices.xbee.xbee_config_blocks.xbee_config_block.XBeeConfigBlock`. """ AbstractXBeeConfigBlockDDO.__init__(self, ext_addr) def apply_config(self): """\ Apply the configuration actions to the node targeted by this object. After this method has been called the :py:meth:`~devices.xbee.xbee_config_blocks.xbee_config_block.XBeeConfigBlock.is_complete` method will return True. See :py:class:`~devices.xbee.xbee_config_blocks.xbee_config_block.XBeeConfigBlock`. """ try: if not AbstractXBeeConfigBlockDDO._is_applicable(self): # If the block is not applicable, mark this block as complete: return AbstractXBeeConfigBlockDDO.apply_config(self) except Exception, e: # trace message will be printed by _is_applicable() or # apply_config() upon exception. return False from core.tracing import get_tracer __tracer = get_tracer('XBeeConfigBlockWakeup') try: __tracer.debug("Trying 'CB=1' to '%s'", AbstractXBeeConfigBlockDDO.ext_addr_get(self)) AbstractXBeeConfigBlockDDO.configurator_get(self).ddo_set_param( AbstractXBeeConfigBlockDDO.ext_addr_get(self), 'CB', 1, retries=DDO_RETRY_ATTEMPTS) except Exception, e: __tracer.error("Trying 'CB=1' to '%s' failed (%s)", AbstractXBeeConfigBlockDDO.ext_addr_get(self), str(e)) return False
class XBeeConfigBlockFinalWrite(AbstractXBeeConfigBlockDDO): """\ XBee DDO Configuration Block Implements an :py:class:`~devices.xbee.xbee_config_blocks.xbee_config_block_ddo.AbstractXBeeConfigBlockDDO` for proper sequencing by the :py:class:`~devices.xbee.xbee_device_manager.xbee_device_manager.XBeeDeviceManager`. This class will automatically be placed at the end of the chain of :py:class:`~devices.xbee.xbee_config_blocks.xbee_config_block.XBeeConfigBlock` objects by the :py:class:`~devices.xbee.xbee_device_manager.xbee_device_manager.XBeeDeviceManager`. It's purpose is to store the applied settings to non-volatile memory so nodes will reboot into a configured state in the event of a power loss. It will also apply all changes performed by the chain, so that they take affect at the same time. """ def __init__(self, ext_addr): """\ Create an XBeeConfigBlockFinalWrite object. See: :py:class:`~devices.xbee.xbee_config_blocks.xbee_config_block.XBeeConfigBlock` """ AbstractXBeeConfigBlockDDO.__init__(self, ext_addr) def apply_config(self): """\ Apply the configuration actions to the node targeted by this object. After this method has been called the :py:meth:`~devices.xbee.xbee_config_blocks.xbee_config_block.XBeeConfigBlock.is_complete` method will return True. See :py:class:`~devices.xbee.xbee_config_blocks.xbee_config_block.XBeeConfigBlock` """ try: if not AbstractXBeeConfigBlockDDO._is_applicable(self): # If the block is not applicable, mark this block as complete: return AbstractXBeeConfigBlockDDO.apply_config(self) except Exception, e: # trace message will be printed by _is_applicable() or # apply_config() upon exception. return False from core.tracing import get_tracer __tracer = get_tracer('XBeeConfigBlockFinalWrite') try: __tracer.debug("trying 'WR' to '%s'", AbstractXBeeConfigBlockDDO.ext_addr_get(self)) AbstractXBeeConfigBlockDDO.configurator_get(self).ddo_set_param( AbstractXBeeConfigBlockDDO.ext_addr_get(self), 'WR', retries=DDO_RETRY_ATTEMPTS, apply=True) except Exception, e: __tracer.error("Trying 'WR' to '%s' failed (%s)", AbstractXBeeConfigBlockDDO.ext_addr_get(self), str(e)) return False