def __get_device_data(self, address):

        product_type = None
        node_identifier = None

        try:
            device_data = self.__xbee_manager.xbee_device_ddo_get_param(\
                                 address, 'DD', use_cache=True)
        except:
            # On any exceptions, just bail.
            # The next discovery we will take another crack at it.
            self.__tracer.warning(("XBeeAutoEnum: __add_new_device. " +
                                   "UNABLE to get DD from %s."), address)
            return product_type, node_identifier

        device_type, product_type = parse_dd(device_data)

        # Now ask the device what its Node Identification is.
        try:
            node_identifier = self.__xbee_manager.xbee_device_ddo_get_param(\
                                     address, 'NI', use_cache=True)
        except:
            # On any exceptions, just bail.
            # The next discovery we will take another crack at it.
            self.__tracer.warning("XBeeAutoEnum: __add_new_device. " +
                                  "UNABLE to get NI from %s.", address)
            return product_type, node_identifier

        return product_type, node_identifier
    def __get_device_data(self, address):

        product_type = None
        node_identifier = None

        try:
            device_data = self.__xbee_manager.xbee_device_ddo_get_param(\
                                 address, 'DD', use_cache=True)
        except:
            # On any exceptions, just bail.
            # The next discovery we will take another crack at it.
            self.__tracer.warning(('XBeeAutoEnum: __add_new_device. '
                                   'UNABLE to get DD from %s.'), address)
            return product_type, node_identifier

        _, product_type = parse_dd(device_data)

        # Now ask the device what its Node Identification is.
        try:
            node_identifier = self.__xbee_manager.xbee_device_ddo_get_param(\
                                     address, 'NI', use_cache=True)
        except:
            # On any exceptions, just bail.
            # The next discovery we will take another crack at it.
            self.__tracer.warning(
                'XBeeAutoEnum: __add_new_device. '
                'UNABLE to get NI from %s.', address)
            return product_type, node_identifier

        return product_type, node_identifier
Beispiel #3
0
    def __is_sleep_mode_available(self, ext_addr=False):
        '''
        If ext_addr is False, uses the device referred to in this
        config block.
        '''
        # 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):
        if ext_addr == False:
            ext_addr = AbstractXBeeConfigBlockDDO.ext_addr_get(self)

        module_id, _ = parse_dd(AbstractXBeeConfigBlockDDO.\
                                configurator_get(self)\
                                .ddo_get_param(ext_addr, 'DD',
                                               retries=DDO_RETRY_ATTEMPTS,
                                               use_cache=True))
        if module_id not in SLEEPABLE_MODULES:
            return False

        if module_id == MOD_XB_ZB or module_id == MOD_XB_S2C_ZB:
            fw_func, fw_v = parse_vr(AbstractXBeeConfigBlockDDO.\
                                     configurator_get(self).\
                                     ddo_get_param(ext_addr, 'VR',
                                                   retries=\
                                                   DDO_RETRY_ATTEMPTS,
                                                   use_cache=True))

            if (fw_func in UNSUPPORTED_ZB_FW_FUNCSETS
                    and fw_v < UNSUPPORTED_ZB_LT_FW_VERSION):
                self.__tracer.warning(
                    "'%s' FW version is %s < %s, "
                    "sleep mode configuration unavailable.", ext_addr,
                    hex(fw_v), hex(UNSUPPORTED_ZB_LT_FW_VERSION))
                return False
        return True
Beispiel #4
0
    def running_indication(self):
        # request initial status here.
        self.__tracer.info("Running indication")
        extended_address = SettingsBase.get_setting(self, "extended_address")
        humidity_present = SettingsBase.get_setting(self, "humidity_present")

        # this is a flawed design - if the gateway has just rebooted,
        # and the Xbee sensor sleeps (which it should), then an actual
        # GET_DDO will be issued, which causes Dia to freeze here and
        # almost certainly throw exception and put the device off line.
        try:
            dd_value = self.__xbee_manager.xbee_device_ddo_get_param(
                    extended_address, 'DD', use_cache=True)
        except:
            self.__tracer.warning('Using default DD')
            dd_value = 0x0003000E

        module_id, product_id = parse_dd(dd_value)
        self.__tracer.info('DD info (module_id, product_id) = ' +
                           '(0x%04x, 0x%04x)"', module_id, product_id)

        if product_id == PROD_DIGI_XB_SENSOR_LTH or humidity_present == True:
            self.__tracer.info("Sensor is a '%s' adding humidity channel",
                               product_name(product_id))

            self.add_property(
                ChannelSourceDeviceProperty(name="humidity", type=float,
                    initial=Sample(timestamp=0, value=0.0, unit="%"),
                    perms_mask=DPROP_PERM_GET, options=DPROP_OPT_AUTOTIMESTAMP)) 
        else:
            self.__tracer.info("Sensor is a '%s' no humidity capability.",
                               product_name(product_id))
    def __get_device_data(self, address):

        product_type = None
        node_identifier = None
        device_data = None

        try:
            device_data = self.__xbee_manager.xbee_device_ddo_get_param(\
                                 address, 'DD', use_cache=True)
        except:
            device_data = None
            # On any exceptions, just bail.
            # The next discovery we will take another crack at it.
            self.__tracer.warning(('XBeeAutoEnum: __add_new_device. '
                                   'UNABLE to get DD from %s.'), address)
            return product_type, node_identifier, device_data

        _, product_type = parse_dd(device_data)
        print "here is the stuff you are looking for"
        print _
        print product_type

        # Now ask the device what its Node Identification is.
        try:
            node_identifier = self.__xbee_manager.xbee_device_ddo_get_param(\
                                     address, 'NI', use_cache=True)
        except:
            # On any exceptions, just bail.
            # The next discovery we will take another crack at it.
            self.__tracer.warning('XBeeAutoEnum: __add_new_device. '
                                  'UNABLE to get NI from %s.', address)
            return product_type, node_identifier, device_data

        return product_type, node_identifier, device_data
    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 _is_applicable(self, xbee_dd_ddo_value=None):
        """
        Test if this XBee configuration block is applicable given
        combinations of apply_except_* and apply_only_* filters.
        
        This method is intended to be used by derived classes in order
        to test applicability before allowing :meth:`apply_config` to
        perform any actions.  See :meth:`apply_config` for a code
        example.
        
        This method may be hinted with `xbee_dd_ddo_value` in order to
        avoid this method from attempting to access the network (or
        hit the DDO parameter cache) to determine which module_id
        and product_id are valid for the extended address of the node
        this XBee configuration block will act upon.

        Parameters:
            * **xbee_dd_ddo_value**: an XBee DD DDO value that will be decoded
                                     to a module_id and product_id.
        Return type:
            * bool

        """
        if not xbee_dd_ddo_value:
            xbee_dd_ddo_value = self.__configurator.ddo_get_param(
                                    self.__ext_addr,
                                    'DD',
                                    retries=DDO_RETRY_ATTEMPTS,
                                    use_cache=True)

        module_id, product_id = parse_dd(xbee_dd_ddo_value)

        applicability = True

        if self.__module_applicability == self.APPLICABILITY_ONLY:
            applicability &= module_id in self.__modules
        elif self.__module_applicability == self.APPLICABILITY_EXCEPT:
            applicability &= module_id not in self.__modules

        if self.__product_applicability == self.APPLICABILITY_ONLY:
            applicability &= product_id in self.__products
        elif self.__product_applicability == self.APPLICABILITY_EXCEPT:
            applicability &= product_id not in self.__products

        return applicability
Beispiel #8
0
    def _is_applicable(self, xbee_dd_ddo_value=None):
        """
        Test if this XBee configuration block is applicable given
        combinations of apply_except_* and apply_only_* filters.

        This method is intended to be used by derived classes in order
        to test applicability before allowing :meth:`apply_config` to
        perform any actions.  See :meth:`apply_config` for a code
        example.

        This method may be hinted with `xbee_dd_ddo_value` in order to
        avoid this method from attempting to access the network (or
        hit the DDO parameter cache) to determine which module_id
        and product_id are valid for the extended address of the node
        this XBee configuration block will act upon.

        Parameters:
            * **xbee_dd_ddo_value**: an XBee DD DDO value that will be decoded
                                     to a module_id and product_id.
        Return type:
            * bool

        """
        if not xbee_dd_ddo_value:
            xbee_dd_ddo_value = self.__configurator.ddo_get_param(
                                    self._ext_addr,
                                    'DD',
                                    retries=DDO_RETRY_ATTEMPTS,
                                    use_cache=True)

        module_id, product_id = parse_dd(xbee_dd_ddo_value)

        applicability = True

        if self.__module_applicability == self.APPLICABILITY_ONLY:
            applicability &= module_id in self.__modules
        elif self.__module_applicability == self.APPLICABILITY_EXCEPT:
            applicability &= module_id not in self.__modules

        if self.__product_applicability == self.APPLICABILITY_ONLY:
            applicability &= product_id in self.__products
        elif self.__product_applicability == self.APPLICABILITY_EXCEPT:
            applicability &= product_id not in self.__products

        return applicability
Beispiel #9
0
    def running_indication(self):
        # request initial status here.
        self._tracer.info("Running indication")
        humidity_present = SettingsBase.get_setting(self, "humidity_present")

        # this is a flawed design - if the gateway has just rebooted,
        # and the Xbee sensor sleeps (which it should), then an actual
        # GET_DDO will be issued, which causes DIA to freeze here and
        # almost certainly throw exception and put the device off line.
        try:
            dd_value = self._xbee_manager.xbee_device_ddo_get_param(
                self._extended_address, 'DD', use_cache=True)
        except:
            self._tracer.warning('Using default DD')
            dd_value = 0x0003000E

        module_id, product_id = parse_dd(dd_value)
        self._tracer.debug(
            'DD info (module_id, product_id) = ' + '(0x%04x, 0x%04x)"',
            module_id, product_id)

        if product_id == PROD_DIGI_XB_SENSOR_LTH or humidity_present == True:
            self._tracer.info("Sensor is a '%s' adding humidity channel",
                              product_name(product_id))

            self.add_property(
                ChannelSourceDeviceProperty(name="humidity",
                                            type=float,
                                            initial=Sample(timestamp=0,
                                                           value=0.0,
                                                           unit="%"),
                                            perms_mask=DPROP_PERM_GET,
                                            options=DPROP_OPT_AUTOTIMESTAMP))
        else:
            self._tracer.info("Sensor is a '%s' no humidity capability.",
                              product_name(product_id))
    def calibrate(self):
        """\
            Calibrate analog inputs on the XBee radio.
            Calculates scale and offset.
        """

        # Retrieve the radio type.
        # Calibration is different based on the XBee radio in the unit.
        xbee_dd_ddo_value = self.__xbee_manager.xbee_device_ddo_get_param(None,
                            'DD', use_cache = True)
        module_id, product_id = parse_dd(xbee_dd_ddo_value)

        # XBee series 1 uses one calibration voltage on AN2
        if module_id == MOD_XB_802154:

            # Enable calibration voltages on channel 1
            for ch in self.__aio_channel_structures:
               if ch.channel() == 1:
                  ch.turn_on_calibration_series1()

            # Give it a moment to synch up.  Yes, this IS required!
            digitime.sleep(0.010)

            # Read calibration sample
            result = self.__xbee_manager.xbee_device_ddo_get_param(None, 'IS')
            sample = parse_is(result)["AD1"]
            self.__tracer.debug("Calibration sample is %d", sample)

            # Disable calibration voltages on channels 0 and 1
            for ch in self.__aio_channel_structures:
               if ch.channel() == 0 or ch.channel() == 1:
                  ch.turn_off_calibration_series2()

            # Give it a moment to synch up.  Yes, this IS required!
            digitime.sleep(0.010)

            if sample == 0:
                raise ValueError, "Calibration error: bad sample"

            # Calulate linear scale and offset.
            # These apply to all analog channels.
            self.__scale = 1.25 / sample
            self.__offset = 0

        # XBee series 2 uses two calibration voltages on AN1 and AN2
        elif module_id == MOD_XB_ZNET25 or module_id == MOD_XB_ZB or module_id == MOD_XB_S2C_ZB:

            # Enable calibration voltages on channels 0 and 1
            for ch in self.__aio_channel_structures:
               if ch.channel() == 0 or ch.channel() == 1:
                  ch.turn_on_calibration_series2()

            # Give it a moment to synch up.  Yes, this IS required!
            digitime.sleep(0.010)

            # Read calibration samples
            result = self.__xbee_manager.xbee_device_ddo_get_param(None, 'IS')
            data = parse_is(result)
            sample = [ data["AD0"], data["AD1"] ]

            self.__tracer.debug("Calibration samples are %d, %d", 
                                sample[0], sample[1])

            # Disable calibration voltages on channels 0 and 1
            for ch in self.__aio_channel_structures:
               if ch.channel() == 0 or ch.channel() == 1:
                  ch.turn_off_calibration_series2()

            # Give it a moment to synch up.  Yes, this IS required!
            digitime.sleep(0.010)

            if sample[0] == sample[1]:
                raise ValueError, "Calibration error: equal samples"

            scale1 = self.__CALIBRATION_06 / float(sample[1])
            scale2 = self.__CALIBRATION_10 / float(sample[0])

            self.__scale = (scale1 + scale2) / 2.0

            if self.__OLD_HARDWARE == True:
                self.__offset = (sample[1] *
                       self.__scale - self.LOCAL_AIO_CALIBRATION_06) * 2.4
            else:
                self.__offset = 0.0

        else:
            raise ValueError, "XBee does not support analog inputs"

        self.__calibration_time = digitime.real_clock()

        self.__tracer.debug("Scale is %f, offset is %f", 
                            self.__scale, self.__offset)
Beispiel #11
0
    def start(self):

        # Fetch the XBee Manager name from the Settings Manager:
        xbee_manager_name = SettingsBase.get_setting(self, "xbee_device_manager")
        dm = self.__core.get_service("device_driver_manager")
        self.__xbee_manager = dm.instance_get(xbee_manager_name)

        # Register ourselves with the XBee Device Manager instance:
        self.__xbee_manager.xbee_device_register(self)

        # Get the extended address of the device:
        extended_address = SettingsBase.get_setting(self, "extended_address")

        # Retrieve the flag which tells us if we should sleep:

        # Create a callback specification for our device address, endpoint
        # Digi XBee profile and sample cluster id:
        xbdm_rx_event_spec = XBeeDeviceManagerRxEventSpec()
        xbdm_rx_event_spec.cb_set(self.sample_indication)
        xbdm_rx_event_spec.match_spec_set(
            (extended_address, 0xe8, 0xc105, 0x92),
            (True, True, True, True))
        self.__xbee_manager.xbee_device_event_spec_add(self,
                                xbdm_rx_event_spec)

        # Create a callback specification that calls back this driver when
        # our device has left the configuring state and has transitioned
        # to the running state:
        xbdm_running_event_spec = XBeeDeviceManagerRunningEventSpec()
        xbdm_running_event_spec.cb_set(self.running_indication)
        self.__xbee_manager.xbee_device_event_spec_add(self,
                                                        xbdm_running_event_spec)

        # Create a DDO configuration block for this device:
        xbee_ddo_cfg = XBeeConfigBlockDDO(extended_address)

        # Get the gateway's extended address:
        gw_xbee_sh, gw_xbee_sl = gw_extended_address_tuple()

        # Set the destination for I/O samples to be the gateway:
        xbee_ddo_cfg.add_parameter('DH', gw_xbee_sh)
        xbee_ddo_cfg.add_parameter('DL', gw_xbee_sl)

        # Configure pins DI1 .. DI3 for analog input:
        for io_pin in [ 'D1', 'D2', 'D3' ]:
            xbee_ddo_cfg.add_parameter(io_pin, 2)

        # Configure battery-monitor pin DIO11/P1 for digital input:
        xbee_ddo_cfg.add_parameter('P1', 3)
        # Enable change detection on DIO11:
        #
        # 0x   8    0    0
        #   1000 0000 0000 (b)
        #   DDDD DDDD DDDD
        #   IIII IIII IIII
        #   OOOO OOOO OOOO
        #   1198 7654 3210
        #   10
        #
        xbee_ddo_cfg.add_parameter('IC', 0x800)

        if SettingsBase.get_setting(self, "humidity_present"):
            # Get gateway module_id, universal to all nodes on the network:
            gw_dd = self.__xbee_manager.xbee_device_ddo_get_param(
                        None, 'DD', use_cache=True)
            module_id, product_id = parse_dd(gw_dd)
            # Re-program DD value to set sensor type to /L/T/H:
            device_dd = format_dd(module_id, PROD_DIGI_XB_SENSOR_LTH)
            xbee_ddo_cfg.add_parameter('DD', device_dd)

        # Configure the IO Sample Rate:
        # Clip sample_rate_ms to the max value of IR:
        sample_rate_ms = SettingsBase.get_setting(self, "sample_rate_ms")
        sample_rate_ms = min(sample_rate_ms, 0xffff)
        xbee_ddo_cfg.add_parameter('IR', sample_rate_ms)

        # Register this configuration block with the XBee Device Manager:
        self.__xbee_manager.xbee_device_config_block_add(self, xbee_ddo_cfg)

        # Setup the sleep parameters on this device:
        will_sleep = SettingsBase.get_setting(self, "sleep")
        sample_predelay = SettingsBase.get_setting(self, "sample_predelay")
        awake_time_ms = (SettingsBase.get_setting(self, "awake_time_ms") +
                         sample_predelay)
        
        if will_sleep:
            # Sample time pre-delay, allow the circuitry to power up and
            # settle before we allow the XBee to send us a sample:            
            xbee_ddo_wh_block = XBeeConfigBlockDDO(extended_address)
            xbee_ddo_wh_block.apply_only_to_modules((MOD_XB_ZB, MOD_XB_S2C_ZB,))
            xbee_ddo_wh_block.add_parameter('WH', sample_predelay)
            self.__xbee_manager.xbee_device_config_block_add(self,
                                    xbee_ddo_wh_block)

        # The original sample rate is used as the sleep rate:
        sleep_rate_ms = SettingsBase.get_setting(self, "sample_rate_ms")
        xbee_sleep_cfg = XBeeConfigBlockSleep(extended_address)
        if will_sleep:
            xbee_sleep_cfg.sleep_cycle_set(awake_time_ms, sleep_rate_ms)
        else:
            xbee_sleep_cfg.sleep_mode_set(SM_DISABLED)
        self.__xbee_manager.xbee_device_config_block_add(self, xbee_sleep_cfg)



        # Indicate that we have no more configuration to add:
        self.__xbee_manager.xbee_device_configure(self)

        return True
    def calibrate(self):
        """\
            Calibrate analog inputs on the XBee radio.
            Calculates scale and offset.
        """

        # Retrieve the radio type.
        # Calibration is different based on the XBee radio in the unit.
        xbee_dd_ddo_value = self.__xbee_manager.xbee_device_ddo_get_param(None,
                            'DD', use_cache = True)
        module_id, product_id = parse_dd(xbee_dd_ddo_value)

        # XBee series 1 uses one calibration voltage on AN2
        if module_id == MOD_XB_802154:

            # Enable calibration voltages on channel 1
            for ch in self.__aio_channel_structures:
               if ch.channel() == 1:
                  ch.turn_on_calibration_series1()

            # Give it a moment to synch up.  Yes, this IS required!
            digitime.sleep(0.010)

            # Read calibration sample
            result = self.__xbee_manager.xbee_device_ddo_get_param(None, 'IS')
            sample = parse_is(result)["AD1"]
            self.__tracer.debug("Calibration sample is %d", sample)

            # Disable calibration voltages on channels 0 and 1
            for ch in self.__aio_channel_structures:
               if ch.channel() == 0 or ch.channel() == 1:
                  ch.turn_off_calibration_series2()

            # Give it a moment to synch up.  Yes, this IS required!
            digitime.sleep(0.010)

            if sample == 0:
                raise ValueError, "Calibration error: bad sample"

            # Calulate linear scale and offset.
            # These apply to all analog channels.
            self.__scale = 1.25 / sample
            self.__offset = 0

        # XBee series 2 uses two calibration voltages on AN1 and AN2
        elif module_id == MOD_XB_ZNET25 or module_id == MOD_XB_ZB or module_id == MOD_XB_S2C_ZB:

            # Enable calibration voltages on channels 0 and 1
            for ch in self.__aio_channel_structures:
               if ch.channel() == 0 or ch.channel() == 1:
                  ch.turn_on_calibration_series2()

            # Give it a moment to synch up.  Yes, this IS required!
            digitime.sleep(0.010)

            # Read calibration samples
            result = self.__xbee_manager.xbee_device_ddo_get_param(None, 'IS')
            data = parse_is(result)
            sample = [ data["AD0"], data["AD1"] ]

            self.__tracer.debug("Calibration samples are %d, %d", 
                                sample[0], sample[1])

            # Disable calibration voltages on channels 0 and 1
            for ch in self.__aio_channel_structures:
               if ch.channel() == 0 or ch.channel() == 1:
                  ch.turn_off_calibration_series2()

            # Give it a moment to synch up.  Yes, this IS required!
            digitime.sleep(0.010)

            if sample[0] == sample[1]:
                raise ValueError, "Calibration error: equal samples"

            scale1 = self.__CALIBRATION_06 / float(sample[1])
            scale2 = self.__CALIBRATION_10 / float(sample[0])

            self.__scale = (scale1 + scale2) / 2.0

            if self.__OLD_HARDWARE == True:
                self.__offset = (sample[1] *
                       self.__scale - self.LOCAL_AIO_CALIBRATION_06) * 2.4
            else:
                self.__offset = 0.0

        else:
            raise ValueError, "XBee does not support analog inputs"

        self.__calibration_time = digitime.real_clock()

        self.__tracer.debug("Scale is %f, offset is %f", 
                            self.__scale, self.__offset)
    def __calibrate(self):
        """__calibrate()
        Calibrate analog inputs. Calculates scale and offset."""

        xbee_dd_ddo_value = self.__xbee_manager.xbee_device_ddo_get_param(None,
                            'DD', use_cache=True)
        module_id, product_id = parse_dd(xbee_dd_ddo_value)

        # XBee series 1 uses one calibration voltage on AN2
        if module_id == MOD_XB_802154:

            # Enable calibration voltage on channel 1
            self.__xbee_manager.xbee_device_ddo_set_param(None, 'D4', 4,
                                apply=True)
            digitime.sleep(0.010)

            # Read calibration sample
            result = self.__xbee_manager.xbee_device_ddo_get_param(None, 'IS')
            sample = parse_is(result)["AD1"]
            self.__tracer.debug("Calibration sample is %d", sample)

            # Return channel to operating mode
            self.__xbee_manager.xbee_device_ddo_set_param(None, 'D4', 5,
                                apply=True)
            digitime.sleep(0.010) 

            if sample == 0:
                raise ValueError, "Calibration error: bad sample"

            # Calulate linear scale and offset.
            # These apply to all analog channels.
            self.__scale = 1.25 / sample
            self.__offset = 0

        # XBee series 2 uses two calibration voltages on AN1 and AN2
        elif module_id == MOD_XB_ZNET25 or module_id == MOD_XB_ZB or module_id == MOD_XB_S2C_ZB:

            # Enable calibration voltages on channels 0 and 1
            if get_platform_name() == 'digix3':
                self.__xbee_manager.xbee_device_ddo_set_param(None, 
                            self.LOCAL_AIO_CONTROL_LINES[0], 2, apply=True)
                self.__xbee_manager.xbee_device_ddo_set_param(None,
                            self.LOCAL_AIO_CONTROL_LINES[1], 2, apply=True)
                digihw.gpio_set_value(0, 0)
            elif get_platform_name() == 'digiconnect':
                self.__xbee_manager.xbee_device_ddo_set_param(None, 'P2', 4,
                                    apply=True)
                self.__xbee_manager.xbee_device_ddo_set_param(None, 'D4', 4, 
                                    apply=True)

            digitime.sleep(0.010)

            # Read calibration samples
            result = self.__xbee_manager.xbee_device_ddo_get_param(None, 'IS')
            data = parse_is(result)
            sample = [ data["AD0"], data["AD1"] ]

            self.__tracer.debug("Calibration samples are %d, %d", 
                               sample[0], sample[1])

            # Return channels to operating mode
            if get_platform_name() == 'digix3':
                digihw.gpio_set_value(0, 1)
            elif get_platform_name() == 'digiconnect':
                self.__xbee_manager.xbee_device_ddo_set_param(None, 'P2', 5,
                                    apply=True)
                self.__xbee_manager.xbee_device_ddo_set_param(None, 'D4', 5,
                                    apply=True)

            digitime.sleep(0.010)

            for io_pin in range(2):
                mode = SettingsBase.get_setting(self, 'channel%d_mode' % (io_pin+1) )
                mode = self.LOCAL_AIO_MODE_MAP[mode.lower()]

                if mode == self.LOCAL_AIO_MODE_CURRENTLOOP:
                    self.__xbee_manager.xbee_device_ddo_set_param(None,
                           self.LOCAL_AIO_CONTROL_LINES[io_pin], 2, apply=True)
                elif mode == self.LOCAL_AIO_MODE_TENV:
                    self.__xbee_manager.xbee_device_ddo_set_param(None,
                           self.LOCAL_AIO_CONTROL_LINES[io_pin], 2, apply=True)

            if sample[0] == sample[1]:
                raise ValueError, "Calibration error: equal samples"

            self.__sample1 = sample[1]
            self.__sample2 = sample[0]

            scale1 = self.LOCAL_AIO_CALIBRATION_06 / float(sample[1])
            scale2 = self.LOCAL_AIO_CALIBRATION_10 / float(sample[0])

            self.__scale = (scale1 + scale2) / 2.0

            if self.__OLD_HARDWARE == True:
                self.__offset = (self.__sample1 *
                       self.__scale - self.LOCAL_AIO_CALIBRATION_06) * 2.4
            else:
                self.__offset = 0.0

        else:
            raise ValueError, "XBee does not support analog inputs"

        self.__calibration_time = digitime.real_clock()

        self.__tracer.debug("Scale is %f, offset is %f", 
                            self.__scale, self.__offset)
Beispiel #14
0
    def prepare_network(self, override_map=None):
        '''
        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(None):
            return False

        if self.__sleep_mode == DM_SUPPORT:
            # ensure this device is not a preferred sleep coord
            # bit 1: non-sleep coordinator
            # bit 2: enable api sleep status messages
            self._add_parameter('SO', 0x06)
            return True

        if self.__sleep_mode == DM_SLEEP:
            # ensure not a sleep coordinator
            self._add_parameter('SO', 0x0)
            return True

        # 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 = [n.addr_extended for n in router_list if \
                       n.type == 'router' or n.type == 'coordinator']
        write_list = []


        module_id, _ = parse_dd(AbstractXBeeConfigBlockDDO.\
                                configurator_get(self)\
                                .ddo_get_param(None, 'DD',
                                               retries=DDO_RETRY_ATTEMPTS,
                                               use_cache=True))

        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:
                for network_node in router_list:
                    try:
                        if not self.__prepare_network_update_param(
                                network_node, param, override_map):
                            # 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)
Beispiel #15
0
    def start(self):

        self._tracer.calls("XBeeSensor.start()")

        # init self._xbee_manager and self._extended_address
        # register ourself with our Xbee manager
        # create the self.running_indication callback
        XBeeBase.pre_start(self)

        # Retrieve the flag which tells us if we should sleep:

        # Create a callback specification for our device address
        self._xbee_manager.register_sample_listener(self,
                                                    self._extended_address,
                                                    self.sample_indication)

        # Create a DDO configuration block for this device:
        xbee_ddo_cfg = XBeeConfigBlockDDO(self._extended_address)

        # Configure pins DI1 .. DI3 for analog input:
        for io_pin in ['D1', 'D2', 'D3']:
            xbee_ddo_cfg.add_parameter(io_pin, 2)

        # Configure battery-monitor pin DIO11/P1 for digital input:
        xbee_ddo_cfg.add_parameter('P1', 3)
        # Enable change detection on DIO11:
        #
        # 0x   8    0    0
        #   1000 0000 0000 (b)
        #   DDDD DDDD DDDD
        #   IIII IIII IIII
        #   OOOO OOOO OOOO
        #   1198 7654 3210
        #   10
        #
        xbee_ddo_cfg.add_parameter('IC', 0x800)

        if SettingsBase.get_setting(self, "humidity_present"):
            # Get gateway module_id, universal to all nodes on the network:
            gw_dd = self._xbee_manager.xbee_device_ddo_get_param(
                None, 'DD', use_cache=True)
            module_id, product_id = parse_dd(gw_dd)
            # Re-program DD value to set sensor type to /L/T/H:
            device_dd = format_dd(module_id, PROD_DIGI_XB_SENSOR_LTH)
            xbee_ddo_cfg.add_parameter('DD', device_dd)

        # Configure the IO Sample Rate:
        # Clip sample_rate_ms to the max value of IR:
        sample_rate_ms = SettingsBase.get_setting(self, "sample_rate_ms")
        sample_rate_ms = min(sample_rate_ms, 0xffff)
        xbee_ddo_cfg.add_parameter('IR', sample_rate_ms)

        # Register this configuration block with the XBee Device Manager:
        self._xbee_manager.xbee_device_config_block_add(self, xbee_ddo_cfg)

        # Setup the sleep parameters on this device:
        will_sleep = SettingsBase.get_setting(self, "sleep")
        sample_predelay = SettingsBase.get_setting(self, "sample_predelay")
        awake_time_ms = (SettingsBase.get_setting(self, "awake_time_ms") +
                         sample_predelay)

        if will_sleep:
            # Sample time pre-delay, allow the circuitry to power up and
            # settle before we allow the XBee to send us a sample:
            xbee_ddo_wh_block = XBeeConfigBlockDDO(self._extended_address)
            xbee_ddo_wh_block.apply_only_to_modules((
                MOD_XB_ZB,
                MOD_XB_S2C_ZB,
            ))
            xbee_ddo_wh_block.add_parameter('WH', sample_predelay)
            self._xbee_manager.xbee_device_config_block_add(
                self, xbee_ddo_wh_block)

        # The original sample rate is used as the sleep rate:
        sleep_rate_ms = SettingsBase.get_setting(self, "sample_rate_ms")

        # new method for mesh health monitoring
        self.set_data_update_rate_seconds(sleep_rate_ms / 1000)

        # not including sample_predelay here... specially configured above
        xbee_sleep_cfg = self._xbee_manager.get_sleep_block(
            self._extended_address,
            sleep=will_sleep,
            sleep_rate_ms=sleep_rate_ms,
            awake_time_ms=awake_time_ms)

        self._xbee_manager.xbee_device_config_block_add(self, xbee_sleep_cfg)

        # we've no more to config, indicate we're ready to configure.
        return XBeeBase.start(self)
    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)
    def __calibrate(self):
        """__calibrate()
        Calibrate analog inputs. Calculates scale and offset."""

        xbee_dd_ddo_value = self.__xbee_manager.xbee_device_ddo_get_param(
            None, 'DD', use_cache=True)
        module_id, product_id = parse_dd(xbee_dd_ddo_value)

        # XBee series 1 uses one calibration voltage on AN2
        if module_id == MOD_XB_802154:

            # Enable calibration voltage on channel 1
            self.__xbee_manager.xbee_device_ddo_set_param(None,
                                                          'D4',
                                                          4,
                                                          apply=True)
            digitime.sleep(0.010)

            # Read calibration sample
            result = self.__xbee_manager.xbee_device_ddo_get_param(None, 'IS')
            sample = parse_is(result)["AD1"]
            self.__tracer.debug("Calibration sample is %d", sample)

            # Return channel to operating mode
            self.__xbee_manager.xbee_device_ddo_set_param(None,
                                                          'D4',
                                                          5,
                                                          apply=True)
            digitime.sleep(0.010)

            if sample == 0:
                raise ValueError, "Calibration error: bad sample"

            # Calulate linear scale and offset.
            # These apply to all analog channels.
            self.__scale = 1.25 / sample
            self.__offset = 0

        # XBee series 2 uses two calibration voltages on AN1 and AN2
        elif module_id == MOD_XB_ZNET25 or module_id == MOD_XB_ZB or module_id == MOD_XB_S2C_ZB:

            # Enable calibration voltages on channels 0 and 1
            if get_platform_name() == 'digix3':
                self.__xbee_manager.xbee_device_ddo_set_param(
                    None, self.LOCAL_AIO_CONTROL_LINES[0], 2, apply=True)
                self.__xbee_manager.xbee_device_ddo_set_param(
                    None, self.LOCAL_AIO_CONTROL_LINES[1], 2, apply=True)
                digihw.gpio_set_value(0, 0)
            elif get_platform_name() == 'digiconnect':
                self.__xbee_manager.xbee_device_ddo_set_param(None,
                                                              'P2',
                                                              4,
                                                              apply=True)
                self.__xbee_manager.xbee_device_ddo_set_param(None,
                                                              'D4',
                                                              4,
                                                              apply=True)

            digitime.sleep(0.010)

            # Read calibration samples
            result = self.__xbee_manager.xbee_device_ddo_get_param(None, 'IS')
            data = parse_is(result)
            sample = [data["AD0"], data["AD1"]]

            self.__tracer.debug("Calibration samples are %d, %d", sample[0],
                                sample[1])

            # Return channels to operating mode
            if get_platform_name() == 'digix3':
                digihw.gpio_set_value(0, 1)
            elif get_platform_name() == 'digiconnect':
                self.__xbee_manager.xbee_device_ddo_set_param(None,
                                                              'P2',
                                                              5,
                                                              apply=True)
                self.__xbee_manager.xbee_device_ddo_set_param(None,
                                                              'D4',
                                                              5,
                                                              apply=True)

            digitime.sleep(0.010)

            for io_pin in range(2):
                mode = SettingsBase.get_setting(
                    self, 'channel%d_mode' % (io_pin + 1))
                mode = self.LOCAL_AIO_MODE_MAP[mode.lower()]

                if mode == self.LOCAL_AIO_MODE_CURRENTLOOP:
                    self.__xbee_manager.xbee_device_ddo_set_param(
                        None,
                        self.LOCAL_AIO_CONTROL_LINES[io_pin],
                        2,
                        apply=True)
                elif mode == self.LOCAL_AIO_MODE_TENV:
                    self.__xbee_manager.xbee_device_ddo_set_param(
                        None,
                        self.LOCAL_AIO_CONTROL_LINES[io_pin],
                        2,
                        apply=True)

            if sample[0] == sample[1]:
                raise ValueError, "Calibration error: equal samples"

            self.__sample1 = sample[1]
            self.__sample2 = sample[0]

            scale1 = self.LOCAL_AIO_CALIBRATION_06 / float(sample[1])
            scale2 = self.LOCAL_AIO_CALIBRATION_10 / float(sample[0])

            self.__scale = (scale1 + scale2) / 2.0

            if self.__OLD_HARDWARE == True:
                self.__offset = (self.__sample1 * self.__scale -
                                 self.LOCAL_AIO_CALIBRATION_06) * 2.4
            else:
                self.__offset = 0.0

        else:
            raise ValueError, "XBee does not support analog inputs"

        self.__calibration_time = digitime.real_clock()

        self.__tracer.debug("Scale is %f, offset is %f", self.__scale,
                            self.__offset)