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
Example #2
0
    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)
Example #3
0
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
Example #6
0
    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?