ESP8266: MQTT Publish Generator
Omas Beatmungsgerät gehört direkt an die Steckdose, nicht hinter diesen Code. Und schon gar nicht in CustomLoop()
Das kommt in naher Zukunft häufiger auf mich zu: ein Arduino (in meinem Fall ein NodeMCU ESP8266 [Amazon, kein Affiliate]) mit mehreren Buttons und Relays. Anbindung an Home Assistant über MQTT. Genutzt wird der PubSubClient als MQTT-Client.
Nach Angabe der Konfiguration wird im Browser ein Code generiert, der ggf. weiter angepasst werden kann und über die Arduino-IDE wie jeder andere Code geflasht werden kann. Ebenfalls generiert wird ein Template für Home Assistant, das einfach in die configuration.yaml eingebunden werden kann, um die entsprechenden INPUT-/OUTPUT-Pins im Zugriff zu haben.
Kurze Randnotiz: INPUT und OUTPUT bezieht sich aus Sicht von Home Assistant. Ein INPUT-GPIO ist zum Beispiel ein Taster. Ein OUTPUT-GPIO eine LED oder ein Relay. WiFi blinkt bei Verbindungsaufbau (400ms EIN, 400ms AUS) oder leuchtet durchgängig bei vorhandenem Wlan.
GPIO | Beschriftung Board | Verwendung | Invertieren |
---|---|---|---|
GPIO00 | D3 | ||
GPIO01 | TX | ||
GPIO02 | D4 | ||
GPIO03 | RX | ||
GPIO04 | D2 | ||
GPIO05 | D1 | ||
GPIO06 | CLK | ||
GPIO07 | SD0 | ||
GPIO08 | SD1 | ||
GPIO09 | SD2 | ||
GPIO10 | SD3 | ||
GPIO11 | CMD | ||
GPIO12 | D6 | ||
GPIO13 | D7 | ||
GPIO14 | D5 | ||
GPIO15 | D8 | ||
GPIO16 | D0 |
Am Ende des Codes findet sich übrigens eine „CustomLoop“. In dieser kann direkt auf die Input-/Output-GPIOs zugegriffen werden und der Status verändert werden. Im Falle von Output-GPIOs wird der Status auch direkt über MQTT aktualisiert – schaltet ihr in der CustomLoop eine LED ein, bekommt dies euer HomeAssistant ebenfalls mit. Bitte beachte, dass, wenn keine Verbindung zum MQTT-Broker vorhanden ist, ggf. diese Funktion nur sehr selten (etwa ein mal alle 30 Sekunden) aufgerufen wird.
Falls dich ein paar Erklärungen zum Code interessieren, fange ich mal mit den INPUT-GPIOs an:
- für jeden GPIO gibt es eine Variable, die den letzten Status enthält
- Bei Veränderung des INPUTs (kurzgeschlossen / nicht kurzgeschlossen) wird eine MQTT-Nachricht gesendet
- der letzte Status wird sich gemerkt
- Repeat
Für jeden INPUT-GPIO gibt es eine eigene Funktion. Diese lautet "CheckButtonX", wobei X der GPIO ist. Wenn du angegeben hast, dass 5 ein INPUT ist, gibt es definitiv eine Funktion "CheckButton5", die den aktuellen Status von 5 mit der Variable Button5State
gegengleicht und erkennt, ob sich der Status von GPIO 5 geändert hat.
Die OUTPUT-GPIOs sehen etwas anders aus. Die haben zwar auch Variablen im selben Namensschema wie INPUT (z.B. Button12State
), aber die sind nur dafür da, um in CustomLoop
zu erkennen, ob du doch noch mal irgendwo Spannung angelegt hast. Die werden in der Funktion OnMQTTMessage
gegengeprüft und dementsprechend geschaltet. Alle OUTPUT-GPIOs werden in der Funktion OnMQTTMessage
verwaltet. Die wird, PubSubClient sei Dank, bei jeder eingehenden MQTT-Nachricht, die subscribed ist (was automatisch der Fall ist, wenn ein PIN auf OUTPUT steht, egal) aufgerufen. Da wird geguckt, ob ON oder OFF gesendet wird, und der PIN dementsprechend LOW oder HIGH geschaltet.
Es gibt eine zentrale Funktion ReportMQTTState
. Die wird jedes mal aufgerufen, wenn du in CustomLoop
den Status eines OUTPUTs änderst oder wenn der letzte Aufruf [inklusive Änderung von GPIOs durch dich] mindestens 15 Sekunden her ist. Die dient dazu, dass andere IoT-Geräte nicht der Meinung sind, dass der Arduino ein Timeout hat. Und halt, um den aktuellen Status von GPIOs zu übermitteln. Musst du dich nicht drum kümmern. Nutze einfach die CustomLoop
, schreibe da sowas rein wie digitalWrite(5, digitalRead(4) || digitalRead(12) ? HIGH : LOW)
und sei glücklich, dass alles sauber an Home Assistant übertragen wird.
Die Funktion CustomLoop
wird in der Standard-Config nur aufgerufen, wenn WiFi vorhanden ist. Wenn du kein WLAN hast, was du nutzen möchtest (und damit durch diesen Generator ein paar Zeilen Code generierst, die du sowieso wieder löscht, lass es in dem Fall einfach) wird die nicht funktionieren. Standardmäßig funktioniert die nur, wenn WLAN und Anbindung an den MQTT-Broker i.O. sind. Sonst nicht. Keine Ahnung, installiere dann Tasmoto, wird schon schief gehen. Aber dieser Codegenerator braucht dringend eine Verbindung zum WLAN und zum MQTT-Broker, um sauber zu laufen.
Das Script nimmt an Ressourcen, was es bekommt. Es unterstützt kein Deep Sleep, ohne größere Anpassungen vorzunehmen. Wenn du der Meinung bist, dass Strom sowieso zu teuer ist, kannst du ganz am Ende der loop()
ein Delay einbauen. Das kann das Script ab. Für DeepSleep habe ich abgefuckte Schaltungen mit Kondensatoren und XOR-Gattern gesehen, das würde zwar auch in so einen simplen Code-Generator machbar sein, aber auch automatisch ein paar Seiten an Anleitungen mitgenerieren müssen. Dafür bin ich zu faul.
Mehrere OUTPUTs, INPUTs, und WiFis sind möglich. Ich weiß nicht, was ich mal brauche, vielleicht möchte ich mal einen Radiowecker starten, wenn mein Türschloss keine Verbindung mehr zum WLAN hat. Auf dem Weg kann ich sowohl immer 400 Sekunden am Stück (mit 400 Sekunden Pause zwischendrin) den Wecker hören, als auch eine LED in einem verbauten Kasten (nicht) angucken. Praktisch. Ist gewollt, dass man mehr WLAN-LEDs angeben kann, aber je mehr ich drüber nachdenke umso dümmer klingt das. Ist dennoch möglich.
Kategorien: Arduino, Home Assistant