예제 #1
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,
                                              int(self.period*1.5)).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
예제 #2
0
 def get_measurement(self, display_id, i):
     try:
         if self.lcd_line[display_id][i]['measurement'] == 'relay_state':
             self.lcd_line[display_id][i][
                 'measurement_value'] = self.output_state(
                     self.lcd_line[display_id][i]['id'])
             return True
         else:
             if self.lcd_line[display_id][i]['measurement'] == 'time':
                 last_measurement = read_last_influxdb(
                     self.lcd_line[display_id][i]['id'],
                     '/.*/',
                     duration_sec=self.lcd_max_age[display_id][i])
             else:
                 last_measurement = read_last_influxdb(
                     self.lcd_line[display_id][i]['id'],
                     self.lcd_line[display_id][i]['measurement'],
                     duration_sec=self.lcd_max_age[display_id][i])
             if last_measurement:
                 self.lcd_line[display_id][i]['time'] = last_measurement[0]
                 self.lcd_line[display_id][i][
                     'measurement_value'] = last_measurement[1]
                 utc_dt = datetime.datetime.strptime(
                     self.lcd_line[display_id][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("Latest {}: {} @ {}".format(
                     self.lcd_line[display_id][i]['measurement'],
                     self.lcd_line[display_id][i]['measurement_value'],
                     local_timestamp))
                 return True
             else:
                 self.lcd_line[display_id][i]['time'] = None
                 self.lcd_line[display_id][i]['measurement_value'] = None
                 self.logger.debug("No data returned from influxdb")
         return False
     except Exception as except_msg:
         self.logger.debug(
             "Failed to read measurement from the influxdb database: "
             "{err}".format(err=except_msg))
         return False
예제 #3
0
    def run(self):
        try:
            self.running = True
            self.logger.info("Activated in {:.1f} ms".format(
                (timeit.default_timer() - self.thread_startup_timer) * 1000))
            self.ready.set()

            while self.running:

                if self.is_activated and t.time() > self.timer:
                    # Ensure the timer ends in the future
                    while t.time() > self.timer:
                        self.timer = self.timer + self.period

                    # If PID is active, retrieve input measurement and update PID output
                    if self.math_type == 'average' and self.inputs:
                        missing_measure = False
                        measurements = []
                        inputs_list = self.inputs.split(';')
                        for each_input_set in inputs_list:
                            input_id = each_input_set.split(',')[0]
                            input_measure = each_input_set.split(',')[1]
                            last_measurement = read_last_influxdb(
                                input_id, input_measure, self.max_measure_age)
                            if not last_measurement:
                                missing_measure = True
                            else:
                                measurements.append(last_measurement[1])

                        if not missing_measure:
                            average = sum(measurements) / float(
                                len(measurements))
                            write_math_db = threading.Thread(
                                target=write_influxdb_value,
                                args=(
                                    self.math_unique_id,
                                    self.measure,
                                    average,
                                ))
                            write_math_db.start()

                        else:
                            self.logger.error(
                                "One or more inputs were not within the "
                                "Max Age that has been set. Ensure all "
                                "Inputs are operating properly.")

                t.sleep(0.1)

            self.running = False
            self.logger.info("Deactivated in {:.1f} ms".format(
                (timeit.default_timer() - self.thread_shutdown_timer) * 1000))
        except Exception as except_msg:
            self.logger.exception("Run Error: {err}".format(err=except_msg))
예제 #4
0
    def write_log(self):
        """
        Append log file with latest measurement if the latest measurement
        timestamp is more recent than the last retrieved timestamp.
        """
        self.logger.debug("Log Controller: {} ({}) {} {} {}".format(
                self.log_id, self.name, self.sensor_id,
                self.measure_type, self.period))
        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']
            else:
                self.logger.warning("[Log {}] No data returned "
                                    "from influxdb".format(self.log_id))
                return 1

            self.dt =  date_parse(self.last_time)
            self.timestamp = calendar.timegm(self.dt.timetuple())
            if self.last_timestamp != self.timestamp:
                self.last_timestamp = self.timestamp
                self.logger.debug("[Log {}] Time: {}, {} Value: "
                                  "{}".format(self.log_id,
                                              self.last_time,
                                              self.timestamp,
                                              self.last_measurement))
                SENSOR_LOG_FILE = os.path.join(
                    LOG_PATH, "{}-{}.log".format(self.sensor_id,
                                                 self.measure_type))
                assure_path_exists(LOG_PATH)
                with open(SENSOR_LOG_FILE, "a") as log_file:
                    log_file.write("{},{}\n".format(self.timestamp, self.last_measurement))

                # Ensure log is owned by user 'mycodo'
                if find_owner(SENSOR_LOG_FILE) != 'mycodo':
                    set_user_grp(SENSOR_LOG_FILE, 'mycodo', 'mycodo')
            else:
                self.logger.debug("[Log {}] No new data from "
                                    "influxdb could be "
                                    "retrieved.".format(self.log_id))
        except Exception as except_msg:
            self.logger.exception("[Log {}] Could not retrieve influxdb"
                                " data: {}".format(self.log_id,
                                                   except_msg))
예제 #5
0
    def get_last_measurement(self):
        """
        Retrieve the latest input measurement from InfluxDB

        :rtype: None
        """
        self.last_measurement_success = False
        # Get latest measurement (from within the past minute) from influxdb
        try:
            if self.input_duration < 60:
                duration = 60
            else:
                duration = int(self.input_duration * 1.5)
            self.last_measurement = read_last_influxdb(self.input_unique_id,
                                                       self.measurement,
                                                       duration)
            if self.last_measurement:
                self.last_time = self.last_measurement[0]
                self.last_measurement = self.last_measurement[1]

                utc_dt = datetime.datetime.strptime(
                    self.last_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("Latest {meas}: {last} @ {ts}".format(
                    meas=self.measurement,
                    last=self.last_measurement,
                    ts=local_timestamp))
                if calendar.timegm(
                        t.gmtime()) - utc_timestamp > self.max_measure_age:
                    self.logger.error(
                        "Last measurement was {last_sec} seconds ago, however"
                        " the maximum measurement age is set to {max_sec}"
                        " seconds.".format(
                            last_sec=calendar.timegm(t.gmtime()) -
                            utc_timestamp,
                            max_sec=self.max_measure_age))
                self.last_measurement_success = True
            else:
                self.logger.warning("No data returned from influxdb")
        except requests.ConnectionError:
            self.logger.error("Failed to read measurement from the "
                              "influxdb database: Could not connect.")
        except Exception as except_msg:
            self.logger.exception(
                "Exception while reading measurement from the influxdb "
                "database: {err}".format(err=except_msg))
예제 #6
0
    def get_last_measurement(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(self.sensor_id, measurement_type,
                                              int(self.period * 1.5)).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
예제 #7
0
    def get_last_measurement(self, measurement_type):
        """
        Retrieve the latest input measurement

        :return: The latest input value or None if no data available
        :rtype: float or None

        :param measurement_type: Environmental condition of a input (e.g.
            temperature, humidity, pressure, etc.)
        :type measurement_type: str
        """
        last_measurement = read_last_influxdb(self.unique_id, measurement_type,
                                              int(self.period * 1.5))

        if last_measurement:
            last_value = last_measurement[1]
            return last_value
        else:
            return None
예제 #8
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:
            if self.sensor_duration < 60:
                duration = 60
            else:
                duration = int(self.sensor_duration*1.5)
            self.last_measurement = read_last_influxdb(
                INFLUXDB_HOST,
                INFLUXDB_PORT,
                INFLUXDB_USER,
                INFLUXDB_PASSWORD,
                INFLUXDB_DATABASE,
                self.sensor_id,
                self.measure_type,
                duration)
            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.datetime.strptime(self.last_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("[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))
예제 #9
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:
            if self.sensor_duration/60 < 1:
                duration = 1
            else:
                duration = self.sensor_duration/60*1.5
            self.last_measurement = read_last_influxdb(
                INFLUXDB_HOST,
                INFLUXDB_PORT,
                INFLUXDB_USER,
                INFLUXDB_PASSWORD,
                INFLUXDB_DATABASE,
                self.sensor_id,
                self.measure_type,
                duration)
            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.datetime.strptime(self.last_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("[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))
예제 #10
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:
            if self.sensor_duration < 60:
                duration = 60
            else:
                duration = int(self.sensor_duration * 1.5)
            self.last_measurement = read_last_influxdb(self.sensor_id,
                                                       self.measure_type,
                                                       duration)
            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.datetime.strptime(
                    self.last_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("Latest {}: {} @ {}".format(
                    self.measure_type, self.last_measurement, local_timestamp))
                self.last_measurement_success = True
            else:
                self.logger.warning("No data returned from influxdb")
        except Exception as except_msg:
            self.logger.exception(
                "Failed to read measurement from the influxdb database: "
                "{err}".format(err=except_msg))
예제 #11
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 (within 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(
                                self.lcd_line[i]['id'], '/.*/')
                        else:
                            last_measurement = read_last_influxdb(
                                self.lcd_line[i]['id'],
                                self.lcd_line[i]['measurement'])
                        if last_measurement:
                            self.lcd_line[i]['time'] = last_measurement[0]
                            self.lcd_line[i][
                                'measurement_value'] = last_measurement[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("Latest {}: {} @ {}".format(
                                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("No data returned from "
                                              "influxdb")
                except Exception as except_msg:
                    self.logger.debug(
                        "Failed to read measurement from the "
                        "influxdb database: {err}".format(err=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':
                            pid = db_retrieve_table_daemon(
                                PID, unique_id=self.lcd_line[i]['id'])
                            measurement = pid.measurement
                        elif self.lcd_line[i]['measurement'] == 'duration_sec':
                            measurement = 'duration_sec'
                            self.lcd_line[i][
                                'measurement_value'] = '{:.2f}'.format(
                                    self.lcd_line[i]['measurement_value'])
                        elif self.lcd_line[i][
                                'measurement'] in MEASUREMENT_UNITS:
                            measurement = self.lcd_line[i]['measurement']

                        # 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(
                                MEASUREMENT_UNITS[measurement]['unit'])
                            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] = u'{name} {value} {unit}'.format(
                                    name=name_cropped,
                                    value=self.lcd_line[i]
                                    ['measurement_value'],
                                    unit=MEASUREMENT_UNITS[measurement]
                                    ['unit'])
                        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] = u'{name} {value}'.format(
                                name=name_cropped,
                                value=self.lcd_line[i]['measurement_value'])
                    else:
                        self.lcd_string_line[i] = 'ERROR: NO DATA'
                except Exception as except_msg:
                    self.logger.exception(
                        "Error: {err}".format(err=except_msg))
            else:
                self.lcd_string_line[i] = ''
예제 #12
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'], '/.*/').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']).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] = ''
예제 #13
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'],
                                '/.*/').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']).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] = ''
예제 #14
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 (within 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(
                                self.lcd_line[i]['id'],
                                '/.*/').raw
                        else:
                            last_measurement = read_last_influxdb(
                                self.lcd_line[i]['id'],
                                self.lcd_line[i]['measurement']).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("Latest {}: {} @ {}".format(
                                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("No data returned from "
                                              "influxdb")
                except Exception as except_msg:
                    self.logger.debug("Failed to read measurement from the "
                                      "influxdb database: {err}".format(
                                        err=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':
                            pid = db_retrieve_table(
                                MYCODO_DB_PATH,
                                PID,
                                device_id=self.lcd_line[i]['id'])
                            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(MEASUREMENT_UNITS[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'],
                                MEASUREMENT_UNITS[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("Error: {err}".format(
                        err=except_msg))
            else:
                self.lcd_string_line[i] = ''