def check_actions(action, error): """Check if the Actions form inputs are valid""" if action.action_type == 'command': if not action.do_action_string or action.do_action_string == '': error.append("Command must be set") elif action.action_type == 'output': if not action.do_unique_id or action.do_unique_id == '': error.append("Output must be set") if not action.do_output_state or action.do_output_state == '': error.append("State must be set") elif action.action_type in ['activate_pid', 'deactivate_pid']: if not action.do_unique_id or action.do_unique_id == '': error.append("PID must be set") elif action.action_type == 'email': if not action.do_action_string or action.do_action_string == '': error.append("Email must be set") elif action.action_type in ['photo_email', 'video_email']: if not action.do_action_string or action.do_action_string == '': error.append("Email must be set") if not action.do_unique_id or action.do_unique_id == '': error.append("Camera must be set") if (action.action_type == 'video_email' and Camera.query.filter( and_(Camera.unique_id == action.do_unique_id, Camera.library != 'picamera')).count()): error.append('Only Pi Cameras can record video') elif action.action_type == 'flash_lcd_on' and not action.do_unique_id: error.append("LCD must be set") elif action.action_type == 'lcd_backlight_color': if not action.do_unique_id: error.append("LCD must be set") try: tuple_colors = action.do_action_string.split(",") if len(tuple_colors) != 3: error.append( 'LCD backlight color must be in the R,G,B format "255,255,255"' ) if not is_int(tuple_colors[0]): error.append('Red color does not represent an integer.') elif int(tuple_colors[0]) < 0 or int(tuple_colors[0]) > 255: error.append('Red color must be >= 0 and <= 255') if not is_int(tuple_colors[1]): error.append('Blue color does not represent an integer.') elif int(tuple_colors[1]) < 0 or int(tuple_colors[1]) > 255: error.append('Blue color must be >= 0 and <= 255') if not is_int(tuple_colors[2]): error.append('Green color does not represent an integer.') elif int(tuple_colors[2]) < 0 or int(tuple_colors[2]) > 255: error.append('Green color must be >= 0 and <= 255') except: error.append( 'Error parsing LCD backlight color. Must be in the R,G,B format ' '"255,255,255" without quotes.') elif (action.action_type in ['photo', 'video'] and (not action.do_unique_id or action.do_unique_id == '')): error.append("Camera must be set") return error
def calibration_export(self, args_dict): try: atlas_status, atlas_return = self.atlas_device.query("Export,?") self.logger.info("Command returned: {}".format(atlas_return)) if atlas_return and ',' in atlas_return: list_return = atlas_return.split(',') length = None bytes = None for each_item in list_return: if is_int(each_item): if length is None: length = int(each_item) elif bytes is None: bytes = int(each_item) break list_export = [] for _ in range(length): atlas_status, atlas_return = self.atlas_device.query( "Export") if atlas_return: list_export.append(atlas_return) atlas_status, atlas_return = self.atlas_device.query("Export") if atlas_return != "*DONE": self.logger.error( "Did not receive *DONE response indicating export ended" ) self.logger.info("pH Calibration export string: {}".format( ",".join(list_export))) atlas_status, atlas_return = self.atlas_device.query("Slope,?") if atlas_status == "success": self.logger.info("Slope: {}".format(atlas_return)) except: self.logger.exception("Exception exporting calibrating")
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_add(form_add): action = '{action} {controller}'.format(action=gettext("Add"), controller=gettext("Output")) error = [] dep_unmet, _ = return_dependencies(form_add.output_type.data) if dep_unmet: list_unmet_deps = [] for each_dep in dep_unmet: list_unmet_deps.append(each_dep[0]) error.append( "The {dev} device you're trying to add has unmet dependencies: {dep}" .format(dev=form_add.output_type.data, dep=', '.join(list_unmet_deps))) if is_int(form_add.output_quantity.data, check_range=[1, 20]): for _ in range(0, form_add.output_quantity.data): try: new_output = Output() new_output.name = OUTPUT_INFO[ form_add.output_type.data]['name'] new_output.output_type = form_add.output_type.data if form_add.output_type.data == 'wired': new_output.on_at_start = False elif form_add.output_type.data == 'wireless_433MHz_pi_switch': new_output.pin = None new_output.protocol = 1 new_output.pulse_length = 189 new_output.on_command = '22559' new_output.off_command = '22558' elif form_add.output_type.data == 'command': new_output.on_command = '/home/pi/script_on.sh' new_output.off_command = '/home/pi/script_off.sh' elif form_add.output_type.data == 'command_pwm': new_output.pwm_command = '/home/pi/script_pwm.sh ((duty_cycle))' elif form_add.output_type.data == 'pwm': new_output.pwm_hertz = 22000 new_output.pwm_library = 'pigpio_any' if not error: new_output.save() display_order = csv_to_list_of_str( DisplayOrder.query.first().output) DisplayOrder.query.first().output = add_display_order( display_order, new_output.unique_id) db.session.commit() manipulate_output('Add', new_output.unique_id) except sqlalchemy.exc.OperationalError as except_msg: error.append(except_msg) except sqlalchemy.exc.IntegrityError as except_msg: error.append(except_msg) else: error_msg = "{error}. {accepted_values}: 1-20".format( error=gettext("Invalid quantity"), accepted_values=gettext("Acceptable values")) error.append(error_msg) flash_success_errors(error, action, url_for('routes_page.page_output')) if dep_unmet: return 1
def output_mod(form_relay): action = '{action} {controller}'.format(action=gettext("Modify"), controller=gettext("Output")) error = [] try: mod_relay = Output.query.filter( Output.id == form_relay.relay_id.data).first() mod_relay.name = form_relay.name.data if mod_relay.relay_type == 'wired': if not is_int(form_relay.gpio.data): error.append("BCM Pin must be an integer") mod_relay.pin = form_relay.gpio.data mod_relay.trigger = bool(int(form_relay.trigger.data)) elif mod_relay.relay_type == 'wireless_433MHz_pi_switch': if not is_int(form_relay.wiringpi_pin.data): error.append("Pin must be an integer") if not is_int(form_relay.protocol.data): error.append("Protocol must be an integer") if not is_int(form_relay.pulse_length.data): error.append("Pulse Length must be an integer") if not is_int(form_relay.bit_length.data): error.append("Bit Length must be an integer") if not is_int(form_relay.on_command.data): error.append("On Command must be an integer") if not is_int(form_relay.off_command.data): error.append("Off Command must be an integer") mod_relay.pin = form_relay.wiringpi_pin.data mod_relay.protocol = form_relay.protocol.data mod_relay.pulse_length = form_relay.pulse_length.data mod_relay.bit_length = form_relay.bit_length.data mod_relay.on_command = form_relay.on_command.data mod_relay.off_command = form_relay.off_command.data elif mod_relay.relay_type == 'command': mod_relay.on_command = form_relay.on_command.data mod_relay.off_command = form_relay.off_command.data elif mod_relay.relay_type == 'pwm': mod_relay.pin = form_relay.gpio.data mod_relay.pwm_hertz = form_relay.pwm_hertz.data mod_relay.pwm_library = form_relay.pwm_library.data mod_relay.amps = form_relay.amps.data if form_relay.on_at_start.data == '-1' or mod_relay.relay_type == 'pwm': mod_relay.on_at_start = None else: mod_relay.on_at_start = bool(int(form_relay.on_at_start.data)) if not error: db.session.commit() manipulate_output('Modify', form_relay.relay_id.data) except Exception as except_msg: error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_output'))
def output_add(form_add_relay): action = '{action} {controller}'.format(action=gettext("Add"), controller=gettext("Output")) error = [] if is_int(form_add_relay.relay_quantity.data, check_range=[1, 20]): for _ in range(0, form_add_relay.relay_quantity.data): try: new_relay = Output() new_relay.relay_type = form_add_relay.relay_type.data if form_add_relay.relay_type.data == 'wired': new_relay.on_at_start = False elif form_add_relay.relay_type.data == 'wireless_433MHz_pi_switch': new_relay.protocol = 1 new_relay.bit_length = 25 new_relay.pulse_length = 189 new_relay.on_command = '22559' new_relay.off_command = '22558' elif form_add_relay.relay_type.data == 'command': new_relay.on_command = '/home/pi/script_on.sh' new_relay.off_command = '/home/pi/script_off.sh' elif form_add_relay.relay_type.data == 'pwm': new_relay.pwm_hertz = 22000 new_relay.pwm_library = 'pigpio_any' new_relay.save() display_order = csv_to_list_of_int( DisplayOrder.query.first().relay) DisplayOrder.query.first().relay = add_display_order( display_order, new_relay.id) db.session.commit() manipulate_output('Add', new_relay.id) except sqlalchemy.exc.OperationalError as except_msg: error.append(except_msg) except sqlalchemy.exc.IntegrityError as except_msg: error.append(except_msg) else: error_msg = "{error}. {accepted_values}: 1-20".format( error=gettext("Invalid quantity"), accepted_values=gettext("Acceptable values")) error.append(error_msg) flash_success_errors(error, action, url_for('routes_page.page_output'))
def output_add(form_add): action = '{action} {controller}'.format( action=TRANSLATIONS['add']['title'], controller=TRANSLATIONS['output']['title']) error = [] dep_unmet, _ = return_dependencies(form_add.output_type.data.split(',')[0]) if dep_unmet: list_unmet_deps = [] for each_dep in dep_unmet: list_unmet_deps.append(each_dep[0]) error.append( "The {dev} device you're trying to add has unmet dependencies: " "{dep}".format(dev=form_add.output_type.data, dep=', '.join(list_unmet_deps))) if len(form_add.output_type.data.split(',')) < 2: error.append("Must select an Output type") if not is_int(form_add.output_quantity.data, check_range=[1, 20]): error.append("{error}. {accepted_values}: 1-20".format( error=gettext("Invalid quantity"), accepted_values=gettext("Acceptable values") )) if not error: for _ in range(0, form_add.output_quantity.data): try: output_type = form_add.output_type.data.split(',')[0] interface = form_add.output_type.data.split(',')[1] new_output = Output() new_output.name = str(OUTPUT_INFO[output_type]['name']) new_output.output_type = output_type new_output.interface = interface if output_type in ['wired', 'wireless_rpi_rf', 'command', 'python']: new_output.measurement = 'duration_time' new_output.unit = 's' elif output_type in ['command_pwm', 'pwm', 'python_pwm']: new_output.measurement = 'duty_cycle' new_output.unit = 'percent' elif output_type == 'atlas_ezo_pmp': new_output.measurement = 'volume' new_output.unit = 'ml' new_output.channel = 0 if output_type == 'wired': new_output.on_at_start = False elif output_type == 'wireless_rpi_rf': new_output.pin = None new_output.protocol = 1 new_output.pulse_length = 189 new_output.on_command = '22559' new_output.off_command = '22558' elif output_type == 'command': new_output.on_command = '/home/pi/script_on.sh' new_output.off_command = '/home/pi/script_off.sh' elif output_type == 'command_pwm': new_output.pwm_command = '/home/pi/script_pwm.sh ((duty_cycle))' elif output_type == 'pwm': new_output.pwm_hertz = 22000 new_output.pwm_library = 'pigpio_any' elif output_type == 'python': new_output.on_command = """ timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") write_string = "{ts}: ID: {id}: ON\\n".format(id=output_id, ts=timestamp) with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile: myfile.write(write_string)""" new_output.off_command = """ timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") write_string = "{ts}: ID: {id}: OFF\\n".format(id=output_id, ts=timestamp) with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile: myfile.write(write_string)""" elif output_type == 'python_pwm': new_output.pwm_command = """ timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") write_string = "{ts}: ID: {id}: Duty Cycle: ((duty_cycle)) %\\n".format( id=output_id, ts=timestamp) with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile: myfile.write(write_string)""" elif output_type == 'atlas_ezo_pmp': new_output.flow_rate = 10 if interface == 'I2C': new_output.location = '0x67' new_output.i2c_bus = 1 elif interface == 'UART': new_output.location = '/dev/ttyAMA0' new_output.baud_rate = 9600 if not error: new_output.save() display_order = csv_to_list_of_str( DisplayOrder.query.first().output) DisplayOrder.query.first().output = add_display_order( display_order, new_output.unique_id) db.session.commit() manipulate_output('Add', new_output.unique_id) except sqlalchemy.exc.OperationalError as except_msg: error.append(except_msg) except sqlalchemy.exc.IntegrityError as except_msg: error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_output')) if dep_unmet: return 1
def output_add(form_add): action = '{action} {controller}'.format( action=TRANSLATIONS['add']['title'], controller=TRANSLATIONS['output']['title']) error = [] dict_outputs = parse_output_information() output_types_dict = output_types() # only one comma should be in the output_type string if form_add.output_type.data.count(',') > 1: error.append("Invalid output module formatting. It appears there is " "a comma in either 'output_name_unique' or 'interfaces'.") if form_add.output_type.data.count(',') == 1: output_type = form_add.output_type.data.split(',')[0] output_interface = form_add.output_type.data.split(',')[1] else: output_type = '' output_interface = '' error.append( "Invalid output string (must be a comma-separated string)") if current_app.config['TESTING']: dep_unmet = False else: dep_unmet, _ = return_dependencies( form_add.output_type.data.split(',')[0]) if dep_unmet: list_unmet_deps = [] for each_dep in dep_unmet: list_unmet_deps.append(each_dep[0]) error.append( "The {dev} device you're trying to add has unmet dependencies: " "{dep}".format(dev=form_add.output_type.data, dep=', '.join(list_unmet_deps))) if not is_int(form_add.output_quantity.data, check_range=[1, 20]): error.append("{error}. {accepted_values}: 1-20".format( error=gettext("Invalid quantity"), accepted_values=gettext("Acceptable values"))) if not error: for _ in range(0, form_add.output_quantity.data): try: new_output = Output() try: from RPi import GPIO if GPIO.RPI_INFO['P1_REVISION'] == 1: new_output.i2c_bus = 0 else: new_output.i2c_bus = 1 except: logger.error( "RPi.GPIO and Raspberry Pi required for this action") new_output.name = "Name" new_output.output_type = output_type new_output.interface = output_interface # # Set default values for new input being added # # input add options if output_type in dict_outputs: def dict_has_value(key): if (key in dict_outputs[output_type] and dict_outputs[output_type][key] is not None): return True # # Interfacing options # if output_interface == 'I2C': if dict_has_value('i2c_address_default'): new_output.i2c_location = dict_outputs[ output_type]['i2c_address_default'] elif dict_has_value('i2c_location'): new_output.i2c_location = dict_outputs[ output_type]['i2c_location'][ 0] # First list entry if output_interface == 'FTDI': if dict_has_value('ftdi_location'): new_output.ftdi_location = dict_outputs[ output_type]['ftdi_location'] if output_interface == 'UART': if dict_has_value('uart_location'): new_output.uart_location = dict_outputs[ output_type]['uart_location'] # UART options if dict_has_value('uart_baud_rate'): new_output.baud_rate = dict_outputs[output_type][ 'uart_baud_rate'] if dict_has_value('pin_cs'): new_output.pin_cs = dict_outputs[output_type]['pin_cs'] if dict_has_value('pin_miso'): new_output.pin_miso = dict_outputs[output_type][ 'pin_miso'] if dict_has_value('pin_mosi'): new_output.pin_mosi = dict_outputs[output_type][ 'pin_mosi'] if dict_has_value('pin_clock'): new_output.pin_clock = dict_outputs[output_type][ 'pin_clock'] # Bluetooth (BT) options elif output_interface == 'BT': if dict_has_value('bt_location'): new_output.location = dict_outputs[output_type][ 'bt_location'] if dict_has_value('bt_adapter'): new_output.bt_adapter = dict_outputs[output_type][ 'bt_adapter'] # GPIO options elif output_interface == 'GPIO': if dict_has_value('gpio_pin'): new_output.pin = dict_outputs[output_type][ 'gpio_pin'] # Custom location location elif dict_has_value('location'): new_output.location = dict_outputs[output_type][ 'location']['options'][0][0] # First entry in list # # Custom Options # list_options = [] if 'custom_options' in dict_outputs[output_type]: for each_option in dict_outputs[output_type][ 'custom_options']: if each_option['default_value'] is False: default_value = '' else: default_value = each_option['default_value'] option = '{id},{value}'.format(id=each_option['id'], value=default_value) list_options.append(option) new_output.custom_options = ';'.join(list_options) if output_type in output_types_dict['pwm']: new_output.pwm_hertz = 22000 new_output.pwm_library = 'pigpio_any' if output_type in output_types_dict['volume']: new_output.output_mode = 'fastest_flow_rate' new_output.flow_rate = 10 if output_type == 'atlas_ezo_pmp': if output_interface == 'FTDI': new_output.location = '/dev/ttyUSB0' elif output_interface == 'I2C': new_output.location = '0x67' new_output.i2c_bus = 1 elif output_interface == 'UART': new_output.location = '/dev/ttyAMA0' new_output.baud_rate = 9600 if output_type == 'wired': new_output.state_startup = '0' new_output.state_shutdown = '0' elif output_type == 'wireless_rpi_rf': new_output.pin = None new_output.protocol = 1 new_output.pulse_length = 189 new_output.on_command = '22559' new_output.off_command = '22558' new_output.force_command = True elif output_type == 'command': new_output.linux_command_user = '******' new_output.on_command = '/home/pi/script_on.sh' new_output.off_command = '/home/pi/script_off.sh' new_output.force_command = True elif output_type == 'command_pwm': new_output.linux_command_user = '******' new_output.pwm_command = '/home/pi/script_pwm.sh ((duty_cycle))' elif output_type == 'python': new_output.on_command = """ import datetime timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_string = "{ts}: ID: {id}: ON".format(id=output_id, ts=timestamp) self.logger.info(log_string)""" new_output.off_command = """ import datetime timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_string = "{ts}: ID: {id}: OFF".format(id=output_id, ts=timestamp) self.logger.info(log_string)""" new_output.force_command = True elif output_type == 'python_pwm': new_output.pwm_command = """ import datetime timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") log_string = "{ts}: ID: {id}: {dc} % Duty Cycle".format( dc=duty_cycle, id=output_id, ts=timestamp) self.logger.info(log_string)""" if not error: new_output.save() display_order = csv_to_list_of_str( DisplayOrder.query.first().output) DisplayOrder.query.first().output = add_display_order( display_order, new_output.unique_id) # # If measurements defined in the Output Module # if ('measurements_dict' in dict_outputs[output_type] and dict_outputs[output_type]['measurements_dict'] != []): for each_channel in dict_outputs[output_type][ 'measurements_dict']: measure_info = dict_outputs[output_type][ 'measurements_dict'][each_channel] new_measurement = DeviceMeasurements() if 'name' in measure_info: new_measurement.name = measure_info['name'] new_measurement.device_id = new_output.unique_id new_measurement.measurement = measure_info[ 'measurement'] new_measurement.unit = measure_info['unit'] new_measurement.channel = each_channel new_measurement.save() db.session.commit() if not current_app.config['TESTING']: manipulate_output('Add', new_output.unique_id) except sqlalchemy.exc.OperationalError as except_msg: error.append(except_msg) except sqlalchemy.exc.IntegrityError as except_msg: error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_output')) if dep_unmet: return 1
def output_mod(form_output, request_form): action = '{action} {controller}'.format( action=TRANSLATIONS['modify']['title'], controller=TRANSLATIONS['output']['title']) error = [] dict_outputs = parse_output_information() try: mod_output = Output.query.filter( Output.unique_id == form_output.output_id.data).first() if (form_output.uart_location.data and not os.path.exists(form_output.uart_location.data)): error.append( gettext( "Invalid device or improper permissions to read device")) mod_output.name = form_output.name.data if form_output.location.data: mod_output.location = form_output.location.data if form_output.i2c_location.data: mod_output.i2c_location = form_output.i2c_location.data if form_output.ftdi_location.data: mod_output.ftdi_location = form_output.ftdi_location.data if form_output.uart_location.data: mod_output.uart_location = form_output.uart_location.data if form_output.gpio_location.data: if not is_int(form_output.gpio_location.data): error.append("BCM GPIO Pin must be an integer") else: mod_output.pin = form_output.gpio_location.data mod_output.i2c_bus = form_output.i2c_bus.data mod_output.baud_rate = form_output.baud_rate.data mod_output.log_level_debug = form_output.log_level_debug.data mod_output.amps = form_output.amps.data mod_output.trigger_functions_at_start = form_output.trigger_functions_at_start.data mod_output.location = form_output.location.data mod_output.output_mode = form_output.output_mode.data if form_output.on_state.data in ["0", "1"]: mod_output.on_state = bool(int(form_output.on_state.data)) # Wireless options mod_output.protocol = form_output.protocol.data mod_output.pulse_length = form_output.pulse_length.data # Command options mod_output.on_command = form_output.on_command.data mod_output.off_command = form_output.off_command.data mod_output.force_command = form_output.force_command.data # PWM options mod_output.pwm_hertz = form_output.pwm_hertz.data mod_output.pwm_library = form_output.pwm_library.data mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data # Pump options if form_output.flow_rate.data: if (mod_output.output_type == 'atlas_ezo_pmp' and (form_output.flow_rate.data > 105 or form_output.flow_rate.data < 0.5)): error.append( "The Atlas Scientific Flow Rate must be between 0.5 and 105 ml/min" ) elif form_output.flow_rate.data <= 0: error.append("Flow Rate must be a positive value") else: mod_output.flow_rate = form_output.flow_rate.data mod_output.pwm_command = form_output.pwm_command.data mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data mod_output.linux_command_user = form_output.linux_command_user.data if form_output.state_startup.data == '-1': mod_output.state_startup = None elif form_output.state_startup.data is not None: mod_output.state_startup = form_output.state_startup.data if (hasattr(form_output, 'startup_value') and form_output.startup_value.data): mod_output.startup_value = form_output.startup_value.data if form_output.state_shutdown.data == '-1': mod_output.state_shutdown = None elif form_output.state_shutdown.data is not None: mod_output.state_shutdown = form_output.state_shutdown.data if (hasattr(form_output, 'shutdown_value') and form_output.shutdown_value.data): mod_output.shutdown_value = form_output.shutdown_value.data if 'test_before_saving' in dict_outputs[mod_output.output_type]: (constraints_pass, constraints_errors, mod_input ) = dict_outputs[mod_output.output_type]['test_before_saving']( mod_output, request_form) if constraints_pass: pass elif constraints_errors: for each_error in constraints_errors: flash(each_error, 'error') # Generate string to save from custom options error, custom_options = custom_options_return_string( error, dict_outputs, mod_output, request_form) if not error: mod_output.custom_options = custom_options db.session.commit() manipulate_output('Modify', form_output.output_id.data) except Exception as except_msg: logger.exception(1) error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_output'))
def output_mod(form_output, request_form): messages = { "success": [], "info": [], "warning": [], "error": [], "name": None, "return_text": [] } page_refresh = False dict_outputs = parse_output_information() try: channels = OutputChannel.query.filter( OutputChannel.output_id == form_output.output_id.data).all() mod_output = Output.query.filter( Output.unique_id == form_output.output_id.data).first() if (form_output.uart_location.data and not os.path.exists(form_output.uart_location.data)): messages["warning"].append(gettext( "Invalid device or improper permissions to read device")) mod_output.name = form_output.name.data messages["name"] = form_output.name.data if form_output.location.data: mod_output.location = form_output.location.data if form_output.i2c_location.data: mod_output.i2c_location = form_output.i2c_location.data if form_output.ftdi_location.data: mod_output.ftdi_location = form_output.ftdi_location.data if form_output.uart_location.data: mod_output.uart_location = form_output.uart_location.data if form_output.gpio_location.data: if not is_int(form_output.gpio_location.data): messages["error"].append("BCM GPIO Pin must be an integer") else: mod_output.pin = form_output.gpio_location.data if form_output.i2c_bus.data is not None: mod_output.i2c_bus = form_output.i2c_bus.data if form_output.baud_rate.data: mod_output.baud_rate = form_output.baud_rate.data mod_output.log_level_debug = form_output.log_level_debug.data # Parse pre-save custom options for output device and its channels try: custom_options_dict_presave = json.loads(mod_output.custom_options) except: logger.error("Malformed JSON") custom_options_dict_presave = {} custom_options_channels_dict_presave = {} for each_channel in channels: if each_channel.custom_options and each_channel.custom_options != "{}": custom_options_channels_dict_presave[each_channel.channel] = json.loads( each_channel.custom_options) else: custom_options_channels_dict_presave[each_channel.channel] = {} # Parse post-save custom options for output device and its channels messages["error"], custom_options_json_postsave = custom_options_return_json( messages["error"], dict_outputs, request_form, mod_dev=mod_output, device=mod_output.output_type) custom_options_dict_postsave = json.loads(custom_options_json_postsave) custom_options_channels_dict_postsave = {} for each_channel in channels: messages["error"], custom_options_channels_json_postsave_tmp = custom_channel_options_return_json( messages["error"], dict_outputs, request_form, form_output.output_id.data, each_channel.channel, device=mod_output.output_type, use_defaults=False) custom_options_channels_dict_postsave[each_channel.channel] = json.loads( custom_options_channels_json_postsave_tmp) if 'execute_at_modification' in dict_outputs[mod_output.output_type]: # pass custom options to module prior to saving to database (messages, mod_output, custom_options_dict, custom_options_channels_dict) = dict_outputs[mod_output.output_type]['execute_at_modification']( messages, mod_output, request_form, custom_options_dict_presave, custom_options_channels_dict_presave, custom_options_dict_postsave, custom_options_channels_dict_postsave) custom_options = json.dumps(custom_options_dict) # Convert from dict to JSON string custom_channel_options = custom_options_channels_dict else: # Don't pass custom options to module custom_options = json.dumps(custom_options_dict_postsave) custom_channel_options = custom_options_channels_dict_postsave # Finally, save custom options for both output and channels mod_output.custom_options = custom_options for each_channel in channels: if 'name' in custom_channel_options[each_channel.channel]: each_channel.name = custom_channel_options[each_channel.channel]['name'] each_channel.custom_options = json.dumps(custom_channel_options[each_channel.channel]) if not messages["error"]: db.session.commit() messages["success"].append('{action} {controller}'.format( action=TRANSLATIONS['modify']['title'], controller=TRANSLATIONS['output']['title'])) if not current_app.config['TESTING']: new_messages = manipulate_output( 'Modify', form_output.output_id.data) messages["error"].extend(new_messages["error"]) messages["success"].extend(new_messages["success"]) except Exception as except_msg: messages["error"].append(str(except_msg)) return messages, page_refresh
def custom_options_return_string(error, dict_options, mod_dev, request_form): # Custom options list_options = [] if 'custom_options' in dict_options[mod_dev.device]: for each_option in dict_options[mod_dev.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_dev) = each_option['constraints_pass']( mod_dev, 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_dev) = each_option['constraints_pass']( mod_dev, 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', 'select_measurement', 'select_device']: if 'constraints_pass' in each_option: (constraints_pass, constraints_errors, mod_dev) = each_option['constraints_pass']( mod_dev, 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) return error, ';'.join(list_options)
def output_add(form_add, request_form): action = '{action} {controller}'.format( action=TRANSLATIONS['add']['title'], controller=TRANSLATIONS['output']['title']) error = [] dict_outputs = parse_output_information() if current_app.config['TESTING']: dep_unmet = False else: dep_unmet, _ = return_dependencies(form_add.output_type.data.split(',')[0]) if dep_unmet: list_unmet_deps = [] for each_dep in dep_unmet: list_unmet_deps.append(each_dep[0]) error.append("The {dev} device you're trying to add has unmet dependencies: {dep}".format( dev=form_add.output_type.data.split(',')[0], dep=', '.join(list_unmet_deps))) if not is_int(form_add.output_quantity.data, check_range=[1, 20]): error.append("{error}. {accepted_values}: 1-20".format( error=gettext("Invalid quantity"), accepted_values=gettext("Acceptable values") )) if form_add.output_type.data.count(',') == 1: output_type = form_add.output_type.data.split(',')[0] output_interface = form_add.output_type.data.split(',')[1] else: output_type = '' output_interface = '' error.append("Invalid output string (must be a comma-separated string)") if not error: for _ in range(0, form_add.output_quantity.data): try: new_output = Output() try: from RPi import GPIO if GPIO.RPI_INFO['P1_REVISION'] == 1: new_output.i2c_bus = 0 else: new_output.i2c_bus = 1 except: logger.error( "RPi.GPIO and Raspberry Pi required for this action") new_output.name = "Name" new_output.output_type = output_type new_output.interface = output_interface # # Set default values for new input being added # # input add options if output_type in dict_outputs: def dict_has_value(key): if (key in dict_outputs[output_type] and dict_outputs[output_type][key] is not None): return True # # Interfacing options # if output_interface == 'I2C': if dict_has_value('i2c_address_default'): new_output.i2c_location = dict_outputs[output_type]['i2c_address_default'] elif dict_has_value('i2c_location'): new_output.i2c_location = dict_outputs[output_type]['i2c_location'][0] # First list entry if output_interface == 'FTDI': if dict_has_value('ftdi_location'): new_output.ftdi_location = dict_outputs[output_type]['ftdi_location'] if output_interface == 'UART': if dict_has_value('uart_location'): new_output.uart_location = dict_outputs[output_type]['uart_location'] # UART options if dict_has_value('uart_baud_rate'): new_output.baud_rate = dict_outputs[output_type]['uart_baud_rate'] if dict_has_value('pin_cs'): new_output.pin_cs = dict_outputs[output_type]['pin_cs'] if dict_has_value('pin_miso'): new_output.pin_miso = dict_outputs[output_type]['pin_miso'] if dict_has_value('pin_mosi'): new_output.pin_mosi = dict_outputs[output_type]['pin_mosi'] if dict_has_value('pin_clock'): new_output.pin_clock = dict_outputs[output_type]['pin_clock'] # Bluetooth (BT) options elif output_interface == 'BT': if dict_has_value('bt_location'): new_output.location = dict_outputs[output_type]['bt_location'] if dict_has_value('bt_adapter'): new_output.bt_adapter = dict_outputs[output_type]['bt_adapter'] # GPIO options elif output_interface == 'GPIO': if dict_has_value('gpio_pin'): new_output.pin = dict_outputs[output_type]['gpio_pin'] # Custom location location elif dict_has_value('location'): new_output.location = dict_outputs[output_type]['location']['options'][0][0] # First entry in list # Generate string to save from custom options error, custom_options = custom_options_return_json( error, dict_outputs, request_form, device=output_type, use_defaults=True) new_output.custom_options = custom_options # # Execute at Creation # new_output.unique_id = set_uuid() if 'execute_at_creation' in dict_outputs[output_type] and not current_app.config['TESTING']: dict_outputs[output_type]['execute_at_creation']( new_output, dict_outputs[output_type]) if not error: new_output.save() display_order = csv_to_list_of_str( DisplayOrder.query.first().output) DisplayOrder.query.first().output = add_display_order( display_order, new_output.unique_id) db.session.commit() # # If measurements defined in the Output Module # if ('measurements_dict' in dict_outputs[output_type] and dict_outputs[output_type]['measurements_dict'] != []): for each_measurement in dict_outputs[output_type]['measurements_dict']: measure_info = dict_outputs[output_type]['measurements_dict'][each_measurement] new_measurement = DeviceMeasurements() if 'name' in measure_info: new_measurement.name = measure_info['name'] new_measurement.device_id = new_output.unique_id new_measurement.measurement = measure_info['measurement'] new_measurement.unit = measure_info['unit'] new_measurement.channel = each_measurement new_measurement.save() for each_channel, channel_info in dict_outputs[output_type]['channels_dict'].items(): new_channel = OutputChannel() new_channel.channel = each_channel new_channel.output_id = new_output.unique_id # Generate string to save from custom options error, custom_options = custom_channel_options_return_json( error, dict_outputs, request_form, new_output.unique_id, each_channel, device=output_type, use_defaults=True) new_channel.custom_options = custom_options new_channel.save() # Refresh output settings if not current_app.config['TESTING']: manipulate_output('Add', new_output.unique_id) flash(gettext("{dev} with ID %(id)s successfully added".format( dev=dict_outputs[output_type]['output_name']), id=new_output.id), "success") except sqlalchemy.exc.OperationalError as except_msg: error.append(except_msg) except sqlalchemy.exc.IntegrityError as except_msg: error.append(except_msg) except Exception: logger.exception(1) return dep_unmet
def input_mod(form_mod, request_form): action = '{action} {controller}'.format(action=gettext("Modify"), controller=gettext("Input")) 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 sensor 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.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 if mod_input.device == 'LinuxCommand': mod_input.measurements = form_mod.selected_measurement_unit.data.split( ',')[0] if (mod_input.device == 'LinuxCommand' or ('analog_to_digital_converter' in dict_inputs[mod_input.device] and dict_inputs[mod_input.device]['analog_to_digital_converter'])): mod_input.convert_to_unit = form_mod.selected_measurement_unit.data short_list = [] mod_units = False for key in request_form.keys(): if 'convert_unit' in key: mod_units = True for value in request_form.getlist(key): if value == 'default': pass elif (len(value.split(',')) < 2 or value.split(',')[0] == '' or value.split(',')[1] == ''): error.append("Invalid custom unit") else: short_list.append(value) if mod_units: mod_input.convert_to_unit = ';'.join(short_list) 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 # ADC options mod_input.adc_channel = form_mod.adc_channel.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 mod_input.adc_volts_min = form_mod.adc_volts_min.data mod_input.adc_volts_max = form_mod.adc_volts_max.data mod_input.adc_units_min = form_mod.adc_units_min.data mod_input.adc_units_max = form_mod.adc_units_max.data mod_input.adc_inverse_unit_scale = form_mod.adc_inverse_unit_scale.data # Switch options mod_input.switch_edge = form_mod.switch_edge.data mod_input.switch_bouncetime = form_mod.switch_bounce_time.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 = each_option[ 'constraints_pass'](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 = each_option[ 'constraints_pass'](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 = each_option[ 'constraints_pass'](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 output_mod(form_output): action = '{action} {controller}'.format( action=TRANSLATIONS['modify']['title'], controller=TRANSLATIONS['output']['title']) error = [] try: mod_output = Output.query.filter( Output.unique_id == form_output.output_id.data).first() mod_output.name = form_output.name.data mod_output.amps = form_output.amps.data if form_output.trigger_functions_at_start.data: mod_output.trigger_functions_at_start = form_output.trigger_functions_at_start.data if mod_output.output_type == 'wired': if not is_int(form_output.gpio_location.data): error.append("BCM GPIO Pin must be an integer") mod_output.pin = form_output.gpio_location.data mod_output.on_state = bool(int(form_output.on_state.data)) elif mod_output.output_type == 'wireless_rpi_rf': if not is_int(form_output.gpio_location.data): error.append("Pin must be an integer") if not is_int(form_output.protocol.data): error.append("Protocol must be an integer") if not is_int(form_output.pulse_length.data): error.append("Pulse Length must be an integer") if not is_int(form_output.on_command.data): error.append("On Command must be an integer") if not is_int(form_output.off_command.data): error.append("Off Command must be an integer") mod_output.pin = form_output.gpio_location.data mod_output.protocol = form_output.protocol.data mod_output.pulse_length = form_output.pulse_length.data mod_output.on_command = form_output.on_command.data mod_output.off_command = form_output.off_command.data elif mod_output.output_type in ['command', 'python']: mod_output.on_command = form_output.on_command.data mod_output.off_command = form_output.off_command.data elif mod_output.output_type in ['command_pwm', 'python_pwm']: mod_output.pwm_command = form_output.pwm_command.data mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data elif mod_output.output_type == 'pwm': mod_output.pin = form_output.gpio_location.data mod_output.pwm_hertz = form_output.pwm_hertz.data mod_output.pwm_library = form_output.pwm_library.data mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data elif mod_output.output_type.startswith('atlas_ezo_pmp'): mod_output.location = form_output.location.data mod_output.output_mode = form_output.output_mode.data if form_output.flow_rate.data > 105 or form_output.flow_rate.data < 0.5: error.append("Flow Rate must be between 0.5 and 105 ml/min") else: mod_output.flow_rate = form_output.flow_rate.data if form_output.i2c_bus.data: mod_output.i2c_bus = form_output.i2c_bus.data if form_output.baud_rate.data: mod_output.baud_rate = form_output.baud_rate.data if form_output.state_startup.data == '-1': mod_output.state_startup = None elif form_output.state_startup.data is not None: mod_output.state_startup = form_output.state_startup.data if (hasattr(form_output, 'startup_value') and form_output.startup_value.data): mod_output.startup_value = form_output.startup_value.data if form_output.state_shutdown.data == '-1': mod_output.state_shutdown = None elif form_output.state_shutdown.data is not None: mod_output.state_shutdown = form_output.state_shutdown.data if (hasattr(form_output, 'shutdown_value') and form_output.shutdown_value.data): mod_output.shutdown_value = form_output.shutdown_value.data if not error: db.session.commit() manipulate_output('Modify', form_output.output_id.data) except Exception as except_msg: error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_output'))
def check_form_actions(form, error): """Check if the Actions form inputs are valid""" action = Actions.query.filter( Actions.unique_id == form.function_action_id.data).first() if action.action_type == 'command': if not form.do_action_string.data or form.do_action_string.data == '': error.append("Command must be set") elif action.action_type == 'output': if not form.do_unique_id.data or form.do_unique_id.data == '': error.append("Output must be set") if not form.do_output_state.data or form.do_output_state.data == '': error.append("State must be set") elif action.action_type == 'output_pwm': if not form.do_unique_id.data or form.do_unique_id.data == '': error.append("Output must be set") if form.do_output_pwm.data < 0 or form.do_output_pwm.data > 100 or form.do_output_pwm.data == '': error.append("Duty Cycle must be set (0 <= duty cycle <= 100)") elif action.action_type == 'output_value': if not form.do_unique_id.data or form.do_unique_id.data == '': error.append("Output must be set") if not form.do_output_amount.data: error.append("Value must be set") elif action.action_type == 'output_volume': if not form.do_unique_id.data or form.do_unique_id.data == '': error.append("Output must be set") if not form.do_output_amount.data: error.append("Volume must be set") elif action.action_type in ['activate_pid', 'deactivate_pid', 'resume_pid', 'pause_pid']: if not form.do_unique_id.data or form.do_unique_id.data == '': error.append("ID must be set") elif action.action_type == 'email': if not form.do_action_string.data or form.do_action_string.data == '': error.append("Email must be set") elif action.action_type in ['photo_email', 'video_email']: if not form.do_action_string.data or form.do_action_string.data == '': error.append("Email must be set") if not form.do_unique_id.data or form.do_unique_id.data == '': error.append("Camera must be set") if (action.action_type == 'video_email' and Camera.query.filter( and_(Camera.unique_id == form.do_unique_id.data, Camera.library != 'picamera')).count()): error.append('Only Pi Cameras can record video') elif action.action_type == 'flash_lcd_on' and not form.do_unique_id.data: error.append("LCD must be set") elif action.action_type == 'lcd_backlight_color': if not form.do_unique_id.data: error.append("LCD must be set") try: tuple_colors = form.do_action_string.data.split(",") if len(tuple_colors) != 3: error.append('LCD backlight color must be in the R,G,B format "255,255,255"') if not is_int(tuple_colors[0]): error.append('Red color does not represent an integer.') elif int(tuple_colors[0]) < 0 or int(tuple_colors[0]) > 255: error.append('Red color must be >= 0 and <= 255') if not is_int(tuple_colors[1]): error.append('Blue color does not represent an integer.') elif int(tuple_colors[1]) < 0 or int(tuple_colors[1]) > 255: error.append('Blue color must be >= 0 and <= 255') if not is_int(tuple_colors[2]): error.append('Green color does not represent an integer.') elif int(tuple_colors[2]) < 0 or int(tuple_colors[2]) > 255: error.append('Green color must be >= 0 and <= 255') except: error.append('Error parsing LCD backlight color. Must be in the R,G,B format ' '"255,255,255" without quotes.') elif (action.action_type in ['photo', 'video'] and (not form.do_unique_id.data or form.do_unique_id.data == '')): error.append("Camera must be set") return error
def output_mod(form_output): action = '{action} {controller}'.format( action=TRANSLATIONS['modify']['title'], controller=TRANSLATIONS['output']['title']) error = [] try: mod_output = Output.query.filter( Output.unique_id == form_output.output_id.data).first() mod_output.name = form_output.name.data mod_output.amps = form_output.amps.data if form_output.trigger_functions_at_start.data: mod_output.trigger_functions_at_start = form_output.trigger_functions_at_start.data if mod_output.output_type == 'wired': if not is_int(form_output.gpio_location.data): error.append("BCM GPIO Pin must be an integer") mod_output.pin = form_output.gpio_location.data mod_output.trigger = bool(int(form_output.trigger.data)) elif mod_output.output_type == 'wireless_rpi_rf': if not is_int(form_output.gpio_location.data): error.append("Pin must be an integer") if not is_int(form_output.protocol.data): error.append("Protocol must be an integer") if not is_int(form_output.pulse_length.data): error.append("Pulse Length must be an integer") if not is_int(form_output.on_command.data): error.append("On Command must be an integer") if not is_int(form_output.off_command.data): error.append("Off Command must be an integer") mod_output.pin = form_output.gpio_location.data mod_output.protocol = form_output.protocol.data mod_output.pulse_length = form_output.pulse_length.data mod_output.on_command = form_output.on_command.data mod_output.off_command = form_output.off_command.data elif mod_output.output_type in ['command', 'python']: mod_output.on_command = form_output.on_command.data mod_output.off_command = form_output.off_command.data elif mod_output.output_type in ['command_pwm', 'python_pwm']: mod_output.pwm_command = form_output.pwm_command.data mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data elif mod_output.output_type == 'pwm': mod_output.pin = form_output.gpio_location.data mod_output.pwm_hertz = form_output.pwm_hertz.data mod_output.pwm_library = form_output.pwm_library.data mod_output.pwm_invert_signal = form_output.pwm_invert_signal.data elif mod_output.output_type.startswith('atlas_ezo_pmp'): mod_output.location = form_output.location.data if form_output.flow_rate.data > 105 or form_output.flow_rate.data < 0.5: error.append("Flow Rate must be between 0.5 and 105 ml/min") else: mod_output.flow_rate = form_output.flow_rate.data if form_output.i2c_bus.data: mod_output.i2c_bus = form_output.i2c_bus.data if form_output.baud_rate.data: mod_output.baud_rate = form_output.baud_rate.data if (form_output.on_at_start.data == '-1' or mod_output.output_type in ['pwm', 'command_pwm']): mod_output.on_at_start = None elif form_output.on_at_start.data is not None: try: mod_output.on_at_start = bool(int(form_output.on_at_start.data)) except Exception: logger.error( "Error: Could not handle form_output.on_at_start.data: " "{}".format(form_output.on_at_start.data)) if not error: db.session.commit() manipulate_output('Modify', form_output.output_id.data) except Exception as except_msg: error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_output'))
def check_conditionals(self): """ Check if any Conditionals are activated and execute their actions if the Conditional is true. For example, if "temperature > 30", notify [email protected] "if measured temperature is above 30C" is the Conditional to check. "notify [email protected]" is the Condition Action to execute if the Conditional is True. """ cond = db_retrieve_table_daemon( Conditional, unique_id=self.function_id, entry='first') now = time.time() timestamp = datetime.datetime.fromtimestamp(now).strftime('%Y-%m-%d %H:%M:%S') message = "{ts}\n[Conditional {id}]\n[Name: {name}]".format( ts=timestamp, name=cond.name, id=self.function_id) # self.logger.info("Conditional Statement (pre-replacement):\n{}".format(self.conditional_statement)) cond_statement_replaced = self.conditional_statement # Replace short condition IDs in conditional statement with full condition IDs for each_condition in db_retrieve_table_daemon(ConditionalConditions, entry='all'): cond_statement_replaced = cond_statement_replaced.replace( '{{{id}}}'.format(id=each_condition.unique_id.split('-')[0]), each_condition.unique_id) # Replace short action IDs in conditional statement with full action IDs for each_action in db_retrieve_table_daemon(Actions, entry='all'): cond_statement_replaced = cond_statement_replaced.replace( '{{{id}}}'.format(id=each_action.unique_id.split('-')[0]), each_action.unique_id) message += '\n[Conditional Statement]:\n--------------------\n{statement}\n--------------------\n'.format( statement=cond.conditional_statement) # Add functions to the top of the statement string pre_statement = """ import os, sys sys.path.append(os.path.abspath('/var/mycodo-root')) from mycodo.mycodo_client import DaemonControl control = DaemonControl() message='''{message}''' def measure(condition_id): return control.get_condition_measurement(condition_id) def run_all_actions(message=message): control.trigger_all_actions('{function_id}', message=message) def run_action(action_id, message=message): control.trigger_action(action_id, message=message, single_action=True) """.format(message=message, function_id=self.function_id) cond_statement_replaced = pre_statement + cond_statement_replaced # self.logger.info("Conditional Statement (replaced):\n{}".format(cond_statement_replaced)) # Set the refractory period if self.refractory_period: self.timer_refractory_period = time.time() + self.refractory_period try: codeOut = StringIO() codeErr = StringIO() # capture output and errors sys.stdout = codeOut sys.stderr = codeErr exec(cond_statement_replaced, globals()) # restore stdout and stderr sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ py_error = codeErr.getvalue() py_output = codeOut.getvalue() # Evaluate conditional returned value (should be string of "1" (True) or "0" (False)) if is_int(py_output): evaluated_statement = bool(int(py_output)) else: evaluated_statement = False if py_error: self.logger.error("Error: {err}".format(err=py_error)) codeOut.close() codeErr.close() # self.logger.info("Conditional Statement (evaluated): {}".format(eval(cond_statement_replaced))) except: self.logger.error( "Error evaluating conditional statement. " "Replaced Conditional Statement:\n\n{cond_rep}\n\n{traceback}".format( cond_rep=cond_statement_replaced, traceback=traceback.format_exc())) evaluated_statement = None
def output_add(form_add, request_form): messages = { "success": [], "info": [], "warning": [], "error": [] } output_id = None dep_name = None size_y = None dict_outputs = parse_output_information() if form_add.output_type.data.count(',') == 1: output_type = form_add.output_type.data.split(',')[0] output_interface = form_add.output_type.data.split(',')[1] else: output_type = '' output_interface = '' messages["error"].append("Invalid output string (must be a comma-separated string)") if current_app.config['TESTING']: dep_unmet = False else: dep_unmet, _ = return_dependencies(form_add.output_type.data.split(',')[0]) if dep_unmet: list_unmet_deps = [] for each_dep in dep_unmet: list_unmet_deps.append(each_dep[0]) messages["error"].append( "{dev} has unmet dependencies. They must be installed before the Output can be added.".format( dev=output_type)) if output_type in dict_outputs: dep_name = dict_outputs[output_type]["output_name"] else: messages["error"].append("Output not found: {}".format(output_type)) return messages, dep_name, list_unmet_deps, None, None if not is_int(form_add.output_quantity.data, check_range=[1, 20]): messages["error"].append("{error}. {accepted_values}: 1-20".format( error=gettext("Invalid quantity"), accepted_values=gettext("Acceptable values") )) if not messages["error"]: for _ in range(0, form_add.output_quantity.data): try: new_output = Output() try: from RPi import GPIO if GPIO.RPI_INFO['P1_REVISION'] == 1: new_output.i2c_bus = 0 else: new_output.i2c_bus = 1 except: logger.error( "RPi.GPIO and Raspberry Pi required for this action") new_output.name = "Name" new_output.interface = output_interface size_y = len(dict_outputs[output_type]['channels_dict']) + 1 new_output.size_y = len(dict_outputs[output_type]['channels_dict']) + 1 new_output.output_type = output_type new_output.position_y = 999 # # Set default values for new input being added # # input add options if output_type in dict_outputs: def dict_has_value(key): if (key in dict_outputs[output_type] and dict_outputs[output_type][key] is not None): return True # # Interfacing options # if output_interface == 'I2C': if dict_has_value('i2c_address_default'): new_output.i2c_location = dict_outputs[output_type]['i2c_address_default'] elif dict_has_value('i2c_location'): new_output.i2c_location = dict_outputs[output_type]['i2c_location'][0] # First list entry if output_interface == 'FTDI': if dict_has_value('ftdi_location'): new_output.ftdi_location = dict_outputs[output_type]['ftdi_location'] if output_interface == 'UART': if dict_has_value('uart_location'): new_output.uart_location = dict_outputs[output_type]['uart_location'] # UART options if dict_has_value('uart_baud_rate'): new_output.baud_rate = dict_outputs[output_type]['uart_baud_rate'] if dict_has_value('pin_cs'): new_output.pin_cs = dict_outputs[output_type]['pin_cs'] if dict_has_value('pin_miso'): new_output.pin_miso = dict_outputs[output_type]['pin_miso'] if dict_has_value('pin_mosi'): new_output.pin_mosi = dict_outputs[output_type]['pin_mosi'] if dict_has_value('pin_clock'): new_output.pin_clock = dict_outputs[output_type]['pin_clock'] # Bluetooth (BT) options elif output_interface == 'BT': if dict_has_value('bt_location'): new_output.location = dict_outputs[output_type]['bt_location'] if dict_has_value('bt_adapter'): new_output.bt_adapter = dict_outputs[output_type]['bt_adapter'] # GPIO options elif output_interface == 'GPIO': if dict_has_value('gpio_pin'): new_output.pin = dict_outputs[output_type]['gpio_pin'] # Custom location location elif dict_has_value('location'): new_output.location = dict_outputs[output_type]['location']['options'][0][0] # First entry in list # Generate string to save from custom options messages["error"], custom_options = custom_options_return_json( messages["error"], dict_outputs, request_form, device=output_type, use_defaults=True) new_output.custom_options = custom_options # # Execute at Creation # new_output.unique_id = set_uuid() if 'execute_at_creation' in dict_outputs[output_type] and not current_app.config['TESTING']: messages["error"], new_output = dict_outputs[output_type]['execute_at_creation']( messages["error"], new_output, dict_outputs[output_type]) if not messages["error"]: new_output.save() output_id = new_output.unique_id db.session.commit() messages["success"].append('{action} {controller}'.format( action=TRANSLATIONS['add']['title'], controller=TRANSLATIONS['output']['title'])) # # If measurements defined in the Output Module # if ('measurements_dict' in dict_outputs[output_type] and dict_outputs[output_type]['measurements_dict'] != []): for each_measurement in dict_outputs[output_type]['measurements_dict']: measure_info = dict_outputs[output_type]['measurements_dict'][each_measurement] new_measurement = DeviceMeasurements() if 'name' in measure_info: new_measurement.name = measure_info['name'] new_measurement.device_id = new_output.unique_id new_measurement.measurement = measure_info['measurement'] new_measurement.unit = measure_info['unit'] new_measurement.channel = each_measurement new_measurement.save() for each_channel, channel_info in dict_outputs[output_type]['channels_dict'].items(): new_channel = OutputChannel() new_channel.channel = each_channel new_channel.output_id = new_output.unique_id # Generate string to save from custom options messages["error"], custom_options = custom_channel_options_return_json( messages["error"], dict_outputs, request_form, new_output.unique_id, each_channel, device=output_type, use_defaults=True) new_channel.custom_options = custom_options new_channel.save() # Refresh output settings if not current_app.config['TESTING']: new_messages = manipulate_output( 'Add', new_output.unique_id) messages["error"].extend(new_messages["error"]) messages["success"].extend(new_messages["success"]) except sqlalchemy.exc.OperationalError as except_msg: messages["error"].append(str(except_msg)) except sqlalchemy.exc.IntegrityError as except_msg: messages["error"].append(str(except_msg)) except Exception as except_msg: messages["error"].append(str(except_msg)) logger.exception(1) return messages, dep_unmet, None, output_id, size_y
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 output_mod(form_output, request_form): action = '{action} {controller}'.format( action=TRANSLATIONS['modify']['title'], controller=TRANSLATIONS['output']['title']) error = [] dict_outputs = parse_output_information() try: channels = OutputChannel.query.filter( OutputChannel.output_id == form_output.output_id.data).all() mod_output = Output.query.filter( Output.unique_id == form_output.output_id.data).first() if (form_output.uart_location.data and not os.path.exists(form_output.uart_location.data)): error.append(gettext( "Invalid device or improper permissions to read device")) mod_output.name = form_output.name.data if form_output.location.data: mod_output.location = form_output.location.data if form_output.i2c_location.data: mod_output.i2c_location = form_output.i2c_location.data if form_output.ftdi_location.data: mod_output.ftdi_location = form_output.ftdi_location.data if form_output.uart_location.data: mod_output.uart_location = form_output.uart_location.data if form_output.gpio_location.data: if not is_int(form_output.gpio_location.data): error.append("BCM GPIO Pin must be an integer") else: mod_output.pin = form_output.gpio_location.data if form_output.i2c_bus.data is not None: mod_output.i2c_bus = form_output.i2c_bus.data if form_output.baud_rate.data: mod_output.baud_rate = form_output.baud_rate.data mod_output.log_level_debug = form_output.log_level_debug.data # Parse pre-save custom options for output device and its channels try: custom_options_dict_presave = json.loads(mod_output.custom_options) except: logger.error("Malformed JSON") custom_options_dict_presave = {} custom_options_channels_dict_presave = {} for each_channel in channels: if each_channel.custom_options and each_channel.custom_options != "{}": custom_options_channels_dict_presave[each_channel.channel] = json.loads( each_channel.custom_options) else: custom_options_channels_dict_presave[each_channel.channel] = {} # Parse post-save custom options for output device and its channels error, custom_options_json_postsave = custom_options_return_json( error, dict_outputs, request_form, device=mod_output.output_type) custom_options_dict_postsave = json.loads(custom_options_json_postsave) custom_options_channels_dict_postsave = {} for each_channel in channels: error, custom_options_channels_json_postsave_tmp = custom_channel_options_return_json( error, dict_outputs, request_form, form_output.output_id.data, each_channel.channel, device=mod_output.output_type, use_defaults=True) custom_options_channels_dict_postsave[each_channel.channel] = json.loads( custom_options_channels_json_postsave_tmp) if 'execute_at_modification' in dict_outputs[mod_output.output_type]: # pass custom options to module prior to saving to database (allow_saving, mod_output, custom_options_dict, custom_options_channels_dict) = dict_outputs[mod_output.output_type]['execute_at_modification']( mod_output, request_form, custom_options_dict_presave, custom_options_channels_dict_presave, custom_options_dict_postsave, custom_options_channels_dict_postsave) custom_options = json.dumps(custom_options_dict) # Convert from dict to JSON string custom_channel_options = custom_options_channels_dict if not allow_saving: error.append("execute_at_modification() would not allow output options to be saved") else: # Don't pass custom options to module custom_options = json.dumps(custom_options_dict_postsave) custom_channel_options = custom_options_channels_dict_postsave # Finally, save custom options for both output and channels mod_output.custom_options = custom_options for each_channel in channels: if 'name' in custom_channel_options[each_channel.channel]: each_channel.name = custom_channel_options[each_channel.channel]['name'] each_channel.custom_options = json.dumps(custom_channel_options[each_channel.channel]) if not error: db.session.commit() manipulate_output('Modify', form_output.output_id.data) except Exception as except_msg: logger.exception(1) error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_output'))
def output_add(form_add): action = '{action} {controller}'.format( action=TRANSLATIONS['add']['title'], controller=TRANSLATIONS['output']['title']) error = [] dep_unmet, _ = return_dependencies(form_add.output_type.data.split(',')[0]) if dep_unmet: list_unmet_deps = [] for each_dep in dep_unmet: list_unmet_deps.append(each_dep[0]) error.append( "The {dev} device you're trying to add has unmet dependencies: " "{dep}".format(dev=form_add.output_type.data, dep=', '.join(list_unmet_deps))) if len(form_add.output_type.data.split(',')) < 2: error.append("Must select an Output type") if not is_int(form_add.output_quantity.data, check_range=[1, 20]): error.append("{error}. {accepted_values}: 1-20".format( error=gettext("Invalid quantity"), accepted_values=gettext("Acceptable values"))) if not error: for _ in range(0, form_add.output_quantity.data): try: output_type = form_add.output_type.data.split(',')[0] interface = form_add.output_type.data.split(',')[1] new_output = Output() new_output.name = str(OUTPUT_INFO[output_type]['name']) new_output.output_type = output_type new_output.interface = interface if output_type in [ 'wired', 'wireless_rpi_rf', 'command', 'python' ]: new_output.measurement = 'duration_time' new_output.unit = 's' elif output_type in OUTPUTS_PWM: new_output.measurement = 'duty_cycle' new_output.unit = 'percent' new_output.channel = 0 if output_type == 'wired': new_output.state_startup = '0' new_output.state_shutdown = '0' elif output_type == 'wireless_rpi_rf': new_output.pin = None new_output.protocol = 1 new_output.pulse_length = 189 new_output.on_command = '22559' new_output.off_command = '22558' elif output_type == 'command': new_output.on_command = '/home/pi/script_on.sh' new_output.off_command = '/home/pi/script_off.sh' elif output_type == 'command_pwm': new_output.pwm_command = '/home/pi/script_pwm.sh ((duty_cycle))' elif output_type == 'pwm': new_output.pwm_hertz = 22000 new_output.pwm_library = 'pigpio_any' elif output_type == 'python': new_output.on_command = """ timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") write_string = "{ts}: ID: {id}: ON\\n".format(id=output_id, ts=timestamp) with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile: myfile.write(write_string)""" new_output.off_command = """ timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") write_string = "{ts}: ID: {id}: OFF\\n".format(id=output_id, ts=timestamp) with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile: myfile.write(write_string)""" elif output_type == 'python_pwm': new_output.pwm_command = """ timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") write_string = "{ts}: ID: {id}: Duty Cycle: ((duty_cycle)) %\\n".format( id=output_id, ts=timestamp) with open("/home/pi/Mycodo/OutputTest.txt", "a") as myfile: myfile.write(write_string)""" elif output_type == 'atlas_ezo_pmp': new_output.output_mode = 'fastest_flow_rate' new_output.flow_rate = 10 if interface == 'FTDI': new_output.location = '/dev/ttyUSB0' elif interface == 'I2C': new_output.location = '0x67' new_output.i2c_bus = 1 elif interface == 'UART': new_output.location = '/dev/ttyAMA0' new_output.baud_rate = 9600 if not error: new_output.save() display_order = csv_to_list_of_str( DisplayOrder.query.first().output) DisplayOrder.query.first().output = add_display_order( display_order, new_output.unique_id) db.session.commit() # Add device measurements for measurement, measure_data in OUTPUT_INFO[ new_output.output_type]['measure'].items(): for unit, unit_data in measure_data.items(): for channel, _ in unit_data.items(): new_measurement = DeviceMeasurements() new_measurement.device_id = new_output.unique_id new_measurement.name = '' new_measurement.is_enabled = True new_measurement.measurement = measurement new_measurement.unit = unit new_measurement.channel = channel new_measurement.save() manipulate_output('Add', new_output.unique_id) except sqlalchemy.exc.OperationalError as except_msg: error.append(except_msg) except sqlalchemy.exc.IntegrityError as except_msg: error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_output')) if dep_unmet: return 1
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'))