Example #1
0
def get_past_measurements(unique_id, unit, measurement, channel, duration_sec):
    """
    Retrieve the past input measurements

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

    :param unique_id: What unique_id tag to query in the Influxdb
        database (eg. '00000001')
    :type unique_id: str
    :param unit: What unit to query in the Influxdb
        database (eg. 'C', 's')
    :type unit: str
    :param measurement: What measurement to query in the Influxdb
        database (eg. 'temperature', 'duration_time')
    :type measurement: str or None
    :param channel: Channel
    :type channel: int or None
    :param duration_sec: How many seconds to look for a past measurement
    :type duration_sec: int or None
    """

    past_measurements = read_past_influxdb(unique_id,
                                           unit,
                                           channel,
                                           duration_sec,
                                           measure=measurement)

    if past_measurements:
        string_ts_values = ''
        for index, each_set in enumerate(past_measurements):
            string_ts_values += '{},{}'.format(each_set[0], each_set[1])
            if index + 1 < len(past_measurements):
                string_ts_values += ';'
        return string_ts_values
Example #2
0
    def calculate_math(self):
        if self.math_type == 'average':
            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                measure_dict = {
                    self.measure:
                    float('{0:.4f}'.format(sum(measure) / float(len(measure))))
                }
                self.measurements = Measurement(measure_dict)
                add_measure_influxdb(self.unique_id, self.measurements)
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'average_single':
            device_id = self.inputs.split(',')[0]
            measurement = self.inputs.split(',')[1]
            try:
                last_measurements = read_past_influxdb(device_id, measurement,
                                                       self.max_measure_age)

                if last_measurements:
                    measure_list = []
                    for each_set in last_measurements:
                        if len(each_set) == 2:
                            measure_list.append(each_set[1])
                    average = sum(measure_list) / float(len(measure_list))

                    measure_dict = {
                        self.measure: float('{0:.4f}'.format(average))
                    }
                    self.measurements = Measurement(measure_dict)
                    add_measure_influxdb(self.unique_id, self.measurements)
                else:
                    self.error_not_within_max_age()
            except Exception as msg:
                self.logger.error(
                    "average_single Error: {err}".format(err=msg))

        elif self.math_type == 'difference':
            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                if self.difference_reverse_order:
                    difference = measure[1] - measure[0]
                else:
                    difference = measure[0] - measure[1]
                if self.difference_absolute:
                    difference = abs(difference)
                measure_dict = {
                    self.measure: float('{0:.4f}'.format(difference))
                }
                self.measurements = Measurement(measure_dict)
                add_measure_influxdb(self.unique_id, self.measurements)
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'equation':
            success, measure = self.get_measurements_from_str(
                self.equation_input)
            if success:
                replaced_str = self.equation.replace('x', str(measure[0]))
                equation_output = eval(replaced_str)
                measure_dict = {
                    self.measure: float('{0:.4f}'.format(equation_output))
                }
                self.measurements = Measurement(measure_dict)
                add_measure_influxdb(self.unique_id, self.measurements)
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'median':
            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                measure_dict = {
                    self.measure: float('{0:.4f}'.format(median(measure)))
                }
                self.measurements = Measurement(measure_dict)
                add_measure_influxdb(self.unique_id, self.measurements)
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'maximum':
            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                measure_dict = {
                    self.measure: float('{0:.4f}'.format(max(measure)))
                }
                self.measurements = Measurement(measure_dict)
                add_measure_influxdb(self.unique_id, self.measurements)
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'minimum':
            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                measure_dict = {
                    self.measure: float('{0:.4f}'.format(min(measure)))
                }
                self.measurements = Measurement(measure_dict)
                add_measure_influxdb(self.unique_id, self.measurements)
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'verification':
            success, measure = self.get_measurements_from_str(self.inputs)
            if (success and max(measure) - min(measure) < self.max_difference):
                measure_dict = {
                    self.measure:
                    float('{0:.4f}'.format(sum(measure) / float(len(measure))))
                }
                self.measurements = Measurement(measure_dict)
                add_measure_influxdb(self.unique_id, self.measurements)
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'humidity':
            measure_temps_good = False
            pressure_pa = 101325

            success_dbt, dry_bulb_t = self.get_measurements_from_id(
                self.dry_bulb_t_id, self.dry_bulb_t_measure)
            success_wbt, wet_bulb_t = self.get_measurements_from_id(
                self.wet_bulb_t_id, self.wet_bulb_t_measure)
            if success_dbt and success_wbt:
                measure_temps_good = True

            if self.pressure_pa_id and self.pressure_pa_measure:
                success_pa, pressure = self.get_measurements_from_id(
                    self.pressure_pa_id, self.pressure_pa_measure)
                if success_pa:
                    pressure_pa = int(pressure[1])

            if measure_temps_good:
                dbt_kelvin = celsius_to_kelvin(float(dry_bulb_t[1]))
                wbt_kelvin = celsius_to_kelvin(float(wet_bulb_t[1]))
                psypi = None

                try:
                    psypi = SI.state("DBT", dbt_kelvin, "WBT", wbt_kelvin,
                                     pressure_pa)
                except TypeError as err:
                    self.logger.error("TypeError: {msg}".format(msg=err))

                if psypi:
                    percent_relative_humidity = psypi[2] * 100

                    # Ensure percent humidity stays within 0 - 100 % range
                    if percent_relative_humidity > 100:
                        percent_relative_humidity = 100
                    elif percent_relative_humidity < 0:
                        percent_relative_humidity = 0

                    # Dry bulb temperature: psypi[0])
                    # Wet bulb temperature: psypi[5])

                    measure_dict = dict(
                        specific_enthalpy=float('{0:.5f}'.format(psypi[1])),
                        humidity=float(
                            '{0:.5f}'.format(percent_relative_humidity)),
                        specific_volume=float('{0:.5f}'.format(psypi[3])),
                        humidity_ratio=float('{0:.5f}'.format(psypi[4])))
                    self.measurements = Measurement(measure_dict)
                    add_measure_influxdb(self.unique_id, self.measurements)
            else:
                self.error_not_within_max_age()
Example #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:
                # Pause loop to modify conditional statements.
                # Prevents execution of conditional while variables are
                # being modified.
                if self.pause_loop:
                    self.verify_pause_loop = True
                    while self.pause_loop:
                        time.sleep(0.1)

                if self.is_activated and time.time() > self.timer:

                    if self.math_type == 'average':
                        success, measure = self.get_measurements_from_str(
                            self.inputs)
                        if success:
                            measure_dict = {
                                self.measure:
                                float('{0:.4f}'.format(
                                    sum(measure) / float(len(measure))))
                            }
                            self.measurements = Measurement(measure_dict)
                            add_measure_influxdb(self.unique_id,
                                                 self.measurements)
                        elif measure:
                            self.logger.error(measure)
                        else:
                            self.error_not_within_max_age()

                    elif self.math_type == 'average_single':
                        device_id = self.inputs.split(',')[0]
                        measurement = self.inputs.split(',')[1]
                        try:
                            last_measurements = read_past_influxdb(
                                device_id, measurement, self.max_measure_age)

                            if last_measurements:
                                measure_list = []
                                for each_set in last_measurements:
                                    if len(each_set) == 2:
                                        measure_list.append(each_set[1])
                                average = sum(measure_list) / float(
                                    len(measure_list))

                                if self.measure in MEASUREMENT_INTEGERS:
                                    measure_dict = {self.measure: int(average)}
                                else:
                                    measure_dict = {
                                        self.measure:
                                        float('{0:.4f}'.format(average))
                                    }
                                self.measurements = Measurement(measure_dict)
                                add_measure_influxdb(self.unique_id,
                                                     self.measurements)
                            else:
                                self.error_not_within_max_age()
                        except Exception as msg:
                            self.logger.error(
                                "average_single Error: {err}".format(err=msg))

                    elif self.math_type == 'difference':
                        success, measure = self.get_measurements_from_str(
                            self.inputs)
                        if success:
                            if self.difference_reverse_order:
                                difference = measure[1] - measure[0]
                            else:
                                difference = measure[0] - measure[1]
                            if self.difference_absolute:
                                difference = abs(difference)
                            measure_dict = {
                                self.measure:
                                float('{0:.4f}'.format(difference))
                            }
                            self.measurements = Measurement(measure_dict)
                            add_measure_influxdb(self.unique_id,
                                                 self.measurements)
                        elif measure:
                            self.logger.error(measure)
                        else:
                            self.error_not_within_max_age()

                    elif self.math_type == 'equation':
                        success, measure = self.get_measurements_from_str(
                            self.equation_input)
                        if success:
                            replaced_str = self.equation.replace(
                                'x', str(measure[0]))
                            equation_output = eval(replaced_str)
                            measure_dict = {
                                self.measure:
                                float('{0:.4f}'.format(equation_output))
                            }
                            self.measurements = Measurement(measure_dict)
                            add_measure_influxdb(self.unique_id,
                                                 self.measurements)
                        elif measure:
                            self.logger.error(measure)
                        else:
                            self.error_not_within_max_age()

                    elif self.math_type == 'median':
                        success, measure = self.get_measurements_from_str(
                            self.inputs)
                        if success:
                            measure_dict = {
                                self.measure:
                                float('{0:.4f}'.format(median(measure)))
                            }
                            self.measurements = Measurement(measure_dict)
                            add_measure_influxdb(self.unique_id,
                                                 self.measurements)
                        elif measure:
                            self.logger.error(measure)
                        else:
                            self.error_not_within_max_age()

                    elif self.math_type == 'maximum':
                        success, measure = self.get_measurements_from_str(
                            self.inputs)
                        if success:
                            measure_dict = {
                                self.measure:
                                float('{0:.4f}'.format(max(measure)))
                            }
                            self.measurements = Measurement(measure_dict)
                            add_measure_influxdb(self.unique_id,
                                                 self.measurements)
                        elif measure:
                            self.logger.error(measure)
                        else:
                            self.error_not_within_max_age()

                    elif self.math_type == 'minimum':
                        success, measure = self.get_measurements_from_str(
                            self.inputs)
                        if success:
                            measure_dict = {
                                self.measure:
                                float('{0:.4f}'.format(min(measure)))
                            }
                            self.measurements = Measurement(measure_dict)
                            add_measure_influxdb(self.unique_id,
                                                 self.measurements)
                        elif measure:
                            self.logger.error(measure)
                        else:
                            self.error_not_within_max_age()

                    elif self.math_type == 'verification':
                        success, measure = self.get_measurements_from_str(
                            self.inputs)
                        if (success and max(measure) - min(measure) <
                                self.max_difference):
                            measure_dict = {
                                self.measure:
                                float('{0:.4f}'.format(
                                    sum(measure) / float(len(measure))))
                            }
                            self.measurements = Measurement(measure_dict)
                            add_measure_influxdb(self.unique_id,
                                                 self.measurements)
                        elif measure:
                            self.logger.error(measure)
                        else:
                            self.error_not_within_max_age()

                    elif self.math_type == 'humidity':
                        measure_temps_good = False
                        measure_press_good = False
                        pressure_pa = 101325

                        success_dbt, dry_bulb_t = self.get_measurements_from_id(
                            self.dry_bulb_t_id, self.dry_bulb_t_measure)
                        success_wbt, wet_bulb_t = self.get_measurements_from_id(
                            self.wet_bulb_t_id, self.wet_bulb_t_measure)
                        if success_dbt and success_wbt:
                            measure_temps_good = True

                        if self.pressure_pa_id and self.pressure_pa_measure:
                            success_pa, pressure = self.get_measurements_from_id(
                                self.pressure_pa_id, self.pressure_pa_measure)
                            if success_pa:
                                pressure_pa = int(pressure[1])
                                measure_press_good = True

                        if (measure_temps_good and
                            ((self.pressure_pa_id and self.pressure_pa_measure
                              and measure_press_good) or
                             (not self.pressure_pa_id
                              or not self.pressure_pa_measure))):

                            dbt_kelvin = celsius_to_kelvin(float(
                                dry_bulb_t[1]))
                            wbt_kelvin = celsius_to_kelvin(float(
                                wet_bulb_t[1]))

                            try:
                                psypi = SI.state("DBT", dbt_kelvin, "WBT",
                                                 wbt_kelvin, pressure_pa)
                            except TypeError as err:
                                self.logger.error(
                                    "TypeError: {msg}".format(msg=err))

                            percent_relative_humidity = psypi[2] * 100

                            # Ensure percent humidity stays within 0 - 100 % range
                            if percent_relative_humidity > 100:
                                percent_relative_humidity = 100
                            elif percent_relative_humidity < 0:
                                percent_relative_humidity = 0

                            # Dry bulb temperature: psypi[0])
                            # Wet bulb temperature: psypi[5])

                            measure_dict = dict(
                                specific_enthalpy=float('{0:.5f}'.format(
                                    psypi[1])),
                                humidity=float('{0:.5f}'.format(
                                    percent_relative_humidity)),
                                specific_volume=float('{0:.5f}'.format(
                                    psypi[3])),
                                humidity_ratio=float('{0:.5f}'.format(
                                    psypi[4])))
                            self.measurements = Measurement(measure_dict)
                            add_measure_influxdb(self.unique_id,
                                                 self.measurements)
                        else:
                            self.error_not_within_max_age()

                    # Ensure the next timer ends in the future
                    while time.time() > self.timer:
                        self.timer += self.period

                time.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))
Example #4
0
    def calculate_math(self):
        measurement_dict = {}

        if self.math_type == 'average':

            device_measurement = self.device_measurements.filter(
                DeviceMeasurements.channel == 0).first()

            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                average = float(sum(measure) / float(len(measure)))

                measurement_dict = {
                    channel: {
                        'measurement': measurement,
                        'unit': unit,
                        'value': average
                    }
                }
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'average_single':

            device_id = self.inputs.split(',')[0]
            measurement_id = self.inputs.split(',')[1]

            device_measurement = db_retrieve_table_daemon(
                DeviceMeasurements, unique_id=measurement_id)
            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            try:
                last_measurements = read_past_influxdb(device_id, unit,
                                                       measurement, channel,
                                                       self.max_measure_age)

                if last_measurements:
                    measure_list = []
                    for each_set in last_measurements:
                        if len(each_set) == 2:
                            measure_list.append(each_set[1])
                    average = sum(measure_list) / float(len(measure_list))

                    measurement_dict = {
                        channel: {
                            'measurement': measurement,
                            'unit': unit,
                            'value': average
                        }
                    }
                else:
                    self.error_not_within_max_age()
            except Exception as msg:
                self.logger.exception(
                    "average_single Error: {err}".format(err=msg))

        elif self.math_type == 'difference':

            device_measurement = self.device_measurements.filter(
                DeviceMeasurements.channel == 0).first()
            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                if self.difference_reverse_order:
                    difference = measure[1] - measure[0]
                else:
                    difference = measure[0] - measure[1]
                if self.difference_absolute:
                    difference = abs(difference)

                measurement_dict = {
                    channel: {
                        'measurement': measurement,
                        'unit': unit,
                        'value': difference
                    }
                }
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'equation':

            device_measurement = self.device_measurements.filter(
                DeviceMeasurements.channel == 0).first()
            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                replaced_str = self.equation.replace('x', str(measure[0]))
                equation_output = eval(replaced_str)

                measurement_dict = {
                    channel: {
                        'measurement': measurement,
                        'unit': unit,
                        'value': float(equation_output)
                    }
                }
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'redundancy':
            list_order = self.order_of_use.split(';')
            measurement_success = False

            for each_id_measurement_id in list_order:
                device_id = each_id_measurement_id.split(',')[0]
                measurement_id = each_id_measurement_id.split(',')[1]

                device_measurement = self.device_measurements.filter(
                    DeviceMeasurements.channel == 0).first()
                if device_measurement:
                    conversion = db_retrieve_table_daemon(
                        Conversion, unique_id=device_measurement.conversion_id)
                else:
                    conversion = None
                channel, unit, measurement = return_measurement_info(
                    device_measurement, conversion)

                try:
                    success_measure, measure = self.get_measurements_from_id(
                        device_id, measurement_id)

                    if success_measure:
                        measurement_dict = {
                            channel: {
                                'measurement': measurement,
                                'unit': unit,
                                'value': float(measure[1]),
                                'timestamp': measure[0],
                            }
                        }
                        measurement_success = True
                        break

                except Exception as msg:
                    self.logger.exception(
                        "redundancy Error: {err}".format(err=msg))

            if not measurement_success:
                self.error_not_within_max_age()

        elif self.math_type == 'statistics':

            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                # Perform some math
                stat_mean = float(sum(measure) / float(len(measure)))
                stat_median = median(measure)
                stat_minimum = min(measure)
                stat_maximum = max(measure)
                stdev_ = stdev(measure)
                stdev_mean_upper = stat_mean + stdev_
                stdev_mean_lower = stat_mean - stdev_

                list_measurement = [
                    stat_mean, stat_median, stat_minimum, stat_maximum, stdev_,
                    stdev_mean_upper, stdev_mean_lower
                ]

                for each_measurement in self.device_measurements.all():
                    conversion = db_retrieve_table_daemon(
                        Conversion, unique_id=each_measurement.conversion_id)
                    channel, unit, measurement = return_measurement_info(
                        each_measurement, conversion)

                    measurement_dict[channel] = {
                        'measurement': measurement,
                        'unit': unit,
                        'value': list_measurement[channel]
                    }

            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'verification':

            device_measurement = self.device_measurements.filter(
                DeviceMeasurements.channel == 0).first()
            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            success, measure = self.get_measurements_from_str(self.inputs)
            if (success and max(measure) - min(measure) < self.max_difference):
                difference = max(measure) - min(measure)

                measurement_dict = {
                    channel: {
                        'measurement': measurement,
                        'unit': unit,
                        'value': difference
                    }
                }
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'humidity':

            pressure_pa = 101325
            critical_error = False

            if self.pressure_pa_id and self.pressure_pa_measure_id:
                success_pa, pressure = self.get_measurements_from_id(
                    self.pressure_pa_id, self.pressure_pa_measure_id)
                if success_pa:
                    pressure_pa = int(pressure[1])
                    # Pressure must be in Pa, convert if not

                    if db_retrieve_table_daemon(
                            DeviceMeasurements,
                            unique_id=self.pressure_pa_measure_id):
                        measurement = db_retrieve_table_daemon(
                            DeviceMeasurements,
                            unique_id=self.pressure_pa_measure_id)
                    else:
                        self.logger.error(
                            "Could not find pressure measurement")
                        measurement = None
                        critical_error = True

                    if measurement and measurement.unit != 'Pa':
                        for each_conv in db_retrieve_table_daemon(Conversion,
                                                                  entry='all'):
                            if (each_conv.convert_unit_from == measurement.unit
                                    and each_conv.convert_unit_to == 'Pa'):
                                pressure_pa = convert_units(
                                    each_conv.unique_id, pressure_pa)
                            else:
                                self.logger.error(
                                    "Could not find conversion for unit "
                                    "{unit} to Pa (Pascals)".format(
                                        unit=measurement.unit))
                                critical_error = True

            success_dbt, dry_bulb_t = self.get_measurements_from_id(
                self.dry_bulb_t_id, self.dry_bulb_t_measure_id)
            success_wbt, wet_bulb_t = self.get_measurements_from_id(
                self.wet_bulb_t_id, self.wet_bulb_t_measure_id)

            if success_dbt and success_wbt:
                dbt_kelvin = float(dry_bulb_t[1])
                wbt_kelvin = float(wet_bulb_t[1])

                if db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.dry_bulb_t_measure_id):
                    measurement = db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.dry_bulb_t_measure_id)
                else:
                    self.logger.error("Could not find pressure measurement")
                    measurement = None
                    critical_error = True

                if measurement and measurement.unit != 'K':
                    conversion_found = False
                    for each_conv in db_retrieve_table_daemon(Conversion,
                                                              entry='all'):
                        if (each_conv.convert_unit_from == measurement.unit
                                and each_conv.convert_unit_to == 'K'):
                            dbt_kelvin = convert_units(each_conv.unique_id,
                                                       dbt_kelvin)
                            conversion_found = True
                    if not conversion_found:
                        self.logger.error("Could not find conversion for unit "
                                          "{unit} to K (Kelvin)".format(
                                              unit=measurement.unit))
                        critical_error = True

                if db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.dry_bulb_t_measure_id):
                    measurement = db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.dry_bulb_t_measure_id)
                else:
                    self.logger.error("Could not find pressure measurement")
                    measurement = None
                    critical_error = True

                if measurement and measurement.unit != 'K':
                    conversion_found = False
                    for each_conv in db_retrieve_table_daemon(Conversion,
                                                              entry='all'):
                        if (each_conv.convert_unit_from == measurement.unit
                                and each_conv.convert_unit_to == 'K'):
                            wbt_kelvin = convert_units(each_conv.unique_id,
                                                       wbt_kelvin)
                            conversion_found = True
                    if not conversion_found:
                        self.logger.error("Could not find conversion for unit "
                                          "{unit} to K (Kelvin)".format(
                                              unit=measurement.unit))
                        critical_error = True

                # Convert temperatures to Kelvin (already done above)
                # dbt_kelvin = celsius_to_kelvin(dry_bulb_t_c)
                # wbt_kelvin = celsius_to_kelvin(wet_bulb_t_c)
                psypi = None

                try:
                    if not critical_error:
                        psypi = SI.state("DBT", dbt_kelvin, "WBT", wbt_kelvin,
                                         pressure_pa)
                    else:
                        self.logger.error(
                            "One or more critical errors prevented the "
                            "humidity from being calculated")
                except TypeError as err:
                    self.logger.error("TypeError: {msg}".format(msg=err))

                if psypi:
                    percent_relative_humidity = psypi[2] * 100

                    # Ensure percent humidity stays within 0 - 100 % range
                    if percent_relative_humidity > 100:
                        percent_relative_humidity = 100
                    elif percent_relative_humidity < 0:
                        percent_relative_humidity = 0

                    # Dry bulb temperature: psypi[0])
                    # Wet bulb temperature: psypi[5])

                    specific_enthalpy = float(psypi[1])
                    humidity = float(percent_relative_humidity)
                    specific_volume = float(psypi[3])
                    humidity_ratio = float(psypi[4])

                    list_measurement = [
                        specific_enthalpy, humidity, specific_volume,
                        humidity_ratio
                    ]

                    for each_measurement in self.device_measurements.all():
                        conversion = db_retrieve_table_daemon(
                            Conversion,
                            unique_id=each_measurement.conversion_id)
                        channel, unit, measurement = return_measurement_info(
                            each_measurement, conversion)

                        measurement_dict[channel] = {
                            'measurement': measurement,
                            'unit': unit,
                            'value': list_measurement[channel]
                        }
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'vapor_pressure_deficit':

            vpd_pa = None
            critical_error = False

            success_dbt, temperature = self.get_measurements_from_id(
                self.unique_id_1, self.unique_measurement_id_1)
            success_wbt, humidity = self.get_measurements_from_id(
                self.unique_id_2, self.unique_measurement_id_2)

            if success_dbt and success_wbt:
                vpd_temperature_celsius = float(temperature[1])
                vpd_humidity_percent = float(humidity[1])

                if db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.unique_measurement_id_1):
                    measurement = db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.unique_measurement_id_1)
                else:
                    self.logger.error("Could not find temperature measurement")
                    measurement = None
                    critical_error = True

                if measurement and measurement.unit != 'C':
                    conversion_found = False
                    for each_conv in db_retrieve_table_daemon(Conversion,
                                                              entry='all'):
                        if (each_conv.convert_unit_from == measurement.unit
                                and each_conv.convert_unit_to == 'C'):
                            vpd_temperature_celsius = convert_units(
                                each_conv.unique_id, vpd_temperature_celsius)
                            conversion_found = True
                    if not conversion_found:
                        self.logger.error("Could not find conversion for unit "
                                          "{unit} to C (Celsius)".format(
                                              unit=measurement.unit))
                        critical_error = True

                if db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.unique_measurement_id_2):
                    measurement = db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.unique_measurement_id_2)
                else:
                    self.logger.error("Could not find humidity measurement")
                    measurement = None
                    critical_error = True

                if measurement and measurement.unit != 'percent':
                    conversion_found = False
                    for each_conv in db_retrieve_table_daemon(Conversion,
                                                              entry='all'):
                        if (each_conv.convert_unit_from == measurement.unit
                                and each_conv.convert_unit_to == 'percent'):
                            vpd_humidity_percent = convert_units(
                                each_conv.unique_id, vpd_humidity_percent)
                            conversion_found = True
                    if not conversion_found:
                        self.logger.error("Could not find conversion for unit "
                                          "{unit} to percent (%)".format(
                                              unit=measurement.unit))
                        critical_error = True

                try:
                    if not critical_error:
                        vpd_pa = calculate_vapor_pressure_deficit(
                            vpd_temperature_celsius, vpd_humidity_percent)
                    else:
                        self.logger.error(
                            "One or more critical errors prevented the "
                            "vapor pressure deficit from being calculated")
                except TypeError as err:
                    self.logger.error("TypeError: {msg}".format(msg=err))

                if vpd_pa:
                    measure = self.device_measurements.first()
                    conversion = db_retrieve_table_daemon(
                        Conversion, unique_id=measure.conversion_id)
                    channel, unit, measurement = return_measurement_info(
                        measure, conversion)

                    measurement_dict[channel] = {
                        'measurement': measurement,
                        'unit': unit,
                        'value': vpd_pa
                    }
            else:
                self.error_not_within_max_age()

        else:
            self.logger.error(
                "Unknown math type: {type}".format(type=self.math_type))

        # Finally, add measurements to influxdb
        add_measurements_influxdb(self.unique_id, measurement_dict)
Example #5
0
    def calculate_math(self):
        measurement_dict = {}

        if self.math_type == 'average':

            device_measurement = self.device_measurements.filter(
                DeviceMeasurements.channel == 0).first()

            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                average = float(sum(measure) / float(len(measure)))

                measurement_dict = {
                    channel: {
                        'measurement': measurement,
                        'unit': unit,
                        'value': average
                    }
                }
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'average_single':

            device_id = self.inputs.split(',')[0]
            measurement_id = self.inputs.split(',')[1]

            device_measurement = db_retrieve_table_daemon(
                DeviceMeasurements, unique_id=measurement_id)
            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            try:
                last_measurements = read_past_influxdb(
                    device_id,
                    unit,
                    measurement,
                    channel,
                    self.max_measure_age)

                if last_measurements:
                    measure_list = []
                    for each_set in last_measurements:
                        if len(each_set) == 2:
                            measure_list.append(each_set[1])
                    average = sum(measure_list) / float(len(measure_list))

                    measurement_dict = {
                        channel: {
                            'measurement': measurement,
                            'unit': unit,
                            'value': average
                        }
                    }
                else:
                    self.error_not_within_max_age()
            except Exception as msg:
                self.logger.exception("average_single Error: {err}".format(err=msg))

        elif self.math_type == 'difference':

            device_measurement = self.device_measurements.filter(
                DeviceMeasurements.channel == 0).first()
            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                if self.difference_reverse_order:
                    difference = measure[1] - measure[0]
                else:
                    difference = measure[0] - measure[1]
                if self.difference_absolute:
                    difference = abs(difference)

                measurement_dict = {
                    channel: {
                        'measurement': measurement,
                        'unit': unit,
                        'value': difference
                    }
                }
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'equation':

            device_measurement = self.device_measurements.filter(
                DeviceMeasurements.channel == 0).first()
            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                replaced_str = self.equation.replace('x', str(measure[0]))
                equation_output = eval(replaced_str)

                measurement_dict = {
                    channel: {
                        'measurement': measurement,
                        'unit': unit,
                        'value': float(equation_output)
                    }
                }
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'redundancy':
            list_order = self.order_of_use.split(';')
            measurement_success = False

            for each_id_measurement_id in list_order:
                device_id = each_id_measurement_id.split(',')[0]
                measurement_id = each_id_measurement_id.split(',')[1]

                device_measurement = self.device_measurements.filter(
                    DeviceMeasurements.channel == 0).first()
                if device_measurement:
                    conversion = db_retrieve_table_daemon(
                        Conversion, unique_id=device_measurement.conversion_id)
                else:
                    conversion = None
                channel, unit, measurement = return_measurement_info(
                    device_measurement, conversion)

                try:
                    success_measure, measure = self.get_measurements_from_id(
                        device_id, measurement_id)

                    if success_measure:
                        measurement_dict = {
                            channel: {
                                'measurement': measurement,
                                'unit': unit,
                                'value': float(measure[1]),
                                'timestamp': measure[0],
                            }
                        }
                        measurement_success = True
                        break

                except Exception as msg:
                    self.logger.exception("redundancy Error: {err}".format(err=msg))

            if not measurement_success:
                self.error_not_within_max_age()

        elif self.math_type == 'statistics':

            success, measure = self.get_measurements_from_str(self.inputs)
            if success:
                # Perform some math
                stat_mean = float(sum(measure) / float(len(measure)))
                stat_median = median(measure)
                stat_minimum = min(measure)
                stat_maximum = max(measure)
                stdev_ = stdev(measure)
                stdev_mean_upper = stat_mean + stdev_
                stdev_mean_lower = stat_mean - stdev_

                list_measurement = [
                    stat_mean,
                    stat_median,
                    stat_minimum,
                    stat_maximum,
                    stdev_,
                    stdev_mean_upper,
                    stdev_mean_lower
                ]

                for each_measurement in self.device_measurements.all():
                    conversion = db_retrieve_table_daemon(
                        Conversion, unique_id=each_measurement.conversion_id)
                    channel, unit, measurement = return_measurement_info(
                        each_measurement, conversion)

                    measurement_dict[channel] = {
                            'measurement': measurement,
                            'unit': unit,
                            'value': list_measurement[channel]
                    }

            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'verification':

            device_measurement = self.device_measurements.filter(
                DeviceMeasurements.channel == 0).first()
            if device_measurement:
                conversion = db_retrieve_table_daemon(
                    Conversion, unique_id=device_measurement.conversion_id)
            else:
                conversion = None
            channel, unit, measurement = return_measurement_info(
                device_measurement, conversion)

            success, measure = self.get_measurements_from_str(self.inputs)
            if (success and
                    max(measure) - min(measure) <
                    self.max_difference):
                difference = max(measure) - min(measure)

                measurement_dict = {
                    channel: {
                        'measurement': measurement,
                        'unit': unit,
                        'value': difference
                    }
                }
            elif measure:
                self.logger.error(measure)
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'humidity':

            pressure_pa = 101325
            critical_error = False

            if self.pressure_pa_id and self.pressure_pa_measure_id:
                success_pa, pressure = self.get_measurements_from_id(
                    self.pressure_pa_id, self.pressure_pa_measure_id)
                if success_pa:
                    pressure_pa = int(pressure[1])
                    # Pressure must be in Pa, convert if not

                    if db_retrieve_table_daemon(DeviceMeasurements, unique_id=self.pressure_pa_measure_id):
                        measurement = db_retrieve_table_daemon(DeviceMeasurements, unique_id=self.pressure_pa_measure_id)
                    else:
                        self.logger.error("Could not find pressure measurement")
                        measurement = None
                        critical_error = True

                    if measurement and measurement.unit != 'Pa':
                        for each_conv in db_retrieve_table_daemon(Conversion, entry='all'):
                            if (each_conv.convert_unit_from == measurement.unit and
                                    each_conv.convert_unit_to == 'Pa'):
                                pressure_pa = convert_units(
                                    each_conv.unique_id, pressure_pa)
                            else:
                                self.logger.error(
                                    "Could not find conversion for unit "
                                    "{unit} to Pa (Pascals)".format(
                                        unit=measurement.unit))
                                critical_error = True

            success_dbt, dry_bulb_t = self.get_measurements_from_id(
                self.dry_bulb_t_id, self.dry_bulb_t_measure_id)
            success_wbt, wet_bulb_t = self.get_measurements_from_id(
                self.wet_bulb_t_id, self.wet_bulb_t_measure_id)

            if success_dbt and success_wbt:
                dbt_kelvin = float(dry_bulb_t[1])
                wbt_kelvin = float(wet_bulb_t[1])

                if db_retrieve_table_daemon(DeviceMeasurements, unique_id=self.dry_bulb_t_measure_id):
                    measurement = db_retrieve_table_daemon(DeviceMeasurements, unique_id=self.dry_bulb_t_measure_id)
                else:
                    self.logger.error("Could not find pressure measurement")
                    measurement = None
                    critical_error = True

                if measurement and measurement.unit != 'K':
                    conversion_found = False
                    for each_conv in db_retrieve_table_daemon(Conversion, entry='all'):
                        if (each_conv.convert_unit_from == measurement.unit and
                                each_conv.convert_unit_to == 'K'):
                            dbt_kelvin = convert_units(
                                each_conv.unique_id, dbt_kelvin)
                            conversion_found = True
                    if not conversion_found:
                        self.logger.error(
                            "Could not find conversion for unit "
                            "{unit} to K (Kelvin)".format(
                                unit=measurement.unit))
                        critical_error = True

                if db_retrieve_table_daemon(DeviceMeasurements, unique_id=self.dry_bulb_t_measure_id):
                    measurement = db_retrieve_table_daemon(DeviceMeasurements, unique_id=self.dry_bulb_t_measure_id)
                else:
                    self.logger.error("Could not find pressure measurement")
                    measurement = None
                    critical_error = True

                if measurement and measurement.unit != 'K':
                    conversion_found = False
                    for each_conv in db_retrieve_table_daemon(Conversion, entry='all'):
                        if (each_conv.convert_unit_from == measurement.unit and
                                each_conv.convert_unit_to == 'K'):
                            wbt_kelvin = convert_units(
                                each_conv.unique_id, wbt_kelvin)
                            conversion_found = True
                    if not conversion_found:
                        self.logger.error(
                            "Could not find conversion for unit "
                            "{unit} to K (Kelvin)".format(
                                unit=measurement.unit))
                        critical_error = True

                # Convert temperatures to Kelvin (already done above)
                # dbt_kelvin = celsius_to_kelvin(dry_bulb_t_c)
                # wbt_kelvin = celsius_to_kelvin(wet_bulb_t_c)
                psypi = None

                try:
                    if not critical_error:
                        psypi = SI.state(
                            "DBT", dbt_kelvin, "WBT", wbt_kelvin, pressure_pa)
                    else:
                        self.logger.error(
                            "One or more critical errors prevented the "
                            "humidity from being calculated")
                except TypeError as err:
                    self.logger.error("TypeError: {msg}".format(msg=err))

                if psypi:
                    percent_relative_humidity = psypi[2] * 100

                    # Ensure percent humidity stays within 0 - 100 % range
                    if percent_relative_humidity > 100:
                        percent_relative_humidity = 100
                    elif percent_relative_humidity < 0:
                        percent_relative_humidity = 0

                    # Dry bulb temperature: psypi[0])
                    # Wet bulb temperature: psypi[5])

                    specific_enthalpy = float(psypi[1])
                    humidity = float(percent_relative_humidity)
                    specific_volume = float(psypi[3])
                    humidity_ratio = float(psypi[4])

                    list_measurement = [
                        specific_enthalpy,
                        humidity,
                        specific_volume,
                        humidity_ratio
                    ]

                    for each_measurement in self.device_measurements.all():
                        conversion = db_retrieve_table_daemon(
                            Conversion, unique_id=each_measurement.conversion_id)
                        channel, unit, measurement = return_measurement_info(
                            each_measurement, conversion)

                        measurement_dict[channel] = {
                            'measurement': measurement,
                            'unit': unit,
                            'value': list_measurement[channel]
                        }
            else:
                self.error_not_within_max_age()

        elif self.math_type == 'vapor_pressure_deficit':

            vpd_pa = None
            critical_error = False

            success_dbt, temperature = self.get_measurements_from_id(
                self.unique_id_1, self.unique_measurement_id_1)
            success_wbt, humidity = self.get_measurements_from_id(
                self.unique_id_2, self.unique_measurement_id_2)

            if success_dbt and success_wbt:
                vpd_temperature_celsius = float(temperature[1])
                vpd_humidity_percent = float(humidity[1])

                if db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.unique_measurement_id_1):
                    measurement = db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.unique_measurement_id_1)
                else:
                    self.logger.error("Could not find temperature measurement")
                    measurement = None
                    critical_error = True

                if measurement and measurement.unit != 'C':
                    conversion_found = False
                    for each_conv in db_retrieve_table_daemon(Conversion, entry='all'):
                        if (each_conv.convert_unit_from == measurement.unit and
                                each_conv.convert_unit_to == 'C'):
                            vpd_temperature_celsius = convert_units(
                                each_conv.unique_id, vpd_temperature_celsius)
                            conversion_found = True
                    if not conversion_found:
                        self.logger.error(
                            "Could not find conversion for unit "
                            "{unit} to C (Celsius)".format(
                                unit=measurement.unit))
                        critical_error = True

                if db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.unique_measurement_id_2):
                    measurement = db_retrieve_table_daemon(
                        DeviceMeasurements,
                        unique_id=self.unique_measurement_id_2)
                else:
                    self.logger.error("Could not find humidity measurement")
                    measurement = None
                    critical_error = True

                if measurement and measurement.unit != 'percent':
                    conversion_found = False
                    for each_conv in db_retrieve_table_daemon(Conversion, entry='all'):
                        if (each_conv.convert_unit_from == measurement.unit and
                                each_conv.convert_unit_to == 'percent'):
                            vpd_humidity_percent = convert_units(
                                each_conv.unique_id, vpd_humidity_percent)
                            conversion_found = True
                    if not conversion_found:
                        self.logger.error(
                            "Could not find conversion for unit "
                            "{unit} to percent (%)".format(
                                unit=measurement.unit))
                        critical_error = True

                try:
                    if not critical_error:
                        vpd_pa = calculate_vapor_pressure_deficit(
                            vpd_temperature_celsius, vpd_humidity_percent)
                    else:
                        self.logger.error(
                            "One or more critical errors prevented the "
                            "vapor pressure deficit from being calculated")
                except TypeError as err:
                    self.logger.error("TypeError: {msg}".format(msg=err))

                if vpd_pa:
                    measure = self.device_measurements.first()
                    conversion = db_retrieve_table_daemon(
                        Conversion, unique_id=measure.conversion_id)
                    channel, unit, measurement = return_measurement_info(
                        measure, conversion)

                    measurement_dict[channel] = {
                        'measurement': measurement,
                        'unit': unit,
                        'value': vpd_pa
                    }
            else:
                self.error_not_within_max_age()

        else:
            self.logger.error("Unknown math type: {type}".format(type=self.math_type))

        # Finally, add measurements to influxdb
        add_measurements_influxdb(self.unique_id, measurement_dict)