def initialize_variables(self): function = db_retrieve_table_daemon(CustomController, unique_id=self.unique_id) self.log_level_debug = function.log_level_debug self.set_log_level_debug(self.log_level_debug) self.dict_function = parse_function_information() self.sample_rate = db_retrieve_table_daemon( Misc, entry='first').sample_rate_controller_function self.device_measurements = db_retrieve_table_daemon( DeviceMeasurements).filter( DeviceMeasurements.device_id == self.unique_id) self.conversions = db_retrieve_table_daemon(Conversion) self.function = function self.unique_id = function.unique_id self.function_name = function.name self.device = function.device if self.device in self.dict_function: function_loaded = load_module_from_file( self.dict_function[self.device]['file_path'], 'function') self.run_function = function_loaded.CustomModule(self.function) else: self.logger.debug( "Device '{device}' not recognized".format(device=self.device)) raise Exception("'{device}' is not a valid device type.".format( device=self.device))
def all_outputs_initialize(self, outputs): """ Initialize all output variables and classes """ self.dict_outputs = parse_output_information() self.output_types = output_types() for each_output in outputs: try: self.output_type[each_output.unique_id] = each_output.output_type self.output_unique_id[each_output.unique_id] = {} if 'channels_dict' in self.dict_outputs[each_output.output_type]: for each_channel in self.dict_outputs[each_output.output_type]['channels_dict']: self.output_unique_id[each_output.unique_id][each_channel] = None else: self.output_unique_id[each_output.unique_id][0] = None if each_output.output_type in self.dict_outputs: output_loaded = load_module_from_file( self.dict_outputs[each_output.output_type]['file_path'], 'outputs') self.output[each_output.unique_id] = output_loaded.OutputModule(each_output) self.output[each_output.unique_id].setup_output() self.output[each_output.unique_id].init_post() self.logger.debug("{id} ({name}) Initialized".format( id=each_output.unique_id.split('-')[0], name=each_output.name)) except: self.logger.exception("Could not initialize output {}".format( each_output.unique_id))
def trigger_action(dict_actions, action_id, value=None, message='', debug=False): """ Trigger individual action If single_action == False, message, note_tags, email_recipients, attachment_file, and attachment_type are returned and may be passed back to this function in order to append to those lists. :param dict_actions: dict of function action information :param action_id: unique_id of action :param value: a variable to be sent to the action :param message: message string to append to that will be sent back :param debug: determine if logging level should be DEBUG :return: message or (message, note_tags, email_recipients, attachment_file, attachment_type) """ action = db_retrieve_table_daemon(Actions, unique_id=action_id) if not action: message += 'Error: Action with ID {} not found!'.format(action_id) return message logger_actions = logging.getLogger( "mycodo.trigger_action_{id}".format(id=action.unique_id.split('-')[0])) if debug: logger_actions.setLevel(logging.DEBUG) else: logger_actions.setLevel(logging.INFO) # Set up function action to run from standalone action module file run_function_action = None if action.action_type in dict_actions: dict_vars = {"value": value} message += "\n[Action {id}, {name}]:".format( id=action.unique_id.split('-')[0], name=dict_actions[action.action_type]['name']) try: function_action_loaded, status = load_module_from_file( dict_actions[action.action_type]['file_path'], 'function_action') if function_action_loaded: run_function_action = function_action_loaded.ActionModule( action) message = run_function_action.run_action(message, dict_vars) except: message += " Exception executing action: {}".format( traceback.print_exc()) logger_actions.debug("Message: {}".format(message)) return message
def add_mod_output(self, output_id): """ Add or modify local dictionary of output settings form SQL database When a output is added or modified while the output controller is running, these local variables need to also be modified to maintain consistency between the SQL database and running controller. :param output_id: Unique ID for each output :type output_id: str :return: 0 for success, 1 for fail, with success for fail message :rtype: int, str """ try: self.dict_outputs = parse_output_information() output = db_retrieve_table_daemon(Output, unique_id=output_id) self.output_type[output_id] = output.output_type self.output_unique_id[output_id] = {} if 'channels_dict' in self.dict_outputs[output.output_type]: for each_channel in self.dict_outputs[ output.output_type]['channels_dict']: self.output_unique_id[output_id][each_channel] = None else: self.output_unique_id[output_id][0] = None if self.output_type[output_id] in self.dict_outputs: if ('no_run' in self.dict_outputs[output.output_type] and self.dict_outputs[output.output_type]['no_run']): pass else: # Try to stop the output if output_id in self.output: try: self.output[output_id].stop_output() except Exception: self.logger.exception("Stopping output") output_loaded, status = load_module_from_file( self.dict_outputs[self.output_type[output_id]] ['file_path'], 'outputs') if output_loaded: self.output[output_id] = output_loaded.OutputModule( output) self.output[output_id].try_initialize() self.output[output_id].init_post() return 0, "add_mod_output() Success" except Exception as e: return 1, f"add_mod_output() Error: {output_id}: {e}"
def settings_input(): """Display measurement settings.""" if not utils_general.user_has_permission('view_settings'): return redirect(url_for('routes_general.home')) form_input = forms_settings.Input() form_input_delete = forms_settings.InputDel() dict_measurements = add_custom_measurements(Measurement.query.all()) dict_units = add_custom_units(Unit.query.all()) # Get list of custom inputs excluded_files = ['__init__.py', '__pycache__'] if request.method == 'POST': if not utils_general.user_has_permission('edit_controllers'): return redirect(url_for('routes_general.home')) if form_input.import_input_upload.data: utils_settings.settings_input_import(form_input) elif form_input_delete.delete_input.data: utils_settings.settings_input_delete(form_input_delete) return redirect(url_for('routes_settings.settings_input')) dict_inputs = {} for each_file in os.listdir(PATH_INPUTS_CUSTOM): if each_file not in excluded_files: try: full_path_file = os.path.join(PATH_INPUTS_CUSTOM, each_file) input_info, status = load_module_from_file( full_path_file, 'inputs') if input_info: dict_inputs[input_info. INPUT_INFORMATION['input_name_unique']] = {} dict_inputs[input_info.INPUT_INFORMATION['input_name_unique']]['input_name'] = \ input_info.INPUT_INFORMATION['input_name'] dict_inputs[input_info.INPUT_INFORMATION['input_name_unique']]['input_manufacturer'] = \ input_info.INPUT_INFORMATION['input_manufacturer'] dict_inputs[input_info.INPUT_INFORMATION['input_name_unique']]['measurements_name'] = \ input_info.INPUT_INFORMATION['measurements_name'] except: pass return render_template('settings/input.html', dict_inputs=dict_inputs, dict_measurements=dict_measurements, dict_units=dict_units, form_input=form_input, form_input_delete=form_input_delete)
def all_outputs_initialize(self, outputs): """ Initialize all output variables and classes """ self.dict_outputs = parse_output_information() self.output_types = output_types() for each_output in outputs: try: self.output_unique_id[ each_output.unique_id] = each_output.unique_id self.output_type[ each_output.unique_id] = each_output.output_type self.output_name[each_output.unique_id] = each_output.name self.output_amps[each_output.unique_id] = each_output.amps self.output_state_startup[ each_output.unique_id] = each_output.state_startup self.output_startup_value[ each_output.unique_id] = each_output.startup_value self.output_state_shutdown[ each_output.unique_id] = each_output.state_shutdown self.output_shutdown_value[ each_output.unique_id] = each_output.shutdown_value self.output_on_until[ each_output.unique_id] = datetime.datetime.now() self.output_last_duration[each_output.unique_id] = 0 self.output_on_duration[each_output.unique_id] = False self.output_off_triggered[each_output.unique_id] = False self.output_time_turned_on[each_output.unique_id] = None self.output_force_command[ each_output.unique_id] = each_output.force_command self.trigger_functions_at_start[ each_output. unique_id] = each_output.trigger_functions_at_start if each_output.output_type in self.dict_outputs: output_loaded = load_module_from_file( self.dict_outputs[each_output.output_type] ['file_path'], 'outputs') self.output[ each_output.unique_id] = output_loaded.OutputModule( each_output) self.output[each_output.unique_id].setup_output() self.output[each_output.unique_id].init_post() self.logger.debug("{id} ({name}) Initialized".format( id=each_output.unique_id.split('-')[0], name=each_output.name)) except: self.logger.exception("Could not initialize output {}".format( each_output.unique_id))
def all_outputs_initialize(self, outputs): """Initialize all output variables and classes.""" self.dict_outputs = parse_output_information() self.output_types = output_types() for each_output in outputs: if each_output.output_type not in self.dict_outputs: self.logger.error( f"'{each_output.output_type}' not found in Output dictionary. Not starting Output." ) continue try: self.output_type[ each_output.unique_id] = each_output.output_type self.output_unique_id[each_output.unique_id] = {} if 'channels_dict' in self.dict_outputs[ each_output.output_type]: for each_channel in self.dict_outputs[ each_output.output_type]['channels_dict']: self.output_unique_id[ each_output.unique_id][each_channel] = None else: self.output_unique_id[each_output.unique_id][0] = None if each_output.output_type in self.dict_outputs: if ('no_run' in self.dict_outputs[each_output.output_type] and self.dict_outputs[ each_output.output_type]['no_run']): continue output_loaded, status = load_module_from_file( self.dict_outputs[each_output.output_type] ['file_path'], 'outputs') if output_loaded: self.output[each_output. unique_id] = output_loaded.OutputModule( each_output) self.output[each_output.unique_id].try_initialize() self.output[each_output.unique_id].init_post() self.logger.debug( f"{each_output.unique_id.split('-')[0]} ({each_output.name}) Initialized" ) except: self.logger.exception( f"Could not initialize output {each_output.unique_id}")
def add_mod_output(self, output_id): """ Add or modify local dictionary of output settings form SQL database When a output is added or modified while the output controller is running, these local variables need to also be modified to maintain consistency between the SQL database and running controller. :param output_id: Unique ID for each output :type output_id: str :return: 0 for success, 1 for fail, with success for fail message :rtype: int, str """ try: self.dict_outputs = parse_output_information() output = db_retrieve_table_daemon(Output, unique_id=output_id) self.output_unique_id[output_id] = output.unique_id self.output_type[output_id] = output.output_type self.output_name[output_id] = output.name self.output_amps[output_id] = output.amps self.output_state_startup[output_id] = output.state_startup self.output_startup_value[output_id] = output.startup_value self.output_state_shutdown[output_id] = output.state_shutdown self.output_shutdown_value[output_id] = output.shutdown_value self.output_on_until[output_id] = datetime.datetime.now() self.output_time_turned_on[output_id] = None self.output_last_duration[output_id] = 0 self.output_on_duration[output_id] = False self.output_off_triggered[output_id] = False self.output_force_command[output_id] = output.force_command self.trigger_functions_at_start[ output_id] = output.trigger_functions_at_start if self.output_type[output_id] in self.dict_outputs: output_loaded = load_module_from_file( self.dict_outputs[self.output_type[output_id]] ['file_path'], 'outputs') self.output[output_id] = output_loaded.OutputModule(output) self.output[output_id].setup_output() self.output[output_id].init_post() return 0, "add_mod_output() Success" except Exception as e: return 1, "add_mod_output() Error: {id}: {e}".format(id=output_id, e=e)
def settings_controller(): """ Display controller settings """ if not utils_general.user_has_permission('view_settings'): return redirect(url_for('routes_general.home')) form_controller = forms_settings.Controller() form_controller_delete = forms_settings.ControllerDel() # Get list of custom controllers excluded_files = ['__init__.py', '__pycache__'] if request.method == 'POST': if not utils_general.user_has_permission('edit_controllers'): return redirect(url_for('routes_general.home')) if form_controller.import_controller_upload.data: utils_settings.settings_controller_import(form_controller) elif form_controller_delete.delete_controller.data: utils_settings.settings_controller_delete(form_controller_delete) return redirect(url_for('routes_settings.settings_controller')) dict_controllers = {} for each_file in os.listdir(PATH_CONTROLLERS_CUSTOM): if each_file not in excluded_files: try: full_path_file = os.path.join(PATH_CONTROLLERS_CUSTOM, each_file) controller_info = load_module_from_file( full_path_file, 'controllers') dict_controllers[controller_info.CONTROLLER_INFORMATION[ 'controller_name_unique']] = {} dict_controllers[controller_info.CONTROLLER_INFORMATION['controller_name_unique']]['controller_name'] = \ controller_info.CONTROLLER_INFORMATION['controller_name'] except: pass # dict_controllers = parse_controller_information() return render_template('settings/controller.html', dict_controllers=dict_controllers, form_controller=form_controller, form_controller_delete=form_controller_delete)
def settings_action(): """Display action settings.""" if not utils_general.user_has_permission('view_settings'): return redirect(url_for('routes_general.home')) form_action = forms_settings.Action() form_action_delete = forms_settings.ActionDel() # Get list of custom functions excluded_files = ['__init__.py', '__pycache__'] if request.method == 'POST': if not utils_general.user_has_permission('edit_controllers'): return redirect(url_for('routes_general.home')) if form_action.import_action_upload.data: utils_settings.settings_action_import(form_action) elif form_action_delete.delete_action.data: utils_settings.settings_action_delete(form_action_delete) return redirect(url_for('routes_settings.settings_action')) dict_actions = {} for each_file in os.listdir(PATH_ACTIONS_CUSTOM): if each_file not in excluded_files: try: full_path_file = os.path.join(PATH_ACTIONS_CUSTOM, each_file) action_info, status = load_module_from_file( full_path_file, 'actions') if action_info: func_info = action_info.ACTION_INFORMATION dict_actions[func_info['name_unique']] = {} dict_actions[ func_info['name_unique']]['name'] = func_info['name'] except: pass return render_template('settings/action.html', dict_actions=dict_actions, form_action=form_action, form_action_delete=form_action_delete)
def widget_add_refresh(self, unique_id): self.dict_widgets = parse_widget_information() widget = db_retrieve_table_daemon(Widget, unique_id=unique_id) if ('no_class' in self.dict_widgets[widget.graph_type] and self.dict_widgets[widget.graph_type]['no_class']): return try: timer = timeit.default_timer() input_loaded = load_module_from_file( self.dict_widgets[widget.graph_type]['file_path'], 'widgets') widget = db_retrieve_table_daemon(Widget, unique_id=unique_id) self.widget_loaded[unique_id] = input_loaded.WidgetModule(widget) self.widget_loaded[unique_id].initialize_variables() self.widget_ready[unique_id] = True self.logger.info( "Widget {id} created/refreshed in {time:.1f} ms".format( id=widget.unique_id.split('-')[0], time=(timeit.default_timer() - timer) * 1000)) except Exception: self.logger.exception("Widget create/refresh")
def initialize_variables(self): function = db_retrieve_table_daemon(CustomController, unique_id=self.unique_id) self.log_level_debug = function.log_level_debug self.set_log_level_debug(self.log_level_debug) self.dict_function = parse_function_information() self.sample_rate = db_retrieve_table_daemon( Misc, entry='first').sample_rate_controller_function self.device_measurements = db_retrieve_table_daemon( DeviceMeasurements).filter( DeviceMeasurements.device_id == self.unique_id) self.conversions = db_retrieve_table_daemon(Conversion) self.function = function self.unique_id = function.unique_id self.function_name = function.name self.device = function.device if self.device in self.dict_function: function_loaded, status = load_module_from_file( self.dict_function[self.device]['file_path'], 'function') if function_loaded: self.run_function = function_loaded.CustomModule(self.function) self.ready.set() self.running = True else: self.ready.set() self.running = False self.logger.error( f"'{self.device}' is not a valid device type. Deactivating controller." ) return
def parse_widget_information(exclude_custom=False): """Parses the variables assigned in each Widget and return a dictionary of IDs and values""" def dict_has_value(dict_inp, widget_cus, key, force_type=None): if (key in widget_cus.WIDGET_INFORMATION and (widget_cus.WIDGET_INFORMATION[key] or widget_cus.WIDGET_INFORMATION[key] == 0)): if force_type == 'list': if isinstance(widget_cus.WIDGET_INFORMATION[key], list): dict_inp[widget_cus.WIDGET_INFORMATION['widget_name_unique']][key] = \ widget_cus.WIDGET_INFORMATION[key] else: dict_inp[widget_cus.WIDGET_INFORMATION['widget_name_unique']][key] = \ [widget_cus.WIDGET_INFORMATION[key]] else: dict_inp[widget_cus.WIDGET_INFORMATION['widget_name_unique']][key] = \ widget_cus.WIDGET_INFORMATION[key] return dict_inp excluded_files = [ '__init__.py', '__pycache__', 'base_widget.py', 'custom_widgets', 'examples', 'tmp_widgets' ] widget_paths = [PATH_WIDGETS] if not exclude_custom: widget_paths.append(PATH_WIDGETS_CUSTOM) dict_widgets = {} for each_path in widget_paths: real_path = os.path.realpath(each_path) for each_file in os.listdir(real_path): if each_file in excluded_files: continue full_path = "{}/{}".format(real_path, each_file) widget_custom = load_module_from_file(full_path, 'widgets') if not hasattr(widget_custom, 'WIDGET_INFORMATION'): continue # Populate dictionary of widget information if widget_custom.WIDGET_INFORMATION[ 'widget_name_unique'] in dict_widgets: logger.error( "Error: Cannot add widget modules because it does not have a unique name: {name}" .format(name=widget_custom. WIDGET_INFORMATION['widget_name_unique'])) else: dict_widgets[widget_custom. WIDGET_INFORMATION['widget_name_unique']] = {} dict_widgets[widget_custom.WIDGET_INFORMATION[ 'widget_name_unique']]['file_path'] = full_path dict_widgets = dict_has_value(dict_widgets, widget_custom, 'widget_name') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'widget_library') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'no_class') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'widget_height') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'widget_width') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'listener') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'message') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'url_datasheet', force_type='list') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'url_manufacturer', force_type='list') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'url_product_purchase', force_type='list') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'url_additional', force_type='list') # Dependencies dict_widgets = dict_has_value(dict_widgets, widget_custom, 'dependencies_module') # Which form options to display and whether each option is enabled dict_widgets = dict_has_value(dict_widgets, widget_custom, 'options_enabled') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'options_disabled') # Misc dict_widgets = dict_has_value(dict_widgets, widget_custom, 'period') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'execute_at_creation') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'execute_at_modification') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'execute_at_deletion') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'generate_page_variables') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'custom_options_message') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'custom_options') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'custom_actions_message') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'custom_actions') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'widget_dashboard_head') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'widget_dashboard_title_bar') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'widget_dashboard_body') dict_widgets = dict_has_value( dict_widgets, widget_custom, 'widget_dashboard_configure_options') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'widget_dashboard_js') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'widget_dashboard_js_ready') dict_widgets = dict_has_value(dict_widgets, widget_custom, 'widget_dashboard_js_ready_end') return dict_widgets
def parse_output_information(exclude_custom=False): """Parses the variables assigned in each Output and return a dictionary of IDs and values""" def dict_has_value(dict_inp, output_cus, key, force_type=None): if (key in output_cus.OUTPUT_INFORMATION and (output_cus.OUTPUT_INFORMATION[key] is not None)): if force_type == 'list': if isinstance(output_cus.OUTPUT_INFORMATION[key], list): dict_inp[output_cus.OUTPUT_INFORMATION['output_name_unique']][key] = \ output_cus.OUTPUT_INFORMATION[key] else: dict_inp[output_cus.OUTPUT_INFORMATION['output_name_unique']][key] = \ [output_cus.OUTPUT_INFORMATION[key]] else: dict_inp[output_cus.OUTPUT_INFORMATION['output_name_unique']][key] = \ output_cus.OUTPUT_INFORMATION[key] return dict_inp excluded_files = [ '__init__.py', '__pycache__', 'base_output.py', 'custom_outputs', 'examples', 'scripts', 'tmp_outputs' ] output_paths = [PATH_OUTPUTS] if not exclude_custom: output_paths.append(PATH_OUTPUTS_CUSTOM) dict_outputs = {} for each_path in output_paths: real_path = os.path.realpath(each_path) for each_file in os.listdir(real_path): if each_file in excluded_files: continue full_path = "{}/{}".format(real_path, each_file) output_custom = load_module_from_file(full_path, 'outputs') if not hasattr(output_custom, 'OUTPUT_INFORMATION'): continue # Populate dictionary of output information if output_custom.OUTPUT_INFORMATION['output_name_unique'] in dict_outputs: logger.error("Error: Cannot add output modules because it does not have a unique name: {name}".format( name=output_custom.OUTPUT_INFORMATION['output_name_unique'])) else: dict_outputs[output_custom.OUTPUT_INFORMATION['output_name_unique']] = {} dict_outputs[output_custom.OUTPUT_INFORMATION['output_name_unique']]['file_path'] = full_path dict_outputs = dict_has_value(dict_outputs, output_custom, 'output_name') dict_outputs = dict_has_value(dict_outputs, output_custom, 'output_manufacturer') dict_outputs = dict_has_value(dict_outputs, output_custom, 'output_library') dict_outputs = dict_has_value(dict_outputs, output_custom, 'measurements_dict') dict_outputs = dict_has_value(dict_outputs, output_custom, 'channels_dict') dict_outputs = dict_has_value(dict_outputs, output_custom, 'on_state_internally_handled') dict_outputs = dict_has_value(dict_outputs, output_custom, 'output_types') dict_outputs = dict_has_value(dict_outputs, output_custom, 'message') dict_outputs = dict_has_value(dict_outputs, output_custom, 'url_datasheet', force_type='list') dict_outputs = dict_has_value(dict_outputs, output_custom, 'url_manufacturer', force_type='list') dict_outputs = dict_has_value(dict_outputs, output_custom, 'url_product_purchase', force_type='list') dict_outputs = dict_has_value(dict_outputs, output_custom, 'url_additional', force_type='list') # Dependencies dict_outputs = dict_has_value(dict_outputs, output_custom, 'dependencies_module') # Interface dict_outputs = dict_has_value(dict_outputs, output_custom, 'interfaces') # Nonstandard (I2C, UART, etc.) location dict_outputs = dict_has_value(dict_outputs, output_custom, 'location') # I2C dict_outputs = dict_has_value(dict_outputs, output_custom, 'i2c_location') dict_outputs = dict_has_value(dict_outputs, output_custom, 'i2c_address_editable') dict_outputs = dict_has_value(dict_outputs, output_custom, 'i2c_address_default') # FTDI dict_outputs = dict_has_value(dict_outputs, output_custom, 'ftdi_location') # UART dict_outputs = dict_has_value(dict_outputs, output_custom, 'uart_location') dict_outputs = dict_has_value(dict_outputs, output_custom, 'uart_baud_rate') dict_outputs = dict_has_value(dict_outputs, output_custom, 'pin_cs') dict_outputs = dict_has_value(dict_outputs, output_custom, 'pin_miso') dict_outputs = dict_has_value(dict_outputs, output_custom, 'pin_mosi') dict_outputs = dict_has_value(dict_outputs, output_custom, 'pin_clock') # Bluetooth (BT) dict_outputs = dict_has_value(dict_outputs, output_custom, 'bt_location') dict_outputs = dict_has_value(dict_outputs, output_custom, 'bt_adapter') # Which form options to display and whether each option is enabled dict_outputs = dict_has_value(dict_outputs, output_custom, 'options_enabled') dict_outputs = dict_has_value(dict_outputs, output_custom, 'options_disabled') dict_outputs = dict_has_value(dict_outputs, output_custom, 'custom_options_message') dict_outputs = dict_has_value(dict_outputs, output_custom, 'custom_options') dict_outputs = dict_has_value(dict_outputs, output_custom, 'custom_channel_options_message') dict_outputs = dict_has_value(dict_outputs, output_custom, 'custom_channel_options') dict_outputs = dict_has_value(dict_outputs, output_custom, 'custom_actions_message') dict_outputs = dict_has_value(dict_outputs, output_custom, 'custom_actions') return dict_outputs
def initialize_variables(self): self.dict_inputs = parse_input_information() self.sample_rate = db_retrieve_table_daemon( Misc, entry='first').sample_rate_controller_input input_dev = db_retrieve_table_daemon(Input, unique_id=self.unique_id) self.device_measurements = db_retrieve_table_daemon( DeviceMeasurements).filter( DeviceMeasurements.device_id == self.unique_id) self.conversions = db_retrieve_table_daemon(Conversion) self.input_dev = input_dev self.input_name = input_dev.name self.unique_id = input_dev.unique_id self.log_level_debug = input_dev.log_level_debug self.gpio_location = input_dev.gpio_location self.device = input_dev.device self.interface = input_dev.interface self.period = input_dev.period self.start_offset = input_dev.start_offset # Edge detection self.switch_edge = input_dev.switch_edge self.switch_bouncetime = input_dev.switch_bouncetime self.switch_reset_period = input_dev.switch_reset_period # Pre-Output: Activates prior to input measurement self.pre_output_id = input_dev.pre_output_id self.pre_output_duration = input_dev.pre_output_duration self.pre_output_during_measure = input_dev.pre_output_during_measure self.pre_output_setup = False self.last_measurement = 0 self.next_measurement = time.time() + self.start_offset self.get_new_measurement = False self.trigger_cond = False self.measurement_acquired = False self.pre_output_activated = False self.pre_output_locked = False self.pre_output_timer = time.time() self.set_log_level_debug(self.log_level_debug) # Check if Pre-Output ID actually exists output = db_retrieve_table_daemon(Output, entry='all') for each_output in output: if (each_output.unique_id == self.pre_output_id and self.pre_output_duration): self.pre_output_setup = True smtp = db_retrieve_table_daemon(SMTP, entry='first') self.smtp_max_count = smtp.hourly_max self.email_count = 0 self.allowed_to_send_notice = True # Set up input lock self.input_lock = None self.lock_file = '/var/lock/input_pre_output_{id}'.format( id=self.pre_output_id) # Convert string I2C address to base-16 int if self.interface == 'I2C': self.i2c_address = int(str(self.input_dev.i2c_location), 16) # Set up edge detection of a GPIO pin if self.device == 'EDGE': if self.switch_edge == 'rising': self.switch_edge_gpio = GPIO.RISING elif self.switch_edge == 'falling': self.switch_edge_gpio = GPIO.FALLING else: self.switch_edge_gpio = GPIO.BOTH self.device_recognized = True if self.device in self.dict_inputs: input_loaded = load_module_from_file( self.dict_inputs[self.device]['file_path'], 'inputs') if self.device == 'EDGE': # Edge detection handled internally, no module to load self.measure_input = None else: self.measure_input = input_loaded.InputModule(self.input_dev) else: self.device_recognized = False self.logger.debug( "Device '{device}' not recognized".format(device=self.device)) raise Exception("'{device}' is not a valid device type.".format( device=self.device)) self.edge_reset_timer = time.time() self.input_timer = time.time() self.lastUpdate = None # Set up edge detection if self.device == 'EDGE': GPIO.setmode(GPIO.BCM) GPIO.setup(int(self.gpio_location), GPIO.IN) GPIO.add_event_detect(int(self.gpio_location), self.switch_edge_gpio, callback=self.edge_detected, bouncetime=self.switch_bouncetime) # Set up MQTT listener elif ('listener' in self.dict_inputs[self.device] and self.dict_inputs[self.device]['listener']): input_listener = threading.Thread( target=self.measure_input.listener()) input_listener.daemon = True input_listener.start()
def initialize_variables(self): input_dev = db_retrieve_table_daemon(Input, unique_id=self.unique_id) self.log_level_debug = input_dev.log_level_debug self.set_log_level_debug(self.log_level_debug) self.dict_inputs = parse_input_information() self.sample_rate = db_retrieve_table_daemon( Misc, entry='first').sample_rate_controller_input self.device_measurements = db_retrieve_table_daemon( DeviceMeasurements).filter( DeviceMeasurements.device_id == self.unique_id) self.conversions = db_retrieve_table_daemon(Conversion) self.input_dev = input_dev self.input_name = input_dev.name self.unique_id = input_dev.unique_id self.gpio_location = input_dev.gpio_location self.device = input_dev.device self.interface = input_dev.interface self.period = input_dev.period self.start_offset = input_dev.start_offset # Pre-Output (activates output prior to and/or during input measurement) self.pre_output_setup = False if self.input_dev.pre_output_id and "," in self.input_dev.pre_output_id: try: self.pre_output_id = input_dev.pre_output_id.split(",")[0] self.pre_output_channel_id = input_dev.pre_output_id.split( ",")[1] self.pre_output_duration = input_dev.pre_output_duration self.pre_output_during_measure = input_dev.pre_output_during_measure self.pre_output_activated = False self.pre_output_timer = time.time() self.pre_output_lock_file = '/var/lock/input_pre_output_{id}_{ch}'.format( id=self.pre_output_id, ch=self.pre_output_channel_id) # Check if Pre Output and channel IDs exists output = db_retrieve_table_daemon(Output, unique_id=self.pre_output_id) output_channel = db_retrieve_table_daemon( OutputChannel, unique_id=self.pre_output_channel_id) if output and output_channel and self.pre_output_duration: self.pre_output_channel = output_channel.channel self.logger.debug("Pre output successfully set up") self.pre_output_setup = True except: self.logger.exception("Could not set up pre-output") self.last_measurement = 0 self.next_measurement = time.time() + self.start_offset self.get_new_measurement = False self.trigger_cond = False self.measurement_acquired = False smtp = db_retrieve_table_daemon(SMTP, entry='first') self.smtp_max_count = smtp.hourly_max self.email_count = 0 self.allowed_to_send_notice = True # Convert string I2C address to base-16 int if self.interface == 'I2C' and self.input_dev.i2c_location: self.i2c_address = int(str(self.input_dev.i2c_location), 16) self.device_recognized = True if self.device in self.dict_inputs: input_loaded = load_module_from_file( self.dict_inputs[self.device]['file_path'], 'inputs') self.measure_input = input_loaded.InputModule(self.input_dev) else: self.device_recognized = False self.logger.debug( "Device '{device}' not recognized".format(device=self.device)) raise Exception("'{device}' is not a valid device type.".format( device=self.device)) self.input_timer = time.time() self.lastUpdate = None # Set up listener (e.g. MQTT, EDGE) if ('listener' in self.dict_inputs[self.device] and self.dict_inputs[self.device]['listener']): self.logger.debug( "Detected as listener. Starting listener thread.") input_listener = threading.Thread( target=self.measure_input.listener()) input_listener.daemon = True input_listener.start()
def parse_function_information(exclude_custom=False): """Parses the variables assigned in each Function and return a dictionary of IDs and values""" def dict_has_value(dict_inp, controller_cus, key): if (key in controller_cus.FUNCTION_INFORMATION and (controller_cus.FUNCTION_INFORMATION[key] or controller_cus.FUNCTION_INFORMATION[key] == 0)): dict_inp[controller_cus.FUNCTION_INFORMATION['function_name_unique']][key] = \ controller_cus.FUNCTION_INFORMATION[key] return dict_inp excluded_files = [ '__init__.py', '__pycache__', 'base_function.py', 'custom_functions', 'examples', 'scripts', 'tmp_functions' ] function_paths = [PATH_FUNCTIONS] if not exclude_custom: function_paths.append(PATH_FUNCTIONS_CUSTOM) dict_controllers = {} for each_path in function_paths: real_path = os.path.realpath(each_path) for each_file in os.listdir(real_path): if each_file in excluded_files: continue full_path = "{}/{}".format(real_path, each_file) function_custom = load_module_from_file(full_path, 'functions') if not hasattr(function_custom, 'FUNCTION_INFORMATION'): continue # Populate dictionary of function information if function_custom.FUNCTION_INFORMATION[ 'function_name_unique'] in dict_controllers: logger.error( "Error: Cannot add controller modules because it does not have a unique name: {name}" .format(name=function_custom. FUNCTION_INFORMATION['function_name_unique'])) else: dict_controllers[function_custom.FUNCTION_INFORMATION[ 'function_name_unique']] = {} dict_controllers[function_custom.FUNCTION_INFORMATION[ 'function_name_unique']]['file_path'] = full_path dict_controllers = dict_has_value(dict_controllers, function_custom, 'function_name') dict_controllers = dict_has_value(dict_controllers, function_custom, 'message') dict_controllers = dict_has_value(dict_controllers, function_custom, 'options_enabled') dict_controllers = dict_has_value(dict_controllers, function_custom, 'options_disabled') dict_controllers = dict_has_value(dict_controllers, function_custom, 'dependencies_module') dict_controllers = dict_has_value(dict_controllers, function_custom, 'custom_options') return dict_controllers
def parse_controller_information(): """Parses the variables assigned in each Controller and return a dictionary of IDs and values""" def dict_has_value(dict_inp, controller_cus, key): if (key in controller_cus.CONTROLLER_INFORMATION and (controller_cus.CONTROLLER_INFORMATION[key] or controller_cus.CONTROLLER_INFORMATION[key] == 0)): dict_inp[controller_cus.CONTROLLER_INFORMATION['controller_name_unique']][key] = \ controller_cus.CONTROLLER_INFORMATION[key] return dict_inp excluded_files = [ '__init__.py', '__pycache__', 'base_controller.py', 'custom_controllers', 'examples', 'scripts', 'tmp_controllers' ] controller_paths = [PATH_CONTROLLERS_CUSTOM] dict_controllers = {} for each_path in controller_paths: real_path = os.path.realpath(each_path) for each_file in os.listdir(real_path): skip_file = False if each_file in excluded_files: skip_file = True if not skip_file: full_path = "{}/{}".format(real_path, each_file) controller_custom = load_module_from_file(full_path, 'controllers') if not hasattr(controller_custom, 'CONTROLLER_INFORMATION'): skip_file = True if not skip_file: # logger.info("Found controller: {}, {}".format( # controller_custom.CONTROLLER_INFORMATION['controller_name_unique'], # full_path)) # Populate dictionary of controller information if controller_custom.CONTROLLER_INFORMATION['controller_name_unique'] in dict_controllers: logger.error("Error: Cannot add controller modules because it does not have a unique name: {name}".format( name=controller_custom.CONTROLLER_INFORMATION['controller_name_unique'])) else: dict_controllers[controller_custom.CONTROLLER_INFORMATION['controller_name_unique']] = {} dict_controllers[controller_custom.CONTROLLER_INFORMATION['controller_name_unique']]['file_path'] = full_path dict_controllers = dict_has_value(dict_controllers, controller_custom, 'controller_name') dict_controllers = dict_has_value(dict_controllers, controller_custom, 'message') dict_controllers = dict_has_value(dict_controllers, controller_custom, 'options_enabled') dict_controllers = dict_has_value(dict_controllers, controller_custom, 'options_disabled') # Dependencies dict_controllers = dict_has_value(dict_controllers, controller_custom, 'dependencies_module') dict_controllers = dict_has_value(dict_controllers, controller_custom, 'custom_options') return dict_controllers
def parse_input_information(): """Parses the variables assigned in each Input and return a dictionary of IDs and values""" def dict_has_value(dict_inp, input_cus, key): if (key in input_cus.INPUT_INFORMATION and (input_cus.INPUT_INFORMATION[key] or input_cus.INPUT_INFORMATION[key] == 0)): dict_inp[input_cus.INPUT_INFORMATION['input_name_unique']][key] = \ input_cus.INPUT_INFORMATION[key] return dict_inp excluded_files = [ '__init__.py', '__pycache__', 'base_input.py', 'custom_inputs', 'examples', 'scripts', 'tmp_inputs', 'sensorutils.py' ] input_paths = [PATH_INPUTS, PATH_INPUTS_CUSTOM] dict_inputs = {} for each_path in input_paths: real_path = os.path.realpath(each_path) for each_file in os.listdir(real_path): skip_file = False if each_file in excluded_files: skip_file = True if not skip_file: full_path = "{}/{}".format(real_path, each_file) input_custom = load_module_from_file(full_path, 'inputs') if not hasattr(input_custom, 'INPUT_INFORMATION'): skip_file = True if not skip_file: # logger.info("Found input: {}, {}".format( # input_custom.INPUT_INFORMATION['input_name_unique'], # full_path)) # Populate dictionary of input information if input_custom.INPUT_INFORMATION['input_name_unique'] in dict_inputs: logger.error("Error: Cannot add input modules because it does not have a unique name: {name}".format( name=input_custom.INPUT_INFORMATION['input_name_unique'])) else: dict_inputs[input_custom.INPUT_INFORMATION['input_name_unique']] = {} dict_inputs[input_custom.INPUT_INFORMATION['input_name_unique']]['file_path'] = full_path dict_inputs = dict_has_value(dict_inputs, input_custom, 'input_manufacturer') dict_inputs = dict_has_value(dict_inputs, input_custom, 'input_name') dict_inputs = dict_has_value(dict_inputs, input_custom, 'input_library') dict_inputs = dict_has_value(dict_inputs, input_custom, 'measurements_name') dict_inputs = dict_has_value(dict_inputs, input_custom, 'measurements_dict') dict_inputs = dict_has_value(dict_inputs, input_custom, 'measurements_variable_amount') dict_inputs = dict_has_value(dict_inputs, input_custom, 'measurements_use_same_timestamp') dict_inputs = dict_has_value(dict_inputs, input_custom, 'measurements_rescale') dict_inputs = dict_has_value(dict_inputs, input_custom, 'listener') dict_inputs = dict_has_value(dict_inputs, input_custom, 'message') # Dependencies dict_inputs = dict_has_value(dict_inputs, input_custom, 'dependencies_module') dict_inputs = dict_has_value(dict_inputs, input_custom, 'enable_channel_unit_select') # Interface dict_inputs = dict_has_value(dict_inputs, input_custom, 'interfaces') # Nonstandard (I2C, UART, etc.) location dict_inputs = dict_has_value(dict_inputs, input_custom, 'location') # I2C dict_inputs = dict_has_value(dict_inputs, input_custom, 'i2c_location') dict_inputs = dict_has_value(dict_inputs, input_custom, 'i2c_address_editable') # FTDI dict_inputs = dict_has_value(dict_inputs, input_custom, 'ftdi_location') # UART dict_inputs = dict_has_value(dict_inputs, input_custom, 'uart_location') dict_inputs = dict_has_value(dict_inputs, input_custom, 'uart_baud_rate') dict_inputs = dict_has_value(dict_inputs, input_custom, 'pin_cs') dict_inputs = dict_has_value(dict_inputs, input_custom, 'pin_miso') dict_inputs = dict_has_value(dict_inputs, input_custom, 'pin_mosi') dict_inputs = dict_has_value(dict_inputs, input_custom, 'pin_clock') # Bluetooth (BT) dict_inputs = dict_has_value(dict_inputs, input_custom, 'bt_location') dict_inputs = dict_has_value(dict_inputs, input_custom, 'bt_adapter') # Which form options to display and whether each option is enabled dict_inputs = dict_has_value(dict_inputs, input_custom, 'options_enabled') dict_inputs = dict_has_value(dict_inputs, input_custom, 'options_disabled') # Host options dict_inputs = dict_has_value(dict_inputs, input_custom, 'times_check') dict_inputs = dict_has_value(dict_inputs, input_custom, 'deadline') dict_inputs = dict_has_value(dict_inputs, input_custom, 'port') # Signal options dict_inputs = dict_has_value(dict_inputs, input_custom, 'weighting') dict_inputs = dict_has_value(dict_inputs, input_custom, 'sample_time') # Analog-to-digital converter dict_inputs = dict_has_value(dict_inputs, input_custom, 'adc_gain') dict_inputs = dict_has_value(dict_inputs, input_custom, 'adc_resolution') dict_inputs = dict_has_value(dict_inputs, input_custom, 'adc_sample_speed') # Misc dict_inputs = dict_has_value(dict_inputs, input_custom, 'period') dict_inputs = dict_has_value(dict_inputs, input_custom, 'sht_voltage') dict_inputs = dict_has_value(dict_inputs, input_custom, 'cmd_command') dict_inputs = dict_has_value(dict_inputs, input_custom, 'resolution') dict_inputs = dict_has_value(dict_inputs, input_custom, 'resolution_2') dict_inputs = dict_has_value(dict_inputs, input_custom, 'sensitivity') dict_inputs = dict_has_value(dict_inputs, input_custom, 'thermocouple_type') dict_inputs = dict_has_value(dict_inputs, input_custom, 'ref_ohm') dict_inputs = dict_has_value(dict_inputs, input_custom, 'execute_at_creation') dict_inputs = dict_has_value(dict_inputs, input_custom, 'test_before_saving') dict_inputs = dict_has_value(dict_inputs, input_custom, 'custom_options') return dict_inputs
def parse_action_information(exclude_custom=False): """Parses the variables assigned in each Function Action and return a dictionary of IDs and values.""" def dict_has_value(dict_inp, action, key, force_type=None): if (key in action.ACTION_INFORMATION and (action.ACTION_INFORMATION[key] or action.ACTION_INFORMATION[key] == 0)): if force_type == 'list': if isinstance(action.ACTION_INFORMATION[key], list): dict_inp[action.ACTION_INFORMATION['name_unique']][key] = \ action.ACTION_INFORMATION[key] else: dict_inp[action.ACTION_INFORMATION['name_unique']][key] = \ [action.ACTION_INFORMATION[key]] else: dict_inp[action.ACTION_INFORMATION['name_unique']][key] = \ action.ACTION_INFORMATION[key] return dict_inp excluded_files = [ '__init__.py', '__pycache__', 'base_action.py', 'custom_actions', 'examples', 'scripts', 'tmp_actions' ] function_paths = [PATH_ACTIONS] if not exclude_custom: function_paths.append(PATH_ACTIONS_CUSTOM) dict_actions = {} for each_path in function_paths: real_path = os.path.realpath(each_path) for each_file in os.listdir(real_path): if each_file in excluded_files: continue full_path = "{}/{}".format(real_path, each_file) function_action, status = load_module_from_file( full_path, 'actions') if not function_action or not hasattr(function_action, 'ACTION_INFORMATION'): continue # Populate dictionary of function information if function_action.ACTION_INFORMATION[ 'name_unique'] in dict_actions: logger.error( "Error: Cannot add controller modules because it does not have a unique name: {name}" .format(name=function_action. ACTION_INFORMATION['name_unique'])) else: dict_actions[ function_action.ACTION_INFORMATION['name_unique']] = {} dict_actions[function_action.ACTION_INFORMATION['name_unique']][ 'file_path'] = full_path dict_actions = dict_has_value(dict_actions, function_action, 'name') dict_actions = dict_has_value(dict_actions, function_action, 'manufacturer') dict_actions = dict_has_value(dict_actions, function_action, 'application') dict_actions = dict_has_value(dict_actions, function_action, 'url_datasheet', force_type='list') dict_actions = dict_has_value(dict_actions, function_action, 'url_manufacturer', force_type='list') dict_actions = dict_has_value(dict_actions, function_action, 'url_product_purchase', force_type='list') dict_actions = dict_has_value(dict_actions, function_action, 'url_additional', force_type='list') dict_actions = dict_has_value(dict_actions, function_action, 'application', force_type='list') dict_actions = dict_has_value(dict_actions, function_action, 'message') dict_actions = dict_has_value(dict_actions, function_action, 'usage') dict_actions = dict_has_value(dict_actions, function_action, 'dependencies_module') dict_actions = dict_has_value(dict_actions, function_action, 'dependencies_message') dict_actions = dict_has_value(dict_actions, function_action, 'custom_options') return dict_actions