def sample_indication(self, buf, addr): # Parse the I/O sample: self._tracer.calls("XBeeXBIB.sample_indication()") io_sample = parse_is(buf) change = False now = None for i in range(4): # Refresh switch states, if different: val = bool(io_sample[self.DIO_NAME[i]]) oldval = bool(self.property_get(self.SW_NAME[i]).value) if oldval != val: change = True self.property_set(self.SW_NAME[i], Sample(0, val)) if val: # then switch is NOT pressed self._tracer.info('%s is NOT pressed (val=%s)', self.SW_NAME[i], val) else: self._tracer.info('%s is PRESSED (val=%s)', self.SW_NAME[i], val) if not change: self._tracer.debug('Sample indication, but no change to switches')
def sample_indication(self, buf, addr, force=False): #print "XBeeDIO: Got sample indication from: %s, buf is len %d." \ # % (str(addr), len(buf)) extended_address = SettingsBase.get_setting(self, "extended_address") now = time.time() # we need all samples 'stamped' the same - no lag/jitter if self.trace: msg = "XBeeDIO(%s):" % (self.__name) io_sample = parse_is(buf) for io_pin in range(4): key = 'DIO%d' % INPUT_CHANNEL_TO_PIN[io_pin] if io_sample.has_key(key): val = bool(io_sample[key]) name = "channel%d_input" % (io_pin+1) if self.trace: msg += ' Dio%d=' % (io_pin+1) try: old = self.property_get(name) if force or (old.timestamp == 0) or (old.value != val): units1 = self.property_get(name).unit self.property_set(name, Sample(now, val, units1)) if self.trace: # show value with '^' for change msg += '%s^' % val else: if self.trace: # show value, no change msg += '%s' % val except Exception, e: print "XBeeDIO(%s): Exception generated: %s" %(self.__name, str(e))
def sample_indication(self, buf, addr): #print "XBeeDIO: Got sample indication from: %s, buf is len %d." \ # % (str(addr), len(buf)) now = time.time() # we need all samples 'stamped' the same - no lag/jitter msg = "" io_sample = parse_is(buf) for io_pin in range(4): key = 'DIO%d' % INPUT_CHANNEL_TO_PIN[io_pin] if io_sample.has_key(key): val = bool(io_sample[key]) name = "channel%d_input" % (io_pin+1) msg += ' Dio%d=' % (io_pin+1) # Always update the channel with the new sample value, and # its timestamp, even if it is the same as the previous value. try: # Make a copy of the old values. old = self.property_get(name) # Set the new value. self.property_set(name, Sample(now, val, "bool")) # Print out some tracing about old versus new sample value. if old.timestamp == 0 or old.value != val: # show value with '^' for change msg += '%s^' % val else: # show value, no change msg += '%s' % val except Exception, e: self.__tracer.error("Exception generated: %s", str(e))
def sample_indication(self, buf, addr): self.__tracer.debug('Sample indication') # Parse the I/O sample: io_sample = parse_is(buf) for i in range(4): # Refresh switch states, if different: val = bool(io_sample["DIO%d" % i]) oldval = bool(self.property_get("sw%d" % (i+1)).value) if oldval != val: self.property_set("sw%d" % (i+1), Sample(0, val))
def __decode_sample(self, buf): io_sample = parse_is(buf) for io_pin in range(4): key = 'DIO%d' % self.INPUT_CHANNEL_TO_PIN[io_pin] if io_sample.has_key(key): val = bool(io_sample[key]) name = "channel%d_input" % (io_pin+1) try: self.property_set(name, Sample(0, val, "bool")) except: pass
def __decode_sample(self, buf): io_sample = parse_is(buf) for io_pin in range(4): key = 'DIO%d' % self.INPUT_CHANNEL_TO_PIN[io_pin] if io_sample.has_key(key): val = bool(io_sample[key]) name = "channel%d_input" % (io_pin + 1) try: self.property_set(name, Sample(0, val, "bool")) except: pass
def sample_indication(self, buf, addr): # Parse the I/O sample: io_sample = parse_is(buf) # Calculate sensor channel values: if io_sample.has_key("AD3"): samp = Sample(0, value=int(io_sample["AD3"]), unit="V") self.property_set("battery", samp) return
def sample_indication(self, buf, addr): # Parse the I/O sample: io_sample = parse_is(buf) # Calculate channel values: light_mv, temperature_mv, current_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ("AD1", "AD2", "AD3")) light = round(light_mv,0) if light < 0: # clamp to be zero or higher light = 0 power_state = self.property_get("power_on").value # TODO: CRA Max could you remove this offset code? Change to clip at 0. if not power_state: self.offset = current_mv * (157.0 /47.0) if self.offset >= 600.0: ## Probably a current spike from flipping the power relay self.offset = 520.0 current = round( (current_mv * (157.0 / 47.0) - self.offset) / 180.0 * 0.7071, 3) pf_adj = self.get_power_factor() # compute powerfactor adjusted current if 1.0 >= pf_adj and 0.0 <= pf_adj: current *= pf_adj if current <= 0.05: # Clip the noise at the bottom of this sensor: current = 0.0 temperature = (temperature_mv - 500.0) / 10.0 # self-heating correction temperature = (temperature - 4.0) - (0.017*current**2 + 0.631*current) temperature = round(temperature, 2) # Update channels: self.property_set("light", Sample(0, light, "brightness")) self.property_set("temperature", Sample(0, temperature, "C")) self.property_set("current", Sample(0, current, "A")) # check the realtime clock and compare to the last power_on_time # turn off if the idle_off_setting has been met or exceeded idle_off_setting = SettingsBase.get_setting(self, "idle_off_seconds") if (power_state and idle_off_setting > 0): if ((time.time() - self.__power_on_time) >= idle_off_setting): power_on_state_bool = self.property_get("power_on") power_on_state_bool.value = False self.prop_set_power_control(power_on_state_bool)
def sample_indication(self, buf, addr): #print "XBeeWatchport: Got sample indication from: %s, buf is len %d." \ # % (str(addr), len(buf)) io_sample = parse_is(buf) # Low battery check (attached to DIO11/P1): if SettingsBase.get_setting(self, "enable_low_battery"): # Invert the signal it is actually not_low_battery: low_battery = not bool(io_sample["DIO11"]) self.property_set("low_battery", Sample(0, low_battery)) # If we are in sleep mode, request a sample right now while we are awake! will_sleep = SettingsBase.get_setting(self, "sleep") if will_sleep == True: self.make_request()
def _sample_indication(self, buf, addr): """\ Receive and parse an I/O sample """ self.__tracer.debug('Sample indication') io_sample = parse_is(buf) # Calculate channel values: light_mv, temperature_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ("AD1", "AD2")) light = round(light_mv) temperature = round((temperature_mv - 500.0) / 10.0 - 4.0, 2) # Update channels: self.property_set("light", Sample(0, light, "brightness")) self.property_set("temperature", Sample(0, temperature, "C"))
def __decode_sample(self, buf): """\ Given raw sample data from our device, break it down, and send that result to each of our channels. Each channel will look at the sample, determine if any data in the sample is something it cares about, and if so, return back parsed data that is scaled for the type of channel it is. """ io_sample = parse_is(buf) for ch in self.__aio_channel_structures: sample = ch.decode_sample(io_sample, self.__scale, self.__offset) if sample != None: self.__parent.property_set(ch.name() + "_value", sample) for ch in self.__dio_channel_structures: sample = ch.decode_sample(io_sample, self.__scale, self.__offset) if sample != None: self.__parent.property_set(ch.name() + "_input", sample)
def sample_indication(self, buf, addr): # Parse the I/O sample: io_sample = parse_is(buf) # Calculate channel values: # upbutton_mv, onbutton_mv, downbutton_mv = \ # map(lambda cn: sample_to_mv(io_sample[cn]), ("AD0", "AD1", "AD2")) # Calculate sensor channel values: if io_sample.has_key("AD1") and io_sample.has_key("AD2") and io_sample.has_key("AD3"): light_mv, temperature_mv, humidity_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ("AD1", "AD2", "AD3")) up = round(light_mv, 2) on = round(temperature_mv, 2) down = round(humidity_mv, 2) power_state = self.property_get("power_on").value # Update channels: self.property_set("up", Sample(0, up, "mv")) self.property_set("on", Sample(0, on, "mv")) self.property_set("down", Sample(0, down, "mv")) # wire up any inputs input_source = SettingsBase.get_setting(self, 'input_source') cm = self.__core.get_service("channel_manager") cp = cm.channel_publisher_get() cdb = cm.channel_database_get() # cp.subscribe(input_source, self.prop_set_input) # try: # source_name = SettingsBase.get_setting(self, 'input_source') source_name = self.property_get("user_input_1").value if( source_name != None): source_chan = cdb.channel_get( source_name) # pre-load the starting value, which won't be published to us self.my_input = source_chan.get().value # self.property_set("adder_reg2", Sample(0, my_input)) self.property_set("utemp", Sample(0, self.my_input, "F"))
def sample_indication(self, buf, addr): self._tracer.calls("XBeeDIO.sample_indication()") # save time of last data, plus we want ALL of the samples to have # exact same timestamp (leaving 0 means some may be 1 second newer) self._last_timestamp = digitime.time() if self._tracer.info(): # will be true for debug also msg = "" change = False else: msg = None io_sample = parse_is(buf) for io_pin in range(4): key = self.DIO_RAW_NAME[io_pin] if key in io_sample: val = bool(io_sample[key]) name = self.CHN_INPUT_NAME[io_pin] if msg is not None: msg += self.DIO_USER_NAME[io_pin] # Always update the channel with the new sample value, and # its timestamp, even if it is the same as the previous value. try: # Make a copy of the old values. old = self.property_get(name) # Set the new value. self.property_set(name, Sample(self._last_timestamp, val, "bool")) # Print out some tracing about old versus new sample value. if msg is not None: if old.timestamp == 0 or old.value != val: # show value with '^' for change msg += '=%s^ ' % val change = True else: # show value, no change msg += '=%s ' % val except Exception, e: self._tracer.error("Exception generated: %s", str(e))
def _sample_indication(self, buf, addr): """\ Receive and parse an I/O sample """ self._tracer.calls("XBeeXBR.sample_indication()") io_sample = parse_is(buf) # print io_sample if io_sample["AD2"] <= self.BASE_RAW_TEMP_CUTOFF: # then assume has no valid inputs self._tracer.debug('sample_indication: lacks temperature/light hardware') return False # light is only a 'brightness', so we just return as mv light = round(self.raw_to_mv(io_sample["AD1"])) # temperature we'll convert from mv to degree C temperature = ((self.raw_to_mv(io_sample["AD2"]) - 500.0) / 10.0) + self.BASE_OFFSET_DEGC if SettingsBase.get_setting(self, "degf"): temperature = (temperature * 1.8) + 32.0 units = 'F' else: units = 'C' # offset is a simple float value - we don't care if DegC or DegF temperature += SettingsBase.get_setting(self, "offset") # Update channels: now = digitime.time() self.property_set("light", Sample(now, light, "brightness")) self.property_set("temperature", Sample(now, temperature, units)) self._tracer.debug('temperature:%0.1f%s light:%d ', temperature, units, light) return True
def __decode_sample(self, buf): """\ Given raw sample data from our device, break it down, and send that result to each of our channels. Each channel will look at the sample, determine if any data in the sample is something it cares about, and if so, return back parsed data that is scaled for the type of channel it is. """ io_sample = parse_is(buf) for ch in self.__aio_channel_structures: sample = ch.decode_sample(io_sample, self.__scale, self.__offset) if sample != None: chn = ch.name() + "_value" self.__parent.property_set(chn, sample) if self.__tracer.debug(): self.__tracer.debug("%s = %s", chn, sample) for ch in self.__dio_channel_structures: sample = ch.decode_sample(io_sample, self.__scale, self.__offset) if sample != None: chn = ch.name() + "_input" self.__parent.property_set(chn, sample) if self.__tracer.debug(): self.__tracer.debug("%s = %s", chn, sample)
def __decode_sample(self, buf): io_sample = parse_is(buf) for aio_num in range(4): aio_name = "AD%d" % (aio_num) channel_name = "channel%d_value" % (aio_num+1) channel_mode = SettingsBase.get_setting(self, "channel%d_mode" % (aio_num+1)) channel_mode = channel_mode.lower() channel_mode = self.LOCAL_AIO_MODE_MAP[channel_mode.lower()] if aio_name not in io_sample: continue raw_value = io_sample[aio_name] raw_value = raw_value * self.__scale # Don't reduce the raw_value by the offset if the raw_value is 1023. if self.__offset != 0.0 and raw_value < 1023: raw_value = raw_value - self.__offset raw_value = int(round(raw_value)) if channel_mode == self.LOCAL_AIO_MODE_CURRENTLOOP: mV = raw_value * 1200.0 / 1023 mA = mV / self.LOCAL_AIO_LOOP_R_OHMS # If we have gone negative by a tiny bit, which can happen # because of scaling, just set us back to 0.0. if mA < 0.0: mA = 0.0 self.property_set(channel_name, Sample(0, mA, "mA")) elif channel_mode == self.LOCAL_AIO_MODE_TENV: V = float(raw_value) * 1.2 / 1024.0 / self.LOCAL_AIO_TENV_SCALE self.property_set(channel_name, Sample(0, V, "V"))
def __decode_sample(self, buf): io_sample = parse_is(buf) for aio_num in range(4): aio_name = "AD%d" % (aio_num) channel_name = "channel%d_value" % (aio_num + 1) channel_mode = SettingsBase.get_setting( self, "channel%d_mode" % (aio_num + 1)) channel_mode = channel_mode.lower() channel_mode = self.LOCAL_AIO_MODE_MAP[channel_mode.lower()] if aio_name not in io_sample: continue raw_value = io_sample[aio_name] raw_value = raw_value * self.__scale # Don't reduce the raw_value by the offset if the raw_value is 1023. if self.__offset != 0.0 and raw_value < 1023: raw_value = raw_value - self.__offset raw_value = int(round(raw_value)) if channel_mode == self.LOCAL_AIO_MODE_CURRENTLOOP: mV = raw_value * 1200.0 / 1023 mA = mV / self.LOCAL_AIO_LOOP_R_OHMS # If we have gone negative by a tiny bit, which can happen # because of scaling, just set us back to 0.0. if mA < 0.0: mA = 0.0 self.property_set(channel_name, Sample(0, mA, "mA")) elif channel_mode == self.LOCAL_AIO_MODE_TENV: V = float(raw_value) * 1.2 / 1024.0 / self.LOCAL_AIO_TENV_SCALE self.property_set(channel_name, Sample(0, V, "V"))
def sample_indication(self, buf, addr): # if we haven't gotten initial state yet, ask for it if self.property_get('power_on').value == UNKNOWN_POWER_STATE: if not self._set_initial_power_state(): self.__tracer.warning('Power state unknown, ignoring ' 'sample indication.') return # Parse the I/O sample: io_sample = parse_is(buf) # Calculate channel values: light_mv, temperature_mv, current_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ('AD1', 'AD2', 'AD3')) light = round(light_mv, 0) if light < 0: # clamp to be zero or higher light = 0 power_state = Boolean(self.property_get("power_on").value) # TODO: CRA Max could you remove this offset code? Change to # clip at 0. if not power_state: self.offset = current_mv * (157.0 / 47.0) if self.offset >= 600.0: # Probably a current spike from flipping the power relay self.offset = 520.0 current = round((current_mv * (157.0 / 47.0) - self.offset) \ / 180.0 * 0.7071, 3) pf_adj = self.get_power_factor() # compute powerfactor adjusted current if 1.0 >= pf_adj and 0.0 <= pf_adj: current *= pf_adj if current <= 0.05: # Clip the noise at the bottom of this sensor: current = 0.0 temperature = (temperature_mv - 500.0) / 10.0 # self-heating correction temperature = (temperature - 4.0) - \ (0.017 * current ** 2 + 0.631 * current) temperature = round(temperature, 2) # Update channels: self.property_set("light", Sample(0, light, "brightness")) self.property_set("temperature", Sample(0, temperature, "C")) self.property_set("current", Sample(0, current, "A")) self.__tracer.debug('Power:%r light:%d %0.1fC %0.2fA', power_state, light, temperature, current) # check the realtime clock and compare to the last power_on_time # turn off if the idle_off_setting has been met or exceeded idle_off_setting = SettingsBase.get_setting(self, "idle_off_seconds") if (power_state and idle_off_setting > 0): if ((digitime.time() - self.__power_on_time) \ >= idle_off_setting): power_on_state_bool = self.property_get("power_on") power_on_state_bool.value = False self.prop_set_power_control(power_on_state_bool) self.__tracer.debug('Idle Off True')
def sample_indication(self, buf, addr): # check if we want to scroll a trace line or not do_trace = SettingsBase.get_setting(self, "trace") if do_trace: msg = ['XBeeSensor(%s): ' % self.__name] # Parse the I/O sample: io_sample = parse_is(buf) # Calculate sensor channel values: if io_sample.has_key("AD1") and io_sample.has_key("AD2") and io_sample.has_key("AD3"): light_mv, temperature_mv, humidity_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ("AD1", "AD2", "AD3")) # # handle temperature - first as celsius # scale = "F" temperature = temperature_mv if not SettingsBase.get_setting(self, "sleep"): # self-heating correction if running full-time - reduce 2 DegC temperature -= .001 temperature = round(temperature, 2) #self.property_set("motion", Sample(0, temperature, scale)) #if do_trace: # msg.append( "%d %s" % (temperature, scale)) # # handle the light value # light = round((light_mv / 10), 2) if light < 0: # clamp to be zero or higher light = 0 self.property_set("temperature", Sample(0, light, "F")) # if do_trace: # msg.append( ", %d brightness" % light) # # handle humidity - might be missing # if self.property_exists("humidity"): humidity = ((humidity_mv * 108.2 / 33.2) / 5000.0 - 0.16) / 0.0062 if humidity < 0.0: # clamp to min of 0% humidity = 0.0 elif humidity > 100.0: # clamp to be max of 100% humidity = 100.0 self.property_set("humidity", Sample(0, humidity, "%")) if do_trace: msg.append( ", %d RH%%" % humidity) else: # it remains the original default humidity = 0 activate = self.property_get("power_on").value # Low battery check (attached to DIO11/P1): # Invert the signal it is actually not_low_battery: if io_sample.has_key("DIO2") and activate: low_battery = not bool(io_sample["DIO2"]) if low_battery != bool(self.property_get("low_battery").value): self.property_set("low_battery", Sample(0, low_battery)) if do_trace: if low_battery: msg.append( ", low_battery") # try to keep memory use from dragging out msg = "".join( msg) print msg del msg temp = self.property_get("temperature").value SettingsBase.set_pending_setting(self, 'temp', temp) motion = self.property_get("low_battery").value if activate and motion: self.property_set("motion_event", Sample(0, Boolean(True, style=STYLE_ONOFF))) else: self.property_set("motion_event", Sample(0, Boolean(False, style=STYLE_ONOFF))) return
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 sample_indication(self, buf, addr): self._tracer.calls("XBeeRPM.sample_indication()") # save time of last data, plus we want ALL of the samples to have # exact same timestamp (leaving 0 means some may be 1 second newer) self._last_timestamp = digitime.time() # new method for mesh health monitoring self.set_time_of_last_data(self._last_timestamp) # if we haven't gotten initial state yet, ask for it if self.property_get('power_on').value == UNKNOWN_POWER_STATE: if not self._set_initial_power_state(): self._tracer.warning('Power state unknown, ignoring ' 'sample indication.') return # Parse the I/O sample: io_sample = parse_is(buf) # Calculate channel values: light_mv, temperature_mv, current_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ('AD1', 'AD2', 'AD3')) light = round(light_mv, 0) if light < 0: # clamp to be zero or higher light = 0 power_state = Boolean(self.property_get("power_on").value, style=STYLE_ONOFF) # TODO: CRA Max could you remove this offset code? Change to # clip at 0. if not power_state: self.offset = current_mv * (157.0 / 47.0) if self.offset >= 600.0: # Probably a current spike from flipping the power relay self.offset = 520.0 current = round((current_mv * (157.0 / 47.0) - self.offset) \ / 180.0 * 0.7071, 3) pf_adj = self.get_power_factor() # compute powerfactor adjusted current if 1.0 >= pf_adj and 0.0 <= pf_adj: current *= pf_adj if current <= 0.05: # Clip the noise at the bottom of this sensor: current = 0.0 temperature = (temperature_mv - 500.0) / 10.0 # self-heating correction temperature = (temperature - 4.0) - \ (0.017 * current ** 2 + 0.631 * current) if SettingsBase.get_setting(self, "degf"): temperature = (temperature * 1.8) + 32.0 units = 'F' else: units = 'C' temperature = round(temperature, 2) # Update channels: self.property_set("light", Sample(self._last_timestamp, light, "brightness")) self.property_set("temperature", Sample(self._last_timestamp, temperature, units)) self.property_set("current", Sample(self._last_timestamp, current, "A")) ## Check if sample has information about the power state if io_sample.has_key('AD4'): ## Define it as a boolean compare_state = Boolean(io_sample['AD4'], style=STYLE_ONOFF) ## compare to current power_state if not compare_state == power_state: ## It's different, set the power state to the new value self._tracer.warning("Power state was: %s, but now it is: %s" % (power_state, compare_state)) self._tracer.warning("Returning power state to: %s" % (power_state)) self.prop_set_power_control(Sample(0, str(power_state))) if self._tracer.info(): self._tracer.info('Power:%r light:%d %0.1f%s %0.2fA', power_state, light, temperature, units, current) # check the realtime clock and compare to the last power_on_time # turn off if the idle_off_setting has been met or exceeded idle_off_setting = SettingsBase.get_setting(self, "idle_off_seconds") if (power_state and idle_off_setting > 0): if ((digitime.time() - self.__power_on_time) \ >= idle_off_setting): power_on_state_bool = self.property_get("power_on") power_on_state_bool.value = False self.prop_set_power_control(power_on_state_bool) self._tracer.debug('Idle Off True')
def sample_indication(self, buf, addr): # Parse the I/O sample: io_sample = parse_is(buf)
def sample_indication(self, buf, addr): # save time of last data, plus we want ALL of the samples to have # exact same timestamp (leaving 0 means some may be 1 second newer) self._last_timestamp = digitime.time() if self.__tracer.info(): msg = [] else: msg = None # Parse the I/O sample: io_sample = parse_is(buf) # Calculate sensor channel values: if "AD1" in io_sample and "AD2" in io_sample and \ "AD3" in io_sample: light_mv, temperature_mv, humidity_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ("AD1", "AD2", "AD3")) # # handle temperature - first as celsius # scale = "C" temperature = (temperature_mv - 500.0) / 10.0 if not SettingsBase.get_setting(self, "sleep"): # self-heating correction if running full-time - reduce 2 DegC temperature -= 2.0 temperature = round(temperature, 2) self.property_set("temperature", Sample(self._last_timestamp, temperature, scale)) if msg is not None: msg.append("%d %s" % (temperature, scale)) # # handle the light value # light = round(light_mv, 0) if light < 0: # clamp to be zero or higher light = 0 self.property_set("light", Sample(self._last_timestamp, light, "brightness")) if msg is not None: msg.append(", %d brightness" % light) # # handle humidity - might be missing # if self.property_exists("humidity"): humidity = ((humidity_mv * 108.2 / 33.2) / 5000.0 - 0.16) / \ 0.0062 if humidity < 0.0: # clamp to min of 0% humidity = 0.0 elif humidity > 100.0: # clamp to be max of 100% humidity = 100.0 self.property_set("humidity", Sample(self._last_timestamp, humidity, "%")) if msg is not None: # cannot use %% in string, __tracer will misunderstand msg.append(", %d RH" % humidity) else: # it remains the original default humidity = 0 # Low battery check (attached to DIO11/P1): # Invert the signal it is actually not_low_battery: if "DIO11" in io_sample: low_battery = not bool(io_sample["DIO11"]) if low_battery != bool(self.property_get("low_battery").value): self.property_set("low_battery", Sample(self._last_timestamp, low_battery)) if low_battery and msg is not None: msg.append(", low_battery") # try to keep memory use from dragging out if msg is not None: self.__tracer.info("".join(msg)) del msg return
def sample_indication(self, buf, addr): self._tracer.calls("XBeeSensor.sample_indication()") # save time of last data, plus we want ALL of the samples to have # exact same timestamp (leaving 0 means some may be 1 second newer) self._last_timestamp = digitime.time() # new method for mesh health monitoring self.set_time_of_last_data(self._last_timestamp) if self._tracer.info(): msg = [] else: msg = None # Parse the I/O sample: io_sample = parse_is(buf) # Calculate sensor channel values: if "AD1" in io_sample and "AD2" in io_sample and \ "AD3" in io_sample: light_mv, temperature_mv, humidity_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ("AD1", "AD2", "AD3")) # # handle temperature - first as celsius # temperature = (temperature_mv - 500.0) / 10.0 if not SettingsBase.get_setting(self, "sleep"): # self-heating correction if running full-time - reduce 2 DegC temperature -= 2.0 if SettingsBase.get_setting(self, "degf"): temperature = (temperature * 1.8) + 32.0 units = 'F' else: units = 'C' # offset is a simple float value - we don't care if DegC or DegF temperature += SettingsBase.get_setting(self, "offset") temperature = round(temperature, 2) self.property_set("temperature", Sample(self._last_timestamp, temperature, units)) if msg is not None: msg.append("%d %s" % (temperature, units)) # # handle the light value # light = round(light_mv, 0) if light < 0: # clamp to be zero or higher light = 0 self.property_set( "light", Sample(self._last_timestamp, light, "brightness")) if msg is not None: msg.append(", %d brightness" % light) # # handle humidity - might be missing # if self.property_exists("humidity"): humidity = ((humidity_mv * 108.2 / 33.2) / 5000.0 - 0.16) / \ 0.0062 if humidity < 0.0: # clamp to min of 0% humidity = 0.0 elif humidity > 100.0: # clamp to be max of 100% humidity = 100.0 self.property_set("humidity", Sample(self._last_timestamp, humidity, "%")) if msg is not None: # cannot use %% in string, __tracer will misunderstand msg.append(", %d RH" % humidity) else: # it remains the original default humidity = 0 # Low battery check (attached to DIO11/P1): # Invert the signal it is actually not_low_battery: if "DIO11" in io_sample: low_battery = not bool(io_sample["DIO11"]) if low_battery != bool(self.property_get("low_battery").value): self.property_set("low_battery", Sample(self._last_timestamp, low_battery)) if low_battery and msg is not None: msg.append(", low_battery") # try to keep memory use from dragging out if msg is not None: self._tracer.info("".join(msg)) del msg return
def sample_indication(self, buf, addr): zero_clamp = SettingsBase.get_setting(self, "zero_clamp") # check if we want to scroll a trace line or not msg = [] raw_output = SettingsBase.get_setting(self, "raw_value") #print "XBeeAIO: Got sample indication from: %s, buf is len %d." \ # % (str(addr), len(buf)) io_sample = parse_is(buf) for aio_num in range(4): aio_name = "AD%d" % (aio_num) channel_name = "channel%d_value" % (aio_num+1) channel2_name = "channel%d_value" % (aio_num+2) channel_mode = SettingsBase.get_setting(self, "channel%d_mode" % (aio_num+1)) channel_mode = channel_mode.lower() channel_mode = AIO_MODE_MAP[channel_mode.lower()] if aio_name not in io_sample: continue msg.append('%s=' % aio_name) raw_value = io_sample[aio_name] if( zero_clamp and (raw_value < zero_clamp)): # then user doesn't want to see low near-zero garbage raw_value = 0 if channel_mode == AIO_MODE_OFF: # self.property_set(channel_name, Sample(0, 0, "")) msg.append('Off ') elif( raw_output): # then just put the raw binary in the sample self.property_set(channel_name, Sample(0, float(raw_value), "raw")) msg.append('%04d ' % raw_value) elif channel_mode == AIO_MODE_CURRENTLOOP: mV = raw_value * 1200.0 / 1023 mA = mV / AIO_LOOP_R_OHMS self.property_set(channel_name, Sample(0, mA, "mA")) msg.append('%0.2fmA ' % mA) elif channel_mode == AIO_MODE_TENV: V = (float(raw_value) / 1024) * 10.25 self.property_set(channel_name, Sample(0, V, "V")) # msg.append('(%04d) ' % raw_value) msg.append('%0.2fV ' % V) elif channel_mode == AIO_MODE_DIFFERENTIAL: # Only report the even AIO channels, ie, 0 and 2. # We will replicate and report these values for the # odd AIO channels as well. if aio_num % 2: continue mid = AIO_DIFFERENTIAL_MIDPOINT_CHANNEL0 if aio_num == 2: mid = AIO_DIFFERENTIAL_MIDPOINT_CHANNEL2 V = 0 if raw_value >= mid: V = ((raw_value - mid) / (1023.0 - mid)) * \ AIO_DIFFERENTIAL_MAX else: V = ((mid - raw_value) / mid) * AIO_DIFFERENTIAL_MIN self.property_set(channel_name, Sample(0, V, "V")) self.property_set(channel2_name, Sample(0, V, "V")) msg.append('%0.2fV ' % V) # msg.append('%s=%0,2fV ' % (aio_name+2, V)) # Low battery check (attached to DIO11/P1): if SettingsBase.get_setting(self, "enable_low_battery"): # Invert the signal it is actually not_low_battery: low_battery = not bool(io_sample["DIO11"]) self.property_set("low_battery", Sample(0, low_battery)) if( low_battery): msg.append('bat=LOW!') self.__tracer.debug("".join( msg))
def sample_indication(self, buf, addr): self._tracer.calls("XBeeAIO.sample_indication()") zero_clamp = SettingsBase.get_setting(self, "zero_clamp") # check if we want to scroll a trace line or not if self._tracer.info(): # will be true for debug also msg = [] else: msg = None raw_output = SettingsBase.get_setting(self, "raw_value") io_sample = parse_is(buf) if self._tracer.calls(): self._tracer.calls('io_sample:%s', str(io_sample)) for aio_num in range(4): aio_name = "AD%d" % (aio_num) channel_name = self.CHN_VALUE_NAME[aio_num] channel_mode = SettingsBase.get_setting( self, self.CHN_MODE_NAME[aio_num]) channel_mode = channel_mode.lower() channel_mode = AIO_MODE_MAP[channel_mode.lower()] if aio_name not in io_sample: continue if msg is not None: msg.append('%s=' % aio_name) raw_value = io_sample[aio_name] if zero_clamp and (raw_value < zero_clamp): # then user doesn't want to see low near-zero garbage raw_value = 0 if channel_mode == AIO_MODE_OFF: # self.property_set(channel_name, Sample(0, 0, "")) if msg is not None: msg.append('Off ') elif raw_output: # then just put the raw binary in the sample self.property_set(channel_name, Sample(0, float(raw_value), "raw")) if msg is not None: msg.append('%04d ' % raw_value) elif channel_mode == AIO_MODE_CURRENTLOOP: mV = raw_value * 1200.0 / 1023 mA = mV / AIO_LOOP_R_OHMS self.property_set(channel_name, Sample(0, mA, "mA")) if msg is not None: msg.append('%0.2fmA ' % mA) elif channel_mode == AIO_MODE_TENV: V = (float(raw_value) / 1024) * 10.25 self.property_set(channel_name, Sample(0, V, "V")) # msg.append('(%04d) ' % raw_value) if msg is not None: msg.append('%0.2fV ' % V) elif channel_mode == AIO_MODE_DIFFERENTIAL: # Only report the even AIO channels, ie, 0 and 2. # We will replicate and report these values for the # odd AIO channels as well. if aio_num % 2: continue mid = AIO_DIFFERENTIAL_MIDPOINT_CHANNEL0 if aio_num == 2: mid = AIO_DIFFERENTIAL_MIDPOINT_CHANNEL2 V = 0 if raw_value >= mid: V = ((raw_value - mid) / (1023.0 - mid)) * \ AIO_DIFFERENTIAL_MAX else: V = ((mid - raw_value) / mid) * AIO_DIFFERENTIAL_MIN self.property_set(channel_name, Sample(0, V, "V")) channel2_name = "channel%d_value" % (aio_num + 2) self.property_set(channel2_name, Sample(0, V, "V")) if msg is not None: msg.append('%0.2fV ' % V) # msg.append('%s=%0,2fV ' % (aio_name+2, V)) # Low battery check (attached to DIO11/P1): if SettingsBase.get_setting(self, "enable_low_battery"): # Invert the signal it is actually not_low_battery: low_battery = not bool(io_sample["DIO11"]) self.property_set("low_battery", Sample(0, low_battery)) if low_battery and msg is not None: msg.append('bat=LOW!') if msg is not None: self._tracer.info("".join(msg))
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)
def sample_indication(self, buf, addr): excl = self.property_get("excl").value if excl: self.property_set("excl", Sample(0, value=Boolean(bool(0), style=STYLE_ONOFF))) # Parse the I/O sample: extended_address = SettingsBase.get_setting(self, "extended_address") if self.count > 20: try: db = self.__xbee_manager.xbee_device_ddo_get_param(extended_address, "DB", use_cache=True) # sv = self.__xbee_manager.xbee_device_ddo_get_param(extended_address, # "%V", use_cache=True) try: dd = struct.unpack(">B", db) #print dd except: self.property_set("signal", Sample(0, value="0", unit="")) print "failed 4" # try: # sv = struct.unpack(">H", sv) # except: # self.property_set("volts", Sample(0, value="failed", unit="")) # print sv dd = str(dd) dd = dd[1:3] dd = "-" + dd + " dB" # print "signal strength =" # print dd self.property_set("signal", Sample(0, value=str(dd), unit="")) # sv = str(sv) # sv = sv[1:5] # sv = int(sv) # print sv # volts = (sv * 1.1719) / 1000 # print "volts =" # print volts # self.property_set("volts", Sample(0, value=str(volts), unit="")) except: self.property_set("signal", Sample(0, value="disconnected", unit="")) print "failed to get signal and voltage" if self.count < 22: self.count += 1 io_sample = parse_is(buf) # Calculate channel values: light_mv, temperature_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ("AD1", "AD2")) light = round(light_mv) temperature = round((((temperature_mv - 500.0) / 10.0 - 4.0)) * 1.8 + 32, 2) # Update channels: self.property_set("light", Sample(0, light, "brightness")) self.property_set("temperature", Sample(0, temperature, self.include_unit))
def sample_indication(self, buf, addr): # check if we want to scroll a trace line or not if self.count == 720: self.get_signal() if self.count == 720: self.count = 0 if self.count < 722: self.count += 1 do_trace = SettingsBase.get_setting(self, "trace") if do_trace: msg = ['XBeeSensor(%s): ' % self.__name] # Parse the I/O sample: io_sample = parse_is(buf) # Calculate sensor channel values: if io_sample.has_key("AD1") and io_sample.has_key("AD2") and io_sample.has_key("AD3"): light_mv, temperature_mv, humidity_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ("AD1", "AD2", "AD3")) # # handle temperature - first as celsius # scale = self.include_unit temperature = (((((temperature_mv - 500.0) / 10.0) * (1.8) ) + 32) + 2.6) if not SettingsBase.get_setting(self, "sleep"): # self-heating correction if running full-time - reduce 2 DegC temperature -= 2.0 temperature = round(temperature, 2) self.property_set("temperature", Sample(0, temperature, scale)) if do_trace: msg.append( "%d %s" % (temperature, scale)) # # handle the light value # light = round(light_mv,0) if light < 0: # clamp to be zero or higher light = 0 self.property_set("light", Sample(0, light, "brightness")) if do_trace: msg.append( ", %d brightness" % light) # # handle humidity - might be missing # if self.property_exists("humidity"): humidity = ((humidity_mv * 108.2 / 33.2) / 5000.0 - 0.16) / 0.0062 if humidity < 0.0: # clamp to min of 0% humidity = 0.0 elif humidity > 100.0: # clamp to be max of 100% humidity = 100.0 self.property_set("humidity", Sample(0, humidity, "%")) if do_trace: msg.append( ", %d RH%%" % humidity) else: # it remains the original default humidity = 0 # Low battery check (attached to DIO11/P1): # Invert the signal it is actually not_low_battery: if io_sample.has_key("DIO11"): low_battery = not bool(io_sample["DIO11"]) if low_battery != bool(self.property_get("low_battery").value): self.property_set("low_battery", Sample(0, low_battery)) if do_trace: if low_battery: msg.append( ", low_battery") # try to keep memory use from dragging out msg = "".join( msg) print msg del msg excl = self.property_get("excl").value if excl: self.property_set("excl", Sample(0, value=Boolean(bool(0), style=STYLE_ONOFF))) return
def sample_indication(self, buf, addr): # wire up any inputs # input_source = SettingsBase.get_setting(self, 'input_source') cm = self.__core.get_service("channel_manager") cp = cm.channel_publisher_get() cdb = cm.channel_database_get() # cp.subscribe(input_source, self.prop_set_input) # try: # source_name = SettingsBase.get_setting(self, 'input_source') source_name = self.property_get("user_input_1").value if( source_name != None): source_chan = cdb.channel_get( source_name) # pre-load the starting value, which won't be published to us self.my_input = source_chan.get().value # self.property_set("adder_reg2", Sample(0, my_input)) self.property_set("driving_temp", Sample(0, self.my_input, "F")) # self.property_set("input", Sample(0, self.my_input)) # cp.subscribe(source_name, self.update_power_state1) # cp.subscribe( source_name, self.prop_set_input ) # self.property_set("2_high", Sample(0, 1.0)) # Parse the I/O sample: io_sample = parse_is(buf) # Calculate channel values: # upbutton_mv, onbutton_mv, downbutton_mv = \ # map(lambda cn: sample_to_mv(io_sample[cn]), ("AD0", "AD1", "AD2")) if io_sample.has_key("AD0") and io_sample.has_key("AD1") and io_sample.has_key("AD2"): light_mv, temperature_mv, humidity_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ("AD0", "AD1", "AD2")) up = (round(temperature_mv, 2)) / 10 red_light = round(light_mv) # on = round(temperature_mv, 2) # down = round(humidity_mv, 2) # power_state = self.property_get("power_on").value # Update channels: self.property_set("temperature", Sample(0, up, "F")) self.property_set("red_light", Sample(0, red_light, "mv")) # self.property_set("on", Sample(0, on, "mv")) # self.property_set("down", Sample(0, down, "mv")) red = self.property_get("red_light").value heat = self.property_get("heat").value old = self.property_get("switch_to_old").value on = self.property_get("heat_ac_on").value old_on = self.property_get("old_thermostat_on").value if red_light < 100.0 and old_on: self.property_set("old_thermostat_on", Sample(0, Boolean(False, style=STYLE_ONOFF))) if red_light > 100.0 and not old_on: self.old_thermostat(Sample(0, Boolean("on", STYLE_ONOFF))) # if red_light > 100.0 and not old_on: # self.old_thermostat(Sample(0, Boolean("on", STYLE_ONOFF))) # self.property_set("2_low", Sample(0, 1.0)) # if red_light < 100 and old: # self.property_set("switch_to_old", Sample(0, Boolean(False, style=STYLE_ONOFF))) # self.property_set("old_thermostat_on", Sample(0, Boolean(False, style=STYLE_ONOFF))) # # if red_light < 100 and old_on: # self.property_set("switch_to_old", Sample(0, Boolean(False, style=STYLE_ONOFF))) # self.property_set("old_thermostat_on", Sample(0, Boolean(False, style=STYLE_ONOFF))) driving = self.property_get("driving_temp").value des_temp = self.property_get("desired_temp").value ac = self.property_get("AC").value temp_plus = des_temp + 0.5 temp_minus = des_temp - 0.5 if heat and on and driving > temp_plus: self.prop_set_power_control2_low(Sample(0, Boolean("on", STYLE_ONOFF))) time.sleep(0.75) self.prop_set_power_control2_low(Sample(0, Boolean("off", STYLE_ONOFF))) # self.property_set("2_low", Sample(0, 1.0)) if heat and not on and driving < temp_minus: self.prop_set_power_control2_high(Sample(0, Boolean("on", STYLE_ONOFF))) time.sleep(0.75) self.prop_set_power_control2_high(Sample(0, Boolean("off", STYLE_ONOFF))) if ac and not on and driving > temp_plus: self.prop_set_power_control2_high(Sample(0, Boolean("on", STYLE_ONOFF))) time.sleep(0.75) self.prop_set_power_control2_high(Sample(0, Boolean("off", STYLE_ONOFF))) # self.property_set("2_low", Sample(0, 1.0)) if ac and on and driving < temp_minus: self.prop_set_power_control2_low(Sample(0, Boolean("on", STYLE_ONOFF))) time.sleep(0.75) self.prop_set_power_control2_low(Sample(0, Boolean("off", STYLE_ONOFF))) # self.property_set("2_high", Sample(0, 1.0)) time.sleep(5.0)
def sample_indication(self, buf, addr): msg = [] # Parse the I/O sample: io_sample = parse_is(buf) # Calculate sensor channel values: if io_sample.has_key("AD1") and io_sample.has_key("AD2") and io_sample.has_key("AD3"): light_mv, temperature_mv, humidity_mv = \ map(lambda cn: sample_to_mv(io_sample[cn]), ("AD1", "AD2", "AD3")) # # handle temperature - first as celsius # scale = "C" temperature = (temperature_mv - 500.0) / 10.0 if not SettingsBase.get_setting(self, "sleep"): # self-heating correction if running full-time - reduce 2 DegC temperature -= 2.0 temperature = round(temperature, 2) self.property_set("temperature", Sample(0, temperature, scale)) msg.append( "%d %s" % (temperature, scale)) # # handle the light value # light = round(light_mv,0) if light < 0: # clamp to be zero or higher light = 0 self.property_set("light", Sample(0, light, "brightness")) msg.append( ", %d brightness" % light) # # handle humidity - might be missing # if self.property_exists("humidity"): humidity = ((humidity_mv * 108.2 / 33.2) / 5000.0 - 0.16) / 0.0062 if humidity < 0.0: # clamp to min of 0% humidity = 0.0 elif humidity > 100.0: # clamp to be max of 100% humidity = 100.0 self.property_set("humidity", Sample(0, humidity, "%")) msg.append( ", %d RH%%" % humidity) else: # it remains the original default humidity = 0 # Low battery check (attached to DIO11/P1): # Invert the signal it is actually not_low_battery: if io_sample.has_key("DIO11"): low_battery = not bool(io_sample["DIO11"]) if low_battery != bool(self.property_get("low_battery").value): self.property_set("low_battery", Sample(0, low_battery)) if low_battery: msg.append( ", low_battery") # try to keep memory use from dragging out self.__tracer.debug("".join(msg)) del msg return
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)