def get_last_measurement(self): """ Retrieve the latest sensor measurement from InfluxDB :rtype: None """ self.last_measurement_success = False # Get latest measurement (from within the past minute) from influxdb try: self.last_measurement = read_last_influxdb( INFLUXDB_HOST, INFLUXDB_PORT, INFLUXDB_USER, INFLUXDB_PASSWORD, INFLUXDB_DATABASE, self.sensor_id, self.measure_type) if self.last_measurement: measurement_list = list(self.last_measurement.get_points( measurement=self.measure_type)) self.last_time = measurement_list[0]['time'] self.last_measurement = measurement_list[0]['value'] utc_dt = datetime.strptime(self.last_time.split(".")[0], '%Y-%m-%dT%H:%M:%S') utc_timestamp = calendar.timegm(utc_dt.timetuple()) local_timestamp = str(datetime.fromtimestamp(utc_timestamp)) self.logger.debug("[PID {}] Latest {}: {} @ {}".format( self.pid_id, self.measure_type, self.last_measurement, local_timestamp)) self.last_measurement_success = True else: self.logger.warning("[PID {}] No data returned " "from influxdb".format(self.pid_id)) except Exception as except_msg: self.logger.exception("[PID {}] Failed to read " "measurement from the influxdb " "database: {}".format(self.pid_id, except_msg))
def getLastMeasurement(self, measurement_type): """ Retrieve the latest sensor measurement :return: The latest sensor value or None if no data available :rtype: float or None :param measurement_type: Environmental condition of a sensor (e.g. temperature, humidity, pressure, etc.) :type measurement_type: str """ last_measurement = read_last_influxdb(INFLUXDB_HOST, INFLUXDB_PORT, INFLUXDB_USER, INFLUXDB_PASSWORD, INFLUXDB_DATABASE, self.sensor_id, measurement_type).raw if last_measurement: number = len(last_measurement['series'][0]['values']) last_value = last_measurement['series'][0]['values'][number-1][1] return last_value else: return None
def get_lcd_strings(self): """ Retrieve measurements and/or timestamps and create strings for LCDs If no data is retrieveable, create string "NO DATA RETURNED". """ # loop to acquire all measurements required to be displayed on the LCD for i in range(1, self.lcd_y_lines+1): if self.lcd_line[i]['id']: # Get latest measurement (from within the past minute) from influxdb # FROM '/.*/' returns any measurement (for grabbing time of last measurement) last_measurement_success = False try: if self.lcd_line[i]['measurement'] == 'relay_state': self.lcd_line[i]['measurement_value'] = self.relay_state(self.lcd_line[i]['id']) last_measurement_success = True else: if self.lcd_line[i]['measurement'] == 'time': last_measurement = read_last_influxdb( INFLUXDB_HOST, INFLUXDB_PORT, INFLUXDB_USER, INFLUXDB_PASSWORD, INFLUXDB_DATABASE, self.lcd_line[i]['id'], '/.*/', duration_min=5).raw else: last_measurement = read_last_influxdb( INFLUXDB_HOST, INFLUXDB_PORT, INFLUXDB_USER, INFLUXDB_PASSWORD, INFLUXDB_DATABASE, self.lcd_line[i]['id'], self.lcd_line[i]['measurement'], duration_min=5).raw if last_measurement: number = len(last_measurement['series'][0]['values']) self.lcd_line[i]['time'] = last_measurement['series'][0]['values'][number-1][0] self.lcd_line[i]['measurement_value'] = last_measurement['series'][0]['values'][number-1][1] utc_dt = datetime.datetime.strptime(self.lcd_line[i]['time'].split(".")[0], '%Y-%m-%dT%H:%M:%S') utc_timestamp = calendar.timegm(utc_dt.timetuple()) local_timestamp = str(datetime.datetime.fromtimestamp(utc_timestamp)) self.logger.debug("[LCD {}] Latest {}: {} @ {}".format( self.lcd_id, self.lcd_line[i]['measurement'], self.lcd_line[i]['measurement_value'], local_timestamp)) last_measurement_success = True else: self.lcd_line[i]['time'] = None self.lcd_line[i]['measurement_value'] = None self.logger.debug("[LCD {}] No data returned " "from influxdb".format(self.lcd_id)) except Exception as except_msg: self.logger.debug("[LCD {}] Failed to read " "measurement from the influxdb database: " "{}".format(self.lcd_id, except_msg)) try: if last_measurement_success: # Determine if the LCD output will have a value unit measurement = '' if self.lcd_line[i]['measurement'] == 'setpoint': with session_scope(MYCODO_DB_PATH) as new_session: pid = new_session.query(PID).filter( PID.id == self.lcd_line[i]['id']).first() new_session.expunge_all() new_session.close() measurement = pid.measure_type elif self.lcd_line[i]['measurement'] in ['temperature', 'temperature_die', 'temperature_object', 'humidity', 'co2', 'lux', 'pressure', 'altitude']: measurement = self.lcd_line[i]['measurement'] elif self.lcd_line[i]['measurement'] == 'duration_sec': measurement = 'duration_sec' # Produce the line that will be displayed on the LCD number_characters = self.lcd_x_characters if self.lcd_line[i]['measurement'] == 'time': # Convert UTC timestamp to local timezone utc_dt = datetime.datetime.strptime(self.lcd_line[i]['time'].split(".")[0], '%Y-%m-%dT%H:%M:%S') utc_timestamp = calendar.timegm(utc_dt.timetuple()) self.lcd_string_line[i] = str(datetime.datetime.fromtimestamp(utc_timestamp)) elif measurement: value_length = len(str(self.lcd_line[i]['measurement_value'])) unit_length = len(self.measurement_unit['metric'][measurement]) name_length = number_characters - value_length - unit_length - 2 name_cropped = self.lcd_line[i]['name'].ljust(name_length)[:name_length] self.lcd_string_line[i] = '{} {} {}'.format( name_cropped, self.lcd_line[i]['measurement_value'], self.measurement_unit['metric'][measurement]) else: value_length = len(str(self.lcd_line[i]['measurement_value'])) name_length = number_characters - value_length - 1 name_cropped = self.lcd_line[i]['name'][:name_length] self.lcd_string_line[i] = '{} {}'.format( name_cropped, self.lcd_line[i]['measurement_value']) else: self.lcd_string_line[i] = 'NO DATA < 5 MIN' except Exception as except_msg: self.logger.exception("[LCD {}] Error ({}): {}".format( self.lcd_id, except_msg)) else: self.lcd_string_line[i] = ''