diff --git a/.gitignore b/.gitignore
index c7ee02c58f..c87a1fe575 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,3 +65,31 @@ requirements/conf_all.txt
 **/.vscode/
 /custom_plugins
 /priv_tools
+
+
+# ./etc -- ignore everything
+etc/*
+# except yaml default-files
+!etc/admin.yaml.default
+!etc/holidays.yaml.default
+!etc/logging.yaml.default
+!etc/logic.yaml.default
+!etc/module.yaml.default
+!etc/plugin.yaml.default
+!etc/smarthome.yaml.default
+
+# ./items -- ignore everything
+items/
+
+# ./logics -- ignore everything
+logics/
+
+# ./functions -- ignore everything
+functions/
+
+# ./structs -- ignore everything
+structs/
+
+# ./scenes -- ignore everything
+scenes/
+
diff --git a/etc/.gitignore b/etc/.gitignore
deleted file mode 100644
index f29354a153..0000000000
--- a/etc/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-# ignore everything
-*
-# except .gitignore
-!.gitignore
-#!logging.yaml
-# except yaml default-files
-!admin.yaml.default
-!holidays.yaml.default
-!logging.yaml.default
-!logic.yaml.default
-!module.yaml.default
-!plugin.yaml.default
-!smarthome.yaml.default
diff --git a/functions/.gitignore b/functions/.gitignore
deleted file mode 100644
index 5b5726d9f4..0000000000
--- a/functions/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-# ignore everything
-*
-# except .gitignore and template file
-!.gitignore
-!uf.tpl
diff --git a/items/.gitignore b/items/.gitignore
deleted file mode 100644
index 6c22af6ce7..0000000000
--- a/items/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-# ignore everything
-*
-# except .gitignore
-!.gitignore
diff --git a/lib/backup.py b/lib/backup.py
index a06b4fc7d4..b088572f91 100644
--- a/lib/backup.py
+++ b/lib/backup.py
@@ -23,16 +23,15 @@
 This library creates a zip file with the configuration of SmartHomeNG.
 """
 
-import copy
 import glob
 import logging
 import zipfile
-import shutil
 import time
 import os
 from datetime import datetime
 from lib.shtime import Shtime
 from lib.shpypi import Shpypi
+from lib.constants import (BASE_LOG, BASE_LOGIC, BASE_MODULE, BASE_PLUGIN, BASE_SH, BASE_STRUCT, BASE_HOLIDAY, DIR_ETC, DIR_ITEMS, DIR_LOGICS, DIR_SCENES, DIR_STRUCTS, DIR_UF, DIR_VAR, YAML_FILE, CONF_FILE)
 
 logger = logging.getLogger(__name__)
 
@@ -59,8 +58,8 @@ def make_backup_directories(base_dir):
     :return:
     """
     global backup_dir
-    backup_dir = os.path.join(base_dir, 'var','backup')
-    restore_dir = os.path.join(base_dir, 'var','restore')
+    backup_dir = os.path.join(base_dir, DIR_VAR, 'backup')
+    restore_dir = os.path.join(base_dir, DIR_VAR, 'restore')
 
     if not os.path.isdir(backup_dir):
         try:
@@ -79,7 +78,6 @@ def make_backup_directories(base_dir):
     return True
 
 
-
 def create_backup(conf_base_dir, base_dir, filename_with_timestamp=False, before_restore=False, config_etc=False):
     """
     Create a zip file containing the configuration of SmartHomeNG. The zip file is stored in var/backup
@@ -95,7 +93,7 @@ def create_backup(conf_base_dir, base_dir, filename_with_timestamp=False, before
     """
 
     make_backup_directories(base_dir)
-    backup_dir = os.path.join(base_dir, 'var','backup')
+    backup_dir = os.path.join(base_dir, DIR_VAR, 'backup')
 
     backup_filename = 'shng_config_backup'
     if before_restore:
@@ -104,6 +102,9 @@ def create_backup(conf_base_dir, base_dir, filename_with_timestamp=False, before
         backup_filename += '_' + get_backupdate() + '_' + get_backuptime()
     backup_filename += '.zip'
 
+    # let backup.py create file/directory names the "old way", because this can
+    # be invoked by command line without a working SmartHome instance and so
+    # needs to create the paths for itself. Hope this always works... :)
     etc_dir = os.path.join(conf_base_dir, 'etc')
 
     if config_etc:
@@ -111,33 +112,30 @@ def create_backup(conf_base_dir, base_dir, filename_with_timestamp=False, before
     else:
         conf_dir = base_dir
 
-    items_dir = os.path.join(conf_dir, 'items')
-    logic_dir = os.path.join(conf_dir, 'logics')
-    scenes_dir = os.path.join(conf_dir, 'scenes')
-    structs_dir = os.path.join(conf_dir, 'structs')
-    uf_dir = os.path.join(conf_dir, 'functions')
-    var_dir = os.path.join(conf_dir, 'var')
+    items_dir = os.path.join(conf_dir, DIR_ITEMS)
+    logic_dir = os.path.join(conf_dir, DIR_LOGICS)
+    scenes_dir = os.path.join(conf_dir, DIR_SCENES)
+    structs_dir = os.path.join(conf_dir, DIR_STRUCTS)
+    uf_dir = os.path.join(conf_dir, DIR_UF)
+    var_dir = os.path.join(conf_dir, DIR_VAR)
     esphome_conf_dir = os.path.join(conf_dir, 'var', 'esphome', 'config')
 
     # create new zip file
-    #backupzip = zipfile.ZipFile(backup_dir + os.path.sep + backup_filename, mode='w')
     backupzip = zipfile.ZipFile(backup_dir + os.path.sep + backup_filename, mode='w', compression=zipfile.ZIP_DEFLATED)
-    #backupzip = zipfile.ZipFile(backup_dir + os.path.sep + backup_filename, mode='w', compression=zipfile.ZIP_STORED)
 
     # backup files from /etc
-    #logger.warning("- etc_dir = {}".format(etc_dir))
     source_dir = etc_dir
     arc_dir = 'etc'
-    backup_file(backupzip, source_dir, arc_dir, 'holidays.yaml')
-    backup_file(backupzip, source_dir, arc_dir, 'logging.yaml')
-    backup_file(backupzip, source_dir, arc_dir, 'logic.yaml')
-    backup_file(backupzip, source_dir, arc_dir, 'module.yaml')
-    backup_file(backupzip, source_dir, arc_dir, 'plugin.yaml')
-    backup_file(backupzip, source_dir, arc_dir, 'smarthome.yaml')
-    backup_file(backupzip, source_dir, arc_dir, 'admin.yaml')
-
-    backup_file(backupzip, source_dir, arc_dir, 'struct.yaml')
-    struct_files = glob.glob(os.path.join( etc_dir, 'struct_*.yaml'))
+    backup_file(backupzip, source_dir, arc_dir, BASE_HOLIDAY + YAML_FILE)
+    backup_file(backupzip, source_dir, arc_dir, BASE_LOG + YAML_FILE)
+    backup_file(backupzip, source_dir, arc_dir, BASE_LOGIC + YAML_FILE)
+    backup_file(backupzip, source_dir, arc_dir, BASE_MODULE + YAML_FILE)
+    backup_file(backupzip, source_dir, arc_dir, BASE_PLUGIN + YAML_FILE)
+    backup_file(backupzip, source_dir, arc_dir, BASE_SH + YAML_FILE)
+    backup_file(backupzip, source_dir, arc_dir, 'admin' + YAML_FILE)
+
+    backup_file(backupzip, source_dir, arc_dir, BASE_STRUCT + YAML_FILE)
+    struct_files = glob.glob(os.path.join(etc_dir, BASE_STRUCT + '_*' + YAML_FILE))
     for pn in struct_files:
         fn = os.path.split(pn)[1]
         backup_file(backupzip, source_dir, arc_dir, fn)
@@ -149,31 +147,31 @@ def create_backup(conf_base_dir, base_dir, filename_with_timestamp=False, before
     backup_directory(backupzip, etc_dir, '.key')
 
     # backup files from /items
-    #logger.warning("- items_dir = {}".format(items_dir))
+    # logger.warning("- items_dir = {}".format(items_dir))
     backup_directory(backupzip, items_dir)
 
     # backup files from /logic
-    #logger.warning("- logic_dir = {}".format(logic_dir))
+    # logger.warning("- logic_dir = {}".format(logic_dir))
     backup_directory(backupzip, logic_dir, '.py')
     backup_directory(backupzip, logic_dir, '.txt')
 
     # backup files from /scenes
-    #logger.warning("- scenes_dir = {}".format(scenes_dir))
-    backup_directory(backupzip, scenes_dir, '.yaml')
-    backup_directory(backupzip, scenes_dir, '.conf')
+    # logger.warning("- scenes_dir = {}".format(scenes_dir))
+    backup_directory(backupzip, scenes_dir, YAML_FILE)
+    backup_directory(backupzip, scenes_dir, CONF_FILE)
 
     # backup files from /structs
-    #logger.warning("- structs_dir = {}".format(structs_dir))
-    backup_directory(backupzip, structs_dir, '.yaml')
+    # logger.warning("- structs_dir = {}".format(structs_dir))
+    backup_directory(backupzip, structs_dir, YAML_FILE)
 
     # backup files from /functions
-    #logger.warning("- uf_dir = {}".format(uf_dir))
+    # logger.warning("- uf_dir = {}".format(uf_dir))
     backup_directory(backupzip, uf_dir, '.*')
 
     # backup files for infos-directory
     source_dir = var_dir
     arc_dir = 'infos'
-    backup_file(backupzip, source_dir, arc_dir, 'systeminfo.yaml')
+    backup_file(backupzip, source_dir, arc_dir, 'systeminfo' + YAML_FILE)
 
     # backup files from /var/esphome/config
     backup_directory(backupzip, esphome_conf_dir, '.yaml', 'esphome_config')
@@ -190,7 +188,7 @@ def create_backup(conf_base_dir, base_dir, filename_with_timestamp=False, before
     logger.info("Zipped files: {}".format(zipped_files))
     backupzip.close()
 
-    #logger.warning("- backup_dir = {}".format(backup_dir))
+    # logger.warning("- backup_dir = {}".format(backup_dir))
 
     shtime = Shtime.get_instance()
     if shtime == None:
@@ -225,7 +223,6 @@ def get_lastbackuptime():
     return ""
 
 
-
 def backup_file(backupzip, source_dir, arc_dir, filename):
     """
     Backup one file to a zip-archive
@@ -237,33 +234,30 @@ def backup_file(backupzip, source_dir, arc_dir, filename):
     """
     if not filename.startswith('.'):
         if os.path.isfile(os.path.join(source_dir, filename)):
-            #logger.debug("Zipping file: {}".format(filename))
+            # logger.debug("Zipping file: {}".format(filename))
             backupzip.write(os.path.join(source_dir, filename), arcname=os.path.join(arc_dir, filename))
     return
 
 
-def backup_directory(backupzip, source_dir, extenstion='.yaml', dest_dir=None):
+def backup_directory(backupzip, source_dir, extension=YAML_FILE, dest_dir=None):
     """
     Backup all files with a certain extension from the given directory to a zip-archive
 
     :param backupzip: Name of the zip-archive (full pathname)
     :param source_dir: Directory where the yaml-files to backup are located
-    :param extenstion: Extension of the files to backup (default is .yaml)
+    :param extension: Extension of the files to backup (default is .yaml)
     """
     if os.path.isdir(source_dir):
         path = source_dir.split(os.path.sep)
-        dir = path[len(path)-1]
+        dir = path[len(path) - 1]
         if dest_dir is None:
             arc_dir = dir + os.path.sep
         else:
             arc_dir = dest_dir + os.path.sep
-        files = []
         for filename in os.listdir(source_dir):
-            if filename.endswith(extenstion) or extenstion == '.*':
+            if filename.endswith(extension) or extension == '.*':
                 backup_file(backupzip, source_dir, arc_dir, filename)
 
-    return
-
 
 def restore_backup(conf_base_dir, base_dir, config_etc=False):
     """
@@ -280,7 +274,7 @@ def restore_backup(conf_base_dir, base_dir, config_etc=False):
 
     :return:
     """
-    logger.info(f"Beginning restore of configuration")
+    logger.info("Beginning restore of configuration")
 
     make_backup_directories(base_dir)
     restore_dir = os.path.join(base_dir, 'var', 'restore')
@@ -292,11 +286,11 @@ def restore_backup(conf_base_dir, base_dir, config_etc=False):
     else:
         conf_dir = base_dir
 
-    items_dir = os.path.join(conf_dir, 'items')
-    logic_dir = os.path.join(conf_dir, 'logics')
-    scenes_dir = os.path.join(conf_dir, 'scenes')
-    structs_dir = os.path.join(conf_dir, 'structs')
-    uf_dir = os.path.join(conf_dir, 'functions')
+    items_dir = os.path.join(conf_dir, DIR_ITEMS)
+    logic_dir = os.path.join(conf_dir, DIR_LOGICS)
+    scenes_dir = os.path.join(conf_dir, DIR_SCENES)
+    structs_dir = os.path.join(conf_dir, DIR_STRUCTS)
+    uf_dir = os.path.join(conf_dir, DIR_UF)
     esphome_conf_dir = os.path.join(conf_dir, 'var', 'esphome', 'config')
 
     archive_file = ''
@@ -317,39 +311,40 @@ def restore_backup(conf_base_dir, base_dir, config_etc=False):
         return
     restorezip_filename = os.path.join(restore_dir, archive_file)
 
-    logger.notice(f"Restoring configuration from file {restorezip_filename}")
+    # TODO: as logger has no "notice" method, for the time being log as "info""
+    logger.info(f"Restoring configuration from file {restorezip_filename}")
 
-    logger.info(f"Creating a backup of the current configuration before restoring configuration from zip-file")
+    logger.info("Creating a backup of the current configuration before restoring configuration from zip-file")
     create_backup(conf_base_dir, base_dir, True, True)
     overwrite = True
 
     # open existing zip file
     restorezip = zipfile.ZipFile(restorezip_filename, mode='r')
-    #restorezip = zipfile.ZipFile(restorezip_filename, mode='r', compression=zipfile.ZIP_STORED)
+    # restorezip = zipfile.ZipFile(restorezip_filename, mode='r', compression=zipfile.ZIP_STORED)
 
     # restore files to /etc
-    restore_directory(restorezip, 'etc', etc_dir, overwrite)
+    restore_directory(restorezip, DIR_ETC, etc_dir, overwrite)
 
     # restore files to /items
-    restore_directory(restorezip, 'items', items_dir, overwrite)
+    restore_directory(restorezip, DIR_ITEMS, items_dir, overwrite)
 
-    # restore files to /logic
-    restore_directory(restorezip, 'logics', logic_dir, overwrite)
+    # backup files from /logic
+    restore_directory(restorezip, DIR_LOGICS, logic_dir, overwrite)
 
-    # restore files to /scenes
-    restore_directory(restorezip, 'scenes', scenes_dir, overwrite)
+    # backup files from /scenes
+    restore_directory(restorezip, DIR_SCENES, scenes_dir, overwrite)
 
-    # restore files to /structs
-    restore_directory(restorezip, 'structs', structs_dir, overwrite)
+    # backup files from /structs
+    restore_directory(restorezip, DIR_STRUCTS, structs_dir, overwrite)
 
-    # restore files to /functions
-    restore_directory(restorezip, 'functions', uf_dir, overwrite)
+    # backup files from /functions
+    restore_directory(restorezip, DIR_UF, uf_dir, overwrite)
 
     # restore files to /var/esphome/config
     restore_directory(restorezip, 'esphome_config', esphome_conf_dir, overwrite)
 
     # mark zip-file as restored
-    logger.info(f"- marking zip-file as restored")
+    logger.info("- marking zip-file as restored")
     os.rename(restorezip_filename, restorezip_filename + '.done')
 
     # delete last backup timestamp
@@ -359,7 +354,7 @@ def restore_backup(conf_base_dir, base_dir, config_etc=False):
     except OSError:
         pass
 
-    logger.info(f"Finished restore of configuration")
+    logger.info("Finished restore of configuration")
     return restorezip_filename
 
 
@@ -383,7 +378,7 @@ def restore_file(restorezip, arc_dir, filename, dest_dir, overwrite=False):
 
     # copy file (taken from zipfile's extract)
     zip_info = restorezip.getinfo(os.path.join(arc_dir, filename))
-    if not(zip_info.filename[-1] == '/'):
+    if not zip_info.filename[-1] == '/':
         zip_info.filename = os.path.basename(zip_info.filename)
     restorezip.extract(zip_info, path=dest_dir, pwd=None)
 
@@ -392,9 +387,6 @@ def restore_file(restorezip, arc_dir, filename, dest_dir, overwrite=False):
     os.utime(os.path.join(dest_dir, filename), (date_time, date_time))
 
 
-    return
-
-
 def restore_directory(restorezip, arc_dir, dest_dir, overwrite=False):
     """
     Restore all files from a certain archive directory to a given destination directory
@@ -406,9 +398,8 @@ def restore_directory(restorezip, arc_dir, dest_dir, overwrite=False):
     """
     logger.info(f"- Restoring directory {dest_dir}")
     for fn in restorezip.namelist():
-        if fn.startswith(arc_dir+'/'):
+        if fn.startswith(arc_dir + '/'):
             restore_file(restorezip, arc_dir, os.path.basename(fn), dest_dir, overwrite)
-    return
 
 
 def write_lastbackuptime(timestamp, timefile):
@@ -420,4 +411,4 @@ def write_lastbackuptime(timestamp, timefile):
     :type pid: int
     :type pidfile: str
     """
-
+    pass
diff --git a/lib/config.py b/lib/config.py
index 0fdeddb43b..85fdebaa58 100644
--- a/lib/config.py
+++ b/lib/config.py
@@ -66,11 +66,10 @@ def parse_basename(basename, configtype=''):
     if config == {}:
         config = parse(basename + CONF_FILE)
     if config == {}:
-        if not (configtype == 'logics'):
-            if configtype == 'module':
-                logger.warning(f"No valid file '{basename}.yaml' found with {configtype} configuration")
-            else:
-                logger.error(f"No valid file '{basename}.*' found with {configtype} configuration")
+        if configtype == 'module':
+            logger.warning(f"No valid file '{basename}{YAML_FILE}' found with {configtype} configuration")
+        elif configtype != 'logics':
+            logger.error(f"No valid file '{basename}.*' found with {configtype} configuration")
     return config
 
 
diff --git a/lib/constants.py b/lib/constants.py
index 72a2a973e9..11c6c358a3 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -91,6 +91,32 @@
 YAML_FILE = '.yaml'
 DEFAULT_FILE = '.default'
 
+DIR_VAR = 'var'
+DIR_LIB = 'lib'
+DIR_CACHE = 'cache'
+DIR_ENV = 'env'
+DIR_TPL = 'templates'
+DIR_PLUGINS = 'plugins'
+DIR_MODULES = 'modules'
+DIR_ETC = 'etc'
+DIR_ITEMS = 'items'
+DIR_STRUCTS = 'structs'
+DIR_LOGICS = 'logics'
+DIR_UF = 'functions'
+DIR_SCENES = 'scenes'
+
+BASE_SH = 'smarthome'
+BASE_LOG = 'logging'
+BASE_MODULE = 'module'
+BASE_PLUGIN = 'plugin'
+BASE_LOGIC = 'logic'
+BASE_STRUCT = 'struct'
+BASE_HOLIDAY = 'holidays'
+BASE_ADMIN = 'admin'
+
+DIRS = (DIR_VAR, DIR_LIB, DIR_CACHE, DIR_ENV, DIR_TPL, DIR_PLUGINS, DIR_MODULES, DIR_ETC, DIR_ITEMS, DIR_STRUCTS, DIR_LOGICS, DIR_UF, DIR_SCENES)
+BASES = (BASE_SH, BASE_LOG, BASE_MODULE, BASE_PLUGIN, BASE_LOGIC, BASE_STRUCT, BASE_HOLIDAY, BASE_ADMIN)
+FILES = DIRS + BASES
 
 #attributes for 'autotimer' parameter
 KEY_ATTRIB_COMPAT     = 'assign_compatibility'	# name of key in smarthome.yaml
diff --git a/lib/item/structs.py b/lib/item/structs.py
index 4a40ffc840..1abf76bccf 100644
--- a/lib/item/structs.py
+++ b/lib/item/structs.py
@@ -26,6 +26,7 @@
 
 import lib.shyaml as shyaml
 from lib.config import sanitize_items
+from lib.constants import (YAML_FILE, BASE_STRUCT, DIR_STRUCTS, DIR_ETC)
 
 logger = logging.getLogger(__name__)
 
@@ -48,8 +49,8 @@ def __init__(self, smarthome):
         self.logger = logging.getLogger(__name__)
         self._sh = smarthome
         self.save_joined_structs = False
-        self.etc_dir = self._sh.get_etcdir()
-        self.structs_dir = self._sh.get_structsdir()
+        self.etc_dir = self._sh.get_config_dir(DIR_ETC)
+        self.structs_dir = self._sh.get_config_dir(DIR_STRUCTS)
 
 
     def return_struct_definitions(self, all=True):
@@ -85,13 +86,13 @@ def load_definitions_from_etc(self):
         - structs are read in from ../etc/struct.yaml by this procedure
         - further structs are read in from ../etc/struct_<prefix>.yaml by this procedure
         """
-        self.load_struct_definitions_from_file(self.etc_dir, 'struct.yaml', '')
+        self.load_struct_definitions_from_file(self._sh.get_config_dir(DIR_ETC), BASE_STRUCT + YAML_FILE, '')
 
         # look for further struct files
         file_list = os.listdir(self.etc_dir)
         for filename in file_list:
-            if filename.startswith('struct_') and filename.endswith('.yaml'):
-                key_prefix = 'my.' + filename[7:-5]
+            if filename.startswith(BASE_STRUCT + '_') and filename.endswith(YAML_FILE):
+                key_prefix = 'my.' + filename[len(BASE_STRUCT):-len(YAML_FILE)]
                 self.load_struct_definitions_from_file(self.etc_dir, filename, key_prefix)
         return
 
@@ -117,11 +118,11 @@ def migrate_to_structs_dir(self):
         """
         fl = os.listdir(self.etc_dir)
         for filename in fl:
-            if filename.startswith('struct_') and filename.endswith('.yaml'):
-                dest_fn = filename[7:]
+            if filename.startswith(BASE_STRUCT + '_') and filename.endswith(YAML_FILE):
+                dest_fn = filename[len(BASE_STRUCT):]
                 self.migrate_one_file(filename, dest_fn)
 
-        filename = 'struct.yaml'
+        filename = BASE_STRUCT + YAML_FILE
         if os.path.isfile(os.path.join(self.etc_dir, filename)):
             dest_fn = 'global_structs.yaml'
             self.migrate_one_file(filename, dest_fn)
@@ -135,19 +136,19 @@ def load_definitions_from_structs(self):
 
         - structs are read in from ../structs/<name>.yaml by this procedure
         """
-        self.load_struct_definitions_from_file(self.etc_dir, 'struct.yaml', '')
+        self.load_struct_definitions_from_file(self._sh.get_config_dir(DIR_ETC), BASE_STRUCT + YAML_FILE, '')
         if os.path.isdir(self.structs_dir):
             # look for struct files
             file_list = os.listdir(self.structs_dir)
             for filename in file_list:
-                if not (filename.startswith('.')) and filename.endswith('.yaml'):
+                if not (filename.startswith('.')) and filename.endswith(YAML_FILE):
                     if filename == 'global_structs.yaml':
                         key_prefix = ''
                     else:
-                        key_prefix = 'my.' + filename[:-5]
+                        key_prefix = 'my.' + filename[:-len(YAML_FILE)]
                     self.load_struct_definitions_from_file(self.structs_dir, filename, key_prefix)
         else:
-            self.logger.notice("../structs does not exist")
+            self.logger.notice("../" + DIR_STRUCTS + " does not exist")
         return
 
 
diff --git a/lib/log.py b/lib/log.py
index dc2ed70c61..f200dfdb3d 100644
--- a/lib/log.py
+++ b/lib/log.py
@@ -34,6 +34,7 @@
 import collections
 
 import lib.shyaml as shyaml
+from lib.constants import YAML_FILE, DEFAULT_FILE, BASE_LOG, DIR_ETC, DIR_VAR
 
 logs_instance = None
 
@@ -67,13 +68,15 @@ def __init__(self, sh):
         return
 
 
-    def configure_logging(self, config_filename='logging.yaml'):
+    def configure_logging(self, config_filename=''):
 
+        if not config_filename:
+            config_filename = self._sh.get_config_file(BASE_LOG)
         config_dict = self.load_logging_config(config_filename, ignore_notfound=True)
 
         if config_dict == None:
             print()
-            print(f"ERROR: Invalid logging configuration in file '{os.path.join(self._sh.get_etcdir(), config_filename)}'")
+            print(f"ERROR: Invalid logging configuration in file '{config_filename}'")
             print()
             exit(1)
 
@@ -140,7 +143,7 @@ def configure_logging(self, config_filename='logging.yaml'):
             logging.config.dictConfig(config_dict)
         except Exception as e:
             print()
-            print(f"ERROR: dictConfig: Invalid logging configuration in file '{os.path.join(self._sh.get_etcdir(), config_filename)}'")
+            print(f"ERROR: dictConfig: Invalid logging configuration in file '{config_filename}'")
             print(f"       Exception: {e}")
             print()
             return e
@@ -237,15 +240,18 @@ def return_logs(self):
 
     # ---------------------------------------------------------------------------
 
-    def load_logging_config(self, filename='logging', ignore_notfound=False):
+    def load_logging_config(self, filename='', ignore_notfound=False):
         """
         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._sh.get_etcdir(), filename)
-        if not conf_filename.endswith('.yaml') and not conf_filename.endswith('.default'):
-            conf_filename += '.yaml'
+        if not filename:
+            conf_filename = self._sh.get_config_file(BASE_LOG)
+        else:
+            conf_filename = os.path.join(self._sh.get_config_dir(DIR_ETC), filename)
+        if not conf_filename.endswith(YAML_FILE) and not conf_filename.endswith(DEFAULT_FILE):
+            conf_filename += YAML_FILE
         result = shyaml.yaml_load(conf_filename, ignore_notfound)
 
         return result
@@ -257,7 +263,7 @@ def save_logging_config(self, logging_config, create_backup=False):
         """
         if logging_config is not None:
             logging_config['shng_version'] = self._sh.version.split('-')[0][1:]
-            conf_filename = os.path.join(self._sh.get_etcdir(), 'logging')
+            conf_filename = self._sh.get_config_file(BASE_LOG)
             shyaml.yaml_save_roundtrip(conf_filename, logging_config, create_backup=create_backup)
         return
 
@@ -269,7 +275,7 @@ def load_logging_config_for_edit(self):
         If logging.yaml does not contain a 'shng_version' key, a backup is created
         """
         #self.etc_dir = self._sh.get_etcdir()
-        conf_filename = os.path.join(self._sh.get_etcdir(), 'logging')
+        conf_filename = self._sh.get_config_file(BASE_LOG)
         logging_config = shyaml.yaml_load_roundtrip(conf_filename)
         self.logger.info("load_logging_config_for_edit: shng_version={}".format(logging_config.get('shng_version', None)))
 
@@ -787,7 +793,7 @@ def __init__(self, logname='undefined', maxlen=35, level=logging.NOTSET,
         self._cache = cache
         self._maxlen = maxlen
         # save cache files in var/log/cache directory
-        cache_directory = os.path.join(logs_instance._sh.get_vardir(), 'log'+os.path.sep, 'cache'+os.path.sep)
+        cache_directory = os.path.join(logs_instance._sh.get_config_dir(DIR_VAR), 'log'+os.path.sep, 'cache'+os.path.sep)
         if cache is True:
             if not os.path.isdir(cache_directory):
                 os.makedirs(cache_directory)
diff --git a/lib/logic.py b/lib/logic.py
index 1179237c05..c687c51119 100644
--- a/lib/logic.py
+++ b/lib/logic.py
@@ -59,7 +59,7 @@
 from lib.utils import Utils
 
 from lib.constants import PLUGIN_PARSE_LOGIC
-from lib.constants import (YAML_FILE, CONF_FILE)
+from lib.constants import (YAML_FILE, CONF_FILE, DIR_LOGICS, DIR_ETC, BASE_LOGIC, BASE_ADMIN)
 
 from lib.item import Items
 from lib.plugin import Plugins
@@ -97,8 +97,9 @@ def __init__(self, smarthome, userlogicconf, envlogicconf):
         self._userlogicconf = userlogicconf
         self._env_dir = smarthome._env_dir
         self._envlogicconf = envlogicconf
-        self._etc_dir = smarthome.get_etcdir()
-        self._logic_dir = smarthome.get_logicsdir()
+        self._etc_dir = smarthome.get_config_dir(DIR_ETC)
+        self._logic_dir = smarthome.get_config_dir(DIR_LOGICS)
+        self._logic_conf = smarthome.get_config_file(BASE_LOGIC)
         self._workers = []
         self._logics = {}
         #self._bytecode = {}
@@ -126,7 +127,7 @@ def __init__(self, smarthome, userlogicconf, envlogicconf):
                 self._load_logic(name, _config)
 
         # load /etc/admin.yaml
-        admconf_filename = os.path.join(self._get_etc_dir(), 'admin')
+        admconf_filename = self._sh.get_config_file(BASE_ADMIN)
         _admin_conf = shyaml.yaml_load_roundtrip(admconf_filename)
         if _admin_conf.get('logics', None) is None:
             self._groups = {}
@@ -137,7 +138,7 @@ def __init__(self, smarthome, userlogicconf, envlogicconf):
     def _save_groups(self):
 
         # load /etc/admin.yaml
-        admconf_filename = os.path.join(self._get_etc_dir(), 'admin')
+        admconf_filename = self._sh.get_config_file(BASE_ADMIN)
         _admin_conf = shyaml.yaml_load_roundtrip(admconf_filename)
         _admin_conf['logics']['groups'] = self._groups
         shyaml.yaml_save_roundtrip(admconf_filename, _admin_conf, create_backup=True)
@@ -508,7 +509,7 @@ def is_userlogic(self, name):
             pathname = str(self.return_logic(name)._pathname)
         except:
             return False
-        return os.path.basename(os.path.dirname(pathname)) == 'logics'
+        return os.path.basename(os.path.dirname(pathname)) == DIR_LOGICS
 
 
     def load_logic(self, name):
@@ -618,8 +619,7 @@ def return_logictype(self, name):
         else:
             logger.info("return_logictype: name {} is not loaded".format(name))
             # load /etc/logic.yaml if logic is not in the loaded logics
-            conf_filename = os.path.join(self._get_etc_dir(), 'logic')
-            config = shyaml.yaml_load_roundtrip(conf_filename)
+            config = shyaml.yaml_load_roundtrip(self._logic_conf)
             if config is not None:
                 if name in config:
                     filename = config[name].get('filename', '')
@@ -654,8 +654,7 @@ def return_defined_logics(self, withtype=False):
             logic_list = []
 
         # load /etc/logic.yaml
-        conf_filename = os.path.join(self._get_etc_dir(), 'logic')
-        config = shyaml.yaml_load_roundtrip(conf_filename)
+        config = shyaml.yaml_load_roundtrip(self._logic_conf)
 
         if config is not None:
             for section in config:
@@ -729,8 +728,7 @@ def read_config_section(self, section):
             return False
 
         # load /etc/logic.yaml
-        conf_filename = os.path.join(self._get_etc_dir(), 'logic')
-        _conf = shyaml.yaml_load_roundtrip(conf_filename)
+        _conf = shyaml.yaml_load_roundtrip(self._logic_conf)
 
         config_list = []
         if _conf is not None:
@@ -780,8 +778,7 @@ def set_config_section_key(self, section, key, value):
 
         """
         # load /etc/logic.yaml
-        conf_filename = os.path.join(self._get_etc_dir(), 'logic')
-        conf = shyaml.yaml_load_roundtrip(conf_filename)
+        conf = shyaml.yaml_load_roundtrip(self._logic_conf)
 
         logger.info("set_config_section_key: section={}, key={}, value={}".format(section, key, str(value)))
         if value == None:
@@ -791,7 +788,7 @@ def set_config_section_key(self, section, key, value):
             conf[section][key] = value
 
         # save /etc/logic.yaml
-        shyaml.yaml_save_roundtrip(conf_filename, conf, True)
+        shyaml.yaml_save_roundtrip(self._logic_conf, conf, True)
 
         # activate visu_acl without reloading the logic
         if key == 'visu_acl':
@@ -828,8 +825,7 @@ def update_config_section(self, active, section, config_list):
             return False
 
         # load /etc/logic.yaml
-        conf_filename = os.path.join(self._get_etc_dir(), 'logic')
-        conf = shyaml.yaml_load_roundtrip(conf_filename)
+        conf = shyaml.yaml_load_roundtrip(self._logic_conf)
         if conf is None:
             conf = shyaml.get_emptynode()
 
@@ -889,7 +885,7 @@ def update_config_section(self, active, section, config_list):
 
         if conf[section] == shyaml.get_emptynode():
             conf[section] = None
-        shyaml.yaml_save_roundtrip(conf_filename, conf, True)
+        shyaml.yaml_save_roundtrip(self._logic_conf, conf, True)
 
 
     def _count_filename_uses(self, conf, filename):
@@ -908,8 +904,7 @@ def _count_filename_uses(self, conf, filename):
 
     def filename_used_count(self, filename):
         # load /etc/logic.yaml
-        conf_filename = os.path.join(self._get_etc_dir(), 'logic')
-        conf = shyaml.yaml_load_roundtrip(conf_filename)
+        conf = shyaml.yaml_load_roundtrip(self._logic_conf)
         count = self._count_filename_uses(conf, filename)
         return count
 
@@ -939,8 +934,7 @@ def delete_logic(self, name, with_code=False):
             self.unload_logic(name)
 
         # load /etc/logic.yaml
-        conf_filename = os.path.join(self._get_etc_dir(), 'logic')
-        conf = shyaml.yaml_load_roundtrip(conf_filename)
+        conf = shyaml.yaml_load_roundtrip(self._logic_conf)
 
         section = conf.get(name, None)
         if section is None:
@@ -974,7 +968,7 @@ def delete_logic(self, name, with_code=False):
             logger.info(f"delete_logic: Section '{name}' from configuration deleted")
 
         # save /etc/logic.yaml
-        shyaml.yaml_save_roundtrip(conf_filename, conf, True)
+        shyaml.yaml_save_roundtrip(self._logic_conf, conf, True)
         return True
 
 
diff --git a/lib/metadata.py b/lib/metadata.py
index 853c810ab5..b945591160 100644
--- a/lib/metadata.py
+++ b/lib/metadata.py
@@ -27,7 +27,7 @@
 from lib.utils import Utils
 from lib.utils import Version
 import lib.shyaml as shyaml
-from lib.constants import (YAML_FILE, FOO, META_DATA_TYPES, META_DATA_DEFAULTS)
+from lib.constants import (YAML_FILE, FOO, META_DATA_TYPES, META_DATA_DEFAULTS, DIR_PLUGINS, DIR_MODULES)
 from lib.model.sdp.globals import SDP_VERSION
 
 META_MODULE_PARAMETER_SECTION = 'parameters'
@@ -39,23 +39,22 @@
 META_PLUGIN_FUNCTION_SECTION = 'plugin_functions'
 
 META_STRUCT_SECTION = 'item_structs'
-#META_DATA_TYPES=['bool', 'int', 'float','num', 'scene', 'str', ['list','list(subtype)'], 'dict', 'ip', 'ipv4', 'ipv6', 'mac', 'knx_ga', 'foo']
-#META_DATA_DEFAULTS={'bool': False, 'int': 0, 'float': 0.0, 'scene': 0, 'str': '', 'list': [], 'dict': {}, 'OrderedDict': {}, 'num': 0, 'scene': 0, 'ip': '0.0.0.0', 'ipv4': '0.0.0.0', 'mac': '00:00:00:00:00:00', 'knx_ga': '', 'foo': None}
+# META_DATA_TYPES=['bool', 'int', 'float','num', 'scene', 'str', ['list','list(subtype)'], 'dict', 'ip', 'ipv4', 'ipv6', 'mac', 'knx_ga', 'foo']
+# META_DATA_DEFAULTS={'bool': False, 'int': 0, 'float': 0.0, 'scene': 0, 'str': '', 'list': [], 'dict': {}, 'OrderedDict': {}, 'num': 0, 'scene': 0, 'ip': '0.0.0.0', 'ipv4': '0.0.0.0', 'mac': '00:00:00:00:00:00', 'knx_ga': '', 'foo': None}
 
 
 logger = logging.getLogger(__name__)
 
-
 # global variables to take definitions of multiple plugins
 all_itemdefinitions = {}
 all_itemprefixdefinitions = {}
 all_prefixes_tuple = None
 
+
 class Metadata():
 
     _version = '?'
 
-
     def __init__(self, sh, addon_name, addon_type, classpath=''):
         """
         Initialzes the metadata for an addon (plugin or module) from the definition file
@@ -78,21 +77,21 @@ def __init__(self, sh, addon_name, addon_type, classpath=''):
 
         self._log_premsg = "{} '{}': ".format(addon_type, self._addon_name)
 
-#        logger.warning(self._log_premsg+"classpath = '{}'".format( classpath ) )
+#        logger.warning(self._log_premsg + "classpath = '{}'".format(classpath))
         if classpath == '':
             if addon_type == 'plugin':
-                addon_type_dir = 'plugins'
+                addon_type_dir = DIR_PLUGINS
             elif addon_type == 'module':
-                addon_type_dir = 'modules'
+                addon_type_dir = DIR_MODULES
             else:
                 return
-            self.relative_filename = os.path.join( addon_type_dir, self._addon_name, addon_type+YAML_FILE )
+            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.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 )
+        filename = os.path.join(self._sh.get_basedir(), self.relative_filename)
         self.meta = shyaml.yaml_load(filename, ordered=True)
 
         self.parameters = None
@@ -157,11 +156,11 @@ def __init__(self, sh, addon_name, addon_type, classpath=''):
                             self.parameters[param_name]['_name'] = param_name
                             self.parameters[param_name]['_type'] = 'parameter'
                     self._paramlist = list(self.parameters.keys())
-                    logger.info(self._log_premsg+"Metadata paramlist = '{}'".format( str(self._paramlist) ) )
-            if  self.parameters is not None:
+                    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")
+                logger.debug(self._log_premsg + "has no parameter definitions in metadata")
 
             # test validity of item definition section
             if self.itemdefinitions is not None:
@@ -169,11 +168,11 @@ def __init__(self, sh, addon_name, addon_type, classpath=''):
                     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:
+                    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")
+                logger.debug(self._log_premsg + "has no item definitions in metadata")
 
             # test validity of item-prefix definition section
             if self.itemprefixdefinitions is not None:
@@ -181,11 +180,11 @@ def __init__(self, sh, addon_name, addon_type, classpath=''):
                     self.itemprefixdefinitions = None
                 else:
                     self._itemprefixdeflist = list(self.itemprefixdefinitions.keys())
-                    logger.info(self._log_premsg+"Metadata itemprefixdeflist = '{}'".format( str(self._itemprefixdeflist) ) )
-            if  self.itemprefixdefinitions is not None:
+                    logger.info(self._log_premsg + "Metadata itemprefixdeflist = '{}'".format(str(self._itemprefixdeflist)))
+            if self.itemprefixdefinitions is not None:
                 self._test_definitions(self._itemprefixdeflist, self.itemprefixdefinitions)
             else:
-                logger.debug(self._log_premsg+"has no item definitions in metadata")
+                logger.debug(self._log_premsg + "has no item definitions in metadata")
 
             # build dict for checking of item attributes and their values
             if self.itemdefinitions is not None:
@@ -212,11 +211,11 @@ def __init__(self, sh, addon_name, addon_type, classpath=''):
                     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:
+                    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")
+                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:
@@ -224,8 +223,8 @@ def __init__(self, sh, addon_name, addon_type, classpath=''):
                     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:
+                    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)
@@ -233,7 +232,7 @@ def __init__(self, sh, addon_name, addon_type, classpath=''):
                 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")
+                logger.debug(self._log_premsg + "has no plugin-function definitions in metadata")
 
 
             # test validity of structs definition section
@@ -250,7 +249,7 @@ def __init__(self, sh, addon_name, addon_type, classpath=''):
 #                                    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)
+#                self._test_definitions(self._itemdeflist, self.itemdefinitions)
 #                pass
             else:
                 logger.info(self._log_premsg + "has no item-struct definitions in metadata")
@@ -337,7 +336,7 @@ def _test_definitions(self, definition_list, definition_dict):
         Test parameter or item-attribute definitions for validity
         """
         definition_list = list(definition_dict.keys())
-#        logger.warning(self._log_premsg+"Metadata definition_list = '{}'".format( definition_list ) )
+#        logger.warning(self._log_premsg + "Metadata definition_list = '{}'".format(definition_list))
         for definition in definition_list:
             if definition_dict[definition] is not None:
                 typ = str(definition_dict[definition].get('type', FOO)).lower()
@@ -345,11 +344,11 @@ def _test_definitions(self, definition_list, definition_dict):
                 definition_dict[definition]['listtype'] = [FOO]
                 definition_dict[definition]['listlen'] = 0
                 if definition_dict[definition].get('type', FOO) == 'list':
-                    logger.debug(self._log_premsg+"definition = '{}' of type '{}'".format(definition, str(definition_dict[definition].get('type', FOO)).lower() ) )
+                    logger.debug(self._log_premsg + "definition = '{}' of type '{}'".format(definition, str(definition_dict[definition].get('type', FOO)).lower()))
                 if not (typ in META_DATA_TYPES):
                     # test for list with specified datatype
                     if typ.startswith('list(') and typ.endswith(')'):
-                        logger.debug(self._log_premsg+"definition = '{}' of type '{}'".format(definition, str(definition_dict[definition].get('type', FOO)).lower() ) )
+                        logger.debug(self._log_premsg + "definition = '{}' of type '{}'".format(definition, str(definition_dict[definition].get('type', FOO)).lower()))
                         definition_dict[definition]['type'] = 'list'
                         listparam = typ[5:]
                         listparam = listparam[:-1].strip().split(',')
@@ -370,21 +369,21 @@ def _test_definitions(self, definition_list, definition_dict):
                                     listparam2.append(listparam[i].strip())
                                 else:
                                     listparam2.append(FOO)
-                                    logger.error(self._log_premsg+"definition = '{}': Invalid subtype '{}' specified, using '{}' instead (META_DATA_TYPES={})".format(definition, listparam[i], FOO, META_DATA_TYPES))
+                                    logger.error(self._log_premsg + "definition = '{}': Invalid subtype '{}' specified, using '{}' instead (META_DATA_TYPES={})".format(definition, listparam[i], FOO, META_DATA_TYPES))
                             listparam = listparam2
 
                         definition_dict[definition]['listtype'] = listparam
 
                     else:
-                        logger.error(self._log_premsg+"Invalid definition in metadata file '{}': type '{}' for parameter '{}' -> using type '{}' instead".format( self.relative_filename, typ, definition, FOO ) )
+                        logger.error(self._log_premsg + "Invalid definition in metadata file '{}': type '{}' for parameter '{}' -> using type '{}' instead".format(self.relative_filename, typ, definition, FOO))
                         definition_dict[definition]['type'] = FOO
 
                 if definition_dict[definition].get('type', FOO) == 'list':
-                    logger.debug(self._log_premsg+"definition = '{}' list of subtype_list = {}, listlen={}".format(definition, definition_dict[definition]['listtype'], definition_dict[definition]['listlen'] ) )
+                    logger.debug(self._log_premsg + "definition = '{}' list of subtype_list = {}, listlen={}".format(definition, definition_dict[definition]['listtype'], definition_dict[definition]['listlen']))
                 else:
-                    logger.debug(self._log_premsg+"definition = '{}' list of listparam = >{}<, listlen={}".format(definition, definition_dict[definition]['listtype'], definition_dict[definition]['listlen'] ) )
+                    logger.debug(self._log_premsg + "definition = '{}' list of listparam = >{}<, listlen={}".format(definition, definition_dict[definition]['listtype'], definition_dict[definition]['listlen']))
             else:
-                logger.info(self._log_premsg+"definition = '{}'".format( definition ) )
+                logger.info(self._log_premsg + "definition = '{}'".format(definition))
         return
 
     def _strip_quotes(self, string):
@@ -606,7 +605,7 @@ def _test_valuetype(self, typ, subtype, value):
         """
         Returns True, if the value can be converted to the specified type
         """
-#        logger.warning(self._log_premsg+"_test_valuetype-list: typ={}, subtype={}, value={}".format(typ, subtype, value))
+#        logger.warning(self._log_premsg + "_test_valuetype-list: typ={}, subtype={}, value={}".format(typ, subtype, value))
         if typ == 'bool':
             return Utils.to_bool(value, default='?') != '?'
         elif typ == 'int':
@@ -704,7 +703,7 @@ def _expand_listvalues(self, value, definition):
             if (typ == 'list') and (not isinstance(value, list)):
                 result = Utils.string_to_list(value)
 #            if (typ == 'list'):
-#                logger.warning(self._log_premsg+"_expand_listvalues: value = >{}<, type(value) = >{}<, result = >{}<, type(result) = >{}<".format(value, type(value), result, type(result)))
+#                logger.warning(self._log_premsg + "_expand_listvalues: value = >{}<, type(value) = >{}<, result = >{}<, type(result) = >{}<".format(value, type(value), result, type(result)))
         return result
 
 
@@ -741,7 +740,7 @@ def _convert_valuetotype(self, typ, value):
         elif typ == FOO:
             result = value
         else:
-            logger.error(self._log_premsg+"unhandled type {}".format(typ))
+            logger.error(self._log_premsg + "unhandled type {}".format(typ))
         return result
 
 
@@ -760,9 +759,9 @@ def _convert_value(self, value, definition, is_default=False):
             if result != orig:
                 # Für non-default Prüfung nur Warning
                 if is_default:
-                    logger.error(self._log_premsg+f"Invalid default '{orig}' in metadata file '{self.relative_filename}' for {definition['_type']} '{definition['_name']}' -> using '{result}' instead" )
+                    logger.error(self._log_premsg+f"Invalid default '{orig}' in metadata file '{self.relative_filename}' for {definition['_type']} '{definition['_name']}' -> using '{result}' instead")
                 else:
-                    logger.warning(self._log_premsg+f"Invalid value '{orig}' for {definition['_type']} '{definition['_name']}' -> using '{result}' instead {definition.get('_def_in', '')}" )
+                    logger.warning(self._log_premsg+f"Invalid value '{orig}' for {definition['_type']} '{definition['_name']}' -> using '{result}' instead {definition.get('_def_in', '')}")
         return result
 
 
@@ -826,7 +825,7 @@ def _test_validity(self, param, value, definition=None, is_default=False):
             elif definition.get('type', 'foo') in ['list']:
                  if definition['listlen'] > 0:
                      if definition['listlen'] != len(value):
-                        logger.warning(self._log_premsg+"Invalid value '{}' in plugin configuration file for parameter '{}' -> length of list is not {}".format( value, param, self.parameters[param]['listlen'] ) )
+                        logger.warning(self._log_premsg + "Invalid value '{}' in plugin configuration file for parameter '{}' -> length of list is not {}".format(value, param, self.parameters[param]['listlen']))
                         while len(value) < definition['listlen']:
                             value.append('')
                         result = value
@@ -861,13 +860,13 @@ def _test_validity(self, param, value, definition=None, is_default=False):
             elif self.parameters[param].get('type') in ['list']:
                  if self.parameters[param]['listlen'] > 0:
                      if self.parameters[param]['listlen'] != len(value):
-                        logger.warning(self._log_premsg+"Invalid value '{}' in plugin configuration file for parameter '{}' -> length of list is not {}".format( value, param, self.parameters[param]['listlen'] ) )
+                        logger.warning(self._log_premsg + "Invalid value '{}' in plugin configuration file for parameter '{}' -> length of list is not {}".format(value, param, self.parameters[param]['listlen']))
                         while len(value) < self.parameters[param]['listlen']:
                             value.append('')
                         result = value
 
         if self.parameters[param] is None:
-            logger.warning(self._log_premsg+"_test_validity: param {}".format(param))
+            logger.warning(self._log_premsg + "_test_validity: param {}".format(param))
         else:
             # test against list of valid entries
             result = self._test_against_valid_list(self.parameters[param], result)
@@ -1085,7 +1084,7 @@ def _get_definition_defaultvalue(self, definition, definitions, definitionlist):
                     ###ms
                     if not self._test_value(value, self.parameters[definition]):
                         # Für non-default Prüfung nur Warning
-                        logger.error(self._log_premsg+"Invalid data for type '{}' in metadata file '{}': default '{}' for parameter '{}' -> using '{}' instead".format( definitions[definition].get('type'), self.relative_filename, value, definition, self._get_default_if_none(typ) ) )
+                        logger.error(self._log_premsg + "Invalid data for type '{}' in metadata file '{}': default '{}' for parameter '{}' -> using '{}' instead".format(definitions[definition].get('type'), self.relative_filename, value, definition, self._get_default_if_none(typ)))
                         value = None
                     if value is None:
                         value = self._get_default_if_none(typ)
@@ -1095,7 +1094,7 @@ def _get_definition_defaultvalue(self, definition, definitions, definitionlist):
                     value = self._test_validity('', value, self.parameters[definition], is_default=True)
                     if value != orig_value:
                         # Für non-default Prüfung nur Warning
-                        logger.error(self._log_premsg+"Invalid default '{}' in metadata file '{}' for parameter '{}' -> using '{}' instead".format( orig_value, self.relative_filename, definition, value ) )
+                        logger.error(self._log_premsg + "Invalid default '{}' in metadata file '{}' for parameter '{}' -> using '{}' instead".format(orig_value, self.relative_filename, definition, value))
 
         return value
 
@@ -1159,10 +1158,10 @@ def check_parameters(self, args):
         addon_params = collections.OrderedDict()
         hide_params = collections.OrderedDict()
         if self.meta is None:
-            logger.info(self._log_premsg+"No metadata found" )
+            logger.info(self._log_premsg + "No metadata found")
             return (addon_params, True, hide_params)
         if self.parameters is None:
-            logger.info(self._log_premsg+"No parameter definitions found in metadata" )
+            logger.info(self._log_premsg + "No parameter definitions found in metadata")
             return (addon_params, True, hide_params)
 
         allparams_ok = True
@@ -1172,13 +1171,13 @@ def check_parameters(self, args):
                 if value is None:
                     if self.parameters[param] is not None:
                         if self.parameters[param].get('mandatory'):
-                            logger.error(self._log_premsg+"'{}' is mandatory, but was not found in /etc/{}".format(param, self._addon_type+YAML_FILE))
+                            logger.error(self._log_premsg + "'{}' is mandatory, but was not found in /etc/{}".format(param, self._addon_type + YAML_FILE))
                             allparams_ok = False
                         else:
                             addon_params[param] = self.get_parameter_defaultvalue(param)
                             hide_params[param] = Utils.to_bool(self.parameters[param].get('hide'), default=False)
-                            logger.info(self._log_premsg+"value not found in plugin configuration file for parameter '{}' -> using default value '{}' instead".format(param, addon_params[param] ) )
-        #                    logger.warning(self._log_premsg+"'{}' not found in /etc/{}, using default value '{}'".format(param, self._addon_type+YAML_FILE, addon_params[param]))
+                            logger.info(self._log_premsg + "value not found in plugin configuration file for parameter '{}' -> using default value '{}' instead".format(param, addon_params[param]))
+        #                    logger.warning(self._log_premsg + "'{}' not found in /etc/{}, using default value '{}'".format(param, self._addon_type + YAML_FILE, addon_params[param]))
                 else:
                     value = self._expand_listvalues(value, self.parameters[param])
                     if self._test_value(value, self.parameters[param]):
@@ -1188,16 +1187,16 @@ def check_parameters(self, args):
                             hide_params[param] = None
                         else:
                             hide_params[param] = Utils.to_bool(self.parameters[param].get('hide'), default=False)
-                        logger.debug(self._log_premsg+"Found '{}' with value '{}' in /etc/{}".format(param, value, self._addon_type+YAML_FILE))
+                        logger.debug(self._log_premsg + "Found '{}' with value '{}' in /etc/{}".format(param, value, self._addon_type + YAML_FILE))
                     else:
                         if self.parameters.get(param) is not None:
                             if bool(self.parameters[param].get('mandatory', False)) is True:
-                                logger.error(self._log_premsg+"'{}' is mandatory, but no valid value was found in /etc/{}".format(param, self._addon_type+YAML_FILE))
+                                logger.error(self._log_premsg + "'{}' is mandatory, but no valid value was found in /etc/{}".format(param, self._addon_type + YAML_FILE))
                                 allparams_ok = False
                             else:
                                 addon_params[param] = self.get_parameter_defaultvalue(param)
                                 hide_params[param] = Utils.to_bool(self.parameters[param].get('hide'), default=False)
-                                logger.error(self._log_premsg+"Found invalid value '{}' for parameter '{}' (type {}) in /etc/{}, using default value '{}' instead".format(value, param, self.parameters[param]['type'], self._addon_type+YAML_FILE, str(addon_params[param])))
+                                logger.error(self._log_premsg + "Found invalid value '{}' for parameter '{}' (type {}) in /etc/{}, using default value '{}' instead".format(value, param, self.parameters[param]['type'], self._addon_type + YAML_FILE, str(addon_params[param])))
 
         return (addon_params, allparams_ok, hide_params)
 
@@ -1313,8 +1312,8 @@ def _version_to_list(self, vers):
         # get rid of non numeric parts
         vlist = []
         for v in vsplit:
-            #v = re.findall('\d+', v )[0]
-            v = re.findall(r'\d+', v )[0]
+            #v = re.findall('\d+', v)[0]
+            v = re.findall(r'\d+', v)[0]
             vi = 0
             try:
                 vi = int(v)
diff --git a/lib/module.py b/lib/module.py
index 3ea7f3dbe2..74d9f5aa11 100644
--- a/lib/module.py
+++ b/lib/module.py
@@ -48,7 +48,7 @@
 
 import lib.config
 import lib.translation as translation
-from lib.constants import (KEY_CLASS_NAME, KEY_CLASS_PATH, KEY_INSTANCE,CONF_FILE)
+from lib.constants import (KEY_CLASS_NAME, KEY_CLASS_PATH, KEY_INSTANCE, DIR_MODULES)
 from lib.utils import Utils
 from lib.metadata import Metadata
 
@@ -127,7 +127,7 @@ def _get_modulename_and_metadata(self, module, mod_conf):
         module_name = mod_conf.get('module_name','').lower()
         meta = None
         if module_name != '':
-            module_dir = os.path.join(self._basedir, 'modules', module_name)
+            module_dir = os.path.join(self._sh.get_config_dir(DIR_MODULES), module_name)
             if os.path.isdir(module_dir):
                 meta = Metadata(self._sh, module_name, 'module')
             else:
@@ -181,7 +181,7 @@ def _get_classname_and_classpath(self, mod_conf, module_name):
         try:
             classpath = mod_conf[KEY_CLASS_PATH]
         except:
-            classpath = 'modules.' + module_name
+            classpath = DIR_MODULES + '.' + module_name
         return (classname, classpath)
 
 
diff --git a/lib/plugin.py b/lib/plugin.py
index 458530d9af..00ef96a7b7 100644
--- a/lib/plugin.py
+++ b/lib/plugin.py
@@ -59,7 +59,7 @@
 import lib.translation as translation
 import lib.shyaml as shyaml
 from lib.model.smartplugin import SmartPlugin
-from lib.constants import (KEY_CLASS_NAME, KEY_CLASS_PATH, KEY_INSTANCE, KEY_WEBIF_PAGELENGTH, YAML_FILE,CONF_FILE)
+from lib.constants import (KEY_CLASS_NAME, KEY_CLASS_PATH, KEY_INSTANCE, KEY_WEBIF_PAGELENGTH, YAML_FILE, CONF_FILE, DIR_PLUGINS)
 #from lib.utils import Utils
 from lib.metadata import Metadata
 #import lib.item
@@ -103,7 +103,7 @@ def __init__(self, smarthome, configfile):
         _plugins_instance = self
 
         # until Backend plugin is modified
-        if os.path.isfile(configfile+ YAML_FILE):
+        if os.path.isfile(configfile + YAML_FILE):
             self._plugin_conf_filename = configfile + YAML_FILE
         else:
             self._plugin_conf_filename = configfile + CONF_FILE
@@ -322,7 +322,7 @@ def _get_classname_and_classpath(self, plg_conf, plugin_name):
             if plugin_name == '':
                 classpath = ''
             else:
-                classpath = 'plugins.' + plugin_name
+                classpath = DIR_PLUGINS + '.' + plugin_name
 #        logger.warning("_get_classname_and_classpath: plugin_name = {}, classpath = {}, classname = {}".format(plugin_name, classpath, classname))
         return (classname, classpath+plugin_version)
 
diff --git a/lib/scene.py b/lib/scene.py
index a0708ca588..d56e99f3a2 100644
--- a/lib/scene.py
+++ b/lib/scene.py
@@ -36,6 +36,7 @@
 from lib.utils import Utils
 from lib.shtime import Shtime
 import lib.shyaml as yaml
+from lib.constants import (YAML_FILE, DIR_SCENES)
 
 logger = logging.getLogger(__name__)
 
@@ -81,7 +82,7 @@ def _load_scenes(self):
         """
         self._scenes = {}
         self._learned_values = {}
-        self._scenes_dir = self._sh._scenes_dir
+        self._scenes_dir = self._sh.get_config_dir(DIR_SCENES)
         if not os.path.isdir(self._scenes_dir):
             logger.warning(translate("Directory '{scenes_dir}' not found. Ignoring scenes.", {'scenes_dir': self._scenes_dir}))
             return
@@ -92,7 +93,7 @@ def _load_scenes(self):
             if item.type() == 'scene':
                 self.scene_file = os.path.join(self._scenes_dir, item.property.path)
 
-                scene_file_yaml = yaml.yaml_load(self.scene_file+'.yaml', ordered=False, ignore_notfound=True)
+                scene_file_yaml = yaml.yaml_load(self.scene_file + YAML_FILE, ordered=False, ignore_notfound=True)
                 if scene_file_yaml is not None:
                     # Reading yaml file with scene definition
                     for state in scene_file_yaml:
@@ -186,7 +187,7 @@ def _save_learned_values(self, scene):
                 logger.debug(" - Saving value {} for state/ditem {}".format(lvalue, fkey))
         logger.info(" -> to dict learned_dict {}:".format(learned_dict))
         scene_learnfile = os.path.join(self._scenes_dir, scene+'_learned')
-        yaml.yaml_save(scene_learnfile+'.yaml', learned_dict)
+        yaml.yaml_save(scene_learnfile + YAML_FILE, learned_dict)
         return
 
 
@@ -194,8 +195,8 @@ 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)
+        scene_learnfile = os.path.join(self._scenes_dir, scene + '_learned')
+        learned_dict = yaml.yaml_load(scene_learnfile + YAML_FILE, 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:
diff --git a/lib/shtime.py b/lib/shtime.py
index 2e8f5dedc0..38f7df46c4 100644
--- a/lib/shtime.py
+++ b/lib/shtime.py
@@ -42,7 +42,7 @@
 import os
 
 import lib.shyaml as shyaml
-from lib.constants import (YAML_FILE)
+from lib.constants import (YAML_FILE, BASE_HOLIDAY)
 #from lib.translation import translate
 from lib.translation import translate as lib_translate
 
@@ -1140,9 +1140,7 @@ def _initialize_holidays(self):
         """
 
         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)
+            self.config = shyaml.yaml_load(self._sh.get_config_file(BASE_HOLIDAY))
             location = self.config.get('location', None)
 
             # prepopulate holidays for following years
diff --git a/lib/smarthome.py b/lib/smarthome.py
index c407c4fb9f..fd2afe3ff1 100644
--- a/lib/smarthome.py
+++ b/lib/smarthome.py
@@ -98,7 +98,7 @@
 import lib.shyaml
 from lib.shpypi import Shpypi
 from lib.triggertimes import TriggerTimes
-from lib.constants import (YAML_FILE, CONF_FILE, DEFAULT_FILE)
+from lib.constants import (YAML_FILE, CONF_FILE, DEFAULT_FILE, DIRS, BASES, BASE_LOG, BASE_LOGIC, BASE_MODULE, BASE_PLUGIN, BASE_SH, DIR_CACHE, DIR_ENV, DIR_ETC, DIR_ITEMS, DIR_LIB, DIR_LOGICS, DIR_MODULES, DIR_PLUGINS, DIR_SCENES, DIR_STRUCTS, DIR_TPL, DIR_UF, DIR_VAR)
 import lib.userfunctions as uf
 from lib.systeminfo import Systeminfo
 
@@ -153,7 +153,7 @@ def initialize_dir_vars(self):
         self._base_dir = BASE
         self.base_dir = self._base_dir  # **base_dir** is deprecated. Use method get_basedir() instead. - for external modules using that var (backend, ...?)
 
-        self._etc_dir = os.path.join(self._extern_conf_dir, 'etc')
+        self._etc_dir = os.path.join(self._extern_conf_dir, DIR_ETC)
 
         # self._conf_dir contains the base dir for config folders
         if self._config_etc:
@@ -162,28 +162,32 @@ def initialize_dir_vars(self):
             self._conf_dir = self._extern_conf_dir
 
         # shng system dirs
-        self._var_dir = os.path.join(self._base_dir, 'var')
-        self._lib_dir = os.path.join(self._base_dir, 'lib')
-        self._plugins_dir = os.path.join(self._base_dir, 'plugins')
+        self._var_dir = os.path.join(self._base_dir, DIR_VAR)
+        self._lib_dir = os.path.join(self._base_dir, DIR_LIB)
+        self._plugins_dir = os.path.join(self._base_dir, DIR_PLUGINS)
+        self._modules_dir = os.path.join(self._base_dir, DIR_MODULES)
+        self._templates_dir = os.path.join(self._base_dir, DIR_TPL)
 
         # env and var dirs
-        self._env_dir = os.path.join(self._lib_dir, 'env' + os.path.sep)
-        self._env_logic_conf_basename = os.path.join(self._env_dir, 'logic')
-        self._cache_dir = os.path.join(self._var_dir, 'cache' + os.path.sep)
+        self._env_dir = os.path.join(self._lib_dir, DIR_ENV + os.path.sep)
+        self._cache_dir = os.path.join(self._var_dir, DIR_CACHE + os.path.sep)
 
         # user config dirs
-        self._items_dir = os.path.join(self._conf_dir, 'items' + os.path.sep)
-        self._structs_dir = os.path.join(self._conf_dir, 'structs')
-        self._logic_dir = os.path.join(self._conf_dir, 'logics' + os.path.sep)
-        self._functions_dir = os.path.join(self._conf_dir, 'functions' + os.path.sep)
-        self._scenes_dir = os.path.join(self._conf_dir, 'scenes' + os.path.sep)
+        self._items_dir = os.path.join(self._conf_dir, DIR_ITEMS + os.path.sep)
+        self._structs_dir = os.path.join(self._conf_dir, DIR_STRUCTS)
+        self._logic_dir = os.path.join(self._conf_dir, DIR_LOGICS + os.path.sep)
+        # TODO: remove self._logic_dir later for uniformness (dirs with plural naming)
+        self._logics_dir = self._logic_dir
+        self._functions_dir = os.path.join(self._conf_dir, DIR_UF + os.path.sep)
+        self._scenes_dir = os.path.join(self._conf_dir, DIR_SCENES + os.path.sep)
 
         # system config files
-        self._smarthome_conf_basename = os.path.join(self._etc_dir, 'smarthome')
-        self._log_conf_basename = os.path.join(self._etc_dir, 'logging')
-        self._module_conf_basename = os.path.join(self._etc_dir, 'module')
-        self._plugin_conf_basename = os.path.join(self._etc_dir, 'plugin')
-        self._logic_conf_basename = os.path.join(self._etc_dir, 'logic')
+        self._smarthome_conf_basename = os.path.join(self._etc_dir, BASE_SH)
+        self._log_conf_basename = os.path.join(self._etc_dir, BASE_LOG)
+        self._module_conf_basename = os.path.join(self._etc_dir, BASE_MODULE)
+        self._plugin_conf_basename = os.path.join(self._etc_dir, BASE_PLUGIN)
+        self._logic_conf_basename = os.path.join(self._etc_dir, BASE_LOGIC)
+        self._env_logic_conf_basename = os.path.join(self._env_dir, BASE_LOGIC)
 
 
     def create_directories(self):
@@ -534,33 +538,54 @@ def get_structsdir(self) -> str:
         """
         return self._structs_dir
 
-
-    def get_logicsdir(self) -> str:
+    def get_vardir(self):
         """
-        Function to return the logics config directory
+        Function to return the var directory used by SmartHomeNG
 
-        :return: Config directory as an absolute path
+        :return: var directory as an absolute path
+        :rtype: str
         """
-        return self._logic_dir
+        return self._var_dir
 
 
-    def get_functionsdir(self) -> str:
+    def get_config_dir(self, config):
         """
-        Function to return the userfunctions config directory
+        Function to return a config dir used by SmartHomeNG
+        replace / prevent a plethora of get_<foo>dir() functions
 
-        :return: Config directory as an absolute path
+        Returns '' for invalid config strings.
+
+        :return: directory as an absolute path
+        :rtype: str
         """
-        return self._functions_dir
+        # method would work fine without this check, but...
+        # make sure we don't allow "any" function call here
+        if config not in DIRS:
+            return ''
 
+        if hasattr(self, f'get_{config}dir'):
+            return getattr(self, f'get_{config}dir')()
+        elif hasattr(self, f'_{config}_dir'):
+            return getattr(self, f'_{config}_dir')
+        
+        return ''
 
-    def get_vardir(self):
+
+    def get_config_file(self, config, extension=YAML_FILE):
         """
-        Function to return the var directory used by SmartHomeNG
+        Function to return a config file used by SmartHomeNG
 
-        :return: var directory as an absolute path
+        Returns '' for invalid config strings.
+
+        :return: file name as an absolute path
         :rtype: str
         """
-        return self._var_dir
+        # method would work fine without this check, but...
+        # make sure we don't allow "any" function call here
+        if config not in BASES:
+            return ''
+
+        return os.path.join(self.get_etcdir(), config + extension)
 
 
     def getBaseDir(self):
diff --git a/lib/userfunctions.py b/lib/userfunctions.py
index 6f410083e9..a3efa3429e 100644
--- a/lib/userfunctions.py
+++ b/lib/userfunctions.py
@@ -27,11 +27,12 @@
 import logging
 
 from lib.translation import translate
+from lib.constants import DIR_UF
 
 _logger = logging.getLogger(__name__)
 
 
-_uf_subdir = 'functions'
+_uf_subdir = DIR_UF
 
 _func_dir = None
 _sh = None
@@ -92,7 +93,7 @@ def init_lib(shng_base_dir=None, sh=None):
         base_dir = os.getcwd()
 
     if _sh:
-        _func_dir = _sh.get_functionsdir()
+        _func_dir = _sh.get_config_dir(DIR_UF)
     else:
         _func_dir = os.path.join(base_dir, _uf_subdir)
 
diff --git a/logics/.gitignore b/logics/.gitignore
deleted file mode 100644
index f850825a77..0000000000
--- a/logics/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-# ignore everything
-*
-# except .gitignore
-!.gitignore
-!example_*.*
-!logic.tpl
diff --git a/modules/admin/api_auth.py b/modules/admin/api_auth.py
index 39d0c7bd7f..34f1e98e80 100644
--- a/modules/admin/api_auth.py
+++ b/modules/admin/api_auth.py
@@ -31,6 +31,7 @@
 
 # from lib.item import Items
 from lib.utils import Utils
+from lib.constants import (DIR_ETC, DIR_MODULES)
 
 from .rest import RESTResource
 
@@ -44,8 +45,8 @@ def __init__(self, module):
         self.base_dir = self._sh.get_basedir()
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
-        self.etc_dir = self._sh._etc_dir
-        self.modules_dir = os.path.join(self.base_dir, 'modules')
+        self.etc_dir = self._sh.get_config_dir(DIR_ETC)
+        self.modules_dir = self._sh.get_config_dir(DIR_MODULES)
 
         if self.module.rest_dispatch_force_exception:
             self.logger.notice(f"REST_dispatch_execute warnlevel is set to EXCEPTION")
diff --git a/modules/admin/api_config.py b/modules/admin/api_config.py
index 099694a071..f462e6ff5b 100644
--- a/modules/admin/api_config.py
+++ b/modules/admin/api_config.py
@@ -27,6 +27,7 @@
 
 from lib.module import Modules
 import lib.shyaml as shyaml
+from lib.constants import (DIR_ETC, DIR_MODULES, BASE_SH, BASE_HOLIDAY, BASE_MODULE)
 
 from .rest import RESTResource
 
@@ -42,8 +43,8 @@ def __init__(self, module):
         self.base_dir = self._sh.get_basedir()
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
-        self.etc_dir = self._sh.get_etcdir()
-        self.modules_dir = os.path.join(self.base_dir, 'modules')
+        self.etc_dir = self._sh.get_config_dir(DIR_ETC)
+        self.modules_dir = self._sh.get_config_dir(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'))
@@ -72,7 +73,7 @@ def update_configdict(self, config_dict, data, section='unknown'):
     #  Read holidays
     #
     def read_holidays(self):
-        self.holidays_confdata = shyaml.yaml_load(os.path.join(self.etc_dir, 'holidays.yaml'))
+        self.holidays_confdata = shyaml.yaml_load(self._sh.get_config_file(BASE_HOLIDAYS))
         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', '')
@@ -95,7 +96,7 @@ def read_holidays(self):
     #  Update holidays
     #
     def update_holidays(self, data):
-        filename = os.path.join(self.etc_dir, 'holidays.yaml')
+        filename = self._sh.get_config_file(BASE_HOLIDAYS)
         self.holidays_confdata = shyaml.yaml_load_roundtrip(filename)
         self.logger.info("update_holidays: self.holidays_confdata = '{}'".format(self.holidays_confdata))
         self.logger.info("update_holidays: data['common']['data'] = '{}'".format(data['common']['data']))
@@ -152,10 +153,10 @@ def read(self, id=None):
         """
         self.logger.info("ConfigController.read(): config = {}".format(id))
 
-        self.core_confdata = shyaml.yaml_load(os.path.join(self.etc_dir, 'smarthome.yaml'))
+        self.core_confdata = shyaml.yaml_load(self._sh.get_config_file(BASE_SH))
         self.read_holidays()
 
-        self.module_confdata = shyaml.yaml_load(os.path.join(self.etc_dir, 'module.yaml'))
+        self.module_confdata = shyaml.yaml_load(self._sh.get_config_file(BASE_MODULE))
 
         result = {}
         if (not id) or id == 'core':
@@ -239,12 +240,12 @@ def update(self, id=None):
             self.update_holidays(data)
 
             # update etc/smarthome.yaml with data from admin frontend
-            self.core_confdata = shyaml.yaml_load_roundtrip(os.path.join(self.etc_dir, 'smarthome.yaml'))
+            self.core_confdata = shyaml.yaml_load_roundtrip(self._sh.get_config_file(BASE_SH))
             self.update_configdict(self.core_confdata, data, 'common')
-            shyaml.yaml_save_roundtrip(os.path.join(self.etc_dir, 'smarthome.yaml'), self.core_confdata, create_backup=True)
+            shyaml.yaml_save_roundtrip(self._sh.get_config_file(BASE_SH), self.core_confdata, create_backup=True)
 
             # update etc/module.yaml with data from admin frontend
-            self.module_confdata = shyaml.yaml_load_roundtrip(os.path.join(self.etc_dir, 'module.yaml'))
+            self.module_confdata = shyaml.yaml_load_roundtrip(self._sh.get_config_file(BASE_MODULE))
             self.update_configdict(self.module_confdata['http'], data, 'http')
             self.mod_http = Modules.get_instance().get_module('http')
             hashed_password = data.get('http', {}).get('data', {}).get('hashed_password', '')
@@ -276,7 +277,7 @@ def update(self, id=None):
                 self.module_confdata['mqtt'].pop('enabled', None)
             self.logger.info("Update: ['mqtt'] = {}".format(self.module_confdata['mqtt']))
             self.logger.info("Update: - enabled = {}".format(self.module_confdata['mqtt'].get('enabled', None)))
-            shyaml.yaml_save_roundtrip(os.path.join(self.etc_dir, 'module.yaml'), self.module_confdata, create_backup=True)
+            shyaml.yaml_save_roundtrip(self._sh.get_config_file(BASE_MODULE), self.module_confdata, create_backup=True)
 
             result = {"result": "ok"}
             return json.dumps(result)
diff --git a/modules/admin/api_files.py b/modules/admin/api_files.py
index 255aa5b4a1..1e2ddc2409 100644
--- a/modules/admin/api_files.py
+++ b/modules/admin/api_files.py
@@ -35,6 +35,7 @@
 from lib.item_conversion import convert_yaml as convert_yaml
 from lib.item_conversion import parse_for_convert as parse_for_convert
 from lib.shtime import Shtime
+from lib.constants import (DIR_ETC, DIR_ITEMS, DIR_UF, DIR_SCENES, DIR_LOGICS, DIR_TPL, DIR_MODULES, BASE_LOG, BASE_STRUCT)
 
 
 # ======================================================================
@@ -51,15 +52,14 @@ def __init__(self, module):
         self.base_dir = self._sh.get_basedir()
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
-        self.etc_dir = self._sh.get_etcdir()
-        self.items_dir = self._sh._items_dir
-        self.functions_dir = self._sh.get_functionsdir()
-        self.scenes_dir = self._sh._scenes_dir
-        self.logics_dir = self._sh.get_logicsdir()
-        self.extern_conf_dir = self._sh._extern_conf_dir
-        self.modules_dir = os.path.join(self.base_dir, 'modules')
-        return
-
+        self.etc_dir = self._sh.get_config_dir(DIR_ETC)
+        self.items_dir = self._sh.get_config_dir(DIR_ITEMS)
+        self.functions_dir = self._sh.get_config_dir(DIR_UF)
+        self.scenes_dir = self._sh.get_config_dir(DIR_SCENES)
+        self.logics_dir = self._sh.get_config_dir(DIR_LOGICS)
+        self.template_dir = self._sh.get_config_dir(DIR_TPL)
+        self.extern_conf_dir = self._sh.get_confdir()
+        self.modules_dir = self._sh.get_config_dir(DIR_MODULES)
 
     def get_body(self, text=False, binary=False):
         """
@@ -112,7 +112,7 @@ def get_body(self, text=False, binary=False):
     def get_logging_config(self):
 
         self.logger.info("FilesController.get_logging_config()")
-        filename = os.path.join(self.etc_dir, 'logging.yaml')
+        filename = self._sh.get_config_file(BASE_LOG)
         read_data = None
         with open(filename, encoding='UTF-8') as f:
             read_data = f.read()
@@ -134,7 +134,7 @@ def save_logging_config(self):
         self.logger.debug("FilesController.save_logging_config(): '{}'".format(params))
 
 
-        filename = os.path.join(self.etc_dir, 'logging.yaml')
+        filename = self._sh.get_config_file(BASE_LOG)
         read_data = None
         with open(filename, 'w', encoding='UTF-8') as f:
             f.write(params)
@@ -149,7 +149,7 @@ def save_logging_config(self):
     def get_struct_config(self):
 
         self.logger.info("FilesController.get_struct_config()")
-        filename = os.path.join(self.etc_dir, 'struct.yaml')
+        filename = self._sh.get_config_file(BASE_STRUCT)
         if not(os.path.isfile(filename)):
             open(filename, 'a', encoding='UTF-8').close()
             self.logger.info("FilesController.get_struct_config(): created empty file {}".format(filename))
@@ -175,7 +175,7 @@ def save_struct_config(self):
         self.logger.debug("FilesController.save_struct_config(): '{}'".format(params))
 
 
-        filename = os.path.join(self.etc_dir, 'struct.yaml')
+        filename = self._sh.get_config_file(BASE_STRUCT)
         read_data = None
         with open(filename, 'w', encoding='UTF-8') as f:
             f.write(params)
@@ -337,7 +337,7 @@ def get_functions_config(self, fn):
 
         self.logger.info("FilesController.get_functions_config({})".format(fn))
         if fn.endswith('.tpl'):
-            filename = os.path.join(self.functions_dir, fn)
+            filename = os.path.join(self.template_dir, fn)
         else:
             filename = os.path.join(self.functions_dir, fn + '.py')
         read_data = None
diff --git a/modules/admin/api_logics.py b/modules/admin/api_logics.py
index 1db6703428..e31636346e 100644
--- a/modules/admin/api_logics.py
+++ b/modules/admin/api_logics.py
@@ -34,6 +34,8 @@
 from lib.logic import Logics
 from lib.plugin import Plugins
 from lib.scheduler import Scheduler
+from lib.constants import (DIR_ETC, DIR_LOGICS, DIR_TPL, BASE_LOGIC)
+
 from .rest import RESTResource
 
 
@@ -47,9 +49,10 @@ def __init__(self, module):
         self.base_dir = self._sh.get_basedir()
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
-        self.etc_dir = self._sh._etc_dir
+        self.etc_dir = self._sh.get_config_dir(DIR_ETC)
 
-        self.logics_dir = self._sh.get_logicsdir()
+        self.logics_dir = self._sh.get_config_dir(DIR_LOGICS)
+        self.template_dir = self._sh.get_config_dir(DIR_TPL)
         self.logics = Logics.get_instance()
         self.logger.info("__init__ self.logics = {}".format(self.logics))
         self.plugins = Plugins.get_instance()
@@ -61,7 +64,6 @@ def __init__(self, module):
         self.logics_data = {}
 
         self.logics = Logics.get_instance()
-        return
 
 
     def get_body(self, text=False):
@@ -116,7 +118,6 @@ def logics_initialize(self):
                         self.blockly_plugin_loaded = True
                 except:
                     pass
-        return
 
     def fill_logicdict(self, logicname):
         """
@@ -282,8 +283,7 @@ 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)
+        wrk = shyaml.yaml_load(self._sh.get_config_file(BASE_LOGIC))
         logic_conf = wrk.get(logicname, {})
 
         if Utils.get_type(logic_conf.get('watch_item', None)) == 'str':
@@ -318,7 +318,6 @@ def logic_create_codefile(self, filename, logics_code, overwrite=False):
         f = open(pathname, 'w', encoding='UTF-8')
         f.write(logics_code)
         f.close()
-
         return True
 
 
@@ -331,7 +330,6 @@ def logic_create_config(self, logicname, filename):
         config_list.append(['enabled', False, ''])
         self.logics.update_config_section(True, logicname, config_list)
         #        self.logics.set_config_section_key(logicname, 'visu_acl', False)
-        return
 
 
     def get_logic_state(self, logicname):
@@ -349,6 +347,17 @@ def get_logic_state(self, logicname):
         return json.dumps(logic_status)
 
 
+    def get_logic_template(self, logicname):
+        filename = os.path.join(self.template_dir, 'logic.tpl')
+        read_data = None
+        try:
+            with open(filename, encoding='UTF-8') as f:
+                read_data = f.read().replace('example_logic.py', logicname)
+        except Exception:
+            read_data = '#!/usr/bin/env python3\n' + '# ' + logicname + '\n\n'
+        return read_data
+
+
     def set_logic_state(self, logicname, action, filename):
         """
 
@@ -403,9 +412,9 @@ def set_logic_state(self, logicname, action, filename):
                 self.logger.warning("LogicsController.set_logic_state(create): Logic name {} is already used".format(logicname))
                 return json.dumps({"result": "error", "description": "Logic name {} is already used".format(logicname)})
             else:
-                if not os.path.isfile(os.path.join(self.logics.get_logics_dir(), filename)):
+                if not os.path.isfile(os.path.join(self._sh.get_config_dir(DIR_LOGICS), filename)):
                     #create new logic code file, if none is found
-                    logics_code = '#!/usr/bin/env python3\n' + '# ' + filename + '\n\n'
+                    logics_code = self.get_logic_template(filename)
                     if not self.logic_create_codefile(filename, logics_code):
                         self.logger.error(f"Could not create code-file '{filename}'")
                         return json.dumps({"result": "error", "description": f"Could not create code-file '{filename}'"})
@@ -430,8 +439,7 @@ def save_logic_parameters(self, logicname, params):
         #params = self.get_body()
         self.logger.info(f"LogicsController.save_logic_parameters: logic = {logicname}, params = {params}")
 
-        config_filename = os.path.join(self.etc_dir, 'logic')
-        logic_conf = shyaml.yaml_load_roundtrip(config_filename)
+        logic_conf = shyaml.yaml_load_roundtrip(self._sh.get_config_file(BASE_LOGIC))
         sect = logic_conf.get(logicname)
         if sect is None:
             response = {'result': 'error', 'description': "Configuration section '{}' does not exist".format(logicname)}
@@ -464,7 +472,7 @@ def save_logic_parameters(self, logicname, params):
             self.logger.info("LogicsController.save_logic_parameters: logic = {}, neue params = {}".format(logicname, dict(sect)))
 
 
-            shyaml.yaml_save_roundtrip(config_filename, logic_conf, False)
+            shyaml.yaml_save_roundtrip(self._sh.get_config_file(BASE_LOGIC), logic_conf, False)
             response = {'result': 'ok'}
 
         return json.dumps(response)
diff --git a/modules/admin/api_logs.py b/modules/admin/api_logs.py
index 934787639c..8189ac5027 100644
--- a/modules/admin/api_logs.py
+++ b/modules/admin/api_logs.py
@@ -27,7 +27,7 @@
 
 import lib.shyaml as shyaml
 from lib.utils import Utils
-
+from lib.constants import (DIR_ETC, BASE_LOG)
 import jwt
 from .rest import RESTResource
 
@@ -40,10 +40,10 @@ def __init__(self, module):
         self.base_dir = self._sh.get_basedir()
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
-        self.etc_dir = self._sh._etc_dir
+        self.etc_dir = self._sh.get_config_dir(DIR_ETC)
         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.logging_conf = shyaml.yaml_load(self._sh.get_config_file(BASE_LOG))
 
         self.chunksize = self.module.log_chunksize
 
diff --git a/modules/admin/api_plugin.py b/modules/admin/api_plugin.py
index 6ea940ae30..74587ee7ff 100644
--- a/modules/admin/api_plugin.py
+++ b/modules/admin/api_plugin.py
@@ -32,7 +32,7 @@
 from lib.plugin import Plugins
 from lib.metadata import Metadata
 from lib.model.smartplugin import SmartPlugin
-from lib.constants import (KEY_CLASS_PATH, YAML_FILE)
+from lib.constants import (KEY_CLASS_PATH, YAML_FILE, DIR_PLUGINS)
 
 from .rest import RESTResource
 
@@ -42,7 +42,7 @@ class PluginController(RESTResource):
     def __init__(self, module, jwt_secret=False):
         self._sh = module._sh
         self.base_dir = self._sh.get_basedir()
-        self.plugins_dir = os.path.join(self.base_dir, 'plugins')
+        self.plugins_dir = self._sh.get_config_dir(DIR_PLUGINS)
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
         self.logger.info("PluginController(): __init__")
         self.plugins = Plugins.get_instance()
diff --git a/modules/admin/api_plugins.py b/modules/admin/api_plugins.py
index dd7be5ab00..b644f6115e 100644
--- a/modules/admin/api_plugins.py
+++ b/modules/admin/api_plugins.py
@@ -36,7 +36,7 @@
 from lib.plugin import Plugins
 from lib.metadata import Metadata
 from lib.model.smartplugin import SmartPlugin
-from lib.constants import (KEY_CLASS_PATH, YAML_FILE)
+from lib.constants import (KEY_CLASS_PATH, YAML_FILE, DIR_PLUGINS)
 
 from .rest import RESTResource
 
@@ -45,7 +45,7 @@ class PluginsController(RESTResource):
     def __init__(self, module):
         self._sh = module._sh
         self.base_dir = self._sh.get_basedir()
-        self.plugins_dir = os.path.join(self.base_dir, 'plugins')
+        self.plugins_dir = self._sh.get_config_dir(DIR_PLUGINS)
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
         self.plugin_data = {}
@@ -95,7 +95,7 @@ class PluginsInstalledController(RESTResource):
     def __init__(self, module):
         self._sh = module._sh
         self.base_dir = self._sh.get_basedir()
-        self.plugins_dir = os.path.join(self.base_dir, 'plugins')
+        self.plugins_dir = self._sh.get_config_dir(DIR_PLUGINS)
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
         self.plugin_data = {}
@@ -164,7 +164,7 @@ class PluginsConfigController(RESTResource):
     def __init__(self, module):
         self._sh = module._sh
         self.base_dir = self._sh.get_basedir()
-        self.plugins_dir = os.path.join(self.base_dir, 'plugins')
+        self.plugins_dir = self._sh.get_config_dir(DIR_PLUGINS)
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
         self.plugins = Plugins.get_instance()
@@ -282,7 +282,7 @@ def __init__(self, module, shng_url_root):
         self.shng_url_root = shng_url_root
 
         self.base_dir = self._sh.get_basedir()
-        self.plugins_dir = os.path.join(self.base_dir, 'plugins')
+        self.plugins_dir = self._sh.get_config_dir(DIR_PLUGINS)
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
         self.plugins = Plugins.get_instance()
@@ -510,7 +510,7 @@ def __init__(self, module):
         self.module = module
 
         self.base_dir = self._sh.get_basedir()
-        self.plugins_dir = os.path.join(self.base_dir, 'plugins')
+        self.plugins_dir = self._sh.get_config_dir(DIR_PLUGINS)
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
         self.plugins = Plugins.get_instance()
@@ -553,7 +553,7 @@ def __init__(self, module):
         self.module = module
 
         self.base_dir = self._sh.get_basedir()
-        self.plugins_dir = os.path.join(self.base_dir, 'plugins')
+        self.plugins_dir = self._sh.get_config_dir(DIR_PLUGINS)
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
         self.plugins = Plugins.get_instance()
diff --git a/modules/admin/api_server.py b/modules/admin/api_server.py
index fe8853d69a..62d1385c73 100644
--- a/modules/admin/api_server.py
+++ b/modules/admin/api_server.py
@@ -30,6 +30,7 @@
 import bin.shngversion
 import lib.daemon
 import lib.backup as backup
+from lib.constants import (DIR_ETC, DIR_MODULES)
 
 
 # ======================================================================
@@ -75,9 +76,8 @@ def __init__(self, module):
         self.base_dir = self._sh.get_basedir()
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
-        self.etc_dir = self._sh._etc_dir
-        self.modules_dir = os.path.join(self.base_dir, 'modules')
-        return
+        self.etc_dir = self._sh.get_config_dir(DIR_ETC)  # not used?
+        self.modules_dir = self._sh.get_config_dir(DIR_ETC)  # not used?
 
 
     # ======================================================================
diff --git a/modules/admin/api_services.py b/modules/admin/api_services.py
index 8e671cabe5..639f5c7d11 100755
--- a/modules/admin/api_services.py
+++ b/modules/admin/api_services.py
@@ -35,6 +35,7 @@
 from lib.item_conversion import parse_for_convert as parse_for_convert
 from lib.shtime import Shtime
 import lib.env
+from lib.constants import (DIR_ETC, DIR_MODULES)
 
 
 # ======================================================================
@@ -51,9 +52,8 @@ def __init__(self, module):
         self.base_dir = self._sh.get_basedir()
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
-        self.etc_dir = self._sh._etc_dir
-        self.modules_dir = os.path.join(self.base_dir, 'modules')
-        return
+        self.etc_dir = self._sh.get_config_dir(DIR_ETC)  # not used?
+        self.modules_dir = self._sh.get_config_dir(DIR_ETC)  # not used?
 
 
     def get_body(self, text=False):
diff --git a/modules/admin/api_system.py b/modules/admin/api_system.py
index 481a0f0382..06ee77cbe6 100644
--- a/modules/admin/api_system.py
+++ b/modules/admin/api_system.py
@@ -42,6 +42,7 @@
 from lib.shpypi import Shpypi
 from lib.shtime import Shtime
 from lib.utils import Utils
+from lib.constants import (DIR_ETC, DIR_MODULES)
 
 
 # ======================================================================
@@ -87,9 +88,8 @@ def __init__(self, module):
         self.base_dir = self._sh.get_basedir()
         self.logger = logging.getLogger(__name__.split('.')[0] + '.' + __name__.split('.')[1] + '.' + __name__.split('.')[2][4:])
 
-        self.etc_dir = self._sh._etc_dir
-        self.modules_dir = os.path.join(self.base_dir, 'modules')
-        return
+        self.etc_dir = self._sh.get_config_dir(DIR_ETC)  # not used?
+        self.modules_dir = self._sh.get_config_dir(DIR_ETC)  # not used?
 
 
     # ======================================================================
diff --git a/scenes/.gitignore b/scenes/.gitignore
deleted file mode 100644
index 6c22af6ce7..0000000000
--- a/scenes/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-# ignore everything
-*
-# except .gitignore
-!.gitignore
diff --git a/structs/.gitignore b/structs/.gitignore
deleted file mode 100644
index 6c22af6ce7..0000000000
--- a/structs/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-# ignore everything
-*
-# except .gitignore
-!.gitignore
diff --git a/logics/logic.tpl b/templates/logic.tpl
similarity index 100%
rename from logics/logic.tpl
rename to templates/logic.tpl
diff --git a/functions/uf.tpl b/templates/uf.tpl
similarity index 100%
rename from functions/uf.tpl
rename to templates/uf.tpl
diff --git a/tests/mock/core.py b/tests/mock/core.py
index 967d56c345..47e69d5079 100644
--- a/tests/mock/core.py
+++ b/tests/mock/core.py
@@ -16,7 +16,7 @@
 from lib.module import Modules
 import lib.utils
 from lib.model.smartplugin import SmartPlugin
-from lib.constants import (YAML_FILE, CONF_FILE, DEFAULT_FILE)
+from lib.constants import (YAML_FILE, CONF_FILE, DEFAULT_FILE, BASES, DIRS)
 
 from tests.common import BASE
 
@@ -80,6 +80,8 @@ class MockSmartHome():
 #    _items_dir = os.path.join(_base_dir, 'items'+os.path.sep)
     _logic_conf_basename = os.path.join(_etc_dir, 'logic')
     _logic_dir = os.path.join(_base_dir, 'tests', 'resources', 'logics'+os.path.sep)
+    # for now, later remove _logic_dir, see lib/smarthome.py
+    _logics_dir = _logic_dir
 #    _cache_dir = os.path.join(_var_dir,'cache'+os.path.sep)
     _log_conf_basename = os.path.join(_etc_dir, 'logging')
 #    _smarthome_conf_basename = None
@@ -253,6 +255,45 @@ def getBaseDir(self):
         """
         return self._base_dir
 
+    def get_config_dir(self, config):
+        """
+        Function to return a config dir used by SmartHomeNG
+        replace / prevent a plethora of get_<foo>dir() functions
+
+        Returns '' for invalid config strings.
+
+        :return: directory as an absolute path
+        :rtype: str
+        """
+        # method would work fine without this check, but...
+        # make sure we don't allow "any" function call here
+        if config not in DIRS:
+            return ''
+
+        if hasattr(self, f'get_{config}dir'):
+            return getattr(self, f'get_{config}dir')()
+        elif hasattr(self, f'_{config}_dir'):
+            return getattr(self, f'_{config}_dir')
+        
+        return ''
+
+
+    def get_config_file(self, config, extension=YAML_FILE):
+        """
+        Function to return a config file used by SmartHomeNG
+
+        Returns '' for invalid config strings.
+
+        :return: file name as an absolute path
+        :rtype: str
+        """
+        # method would work fine without this check, but...
+        # make sure we don't allow "any" function call here
+        if config not in BASES:
+            return ''
+
+        return os.path.join(self.get_etcdir(), config + extension)
+
     def trigger(self, name, obj=None, by='Logic', source=None, value=None, dest=None, prio=3, dt=None):
         logger.warning('MockSmartHome (trigger): {}'.format(str(obj)))