Пример #1
0
 def load_deprecated_info(self):
     """
     Load info from smartVISU which widgets have been deprecated or removed
     """
     self.deprecated_widgets = []
     self.removed_widgets = []
     self.deprecated_plugin_widgets = []
     filename = os.path.join(self.smartvisu_dir, 'widgets',
                             'deprecated.yaml')
     dep_warnings = shyaml.yaml_load(filename,
                                     ordered=False,
                                     ignore_notfound=True)
     if dep_warnings is None:
         #load deprecated warnings for older versions of smartvisu
         if self.smartvisu_version.startswith('2.9'):
             filename = os.path.join(self.get_plugin_dir(),
                                     'deprecated_29.yaml')
             dep_warnings = shyaml.yaml_load(filename,
                                             ordered=False,
                                             ignore_notfound=True)
     if dep_warnings is not None:
         self.logger.info(
             "Using deprecated info from file '{}' for smartVISU v{}".
             format(filename, self.smartvisu_version))
         self.deprecated_widgets = dep_warnings.get('deprecated', [])
         self.removed_widgets = dep_warnings.get('removed', [])
Пример #2
0
    def read(self, id=None):
        """
        Handle GET requests
        """
        self.logger.info("ConfigController.read(): config = {}".format(id))

        self.core_confdata = shyaml.yaml_load(os.path.join(self.etc_dir, 'smarthome.yaml'))
        self.read_holidays()

        self.module_confdata = shyaml.yaml_load(os.path.join(self.etc_dir, 'module.yaml'))

        result = {}
        if (not id) or id == 'core':
            result['common'] = {}
            result['common']['data'] = self.core_confdata
            result['common']['meta'] = self.core_conf
            result['http'] = {}
            result['http']['data'] = self.module_confdata.get('http', {})
            result['http']['meta'] = self.http_conf
            result['admin'] = {}
            result['admin']['data'] = self.module_confdata.get('admin', {})
            result['admin']['meta'] = self.admin_conf
            result['mqtt'] = {}
            result['mqtt']['data'] = self.module_confdata.get('mqtt', {})
            if result['mqtt']['data'].get('enabled', None) is None:
                result['mqtt']['data']['enabled'] = True
            result['mqtt']['meta'] = self.mqtt_conf
            self.logger.info("  - index: core = {}".format(result))
            return json.dumps(result)

        if id == 'common':
            result['data'] = self.core_confdata
            result['meta'] = self.core_conf
            self.logger.info("  - index: common = {}".format(result))
            return json.dumps(result)

        if id == 'http':
            result['data'] = self.module_confdata.get('http', {})
            result['meta'] = self.http_conf
            self.logger.info("  - index: http = {}".format(result))
            return json.dumps(result)

        if id == 'admin':
            result['data'] = self.module_confdata.get('admin', {})
            result['meta'] = self.admin_conf
            self.logger.info("  - index: admin = {}".format(result))
            return json.dumps(result)

        if id == 'mqtt':
            result['data'] = self.module_confdata.get('mqtt', {})
            if result['mqtt']['data'].get('enabled', None) is None:
                result['mqtt']['data']['enabled'] = True
            result['meta'] = self.mqtt_conf
            self.logger.info("  - index: admin = {}".format(result))
            return json.dumps(result)

        raise cherrypy.NotFound
Пример #3
0
    def __init__(self, module):
        self._sh = module._sh
        self.module = module
        self.base_dir = self._sh.get_basedir()
        self.logger = logging.getLogger(__name__)

        self.etc_dir = self._sh._etc_dir
        self.modules_dir = os.path.join(self.base_dir, 'modules')

        self.core_conf = shyaml.yaml_load(os.path.join(self.modules_dir, 'core', 'module.yaml'))
        self.http_conf = shyaml.yaml_load(os.path.join(self.modules_dir, 'http', 'module.yaml'))
        self.admin_conf = shyaml.yaml_load(os.path.join(self.modules_dir, 'admin', 'module.yaml'))
        self.mqtt_conf = shyaml.yaml_load(os.path.join(self.modules_dir, 'mqtt', 'module.yaml'))

        return
Пример #4
0
    def read_holidays(self):
        self.holidays_confdata = shyaml.yaml_load(
            os.path.join(self.etc_dir, 'holidays.yaml'))
        if self.holidays_confdata.get('location', None) is not None:
            self.core_confdata['holidays_country'] = self.holidays_confdata[
                'location'].get('country', '')
            self.core_confdata['holidays_province'] = self.holidays_confdata[
                'location'].get('province', '')
            self.core_confdata['holidays_state'] = self.holidays_confdata[
                'location'].get('state', '')

        for i in range(1, 6):
            self.core_confdata['holidays_custom' + str(i)] = ''
        try:
            for i in range(1, 6):
                if isinstance(self.holidays_confdata['custom'][i - 1], dict):
                    self.core_confdata['holidays_custom' +
                                       str(i)] = json.dumps(
                                           self.holidays_confdata['custom'][i -
                                                                            1])
                else:
                    self.core_confdata[
                        'holidays_custom' +
                        str(i)] = self.holidays_confdata['custom'][i - 1]
        except:
            pass
        return
Пример #5
0
    def load_struct_definitions(self, etc_dir):

        # --------------------------------------------------------------------
        # Read in all struct definitions before reading item definitions
        #
        # structs are merged into the item tree in lib.config
        #
        # structs are read in from metadata file of plugins while loading plugins
        # and from ../etc/struct.yaml
        #
        # Read in item structs from ../etc/struct.yaml
        struct_definitions = shyaml.yaml_load(os.path.join(
            etc_dir, 'struct.yaml'),
                                              ordered=True,
                                              ignore_notfound=True)
        if struct_definitions is not None:
            if isinstance(struct_definitions, collections.OrderedDict):
                for key in struct_definitions:
                    self.add_struct_definition('', key,
                                               struct_definitions[key])
            else:
                self.logger.error(
                    "load_itemdefinitions(): Invalid content in struct.yaml: struct_definitions = '{}'"
                    .format(struct_definitions))

        self.fill_nested_structs()

        # for Testing: Save structure of joined item structs
        self.logger.info(
            "load_itemdefinitions(): For testing the joined item structs are saved to {}"
            .format(os.path.join(etc_dir, 'structs_joined.yaml')))
        shyaml.yaml_save(os.path.join(etc_dir, 'structs_joined.yaml'),
                         self._struct_definitions)
Пример #6
0
def reload_translations():
    """
    Reload translations for existing translation_ids - to test new translations without having to restart SmartHomeNG
    """
    logger.info("reload_translations")
    for id in _translation_files:
        translation_type = _translation_files[id]['type']
        filename = _translation_files[id]['filename']
        trans_dict = shyaml.yaml_load(filename,
                                      ordered=False,
                                      ignore_notfound=True)
        if trans_dict != None:
            if translation_type == 'global':
                for translation_section in trans_dict.keys():
                    if translation_section.endswith('_translations'):
                        id = translation_section.split('_')[0].replace(
                            '.', '/')
                        trans = trans_dict.get(translation_section, {})
                        logger.info(
                            "Reloading {} translations (id={}) from {}".format(
                                translation_type, id, filename))
                        _translations[id] = trans
            else:
                trans = trans_dict.get(translation_type + '_translations', {})
                logger.info("Reloading {} translations (id={}) from {}".format(
                    translation_type, id, filename))
                _translations[id] = trans
    return
Пример #7
0
    def get_logic_info(self, logicname):
        """
        Get code of a logic from file
        """
        config_filename = os.path.join(self.etc_dir, 'logic.yaml')
        wrk = shyaml.yaml_load(config_filename)
        logic_conf = wrk.get(logicname, {})

        if Utils.get_type(logic_conf.get('watch_item', None)) == 'str':
            self.logger.info(
                "get_logic: logicname = '{}', converting watch_item = '{}' to list"
                .format(logicname, logic_conf['watch_item']))
            logic_conf['watch_item'] = [logic_conf['watch_item']]

        self.logger.info(
            "get_logic: logicname = '{}', logic_conf = '{}'".format(
                logicname, logic_conf))

        mylogic = self.fill_logicdict(logicname)
        logic_conf['name'] = mylogic['name']
        logic_conf['next_exec'] = mylogic['next_exec']
        logic_conf['last_run'] = mylogic['last_run']

        # self.logger.warning("type = {}, mylogic = {}".format(type(mylogic), mylogic))
        # self.logger.warning("type = {}, logic_conf = {}".format(type(logic_conf), logic_conf))

        return json.dumps(logic_conf)
Пример #8
0
    def load_struct_definitions_from_file(self, etc_dir, fn, key_prefix):
        """
        Loads struct definitions from a file

        :param etc_dir: path to etc directory of SmartHomeNG
        :param fn: filename to load struct definition(s) from
        :param key_prefix: prefix to be used when adding struct(s) to loaded definitions
        """
        if key_prefix == '':
            self.logger.info(f"Loading struct file '{fn}' without key-prefix")
        else:
            self.logger.info(f"Loading struct file '{fn}' with key-prefix '{key_prefix}'")

        # Read in item structs from ../etc/struct.yaml
        struct_definitions = shyaml.yaml_load(os.path.join(etc_dir, fn), ordered=True, ignore_notfound=True)

        # if valid struct definition file etc/struct.yaml ist found
        if struct_definitions is not None:
            if isinstance(struct_definitions, collections.OrderedDict):
                for key in struct_definitions:
                    if fn == 'struct.yaml':
                        struct_name = key
                    else:
                        struct_name = key_prefix + '.' + key
                    self.add_struct_definition('', struct_name, struct_definitions[key])
            else:
                self.logger.error(f"load_itemdefinitions(): Invalid content in {fn}: struct_definitions = '{struct_definitions}'")

        return
Пример #9
0
    def _load_learned_values(self, scene):
        """
        Load learned values for the scene from a file
        """
        scene_learnfile = os.path.join(self._scenes_dir, scene + '_learned')
        learned_dict = yaml.yaml_load(scene_learnfile + '.yaml',
                                      ordered=False,
                                      ignore_notfound=True)
        logger.info("Loading learned values for scene {} from file {}:".format(
            scene, scene_learnfile))
        logger.info(" -> loaded dict learned_dict {}:".format(learned_dict))
        if learned_dict is not None:
            if learned_dict != {}:
                logger.info(
                    "Loading learned values for scene {}".format(scene))
            for fkey in learned_dict:
                key = scene + '#' + fkey
                lvalue = learned_dict[fkey]
                self._learned_values[key] = lvalue
                logger.debug(" - Loading value {} for state/ditem {}".format(
                    lvalue, key))

        logger.info(" -> to dict self._learned_values {}:".format(
            self._learned_values))
        return
Пример #10
0
    def __init__(self, smarthome):
        self._sh = smarthome
        
        global _scenes_instance
        if _scenes_instance is not None:
            import inspect
            curframe = inspect.currentframe()
            calframe = inspect.getouterframes(curframe, 2)
            logger.critical("A second 'scenes' object has been created. There should only be ONE instance of class 'Scenes'!!! Called from: {} ({})".format(calframe[1][1], calframe[1][3]))

        _scenes_instance = self

        self.items = Items.get_instance()

        self._scenes = {}
        self._learned_values = {}
        self._scenes_dir = smarthome.base_dir + '/scenes/'
        if not os.path.isdir(self._scenes_dir):
            logger.warning("Directory scenes not found. Ignoring scenes.".format(self._scenes_dir))
            return

     #   for item in smarthome.return_items():
        for item in self.items.return_items():
            if item.type() == 'scene':
                scene_file = os.path.join(self._scenes_dir, item.id())

                scene_file_yaml = yaml.yaml_load(scene_file+'.yaml', ordered=False, ignore_notfound=True)
                if scene_file_yaml is not None:
                    # Reading yaml file with scene definition
                    for state in scene_file_yaml:
                        actions = scene_file_yaml[state]['actions']
                        if isinstance(actions, dict):
                            actions = [ actions ]
                        if isinstance( actions, list ):
                            for action in actions:
                                if isinstance(action, dict):
                                    self._add_scene_entry(item, str(state), 
                                                          action.get('item', ''), str(action.get('value', '')), 
                                                          action.get('learn', ''), scene_file_yaml[state].get('name', ''))
                                else:
                                    logger.warning("Scene {}, state {}: action '{}' is not a dict".format(item, state, action))
                        else:
                            logger.warning("Scene {}, state {}: actions are not a list".format(item, state))
                    self._load_learned_values(str(item.id()))
                else:
                    # Trying to read conf file with scene definition
                    scene_conf_file = scene_file + '.conf'
                    try:
                        with open(scene_conf_file, 'r', encoding='UTF-8') as f:
                            reader = csv.reader(f, delimiter=' ')
                            for row in reader:
                                if row == []:  # ignore empty lines
                                    continue
                                if row[0][0] == '#':  # ignore comments
                                    continue
                                self._add_scene_entry(item, row[0], row[1], row[2])
                    except Exception as e:
                        logger.warning("Problem reading scene file {0}: {1}".format(scene_file, e))
                        continue
                item.add_method_trigger(self._trigger)
Пример #11
0
    def read(self, id=None):
        """
        Handle GET requests for threads API

        return an object with type info about all installed plugins
        """
        self.logger.info("PluginsController(): read")

        default_language = self._sh.get_defaultlanguage()

        if self.plugin_data == {}:
            plugins_list = sorted(os.listdir(self.plugins_dir))

            self.logger.info("- plugins_list_sorted = {}".format(plugins_list))
            for p in plugins_list:
                if not (p[0] in ['.', '_']):
                    if os.path.isfile(os.path.join(self.plugins_dir, p, 'plugin.yaml')):
                        plg_yaml = shyaml.yaml_load(os.path.join(os.path.join(self.plugins_dir, p, 'plugin.yaml')))
                        if plg_yaml is None:
                            self.logger.warning("- no valid plugin.yaml found for plugin {}".format(p))
                        else:
                            plg_data = plg_yaml.get('plugin', None)
                            if plg_data is None:
                                self.logger.info("- plugin.yaml has no section 'plugin': {}".format(p))
                            else:
                                self.plugin_data[p] = plg_data.get('type', '')
                    else:
                        self.logger.info("- no plugin.yaml: {}".format(p))

        return json.dumps(self.plugin_data)
Пример #12
0
    def __init__(self, module):
        self._sh = module._sh
        self.module = module
        self.base_dir = self._sh.get_basedir()
        self.logger = logging.getLogger(__name__)

        self.etc_dir = self._sh._etc_dir
        self.log_dir = os.path.join(self.base_dir, 'var', 'log')

        self.logging_conf = shyaml.yaml_load(
            os.path.join(self.etc_dir, 'logging.yaml'))

        self.chunksize = self.module.log_chunksize

        try:
            roothandler = self.logging_conf['root']['handlers'][0]
            self.root_logname = os.path.splitext(
                os.path.basename(
                    self.logging_conf['handlers'][roothandler]['filename']))[0]
        except:
            self.root_logname = ''
        self.logger.info("logging_conf: self.root_logname = {}".format(
            self.root_logname))

        return
Пример #13
0
def parse_yaml(filename, config=None, addfilenames=False):
    """
    Load and parse a yaml configuration file and merge it to the configuration tree

    :param filename: Name of the configuration file
    :param config: Optional OrderedDict tree, into which the configuration should be merged
    :type filename: str
    :type config: bool
    
    :return: The resulting merged OrderedDict tree
    :rtype: OrderedDict

    
    The config file should stick to the following setup:

    .. code-block:: yaml

       firstlevel:
           attribute1: xyz
           attribute2: foo
           attribute3: bar
           
           secondlevel:
               attribute1: abc
               attribute2: bar
               attribute3: foo
               
               thirdlevel:
                   attribute1: def
                   attribute2: barfoo
                   attribute3: foobar
                   
           anothersecondlevel:
               attribute1: and so on

    where firstlevel, secondlevel, thirdlevel and anothersecondlevel are defined as items and attribute are their respective attribute - value pairs

    Valid characters for the items are a-z and A-Z plus any digit and underscore as second or further characters.
    Valid characters for the attributes are the same as for an item plus @ and *

    """
    logger.debug("parse_yaml: Parsing file {}".format(os.path.basename(filename)))
    if config is None:
        config = collections.OrderedDict()

    items = shyaml.yaml_load(filename, ordered=True)
    if items is not None:
        remove_comments(items)
        remove_digits(items)
        remove_reserved(items)
        remove_keyword(items)
        remove_invalid(items)

        if addfilenames:
            logger.debug("parse_yaml: Add filename = {} to items".format(os.path.basename(filename)))
            _add_filenames_to_config(items, os.path.basename(filename))

        config = merge(items, config)
    return config
Пример #14
0
    def _load_scenes(self):
        """
        Load defined scenes with learned values from ../scene directory

        :return:
        """
        self._scenes = {}
        self._learned_values = {}
        self._scenes_dir = self._sh._scenes_dir
        if not os.path.isdir(self._scenes_dir):
            logger.warning(translate("Directory '{scenes_dir}' not found. Ignoring scenes.", {'scenes_dir': self._scenes_dir}))
            return

        self._learned_values = {}
        #   for item in smarthome.return_items():
        for item in self.items.return_items():
            if item.type() == 'scene':
                self.scene_file = os.path.join(self._scenes_dir, item.id())

                scene_file_yaml = yaml.yaml_load(self.scene_file+'.yaml', ordered=False, ignore_notfound=True)
                if scene_file_yaml is not None:
                    # Reading yaml file with scene definition
                    for state in scene_file_yaml:
                        actions = scene_file_yaml[state].get('actions', None)
                        if actions is not None:
                            if isinstance(actions, dict):
                                actions = [ actions ]
                            if isinstance( actions, list ):
                                for action in actions:
                                    if isinstance(action, dict):
                                        self._add_scene_entry(item, str(state),
                                                              action.get('item', ''), str(action.get('value', '')),
                                                              action.get('learn', ''), scene_file_yaml[state].get('name', ''))
                                    else:
                                        logger.warning(translate("Scene {scene}, state {state}: action '{action}' is not a dict", {'scene': item, 'state': state, 'action': action}))
                            else:
                                logger.warning(translate("Scene {scene}, state {state}: actions are not a list", {'scene': item, 'state': state}))

                    self._load_learned_values(str(item.id()))
                else:
                    # Trying to read conf file with scene definition
                    scene_conf_file = self.scene_file + '.conf'
                    try:
                        with open(scene_conf_file, 'r', encoding='UTF-8') as f:
                            reader = csv.reader(f, delimiter=' ')
                            for row in reader:
                                if row == []:  # ignore empty lines
                                    continue
                                if row[0][0] == '#':  # ignore comments
                                    continue
                                self._add_scene_entry(item, row[0], row[1], row[2])
                    except Exception as e:
                        logger.warning(translate("Problem reading scene file {file}: No .yaml or .conf file found with this name", {'file': self.scene_file}))
                        continue
                item.add_method_trigger(self._trigger)

        return
Пример #15
0
 def _load_translations(self):
     """
     """
     self._gtrans = {}
     self.relative_filename = os.path.join( 'bin', 'locale'+YAML_FILE ) 
     filename = os.path.join( self._sh.get_basedir(), self.relative_filename )
     trans = shyaml.yaml_load(filename, ordered=False, ignore_notfound=True)
     if trans != None:
         self._gtrans = trans.get('global_translations', {})
         logger.info("Loaded global translations = {}".format(self._gtrans))
Пример #16
0
 def _load_translations(self):
     """
     """
     self._gtrans = {}
     self.relative_filename = os.path.join('bin', 'locale' + YAML_FILE)
     filename = os.path.join(self._sh.get_basedir(), self.relative_filename)
     trans = shyaml.yaml_load(filename, ordered=False, ignore_notfound=True)
     if trans != None:
         self._gtrans = trans.get('global_translations', {})
         logger.info("Loaded global translations = {}".format(self._gtrans))
Пример #17
0
    def load_logging_config(self):
        """
        Load config from logging.yaml to a dict

        If logging.yaml does not contain a 'shng_version' key, a backup is created
        """
        conf_filename = os.path.join(self.etc_dir, 'logging')
        result = shyaml.yaml_load(conf_filename + '.yaml')

        return result
Пример #18
0
    def read_visu_definition(self):

        from pprint import pformat

        self.etc_dir = self._sh._etc_dir

        filename = os.path.join(self.etc_dir, 'visu.yaml')
        self.visu_definition = shyaml.yaml_load(filename,
                                                ordered=False,
                                                ignore_notfound=True)
        return
Пример #19
0
    def test_conf_plugins_requirements(self, plugin_conf_basename,
                                       plugins_dir):
        # import lib.shyaml here, so test_base_requirements() can be run even if ruamel.yaml package is not installed
        import lib.shyaml as shyaml

        if not os.path.isfile(plugin_conf_basename + YAML_FILE):
            self.logger.warning(
                "Requirments for configured plugins were not checked because the plugin configuration is not in YAML format"
            )
            return True

        plugin_conf = shyaml.yaml_load(plugin_conf_basename + YAML_FILE,
                                       ordered=False)

        req_dict = {}
        for plugin_instance in plugin_conf:
            plugin_name = plugin_conf[plugin_instance].get('plugin_name', None)
            class_path = plugin_conf[plugin_instance].get('class_path', None)
            plugin = ''
            if class_path:
                if class_path.startswith('plugins.'):
                    sp = class_path.split('.')
                    if len(sp) == 2:
                        plugin = sp[1]
            if plugin == '' and plugin_name:
                plugin = plugin_name

            filename = os.path.join(plugins_dir, plugin, 'requirements.txt')
            if not os.path.isfile(filename):
                filename = ''
            else:
                if plugin != '':
                    req_dict[plugin] = filename

        self._conf_plugin_filelist = []
        for plugin in req_dict:
            self._conf_plugin_filelist.append(req_dict[plugin])

        #req_files = Requirements_files()
        self.req_files.set_conf_plugin_files(self._conf_plugin_filelist)
        self.req_files.create_requirementsfile('conf_all')

        requirements_met = self.test_requirements(
            os.path.join(self._sh_dir, 'requirements', 'conf_all.txt'), True)
        if not requirements_met:
            self.logger.info(
                "test_conf_plugins_requirements: Python package requirements for configured plugins not met"
            )

        return requirements_met
Пример #20
0
    def read(self, id=None):
        """
        return an object with data about all installed plugins
        """
        self.logger.info("PluginsInstalledController(): index")
        if self._sh.shng_status['code'] < 20:
            self.logger.error("PluginsInstalledController.read(): SmartHomeNG has not yet finished initialization")
            return json.dumps({})

        default_language = self._sh.get_defaultlanguage()

        if self.plugin_data == {}:
            plugins_list = sorted(os.listdir(self.plugins_dir))
            self.logger.warning("PluginsInstalledController.read(): plugin_list (sollte sortiert sein) = '{}'".format(plugins_list))

            self.logger.info("- plugins_list_sorted = {}".format(plugins_list))
            for p in plugins_list:
                if not (p[0] in ['.', '_']):
                    if os.path.isfile(os.path.join(self.plugins_dir, p, 'plugin.yaml')):
                        plg_yaml = shyaml.yaml_load(os.path.join(os.path.join(self.plugins_dir, p, 'plugin.yaml')))
                        if plg_yaml == None:
                            self.logger.warning("PluginsInstalledController.read(): Plugin '{}': plugin.yaml cannot be read".format(p))
                        else:
                            plg_data = plg_yaml.get('plugin', None)
                            if plg_data is None:
                                self.logger.info("- plugin.yaml has no section 'plugin': {}".format(p))
                            else:
                                # self.plugin_data[p] = {}
                                self.plugin_data[p] = collections.OrderedDict()
                                self.plugin_data[p]['type'] = plg_data.get('type', '')
                                description = plg_data.get('description', {'de': '', 'en': ''})

                                # self.plugin_data[p]['description'] = description.get(default_language, '')
                                # if self.plugin_data[p]['description'] == '':
                                #     self.plugin_data[p]['description'] = description[self.fallback_language_order[0]]
                                # if self.plugin_data[p]['description'] == '':
                                #     self.plugin_data[p]['description'] = description[self.fallback_language_order[1]]

                                self.plugin_data[p]['description'] = description

                                self.plugin_data[p]['version'] = plg_data.get('version', '')
                                self.plugin_data[p]['state'] = plg_data.get('state', '')
                                self.plugin_data[p]['documentation'] = plg_data.get('documentation', '')
                                self.plugin_data[p]['multi_instance'] = plg_data.get('multi_instance', '')
                                self.plugin_data[p]['configuration_needed'] = plg_data.get('configuration_needed', True)
                    else:
                        self.logger.info("- no plugin.yaml: {}".format(p))
        self.logger.warning("PluginsInstalledController.read(): Plugin Liste (sollte sortiert sein), json.dumps(self.plugin_data) = '{}'".format(json.dumps(self.plugin_data)))
        return json.dumps(self.plugin_data, sort_keys=True)
Пример #21
0
 def _load_learned_values(self, scene):
     """
     Load learned values for the scene from a file
     """
     self._learned_values = {}
     scene_learnfile = os.path.join(self._scenes_dir, scene+'_learned')
     learned_dict = yaml.yaml_load(scene_learnfile+'.yaml', ordered=False, ignore_notfound=True)
     if learned_dict is not None:
         if learned_dict != {}:
             logger.info("Loading learned values for scene {}".format(scene))
         for fkey in learned_dict:
             key = scene + '#' + fkey
             lvalue = learned_dict[fkey]
             self._learned_values[key] = lvalue 
             logger.debug(" - Loading value {} for state/ditem {}".format(lvalue, key))
     return
Пример #22
0
def load_translations(translation_type='global',
                      from_dir='bin',
                      translation_id='global'):
    """
    Load global or plugin-specific translations from a locale.yaml file

    :param translation_type: 'global' or 'plugin'
    :param from_dir: 'bin' (for global) or 'plugins/<plugin name>'

    :return: loaded translations as s dict
    """
    global _translations

    trans = {}
    relative_filename = os.path.join(from_dir, 'locale' + YAML_FILE)
    filename = os.path.join(_base_dir, relative_filename)
    trans_dict = shyaml.yaml_load(filename,
                                  ordered=False,
                                  ignore_notfound=True)
    if trans_dict != None:
        if translation_type == 'global':
            for translation_section in trans_dict.keys():
                if translation_section.endswith('_translations'):
                    trans_id = translation_section.split('_')[0].replace(
                        '.', '/')
                    trans = trans_dict.get(translation_section, {})
                    _translations[trans_id] = trans
                    logger.info(
                        "Loading {} translations (id={}) from {}".format(
                            translation_type, trans_id, relative_filename))
                    logger.debug(" - translations = {}".format(trans))
        else:
            trans = trans_dict.get(translation_type + '_translations', {})
            logger.info("Loading {} translations (id={}) from {}".format(
                translation_type, translation_id, relative_filename))
            if _translations.get(translation_id, None) is not None:
                logger.info(
                    "Duplicate identifier '{}' used for translation_type '{}' to load from '{}' - translations not loaded"
                    .format(translation_id, translation_type, from_dir))
                return trans
            _translations[translation_id] = trans
            logger.debug(" - translations = {}".format(trans))

        _translation_files[translation_id] = {}
        _translation_files[translation_id]['type'] = translation_type
        _translation_files[translation_id]['filename'] = filename
    return trans
Пример #23
0
def parse_yaml(filename, config=None):
    '''
    Load and parse a yaml configuration file and merge it to the configuration tree

    :param filename: Name of the configuration file
    :param config: Optional OrderedDict tree, into which the configuration should be merged
    :return: The resulting merged OrderedDict tree
    '''
    if config is None:
        config = collections.OrderedDict()

    items = shyaml.yaml_load(filename, ordered=True)
    if items is not None:
        remove_comments(items)
        remove_digits(items)
        remove_reserved(items)
        remove_keyword(items)
        remove_invalid(items)

        config = merge(items, config)
    return config
Пример #24
0
    def __init__(self, smarthome, name, classname, classpath, args, instance,
                 meta, gtranslations):
        """
        Initialization of wrapper class
        """
        logger.debug(
            'PluginWrapper __init__: Section {}, classname {}, classpath {}'.
            format(name, classname, classpath))

        threading.Thread.__init__(self, name=name)

        self._init_complete = False
        self.meta = meta
        # Load an instance of the plugin
        try:
            exec("import {0}".format(classpath))
        except Exception as e:
            logger.exception(
                "Plugin '{0}' exception during import of __init__.py: {1}".
                format(name, e))
            return
        exec("self.plugin = {0}.{1}.__new__({0}.{1})".format(
            classpath, classname))

        relative_filename = os.path.join(classpath.replace('.', '/'),
                                         'locale' + YAML_FILE)
        filename = os.path.join(smarthome.get_basedir(), relative_filename)
        trans = shyaml.yaml_load(filename, ordered=False, ignore_notfound=True)
        if trans != None:
            self._ptrans = trans.get('plugin_translations', {})
            logger.info("Plugin '{}': Loaded plugin translations = {}".format(
                name, self._ptrans))
        else:
            self._ptrans = {}

        # make the plugin a method/function of the main smarthome object  (MS: Ist das zu früh? Falls Init fehlschlägt?)
#        setattr(smarthome, self.name, self.plugin)
# initialize attributes of the newly created plugin object instance
        if isinstance(self.get_implementation(), SmartPlugin):
            self.get_implementation()._gtranslations = gtranslations
            self.get_implementation()._ptranslations = self._ptrans
            self.get_implementation()._set_configname(name)
            #            self.get_implementation()._config_section = name
            self.get_implementation()._set_shortname(
                str(classpath).split('.')[1])
            self.get_implementation()._classpath = classpath
            self.get_implementation()._set_classname(classname)
            # if instance != '' war auskommentiert, reaktiviert: 26.01.2018 MS
            if self.get_implementation().ALLOW_MULTIINSTANCE is None:
                self.get_implementation(
                ).ALLOW_MULTIINSTANCE = self.meta.get_bool('multi_instance')
            if instance != '':
                logger.debug("set plugin {0} instance to {1}".format(
                    name, instance))
                self.get_implementation()._set_instance_name(instance)
            self.get_implementation()._set_sh(smarthome)
            self.get_implementation()._set_plugin_dir(
                os.path.join(
                    os.path.dirname(os.path.dirname(
                        os.path.abspath(__file__))),
                    classpath.replace('.', os.sep)))
            self.get_implementation()._plgtype = self.meta.get_string('type')
        else:
            # classic plugin
            #            self.get_implementation()._config_section = name
            self.get_implementation()._configname = name
            self.get_implementation()._shortname = str(classpath).split('.')[1]
            self.get_implementation()._classpath = classpath
            self.get_implementation()._classname = classname
            self.get_implementation()._plgtype = ''
        self.get_implementation()._itemlist = []

        # get arguments defined in __init__ of plugin's class to self.args
        exec("self.args = inspect.getargspec({0}.{1}.__init__)[0][1:]".format(
            classpath, classname))

        # get list of argument used names, if they are defined in the plugin's class
        logger.debug("Plugin '{}': args = '{}'".format(classname, str(args)))
        arglist = [name for name in self.args if name in args]
        argstring = ",".join(
            ["{}={}".format(name, args[name]) for name in arglist])
        #        logger.debug("Plugin '{}' using arguments {}".format(str(classpath).split('.')[1], arglist))

        self.get_implementation()._init_complete = False
        (plugin_params, params_ok,
         hide_params) = self.meta.check_parameters(args)
        if params_ok == True:
            if plugin_params != {}:
                # initialize parameters the old way
                argstring = ",".join([
                    "{}={}".format(
                        name, '"' + str(plugin_params.get(name, '')) + '"')
                    for name in arglist
                ])
            # initialize parameters the new way: Define a dict within the instance
            self.get_implementation()._parameters = plugin_params
            self.get_implementation()._hide_parameters = hide_params
            self.get_implementation()._metadata = self.meta

            # initialize the loaded instance of the plugin
            self.get_implementation(
            )._init_complete = True  # set to false by plugin, if an initalization error occurs

            # initialize the loaded instance of the plugin
            exec("self.plugin.__init__(smarthome{0}{1})".format(
                "," if len(arglist) else "", argstring))

            # set level to make logger appear in internal list of loggers (if not configured by logging.yaml)
            try:  # skip classic plugins
                if self.get_implementation().logger.level == 0:
                    self.get_implementation().logger.setLevel('WARNING')
            except:
                pass

        # set the initialization complete status for the wrapper instance
        self._init_complete = self.get_implementation()._init_complete
        if self.get_implementation()._init_complete == True:
            # make the plugin a method/function of the main smarthome object  (MS: Ist das zu früh? Falls Init fehlschlägt?)
            setattr(smarthome, self.name, self.plugin)
            try:
                code_version = self.get_implementation().PLUGIN_VERSION
            except:
                code_version = None  # if plugin code without version
            if isinstance(self.get_implementation(), SmartPlugin):
                if self.meta.test_version(code_version):
                    # set version in plugin instance (if not defined in code)
                    if code_version == None:
                        self.get_implementation(
                        ).PLUGIN_VERSION = self.meta.get_version()
                    # set multiinstance in plugin instance (if not defined in code)
                    try:
                        dummy = self.get_implementation().ALLOW_MULTIINSTANCE
                    except:
                        #                        logger.warning("self.meta.get_bool('multi_instance') = {}".format(self.meta.get_bool('multi_instance')))
                        self.get_implementation(
                        ).ALLOW_MULTIINSTANCE = self.meta.get_bool(
                            'multi_instance')
#                        logger.warning("get_implementation().ALLOW_MULTIINSTANCE = {}".format(self.get_implementation().ALLOW_MULTIINSTANCE))
                    if not self.get_implementation(
                    )._set_multi_instance_capable(
                            self.meta.get_bool('multi_instance')):
                        logger.error(
                            "Plugins: Loaded plugin '{}' ALLOW_MULTIINSTANCE differs between metadata ({}) and Python code ({})"
                            .format(
                                name, self.meta.get_bool('multi_instance'),
                                self.get_implementation().ALLOW_MULTIINSTANCE))
                    logger.debug(
                        "Plugins: Loaded plugin '{}' (class '{}') v{}: {}".
                        format(
                            name,
                            str(self.get_implementation().__class__.__name__),
                            self.meta.get_version(),
                            self.meta.get_mlstring('description')))
            else:
                logger.debug(
                    "Plugins: Loaded classic-plugin '{}' (class '{}')".format(
                        name,
                        str(self.get_implementation().__class__.__name__)))
            if instance != '':
                logger.debug("set plugin {0} instance to {1}".format(
                    name, instance))
                self.get_implementation()._set_instance_name(instance)
        else:
            logger.error(
                "Plugins: Plugin '{}' initialization failed, plugin not loaded"
                .format(classpath.split('.')[1]))
Пример #25
0
    def __init__(self, smarthome, name, classname, classpath, args, instance, meta, gtranslations):
        """
        Initialization of wrapper class
        """
        logger.debug('PluginWrapper __init__: Section {}, classname {}, classpath {}'.format( name, classname, classpath ))

        threading.Thread.__init__(self, name=name)

        self._init_complete = False
        self.meta = meta
        # Load an instance of the plugin
        try:
            exec("import {0}".format(classpath))
        except Exception as e:
            logger.exception("Plugin '{0}' exception during import of __init__.py: {1}".format(name, e))
            return
        exec("self.plugin = {0}.{1}.__new__({0}.{1})".format(classpath, classname))

        relative_filename = os.path.join( classpath.replace('.', '/'), 'locale'+YAML_FILE ) 
        filename = os.path.join( smarthome.get_basedir(), relative_filename )
        trans = shyaml.yaml_load(filename, ordered=False, ignore_notfound=True)
        if trans != None:
            self._ptrans = trans.get('plugin_translations', {})
            logger.info("Plugin '{}': Loaded plugin translations = {}".format(name, self._ptrans))
        else:
            self._ptrans = {}

        # make the plugin a method/function of the main smarthome object  (MS: Ist das zu früh? Falls Init fehlschlägt?)
#        setattr(smarthome, self.name, self.plugin)
        # initialize attributes of the newly created plugin object instance
        if isinstance(self.get_implementation(), SmartPlugin):
            self.get_implementation()._gtranslations = gtranslations
            self.get_implementation()._ptranslations = self._ptrans
            self.get_implementation()._set_configname(name)
#            self.get_implementation()._config_section = name
            self.get_implementation()._set_shortname(str(classpath).split('.')[1])
            self.get_implementation()._classpath = classpath
            self.get_implementation()._set_classname(classname)
            # if instance != '' war auskommentiert, reaktiviert: 26.01.2018 MS
            if self.get_implementation().ALLOW_MULTIINSTANCE is None:
                self.get_implementation().ALLOW_MULTIINSTANCE = self.meta.get_bool('multi_instance')
            if instance != '':
                logger.debug("set plugin {0} instance to {1}".format(name, instance ))
                self.get_implementation()._set_instance_name(instance)
            self.get_implementation()._set_sh(smarthome)
            self.get_implementation()._set_plugin_dir( os.path.join( os.path.dirname( os.path.dirname(os.path.abspath(__file__)) ), classpath.replace('.',os.sep) ) )
            self.get_implementation()._plgtype = self.meta.get_string('type')
        else:
            # classic plugin
#            self.get_implementation()._config_section = name
            self.get_implementation()._configname = name
            self.get_implementation()._shortname = str(classpath).split('.')[1]
            self.get_implementation()._classpath = classpath
            self.get_implementation()._classname = classname
            self.get_implementation()._plgtype = ''
        self.get_implementation()._itemlist = []

        # get arguments defined in __init__ of plugin's class to self.args
        exec("self.args = inspect.getargspec({0}.{1}.__init__)[0][1:]".format(classpath, classname))

        # get list of argument used names, if they are defined in the plugin's class
        logger.debug("Plugin '{}': args = '{}'".format(classname, str(args)))
        arglist = [name for name in self.args if name in args]
        argstring = ",".join(["{}={}".format(name, args[name]) for name in arglist])
#        logger.debug("Plugin '{}' using arguments {}".format(str(classpath).split('.')[1], arglist))

        self.get_implementation()._init_complete = False
        (plugin_params, params_ok, hide_params) = self.meta.check_parameters(args)
        if params_ok == True:
            if plugin_params != {}:
                # initialize parameters the old way
                argstring = ",".join(["{}={}".format(name, '"'+str(plugin_params.get(name,''))+'"') for name in arglist])
            # initialize parameters the new way: Define a dict within the instance
            self.get_implementation()._parameters = plugin_params
            self.get_implementation()._hide_parameters = hide_params
            self.get_implementation()._metadata = self.meta
 
            # initialize the loaded instance of the plugin
            self.get_implementation()._init_complete = True   # set to false by plugin, if an initalization error occurs

            # initialize the loaded instance of the plugin
            exec("self.plugin.__init__(smarthome{0}{1})".format("," if len(arglist) else "", argstring))

            # set level to make logger appear in internal list of loggers (if not configured by logging.yaml)
            try: # skip classic plugins
                if self.get_implementation().logger.level == 0:
                    self.get_implementation().logger.setLevel('WARNING')
            except:
                pass

        # set the initialization complete status for the wrapper instance
        self._init_complete = self.get_implementation()._init_complete
        if self.get_implementation()._init_complete == True:
            # make the plugin a method/function of the main smarthome object  (MS: Ist das zu früh? Falls Init fehlschlägt?)
            setattr(smarthome, self.name, self.plugin)
            try:
                code_version = self.get_implementation().PLUGIN_VERSION
            except:
                code_version = None    # if plugin code without version
            if isinstance(self.get_implementation(), SmartPlugin):
                if self.meta.test_version(code_version):
                    # set version in plugin instance (if not defined in code)
                    if code_version == None:
                        self.get_implementation().PLUGIN_VERSION = self.meta.get_version()
                    # set multiinstance in plugin instance (if not defined in code)
                    try:
                        dummy = self.get_implementation().ALLOW_MULTIINSTANCE
                    except:
#                        logger.warning("self.meta.get_bool('multi_instance') = {}".format(self.meta.get_bool('multi_instance')))
                        self.get_implementation().ALLOW_MULTIINSTANCE = self.meta.get_bool('multi_instance')
#                        logger.warning("get_implementation().ALLOW_MULTIINSTANCE = {}".format(self.get_implementation().ALLOW_MULTIINSTANCE))
                    if not self.get_implementation()._set_multi_instance_capable(self.meta.get_bool('multi_instance')):
                        logger.error("Plugins: Loaded plugin '{}' ALLOW_MULTIINSTANCE differs between metadata ({}) and Python code ({})".format(name, self.meta.get_bool('multi_instance'), self.get_implementation().ALLOW_MULTIINSTANCE ))
                    logger.debug("Plugins: Loaded plugin '{}' (class '{}') v{}: {}".format( name, str(self.get_implementation().__class__.__name__), self.meta.get_version(), self.meta.get_mlstring('description') ) )
            else:
                logger.debug("Plugins: Loaded classic-plugin '{}' (class '{}')".format( name, str(self.get_implementation().__class__.__name__) ) )
            if instance != '':
                logger.debug("set plugin {0} instance to {1}".format(name, instance ))
                self.get_implementation()._set_instance_name(instance)
        else:
            logger.error("Plugins: Plugin '{}' initialization failed, plugin not loaded".format(classpath.split('.')[1]))
Пример #26
0
def parse_yaml(filename, config=None, addfilenames=False):
    """
    Load and parse a yaml configuration file and merge it to the configuration tree

    :param filename: Name of the configuration file
    :param config: Optional OrderedDict tree, into which the configuration should be merged
    :type filename: str
    :type config: bool
    
    :return: The resulting merged OrderedDict tree
    :rtype: OrderedDict

    
    The config file should stick to the following setup:

    .. code-block:: yaml

       firstlevel:
           attribute1: xyz
           attribute2: foo
           attribute3: bar
           
           secondlevel:
               attribute1: abc
               attribute2: bar
               attribute3: foo
               
               thirdlevel:
                   attribute1: def
                   attribute2: barfoo
                   attribute3: foobar
                   
           anothersecondlevel:
               attribute1: and so on

    where firstlevel, secondlevel, thirdlevel and anothersecondlevel are defined as items and attribute are their respective attribute - value pairs

    Valid characters for the items are a-z and A-Z plus any digit and underscore as second or further characters.
    Valid characters for the attributes are the same as for an item plus @ and *

    """
    logger.debug("parse_yaml: Parsing file {}".format(
        os.path.basename(filename)))
    if config is None:
        config = collections.OrderedDict()

    items = shyaml.yaml_load(filename, ordered=True)
    if items is not None:
        remove_comments(items)
        remove_digits(items)
        remove_reserved(items)
        remove_keyword(items)
        remove_invalid(items)

        if addfilenames:
            logger.debug("parse_yaml: Add filename = {} to items".format(
                os.path.basename(filename)))
            _add_filenames_to_config(items, os.path.basename(filename))

        config = merge(items, config)
    return config
Пример #27
0
    def _initialize_holidays(self):
        """
        Initialize the holidays according to etc/holidays.yaml for the current year and the two years to come
        """

        if self.holidays is None:
            self._etc_dir = self._sh._etc_dir
            conf_filename = os.path.join(self._sh._etc_dir,
                                         'holidays' + YAML_FILE)
            self.config = shyaml.yaml_load(conf_filename)
            location = self.config.get('location', None)

            # prepopulate holidays for following years
            this_year = self.today().year
            self.years = [this_year, this_year + 1, this_year + 2]

            if location:
                country = location.get('country', 'DE')
                prov = location.get('province', None)
                state = location.get('state', None)
                try:
                    self.holidays = holidays.CountryHoliday(country,
                                                            years=self.years,
                                                            prov=prov,
                                                            state=state)
                except KeyError as e:
                    self.logger.error(
                        "Error initializing self.holidays: {}".format(e))
                try:
                    self.public_holidays = holidays.CountryHoliday(
                        country, years=self.years, prov=prov, state=state)
                except KeyError as e:
                    self.logger.error(
                        "Error initializing self.public_holidays: {}".format(
                            e))
            else:
                self.holidays = holidays.CountryHoliday('US',
                                                        years=self.years,
                                                        prov=None,
                                                        state=None)
                self.public_holidays = holidays.CountryHoliday(
                    'US', years=self.years, prov=None, state=None)

            if self.holidays is not None:
                c_logtext = self.translate('not defined')
                c_logcount = ''
                count = self._add_custom_holidays()
                if count > 0:
                    c_logcount = ' ' + str(count)
                    c_logtext = self.translate('defined')
                defined_state = ''
                # Test if class of self.holiday has an attribute 'state'
                try:
                    state = self.holidays.state
                except Exception as e:
                    state = self.holidays.subdiv

                # Test if class of self.holiday has an attribute 'prov'
                try:
                    prov = self.holidays.prov
                except Exception as e:
                    prov = self.holidays.subdiv
                    state = None

                if state is not None:
                    defined_state = ", state'" + state + "'"
                self.log_msg = self.translate(
                    "Using holidays for country '{country}', province '{province}'{state},{count} custom holiday(s) {defined}"
                )
                self.log_msg = self.log_msg.format(
                    country=self.holidays.country,
                    province=prov,
                    state=defined_state,
                    count=c_logcount,
                    defined=c_logtext)
                self.logger.info(self.log_msg)

                self.logger.info(self.translate('Defined holidays') + ':')
                for ft in sorted(self.holidays):
                    self.logger.info(' - {}: {}'.format(ft, self.holidays[ft]))

        return
Пример #28
0
    def __init__(self, smarthome):
        self._sh = smarthome

        global _scenes_instance
        if _scenes_instance is not None:
            import inspect
            curframe = inspect.currentframe()
            calframe = inspect.getouterframes(curframe, 2)
            logger.critical(
                "A second 'scenes' object has been created. There should only be ONE instance of class 'Scenes'!!! Called from: {} ({})"
                .format(calframe[1][1], calframe[1][3]))

        _scenes_instance = self

        self.items = Items.get_instance()
        self.logics = Logics.get_instance()

        self._scenes = {}
        self._learned_values = {}
        self._scenes_dir = smarthome._scenes_dir
        if not os.path.isdir(self._scenes_dir):
            logger.warning(
                "Directory scenes not found. Ignoring scenes.".format(
                    self._scenes_dir))
            return

        self._learned_values = {}
        #   for item in smarthome.return_items():
        for item in self.items.return_items():
            if item.type() == 'scene':
                self.scene_file = os.path.join(self._scenes_dir, item.id())

                scene_file_yaml = yaml.yaml_load(self.scene_file + '.yaml',
                                                 ordered=False,
                                                 ignore_notfound=True)
                if scene_file_yaml is not None:
                    # Reading yaml file with scene definition
                    for state in scene_file_yaml:
                        actions = scene_file_yaml[state].get('actions', None)
                        if actions is not None:
                            if isinstance(actions, dict):
                                actions = [actions]
                            if isinstance(actions, list):
                                for action in actions:
                                    if isinstance(action, dict):
                                        self._add_scene_entry(
                                            item, str(state),
                                            action.get('item', ''),
                                            str(action.get('value', '')),
                                            action.get('learn', ''),
                                            scene_file_yaml[state].get(
                                                'name', ''))
                                    else:
                                        logger.warning(
                                            "Scene {}, state {}: action '{}' is not a dict"
                                            .format(item, state, action))
                            else:
                                logger.warning(
                                    "Scene {}, state {}: actions are not a list"
                                    .format(item, state))
                    self._load_learned_values(str(item.id()))
                else:
                    # Trying to read conf file with scene definition
                    scene_conf_file = self.scene_file + '.conf'
                    try:
                        with open(scene_conf_file, 'r', encoding='UTF-8') as f:
                            reader = csv.reader(f, delimiter=' ')
                            for row in reader:
                                if row == []:  # ignore empty lines
                                    continue
                                if row[0][0] == '#':  # ignore comments
                                    continue
                                self._add_scene_entry(item, row[0], row[1],
                                                      row[2])
                    except Exception as e:
                        logger.warning(
                            "Problem reading scene file {0}: No .yaml or .conf file found with this name"
                            .format(self.scene_file))
                        continue
                item.add_method_trigger(self._trigger)
Пример #29
0
    def __init__(self, smarthome):
        self._sh = smarthome
        global _scenes_instance
        _scenes_instance = self
        self._scenes = {}
        self._learned_values = {}
        self._scenes_dir = smarthome.base_dir + '/scenes/'
        if not os.path.isdir(self._scenes_dir):
            logger.warning(
                "Directory scenes not found. Ignoring scenes.".format(
                    self._scenes_dir))
            return

        for item in smarthome.return_items():
            if item.type() == 'scene':
                scene_file = os.path.join(self._scenes_dir, item.id())

                scene_file_yaml = yaml.yaml_load(scene_file + '.yaml',
                                                 ordered=False,
                                                 ignore_notfound=True)
                if scene_file_yaml is not None:
                    # Reading yaml file with scene definition
                    for state in scene_file_yaml:
                        actions = scene_file_yaml[state]['actions']
                        if isinstance(actions, dict):
                            actions = [actions]
                        if isinstance(actions, list):
                            for action in actions:
                                if isinstance(action, dict):
                                    self._add_scene_entry(
                                        item, str(state),
                                        action.get('item', ''),
                                        str(action.get('value', '')),
                                        action.get('learn', ''),
                                        scene_file_yaml[state].get('name', ''))
                                else:
                                    logger.warning(
                                        "Scene {}, state {}: action '{}' is not a dict"
                                        .format(item, state, action))
                        else:
                            logger.warning(
                                "Scene {}, state {}: actions are not a list".
                                format(item, state))
                    self._load_learned_values(str(item.id()))
                else:
                    # Trying to read conf file with scene definition
                    scene_conf_file = scene_file + '.conf'
                    try:
                        with open(scene_conf_file, 'r', encoding='UTF-8') as f:
                            reader = csv.reader(f, delimiter=' ')
                            for row in reader:
                                if row == []:  # ignore empty lines
                                    continue
                                if row[0][0] == '#':  # ignore comments
                                    continue
                                self._add_scene_entry(item, row[0], row[1],
                                                      row[2])
                    except Exception as e:
                        logger.warning(
                            "Problem reading scene file {0}: {1}".format(
                                scene_file, e))
                        continue
                item.add_method_trigger(self._trigger)
Пример #30
0
    def __init__(self, sh, addon_name, addon_type, classpath=''):
        self._sh = sh
        self._addon_name = addon_name.lower()
        self._addon_type = addon_type

        self._log_premsg = "{} '{}': ".format(addon_type, self._addon_name)

#        logger.warning(self._log_premsg+"classpath = '{}'".format( classpath ) )
        if classpath == '':
            if addon_type == 'plugin':
                addon_type_dir = 'plugins'
            elif addon_type == 'module':
                addon_type_dir = 'modules'
            else:
                return
            self.relative_filename = os.path.join( addon_type_dir, self._addon_name, addon_type+YAML_FILE )
        else:
            self.relative_filename = os.path.join( classpath.replace('.', os.sep), addon_type+YAML_FILE )
#        logger.warning(self._log_premsg+"relative_filename = '{}'".format( self.relative_filename ) )

        # read definitions from metadata file        
        filename = os.path.join( self._sh.get_basedir(), self.relative_filename )
        self.meta = shyaml.yaml_load(filename, ordered=True)

        self.parameters = None
        self._paramlist = []
        self.itemdefinitions = None
        self._itemdeflist = []

        if self.meta != None:
            # read paramter and item definition sections
            if self._addon_type == 'module':
                self.parameters = self.meta.get(META_MODULE_PARAMETER_SECTION)
            else:
                self.parameters = self.meta.get(META_PLUGIN_PARAMETER_SECTION)
                self.itemdefinitions = self.meta.get(META_PLUGIN_ITEMATTRIBUTE_SECTION)

            # test validity of paramter definition section
            if self.parameters is not None:
                self._paramlist = list(self.parameters.keys())
                logger.info(self._log_premsg+"Metadata paramlist = '{}'".format( str(self._paramlist) ) )
            if  self.parameters is not None:
                self._test_definitions(self._paramlist, self.parameters)
            else:
                logger.info(self._log_premsg+"has no parameter definitions in metadata")

            # test validity of item definition section
            if self.itemdefinitions != None:
                self._itemdeflist = list(self.itemdefinitions.keys())
                logger.info(self._log_premsg+"Metadata itemdeflist = '{}'".format( str(self._itemdeflist) ) )
            if  self.itemdefinitions is not None:
                self._test_definitions(self._itemdeflist, self.itemdefinitions)
            else:
                logger.info(self._log_premsg+"has no item definitions in metadata")
            
        # Read global metadata for addon
        if self.meta != None:
            self.addon_metadata = self.meta.get(addon_type)
        else:
            self.addon_metadata = None
        
        return
Пример #31
0
    def __init__(self, sh, addon_name, addon_type, classpath=''):
        self._sh = sh
        self._addon_name = addon_name.lower()
        self._addon_type = addon_type
        self._paramlist = []

        self._log_premsg = "{} '{}': ".format(addon_type, self._addon_name)

        #        logger.warning(self._log_premsg+"classpath = '{}'".format( classpath ) )
        if classpath == '':
            if addon_type == 'plugin':
                addon_type_dir = 'plugins'
            elif addon_type == 'module':
                addon_type_dir = 'modules'
            else:
                return
            self.relative_filename = os.path.join(addon_type_dir,
                                                  self._addon_name,
                                                  addon_type + YAML_FILE)
        else:
            self.relative_filename = os.path.join(
                classpath.replace('.', os.sep), addon_type + YAML_FILE)
#        logger.warning(self._log_premsg+"relative_filename = '{}'".format( self.relative_filename ) )

        self.parameters = None
        filename = os.path.join(self._sh.get_basedir(), self.relative_filename)
        self.meta = shyaml.yaml_load(filename, ordered=True)
        if self.meta != None:
            if self._addon_type == 'module':
                self.parameters = self.meta.get(META_MODULE_PARAMETER_SECTION)
            else:
                self.parameters = self.meta.get(META_PLUGIN_PARAMETER_SECTION)
            if self.parameters != None:
                self._paramlist = list(self.parameters.keys())
                logger.info(
                    self._log_premsg +
                    "Metadata paramlist = '{}'".format(str(self._paramlist)))

        # Test parameter definitions for validity
        for param in self._paramlist:
            logger.debug(self._log_premsg + "param = '{}'".format(str(param)))
            if self.parameters[param] != None:
                typ = str(self.parameters[param].get('type', FOO)).lower()
                # to be implemented: timeframe
                self.parameters[param]['listtype'] = ''
                if not (typ in META_DATA_TYPES):
                    # test for list with specified datatype
                    if typ.startswith('list(') and typ.endswith(')'):
                        self.parameters[param]['type'] = 'list'
                        subtyp = typ[5:]
                        subtyp = subtyp[:-1].strip()
                        if subtyp in META_DATA_TYPES:
                            self.parameters[param]['listtype'] = subtyp
                        else:
                            self.parameters[param]['listtype'] = FOO
                    else:
                        logger.error(
                            self._log_premsg +
                            "Invalid definition in metadata file '{}': type '{}' for parameter '{}' -> using type '{}' instead"
                            .format(self.relative_filename, typ, param, FOO))
                        self.parameters[param]['type'] = FOO
            else:
                #                self.parameters[param]['type'] = FOO
                pass

        # Read global metadata for addon

        if self.meta != None:
            self.addon_metadata = self.meta.get(addon_type)
        else:
            self.addon_metadata = None
Пример #32
0
def parse_yaml(filename,
               config=None,
               addfilenames=False,
               parseitems=False,
               struct_dict={}):
    """
    Load and parse a yaml configuration file and merge it to the configuration tree

    :param filename: Name of the configuration file
    :param config: Optional OrderedDict tree, into which the configuration should be merged
    :param addfilenames: x
    :param parseitems: x
    :param struct_dict: dictionary with stuct definitions (templates) for reading item tree
    :type filename: str
    :type config: bool
    :type addfilenames: bool
    :type parseitems: bool
    :type struct_dict: dict

    :return: The resulting merged OrderedDict tree
    :rtype: OrderedDict


    The config file should stick to the following setup:

    .. code-block:: yaml

       firstlevel:
           attribute1: xyz
           attribute2: foo
           attribute3: bar

           secondlevel:
               attribute1: abc
               attribute2: bar
               attribute3: foo

               thirdlevel:
                   attribute1: def
                   attribute2: barfoo
                   attribute3: foobar

           anothersecondlevel:
               attribute1: and so on

    where firstlevel, secondlevel, thirdlevel and anothersecondlevel are defined as items and attribute are their respective attribute - value pairs

    Valid characters for the items are a-z and A-Z plus any digit and underscore as second or further characters.
    Valid characters for the attributes are the same as for an item plus @ and *

    """
    if os.path.basename(filename).startswith('test_'):
        logger.info("parse_yaml: Parsing file {}".format(
            os.path.basename(filename)))
    if config is None:
        config = collections.OrderedDict()

    items = shyaml.yaml_load(filename, ordered=True)
    if items is not None:
        remove_comments(items, filename)
        remove_digits(items, filename)
        remove_reserved(items, filename)
        remove_keyword(items, filename)
        remove_invalid(items, filename)

        if addfilenames:
            #logger.debug("parse_yaml: Add filename = {} to items".format(os.path.basename(filename)))
            _add_filenames_to_config(items, os.path.basename(filename))

        if parseitems:
            # test if file contains 'struct' attribute and merge all items into config
            #logger.debug("parse_yaml: Checking if file {} contains 'struct' attribute".format(os.path.basename(filename)))

            search_for_struct_in_items(items, struct_dict, config,
                                       os.path.basename(filename))

            global special_listentry_found
            if special_listentry_found:
                remove_special_listentries(config, os.path.basename(filename))
            special_listentry_found = False

        if not parseitems:
            # if not parsing items
            config = merge(items, config, os.path.basename(filename),
                           'Config-Tree')
    return config
Пример #33
0
    def __init__(self, sh, addon_name, addon_type, classpath=''):
        self._sh = sh
        self._addon_name = addon_name.lower()
        self._addon_type = addon_type

        self._log_premsg = "{} '{}': ".format(addon_type, self._addon_name)

        #        logger.warning(self._log_premsg+"classpath = '{}'".format( classpath ) )
        if classpath == '':
            if addon_type == 'plugin':
                addon_type_dir = 'plugins'
            elif addon_type == 'module':
                addon_type_dir = 'modules'
            else:
                return
            self.relative_filename = os.path.join(addon_type_dir,
                                                  self._addon_name,
                                                  addon_type + YAML_FILE)
        else:
            self.relative_filename = os.path.join(
                classpath.replace('.', os.sep), addon_type + YAML_FILE)
#        logger.warning(self._log_premsg+"relative_filename = '{}'".format( self.relative_filename ) )

# read definitions from metadata file
        filename = os.path.join(self._sh.get_basedir(), self.relative_filename)
        self.meta = shyaml.yaml_load(filename, ordered=True)

        self.parameters = None
        self._paramlist = []
        self.itemdefinitions = None
        self._itemdeflist = []

        if self.meta != None:
            # read paramter and item definition sections
            if self._addon_type == 'module':
                self.parameters = self.meta.get(META_MODULE_PARAMETER_SECTION)
            else:
                self.parameters = self.meta.get(META_PLUGIN_PARAMETER_SECTION)
                self.itemdefinitions = self.meta.get(
                    META_PLUGIN_ITEMATTRIBUTE_SECTION)

            # test validity of paramter definition section
            if self.parameters is not None:
                self._paramlist = list(self.parameters.keys())
                logger.info(
                    self._log_premsg +
                    "Metadata paramlist = '{}'".format(str(self._paramlist)))
            if self.parameters is not None:
                self._test_definitions(self._paramlist, self.parameters)
            else:
                logger.info(self._log_premsg +
                            "has no parameter definitions in metadata")

            # test validity of item definition section
            if self.itemdefinitions != None:
                self._itemdeflist = list(self.itemdefinitions.keys())
                logger.info(self._log_premsg +
                            "Metadata itemdeflist = '{}'".format(
                                str(self._itemdeflist)))
            if self.itemdefinitions is not None:
                self._test_definitions(self._itemdeflist, self.itemdefinitions)
            else:
                logger.info(self._log_premsg +
                            "has no item definitions in metadata")

        # Read global metadata for addon
        if self.meta != None:
            self.addon_metadata = self.meta.get(addon_type)
        else:
            self.addon_metadata = None

        return
Пример #34
0
    def __init__(self, sh, addon_name, addon_type, classpath=''):
        self._sh = sh
        self._addon_name = addon_name.lower()
        self._addon_type = addon_type
        self._paramlist = []

        self._log_premsg = "{} '{}': ".format(addon_type, self._addon_name)

#        logger.warning(self._log_premsg+"classpath = '{}'".format( classpath ) )
        if classpath == '':
            if addon_type == 'plugin':
                addon_type_dir = 'plugins'
            elif addon_type == 'module':
                addon_type_dir = 'modules'
            else:
                return
            self.relative_filename = os.path.join( addon_type_dir, self._addon_name, addon_type+YAML_FILE )
        else:
            self.relative_filename = os.path.join( classpath.replace('.', os.sep), addon_type+YAML_FILE )
#        logger.warning(self._log_premsg+"relative_filename = '{}'".format( self.relative_filename ) )
        
        self.parameters = None
        filename = os.path.join( self._sh.get_basedir(), self.relative_filename )
        self.meta = shyaml.yaml_load(filename, ordered=True)
        if self.meta != None:
            if self._addon_type == 'module':
                self.parameters = self.meta.get(META_MODULE_PARAMETER_SECTION)
            else:
                self.parameters = self.meta.get(META_PLUGIN_PARAMETER_SECTION)
            if self.parameters != None:
                self._paramlist = list(self.parameters.keys())
                logger.info(self._log_premsg+"Metadata paramlist = '{}'".format( str(self._paramlist) ) )
            
        # Test parameter definitions for validity
        for param in self._paramlist:
            logger.debug(self._log_premsg+"param = '{}'".format( str(param) ) )
            if self.parameters[param] != None:
                typ = str(self.parameters[param].get('type', FOO)).lower()
                # to be implemented: timeframe
                self.parameters[param]['listtype'] = ''
                if not (typ in META_DATA_TYPES):
                    # test for list with specified datatype
                    if typ.startswith('list(') and typ.endswith(')'):
                        self.parameters[param]['type'] = 'list'
                        subtyp = typ[5:]
                        subtyp = subtyp[:-1].strip()
                        if subtyp in META_DATA_TYPES:
                            self.parameters[param]['listtype'] = subtyp
                        else:
                            self.parameters[param]['listtype'] = FOO
                    else:
                        logger.error(self._log_premsg+"Invalid definition in metadata file '{}': type '{}' for parameter '{}' -> using type '{}' instead".format( self.relative_filename, typ, param, FOO ) )
                        self.parameters[param]['type'] = FOO
            else:
#                self.parameters[param]['type'] = FOO
                pass
            
        # Read global metadata for addon
        
        if self.meta != None:
            self.addon_metadata = self.meta.get(addon_type)
        else:
            self.addon_metadata = None
Пример #35
0
    def __init__(self, sh, addon_name, addon_type, classpath=''):
        """
        Initialzes the metadata for an addon (plugin or module) from the definition file

        :param sh: SmartHomeNG main object
        :param addon_name:
        :param addon_type: 'plugin' or 'module'
        :param classpath:
        :type sh: object
        :type addon_name: str
        :type addon_type: str
        :type classpath: str
        """
        self._sh = sh
        self._addon_name = addon_name.lower()
        self._addon_type = addon_type

        self._log_premsg = "{} '{}': ".format(addon_type, self._addon_name)

        #        logger.warning(self._log_premsg+"classpath = '{}'".format( classpath ) )
        if classpath == '':
            if addon_type == 'plugin':
                addon_type_dir = 'plugins'
            elif addon_type == 'module':
                addon_type_dir = 'modules'
            else:
                return
            self.relative_filename = os.path.join(addon_type_dir,
                                                  self._addon_name,
                                                  addon_type + YAML_FILE)
        else:
            self.relative_filename = os.path.join(
                classpath.replace('.', os.sep), addon_type + YAML_FILE)
#        logger.warning(self._log_premsg+"relative_filename = '{}'".format( self.relative_filename ) )

# read complete definitions from metadata file
        filename = os.path.join(self._sh.get_basedir(), self.relative_filename)
        self.meta = shyaml.yaml_load(filename, ordered=True)

        self.parameters = None
        self._paramlist = []
        self.itemdefinitions = None
        self._itemdeflist = []
        self.itemstructs = None
        self._itemstructlist = []
        self.logic_parameters = None
        self._logic_paramlist = []
        self.plugin_functions = None
        self._plugin_functionlist = []

        if self.meta is not None:
            # read paramter and item definition sections
            if self._addon_type == 'module':
                self.parameters = self.meta.get(META_MODULE_PARAMETER_SECTION)
                self.itemstructs = self.meta.get(META_STRUCT_SECTION)
            else:
                self.parameters = self.meta.get(META_PLUGIN_PARAMETER_SECTION)
                self.itemdefinitions = self.meta.get(
                    META_PLUGIN_ITEMATTRIBUTE_SECTION)
                self.itemstructs = self.meta.get(META_STRUCT_SECTION)
                self.logic_parameters = self.meta.get(
                    META_PLUGIN_LOGIC_PARAMETER_SECTION)
                self.plugin_functions = self.meta.get(
                    META_PLUGIN_FUNCTION_SECTION)

            # test validity of parameter definition section
            if self.parameters is not None:
                if self.parameters == 'NONE':
                    self.parameters = None
                else:
                    self._paramlist = list(self.parameters.keys())
                    logger.info(self._log_premsg +
                                "Metadata paramlist = '{}'".format(
                                    str(self._paramlist)))
            if self.parameters is not None:
                self._test_definitions(self._paramlist, self.parameters)
            else:
                logger.debug(self._log_premsg +
                             "has no parameter definitions in metadata")

            # test validity of item definition section
            if self.itemdefinitions is not None:
                if self.itemdefinitions == 'NONE':
                    self.itemdefinitions = None
                else:
                    self._itemdeflist = list(self.itemdefinitions.keys())
                    logger.info(self._log_premsg +
                                "Metadata itemdeflist = '{}'".format(
                                    str(self._itemdeflist)))
            if self.itemdefinitions is not None:
                self._test_definitions(self._itemdeflist, self.itemdefinitions)
            else:
                logger.debug(self._log_premsg +
                             "has no item definitions in metadata")

            # test validity of logic-parameter definition section
            if self.logic_parameters is not None:
                if self.logic_parameters == 'NONE':
                    self.logic_parameters = None
                else:
                    self._logic_paramlist = list(self.logic_parameters.keys())
                    logger.info(self._log_premsg +
                                "Metadata logic_paramlist = '{}'".format(
                                    str(self._logic_paramlist)))
            if self.logic_parameters is not None:
                self._test_definitions(self._logic_paramlist,
                                       self.logic_parameters)
            else:
                logger.debug(self._log_premsg +
                             "has no logic-parameter definitions in metadata")

            # test validity of plugin-function definition section
            if self.plugin_functions is not None:
                if self.plugin_functions == 'NONE':
                    self.plugin_functions = None
                else:
                    self._plugin_functionlist = list(
                        self.plugin_functions.keys())
                    logger.info(self._log_premsg +
                                "Metadata plugin_functionlist = '{}'".format(
                                    str(self._plugin_functionlist)))
            if self.plugin_functions is not None:
                # self._test_definitions(self._plugin_functionlist, self.plugin_functions)
                pass
                dummy = self.get_plugin_function_defstrings(with_type=False,
                                                            with_default=False)
                dummy = self.get_plugin_function_defstrings(with_type=True,
                                                            with_default=False)
                dummy = self.get_plugin_function_defstrings(with_type=False,
                                                            with_default=True)
                dummy = self.get_plugin_function_defstrings(with_type=True,
                                                            with_default=True)
            else:
                logger.debug(self._log_premsg +
                             "has no plugin-function definitions in metadata")

            # test validity of structs definition section
            if self.itemstructs is not None:
                if self.itemstructs == 'NONE':
                    self.itemstructs = None
                else:
                    logger.info(self._log_premsg +
                                "Metadata itemstructlist = '{}'".format(
                                    self._itemstructlist))
#                    for struct in self._itemstructlist:
#                        for i in self.itemstructs[struct]:
#                            self.itemstructs[struct][i] = dict(self.itemstructs[struct][i])
#                            for si in self.itemstructs[struct][i]:
#                                if type(self.itemstructs[struct][i][si]) is collections.OrderedDict:
#                                    self.itemstructs[struct][i][si] = dict(self.itemstructs[struct][i][si])
#                        logger.info(self._log_premsg + "Metadata itemstruct '{}' = '{}'".format(struct, dict(self.itemstructs[struct])))
#            if self.itemstructs is not None:
##                self._test_definitions(self._itemdeflist, self.itemdefinitions)
#                pass
            else:
                logger.info(self._log_premsg +
                            "has no item-struct definitions in metadata")

        # Read global metadata for addon (either 'plugin' or 'module'
        if self.meta is not None:
            self.addon_metadata = self.meta.get(addon_type)
        else:
            self.addon_metadata = None

        return