FHEM Tutorial-Reihe - Part 26: Wemos ESP8266 Temperatur per MQTT an FHEM senden
Dieses Video ist schon überfällig! Umso mehr freue ich mich, dass ich es endlich mit Euch teilen darf. Es geht um die ESP8266 Mikrokontroller. In meinem Beispiel habe ich WeMos gewählt. Diese sind sowohl mit Arduino als auch NodeMCU kompatibel. Für dieses Video nutze ich einen DHT-Sensor, welcher sowohl die Temperatur, als auch die Luftfeuchtigkeit misst.
Was wird benötigt?
- Ein Arduino kompatibler ESP8266 + Sensoren
- Ein Raspberry Pi mit FHEM o.ä.
Video
Komponenten
Ich habe meine Komponenten über Amazon bezogen - wobei ich sagen muss, dass man dort viel zu viel Geld ausgibt. Über verschiedene ausländische Shops bleibt man sehr deutlich unter diesem Kurs. Mir war allerdings die Liefergeschwindigkeit sehr wichtig, und so habe ich kurzerhand über Amazon bestellt. Falls Du etwas mehr Zeit mitbringst oder direkt mehrere Boards bestellen möchtest, lohnt sich in jedem Fall eine genauere Recherche.
Der D1-Mini ist ein kleines Board mit 11 digitalen Ein-/Ausgänge und einem analoger Eingang. Programmiert wird das Board mit der Arduino- oder nodemcu-Umgebung. Angeschlossen wird er über Micro-USB. Zusätzlich gibt es verschiedene fertige “Shields”, welche man auf das Board einfach aufstecken kann. Diese sind relativ einfach zu intergrieren, da es bestehende Beispielprojekte gibt, welche man einfach kopieren kann.
Da der D1-Mini über ein WLAN-Modul verfügt, kann man diesen extrem komfortabel und platzsparend integrieren. Mit verschiedenen Deep-Sleep-Mechanismen ist es außerdem möglichen, diesen per Battery-Pack sehr lange zu betreiben. So könnte man z.B. eine Powerbank nutzen und hat so ein sehr kompaktes System, welches man praktisch überall verstauen kann. Das Limit ist hierbei dann nurnoch die Reichweite vom WLAN.
Welche Shields es alle gibt, findest Du hier. Darüber hinaus kann man sich natürlich alles mögliche selber bauen.
Mein DHT11 unterscheidet sich vom teureren DHT22 wie folgt.
DHT11
- 20-80% Luftfeuchtigkeitsmessung mit 5% Genauigkeit
- 0 bis 50°C Temperaturmessung ±2°C Genauigkeit
- No more than 1 Hz sampling rate (once every second)
- Größe15.5mm x 12mm x 5.5mm
DHT22
- 0-100% Luftfeuchtigkeitsmessung mit 2-5% Genauigkeit
- -40 bis 125°C Temperaturmessung ±0.5°CGenauigkeit
- No more than 0.5 Hz sampling rate (once every 2 seconds)
- Größe 15.1mm x 25mm x 7.7mm
MQTT
MQTT steht für Message Queue Telemetry Transport. Das klingt aber komplizierter als es ist. Vom Prinzip her gibt es einen “Broker”, welche alle Verbindungen verwaltet und als Zentrale alle Nachrichten zustellt. Dabei werden die Nachrichten in einer Hierarchie/Baumstruktur aufgebaut. So könnte ein Pfad zum Beispiel wie folgt lauten: /Wohnung/WeMos/Buero/Temperatur/Grad
So kann man sich eine logische Struktur nach den eigenen Wünschen aufbauen. Wobei “aufbauen” bedeutet, dass man sich diese einfach überlegt und dann Nachrichten dorthin sendet. Also extrem einfach. Wie das genau abläuft, erfahrt ihr aber im Video.
Wir entscheiden uns für den OpenSource Broker “Mosquitto”. Dieser wird einfach zusätzlich auf dem Raspberry installiert. Generell wäre es aber auch möglich, Broker im Internet zu nutzen. Das hätte den Vorteil, dass man von überall an seine Daten kommt und sich z.B. auch eine App bauen könnte, welche per MQTT Daten erhält. Das ginge aber mit Port-Forwarding genauso.
sudo apt-get update
sudo apt-get upgrade
wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key
cd /etc/apt/sources.list.d/
sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list
sudo apt-get update
sudo apt-get install mosquitto mosquitto-clients python-mosquitto
sudo cpan install Net::MQTT:Simple
sudo cpan install Net::MQTT:Constants
Zum Testen ob alles läuft, können wir in zwei getrennten SSH-Verbindungen folgendes ausführen.
mosquitto_sub -h 127.0.0.1 -t Test/#
mosquitto_pub -h 127.0.0.1 -t Test/Temperature -m "19.5"
Den ersten Befehl führen wir in der ersten Verbindung aus und den zweiten in der anderen. Wenn alles richtig läuft können wir die Ausgabe “19.5” im ersten Fenster sehen.
Herzlichen Glückwunsch, das war der erste Versand von Informationen über MQTT.
Arduino IDE
Die Arduino-IDE benötigen wir, um unser Programm auf den ESP8266 zu bekommen. Diese müssen wir auf dieser Webseite herunterladen. Die IDE gibt es für jedes gängige Betriebssystem.
Folgende URLs braucht ihr (mehr Infos im Video):
- http://arduino.esp8266.com/stable/package_esp8266com_index.json
- https://github.com/adafruit/DHT-sensor-library
- https://github.com/256dpi/arduino-mqtt
- https://github.com/adafruit/Adafruit_Sensor
Ich musste auf dem Mac noch einen Treiber für USB zu Serial installieren.
- https://www.silabs.com/products/mcu/Pages/USBtoUARTBridgeVCPDrivers.aspx (aus dem Video)
- oder (falls der andere nicht funktioniert) https://www.wemos.cc/downloads
Nach der Installation ist unbedingt ein Neustart des Computers erforderlich. Fragt mich nicht warum, aber von Unix-Systemen bin ich eigentlich anderes gewöhnt. Mein Mac starte ich sonst maximal einmal im Monat neu.
In der Arduino-IDE legen wir dann ein neues Projekt an. Hier der Code:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include "DHT.h"
#include <MQTTClient.h>
#define DHTTYPE DHT11
#define DHTPIN 2
const char* host = "192.168.178.21";
const char* ssid = "DeineCooleSSID";
const char* password = "xxxxxx";
WiFiClient net;
MQTTClient mqtt;
DHT dht(DHTPIN, DHTTYPE);
void connect();
void setup() {
dht.begin();
Serial.begin(115200);
Serial.println();
Serial.println("Booting...");
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
mqtt.begin(host, net);
connect();
Serial.println("Setup completed...");
}
void loop() {
if (!mqtt.connected()) {
connect();
}
mqtt.loop();
float temp = dht.readTemperature();
float humidity = dht.readHumidity();
Serial.print("Sending... ");
if (!isnan(humidity) || !isnan(temp)) {
mqtt.publish("/Wohnung/Buero/temp", String(temp));
mqtt.publish("/Wohnung/Buero/humidity", String(humidity));
Serial.print("Temp: ");
Serial.print(String(temp));
Serial.print(" Humidity: ");
Serial.println(String(humidity));
}
delay(30000);
}
void connect() {
while(WiFi.waitForConnectResult() != WL_CONNECTED) {
WiFi.begin(ssid, password);
Serial.println("WiFi connection failed. Retry.");
}
Serial.print("Wifi connection successful - IP-Address: ");
Serial.println(WiFi.localIP());
while (!mqtt.connect(host)) {
Serial.print(".");
}
Serial.println("MQTT connected!");
}
void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
Serial.print("incoming: ");
Serial.print(topic);
Serial.print(" - ");
Serial.print(payload);
Serial.println();
}
Natürlich müssen oben im Code die Werte für host (der Raspberry, auf welchem MQTT läuft), SSID und Passwort geändert werden. Ansonsten weiß der ESP ja nicht, wo er seine gesammelten Informationen hinschicken darf.
Dann richten wir die Umgebungseinstellungen noch wie im Video zu sehen ein und schießen das Ganze per USB auf unseren D1 mini. Danach können wir über die serielle Schnittstelle sehen, ob alles richtig gesammelt und versendet wird.
FHEM
Der wichtigste Teil läuft nun schon. Jetzt müssen wir uns mit FHEM nur noch auf den Broker verbinden und die entsprechenden Werte in Readings schreiben. Klingt einfach, ist es auch.
define Mosquitto MQTT <ip>:1883
define <mqtt-device-name> MQTT_DEVICE
Natürlich muss hierbei
Hier noch das konkrete Beispiel aus dem Video:
define BueroTemperatur MQTT_DEVICE
attr BueroTemperatur subscribeReading_messured-temp /Wohnung/Buero/temp
attr BueroTemperatur subscribeReading_humidity /Wohnung/Buero/humidity
Eigentlich relativ schnell erklärt: Der zweite Teil des Attributnamens (hinter subscribeReading_) steht für den Namen des Readings, welches mit den Werten befüllt wird, welche in den danach angegebenen Pfad geschrieben werden.
Das ist der lesende Teil. Theoretisch gibt es auch noch die Möglichkeit, mit einer MQTT_Bridge gewisse Aktionen ausführen zu lassen, sobald dort etwas gesendet wird. Aber da ich aktuell nur Sensoren habe und noch keine Schalter o.ä. kommt dieser Teil für mich in Frage. Das wäre Stoff für ein weiteres Video.
Nachdem alles korrekt eingerichtet wurde, werden alle 30 Sekunden neue Werte über MQTT in den Broker geschrieben und somit auch in FHEM aktualisiert. Darauf könnte man nun einen Graphen erstellen etc.
Fazit
Ich finde die Lösung extrem praktisch. Das Ganze ist mit nur einem Gerät natürlich etwas übers Ziel hinaus geschossen, aber spätestens wenn man sehr viele von den kleinen ESP8266 überall im Netzwerk einbaut, zahlt sich diese Lösung am Ende aus. Ein weiteres Gerät vom gleichen Typ wäre jetzt in wenigen Minuten aufgenommen. Einfach den MQTT-Pfad ändern, ebenfalls aufspielen und in FHEM ein weiters Gerät anlegen. Fertig.
Natürlich ist dies nur ein ganz kleiner Schritt in eine große Welt. Was man alles mit Arduino anstellen kann ist unglaublich. Man könnte auf Tastendrücke reagieren und sich so eigene Batteriebetriebene WLAN-Schalter bauen. Oder die Feuchtigkeit in Blumen messen um sich informieren zu lassen, wann diese wieder gegossen werden müssen. Die Möglichkeiten sind (ohne zu übertreiben) wirklich grenzenlos.
Auf der anderen Seite steht MQTT - ebenfalls sind hier die Möglichkeiten unendlich. Für so gut wie jede Programmiersprache gibt es einen Client, sodass man auch aus FHEM heraus seine ganzen Events zu MQTT schicken könnte, um diese dann in Echzeit-Apps, Dashboards oder anderen Lösungen zu integrieren. Den ganzen Kommunikations-Stress übernimmt dabei MQTT für einen. Man kann sich also sicher sein, dass Nachrichten auch wirklich zugestellt werden.
Was habe ich draus gemacht?
In meinem Rack misst jetzt also mein neuer kleiner Freund immer brav die Temperatur. Sollte diese über ein gewisses Level steigen, werde ich benachrichtigt. Aber das ist natürlich nur der erste Schritt. Später werde ich dafür sorgen, dass automatisch ein Lüfter eingeschaltet wird, wenn es zu warm im Rack wird.
Zusätzlich würde ich mir ganz gerne auf einem Display Infos aus FHEM einblenden lassen. Diese werden natürlich ebenfalls per MQTT übermittelt. Aber dazu später mehr.
Mein Bastelinstinkt ist jedenfalls mehr als geweckt!
Viel Erfolg bei der Umsetzung!