def retry_ddo_set_param(retries, ext_addr, param, value = '', timeout = GLOBAL_DDO_TIMEOUT, order = None, apply = None): """\ Attempt to set a DDO param on an XBee device. This function will attempt to send a DDO command/parameter to a local or remote XBee device. It will attempt to send the command/parameter up to 'retries' times. Returns the result, or None on failure. """ result = None while 1: try: if order is not None or apply is not None: # new style (ConnectPort version > 2.8.3) parameters: result = xbee.ddo_set_param(ext_addr, param, value, timeout, order = order, apply = apply) else: # old style parameters: result = xbee.ddo_set_param(ext_addr, param, value, timeout) break except: retries -= 1 if retries > 0: continue raise DDOTimeoutException, "could not set '%s' on '%s'" % (param, ext_addr) return result
def __rci_at(self, xig_tree): """\ Process a an "at" node, xig_tree is an ElementTree. Returns a string response. """ destination = str(xig_tree.get("hw_address")) command = str(xig_tree.get("command")).upper() if destination is None: return self.__xml_err_msg('invalid hw_address "%s" (missing \'!\'?)' % destination) if command is None: return self.__xml_err_msg('invalid command "%s"' % command) value = xig_tree.get("value") if value is not None: value = str(value) apply = False try: apply = bool(xig_tree.get("apply").lower() == "true") except: pass # interpret value: if command in ("NI","DN"): pass # interpret value as string elif command in ("AC", "WR"): value = "" elif value is None or len(value) == 0 or value.isspace(): value = None # will cause us to read instead of write param elif value.lower().startswith("0x"): try: value = int(value, 16) except: return self.__xml_err_msg( "unable to parse hex int for cmd %s" % repr(command)) else: try: value = int(value) except: return self.__xml_err_msg( "unable to parse int for cmd %s" % repr(command)) # run command: try: result = "" operation = "set" if value is not None: logger.info("AT set param to %s %s=%s" % (repr(destination), command, repr(value))) value = xbee.ddo_set_param(destination, command, value, apply=apply) result = "ok" else: operation = "get" logger.info("AT get param %s from %s" % (command, repr(destination))) value = xbee.ddo_get_param(destination, command) result = "ok" except Exception, e: result = "error" value = str(e)
def retry_ddo_set_param(retries, ext_addr, param, value='', timeout=GLOBAL_DDO_TIMEOUT, order=None, apply=None): """\ Attempt to set a DDO param on an XBee device. This function will attempt to send a DDO command/parameter to a local or remote XBee device. It will attempt to send the command/parameter up to 'retries' times. Returns the result, or None on failure. """ result = None while 1: try: if order is not None or apply is not None: # new style (ConnectPort version > 2.8.3) parameters: result = xbee.ddo_set_param(ext_addr, param, value, timeout, order=order, apply=apply) else: # old style parameters: result = xbee.ddo_set_param(ext_addr, param, value, timeout) break except: retries -= 1 if retries > 0: continue raise DDOTimeoutException, "could not set '%s' on '%s'" % ( param, ext_addr) return result
def _coordinator_ddo_config(self): # handle rare case where coordinator child-table is 'full' after # restart. Since we have no idea how long we've been offline, it is # possible all 10 children seek new association, and with NC=0 the # coordinator will NOT offer association for 3 * SN * SP time # so if sensor wakes once per 4 hours, then would take 12 hours for # coordinator to begin allowing association and data resumption nc = ord(ddo_get_param(None, 'NC')) self._tracer.debug("Coordinator NC=%d at startup", nc) if nc == 0: # then issue network reset self._tracer.debug("Child Table is full - Reset coordinator") ddo_set_param(None, 'NR', 0) # note: reading NC immediately will still have NC=0 sn_sp_val = SettingsBase.get_setting(self, 'sn_sp_override') if sn_sp_val != ZigBeeDeviceManager.SN_SP_DEFAULT: sn_sp_override = _time_formatter(sn_sp_val, test_only=False) if sn_sp_override != None: try: self._sn_sp_override = generate_sn_sp(sn_sp_override) self._tracer.debug('Setting SN/SP override.') except ValueError: self._tracer.warning( 'SN/SP override could not be set. ' 'The given time does not factor cleanly.') ar_new = SettingsBase.get_setting(self, 'source_routing') self._tracer.debug("Zigbee Source Routing setting is:%s", ar_new) ar_new = self.__parse_source_routing(ar_new) if ar_new is not None and (ar_new != ord(ddo_get_param(None, 'AR'))): # only update if changing self._tracer.debug("Zigbee Source Routing: " \ "set AR=%d (0x%02x)", ar_new, ar_new) ddo_set_param(None, 'AR', ar_new, timeout=15) ddo_set_param(None, 'AC', timeout=15) ddo_set_param(None, 'WR', timeout=15) return
def _coordinator_ddo_config(self): # handle rare case where coordinator child-table is 'full' after # restart. Since we have no idea how long we've been offline, it is # possible all 10 children seek new association, and with NC=0 the # coordinator will NOT offer association for 3 * SN * SP time # so if sensor wakes once per 4 hours, then would take 12 hours for # coordinator to begin allowing association and data resumption nc = ord(ddo_get_param(None, 'NC')) self._tracer.debug("Coordinator NC=%d at startup", nc) if nc == 0: # then issue network reset self._tracer.debug("Child Table is full - Reset coordinator") ddo_set_param(None, 'NR', 0) # note: reading NC immediately will still have NC=0 sn_sp_val = SettingsBase.get_setting(self, 'sn_sp_override') if sn_sp_val != ZigBeeDeviceManager.SN_SP_DEFAULT: sn_sp_override = _time_formatter(sn_sp_val, test_only=False) if sn_sp_override != None: try: self._sn_sp_override = generate_sn_sp(sn_sp_override) self._tracer.debug('Setting SN/SP override.') except ValueError: self._tracer.warning('SN/SP override could not be set. ' 'The given time does not factor cleanly.') ar_new = SettingsBase.get_setting(self, 'source_routing') self._tracer.debug("Zigbee Source Routing setting is:%s", ar_new) ar_new = self.__parse_source_routing(ar_new) if ar_new is not None and (ar_new != ord(ddo_get_param(None, 'AR'))): # only update if changing self._tracer.debug("Zigbee Source Routing: " \ "set AR=%d (0x%02x)", ar_new, ar_new) ddo_set_param(None, 'AR', ar_new, timeout=15) ddo_set_param(None, 'AC', timeout=15) ddo_set_param(None, 'WR', timeout=15) return
def __rci_at(self, xig_tree): """\ Process a an "at" node, xig_tree is an ElementTree. Returns a string response. """ destination = str(xig_tree.get("hw_address")) command = str(xig_tree.get("command")).upper() if destination is None: return self.__xml_err_msg( 'invalid hw_address "%s" (missing \'!\'?)' % destination) if command is None: return self.__xml_err_msg('invalid command "%s"' % command) value = xig_tree.get("value") if value is not None: value = str(value) apply = False try: apply = bool(xig_tree.get("apply").lower() == "true") except: pass # interpret value: if command in ("NI", "DN"): pass # interpret value as string elif command in ("AC", "WR"): value = "" elif value is None or len(value) == 0 or value.isspace(): value = None # will cause us to read instead of write param elif value.lower().startswith("0x"): try: value = int(value, 16) except: return self.__xml_err_msg( "unable to parse hex int for cmd %s" % repr(command)) else: try: value = int(value) except: return self.__xml_err_msg("unable to parse int for cmd %s" % repr(command)) # run command: try: result = "" operation = "set" if value is not None: logger.info("AT set param to %s %s=%s" % (repr(destination), command, repr(value))) value = xbee.ddo_set_param(destination, command, value, apply=apply) result = "ok" else: operation = "get" logger.info("AT get param %s from %s" % (command, repr(destination))) value = xbee.ddo_get_param(destination, command) result = "ok" except Exception, e: result = "error" value = str(e)
# Smart Plug power report cluster POWER_REPORT_CLUSTER = 0x00EF # listen for ZCL messages so we can send special init messages # needed by the Iris Smart sd_announce = socket(AF_XBEE, SOCK_DGRAM, XBS_PROT_TRANSPORT) sd_announce.bind(("", ZDO_ENDPOINT, 0, 0)) sd_announce.settimeout(1) # listen and send higher level messages for control and reporting sd_data = socket(AF_XBEE, SOCK_DGRAM, XBS_PROT_TRANSPORT) sd_data.bind(("", IRIS_ENDPOINT, 0, 0)) sd_data.settimeout(1) # pass through frames necessary to join Iris Smart Plug xbee.ddo_set_param(None, "AO", 3) # Set this true to print out extra message details debug = False def handle_message(sd): payload = None try: payload, (address_string, endpoint, profile_id, cluster_id, options_bitmask, transmission_id) = sd.recvfrom(255) except timeout: return False if debug: print "Received data from endpoint %02X profile %04X cluster %04X tid %02X: %s" % (endpoint, profile_id, cluster_id, transmission_id, binascii.hexlify(payload)) # is it a ZDO level message?