Der Traum einer eigenen Hausautomation

Da wir seit kurzem Häuslebesitzer sind, wollte ich mein Heim etwas automatisieren. Bestehende Lösungen wie z.B. von Homematic und Konsorten, finde ich persönlich nicht gut, da sie entweder teuer oder unsicher sind und ich nicht weiß, was mit meinen Daten passiert, daher baue ich mir einfach etwas eigenes. Know-How ist vorhanden. Alles was fehlt, kann man kaufen oder sich aneignen. Im ersten Step, soll einfach eine simple Temperatur- und Luftfeuchtigkeitsmessung implementiert werden.

Aktuell arbeite ich mich in die Mikrocontroller von espressif ein, da Sie recht günstig und vollgestopft mit sinnvollen Funktionen sind. Aktuell kostet ein ESP32 Dev Board (bereits mit Pinouts und einigen Spielereien) ca. 10€. Entweder man bestellt Sie im Land der aufgehenden Sonne, muss aber dann einige Wochen warten, oder man wird hier direkt bei Amazon fündig:

Nach dem die guten Stücke dann angekommen sind, habe ich prompt begonnen die Firmware zu schreiben. Wie das geht, werde ich in einem späteren Artikel niederschreiben.

Etliche Stunden und Tests später, war die grundlegende Firmware „fertig“ (wann ist Software mal fertig?).

Automatische Updates und Zugriff auf externe APIs

Da ich in meinem Haus mindestens einen Controller pro Raum haben möchte, wäre es ziemlich dämlich, eventuelle neue Firmwares via USB auszurollen. Das ist zeitaufwendig und nervig, das will ich nicht.

Programmierer wie ich bin, habe ich dann einfach ein OTA-Update-System (over the air) implementiert. Zugegebenermaßen, ist das nicht auf meinen Mist gewachsen und habe mich der großen Community hinter den Controllern bedient und an meine Bedürfnisse angepasst und erweitert.

Der Vorteil eines solchen Systems liegt klar auf der Hand:

Ich schreibe eine neue Firmware bzw. implementiere neue Funktionen, teste sie mit einem Developer-Board direkt am Rechner, committe Sie nach GitLab und die CI baut mir die Firmware, mithilfe von PlatformIO und Docker, und schiebt sie auf einen FTP-Server. Von dort aus holen sich dann die Controller die Infos und die Binaries. Das ganze Verfahren klappt super und verlässlich. Wie genau das funktioniert, erfährst du in meinem Artikel Automatische Firmware-Updates für Microcontroller mit Gitlab und PlatformIO, da auch der Wunsch innerhalb der ESP-Gruppen im Facebook kam.

Das passende Diagramm sähe, im Groben, so aus:

Zu schnell gefreut, irgendetwas kommt immer

Mein ESP8266 startet nun aber nicht mehr und hängt in einer Bootschleife. Das passiert aber nur bei meinem WLAN zuhause. Mit dem ESP32 klappt das wunderbar und auch mit einem anderen WLAN mit dem ESP8266. Daher habe ich mir einmal den Exception-Stack genommen und diesen einmal entschlüsselt (wie das geht, erfährst du in meinem Artikel Exceptions und Fehlermeldungen eines ESP-Mikrocontroller entschlüsseln):

Decoding 10 results
Exception (28):
epc1=0x40219f8c epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: cont
sp: 3fff26e0 end: 3fff2960 offset: 01a0
>>>stack>>>
3fff2880: 00000000 3ffe8f0c 3fff1778 40219f8c
3fff2890: 00000000 00000000 00000000 00000000
3fff28a0: 00000000 00000000 00000000 00000000
3fff28b0: 00000000 3fff5f7c 0000003f 00000034
3fff28c0: 00000000 3fff3198 3fff1778 4021a0ed
3fff28d0: 00000000 00000000 00000000 4020ba68
3fff28e0: 00000000 00000000 3fff5e3c 4020bbcc
3fff28f0: 00000000 00000000 4021961c 4021b72c
3fff2900: 00000000 3fff14b8 3fff15cc 3fff5ea4
3fff2910: 0000000f 0000000a 3fff1778 4021197e
3fff2920: 00000000 3fff14b8 3fff1778 4021bb44
3fff2930: 00000000 00000000 00000000 feefeffe
3fff2940: 3fffdad0 00000000 3fff1924 40202ef8
3fff2950: feefeffe feefeffe 3fff1940 40205064
<<<stack<<<

Der „entschlüsselte“ Stack ist dieser hier:

Decoding 10 results
0x40219f8c: checkRegistration() at ?? line ?
0x4021a0ed: registerDeviceAPI() at ?? line ?
0x4020ba68: UdpContext::UdpContext() at ?? line ?
0x4020bbcc: WiFiUDP::begin(unsigned short) at ?? line ?
0x4021961c: std::_Function_base::_Base_manager ::_M_manager(std::_Any_data&, std::_Function_base::_Base_manager const&, std::_Manager_operation) at main.cpp line ?
0x4021b72c: std::_Function_handler ::_M_invoke(std::_Any_data const&) at main.cpp line ?
0x4021197e: Ticker::start() at ?? line ?
0x4021bb44: setup at ?? line ?
0x40202ef8: loop_wrapper() at core_esp8266_main.cpp line ?
0x40205064: cont_norm at cont.o line ?

Das Problem scheint also in der Function „checkRegistration“ zu passieren. Diese sieht wie folgt aus:

bool checkRegistration(){
  String params = "columns=ID&filter=MAC,eq,"+urlencode(WiFi.macAddress());
  // Debug.println("[checkRegistration]: Params: "+params);
  JsonObject& ret = api.get("Devices", params);
  if (ret.success()) {
    DeviceID = ret["Devices"][0]["ID"] | 0;
    if(DeviceID != 0){
      Debug.println("[checkRegistration]: Device already registered: "+String(DeviceID));
      return true;
    }else{
      Debug.println("[checkRegistration]: Device not registered");
      return false;
    }
  }else{
     Debug.println("[checkRegistration]: Failed!");
     return false;
  }
}
JsonObject& API::get(String url, String params){
    DynamicJsonBuffer apiJsonBuffer(2000);
    String URL = String(API_BASE)+"/"+url+"/?"+params+"&transform=1";
    if(verboseLogging){
        Debug.println("[API::get]: Calling API: "+URL);
    }

    API::apiObject.begin(URL);
    int httpCode = API::apiObject.GET();
    // delay(1000);
    if(httpCode) {
        Debug.println("[API::get]: Got HTTP: "+String(httpCode));
        if(httpCode == 200) {
            String retJson = API::apiObject.getString();
            retJson.replace("""", "\\""");
            Debug.println("[API::get]: Got JSON: "+String(retJson));

            JsonObject& ret = apiJsonBuffer.parseObject(retJson);
            apiJsonBuffer.clear();
            if (ret.success()) {
                return ret;
            }else{
                Debug.println("[API::get]: Could not parse JSON: ");
                return apiJsonBuffer.createObject();
            }
        }
        }else{
            Debug.println("[API::get]: Call Failed! HTTP-Code "+String(httpCode));
            // display_text("API::get failed");
            API::apiObject.end();
            return apiJsonBuffer.createObject();
        }
}

Das Objekt API::apiObject ist eigentlich nichts anderes, als eine Instanz der HTTPClient-Klasse, also kein Hexenwerk.
Ich habe auch schon mit diversen Ausgaben herausgefunden, dass er gar nicht erst in die Methode der API hineinläuft und scheinbar vor dem Aufruf in der „checkRegistration“ stehen bleibt und nichts mehr passiert.

Wie gesagt, das passiert auch nur in meinem WLAN zuhause. Zuhause habe ich auch nichts besonderes:
Eine einfache Unitymedia Horizon-Box mit 2,4 und 5GHz WLAN, ne Synology NAS und halt ein paar Clients, das war’s aber auch im großen und Ganzen.

Ernüchterung und etwas verbuggte Firmware

Bei Reddit hatte ich das Problem auch beschrieben, ebenso im Facebook. Viele meinten, es könne an Sonderzeichen innerhalb der SSID liegen. Ist bei mir auch der Fall, da meine SSID Leerzeichen enthält. Diese hatte ich aber schon in vorherigen Tests entfernt – ohne Erfolg.
Dann habe mir einmal mein iPhone und mein iPad genommen und einen Hotspot eingerichtet, so dass der ESP sich gegen diesen verbinden kann. Hier klappte es dann ohne Probleme.
Also muss es ein meinem WLAN liegen. Wie sich dann rausstellte, hat der ESP8266 anscheinend Probleme mit Sonderzeichen, im meinem Falle konkret ein Dollar-Zeichen ($). Wer auch immer hier die Finger mit im Spielhatte beim ESP8266, gehört eigentlich dafür erschlagen. Vermutlich werde ich aber dafür einen Call bei Espressif im Github aufmachen. Wenn es nicht sogar schon einen gibt, denn das ist schon ein kritischer Bug.

Jedenfalls klappt es jetzt, ohne Sonderzeichen.

Vielleicht hilft das dem Einen oder Anderen von Euch einmal 🙂

Artikel teilen:Share article:

Mehr Artikel entdecken

Ubuntu-Bash unter Windows 10
Vorheriger Artikel

Ubuntu-Bash unter Windows 10

Microsoft goes Ubuntu Wer Ubuntu und die Linux-Bash allgemein liebt, der wird sie in Windows wohl möglich vermissen und sich nebenher eine VM-Ware mit Ubuntu aufgesetzt habe oder (für die ganzen hardcore Nerds) einen Docker-Container mit einem Ubuntu. Seit neusten bietet aber Windows auch die Möglichkeit an, um genau zu

6 min read 11. Jan. 2018
Automatische Firmware-Updates für Microcontroller mit Gitlab und PlatformIO
Nächster Artikel

Automatische Firmware-Updates für Microcontroller mit Gitlab und PlatformIO

Bereits im Artikel ESP8266 stürzt in nur einem WLAN ab und hängt in einer Bootschleife hatte ich schon einmal angesprochen, dass ich ein selbst aktualisierendes Netzwerk von Controllern bauen möchte, welches mein Haus überwacht. Heute möchte ich Dir einmal das System des automatischen Ausrollen der Firmware-Updates etwas genauer erklären. Voraussetzungen

18 min read 16. Jan. 2018
Exceptions und Fehlermeldungen eines ESP-Mikrocontroller entschlüsseln
Ähnlicher Artikel

Exceptions und Fehlermeldungen eines ESP-Mikrocontroller entschlüsseln

Immer wieder kommt aus vor, dass die Mikrocontroller einfach abstürzen und Fehlermeldungen und Exceptions werfen und im schlimmsten Falle auch in einer Boot-Schleife festhängen. Dann ist es sinnvoll die Ausgabe des Serial-Ports zu begutachten und den Exception-Stack zu analysieren. Dieser ist aber in der Regel recht kryptisch. In diesem Artikel

4 min read 27. Feb. 2018
Pushbenachrichtigungen mit Pushover und ESP-Mikrocontroller
Ähnlicher Artikel

Pushbenachrichtigungen mit Pushover und ESP-Mikrocontroller

Sinn und Unsinn Im Umfeld mit mobilen Geräten kennen wir sie, Pushbenachrichtigungen. Sie „ploppen“ auf diversen Geräten auf, egal ob iPhones, Desktops oder Tablets. Jeder möchte sie, aber jeder hasst sie gleichermaßen. Dennoch haben sie einen Sinn und eine Daseinsberechtigung. Pushbenachrichtigungen sind immer dann sinnvoll, wenn man als Sender aktiv

6 min read 30. Jan. 2018
Automatische Firmware-Updates für Microcontroller mit Gitlab und PlatformIO
Ähnlicher Artikel

Automatische Firmware-Updates für Microcontroller mit Gitlab und PlatformIO

Bereits im Artikel ESP8266 stürzt in nur einem WLAN ab und hängt in einer Bootschleife hatte ich schon einmal angesprochen, dass ich ein selbst aktualisierendes Netzwerk von Controllern bauen möchte, welches mein Haus überwacht. Heute möchte ich Dir einmal das System des automatischen Ausrollen der Firmware-Updates etwas genauer erklären. Voraussetzungen

18 min read 16. Jan. 2018
ESP-Mikrocontroller mit Visual Studio Code programmieren
Ähnlicher Artikel

ESP-Mikrocontroller mit Visual Studio Code programmieren

Arduino-IDE, nur auf den ersten Blick schön Als geneigter und gelernter Entwickler, mit nun mehr als 10 jähriger Berufserfahrung, kenne ich mittlerweile die verschiedensten Tools zum Entwickeln. Ob es nun ein stumpfer Text-Editor ist oder ein vollwertiges und teures Visual-Studio. Alles hat seine Vor- und Nachteile… Als ich vor einigen

6 min read 11. Jan. 2018