def execute_at_creation(error, new_func, dict_functions=None): try: dict_controllers = parse_function_information() for channel in range(lcd_lines): new_channel = FunctionChannel() new_channel.name = "Set 0 Line {}".format(channel) new_channel.function_id = new_func.unique_id new_channel.channel = channel error, custom_options = custom_channel_options_return_json( error, dict_controllers, None, new_func.unique_id, channel, device=new_func.device, use_defaults=True) custom_options_dict = json.loads(custom_options) custom_options_dict["name"] = new_channel.name new_channel.custom_options = json.dumps(custom_options_dict) new_channel.save() except Exception: error.append("execute_at_modification() Error: {}".format( traceback.print_exc())) return error, new_func
def execute_at_modification(mod_function, request_form, custom_options_dict_presave, custom_options_channels_dict_presave, custom_options_dict_postsave, custom_options_channels_dict_postsave): """ This function allows you to view and modify the output and channel settings when the user clicks save on the user interface. Both the output and channel settings are passed to this function, as dictionaries. Additionally, both the pre-saved and post-saved options are available, as it's sometimes useful to know what settings changed and from what values. You can modify the post-saved options and these will be stored in the database. :param mod_output: The post-saved output database entry, minus the custom_options settings :param request_form: The requests.form object the user submitted :param custom_options_dict_presave: dict of pre-saved custom output options :param custom_options_channels_dict_presave: dict of pre-saved custom output channel options :param custom_options_dict_postsave: dict of post-saved custom output options :param custom_options_channels_dict_postsave: dict of post-saved custom output channel options :return: """ allow_saving = True page_refresh = False success = [] error = [] try: dict_controllers = parse_function_information() channels = FunctionChannel.query.filter( FunctionChannel.function_id == mod_function.unique_id) # Ensure name doesn't get overwritten selector_set = 0 selector_line = 0 for channel in range(channels.count()): custom_options_channels_dict_postsave[channel][ "name"] = "Set {} Line {}".format(selector_set, selector_line) selector_line += 1 if selector_line == lcd_lines: selector_set += 1 selector_line = 0 end_channel = custom_options_dict_postsave[ 'number_line_sets'] * lcd_lines # Increase number of channels if (custom_options_dict_postsave['number_line_sets'] > custom_options_dict_presave['number_line_sets']): page_refresh = True start_channel = channels.count() for index in range(start_channel, end_channel): new_channel = FunctionChannel() new_channel.name = "Set {} Line {}".format( math.trunc(index / lcd_lines), index - (math.trunc(index / lcd_lines) * lcd_lines)) new_channel.function_id = mod_function.unique_id new_channel.channel = index error, custom_options = custom_channel_options_return_json( error, dict_controllers, request_form, mod_function.unique_id, index, device=mod_function.device, use_defaults=False) custom_options_dict = json.loads(custom_options) custom_options_dict["name"] = new_channel.name new_channel.custom_options = json.dumps(custom_options_dict) new_channel.save() # Decrease number of channels elif (custom_options_dict_postsave['number_line_sets'] < custom_options_dict_presave['number_line_sets']): page_refresh = True for index, each_channel in enumerate(channels.all()): if index >= end_channel: delete_entry_with_id(FunctionChannel, each_channel.unique_id) except Exception: error.append("execute_at_modification() Error: {}".format( traceback.print_exc())) allow_saving = False for each_error in error: flash(each_error, 'error') for each_success in success: flash(each_success, 'success') return (allow_saving, page_refresh, mod_function, custom_options_dict_postsave, custom_options_channels_dict_postsave)
def input_add(form_add): action = '{action} {controller}'.format( action=TRANSLATIONS['add']['title'], controller=TRANSLATIONS['input']['title']) error = [] dict_inputs = parse_input_information() # only one comma should be in the input_type string if form_add.input_type.data.count(',') > 1: error.append("Invalid input module formatting. It appears there is " "a comma in either 'input_name_unique' or 'interfaces'.") if form_add.input_type.data.count(',') == 1: input_name = form_add.input_type.data.split(',')[0] input_interface = form_add.input_type.data.split(',')[1] else: input_name = '' input_interface = '' error.append("Invalid input string (must be a comma-separated string)") if current_app.config['TESTING']: dep_unmet = False else: dep_unmet, _ = return_dependencies(input_name) 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=input_name, dep=', '.join(list_unmet_deps))) if form_add.validate(): new_input = Input() new_input.device = input_name if input_interface: new_input.interface = input_interface try: from RPi import GPIO if GPIO.RPI_INFO['P1_REVISION'] == 1: new_input.i2c_bus = 0 else: new_input.i2c_bus = 1 except: logger.error("RPi.GPIO and Raspberry Pi required for this action") if 'input_name' in dict_inputs[input_name]: new_input.name = dict_inputs[input_name]['input_name'] else: new_input.name = 'Name' # # Set default values for new input being added # # input add options if input_name in dict_inputs: def dict_has_value(key): if (key in dict_inputs[input_name] and (dict_inputs[input_name][key] or dict_inputs[input_name][key] == 0)): return True # # Interfacing options # if input_interface == 'I2C': if dict_has_value('i2c_location'): new_input.i2c_location = dict_inputs[input_name][ 'i2c_location'][0] # First entry in list if input_interface == 'FTDI': if dict_has_value('ftdi_location'): new_input.ftdi_location = dict_inputs[input_name][ 'ftdi_location'] if input_interface == 'UART': if dict_has_value('uart_location'): new_input.uart_location = dict_inputs[input_name][ 'uart_location'] # UART options if dict_has_value('uart_baud_rate'): new_input.baud_rate = dict_inputs[input_name]['uart_baud_rate'] if dict_has_value('pin_cs'): new_input.pin_cs = dict_inputs[input_name]['pin_cs'] if dict_has_value('pin_miso'): new_input.pin_miso = dict_inputs[input_name]['pin_miso'] if dict_has_value('pin_mosi'): new_input.pin_mosi = dict_inputs[input_name]['pin_mosi'] if dict_has_value('pin_clock'): new_input.pin_clock = dict_inputs[input_name]['pin_clock'] # Bluetooth (BT) options elif input_interface == 'BT': if dict_has_value('bt_location'): if not re.match( "[0-9a-fA-F]{2}([:]?)[0-9a-fA-F]{2}(\\1[0-9a-fA-F]{2}){4}$", dict_inputs[input_name]['bt_location']): error.append( "Please specify device MAC-Address in format AA:BB:CC:DD:EE:FF" ) else: new_input.location = dict_inputs[input_name][ 'bt_location'] if dict_has_value('bt_adapter'): new_input.bt_adapter = dict_inputs[input_name][ 'bt_adapter'] # GPIO options elif input_interface == 'GPIO': if dict_has_value('gpio_location'): new_input.gpio_location = dict_inputs[input_name][ 'gpio_location'] # Custom location location elif dict_has_value('location'): new_input.location = dict_inputs[input_name]['location'][ 'options'][0][0] # First entry in list # # General options # if dict_has_value('period'): new_input.period = dict_inputs[input_name]['period'] # Server Ping options if dict_has_value('times_check'): new_input.times_check = dict_inputs[input_name]['times_check'] if dict_has_value('deadline'): new_input.deadline = dict_inputs[input_name]['deadline'] if dict_has_value('port'): new_input.port = dict_inputs[input_name]['port'] # Signal options if dict_has_value('weighting'): new_input.weighting = dict_inputs[input_name]['weighting'] if dict_has_value('sample_time'): new_input.sample_time = dict_inputs[input_name]['sample_time'] # Analog-to-digital converter options if dict_has_value('adc_gain'): if len(dict_inputs[input_name]['adc_gain']) == 1: new_input.adc_gain = dict_inputs[input_name]['adc_gain'][0] elif len(dict_inputs[input_name]['adc_gain']) > 1: new_input.adc_gain = dict_inputs[input_name]['adc_gain'][ 0][0] if dict_has_value('adc_resolution'): if len(dict_inputs[input_name]['adc_resolution']) == 1: new_input.adc_resolution = dict_inputs[input_name][ 'adc_resolution'][0] elif len(dict_inputs[input_name]['adc_resolution']) > 1: new_input.adc_resolution = dict_inputs[input_name][ 'adc_resolution'][0][0] if dict_has_value('adc_sample_speed'): if len(dict_inputs[input_name]['adc_sample_speed']) == 1: new_input.adc_sample_speed = dict_inputs[input_name][ 'adc_sample_speed'][0] elif len(dict_inputs[input_name]['adc_sample_speed']) > 1: new_input.adc_sample_speed = dict_inputs[input_name][ 'adc_sample_speed'][0][0] # Linux command if dict_has_value('cmd_command'): new_input.cmd_command = dict_inputs[input_name]['cmd_command'] # Misc options if dict_has_value('resolution'): if len(dict_inputs[input_name]['resolution']) == 1: new_input.resolution = dict_inputs[input_name][ 'resolution'][0] elif len(dict_inputs[input_name]['resolution']) > 1: new_input.resolution = dict_inputs[input_name][ 'resolution'][0][0] if dict_has_value('resolution_2'): if len(dict_inputs[input_name]['resolution_2']) == 1: new_input.resolution_2 = dict_inputs[input_name][ 'resolution_2'][0] elif len(dict_inputs[input_name]['resolution_2']) > 1: new_input.resolution_2 = dict_inputs[input_name][ 'resolution_2'][0][0] if dict_has_value('sensitivity'): if len(dict_inputs[input_name]['sensitivity']) == 1: new_input.sensitivity = dict_inputs[input_name][ 'sensitivity'][0] elif len(dict_inputs[input_name]['sensitivity']) > 1: new_input.sensitivity = dict_inputs[input_name][ 'sensitivity'][0][0] if dict_has_value('thermocouple_type'): if len(dict_inputs[input_name]['thermocouple_type']) == 1: new_input.thermocouple_type = dict_inputs[input_name][ 'thermocouple_type'][0] elif len(dict_inputs[input_name]['thermocouple_type']) > 1: new_input.thermocouple_type = dict_inputs[input_name][ 'thermocouple_type'][0][0] if dict_has_value('sht_voltage'): if len(dict_inputs[input_name]['sht_voltage']) == 1: new_input.sht_voltage = dict_inputs[input_name][ 'sht_voltage'][0] elif len(dict_inputs[input_name]['sht_voltage']) > 1: new_input.sht_voltage = dict_inputs[input_name][ 'sht_voltage'][0][0] if dict_has_value('ref_ohm'): new_input.ref_ohm = dict_inputs[input_name]['ref_ohm'] # # Custom Options # # Generate string to save from custom options error, custom_options = custom_options_return_json(error, dict_inputs, device=input_name, use_defaults=True) new_input.custom_options = custom_options # # Execute at Creation # new_input.unique_id = set_uuid() if ('execute_at_creation' in dict_inputs[new_input.device] and not current_app.config['TESTING']): error, new_input = dict_inputs[ new_input.device]['execute_at_creation']( error, new_input, dict_inputs[new_input.device]) try: if not error: new_input.save() display_order = csv_to_list_of_str( DisplayOrder.query.first().inputs) DisplayOrder.query.first().inputs = add_display_order( display_order, new_input.unique_id) db.session.commit() # # If there are a variable number of measurements # if ('measurements_variable_amount' in dict_inputs[input_name] and dict_inputs[input_name] ['measurements_variable_amount']): # Add first default measurement with empty unit and measurement new_measurement = DeviceMeasurements() new_measurement.name = "" new_measurement.device_id = new_input.unique_id new_measurement.measurement = "" new_measurement.unit = "" new_measurement.channel = 0 new_measurement.save() # # If measurements defined in the Input Module # elif ('measurements_dict' in dict_inputs[input_name] and dict_inputs[input_name]['measurements_dict']): for each_channel in dict_inputs[input_name][ 'measurements_dict']: measure_info = dict_inputs[input_name][ 'measurements_dict'][each_channel] new_measurement = DeviceMeasurements() if 'name' in measure_info: new_measurement.name = measure_info['name'] new_measurement.device_id = new_input.unique_id new_measurement.measurement = measure_info[ 'measurement'] new_measurement.unit = measure_info['unit'] new_measurement.channel = each_channel new_measurement.save() if 'channels_dict' in dict_inputs[new_input.device]: for each_channel, channel_info in dict_inputs[ new_input.device]['channels_dict'].items(): new_channel = InputChannel() new_channel.channel = each_channel new_channel.input_id = new_input.unique_id # Generate string to save from custom options error, custom_options = custom_channel_options_return_json( error, dict_inputs, None, new_input.unique_id, each_channel, device=new_input.device, use_defaults=True) new_channel.custom_options = custom_options new_channel.save() flash( gettext( "%(type)s Input with ID %(id)s (%(uuid)s) successfully added", type=input_name, id=new_input.id, uuid=new_input.unique_id), "success") 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_input')) else: flash_form_errors(form_add) 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 = [] warning = [] 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 (form_mod.period.data 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)): warning.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 if form_mod.start_offset.data: mod_input.start_offset = form_mod.start_offset.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 channels = InputChannel.query.filter( InputChannel.input_id == form_mod.input_id.data) # 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']): measurements = DeviceMeasurements.query.filter( DeviceMeasurements.device_id == form_mod.input_id.data) if measurements.count() != form_mod.num_channels.data: # Delete measurements/channels if form_mod.num_channels.data < measurements.count(): for index, each_channel in enumerate(measurements.all()): if index + 1 >= measurements.count(): delete_entry_with_id(DeviceMeasurements, each_channel.unique_id) if ('channel_quantity_same_as_measurements' in dict_inputs[mod_input.device] and dict_inputs[mod_input.device] ["channel_quantity_same_as_measurements"]): 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( InputChannel, each_channel.unique_id) # Add measurements/channels elif form_mod.num_channels.data > measurements.count(): start_number = measurements.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() if ('channel_quantity_same_as_measurements' in dict_inputs[mod_input.device] and dict_inputs[mod_input.device] ["channel_quantity_same_as_measurements"]): new_channel = InputChannel() new_channel.name = "" new_channel.input_id = mod_input.unique_id new_channel.channel = index error, custom_options = custom_channel_options_return_json( error, dict_inputs, request_form, mod_input.unique_id, index, device=mod_input.device, use_defaults=True) new_channel.custom_options = custom_options new_channel.save() # Parse pre-save custom options for output device and its channels try: custom_options_dict_presave = json.loads(mod_input.custom_options) except: logger.error("Malformed JSON") custom_options_dict_presave = {} custom_options_channels_dict_presave = {} for each_channel in channels.all(): 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_inputs, request_form, mod_dev=mod_input, device=mod_input.device) custom_options_dict_postsave = json.loads(custom_options_json_postsave) custom_options_channels_dict_postsave = {} for each_channel in channels.all(): error, custom_options_channels_json_postsave_tmp = custom_channel_options_return_json( error, dict_inputs, request_form, form_mod.input_id.data, each_channel.channel, device=mod_input.device, 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_inputs[mod_input.device]: # pass custom options to module prior to saving to database (allow_saving, mod_output, custom_options_dict, custom_options_channels_dict ) = dict_inputs[mod_input.device]['execute_at_modification']( mod_input, 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 input 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_input.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() except Exception as except_msg: error.append(except_msg) for each_warning in warning: flash(each_warning, "warning") flash_success_errors(error, action, url_for('routes_page.page_input'))
def function_add(form_add_func): messages = {"success": [], "info": [], "warning": [], "error": []} new_function_id = None list_unmet_deps = [] dep_name = None dep_message = '' function_name = form_add_func.function_type.data dict_controllers = parse_function_information() if not current_app.config['TESTING']: dep_unmet, _, dep_message = return_dependencies(function_name) if dep_unmet: for each_dep in dep_unmet: list_unmet_deps.append(each_dep[3]) messages["error"].append( f"{function_name} has unmet dependencies. " "They must be installed before the Function can be added.") if function_name in dict_controllers: dep_name = dict_controllers[function_name]['function_name'] else: messages["error"].append( f"Function not found: {function_name}") return messages, dep_name, list_unmet_deps, dep_message, None new_func = None try: if function_name == 'conditional_conditional': new_func = Conditional() new_func.position_y = 999 new_func.conditional_statement = ''' # Example code for learning how to use a Conditional. See the manual for more information. self.logger.info("This INFO log entry will appear in the Daemon Log") self.logger.error("This ERROR log entry will appear in the Daemon Log") if not hasattr(self, "loop_count"): # Initialize objects saved across executions self.loop_count = 1 else: self.loop_count += 1 # Replace "asdf1234" with a Condition ID measurement = self.condition("{asdf1234}") self.logger.info(f"Check this measurement in the Daemon Log. The value is {measurement}") if measurement is not None: # If a measurement exists self.message += "This message appears in email alerts and notes.\\n" if measurement < 23: # If the measurement is less than 23 self.message += f"Measurement is too Low! Measurement is {measurement}\\n" self.run_all_actions(message=self.message) # Run all actions sequentially elif measurement > 27: # Else If the measurement is greater than 27 self.message += f"Measurement is too High! Measurement is {measurement}\\n" # Replace "qwer5678" with an Action ID self.run_action("{qwer5678}", message=self.message) # Run a single specific Action''' new_func.conditional_status = ''' # Example code to provide a return status for other controllers and widgets. status_dict = { 'string_status': f"This is the demo status of the conditional controller. " f"The controller has looped {self.loop_count} times", 'loop_count': self.loop_count, 'error': [] } return status_dict''' if not messages["error"]: new_func.save() new_function_id = new_func.unique_id if not current_app.config['TESTING']: save_conditional_code(messages["error"], new_func.conditional_statement, new_func.conditional_status, new_func.unique_id, ConditionalConditions.query.all(), Actions.query.all(), test=False) elif function_name == 'pid_pid': new_func = PID() new_func.position_y = 999 new_func.save() new_function_id = new_func.unique_id for each_channel, measure_info in PID_INFO['measure'].items(): new_measurement = DeviceMeasurements() if 'name' in measure_info: new_measurement.name = measure_info['name'] if 'measurement_type' in measure_info: new_measurement.measurement_type = measure_info[ 'measurement_type'] new_measurement.device_id = new_func.unique_id new_measurement.measurement = measure_info['measurement'] new_measurement.unit = measure_info['unit'] new_measurement.channel = each_channel if not messages["error"]: new_measurement.save() elif function_name in [ 'trigger_edge', 'trigger_output', 'trigger_output_pwm', 'trigger_timer_daily_time_point', 'trigger_timer_daily_time_span', 'trigger_timer_duration', 'trigger_run_pwm_method', 'trigger_sunrise_sunset' ]: new_func = Trigger() new_func.name = '{}'.format(FUNCTION_INFO[function_name]['name']) new_func.trigger_type = function_name new_func.position_y = 999 if not messages["error"]: new_func.save() new_function_id = new_func.unique_id elif function_name == 'function_actions': new_func = Function() new_func.position_y = 999 new_func.function_type = function_name if not messages["error"]: new_func.save() new_function_id = new_func.unique_id elif function_name in dict_controllers: # Custom Function Controller new_func = CustomController() new_func.device = function_name new_func.position_y = 999 if 'function_name' in dict_controllers[function_name]: new_func.name = dict_controllers[function_name][ 'function_name'] else: new_func.name = 'Function Name' # Generate string to save from custom options messages["error"], custom_options = custom_options_return_json( messages["error"], dict_controllers, device=function_name, use_defaults=True) new_func.custom_options = custom_options new_func.unique_id = set_uuid() if ('execute_at_creation' in dict_controllers[new_func.device] and not current_app.config['TESTING']): messages["error"], new_func = dict_controllers[ new_func.device]['execute_at_creation']( messages["error"], new_func, dict_controllers[new_func.device]) if not messages["error"]: new_func.save() new_function_id = new_func.unique_id elif function_name == '': messages["error"].append("Must select a function type") else: messages["error"].append( f"Unknown function type: '{function_name}'") if not messages["error"]: if function_name in dict_controllers: # # Add measurements defined in the Function Module # if ('measurements_dict' in dict_controllers[function_name] and dict_controllers[function_name]['measurements_dict']): for each_channel in dict_controllers[function_name][ 'measurements_dict']: measure_info = dict_controllers[function_name][ 'measurements_dict'][each_channel] new_measurement = DeviceMeasurements() new_measurement.device_id = new_func.unique_id if 'name' in measure_info: new_measurement.name = measure_info['name'] else: new_measurement.name = "" if 'measurement' in measure_info: new_measurement.measurement = measure_info[ 'measurement'] else: new_measurement.measurement = "" if 'unit' in measure_info: new_measurement.unit = measure_info['unit'] else: new_measurement.unit = "" new_measurement.channel = each_channel new_measurement.save() # # If there are a variable number of measurements # elif ('measurements_variable_amount' in dict_controllers[function_name] and dict_controllers[function_name] ['measurements_variable_amount']): # Add first default measurement with empty unit and measurement new_measurement = DeviceMeasurements() new_measurement.name = "" new_measurement.device_id = new_func.unique_id new_measurement.measurement = "" new_measurement.unit = "" new_measurement.channel = 0 new_measurement.save() # # Add channels defined in the Function Module # if 'channels_dict' in dict_controllers[function_name]: for each_channel, channel_info in dict_controllers[ function_name]['channels_dict'].items(): new_channel = FunctionChannel() new_channel.channel = each_channel new_channel.function_id = new_func.unique_id # Generate string to save from custom options messages[ "error"], custom_options = custom_channel_options_return_json( messages["error"], dict_controllers, None, new_func.unique_id, each_channel, device=new_func.device, use_defaults=True) new_channel.custom_options = custom_options new_channel.save() messages["success"].append( f"{TRANSLATIONS['add']['title']} {TRANSLATIONS['function']['title']}" ) 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: logger.exception("Add Function") messages["error"].append(str(except_msg)) return messages, dep_name, list_unmet_deps, dep_message, new_function_id
def function_add(form_add_func): action = '{action} {controller}'.format( action=TRANSLATIONS['add']['title'], controller=TRANSLATIONS['function']['title']) error = [] function_name = form_add_func.function_type.data dict_controllers = parse_function_information() if current_app.config['TESTING']: dep_unmet = False else: dep_unmet, _ = return_dependencies(function_name) 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=function_name, dep=', '.join(list_unmet_deps))) new_func = None try: if function_name == 'conditional_conditional': new_func = Conditional() new_func.conditional_statement = ''' # Example code for learning how to use a Conditional. See the manual for more information. self.logger.info("This INFO log entry will appear in the Daemon Log") self.logger.error("This ERROR log entry will appear in the Daemon Log") # Replace "asdf1234" with a Condition ID measurement = self.condition("{asdf1234}") self.logger.info("Check this measurement in the Daemon Log. The value is {val}".format(val=measurement)) if measurement is not None: # If a measurement exists self.message += "This message appears in email alerts and notes.\\n" if measurement < 23: # If the measurement is less than 23 self.message += "Measurement is too Low! Measurement is {meas}\\n".format(meas=measurement) self.run_all_actions(message=self.message) # Run all actions sequentially elif measurement > 27: # Else If the measurement is greater than 27 self.message += "Measurement is too High! Measurement is {meas}\\n".format(meas=measurement) # Replace "qwer5678" with an Action ID self.run_action("{qwer5678}", message=self.message) # Run a single specific Action''' if not error: new_func.save() save_conditional_code( error, new_func.conditional_statement, new_func.unique_id, ConditionalConditions.query.all(), Actions.query.all(), test=False) elif function_name == 'pid_pid': new_func = PID().save() for each_channel, measure_info in PID_INFO['measure'].items(): new_measurement = DeviceMeasurements() if 'name' in measure_info: new_measurement.name = measure_info['name'] if 'measurement_type' in measure_info: new_measurement.measurement_type = measure_info['measurement_type'] new_measurement.device_id = new_func.unique_id new_measurement.measurement = measure_info['measurement'] new_measurement.unit = measure_info['unit'] new_measurement.channel = each_channel if not error: new_measurement.save() elif function_name in ['trigger_edge', 'trigger_output', 'trigger_output_pwm', 'trigger_timer_daily_time_point', 'trigger_timer_daily_time_span', 'trigger_timer_duration', 'trigger_run_pwm_method', 'trigger_sunrise_sunset']: new_func = Trigger() new_func.name = '{}'.format(FUNCTION_INFO[function_name]['name']) new_func.trigger_type = function_name if not error: new_func.save() elif function_name in ['function_spacer', 'function_actions']: new_func = Function() if function_name == 'function_spacer': new_func.name = 'Spacer' new_func.function_type = function_name if not error: new_func.save() elif function_name in dict_controllers: # Custom Function Controller new_func = CustomController() new_func.device = function_name if 'function_name' in dict_controllers[function_name]: new_func.name = dict_controllers[function_name]['function_name'] else: new_func.name = 'Function Name' # Generate string to save from custom options error, custom_options = custom_options_return_json( error, dict_controllers, device=function_name, use_defaults=True) new_func.custom_options = custom_options if not error: new_func.save() elif function_name == '': error.append("Must select a function type") else: error.append("Unknown function type: '{}'".format( function_name)) if not error: display_order = csv_to_list_of_str( DisplayOrder.query.first().function) DisplayOrder.query.first().function = add_display_order( display_order, new_func.unique_id) db.session.commit() if function_name in dict_controllers: # # Add measurements defined in the Function Module # if ('measurements_dict' in dict_controllers[function_name] and dict_controllers[function_name]['measurements_dict']): for each_channel in dict_controllers[function_name]['measurements_dict']: measure_info = dict_controllers[function_name]['measurements_dict'][each_channel] new_measurement = DeviceMeasurements() new_measurement.device_id = new_func.unique_id if 'name' in measure_info: new_measurement.name = measure_info['name'] else: new_measurement.name = "" if 'measurement' in measure_info: new_measurement.measurement = measure_info['measurement'] else: new_measurement.measurement = "" if 'unit' in measure_info: new_measurement.unit = measure_info['unit'] else: new_measurement.unit = "" new_measurement.channel = each_channel new_measurement.save() # # If there are a variable number of measurements # elif ('measurements_variable_amount' in dict_controllers[function_name] and dict_controllers[function_name]['measurements_variable_amount']): # Add first default measurement with empty unit and measurement new_measurement = DeviceMeasurements() new_measurement.name = "" new_measurement.device_id = new_func.unique_id new_measurement.measurement = "" new_measurement.unit = "" new_measurement.channel = 0 new_measurement.save() # # Add channels defined in the Function Module # if 'channels_dict' in dict_controllers[function_name]: for each_channel, channel_info in dict_controllers[function_name]['channels_dict'].items(): new_channel = FunctionChannel() new_channel.channel = each_channel new_channel.function_id = new_func.unique_id # Generate string to save from custom options error, custom_options = custom_channel_options_return_json( error, dict_controllers, None, new_func.unique_id, each_channel, device=new_func.device, use_defaults=True) new_channel.custom_options = custom_options new_channel.save() 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: logger.exception("Add Function") error.append(except_msg) flash_success_errors(error, action, url_for('routes_page.page_function')) if dep_unmet: return 1
def input_add(form_add): messages = {"success": [], "info": [], "warning": [], "error": []} new_input_id = None list_unmet_deps = [] dep_name = None dep_message = '' dict_inputs = parse_input_information() # only one comma should be in the input_type string if form_add.input_type.data.count(',') > 1: messages["error"].append( "Invalid input module formatting. It appears there is " "a comma in either 'input_name_unique' or 'interfaces'.") if form_add.input_type.data.count(',') == 1: input_name = form_add.input_type.data.split(',')[0] input_interface = form_add.input_type.data.split(',')[1] else: input_name = '' input_interface = '' messages["error"].append( "Invalid input string (must be a comma-separated string)") if not current_app.config['TESTING']: dep_unmet, _, dep_message = return_dependencies(input_name) if dep_unmet: for each_dep in dep_unmet: list_unmet_deps.append(each_dep[3]) messages["error"].append( f"{input_name} has unmet dependencies. They must be installed before the Input can be added." ) if input_name in dict_inputs: dep_name = dict_inputs[input_name]['input_name'] else: messages["error"].append(f"Input not found: {input_name}") return messages, dep_name, list_unmet_deps, dep_message, None if form_add.validate(): new_input = Input() new_input.device = input_name new_input.position_y = 999 if input_interface: new_input.interface = input_interface new_input.i2c_bus = 1 if 'input_name_short' in dict_inputs[input_name]: new_input.name = dict_inputs[input_name]['input_name_short'] elif 'input_name' in dict_inputs[input_name]: new_input.name = dict_inputs[input_name]['input_name'] else: new_input.name = 'Name' # # Set default values for new input being added # # input add options if input_name in dict_inputs: def dict_has_value(key): if (key in dict_inputs[input_name] and (dict_inputs[input_name][key] or dict_inputs[input_name][key] == 0)): return True # # Interfacing options # if input_interface == 'I2C': if dict_has_value('i2c_location'): new_input.i2c_location = dict_inputs[input_name][ 'i2c_location'][0] # First entry in list if input_interface == 'FTDI': if dict_has_value('ftdi_location'): new_input.ftdi_location = dict_inputs[input_name][ 'ftdi_location'] if input_interface == 'UART': if dict_has_value('uart_location'): new_input.uart_location = dict_inputs[input_name][ 'uart_location'] # UART options if dict_has_value('uart_baud_rate'): new_input.baud_rate = dict_inputs[input_name]['uart_baud_rate'] if dict_has_value('pin_cs'): new_input.pin_cs = dict_inputs[input_name]['pin_cs'] if dict_has_value('pin_miso'): new_input.pin_miso = dict_inputs[input_name]['pin_miso'] if dict_has_value('pin_mosi'): new_input.pin_mosi = dict_inputs[input_name]['pin_mosi'] if dict_has_value('pin_clock'): new_input.pin_clock = dict_inputs[input_name]['pin_clock'] # Bluetooth (BT) options elif input_interface == 'BT': if dict_has_value('bt_location'): if not re.match( "[0-9a-fA-F]{2}([:]?)[0-9a-fA-F]{2}(\\1[0-9a-fA-F]{2}){4}$", dict_inputs[input_name]['bt_location']): messages["error"].append( "Please specify device MAC-Address in format AA:BB:CC:DD:EE:FF" ) else: new_input.location = dict_inputs[input_name][ 'bt_location'] if dict_has_value('bt_adapter'): new_input.bt_adapter = dict_inputs[input_name][ 'bt_adapter'] # GPIO options elif input_interface == 'GPIO': if dict_has_value('gpio_location'): new_input.gpio_location = dict_inputs[input_name][ 'gpio_location'] # Custom location location elif dict_has_value('location'): new_input.location = dict_inputs[input_name]['location'][ 'options'][0][0] # First entry in list # # General options # if dict_has_value('period'): new_input.period = dict_inputs[input_name]['period'] # Server Ping options if dict_has_value('times_check'): new_input.times_check = dict_inputs[input_name]['times_check'] if dict_has_value('deadline'): new_input.deadline = dict_inputs[input_name]['deadline'] if dict_has_value('port'): new_input.port = dict_inputs[input_name]['port'] # Signal options if dict_has_value('weighting'): new_input.weighting = dict_inputs[input_name]['weighting'] if dict_has_value('sample_time'): new_input.sample_time = dict_inputs[input_name]['sample_time'] # Analog-to-digital converter options if dict_has_value('adc_gain'): if len(dict_inputs[input_name]['adc_gain']) == 1: new_input.adc_gain = dict_inputs[input_name]['adc_gain'][0] elif len(dict_inputs[input_name]['adc_gain']) > 1: new_input.adc_gain = dict_inputs[input_name]['adc_gain'][ 0][0] if dict_has_value('adc_resolution'): if len(dict_inputs[input_name]['adc_resolution']) == 1: new_input.adc_resolution = dict_inputs[input_name][ 'adc_resolution'][0] elif len(dict_inputs[input_name]['adc_resolution']) > 1: new_input.adc_resolution = dict_inputs[input_name][ 'adc_resolution'][0][0] if dict_has_value('adc_sample_speed'): if len(dict_inputs[input_name]['adc_sample_speed']) == 1: new_input.adc_sample_speed = dict_inputs[input_name][ 'adc_sample_speed'][0] elif len(dict_inputs[input_name]['adc_sample_speed']) > 1: new_input.adc_sample_speed = dict_inputs[input_name][ 'adc_sample_speed'][0][0] # Linux command if dict_has_value('cmd_command'): new_input.cmd_command = dict_inputs[input_name]['cmd_command'] # Misc options if dict_has_value('resolution'): if len(dict_inputs[input_name]['resolution']) == 1: new_input.resolution = dict_inputs[input_name][ 'resolution'][0] elif len(dict_inputs[input_name]['resolution']) > 1: new_input.resolution = dict_inputs[input_name][ 'resolution'][0][0] if dict_has_value('resolution_2'): if len(dict_inputs[input_name]['resolution_2']) == 1: new_input.resolution_2 = dict_inputs[input_name][ 'resolution_2'][0] elif len(dict_inputs[input_name]['resolution_2']) > 1: new_input.resolution_2 = dict_inputs[input_name][ 'resolution_2'][0][0] if dict_has_value('sensitivity'): if len(dict_inputs[input_name]['sensitivity']) == 1: new_input.sensitivity = dict_inputs[input_name][ 'sensitivity'][0] elif len(dict_inputs[input_name]['sensitivity']) > 1: new_input.sensitivity = dict_inputs[input_name][ 'sensitivity'][0][0] if dict_has_value('thermocouple_type'): if len(dict_inputs[input_name]['thermocouple_type']) == 1: new_input.thermocouple_type = dict_inputs[input_name][ 'thermocouple_type'][0] elif len(dict_inputs[input_name]['thermocouple_type']) > 1: new_input.thermocouple_type = dict_inputs[input_name][ 'thermocouple_type'][0][0] if dict_has_value('sht_voltage'): if len(dict_inputs[input_name]['sht_voltage']) == 1: new_input.sht_voltage = dict_inputs[input_name][ 'sht_voltage'][0] elif len(dict_inputs[input_name]['sht_voltage']) > 1: new_input.sht_voltage = dict_inputs[input_name][ 'sht_voltage'][0][0] if dict_has_value('ref_ohm'): new_input.ref_ohm = dict_inputs[input_name]['ref_ohm'] # # Custom Options # # Generate string to save from custom options messages["error"], custom_options = custom_options_return_json( messages["error"], dict_inputs, device=input_name, use_defaults=True) new_input.custom_options = custom_options # # Execute at Creation # new_input.unique_id = set_uuid() if ('execute_at_creation' in dict_inputs[new_input.device] and not current_app.config['TESTING']): messages["error"], new_input = dict_inputs[ new_input.device]['execute_at_creation']( messages["error"], new_input, dict_inputs[new_input.device]) try: if not messages["error"]: new_input.save() new_input_id = new_input.unique_id # # If there are a variable number of measurements # if ('measurements_variable_amount' in dict_inputs[input_name] and dict_inputs[input_name] ['measurements_variable_amount']): # Add first default measurement with empty unit and measurement new_measurement = DeviceMeasurements() new_measurement.name = "" new_measurement.device_id = new_input.unique_id new_measurement.measurement = "" new_measurement.unit = "" new_measurement.channel = 0 new_measurement.save() # # If measurements defined in the Input Module # elif ('measurements_dict' in dict_inputs[input_name] and dict_inputs[input_name]['measurements_dict']): for each_channel in dict_inputs[input_name][ 'measurements_dict']: measure_info = dict_inputs[input_name][ 'measurements_dict'][each_channel] new_measurement = DeviceMeasurements() if 'name' in measure_info: new_measurement.name = measure_info['name'] new_measurement.device_id = new_input.unique_id new_measurement.measurement = measure_info[ 'measurement'] new_measurement.unit = measure_info['unit'] new_measurement.channel = each_channel new_measurement.save() if 'channels_dict' in dict_inputs[new_input.device]: for each_channel, channel_info in dict_inputs[ new_input.device]['channels_dict'].items(): new_channel = InputChannel() new_channel.channel = each_channel new_channel.input_id = new_input.unique_id # Generate string to save from custom options messages[ "error"], custom_options = custom_channel_options_return_json( messages["error"], dict_inputs, None, new_input.unique_id, each_channel, device=new_input.device, use_defaults=True) new_channel.custom_options = custom_options new_channel.save() messages["success"].append( f"{TRANSLATIONS['add']['title']} {TRANSLATIONS['input']['title']}" ) except sqlalchemy.exc.OperationalError as except_msg: messages["error"].append(except_msg) except sqlalchemy.exc.IntegrityError as except_msg: messages["error"].append(except_msg) else: for field, errors in form_add.errors.items(): for error in errors: messages["error"].append( gettext("Error in the %(field)s field - %(err)s", field=getattr(form_add, field).label.text, err=error)) return messages, dep_name, list_unmet_deps, dep_message, new_input_id
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 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 controller_mod(form_mod, request_form): """Modify a Custom Function""" error = [] action = '{action} {controller}'.format( action=TRANSLATIONS['modify']['title'], controller=TRANSLATIONS['controller']['title']) dict_controllers = parse_function_information() try: channels = FunctionChannel.query.filter( FunctionChannel.function_id == form_mod.function_id.data).all() mod_controller = CustomController.query.filter( CustomController.unique_id == form_mod.function_id.data).first() if mod_controller.is_activated: error.append( gettext("Deactivate controller before modifying its settings")) mod_controller.name = form_mod.name.data mod_controller.log_level_debug = form_mod.log_level_debug.data # Enable/disable Channels measurements = DeviceMeasurements.query.filter( DeviceMeasurements.device_id == form_mod.function_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 # Add or delete channels for variable measurement Inputs if ('measurements_variable_amount' in dict_controllers[mod_controller.device] and dict_controllers[ mod_controller.device]['measurements_variable_amount']): measurements = DeviceMeasurements.query.filter( DeviceMeasurements.device_id == form_mod.function_id.data) if measurements.count() != form_mod.num_channels.data: # Delete measurements/channels if form_mod.num_channels.data < measurements.count(): for index, each_channel in enumerate(measurements.all()): if index + 1 >= measurements.count(): delete_entry_with_id(DeviceMeasurements, each_channel.unique_id) if ('channel_quantity_same_as_measurements' in dict_controllers[mod_controller.device] and dict_controllers[mod_controller.device] ["channel_quantity_same_as_measurements"]): 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( FunctionChannel, each_channel.unique_id) # Add measurements/channels elif form_mod.num_channels.data > measurements.count(): start_number = measurements.count() for index in range(start_number, form_mod.num_channels.data): new_measurement = DeviceMeasurements() new_measurement.name = "" new_measurement.device_id = mod_controller.unique_id new_measurement.measurement = "" new_measurement.unit = "" new_measurement.channel = index new_measurement.save() if ('channel_quantity_same_as_measurements' in dict_controllers[mod_controller.device] and dict_controllers[mod_controller.device] ["channel_quantity_same_as_measurements"]): new_channel = FunctionChannel() new_channel.name = "" new_channel.function_id = mod_controller.unique_id new_channel.channel = index error, custom_options = custom_channel_options_return_json( error, dict_controllers, request_form, mod_controller.unique_id, index, device=mod_controller.device, use_defaults=True) new_channel.custom_options = custom_options new_channel.save() # Parse pre-save custom options for function device and its channels try: custom_options_dict_presave = json.loads( mod_controller.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 function device and its channels error, custom_options_json_postsave = custom_options_return_json( error, dict_controllers, request_form=request_form, device=mod_controller.device, use_defaults=True) 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_controllers, request_form, form_mod.function_id.data, each_channel.channel, device=mod_controller.device, 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_controllers[ mod_controller.device]: # pass custom options to module prior to saving to database (allow_saving, mod_controller, custom_options_dict, custom_options_channels_dict) = dict_controllers[ mod_controller.device]['execute_at_modification']( mod_controller, 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 function 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 function and channels mod_controller.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() 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 controller_mod(form_mod, request_form): """Modify a Custom Function""" error = [] action = '{action} {controller}'.format( action=TRANSLATIONS['modify']['title'], controller=TRANSLATIONS['controller']['title']) dict_controllers = parse_function_information() try: mod_controller = CustomController.query.filter( CustomController.unique_id == form_mod.function_id.data).first() if mod_controller.is_activated: error.append( gettext("Deactivate controller before modifying its settings")) mod_controller.name = form_mod.name.data mod_controller.log_level_debug = form_mod.log_level_debug.data # Enable/disable Channels measurements = DeviceMeasurements.query.filter( DeviceMeasurements.device_id == form_mod.function_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 channels = FunctionChannel.query.filter( FunctionChannel.function_id == form_mod.function_id.data) # Add or delete channels for variable measurement Inputs if ('measurements_variable_amount' in dict_controllers[mod_controller.device] and dict_controllers[ mod_controller.device]['measurements_variable_amount']): measurements = DeviceMeasurements.query.filter( DeviceMeasurements.device_id == form_mod.function_id.data) if measurements.count() != form_mod.num_channels.data: # Delete measurements/channels if form_mod.num_channels.data < measurements.count(): for index, each_channel in enumerate(measurements.all()): if index + 1 >= measurements.count(): delete_entry_with_id(DeviceMeasurements, each_channel.unique_id) if ('channel_quantity_same_as_measurements' in dict_controllers[mod_controller.device] and dict_controllers[mod_controller.device] ["channel_quantity_same_as_measurements"]): 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( FunctionChannel, each_channel.unique_id) # Add measurements/channels elif form_mod.num_channels.data > measurements.count(): start_number = measurements.count() for index in range(start_number, form_mod.num_channels.data): new_measurement = DeviceMeasurements() new_measurement.name = "" new_measurement.device_id = mod_controller.unique_id new_measurement.measurement = "" new_measurement.unit = "" new_measurement.channel = index new_measurement.save() if ('channel_quantity_same_as_measurements' in dict_controllers[mod_controller.device] and dict_controllers[mod_controller.device] ["channel_quantity_same_as_measurements"]): new_channel = FunctionChannel() new_channel.name = "" new_channel.function_id = mod_controller.unique_id new_measurement.channel = index error, custom_options = custom_channel_options_return_json( error, dict_controllers, request_form, mod_controller.unique_id, index, device=mod_controller.device, use_defaults=True) new_channel.custom_options = custom_options new_channel.save() # Generate string to save from custom options error, custom_options = custom_options_return_json( error, dict_controllers, request_form=request_form, device=mod_controller.device, use_defaults=True) mod_controller.custom_options = custom_options 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 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 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