def calculate_math(self): measurement_dict = {} # # Average (multiple channels) # if self.math_type == 'average': math_dev_measurement = self.device_measurements.filter( DeviceMeasurements.channel == 0).first() channel, unit, measurement = return_measurement_info( math_dev_measurement, None) 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() # # Average (single channel) # elif self.math_type == 'average_single': math_dev_measurement = self.device_measurements.filter( DeviceMeasurements.channel == 0).first() math_conversion = db_retrieve_table_daemon( Conversion, unique_id=math_dev_measurement.conversion_id) (math_channel, math_unit, math_measurement) = return_measurement_info( math_dev_measurement, math_conversion) device_id = self.inputs.split(',')[0] measurement_id = self.inputs.split(',')[1] if measurement_id == 'output': output = db_retrieve_table_daemon(Output, unique_id=device_id) measure_channel = output.channel measure_unit = output.unit measure_measurement = output.measurement else: device_measurement = db_retrieve_table_daemon( DeviceMeasurements, unique_id=measurement_id) if device_measurement: measure_conversion = db_retrieve_table_daemon( Conversion, unique_id=device_measurement.conversion_id) else: measure_conversion = None (measure_channel, measure_unit, measure_measurement) = return_measurement_info( device_measurement, measure_conversion) try: return_value = average_past_seconds( device_id, measure_unit, measure_channel, self.max_measure_age, measure=measure_measurement) if math_dev_measurement.conversion_id: return_value = convert_units( math_dev_measurement.conversion_id, return_value) if return_value: measurement_dict = { math_dev_measurement.channel: { 'measurement': measure_measurement, 'unit': math_unit, 'value': return_value } } else: self.error_not_within_max_age() except Exception as msg: self.logger.exception( "average_single Error: {err}".format(err=msg)) # # Sum (multiple channels) # elif self.math_type == 'sum': math_dev_measurement = self.device_measurements.filter( DeviceMeasurements.channel == 0).first() if math_dev_measurement: conversion = db_retrieve_table_daemon( Conversion, unique_id=math_dev_measurement.conversion_id) else: conversion = None channel, unit, measurement = return_measurement_info( math_dev_measurement, conversion) success, measure = self.get_measurements_from_str(self.inputs) if success: sum_value = float(sum(measure)) measurement_dict = { channel: { 'measurement': measurement, 'unit': unit, 'value': sum_value } } elif measure: self.logger.error(measure) else: self.error_not_within_max_age() # # Sum (single channel) # elif self.math_type == 'sum_single': math_dev_measurement = self.device_measurements.filter( DeviceMeasurements.channel == 0).first() math_conversion = db_retrieve_table_daemon( Conversion, unique_id=math_dev_measurement.conversion_id) (math_channel, math_unit, math_measurement) = return_measurement_info( math_dev_measurement, math_conversion) device_id = self.inputs.split(',')[0] measurement_id = self.inputs.split(',')[1] if measurement_id == 'output': output = db_retrieve_table_daemon(Output, unique_id=device_id) measure_channel = output.channel measure_unit = output.unit measure_measurement = output.measurement else: device_measurement = db_retrieve_table_daemon( DeviceMeasurements, unique_id=measurement_id) if device_measurement: measure_conversion = db_retrieve_table_daemon( Conversion, unique_id=device_measurement.conversion_id) else: measure_conversion = None (measure_channel, measure_unit, measure_measurement) = return_measurement_info( device_measurement, measure_conversion) try: return_value = sum_past_seconds( device_id, measure_unit, measure_channel, self.max_measure_age, measure=measure_measurement) if math_dev_measurement.conversion_id: return_value = convert_units( math_dev_measurement.conversion_id, return_value) if return_value: measurement_dict = { math_dev_measurement.channel: { 'measurement': measure_measurement, 'unit': math_unit, 'value': return_value } } else: self.error_not_within_max_age() except Exception as msg: self.logger.exception( "sum_single Error: {err}".format(err=msg)) # # Difference between two channels # elif self.math_type == 'difference': math_dev_measurement = self.device_measurements.filter( DeviceMeasurements.channel == 0).first() if math_dev_measurement: conversion = db_retrieve_table_daemon( Conversion, unique_id=math_dev_measurement.conversion_id) else: conversion = None channel, unit, measurement = return_measurement_info( math_dev_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() # # Equation (math performed on measurement) # elif self.math_type == 'equation': math_dev_measurement = self.device_measurements.filter( DeviceMeasurements.channel == 0).first() if math_dev_measurement: conversion = db_retrieve_table_daemon( Conversion, unique_id=math_dev_measurement.conversion_id) else: conversion = None channel, unit, measurement = return_measurement_info( math_dev_measurement, conversion) success, measure = self.get_measurements_from_str( self.equation_input) if success: if 'x' in self.equation: replaced_str = self.equation.replace('x', str(measure[0])) else: replaced_str = self.equation 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() # # Redundancy (Use next measurement if one isn't currently available) # 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] math_dev_measurement = self.device_measurements.filter( DeviceMeasurements.channel == 0).first() if math_dev_measurement: conversion = db_retrieve_table_daemon( Conversion, unique_id=math_dev_measurement.conversion_id) else: conversion = None channel, unit, measurement = return_measurement_info( math_dev_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_utc': 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() # # Statistical analysis on all measurements from a period of time # 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() # # Verification (only use measurement if it's close to another measurement) # elif self.math_type == 'verification': math_dev_measurement = self.device_measurements.filter( DeviceMeasurements.channel == 0).first() if math_dev_measurement: conversion = db_retrieve_table_daemon( Conversion, unique_id=math_dev_measurement.conversion_id) else: conversion = None channel, unit, measurement = return_measurement_info( math_dev_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() # # Calculate humidity from wet- and dry-bulb temperatures # 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 measurement_press = db_retrieve_table_daemon( DeviceMeasurements, unique_id=self.pressure_pa_measure_id) if not measurement_press: self.logger.error( "Could not find pressure measurement") measurement_press = None critical_error = True if measurement_press and measurement_press.unit != 'Pa': pressure_pa, status = self.is_measurement_unit( measurement_press.unit, 'Pa', pressure_pa) if status == 'error': 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]) measurement_db_temp = db_retrieve_table_daemon( DeviceMeasurements, unique_id=self.dry_bulb_t_measure_id) if not measurement_db_temp: self.logger.error( "Could not find dry bulb temperature measurement") measurement_db_temp = None critical_error = True if measurement_db_temp and measurement_db_temp.unit != 'K': dbt_kelvin, status = self.is_measurement_unit( measurement_db_temp.unit, 'K', dbt_kelvin) if status == 'error': critical_error = True measurement_wb_temp = db_retrieve_table_daemon( DeviceMeasurements, unique_id=self.wet_bulb_t_measure_id) if not measurement_wb_temp: self.logger.error( "Could not find wet bulb temperature measurement") measurement_wb_temp = None critical_error = True if measurement_wb_temp and measurement_wb_temp.unit != 'K': wbt_kelvin, status = self.is_measurement_unit( measurement_wb_temp.unit, 'K', wbt_kelvin) if status == 'error': 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() # # Calculate vapor pressure deficit from temperature and humidity # elif self.math_type == 'vapor_pressure_deficit': vpd_pa = None critical_error = False success_temp, temperature = self.get_measurements_from_id( self.unique_id_1, self.unique_measurement_id_1) success_hum, humidity = self.get_measurements_from_id( self.unique_id_2, self.unique_measurement_id_2) if success_temp and success_hum: vpd_temperature_celsius = float(temperature[1]) vpd_humidity_percent = float(humidity[1]) measurement_temp = db_retrieve_table_daemon( DeviceMeasurements, unique_id=self.unique_measurement_id_1) if not measurement_temp: self.logger.error("Could not find temperature measurement") measurement_temp = None critical_error = True if measurement_temp and measurement_temp.unit != 'C': vpd_temperature_celsius, status = self.is_measurement_unit( measurement_temp.unit, 'C', vpd_temperature_celsius) if status == 'error': critical_error = True measurement_hum = db_retrieve_table_daemon( DeviceMeasurements, unique_id=self.unique_measurement_id_2) if not measurement_hum: self.logger.error("Could not find humidity measurement") measurement_hum = None critical_error = True if measurement_hum and measurement_hum.unit != 'percent': vpd_humidity_percent, status = self.is_measurement_unit( measurement_hum.unit, 'percent', vpd_humidity_percent) if status == 'error': 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: math_dev_measurement = self.device_measurements.first() conversion = db_retrieve_table_daemon( Conversion, unique_id=math_dev_measurement.conversion_id) channel, unit, measurement = return_measurement_info( math_dev_measurement, 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 if measurement_dict: self.logger.debug( "Adding measurements to InfluxDB with ID {}: {}".format( self.unique_id, measurement_dict)) add_measurements_influxdb(self.unique_id, measurement_dict) else: self.logger.debug( "No measurements to add to InfluxDB with ID {}".format( self.unique_id))
def math_humidity(self, measurement_dict): 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 measurement_press = db_retrieve_table_daemon( DeviceMeasurements, unique_id=self.pressure_pa_measure_id) if not measurement_press: self.logger.error("Could not find pressure measurement") measurement_press = None critical_error = True if measurement_press and measurement_press.unit != 'Pa': pressure_pa, status = self.is_measurement_unit( measurement_press.unit, 'Pa', pressure_pa) if status == 'error': 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]) measurement_db_temp = db_retrieve_table_daemon( DeviceMeasurements, unique_id=self.dry_bulb_t_measure_id) if not measurement_db_temp: self.logger.error( "Could not find dry bulb temperature measurement") measurement_db_temp = None critical_error = True if measurement_db_temp and measurement_db_temp.unit != 'K': dbt_kelvin, status = self.is_measurement_unit( measurement_db_temp.unit, 'K', dbt_kelvin) if status == 'error': critical_error = True measurement_wb_temp = db_retrieve_table_daemon( DeviceMeasurements, unique_id=self.wet_bulb_t_measure_id) if not measurement_wb_temp: self.logger.error( "Could not find wet bulb temperature measurement") measurement_wb_temp = None critical_error = True if measurement_wb_temp and measurement_wb_temp.unit != 'K': wbt_kelvin, status = self.is_measurement_unit( measurement_wb_temp.unit, 'K', wbt_kelvin) if status == 'error': 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() return measurement_dict
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()
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)
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 PID is active, retrieve input measurement and update PID output 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 == '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])) psypi = SI.state("DBT", dbt_kelvin, "WBT", wbt_kelvin, pressure_pa) 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))
def run_function(self): temp_wet_k = None temp_dry_k = None pressure_pa = 101325 if (self.select_measurement_pressure_pa_device_id and self.select_measurement_pressure_pa_measurement_id and self.max_measure_age_pressure_pa): device_measurement = get_measurement( self.select_measurement_pressure_pa_measurement_id) conversion = db_retrieve_table_daemon( Conversion, unique_id=device_measurement.conversion_id) channel, unit, measurement = return_measurement_info( device_measurement, conversion) last_measurement_pa = self.get_last_measurement( self.select_measurement_pressure_pa_device_id, self.select_measurement_pressure_pa_measurement_id, max_age=self.max_measure_age_pressure_pa) if last_measurement_pa: pressure_pa = convert_from_x_to_y_unit(unit, 'Pa', last_measurement_pa[1]) last_measurement_wet = self.get_last_measurement( self.select_measurement_temp_wet_c_device_id, self.select_measurement_temp_wet_c_measurement_id, max_age=self.max_measure_age_temp_wet_c) if last_measurement_wet: device_measurement = get_measurement( self.select_measurement_temp_wet_c_measurement_id) conversion = db_retrieve_table_daemon( Conversion, unique_id=device_measurement.conversion_id) channel, unit, measurement = return_measurement_info( device_measurement, conversion) temp_wet_k = convert_from_x_to_y_unit(unit, 'K', last_measurement_wet[1]) last_measurement_dry = self.get_last_measurement( self.select_measurement_temp_dry_c_device_id, self.select_measurement_temp_dry_c_measurement_id, max_age=self.max_measure_age_temp_dry_c) if last_measurement_dry: device_measurement = get_measurement( self.select_measurement_temp_dry_c_measurement_id) conversion = db_retrieve_table_daemon( Conversion, unique_id=device_measurement.conversion_id) channel, unit, measurement = return_measurement_info( device_measurement, conversion) temp_dry_k = convert_from_x_to_y_unit(unit, 'K', last_measurement_dry[1]) if temp_wet_k and temp_dry_k: measurements = copy.deepcopy(measurements_dict) psypi = None try: psypi = SI.state("DBT", temp_dry_k, "WBT", temp_wet_k, pressure_pa) except TypeError as err: self.logger.error("TypeError: {msg}".format(msg=err)) if not psypi: self.logger.error( "Could not calculate humidity from wet/dry bulbs") return 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]) self.logger.debug("Dry Temp: {dtk}, " "Wet Temp: {wtk}, " "Pressure: {pres}," "Humidity: {rh}".format(dtk=temp_dry_k, wtk=temp_wet_k, pres=pressure_pa, rh=humidity)) list_measurement = [ humidity, humidity_ratio, specific_enthalpy, specific_volume ] for each_measurement in self.device_measurements.all(): if each_measurement.is_enabled: conversion = db_retrieve_table_daemon( Conversion, unique_id=each_measurement.conversion_id) channel, unit, measurement = return_measurement_info( each_measurement, conversion) measurements[channel] = { 'measurement': measurement, 'unit': unit, 'value': list_measurement[channel] } # Add measurement(s) to influxdb if measurements: self.logger.debug( "Adding measurements to InfluxDB with ID {}: {}".format( self.unique_id, measurements)) add_measurements_influxdb(self.unique_id, measurements) else: self.logger.debug( "No measurements to add to InfluxDB with ID {}".format( self.unique_id))
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)