예제 #1
0
    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))
예제 #2
0
    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
예제 #3
0
    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] = ''