Exemple #1
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
Exemple #2
0
def import_user_module(m):
    """
    Import a module with userfunctions

    :param m: name of module to import from <shng_base_dir>/functions

    :return: True, if import was successful
    """
    modulename = _uf_subdir + '.' + m

    import importlib
    try:
        exec(f"globals()['{m}']=importlib.import_module('{modulename}')")
    except Exception as e:
        _logger.error(
            translate("Error importing userfunctions from '{module}': {error}",
                      {
                          'module': m,
                          'error': e
                      }))
        return False
    else:
        global _uf_version
        _uf_version = '?.?.?'
        try:
            exec(f"globals()['_uf_version'] = {m}._VERSION")
        except:
            exec(f"{m}._VERSION = _uf_version")

        global _uf_description
        _uf_description = '?'
        try:
            exec(f"globals()['_uf_description'] = {m}._DESCRIPTION")
        except:
            exec(f"{m}._DESCRIPTION = _uf_description")

        _logger.notice(
            translate(
                "Imported userfunctions from '{mmodule}' v{version} - {description}",
                {
                    'module': m,
                    'version': _uf_version,
                    'description': _uf_description
                }))

        return True
Exemple #3
0
    def reload_scenes(self):
        """
        Reload defined scenes with learned values from ../scene directory

        :return:
        """

        self._load_scenes()
        logger.notice(translate("Reloaded all scenes"))
        return True
Exemple #4
0
 def get_scene_action_name(self, scenename, action):
     """
     Returns the name of a scene-action
     """
     action = str(action)
     try:
         return self._scenes[scenename][action][0][2]
     except:
         logger.warning(translate("get_scene_action_name: " + "unable to get self._scenes['{scenename}']['{action}'][0][2] <- {res}", {'scenename': scenename, 'action': action, 'res': self._scenes[scenename][action][0]}))
         return ''
Exemple #5
0
def reload(userlib):

    import importlib

    if userlib in _user_modules:
        try:
            exec(f"importlib.reload({userlib})")
        except Exception as e:
            if str(e) == f"name '{userlib}' is not defined":
                _logger.warning(
                    translate(
                        "Error reloading userfunctions Modul '{module}': Module is not loaded, trying to newly import userfunctions '{module}' instead",
                        {'module': userlib}))
                if import_user_module(userlib):
                    return True
                else:
                    return False
            else:
                _logger.error(
                    translate(
                        "Error reloading userfunctions '{module}': {error} - old version of '{module}' is still active",
                        {
                            'module': userlib,
                            'error': e
                        }))
                return False

        else:
            _logger.notice(
                translate("Reloaded userfunctions '{module}'",
                          {'module': userlib}))
            return True
    else:
        if import_user_module(userlib):
            #_logger.notice(translate("Reload: Loaded new userfunctions '{module}'", {'module': userlib}))
            return True
        else:
            _logger.error(
                translate("Reload: Userfunctions '{module}' do not exist",
                          {'module': userlib}))
            return False
Exemple #6
0
def reload_all():

    if _user_modules == []:
        _logger.warning(
            translate('No userfunctions are loaded, nothing to reload'))
        return False
    else:
        result = True
        for lib in _user_modules:
            if not reload(lib):
                result = False
        return result
Exemple #7
0
    def _trigger(self, item, caller, source, dest):
        """
        Trigger a scene
        """
        if not item.id() in self._scenes:
            return
        if str(item()&127) in self._scenes[item.id()]:
            state = item()
            if Utils.is_int(state):
                state = int(state)
            else:
                logger.error(translate("Invalid state '{state}' for scene {scene}", {'state': state, 'scene': item.id()}))
                return

            if (state >= 0) and (state < 64):
                # set state
                self._trigger_setstate(item, state, caller, source, dest)
            elif (state >= 128) and (state < 128+64):
                # learn state
                self._trigger_learnstate(item, state&127, caller, source, dest)
            else:
                logger.error(translate("Invalid state '{state}' for scene {scene}", {'state': state, 'scene': item.id()}))
Exemple #8
0
    def _add_scene_entry(self, item, state, ditemname, value, learn=False, name=''):
        """
        Adds a single assignement entry to the loaded scenes

        :param item: item defing the scene (type: scene)
        :param row: list of: state number, item to assign to, value to assign to item
        :param name: name of the scene state
        :type item: item object
        :type row: list (with 3 entries)
        :type name: str
        """
        logger.debug("_add_scene_entry: item = {}, state = {}, ditemname = {}, value = {}, learn = {}, name = {}".format(item.id(), state, ditemname, value, learn, name))
        value = item.get_stringwithabsolutepathes(value, 'sh.', '(', 'scene')
#        ditem = self._sh.return_item(item.get_absolutepath(ditemname, attribute='scene'))
        ditem = self.items.return_item(item.get_absolutepath(ditemname, attribute='scene'))

        if learn:
            rvalue = self._eval(value)
            if str(rvalue) != value:
                logger.warning(translate("_add_scene_entry - " + "Learn set to 'False', because '{rvalue}' != '{value}'", {'rvalue': rvalue, 'value': value}))
                learn = False

        if ditem is None:
            ditem = self.logics.return_logic(ditemname)
            if ditem is None:
                logger.warning(translate("Could not find item or logic '{ditemname}' specified in {file}", {'ditemname': ditemname, 'file': self.scene_file}))
                return

        if item.id() in self._scenes:
            if state in self._scenes[item.id()]:
                self._scenes[item.id()][state].append([ditem, value, name, learn])
            else:
                self._scenes[item.id()][state] = [[ditem, value, name, learn]]
        else:
            self._scenes[item.id()] = {state: [[ditem, value, name, learn]]}
        return
Exemple #9
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(translate("A second 'scenes' object has been created. There should only be ONE instance of class 'Scenes'!!! Called from: {frame1} ({frame2})", {'frame1': calframe[1][1], 'frame2': calframe[1][3]}))

        _scenes_instance = self

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

        self._load_scenes()
        return
Exemple #10
0
    def _eval(self, value):
        """
        Evaluate a scene value

        :param value: value expression to evaluate
        :type value: str

        :return: evaluated value or None
        :rtype: type of evaluated expression or None
        """
        sh = self._sh
        shtime = Shtime.get_instance()
        items = Items.get_instance()
        import math
        import lib.userfunctions as uf

        try:
            rvalue = eval(value)
        except Exception as e:
            logger.warning(" - " + translate("Problem evaluating: {value} - {exception}", {'value': value, 'exception': e}))
            return value
        return rvalue