def get_measurement(self): """ Gets the sensor's Electrical Conductivity measurement via UART/I2C """ self._electrical_conductivity = None electrical_conductivity = None # Read sensor via UART if self.interface == 'UART': if self.atlas_sensor_uart.setup: lines = self.atlas_sensor_uart.query('R') if lines: self.logger.debug("All Lines: {lines}".format(lines=lines)) # 'check probe' indicates an error reading the sensor if 'check probe' in lines: self.logger.error('"check probe" returned from sensor') # if a string resembling a float value is returned, this # is out measurement value elif str_is_float(lines[0]): electrical_conductivity = float(lines[0]) self.logger.debug('Value[0] is float: {val}'.format( val=electrical_conductivity)) else: # During calibration, the sensor is put into # continuous mode, which causes a return of several # values in one string. If the return value does # not represent a float value, it is likely to be a # string of several values. This parses and returns # the first value. if str_is_float(lines[0].split(b'\r')[0]): electrical_conductivity = lines[0].split(b'\r')[0] # Lastly, this is called if the return value cannot # be determined. Watchthe output in the GUI to see # what it is. else: electrical_conductivity = lines[0] self.logger.error( 'Value[0] is not float or "check probe": ' '{val}'.format(val=electrical_conductivity)) else: self.logger.error('UART device is not set up.' 'Check the log for errors.') # Read sensor via I2C elif self.interface == 'I2C': if self.atlas_sensor_i2c.setup: ec_status, ec_str = self.atlas_sensor_i2c.query('R') if ec_status == 'error': self.logger.error( "Sensor read unsuccessful: {err}".format(err=ec_str)) elif ec_status == 'success': electrical_conductivity = float(ec_str) else: self.logger.error( 'I2C device is not set up. Check the log for errors.') electrical_conductivity = convert_units('electrical_conductivity', 'μS_cm', self.convert_to_unit, electrical_conductivity) return electrical_conductivity
def get_measurement(self): """ Gets the Atlas PT1000's temperature in Celsius """ temp = None self.return_dict = measurements_dict.copy() if self.interface == 'FTDI': if self.atlas_sensor_ftdi.setup: lines = self.atlas_sensor_ftdi.query('R') self.logger.debug("All Lines: {lines}".format(lines=lines)) if 'check probe' in lines: self.logger.error('"check probe" returned from sensor') elif isinstance(lines, list): if str_is_float(lines[0]): temp = float(lines[0]) self.logger.debug( 'Value[0] is float: {val}'.format(val=temp)) elif str_is_float(lines): temp = float(lines) self.logger.debug('Value is float: {val}'.format(val=temp)) else: self.logger.error('Unknown value: {val}'.format(val=lines)) else: self.logger.error('FTDI device is not set up. ' 'Check the log for errors.') elif self.interface == 'UART': if self.atlas_sensor_uart.setup: lines = self.atlas_sensor_uart.query('R') self.logger.debug("All Lines: {lines}".format(lines=lines)) if 'check probe' in lines: self.logger.error('"check probe" returned from sensor') elif str_is_float(lines[0]): temp = float(lines[0]) self.logger.debug( 'Value[0] is float: {val}'.format(val=temp)) else: self.logger.error( 'Value[0] is not float or "check probe": ' '{val}'.format(val=lines[0])) else: self.logger.error('UART device is not set up. ' 'Check the log for errors.') elif self.interface == 'I2C': if self.atlas_sensor_i2c.setup: temp_status, temp_str = self.atlas_sensor_i2c.query('R') if temp_status == 'error': self.logger.error( "Sensor read unsuccessful: {err}".format(err=temp_str)) elif temp_status == 'success': temp = float(temp_str) else: self.logger.error('I2C device is not set up.' 'Check the log for errors.') self.value_set(0, temp) return self.return_dict
def get_measurement(self): """ Gets the sensor's ORP measurement """ if not self.atlas_device.setup: self.logger.error("Input not set up") return orp = None self.return_dict = copy.deepcopy(measurements_dict) # Compensate measurement based on a temperature measurement if self.temperature_comp_meas_measurement_id and self.atlas_command: self.logger.debug("pH sensor set to calibrate temperature") last_measurement = self.get_last_measurement( self.temperature_comp_meas_device_id, self.temperature_comp_meas_measurement_id, max_age=self.max_age) if last_measurement: self.logger.debug("Latest temperature used to calibrate: {temp}".format(temp=last_measurement[1])) ret_value, ret_msg = self.atlas_command.calibrate('temperature', set_amount=last_measurement[1]) time.sleep(0.5) self.logger.debug("Calibration returned: {val}, {msg}".format(val=ret_value, msg=ret_msg)) else: self.logger.error("Calibration measurement not found within the past {} seconds".format(self.max_age)) # Read sensor via FTDI or UART if self.interface in ['FTDI', 'UART']: orp_status, orp_list = self.atlas_device.query('R') if orp_list: self.logger.debug("Returned list: {lines}".format(lines=orp_list)) # Find float value in list float_value = None for each_split in orp_list: if str_is_float(each_split): float_value = each_split break if 'check probe' in orp_list: self.logger.error('"check probe" returned from sensor') elif str_is_float(float_value): orp = float(float_value) self.logger.debug('Found float value: {val}'.format(val=orp)) else: self.logger.error('Value or "check probe" not found in list: {val}'.format(val=orp_list)) # Read sensor via I2C elif self.interface == 'I2C': ec_status, ec_str = self.atlas_device.query('R') if ec_status == 'error': self.logger.error("Sensor read unsuccessful: {err}".format(err=ec_str)) elif ec_status == 'success': orp = float(ec_str) self.value_set(0, orp) return self.return_dict
def output_mod(output_id, state, out_type, amount): """ Manipulate output (using non-unique ID) """ if not utils_general.user_has_permission('edit_controllers'): return 'Insufficient user permissions to manipulate outputs' daemon = DaemonControl() if (state in ['on', 'off'] and out_type == 'sec' and (str_is_float(amount) and float(amount) >= 0)): return daemon.output_on_off(output_id, state, float(amount)) elif (state == 'on' and out_type in ['pwm', 'command_pwm'] and (str_is_float(amount) and float(amount) >= 0)): return daemon.output_on(output_id, duty_cycle=float(amount))
def get_measurement(self): """Gets the Atlas Scientific pressure sensor measurement.""" if not self.atlas_device.setup: self.logger.error( "Error 101: Device not set up. See https://kizniche.github.io/Mycodo/Error-Codes#error-101 for more info." ) return pressure = None self.return_dict = copy.deepcopy(measurements_dict) if self.led == 'measure': self.atlas_device.query('L,1') # Read device atlas_status, atlas_return = self.atlas_device.query('R') self.logger.debug("Device Returned: {}: {}".format( atlas_status, atlas_return)) if self.led == 'measure': self.atlas_device.query('L,0') if atlas_status == 'error': self.logger.error( "Sensor read unsuccessful: {err}".format(err=atlas_return)) return # Parse device return data if self.interface in ['FTDI', 'UART']: # Find float value in list float_value = None for each_split in atlas_return: if str_is_float(each_split): float_value = each_split break if 'check probe' in atlas_return: self.logger.error('"check probe" returned from sensor') elif str_is_float(float_value): pressure = float(float_value) self.logger.debug( 'Found float value: {val}'.format(val=pressure)) else: self.logger.error( 'Value or "check probe" not found in list: {val}'.format( val=atlas_return)) elif self.interface == 'I2C': pressure = float(atlas_return) self.value_set(0, pressure) return self.return_dict
def output_mod(output_id, state, out_type, amount): """ Manipulate output (using non-unique ID) """ if not utils_general.user_has_permission('edit_controllers'): return 'Insufficient user permissions to manipulate outputs' daemon = DaemonControl() if (state in ['on', 'off'] and out_type == 'sec' and (str_is_float(amount) and float(amount) >= 0)): return daemon.output_on_off(output_id, state, float(amount)) elif (state == 'on' and out_type in ['pwm', 'command_pwm'] and (str_is_float(amount) and float(amount) >= 0)): return daemon.output_on(output_id, state, duty_cycle=float(amount))
def get_measurement(self): """ Gets the Atlas Scientific pressure sensor measurement """ if not self.atlas_device.setup: self.logger.error("Input not set up") return pressure = None self.return_dict = copy.deepcopy(measurements_dict) if self.led == 'measure': self.atlas_device.query('L,1') # Read sensor via FTDI or UART if self.interface in ['FTDI', 'UART']: press_status, press_list = self.atlas_device.query('R') if press_list: self.logger.debug( "Returned list: {lines}".format(lines=press_list)) # Find float value in list float_value = None for each_split in press_list: if str_is_float(each_split): float_value = each_split break if 'check probe' in press_list: self.logger.error('"check probe" returned from sensor') elif str_is_float(float_value): pressure = float(float_value) self.logger.debug( 'Found float value: {val}'.format(val=pressure)) else: self.logger.error( 'Value or "check probe" not found in list: {val}'.format( val=press_list)) elif self.interface == 'I2C': pressure_status, pressure_str = self.atlas_device.query('R') if pressure_status == 'error': self.logger.error( "Sensor read unsuccessful: {err}".format(err=pressure_str)) elif pressure_status == 'success': pressure = float(pressure_str) if self.led == 'measure': self.atlas_device.query('L,0') self.value_set(0, pressure) return self.return_dict
def setup_atlas_ec_measure(input_id): """ Acquire a measurement from the Atlas Scientific EC input and return it Used during calibration to display the current EC to the user """ if not utils_general.user_has_permission('edit_controllers'): return redirect(url_for('routes_page.page_atlas_ec_calibrate')) selected_input = Input.query.filter_by(unique_id=input_id).first() ec = None error = None atlas_command = setup_atlas_device(selected_input) if selected_input.interface in ['FTDI', 'UART']: ec_status, ec_list = atlas_command.query('R') if ec_list: logger.debug("Returned list: {lines}".format(lines=ec_list)) # Find float value in list float_value = None for each_split in ec_list: if str_is_float(each_split): float_value = each_split break # 'check probe' indicates an error reading the sensor if 'check probe' in ec_list: error = '"check probe" returned from input' # if a string resembling a float value is returned, this # is our measurement value elif str_is_float(float_value): ec = float(float_value) logger.debug('Found float value: {val}'.format(val=ec)) else: logger.error('Value or "check probe" not found in list: ' '{val}'.format(val=ec_list)) elif selected_input.interface == 'I2C': ec_status, ec_str = atlas_command.query('R') if ec_status == 'error': error = "Input read unsuccessful: {err}".format(err=ec_str) elif ec_status == 'success': ec = ec_str if error: logger.error(error) return error, 204 else: return ec
def output_mod_unique_id(unique_id, state, out_type, amount): """ Manipulate output (using unique ID) """ if not utils_general.user_has_permission('edit_controllers'): return 'Insufficient user permissions to manipulate outputs' output = Output.query.filter(Output.unique_id == unique_id).first() daemon = DaemonControl() if (state in ['on', 'off'] and out_type == 'sec' and (str_is_float(amount) and float(amount) >= 0)): return daemon.output_on_off(output.id, state, float(amount)) elif (state == 'on' and out_type == 'pwm' and (str_is_float(amount) and float(amount) >= 0)): return daemon.relay_on(output.id, state, duty_cycle=float(amount))
def get_measurement(self): """ Gets the sensor's measurement """ if not self.atlas_device.setup: self.logger.error("Input not set up") return co2 = None self.return_dict = copy.deepcopy(measurements_dict) # Read sensor via FTDI or UART if self.interface in ['FTDI', 'UART']: co2_status, co2_list = self.atlas_device.query('R') self.logger.debug("Returned: {}".format(co2_list)) # Find float value in list float_value = None for each_split in co2_list: if str_is_float(each_split): float_value = each_split break if 'check probe' in co2_list: self.logger.error('"check probe" returned from sensor') elif str_is_float(float_value): co2 = float(float_value) self.logger.debug('Found float value: {val}'.format(val=co2)) else: self.logger.error( 'Value or "check probe" not found in list: {val}'.format( val=co2_list)) # Read sensor via I2C elif self.interface == 'I2C': co2_status, co2_str = self.atlas_device.query('R') self.logger.debug("Returned: {}".format(co2_str)) if co2_status == 'error': self.logger.error( "Sensor read unsuccessful: {err}".format(err=co2_str)) elif co2_status == 'success': if str_is_float(co2_str): co2 = float(co2_str) else: self.logger.error( "Could not determine co2 from returned string: '{}'". format(co2_str)) self.value_set(0, co2) return self.return_dict
def get_measurement(self): """ Gets the Atlas PT1000's temperature in Celsius """ if not self.atlas_device.setup: self.logger.error("Input not set up") return temp = None self.return_dict = copy.deepcopy(measurements_dict) # Read sensor via FTDI or UART if self.interface in ['FTDI', 'UART']: temp_status, temp_list = self.atlas_device.query('R') if temp_list: self.logger.debug( "Returned list: {lines}".format(lines=temp_list)) # Find float value in list float_value = None for each_split in temp_list: if str_is_float(each_split): float_value = each_split break if 'check probe' in temp_list: self.logger.error('"check probe" returned from sensor') elif str_is_float(float_value): temp = float(float_value) self.logger.debug('Found float value: {val}'.format(val=temp)) else: self.logger.error( 'Value or "check probe" not found in list: {val}'.format( val=temp_list)) # Read sensor via I2C elif self.interface == 'I2C': temp_status, temp_str = self.atlas_device.query('R') if temp_status == 'error': self.logger.error( "Sensor read unsuccessful: {err}".format(err=temp_str)) elif temp_status == 'success': temp = float(temp_str) if temp == -1023: # Erroneous measurement return self.value_set(0, temp) return self.return_dict
def last_data_pid(input_id, input_period): """Return the most recent time and value from influxdb""" if not str_is_float(input_period): return '', 204 try: pid = PID.query.filter(PID.unique_id == input_id).first() measure_id = pid.measurement.split(',')[0] measure_type = pid.measurement.split(',')[1] live_data = { 'activated': pid.is_activated, 'paused': pid.is_paused, 'held': pid.is_held, 'setpoint': return_point_timestamp('setpoint', input_id, input_period), 'pid_p_value': return_point_timestamp('pid_p_value', input_id, input_period), 'pid_i_value': return_point_timestamp('pid_i_value', input_id, input_period), 'pid_d_value': return_point_timestamp('pid_d_value', input_id, input_period), 'pid_output': return_point_timestamp('pid_output', input_id, input_period), 'actual': return_point_timestamp(measure_type, measure_id, input_period) } return jsonify(live_data) except KeyError: logger.debug("No Data returned form influxdb") return '', 204 except Exception as e: logger.exception("URL for 'last_pid' raised and error: " "{err}".format(err=e)) return '', 204
def output_mod(output_id, channel, state, output_type, amount): """ Manipulate output (using non-unique ID) """ if not utils_general.user_has_permission('edit_controllers'): return 'Insufficient user permissions to manipulate outputs' if is_int(channel): # if an integer was returned output_channel = int(channel) else: # if a channel ID was returned channel_dev = db_retrieve_table(OutputChannel).filter( OutputChannel.unique_id == channel).first() if channel_dev: output_channel = channel_dev.channel else: return "Could not determine channel number from channel ID '{}'".format( channel) daemon = DaemonControl() if (state in ['on', 'off'] and str_is_float(amount) and ((output_type in ['sec', 'pwm', 'vol'] and float(amount) >= 0) or (output_type == 'value'))): out_status = daemon.output_on_off(output_id, state, output_type=output_type, amount=float(amount), output_channel=output_channel) if out_status[0]: return 'ERROR: {}'.format(out_status[1]) else: return 'SUCCESS: {}'.format(out_status[1]) else: return 'ERROR: unknown parameters: ' \ 'output_id: {}, channel: {}, state: {}, output_type: {}, amount: {}'.format( output_id, channel, state, output_type, amount)
def output_mod(output_id, channel_id, state, output_type, amount): """ Manipulate output (using non-unique ID) """ if not utils_general.user_has_permission('edit_controllers'): return 'Insufficient user permissions to manipulate outputs' if channel_id == '0': # some parts of pages don't have access to the channel ID and only know there is 1 channel channel = db_retrieve_table(OutputChannel).filter(and_( OutputChannel.output_id == output_id, OutputChannel.channel == 0)).first() else: channel = db_retrieve_table(OutputChannel, unique_id=channel_id) daemon = DaemonControl() if (state in ['on', 'off'] and output_type in ['sec', 'pwm', 'vol'] and (str_is_float(amount) and float(amount) >= 0)): out_status = daemon.output_on_off( output_id, state, output_type=output_type, amount=float(amount), output_channel=channel.channel) if out_status[0]: return 'ERROR: {}'.format(out_status[1]) else: return 'SUCCESS: {}'.format(out_status[1])
def get_measurement(self): """ Determine if the return value of the command is a number """ self.return_dict = measurements_dict.copy() self.logger.debug("Command being executed: {}".format(self.command)) timeout = 360 if self.command_timeout: timeout = self.command_timeout out, err, status = cmd_output( self.command, timeout=timeout, user=self.execute_as_user, cwd=self.current_working_dir) self.logger.debug("Command returned: {}, Status: {}, Error: {}".format(out, err, status)) if str_is_float(out): measurement_value = float(out) else: self.logger.debug( "The command returned a non-numerical value. " "Ensure only one numerical value is returned " "by the command. Value returned: '{}'".format(out)) return for channel in self.channels_measurement: if self.is_enabled(channel): self.return_dict[channel]['unit'] = self.channels_measurement[channel].unit self.return_dict[channel]['measurement'] = self.channels_measurement[channel].measurement self.return_dict[channel]['value'] = measurement_value return self.return_dict
def last_data(input_measure, input_id, input_period): """Return the most recent time and value from influxdb""" if not str_is_float(input_period): return '', 204 current_app.config['INFLUXDB_USER'] = INFLUXDB_USER current_app.config['INFLUXDB_PASSWORD'] = INFLUXDB_PASSWORD current_app.config['INFLUXDB_DATABASE'] = INFLUXDB_DATABASE dbcon = influx_db.connection try: query_str = query_string(input_measure, input_id, value='LAST', past_sec=input_period) if query_str == 1: return '', 204 raw_data = dbcon.query(query_str).raw number = len(raw_data['series'][0]['values']) time_raw = raw_data['series'][0]['values'][number - 1][0] value = raw_data['series'][0]['values'][number - 1][1] value = '{:.3f}'.format(float(value)) # Convert date-time to epoch (potential bottleneck for data) dt = date_parse(time_raw) timestamp = calendar.timegm(dt.timetuple()) * 1000 live_data = '[{},{}]'.format(timestamp, value) return Response(live_data, mimetype='text/json') except KeyError: logger.debug("No Data returned form influxdb") return '', 204 except Exception as e: logger.exception("URL for 'last_data' raised and error: " "{err}".format(err=e)) return '', 204
def get_measurement(self): """ Gets the Atlas PT1000's temperature in Celsius """ temp = None if self.interface == 'UART': if self.atlas_sensor_uart.setup: lines = self.atlas_sensor_uart.query('R') logger.debug("All Lines: {lines}".format(lines=lines)) if 'check probe' in lines: logger.error('"check probe" returned from sensor') elif str_is_float(lines[0]): temp = float(lines[0]) logger.debug('Value[0] is float: {val}'.format(val=temp)) else: temp = lines[0] logger.error('Value[0] is not float or "check probe": ' '{val}'.format(val=temp)) else: logger.error('UART device is not set up. ' 'Check the log for errors.') elif self.interface == 'I2C': if self.atlas_sensor_i2c.setup: temp_status, temp_str = self.atlas_sensor_i2c.query('R') if temp_status == 'error': logger.error( "Sensor read unsuccessful: {err}".format(err=temp_str)) elif temp_status == 'success': temp = float(temp_str) else: logger.error('I2C device is not set up.' 'Check the log for errors.') return temp
def get_measurement(self): """ Gets the sensor's DO measurement """ if not self.atlas_device.setup: self.logger.error("Input not set up") return do = None self.return_dict = copy.deepcopy(measurements_dict) # Read sensor via FTDI or UART if self.interface in ['FTDI', 'UART']: do_status, do_list = self.atlas_device.query('R') if do_list: self.logger.debug( "Returned list: {lines}".format(lines=do_list)) # Find float value in list float_value = None for each_split in do_list: if str_is_float(each_split): float_value = each_split break if 'check probe' in do_list: self.logger.error('"check probe" returned from sensor') elif str_is_float(float_value): do = float(float_value) self.logger.debug('Found float value: {val}'.format(val=do)) else: self.logger.error( 'Value or "check probe" not found in list: {val}'.format( val=do_list)) # Read sensor via I2C elif self.interface == 'I2C': ec_status, ec_str = self.atlas_device.query('R') if ec_status == 'error': self.logger.error( "Sensor read unsuccessful: {err}".format(err=ec_str)) elif ec_status == 'success': do = float(ec_str) self.value_set(0, do) return self.return_dict
def get_measurement(self): """Gets the Atlas Scientific humidity sensor measurement.""" if not self.atlas_device.setup: self.logger.error("Error 101: Device not set up. See https://kizniche.github.io/Mycodo/Error-Codes#error-101 for more info.") return return_string = None self.return_dict = copy.deepcopy(measurements_dict) if self.led == 'measure': self.atlas_device.query('L,1') # Read device atlas_status, atlas_return = self.atlas_device.query('R') self.logger.debug("Device Returned: {}: {}".format(atlas_status, atlas_return)) if self.led == 'measure': self.atlas_device.query('L,0') if atlas_status == 'error': self.logger.error("Sensor read unsuccessful: {err}".format(err=atlas_return)) return # Parse device return data if self.interface in ['FTDI', 'UART']: if 'check probe' in atlas_return: self.logger.error('"check probe" returned from sensor') return # Find value(s) in list for each_split in atlas_return: if "," in each_split or str_is_float(each_split): return_string = each_split break elif self.interface == 'I2C': return_string = atlas_return # Parse return string if return_string and ',' in return_string: index_place = 0 return_list = return_string.split(',') if self.is_enabled(1): self.value_set(1, return_list[index_place]) index_place += 1 if self.is_enabled(0): self.value_set(0, return_list[index_place]) index_place += 1 if self.is_enabled(2): self.value_set(2, return_list[index_place + 1]) elif self.is_enabled(0) and not self.is_enabled(1) and not self.is_enabled(2): self.value_set(0, return_string) elif not self.is_enabled(0) and self.is_enabled(1) and not self.is_enabled(2): self.value_set(1, return_string) return self.return_dict
def get_measurement(self): """ Gets the sensor's pH measurement via UART/I2C """ try: if ',' in self.sensor_sel.calibrate_sensor_measure: logger.debug("pH sensor set to calibrate temperature") device_id = self.sensor_sel.calibrate_sensor_measure.split(',')[0] measurement = self.sensor_sel.calibrate_sensor_measure.split(',')[1] last_measurement = read_last_influxdb( device_id, measurement, duration_sec=300) if last_measurement: logger.debug("Latest temperature used to calibrate: {temp}".format( temp=last_measurement[1])) atlas_command = AtlasScientificCommand(self.sensor_sel) ret_value, ret_msg = atlas_command.calibrate( 'temperature', temperature=last_measurement[1]) time.sleep(0.5) logger.debug("Calibration returned: {val}, {msg}".format( val=ret_value, msg=ret_msg)) ph = None if self.interface == 'UART': if self.atlas_sensor_uart.setup: lines = self.atlas_sensor_uart.query('R') if lines: logger.debug("All Lines: {lines}".format(lines=lines)) if 'check probe' in lines: logger.error('"check probe" returned from sensor') elif str_is_float(lines[0]): ph = float(lines[0]) logger.debug('Value[0] is float: {val}'.format(val=ph)) else: ph = lines[0] logger.error('Value[0] is not float or "check probe": ' '{val}'.format(val=ph)) else: logger.error('UART device is not set up.' 'Check the log for errors.') elif self.interface == 'I2C': if self.atlas_sensor_i2c.setup: ph_status, ph_str = self.atlas_sensor_i2c.query('R') if ph_status == 'error': logger.error("Sensor read unsuccessful: {err}".format( err=ph_str)) elif ph_status == 'success': ph = float(ph_str) else: logger.error('I2C device is not set up.' 'Check the log for errors.') return ph except: logger.exception(1)
def output_mod(output_id, state, out_type, amount): """ Manipulate output (using non-unique ID) """ if not utils_general.user_has_permission('edit_controllers'): return 'Insufficient user permissions to manipulate outputs' daemon = DaemonControl() if (state in ['on', 'off'] and out_type == 'sec' and (str_is_float(amount) and float(amount) >= 0)): out_status = daemon.output_on_off(output_id, state, float(amount)) if out_status[0]: return 'ERROR: {}'.format(out_status[1]) else: return 'SUCCESS: {}'.format(out_status[1]) elif (state == 'on' and out_type in OUTPUTS_PWM and (str_is_float(amount) and float(amount) >= 0)): out_status = daemon.output_on(output_id, duty_cycle=float(amount)) if out_status[0]: return 'ERROR: {}'.format(out_status[1]) else: return 'SUCCESS: {}'.format(out_status[1])
def get_measurement(self): """ Determine if the return value of the command is a number """ self._measurement = None out, _, _ = cmd_output(self.command) if str_is_float(out): return float(out) else: logger.error("The command returned a non-numerical value. " "Ensure only one numerical value is returned " "by the command.") return None
def read(self, num_of_bytes=31): """ Read a specified number of bytes from I2C, then parse and display the result """ res = self.file_read.read(num_of_bytes) # read from the board response = list(filter(lambda x: x != '\x00', res.decode())) # remove the null characters to get the response if ord(response[0]) == 1: # if the response isn't an error # change MSB to 0 for all received characters except the first and get a list of characters char_list = map(lambda x: chr(ord(x) & ~0x80), list(response[1:])) # NOTE: having to change the MSB to 0 is a glitch in the raspberry pi, and you shouldn't have to do this! str_float = ''.join(char_list) if str_is_float(str_float): return "success", str_float # convert the char list to a string and returns it else: return "error", "returned string does not represent a float value: {str}".format(str=str_float) else: return "error", str(ord(response[0]))
def past_data(input_measure, input_id, past_seconds): """Return data from past_seconds until present from influxdb""" if not str_is_float(past_seconds): return '', 204 if input_measure == 'tag': notes_list = [] tag = NoteTags.query.filter(NoteTags.unique_id == input_id).first() notes = Notes.query.filter(Notes.date_time >= ( datetime.datetime.utcnow() - datetime.timedelta(seconds=int(past_seconds)))).all() for each_note in notes: if tag.unique_id in each_note.tags.split(','): notes_list.append([ each_note.date_time.strftime( "%Y-%m-%dT%H:%M:%S.000000000Z"), each_note.name, each_note.note ]) if notes_list: return jsonify(notes_list) else: return '', 204 else: current_app.config['INFLUXDB_USER'] = INFLUXDB_USER current_app.config['INFLUXDB_PASSWORD'] = INFLUXDB_PASSWORD current_app.config['INFLUXDB_DATABASE'] = INFLUXDB_DATABASE current_app.config['INFLUXDB_TIMEOUT'] = 5 dbcon = influx_db.connection try: query_str = query_string(input_measure, input_id, past_sec=past_seconds) if query_str == 1: return '', 204 raw_data = dbcon.query(query_str).raw if raw_data: return jsonify(raw_data['series'][0]['values']) else: return '', 204 except Exception as e: logger.debug("URL for 'past_data' raised and error: " "{err}".format(err=e)) return '', 204
def setup_atlas_ph_measure(input_id): """ Acquire a measurement from the Atlas Scientific pH input and return it Used during calibration to display the current pH to the user """ if not utils_general.user_has_permission('edit_controllers'): return redirect(url_for('routes_page.page_atlas_ph_calibrate')) selected_input = Input.query.filter_by(unique_id=input_id).first() ph = None error = None if selected_input.interface == 'UART': ph_input_uart = AtlasScientificUART( selected_input.device_loc, baudrate=selected_input.baud_rate) lines = ph_input_uart.query('R') logger.debug("All Lines: {lines}".format(lines=lines)) if 'check probe' in lines: error = '"check probe" returned from input' elif not lines: error = 'Nothing returned from input' elif str_is_float(lines[0]): ph = lines[0] logger.debug('Value[0] is float: {val}'.format(val=ph)) else: error = 'Value[0] is not float or "check probe": {val}'.format( val=lines[0]) elif selected_input.interface == 'I2C': ph_input_i2c = AtlasScientificI2C( i2c_address=int(str(selected_input.location), 16), i2c_bus=selected_input.i2c_bus) ph_status, ph_str = ph_input_i2c.query('R') if ph_status == 'error': error = "Input read unsuccessful: {err}".format(err=ph_str) elif ph_status == 'success': ph = ph_str if error: logger.error(error) return error, 204 else: return ph
def get_measurement(self): """ Determine if the return value of the command is a number """ self.return_dict = measurements_dict.copy() out, _, _ = cmd_output(self.command) if str_is_float(out): list_measurements = [float(out)] else: self.logger.error("The command returned a non-numerical value. " "Ensure only one numerical value is returned " "by the command.") return for channel, meas in enumerate(self.device_measurements.all()): if meas.is_enabled: self.return_dict[channel]['unit'] = meas.unit self.return_dict[channel]['measurement'] = meas.measurement self.return_dict[channel]['value'] = list_measurements[channel] return self.return_dict
def get_measurement(self): """ Determine if the return value of the command is a number """ return_dict = measurements_dict.copy() out, _, _ = cmd_output(self.command) if str_is_float(out): list_measurements = [float(out)] else: self.logger.error( "The command returned a non-numerical value. " "Ensure only one numerical value is returned " "by the command.") return for channel, meas in enumerate(self.device_measurements.all()): if meas.is_enabled: return_dict[channel]['unit'] = meas.unit return_dict[channel]['measurement'] = meas.measurement return_dict[channel]['value'] = list_measurements[channel] return return_dict
def past_data(input_measure, input_id, past_seconds): """Return data from past_seconds until present from influxdb""" if not str_is_float(past_seconds): return '', 204 current_app.config['INFLUXDB_USER'] = INFLUXDB_USER current_app.config['INFLUXDB_PASSWORD'] = INFLUXDB_PASSWORD current_app.config['INFLUXDB_DATABASE'] = INFLUXDB_DATABASE dbcon = influx_db.connection try: query_str = query_string( input_measure, input_id, past_sec=past_seconds) if query_str == 1: return '', 204 raw_data = dbcon.query(query_str).raw if raw_data: return jsonify(raw_data['series'][0]['values']) else: return '', 204 except Exception as e: logger.debug("URL for 'past_data' raised and error: " "{err}".format(err=e)) return '', 204
def last_data_pid(pid_id, input_period): """Return the most recent time and value from influxdb""" if not str_is_float(input_period): return '', 204 try: pid = PID.query.filter(PID.unique_id == pid_id).first() device_id = pid.measurement.split(',')[0] measurement_id = pid.measurement.split(',')[1] actual_measurement = DeviceMeasurements.query.filter( DeviceMeasurements.unique_id == measurement_id).first() if actual_measurement: actual_cnversion = Conversion.query.filter( Conversion.unique_id == actual_measurement.conversion_id).first() else: actual_cnversion = None (actual_channel, actual_unit, actual_measurement) = return_measurement_info( actual_measurement, actual_cnversion) setpoint_measurement = None setpoint_unit = None setpoint_pid = PID.query.filter(PID.unique_id == pid_id).first() if setpoint_pid and ',' in setpoint_pid.measurement: pid_measurement = setpoint_pid.measurement.split(',')[1] setpoint_measurement = DeviceMeasurements.query.filter( DeviceMeasurements.unique_id == pid_measurement).first() if setpoint_measurement: conversion = Conversion.query.filter( Conversion.unique_id == setpoint_measurement.conversion_id).first() _, setpoint_unit, _ = return_measurement_info(setpoint_measurement, conversion) p_value = return_point_timestamp( pid_id, 'pid_value', input_period, measurement='pid_p_value') i_value = return_point_timestamp( pid_id, 'pid_value', input_period, measurement='pid_i_value') d_value = return_point_timestamp( pid_id, 'pid_value', input_period, measurement='pid_d_value') pid_value = [p_value[0], '{:.3f}'.format(float(p_value[1]) + float(i_value[1]) + float(d_value[1]))] live_data = { 'activated': pid.is_activated, 'paused': pid.is_paused, 'held': pid.is_held, 'setpoint': return_point_timestamp( pid_id, setpoint_unit, input_period, measurement=setpoint_measurement.measurement), 'pid_p_value': p_value, 'pid_i_value': i_value, 'pid_d_value': d_value, 'pid_pid_value': pid_value, 'duration_time': return_point_timestamp( pid_id, 's', input_period, measurement='duration_time'), 'duty_cycle': return_point_timestamp( pid_id, 'percent', input_period, measurement='duty_cycle'), 'actual': return_point_timestamp( device_id, actual_unit, input_period, measurement=actual_measurement, channel=actual_channel) } return jsonify(live_data) except KeyError: logger.debug("No Data returned form influxdb") return '', 204 except Exception as e: logger.exception("URL for 'last_pid' raised and error: " "{err}".format(err=e)) return '', 204
def get_measurement(self): """ Obtain and return the measurements """ self.return_dict = measurements_dict.copy() self.lock_acquire(self.lock_file, timeout=3600) if self.locked: self.logger.debug("Starting measurement") try: cmd = 'timeout -k 11 10 /var/mycodo-root/env/bin/python ' \ '/var/mycodo-root/mycodo/inputs/scripts/ruuvitag_values.py ' \ '--mac_address {mac} --bt_adapter {bta}'.format( mac=self.location, bta=self.bt_adapter) cmd = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) cmd_return, _ = cmd.communicate() cmd.wait() if not cmd_return: self.logger.debug("Measurement command returned no data") return values = cmd_return.decode('ascii').split(',') if not str_is_float(values[0]): self.logger.debug( "Error: Could not convert string to float: " "string '{}'".format(str(values[0]))) return temperature = float(str(values[0])) humidity = float(values[1]) pressure = float(values[2]) battery = float(values[3]) / 1000 acceleration_g_force = float(values[4]) / 1000 acceleration_x_g_force = float(values[5]) / 1000 acceleration_y_g_force = float(values[6]) / 1000 acceleration_z_g_force = float(values[7]) / 1000 if battery < 1 or battery > 4: self.logger.debug( "Not recording measurements: " "Battery outside expected range (1 < battery volts < 4): " "{bat}".format(bat=battery)) return if self.is_enabled(0): self.value_set(0, temperature) if self.is_enabled(1): self.value_set(1, humidity) if self.is_enabled(2): self.value_set(2, pressure) if self.is_enabled(3): self.value_set(3, battery) if self.is_enabled(4): self.value_set(4, acceleration_g_force) if self.is_enabled(5): self.value_set(5, acceleration_x_g_force) if self.is_enabled(6): self.value_set(6, acceleration_y_g_force) if self.is_enabled(7): self.value_set(7, acceleration_z_g_force) if (self.is_enabled(8) and self.is_enabled(0) and self.is_enabled(1)): self.value_set( 8, calculate_dewpoint(self.value_get(0), self.value_get(1))) if (self.is_enabled(9) and self.is_enabled(0) and self.is_enabled(1)): self.value_set( 9, calculate_vapor_pressure_deficit( self.value_get(0), self.value_get(1))) self.logger.debug("Completed measurement") return self.return_dict except Exception as msg: self.logger.debug("Error: {}".format(msg)) finally: self.lock_release(self.lock_file) time.sleep(1)
def get_measurement(self): """ Gets the sensor's ORP measurement via UART/I2C """ orp = None self.return_dict = measurements_dict.copy() # Compensate measurement based on a temperature measurement if self.temperature_comp_meas_measurement_id and self.atlas_command: self.logger.debug("pH sensor set to calibrate temperature") last_measurement = self.get_last_measurement( self.temperature_comp_meas_device_id, self.temperature_comp_meas_measurement_id, max_age=self.max_age) if last_measurement: self.logger.debug( "Latest temperature used to calibrate: {temp}".format( temp=last_measurement[1])) ret_value, ret_msg = self.atlas_command.calibrate( 'temperature', set_amount=last_measurement[1]) time.sleep(0.5) self.logger.debug("Calibration returned: {val}, {msg}".format( val=ret_value, msg=ret_msg)) else: self.logger.error( "Calibration measurement not found within the past " "{} seconds".format(self.max_age)) # Read sensor via UART if self.interface == 'FTDI': if self.atlas_sensor_ftdi.setup: lines = self.atlas_sensor_ftdi.query('R') if lines: self.logger.debug("All Lines: {lines}".format(lines=lines)) # 'check probe' indicates an error reading the sensor if 'check probe' in lines: self.logger.error('"check probe" returned from sensor') # if a string resembling a float value is returned, this # is out measurement value elif str_is_float(lines[0]): orp = float(lines[0]) self.logger.debug( 'Value[0] is float: {val}'.format(val=orp)) else: # During calibration, the sensor is put into # continuous mode, which causes a return of several # values in one string. If the return value does # not represent a float value, it is likely to be a # string of several values. This parses and returns # the first value. if str_is_float(lines[0].split(b'\r')[0]): orp = lines[0].split(b'\r')[0] # Lastly, this is called if the return value cannot # be determined. Watchthe output in the GUI to see # what it is. else: orp = lines[0] self.logger.error( 'Value[0] is not float or "check probe": ' '{val}'.format(val=orp)) else: self.logger.error('FTDI device is not set up.' 'Check the log for errors.') # Read sensor via UART elif self.interface == 'UART': if self.atlas_sensor_uart.setup: lines = self.atlas_sensor_uart.query('R') if lines: self.logger.debug("All Lines: {lines}".format(lines=lines)) # 'check probe' indicates an error reading the sensor if 'check probe' in lines: self.logger.error('"check probe" returned from sensor') # if a string resembling a float value is returned, this # is out measurement value elif str_is_float(lines[0]): orp = float(lines[0]) self.logger.debug( 'Value[0] is float: {val}'.format(val=orp)) else: # During calibration, the sensor is put into # continuous mode, which causes a return of several # values in one string. If the return value does # not represent a float value, it is likely to be a # string of several values. This parses and returns # the first value. if str_is_float(lines[0].split(b'\r')[0]): orp = lines[0].split(b'\r')[0] # Lastly, this is called if the return value cannot # be determined. Watchthe output in the GUI to see # what it is. else: orp = lines[0] self.logger.error( 'Value[0] is not float or "check probe": ' '{val}'.format(val=orp)) else: self.logger.error('UART device is not set up.' 'Check the log for errors.') # Read sensor via I2C elif self.interface == 'I2C': if self.atlas_sensor_i2c.setup: ec_status, ec_str = self.atlas_sensor_i2c.query('R') if ec_status == 'error': self.logger.error( "Sensor read unsuccessful: {err}".format(err=ec_str)) elif ec_status == 'success': orp = float(ec_str) else: self.logger.error( 'I2C device is not set up. Check the log for errors.') self.value_set(0, orp) return self.return_dict
def get_measurement(self): """ Gets the sensor's Electrical Conductivity measurement via UART/I2C """ return_string = None self.return_dict = measurements_dict.copy() # Read sensor via FTDI if self.interface == 'FTDI': if self.atlas_sensor.setup: lines = self.atlas_sensor.query('R') if lines: self.logger.debug("All Lines: {lines}".format(lines=lines)) # 'check probe' indicates an error reading the sensor if 'check probe' in lines: self.logger.error('"check probe" returned from sensor') # if a string resembling a float value is returned, this # is out measurement value elif str_is_float(lines[0]): return_string = lines[0] self.logger.debug('Value[0] is float: {val}'.format( val=return_string)) else: # During calibration, the sensor is put into # continuous mode, which causes a return of several # values in one string. If the return value does # not represent a float value, it is likely to be a # string of several values. This parses and returns # the first value. if str_is_float(lines[0].split(b'\r')[0]): return_string = lines[0].split(b'\r')[0] # Lastly, this is called if the return value cannot # be determined. Watchthe output in the GUI to see # what it is. else: return_string = lines[0] self.logger.error( 'Value[0] is not float or "check probe": ' '{val}'.format(val=return_string)) else: self.logger.error('FTDI device is not set up.' 'Check the log for errors.') # Read sensor via UART elif self.interface == 'UART': if self.atlas_sensor.setup: lines = self.atlas_sensor.query('R') if lines: self.logger.debug("All Lines: {lines}".format(lines=lines)) # 'check probe' indicates an error reading the sensor if 'check probe' in lines: self.logger.error('"check probe" returned from sensor') # if a string resembling a float value is returned, this # is out measurement value elif str_is_float(lines[0]): return_string = lines[0] self.logger.debug('Value[0] is float: {val}'.format( val=return_string)) else: # During calibration, the sensor is put into # continuous mode, which causes a return of several # values in one string. If the return value does # not represent a float value, it is likely to be a # string of several values. This parses and returns # the first value. if str_is_float(lines[0].split(b'\r')[0]): return_string = lines[0].split(b'\r')[0] # Lastly, this is called if the return value cannot # be determined. Watchthe output in the GUI to see # what it is. else: return_string = lines[0] self.logger.error( 'Value[0] is not float or "check probe": ' '{val}'.format(val=return_string)) else: self.logger.error('UART device is not set up.' 'Check the log for errors.') # Read sensor via I2C elif self.interface == 'I2C': if self.atlas_sensor.setup: ec_status, return_string = self.atlas_sensor.query('R') if ec_status == 'error': self.logger.error("Sensor read unsuccessful: {err}".format( err=return_string)) elif ec_status == 'success': self.logger.debug('Value: {val}'.format(val=return_string)) else: self.logger.error( 'I2C device is not set up. Check the log for errors.') # Parse return string if ',' in return_string: index_place = 0 return_list = return_string.split(',') if self.enabled_rgb: if self.is_enabled(0): self.value_set(0, int(return_list[index_place + 0])) if self.is_enabled(1): self.value_set(1, int(return_list[index_place + 1])) if self.is_enabled(2): self.value_set(2, int(return_list[index_place + 2])) index_place += 3 if return_list[index_place] == 'P': if self.is_enabled(7): self.value_set(7, int(return_list[index_place + 1])) index_place += 2 if return_list[index_place] == 'Lux': if self.is_enabled(6): self.value_set(6, int(return_list[index_place + 1])) index_place += 2 if return_list[index_place] == 'xyY': if self.is_enabled(3): self.value_set(3, float(return_list[index_place + 1])) if self.is_enabled(4): self.value_set(4, float(return_list[index_place + 2])) if self.is_enabled(5): self.value_set(5, int(return_list[index_place + 3])) return self.return_dict
def input_mod(form_mod, request_form): action = '{action} {controller}'.format( action=TRANSLATIONS['modify']['title'], controller=TRANSLATIONS['input']['title']) error = [] dict_inputs = parse_input_information() try: mod_input = Input.query.filter( Input.unique_id == form_mod.input_id.data).first() if mod_input.is_activated: error.append( gettext("Deactivate controller before modifying its settings")) if (mod_input.device == 'AM2315' and form_mod.period.data < 7): error.append( gettext("Choose a Read Period equal to or greater than 7. The " "AM2315 may become unresponsive if the period is " "below 7.")) if (mod_input.device != 'EDGE' and (mod_input.pre_output_duration and form_mod.period.data < mod_input.pre_output_duration)): error.append( gettext("The Read Period cannot be less than the Pre Output " "Duration")) if (form_mod.uart_location.data and not os.path.exists(form_mod.uart_location.data)): error.append( gettext( "Invalid device or improper permissions to read device")) if ('gpio_location' in dict_inputs[mod_input.device]['options_enabled'] and form_mod.gpio_location.data is None): error.append(gettext("Pin (GPIO) must be set")) mod_input.name = form_mod.name.data if form_mod.location.data: mod_input.location = form_mod.location.data if form_mod.i2c_location.data: mod_input.i2c_location = form_mod.i2c_location.data if form_mod.ftdi_location.data: mod_input.ftdi_location = form_mod.ftdi_location.data if form_mod.uart_location.data: mod_input.uart_location = form_mod.uart_location.data if form_mod.gpio_location.data and form_mod.gpio_location.data is not None: mod_input.gpio_location = form_mod.gpio_location.data if form_mod.power_output_id.data: mod_input.power_output_id = form_mod.power_output_id.data else: mod_input.power_output_id = None if form_mod.pre_output_id.data: mod_input.pre_output_id = form_mod.pre_output_id.data else: mod_input.pre_output_id = None # Enable/disable Channels measurements = DeviceMeasurements.query.filter( DeviceMeasurements.device_id == form_mod.input_id.data).all() if form_mod.measurements_enabled.data: for each_measurement in measurements: if each_measurement.unique_id in form_mod.measurements_enabled.data: each_measurement.is_enabled = True else: each_measurement.is_enabled = False mod_input.log_level_debug = form_mod.log_level_debug.data mod_input.i2c_bus = form_mod.i2c_bus.data mod_input.baud_rate = form_mod.baud_rate.data mod_input.pre_output_duration = form_mod.pre_output_duration.data mod_input.pre_output_during_measure = form_mod.pre_output_during_measure.data if form_mod.period.data: mod_input.period = form_mod.period.data mod_input.resolution = form_mod.resolution.data mod_input.resolution_2 = form_mod.resolution_2.data mod_input.sensitivity = form_mod.sensitivity.data mod_input.calibrate_sensor_measure = form_mod.calibrate_sensor_measure.data mod_input.cmd_command = form_mod.cmd_command.data mod_input.thermocouple_type = form_mod.thermocouple_type.data mod_input.ref_ohm = form_mod.ref_ohm.data # Serial options mod_input.pin_clock = form_mod.pin_clock.data mod_input.pin_cs = form_mod.pin_cs.data mod_input.pin_mosi = form_mod.pin_mosi.data mod_input.pin_miso = form_mod.pin_miso.data # Bluetooth options mod_input.bt_adapter = form_mod.bt_adapter.data mod_input.adc_gain = form_mod.adc_gain.data mod_input.adc_resolution = form_mod.adc_resolution.data mod_input.adc_sample_speed = form_mod.adc_sample_speed.data # Switch options mod_input.switch_edge = form_mod.switch_edge.data mod_input.switch_bouncetime = form_mod.switch_bouncetime.data mod_input.switch_reset_period = form_mod.switch_reset_period.data # PWM and RPM options mod_input.weighting = form_mod.weighting.data mod_input.rpm_pulses_per_rev = form_mod.rpm_pulses_per_rev.data mod_input.sample_time = form_mod.sample_time.data # Server options mod_input.port = form_mod.port.data mod_input.times_check = form_mod.times_check.data mod_input.deadline = form_mod.deadline.data # SHT sensor options if form_mod.sht_voltage.data: mod_input.sht_voltage = form_mod.sht_voltage.data if 'test_before_saving' in dict_inputs[mod_input.device]: (constraints_pass, constraints_errors, mod_input) = dict_inputs[mod_input.device]['test_before_saving']( mod_input, request_form) if constraints_pass: pass elif constraints_errors: for each_error in constraints_errors: flash(each_error, 'error') # Custom options list_options = [] if 'custom_options' in dict_inputs[mod_input.device]: for each_option in dict_inputs[mod_input.device]['custom_options']: null_value = True for key in request_form.keys(): if each_option['id'] == key: constraints_pass = True constraints_errors = [] value = None if each_option['type'] == 'float': if str_is_float(request_form.get(key)): if 'constraints_pass' in each_option: (constraints_pass, constraints_errors, mod_input ) = each_option['constraints_pass']( mod_input, float(request_form.get(key))) if constraints_pass: value = float(request_form.get(key)) else: error.append( "{name} must represent a float/decimal value " "(submitted '{value}')".format( name=each_option['name'], value=request_form.get(key))) elif each_option['type'] == 'integer': if is_int(request_form.get(key)): if 'constraints_pass' in each_option: (constraints_pass, constraints_errors, mod_input ) = each_option['constraints_pass']( mod_input, int(request_form.get(key))) if constraints_pass: value = int(request_form.get(key)) else: error.append( "{name} must represent an integer value " "(submitted '{value}')".format( name=each_option['name'], value=request_form.get(key))) elif each_option['type'] in ['text', 'select']: if 'constraints_pass' in each_option: (constraints_pass, constraints_errors, mod_input) = each_option['constraints_pass']( mod_input, request_form.get(key)) if constraints_pass: value = request_form.get(key) elif each_option['type'] == 'bool': value = bool(request_form.get(key)) for each_error in constraints_errors: error.append("Error: {name}: {error}".format( name=each_option['name'], error=each_error)) if value is not None: null_value = False option = '{id},{value}'.format(id=key, value=value) list_options.append(option) if null_value: option = '{id},'.format(id=each_option['id']) list_options.append(option) mod_input.custom_options = ';'.join(list_options) if not error: # Add or delete channels for variable measurement Inputs if ('measurements_variable_amount' in dict_inputs[mod_input.device] and dict_inputs[ mod_input.device]['measurements_variable_amount']): channels = DeviceMeasurements.query.filter( DeviceMeasurements.device_id == form_mod.input_id.data) if channels.count() != form_mod.num_channels.data: # Delete channels if form_mod.num_channels.data < channels.count(): for index, each_channel in enumerate(channels.all()): if index + 1 >= channels.count(): delete_entry_with_id(DeviceMeasurements, each_channel.unique_id) # Add channels elif form_mod.num_channels.data > channels.count(): start_number = channels.count() for index in range(start_number, form_mod.num_channels.data): new_measurement = DeviceMeasurements() new_measurement.name = "" new_measurement.device_id = mod_input.unique_id new_measurement.measurement = "" new_measurement.unit = "" new_measurement.channel = index new_measurement.save() db.session.commit() except Exception as except_msg: error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_data'))
def input_mod(form_mod, request_form): action = '{action} {controller}'.format( action=TRANSLATIONS['modify']['title'], controller=TRANSLATIONS['input']['title']) error = [] dict_inputs = parse_input_information() try: mod_input = Input.query.filter( Input.unique_id == form_mod.input_id.data).first() if mod_input.is_activated: error.append(gettext( "Deactivate controller before modifying its settings")) if (mod_input.device == 'AM2315' and form_mod.period.data < 7): error.append(gettext( "Choose a Read Period equal to or greater than 7. The " "AM2315 may become unresponsive if the period is " "below 7.")) if (mod_input.device != 'EDGE' and (mod_input.pre_output_duration and form_mod.period.data < mod_input.pre_output_duration)): error.append(gettext( "The Read Period cannot be less than the Pre Output " "Duration")) if (form_mod.uart_location.data and not os.path.exists(form_mod.uart_location.data)): error.append(gettext( "Invalid device or improper permissions to read device")) mod_input.name = form_mod.name.data if form_mod.location.data: mod_input.location = form_mod.location.data if form_mod.i2c_location.data: mod_input.i2c_location = form_mod.i2c_location.data if form_mod.ftdi_location.data: mod_input.ftdi_location = form_mod.ftdi_location.data if form_mod.uart_location.data: mod_input.uart_location = form_mod.uart_location.data if form_mod.gpio_location.data: mod_input.gpio_location = form_mod.gpio_location.data if form_mod.power_output_id.data: mod_input.power_output_id = form_mod.power_output_id.data else: mod_input.power_output_id = None if form_mod.pre_output_id.data: mod_input.pre_output_id = form_mod.pre_output_id.data else: mod_input.pre_output_id = None # Enable/disable Channels measurements = DeviceMeasurements.query.filter( DeviceMeasurements.device_id == form_mod.input_id.data).all() if form_mod.measurements_enabled.data: for each_measurement in measurements: if each_measurement.unique_id in form_mod.measurements_enabled.data: each_measurement.is_enabled = True else: each_measurement.is_enabled = False mod_input.i2c_bus = form_mod.i2c_bus.data mod_input.baud_rate = form_mod.baud_rate.data mod_input.pre_output_duration = form_mod.pre_output_duration.data mod_input.pre_output_during_measure = form_mod.pre_output_during_measure.data mod_input.period = form_mod.period.data mod_input.resolution = form_mod.resolution.data mod_input.resolution_2 = form_mod.resolution_2.data mod_input.sensitivity = form_mod.sensitivity.data mod_input.calibrate_sensor_measure = form_mod.calibrate_sensor_measure.data mod_input.cmd_command = form_mod.cmd_command.data mod_input.thermocouple_type = form_mod.thermocouple_type.data mod_input.ref_ohm = form_mod.ref_ohm.data # Serial options mod_input.pin_clock = form_mod.pin_clock.data mod_input.pin_cs = form_mod.pin_cs.data mod_input.pin_mosi = form_mod.pin_mosi.data mod_input.pin_miso = form_mod.pin_miso.data # Bluetooth options mod_input.bt_adapter = form_mod.bt_adapter.data mod_input.adc_gain = form_mod.adc_gain.data mod_input.adc_resolution = form_mod.adc_resolution.data mod_input.adc_sample_speed = form_mod.adc_sample_speed.data # Switch options mod_input.switch_edge = form_mod.switch_edge.data mod_input.switch_bouncetime = form_mod.switch_bouncetime.data mod_input.switch_reset_period = form_mod.switch_reset_period.data # PWM and RPM options mod_input.weighting = form_mod.weighting.data mod_input.rpm_pulses_per_rev = form_mod.rpm_pulses_per_rev.data mod_input.sample_time = form_mod.sample_time.data # Server options mod_input.port = form_mod.port.data mod_input.times_check = form_mod.times_check.data mod_input.deadline = form_mod.deadline.data # SHT sensor options if form_mod.sht_voltage.data: mod_input.sht_voltage = form_mod.sht_voltage.data # Custom options list_options = [] if 'custom_options' in dict_inputs[mod_input.device]: for each_option in dict_inputs[mod_input.device]['custom_options']: null_value = True for key in request_form.keys(): if each_option['id'] == key: constraints_pass = True constraints_errors = [] value = None if each_option['type'] == 'float': if str_is_float(request_form.get(key)): if 'constraints_pass' in each_option: (constraints_pass, constraints_errors, mod_input) = each_option['constraints_pass']( mod_input, float(request_form.get(key))) if constraints_pass: value = float(request_form.get(key)) else: error.append( "{name} must represent a float/decimal value " "(submitted '{value}')".format( name=each_option['name'], value=request_form.get(key))) elif each_option['type'] == 'integer': if is_int(request_form.get(key)): if 'constraints_pass' in each_option: (constraints_pass, constraints_errors, mod_input) = each_option['constraints_pass']( mod_input, int(request_form.get(key))) if constraints_pass: value = int(request_form.get(key)) else: error.append( "{name} must represent an integer value " "(submitted '{value}')".format( name=each_option['name'], value=request_form.get(key))) elif each_option['type'] in ['text', 'select']: if 'constraints_pass' in each_option: (constraints_pass, constraints_errors, mod_input) = each_option['constraints_pass']( mod_input, request_form.get(key)) if constraints_pass: value = request_form.get(key) elif each_option['type'] == 'bool': value = bool(request_form.get(key)) for each_error in constraints_errors: error.append( "Error: {name}: {error}".format( name=each_option['name'], error=each_error)) if value: null_value = False option = '{id},{value}'.format( id=key, value=value) list_options.append(option) if null_value: option = '{id},'.format(id=each_option['id']) list_options.append(option) mod_input.custom_options = ';'.join(list_options) if not error: db.session.commit() except Exception as except_msg: error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_data'))
def action_mod(form): """Modify a Conditional Action""" error = [] action = '{action} {controller}'.format( action=TRANSLATIONS['modify']['title'], controller='{} {}'.format(TRANSLATIONS['conditional']['title'], TRANSLATIONS['actions']['title'])) error = check_form_actions(form, error) try: mod_action = Actions.query.filter( Actions.unique_id == form.function_action_id.data).first() if mod_action.action_type == 'pause_actions': mod_action.pause_duration = form.pause_duration.data elif mod_action.action_type == 'output': mod_action.do_unique_id = form.do_unique_id.data mod_action.do_output_state = form.do_output_state.data mod_action.do_output_duration = form.do_output_duration.data elif mod_action.action_type == 'output_pwm': mod_action.do_unique_id = form.do_unique_id.data mod_action.do_output_pwm = form.do_output_pwm.data elif mod_action.action_type in ['activate_controller', 'deactivate_controller']: mod_action.do_unique_id = form.do_unique_id.data elif mod_action.action_type in ['activate_pid', 'deactivate_pid', 'resume_pid', 'pause_pid']: mod_action.do_unique_id = form.do_unique_id.data elif mod_action.action_type in ['activate_timer', 'deactivate_timer']: mod_action.do_unique_id = form.do_unique_id.data elif mod_action.action_type == 'setpoint_pid': if not str_is_float(form.do_action_string.data): error.append("Setpoint must be an integer or float value") mod_action.do_unique_id = form.do_unique_id.data mod_action.do_action_string = form.do_action_string.data elif mod_action.action_type == 'method_pid': mod_action.do_unique_id = form.do_unique_id.data mod_action.do_action_string = form.do_action_string.data elif mod_action.action_type == 'email': mod_action.do_action_string = form.do_action_string.data elif mod_action.action_type in ['photo_email', 'video_email']: mod_action.do_action_string = form.do_action_string.data mod_action.do_unique_id = form.do_unique_id.data mod_action.do_camera_duration = form.do_camera_duration.data elif mod_action.action_type in ['flash_lcd_on', 'flash_lcd_off', 'lcd_backlight_off', 'lcd_backlight_on']: mod_action.do_unique_id = form.do_unique_id.data elif mod_action.action_type == 'photo': mod_action.do_unique_id = form.do_unique_id.data elif mod_action.action_type == 'video': mod_action.do_unique_id = form.do_unique_id.data mod_action.do_camera_duration = form.do_camera_duration.data elif mod_action.action_type in ['command', 'create_note']: mod_action.do_action_string = form.do_action_string.data if not error: db.session.commit() except sqlalchemy.exc.OperationalError as except_msg: error.append(except_msg) except sqlalchemy.exc.IntegrityError as except_msg: error.append(except_msg) except Exception as except_msg: error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_function'))
def get_measurement(self): """ Gets the Atlas PT1000's temperature in Celsius """ temp = None return_dict = measurements_dict.copy() if self.interface == 'FTDI': if self.atlas_sensor_ftdi.setup: lines = self.atlas_sensor_ftdi.query('R') self.logger.debug("All Lines: {lines}".format(lines=lines)) if 'check probe' in lines: self.logger.error('"check probe" returned from sensor') elif isinstance(lines, list): if str_is_float(lines[0]): temp = float(lines[0]) self.logger.debug( 'Value[0] is float: {val}'.format(val=temp)) elif str_is_float(lines): temp = float(lines) self.logger.debug( 'Value is float: {val}'.format(val=temp)) else: self.logger.error( 'Unknown value: {val}'.format(val=lines)) else: self.logger.error('FTDI device is not set up. ' 'Check the log for errors.') elif self.interface == 'UART': if self.atlas_sensor_uart.setup: lines = self.atlas_sensor_uart.query('R') self.logger.debug("All Lines: {lines}".format(lines=lines)) if 'check probe' in lines: self.logger.error('"check probe" returned from sensor') elif str_is_float(lines[0]): temp = float(lines[0]) self.logger.debug( 'Value[0] is float: {val}'.format(val=temp)) else: self.logger.error( 'Value[0] is not float or "check probe": ' '{val}'.format(val=lines[0])) else: self.logger.error('UART device is not set up. ' 'Check the log for errors.') elif self.interface == 'I2C': if self.atlas_sensor_i2c.setup: temp_status, temp_str = self.atlas_sensor_i2c.query('R') if temp_status == 'error': self.logger.error( "Sensor read unsuccessful: {err}".format( err=temp_str)) elif temp_status == 'success': temp = float(temp_str) else: self.logger.error('I2C device is not set up.' 'Check the log for errors.') return_dict[0]['value'] = temp return return_dict
def last_data(unique_id, measure_type, measurement_id, period): """Return the most recent time and value from influxdb""" if not str_is_float(period): return '', 204 if measure_type in ['input', 'math', 'output', 'pid']: current_app.config['INFLUXDB_USER'] = INFLUXDB_USER current_app.config['INFLUXDB_PASSWORD'] = INFLUXDB_PASSWORD current_app.config['INFLUXDB_DATABASE'] = INFLUXDB_DATABASE current_app.config['INFLUXDB_TIMEOUT'] = 5 dbcon = influx_db.connection if measure_type in ['input', 'math', 'pid']: measure = DeviceMeasurements.query.filter( DeviceMeasurements.unique_id == measurement_id).first() elif measure_type == 'output': measure = Output.query.filter( Output.unique_id == unique_id).first() else: return '', 204 if measure: conversion = Conversion.query.filter( Conversion.unique_id == measure.conversion_id).first() else: conversion = None channel, unit, measurement = return_measurement_info( measure, conversion) if hasattr(measure, 'measurement_type') and measure.measurement_type == 'setpoint': setpoint_pid = PID.query.filter(PID.unique_id == measure.device_id).first() if setpoint_pid and ',' in setpoint_pid.measurement: pid_measurement = setpoint_pid.measurement.split(',')[1] setpoint_measurement = DeviceMeasurements.query.filter( DeviceMeasurements.unique_id == pid_measurement).first() if setpoint_measurement: conversion = Conversion.query.filter( Conversion.unique_id == setpoint_measurement.conversion_id).first() _, unit, measurement = return_measurement_info(setpoint_measurement, conversion) try: if period != '0': query_str = query_string( unit, unique_id, measure=measurement, channel=channel, value='LAST', past_sec=period) else: query_str = query_string( unit, unique_id, measure=measurement, channel=channel, value='LAST') if query_str == 1: return '', 204 raw_data = dbcon.query(query_str).raw number = len(raw_data['series'][0]['values']) time_raw = raw_data['series'][0]['values'][number - 1][0] value = raw_data['series'][0]['values'][number - 1][1] value = float(value) # Convert date-time to epoch (potential bottleneck for data) dt = date_parse(time_raw) timestamp = calendar.timegm(dt.timetuple()) * 1000 live_data = '[{},{}]'.format(timestamp, value) return Response(live_data, mimetype='text/json') except KeyError: logger.debug("No Data returned form influxdb") return '', 204 except Exception as e: logger.exception("URL for 'last_data' raised and error: " "{err}".format(err=e)) return '', 204
def past_data(unique_id, measure_type, measurement_id, past_seconds): """Return data from past_seconds until present from influxdb""" if not str_is_float(past_seconds): return '', 204 if measure_type == 'tag': notes_list = [] tag = NoteTags.query.filter(NoteTags.unique_id == unique_id).first() notes = Notes.query.filter( Notes.date_time >= (datetime.datetime.utcnow() - datetime.timedelta(seconds=int(past_seconds)))).all() for each_note in notes: if tag.unique_id in each_note.tags.split(','): notes_list.append( [each_note.date_time.strftime("%Y-%m-%dT%H:%M:%S.000000000Z"), each_note.name, each_note.note]) if notes_list: return jsonify(notes_list) else: return '', 204 elif measure_type in ['input', 'math', 'output', 'pid']: current_app.config['INFLUXDB_USER'] = INFLUXDB_USER current_app.config['INFLUXDB_PASSWORD'] = INFLUXDB_PASSWORD current_app.config['INFLUXDB_DATABASE'] = INFLUXDB_DATABASE current_app.config['INFLUXDB_TIMEOUT'] = 5 dbcon = influx_db.connection if measure_type in ['input', 'math', 'pid']: measure = DeviceMeasurements.query.filter( DeviceMeasurements.unique_id == measurement_id).first() elif measure_type == 'output': measure = Output.query.filter( Output.unique_id == unique_id).first() else: measure = None if not measure: return "Could not find measurement" if measure: conversion = Conversion.query.filter( Conversion.unique_id == measure.conversion_id).first() else: conversion = None channel, unit, measurement = return_measurement_info( measure, conversion) if hasattr(measure, 'measurement_type') and measure.measurement_type == 'setpoint': setpoint_pid = PID.query.filter(PID.unique_id == measure.device_id).first() if setpoint_pid and ',' in setpoint_pid.measurement: pid_measurement = setpoint_pid.measurement.split(',')[1] setpoint_measurement = DeviceMeasurements.query.filter( DeviceMeasurements.unique_id == pid_measurement).first() if setpoint_measurement: conversion = Conversion.query.filter( Conversion.unique_id == setpoint_measurement.conversion_id).first() _, unit, measurement = return_measurement_info(setpoint_measurement, conversion) try: query_str = query_string( unit, unique_id, measure=measurement, channel=channel, past_sec=past_seconds) if query_str == 1: return '', 204 raw_data = dbcon.query(query_str).raw if 'series' in raw_data: return jsonify(raw_data['series'][0]['values']) else: return '', 204 except Exception as e: logger.debug("URL for 'past_data' raised and error: " "{err}".format(err=e)) return '', 204