Beispiel #1
0
def Run():

    # ++++++++++++++++++++++++++++++++++++++++ CLI Timeout ++++++++++++++++++++++++++++++++++++++++
    # 3 sec option to enter cli after timeout normal boot
    print()
    print()
    CLI_Timeout()


    print()
    print()
    print("Testing here")
    import machine
    print(machine.reset_cause())


    # ++++++++++++++++++++++++++++++++++++++++ Import / Run Dobby ++++++++++++++++++++++++++++++++++++++++
    try:
        import dobby.main
    except MemoryError as e:
        print('\n\n\n   Unable to load Dobby - Not enough free memory - Free memory: ' + str(gc.mem_free()) + ' - Starting CLI\n\n\n')
        CLI_Run()
    except SyntaxError as e:
        print('\n\n\n   Unable to load Dobby - Syntax error: ' + str(e) + ' - Starting CLI\n\n\n')
        CLI_Run()
    # except:
    #     print('\n\n\n   Unable to load Dobby Lib - Unknown Error - Starting CLI\n\n\n')
    #     CLI_Run()
    
    # No errors on import
    else:
        # Try to load the config
        try:
            Config = DobbyConfig.Load(Config_Name = 'device', Delete_On_Error = False)        
        except DobbyConfig.Error as e:
            # On error run the cli
            print("\n\n\n   Unable to load Dobby - Missing 'device' config - Starting CLI\n\n\n")
            CLI_Run()

        # Add defaults if missing
        Config.update(DobbyConfig.Defaults_Device(Config))

        # Check if we got all the config se need
        Resoult = DobbyConfig.Check_Device(Config)
        # If not true Resoult contains a string with the missing settings
        if Resoult is not True:
            print('\n\n\n   Unable to load Dobby - Missing config setting: ' + Resoult + ' - Starting CLI\n\n\n')
            CLI_Run()
        else:
            # Run dobby and pass loaded config
            dobby.main.Run(Config)
Beispiel #2
0
def Run():
    # Dict to hold config
    Config = {}
    # Print entry message
    print("\n   Dobby Command Line Interface\n")
    # Start eternal input loop
    while True:
        # Get_CLI_Input will break true when the user has requested we boot the system
        # After the needed settings is entered
        # This function is the CLI interface printing information and writing settings
        # Get user entry
        try:
            User_Entry = input("Dobby CLI: ")
        except (EOFError, KeyboardInterrupt):
            # If we got interrupted exit
            print("\n\n   Leaving CLI.\n")
            sys.exit()

        # Check if the 200 pound gorilla pressed enter without entering a command
        if User_Entry == "":
            continue

        # Check what we got from the user
        # ---------------------------------------- Help ----------------------------------------
        elif User_Entry.lower() == "help":
            print()
            print("Options marked with * is required configuration")
            print("Avalible commands:")
            print()
            print("   System:")
            print(
                "      boot - Boots the system after neede settings have been entered"
            )
            print("      cat <path> - Prints the content of a file from path")
            print(
                "      config check - Lists all missing settings needed to start Dobby"
            )
            print(
                "      config delete <config name or path> - Deleted the config with the given name or path"
            )
            print("      config dir - Lists all the config files in '/conf'")
            print(
                "      config list - Lists all settings needed to start Dobby and the current value"
            )
            print(
                "      config load <path> - Default: /conf/device.json - Loads the given config"
            )
            print("      config save - Saves the config to file system")
            print("      free memory - Prints the amount of free memory")
            print("      json - Paste a json config string")
            print("      ll <path> - Default: / - Lists content of path")
            print(
                "      log level <1-5> - Default: 1 - 0: Debug - 1: Info - 2: Warning - 3: Error - 4: Critical - 5: Fatal"
            )
            print()
            print("   Communication:")
            print("      wifi ssid <ssid> *")
            print("      wifi password <password> *")
            print()
            print("      mqtt broker <ip address> *")
            print("      mqtt port <port> - Default: 1883")
            print("      mqtt user <username> *")
            print("      mqtt password <password> *")
            print()
            print()
            continue

        # ---------------------------------------- Boot ----------------------------------------
        elif User_Entry.lower() == "boot":

            # Add default settings if needed
            Config.update(DobbyConfig.Defaults_Device(Config))

            # Check if we got all needed settings
            if DobbyConfig.Check_Device(Config) == True:
                # Save config to fs
                try:
                    DobbyConfig.Save('device.json', Config)
                except DobbyConfig.Error as e:
                    print("   " + str(e))
                else:
                    # Log event
                    print("   Base config OK. Rebooting")
                    # Reboot the device since there is not enough memory to load dobby
                    machine.reset()
            else:
                print("   Base config requirements not met unable to boot")
                continue

        # ---------------------------------------- cat ----------------------------------------
        elif User_Entry.lower().startswith("cat ") == True:
            # Check if we got a config store on local fs
            try:

                f = open(User_Entry[4:])
                cat_String = f.read()
                f.close()
            # No config store on fs or other error
            except OSError as e:
                print("   File: " + str[User_Entry[4:]])
                continue

        # ---------------------------------------- Config * ----------------------------------------
        elif User_Entry.lower().startswith("config ") == True:

            # User_Entry[7:] = remove "config " or "CONFIG " or any other combination there of
            User_Entry = User_Entry[7:]

            # ---------------------------------------- Config check ----------------------------------------
            if User_Entry.lower() == "check":
                # Check if we got all needed settings
                if DobbyConfig.Check_Device(Config) == True:
                    print("   Check passed")
                else:
                    print("   Check failed")
                # continue so we dont trigger unknown command
                continue

            # ---------------------------------------- Config delete ----------------------------------------
            elif User_Entry.lower().startswith("delete ") == True:
                User_Entry = User_Entry[7:]
                # Delete file and get resoult
                Resoult = DobbyConfig.Delete(User_Entry)
                if Resoult == True:
                    print("   Config file deleted: " + User_Entry)
                else:
                    print("   Unable to delete config file: " + User_Entry)
                continue

            # ---------------------------------------- Config dir ----------------------------------------
            elif User_Entry.lower() == "dir":

                # for loop to print files in config dir
                for Entry in uos.listdir('/conf'):
                    # print each line stripping ".json" from file name
                    print("   ", Entry.replace(".json", ""))
                continue

            # ---------------------------------------- Config list ----------------------------------------
            elif User_Entry.lower() == "list":
                List_String = ""

                # Add default if missing
                Config.update(DobbyConfig.Defaults_Device(Config))

                # Generate string
                Print_String = ""
                for Key, Value in Config.items():
                    Print_String = Print_String + "   " + str(
                        Key.replace('_', " ")) + ": " + str(Value) + "\n"

                print("\n" + Print_String)
                continue

            # ---------------------------------------- Config load ----------------------------------------
            elif User_Entry.lower().startswith("load") == True:
                # Load with no config specified defaulting to /conf/device.json
                if User_Entry.lower() == "config load":
                    # Load the config
                    Config = DobbyConfig.Load(Config_Name='device',
                                              Delete_On_Error=False)
                else:
                    # Load the config
                    Config = DobbyConfig.Load(Config_Name=None,
                                              Delete_On_Error=False,
                                              Full_Path=User_Entry[12:])
                # Check if we cloud load the config
                if Config == False:
                    Config = {}
                    print("   Unable to load config")
                    # Add defaults
                    Config.update(DobbyConfig.Defaults_Device(Config))
                else:
                    # Add defaults
                    Config.update(DobbyConfig.Defaults_Device(Config))
                    print("   Gonfig loaded")
                continue

            # ---------------------------------------- Config Save ----------------------------------------
            elif User_Entry.lower() == "save":
                # Try to save config
                try:
                    DobbyConfig.Save('device.json', Config)
                except DobbyConfig.Error as e:
                    print("   " + str(e))
                else:
                    # Log event
                    print("   Config saved to: /conf/device.json")
                    # Reboot the device since there is not enough memory to load dobby
                    machine.reset()

            # ---------------------------------------- Unknown command ----------------------------------------
            # Remember continue above so we dont trigger this
            else:
                print("Unknown config command: " + User_Entry)
                # since the 200 pound gorilla entered "config " and then someting incorrect
                # we need to continue because it was a config command and we dont need to check for other matchers
                continue

        # ---------------------------------------- Header ----------------------------------------
        elif User_Entry.lower().startswith("header ") == True:
            Config["Header"] = User_Entry
            continue
        # Hostname
        elif User_Entry.lower().startswith("hostname ") == True:
            Config["Hostname"] = User_Entry[9:]
            continue
        # Exit
        elif User_Entry.lower() == "exit":
            print("Quitting Dobby...")
            sys.exit()
        # free memory
        elif User_Entry.lower() == "free memory":
            print('   Free memory: ' + str(gc.mem_free()))
            continue

        # json
        elif User_Entry.lower() == "json":
            # Get json string from user
            json_Config = input("Please paste json config string: ")

            # Try to parse json
            try:
                # parse json to config dict
                Config = ujson.loads(json_Config)
            except ValueError:
                print()
                print("   Invalid json string")
                print()
                continue
            # Add default settings if needed
            Config.update(DobbyConfig.Defaults_Device(Config))
            # Log Event
            print("   json config ok")
            continue

        # log level
        elif User_Entry.lower().startswith("log level ") == True:
            # Check if the log level is valid
            ## Invalid level
            if int(User_Entry[10:]) not in range(0, 6):
                print()
                print("   Incorrect log level: " + User_Entry[10:])
                print()
            ## Valid level
            else:
                Config["Log_Level"] = int(User_Entry[10:])
            continue
        # ll
        elif User_Entry.lower().startswith("ll") == True:
            ll_Resoult = ""
            # ll /
            if User_Entry.lower() == "ll":
                ll_Resoult = uos.listdir()
            # ll <path>
            else:
                # Try to list path
                try:
                    ll_Resoult = uos.listdir(User_Entry[3:])
                # If failed report dir missing
                except OSError:
                    print()
                    print("   No sucth dir: " + User_Entry[3:])
                    print()
                    continue
            # Print listdir
            print()
            print(ll_Resoult)
            print()
            # continue so we dont trigger unknown command
            continue

        # ---------------------------------------- wifi ----------------------------------------
        elif User_Entry.lower().startswith("wifi ") == True:
            # User_Entry[5:] = remove "wifi " or "WIFI " or any other combination there of
            # wifi SSID
            if User_Entry[5:].lower().startswith("ssid ") == True:
                Config["WiFi_SSID"] = User_Entry[10:]
                continue
            # wifi Password
            elif User_Entry[5:].lower().startswith("password ") == True:
                Config["WiFi_Password"] = User_Entry[14:]
                continue

        # ---------------------------------------- mqtt ----------------------------------------
        elif User_Entry.lower().startswith("mqtt ") == True:
            # User_Entry[5:] = remove "mqtt " or "MQTT " or any other combination there of
            # MQTT broker
            if User_Entry[5:].lower().startswith("broker ") == True:
                Config["MQTT_Broker"] = User_Entry[12:]
                continue
            # MQTT Port
            elif User_Entry[5:].lower().startswith("port ") == True:
                Config["MQTT_Port"] = User_Entry[10:]
                continue
            # MQTT Username
            elif User_Entry[5:].lower().startswith("user ") == True:
                Config["MQTT_Username"] = User_Entry[10:]
                continue
            # MQTT Password
            elif User_Entry[5:].lower().startswith("password ") == True:
                Config["MQTT_Password"] = User_Entry[14:]
                continue

        # ---------------------------------------- Unknown command ----------------------------------------
        # Remember continue above so we dontr trigger this
        else:
            print("Unknown command: " + User_Entry)

    print()
    print("   Exitting Dobby Command Line Interface.")
    print()
Beispiel #3
0
    def __init__(self, Config):

        # Needed Variables
        ## Version
        Version = 300000
        ### First didget = Software type 1-Production 2-Beta 3-Alpha
        ### Secound and third didget = Major version number
        ### Fourth to sixth = Minor version number
        ## Dict holding all configs
        ### Fill with config from device.json if it failes self.Config will = False
        self.Config = Config
        ## Log Queue
        self.Log_Queue = list()
        ## Variable for Pin Monitor
        # Remember to pass Dobby aka self
        self.Pin_Monitor = DobbyPinMonitor.Init(self)
        ## Holds all loaded modules
        self.Modules = {}
        # Holds loaded System Modules like WirePusher if enabeled
        self.Sys_Modules = {}

        # Log relies on this to check if we need to blink on errors
        # So needs to be set before log is used the first time
        self.Indicator = None

        # If this is set, all subscribe and publishes will be mirrored and topic replaced as folles
        # <System Header>/<Hostname>/ = <self.gBridge>
        # We have to load this before mqtt so we know if we need to mirror topics
        self.gBridge_Topic = self.Config.get('gBridge_Topic', None)

        # I havent found a good way to get hardware info.
        # will use machine.EXT0_WAKE in a try statement
        # if we get AttibuteError then we know its a ESP8266
        try:
            if machine.EXT0_WAKE == None:
                pass
        # ESP8266
        except AttributeError:
            self.ESP_Type = 8266
        # ESP32
        else:
            self.ESP_Type = 32
            # # import and Start webrepl if esp32
            # import webrepl
            # webrepl.start()
            # self.Log(0, "System/webrepl", "Starting")

            # Import ntp time
            import ntptime

        # List of push messages that failed to send
        # we retry when online again
        self.Push_Queue = []

        # MQTT Connection status
        self.MQTT_State = 'init'
        self.MQTT_Reconnect_At = 0
        self.MQTT_Subscribe_To = []

        # Init message
        self.Log(1, 'System', 'Initializing Dobby version: ' + str(Version))

        # Subscribe to Commands topic
        self.MQTT_Subscribe(self.Peripherals_Topic("Commands"))

        # Change CPU frequancy if requested
        if Config.get('CPU_16', False) == True:
            machine.freq(160000000)
            self.Log(1, 'System', 'CPU frequancy set to: 16MHz')

        # ++++++++++++++++++++++++++++++++++++++++ WiFi setup ++++++++++++++++++++++++++++++++++++++++
        # Setup WiFi
        # ## Log event
        self.Log(1, 'System',
                 'Connecting to WiFi SSID: ' + self.Config['WiFi_SSID'])

        ## Disable AP
        self.ap0 = network.WLAN(network.AP_IF)
        # Check if AP is active
        if self.ap0.active() == True:
            # Disable ap if active
            self.ap0.active(False)

        ## Setup wlan0
        self.wlan0 = network.WLAN(network.STA_IF)
        # Activate wlan0 regardless if it is no not
        self.wlan0.active(True)

        # Check if the right SSID is configured
        if self.wlan0.config('essid') != self.Config['WiFi_SSID']:
            # Disconnect from incorrect ssid
            self.wlan0.disconnect()
            # Hostname only works with version 4 +
            # Set wifi hostname
            self.wlan0.config(
                dhcp_hostname=str.encode(self.Config['Hostname']))
            # Connect to wifi
            self.wlan0.connect(self.Config['WiFi_SSID'],
                               self.Config['WiFi_Password'])

        else:
            self.Log(0, 'WiFi', 'Config ok')

        # Var to indicate of we have published the ip we got when wifi connected
        self.wlan0_Published_IP = False

        # ++++++++++++++++++++++++++++++++++++++++ MQTT ++++++++++++++++++++++++++++++++++++++++
        # Remember to add something raondom after the hostname so the borker see a new connecton
        # Check if we got a user and pass for mqtt
        # Generate Unique Post Hostname
        Post_Hostname = str(os.urandom(1)[0] % 1000)
        # Log event
        self.Log(
            0, 'MQTT',
            'Using hostname: ' + self.Config['Hostname'] + "-" + Post_Hostname)
        # Stores messages so we can act on them in MQTT Loop
        ## List containing Topic and payload
        ## [[<Topic>, <Payload>]]
        self.MQTT_Incomming_Queue = []
        # Create MQTT Client
        self.MQTT_Client = MQTT.MQTTClient(
            self.Config['Hostname'] + "-" + Post_Hostname,
            self.Config['MQTT_Broker'], int(self.Config.get('MQTT_Port',
                                                            1883)),
            self.Config.get('MQTT_Username', None),
            self.Config.get('MQTT_Password', None))
        # Set last will
        self.MQTT_Client.set_last_will(
            self.Config['System_Header'] + "/" + self.Config['Hostname'] +
            "/Log/Will", "Disconnected")

        # try to connect to mqtt
        self.MQTT_Connect()

        # ++++++++++++++++++++++++++++++++++++++++ Setup peripherals ++++++++++++++++++++++++++++++++++++++++
        # ++++++++++++++++++++++++++++++++++++++++ Setup peripherals ++++++++++++++++++++++++++++++++++++++++
        # ++++++++++++++++++++++++++++++++++++++++ Setup peripherals ++++++++++++++++++++++++++++++++++++++++
        # Loop over config names in /conf and import matching modules
        ## Get config names
        Config_List = os.listdir('/conf')
        # Remove device.json since we dont want to use that again
        Config_List.remove('device.json')
        # Move relay to the front of the list if present
        ## try to remove
        for Entry in ['dimmer.json', 'relay.json']:
            try:
                Config_List.remove(Entry)
            ## if it fails do nothing
            except ValueError as e:
                pass
            ## If we removed relay.json add it back at the beginning of the list
            else:
                Config_List.insert(0, Entry)

        ## Loop over names in config
        for Name in Config_List:

            # Import the config
            ## False = Config not found or error during import
            ## If not false the imported Module will be returned

            Config = DobbyConfig.Load(Config_Name=Name, Delete_On_Error=False)
            Error = None

            # Load config is False if no config is found
            if Config is not False:
                # Try to import dobbydutton
                Module_Name = str('dobby.' + Name.replace('.json', ''))
                try:
                    Module = __import__(Module_Name.replace(".", '/'))
                except (AttributeError, TypeError, SyntaxError, ImportError,
                        KeyError) as e:
                    Error = str(e)
                except MemoryError as e:
                    Error = 'Not enough free memory. Free memory: ' + str(
                        gc.mem_free())
                finally:
                    # Check if Module import ok
                    if Error is None:
                        # Log event
                        self.Log(0, "System",
                                 "Module loaded: " + str(Module_Name))
                        # Pass config and get perifical object
                        # Remember to pass Dobby aka self so we can log in Button and use dobby variables
                        try:
                            self.Modules[Name.replace('.json',
                                                      '')] = Module.Init(
                                                          self, Config)
                        except self.Module_Error as e:
                            Error = str(e)
                            # Log event
                            self.Log(
                                4, "System", "Unable to load module: " +
                                str(Module_Name) + " - Error: " + Error)
                            # Remove config file
                            os.remove("/conf/" + Name)
                            self.Log(1, "System",
                                     "Removed config file: /conf/" + Name)
                    else:
                        # Log event
                        self.Log(
                            4, "System", "Unable to load module: " +
                            str(Module_Name) + " - Error: " + Error)
                        # Remove config file
                        os.remove("/conf/" + Name)
                        self.Log(1, "System",
                                 "Removed config file: /conf/" + Name)
            else:
                self.Log(0, 'System', "Invalid config: /conf/" + Name + "'")

        # Activate indicator if 'LED' owned by Indicator aka not used for something else
        # on esp32 its IO2
        # on esp8266 its D4
        if self.Pin_Monitor.Get_Owner(self.Pin_Monitor.LED) == 'Indicator':
            # check if indicator is already imported and init
            if self.Sys_Modules.get('indicator', None) == None:
                # Import Indicator
                import dobby.indicator
                # Init Indicator and store in Sys_Modules to enable loop
                self.Sys_Modules['indicator'] = dobby.indicator.Init(
                    self, {"System": {
                        "Pin": "LED"
                    }})
                # Create the indicator object
                self.Indicator = self.Sys_Modules['indicator'].Peripherals[
                    "System"]
            # indicator already imported to add an object in stead
            else:
                # Create the indicator object
                self.Indicator = self.Sys_Modules['indicator'].Add(
                    "System", {"Pin": "LED"})
                # On add the indicator will be blinked 3 times
                # will use this as boot blink

            # add wifi infication if disconnected
            if self.wlan0.isconnected() == False:
                self.Indicator.Add("WiFi", 4, "0.5s", "0.75s")

        else:
            # Log we could not enable indicator led
            self.Log(0, 'System/Indicator',
                     "LED Pin in use, cannot enable system indicator")

        # Boot done message
        self.Log(
            0, 'System', 'Dobby - Initialization compleate - Free memory: ' +
            str(gc.mem_free()))

        # Start loop()
        self.Loop()
Beispiel #4
0
    def __init__(self, Config):

        # Needed Variables
        ## Version
        Version = 300000
        ### First didget = Software type 1-Production 2-Beta 3-Alpha
        ### Secound and third didget = Major version number
        ### Fourth to sixth = Minor version number
        ## Dict holding all configs
        ### Fill with config from device.json if it failes self.Config will = False
        self.Config = Config
        ## Log Queue
        self.Log_Queue = list()
        ## Variable for Pin Monitor
        # Remember to pass Dobby aka self
        self.Pin_Monitor = DobbyPinMonitor.Init(self)
        ## Holds all loaded modules
        self.Modules = {}
        # Holds loaded System Modules like WirePusher if enabeled
        self.Sys_Modules = {}
        # Log relies on this to check if we need to blink on errors
        # So needs to be set before log is used the first time
        self.IndicatorLED = None
        # If this is set, all subscribe and publishes will be mirrored and topic replaced as folles
        # <System Header>/<Hostname>/ = <self.gBridge>
        # We have to load this before mqtt so we know if we need to mirror topics
        self.gBridge_Topic = self.Config.get('gBridge_Topic', None)

        # MQTT Connection status
        self.MQTT_State = 'init'
        self.MQTT_Reconnect_At = 0
        self.MQTT_Subscribe_To = []

        # Init message
        self.Log(1, 'System', 'Initializing Dobby version: ' + str(Version))

        # Subscribe to Commands topic
        self.MQTT_Subscribe(self.Peripherals_Topic("Commands"))

        # Change CPU frequancy if requested
        if Config.get('CPU_16', False) == True:
            machine.freq(160000000)
            self.Log(1, 'System', 'CPU frequancy set to: 16MHz')

        # ++++++++++++++++++++++++++++++++++++++++ WiFi setup ++++++++++++++++++++++++++++++++++++++++
        # Setup WiFi
        # ## Log event
        self.Log(1, 'System',
                 'Connecting to WiFi SSID: ' + self.Config['WiFi_SSID'])
        ## Disable AP
        self.ap0 = network.WLAN(network.AP_IF)
        # Check if AP is active
        if self.ap0.active() == True:
            # Disable ap if active
            self.ap0.active(False)

        ## Setup wlan0
        self.wlan0 = network.WLAN(network.STA_IF)
        # Activate wlan0
        self.wlan0.active(True)
        # Set wifi hostname
        self.wlan0.config(dhcp_hostname=str(self.Config['Hostname']))
        # Connect to wifi
        self.wlan0.connect(
            self.Config['WiFi_SSID'],
            self.Config['WiFi_Password'],
        )

        # Check if we connected
        if self.wlan0.isconnected() == True:
            # Log ip
            self.Log(0, 'WiFi', 'Got IP: ' + str(self.wlan0.ifconfig()[0]))
        else:
            # Log ip
            self.Log(0, 'WiFi', "Not connected")

        # ++++++++++++++++++++++++++++++++++++++++ MQTT ++++++++++++++++++++++++++++++++++++++++
        # Remember to add something raondom after the hostname so the borker see a new connecton
        # Check if we got a user and pass for mqtt
        # Generate Unique Post Hostname
        Post_Hostname = str(os.urandom(1)[0] % 1000)
        # Log event
        self.Log(
            0, 'MQTT',
            'Using hostname: ' + self.Config['Hostname'] + "-" + Post_Hostname)
        # Stores messages so we can act on them in MQTT Loop
        ## List containing Topic and payload
        ## [[<Topic>, <Payload>]]
        self.MQTT_Incomming_Queue = []
        # Create MQTT Client
        self.MQTT_Client = MQTT.MQTTClient(
            self.Config['Hostname'] + "-" + Post_Hostname,
            self.Config['MQTT_Broker'], int(self.Config.get('MQTT_Port',
                                                            1883)),
            self.Config.get('MQTT_Username', None),
            self.Config.get('MQTT_Password', None))
        # Set last will
        self.MQTT_Client.set_last_will(
            self.Config['System_Header'] + "/" + self.Config['Hostname'] +
            "/Log/Will", "Disconnected")

        # try to connect to mqtt
        self.MQTT_Connect()

        # ++++++++++++++++++++++++++++++++++++++++ Setup peripherals ++++++++++++++++++++++++++++++++++++++++
        # ++++++++++++++++++++++++++++++++++++++++ Setup peripherals ++++++++++++++++++++++++++++++++++++++++
        # ++++++++++++++++++++++++++++++++++++++++ Setup peripherals ++++++++++++++++++++++++++++++++++++++++
        # Loop over config names in /conf and import matching modules
        ## Get config names
        Config_List = os.listdir('/conf')
        # Remove device.json since we dont want to use that again
        Config_List.remove('device.json')
        # Move relay to the front of the list if present
        ## try to remove
        for Entry in ['dimmer.json', 'relay.json']:
            try:
                Config_List.remove(Entry)
            ## if it fails do nothing
            except ValueError as e:
                pass
            ## If we removed relay.json add it back at the beginning of the list
            else:
                Config_List.insert(0, Entry)

        ## Loop over names in config
        for Name in Config_List:

            # Import the config
            ## False = Config not found or error during import
            ## If not false the imported Module will be returned

            Config = DobbyConfig.Load(Config_Name=Name, Delete_On_Error=False)
            Error = None

            # Load config is False if no config is found
            if Config is not False:
                # Try to import dobbydutton
                Module_Name = str('dobby.' + Name.replace('.json', ''))
                try:
                    Module = __import__(Module_Name.replace(".", '/'))
                except (AttributeError, TypeError, SyntaxError, ImportError,
                        KeyError) as e:
                    Error = str(e)
                except MemoryError as e:
                    Error = 'Not enough free memory. Free memory: ' + str(
                        gc.mem_free())
                finally:
                    # Check if Module import ok
                    if Error is None:
                        # Log event
                        self.Log(0, "System",
                                 "Module loaded: " + str(Module_Name))
                        # Pass config and get perifical object
                        # Remember to pass Dobby aka self so we can log in Button and use dobby variables
                        try:
                            self.Modules[Name.replace('.json',
                                                      '')] = Module.Init(
                                                          self, Config)
                        except self.Module_Error as e:
                            Error = str(e)
                            # Log event
                            self.Log(
                                4, "System", "Unable to load module: " +
                                str(Module_Name) + " - Error: " + Error)
                            # Remove config file
                            os.remove("/conf/" + Name)
                            self.Log(1, "System",
                                     "Removed config file: /conf/" + Name)
                    else:
                        # Log event
                        self.Log(
                            4, "System", "Unable to load module: " +
                            str(Module_Name) + " - Error: " + Error)
                        # Remove config file
                        os.remove("/conf/" + Name)
                        self.Log(1, "System",
                                 "Removed config file: /conf/" + Name)
            else:
                self.Log(0, 'System', "Invalid config: /conf/" + Name + "'")

        # Activate indicator led if D4 owned by IndicatorLED aka not used for something else
        if self.Pin_Monitor.Pins['D4']['Owner'] == 'IndicatorLED':
            # Import IndicatorLED
            import dobby.indicatorled
            # Init IndicatorLED and store in Sys_Modules to enable loop
            self.Sys_Modules['IndicatorLED'] = dobby.indicatorled.Init(self)
            # Do boot blink if IndicatorLED is configured
            self.Sys_Modules['IndicatorLED'].Enable('Booting')

        # Boot done message
        self.Log(
            0, 'System', 'Dobby - Initialization compleate - Free memory: ' +
            str(gc.mem_free()))

        # Start loop()
        self.Loop()