Der Raspberry Pi ist wie geschaffen für die Hausautomatisierung, jedoch gibt es oftmals Anwendungen, bei denen günstigere Außenposten sinnvoll sind. Dafür wollen wir den ESP8266 NodeMCU nutzen. Der Raspberry Pi fungiert dabei als Hauptstation, an den die MQTT Signale vom ESP8266 gesendet werden. Die Übertragung ist dabei sogar über andere Netzwerke / das Internet (der Dinge) möglich. Das ganze kann entweder über ein Smart Home System wie OpenHAB stattfinden, oder aber auch über das normale Raspberry Pi Betriebssystem Raspbian.
Entweder werden die Signale in einem definierten Intervall gesendet, oder aber erst auf Abfrage. Beide Szenarien werden in diesem Tutorial beschrieben und durchgeführt.
Zubehör
Im Endeffekt kannst du eine beliebige Menge an Außenposten betreiben, wobei jeder anders konfiguriert werden kann und somit andere Daten verschickt. Der Einfachheit halber habe ich es jedoch lediglich mit diesen beiden Komponenten durchgeführt:
Mehr Zubehör ist nicht nötig (bis auf Stromversorgung / Batterien bzw. Powerbänke).
Auch wenn der Raspberry Pi nicht viel kostet, ist ein ESP8266 Board noch einmal wesentlich günstiger. So ist es möglich für wenig Geld an verschiedensten Orten
MQTT Vorbereitung: Raspberry Pi & ESP8266 NodeMCU
Wir beginnen mit dem Raspberry Pi. Falls du nicht OpenHAB zur Abfrage nutzen willst, so folge diesem Tutorial um Mosquitto zu installieren. Andernfalls starten wir mit der OpenHAB Einrichtung. Dazu muss zunächst einmal auf dem Raspberry Pi OpenHAB installiert sein.
Rufe in einem Browser deiner Wahl http://openhabianpi:8080/ auf und wähle das Paper UI aus (ggf. musst du die interne IP Adresse statt „openhabianpi“ nehmen). Unter „Add-ons“- > „Bindings“ suchst du das „MQTT Binding“ sowie unter Transformations „Regex“ und installierst diese. Das dauert einen Augenblick.
Weiter geht es mit dem ESP8266 NodeMCU. Wir müssen dafür eine Custom Firmware auf den NodeMCU flashen. Hierbei ist wichtig, dass das MQTT Paket ausgewählt wird (inkl. aller anderen benötigten Bibliotheken). Möchtest du bspw. einen DHT Sensor nutzen, so solltest du die entsprechende Library auch auswählen. Wichtig ist, dass die MQTT Bibliothek ausgewählt wurde.
Danach flashen wir die Firmware mit dem ESP8266Flasher wie hier detailiert beschrieben.
MQTT Exkurs
Wie bereits im vorherigen Tutorial erklärt, wird ein Broker benötigt, um die Daten weiterzuleiten. So ein Broker kann bspw. auf dem Raspberry Pi im Hintergrund laufen. Verbundene Clients (ebenfalls Raspberry Pi’s oder eben ESP8266 NodeMCU’s) können über den Broker angesprochen werden. Der Broker sendet die Nachricht anschließend an alle verbundenen Geräte weiter.
Das Tolle daran ist also, dass wir uns nicht selbst um die Verbindung zu allen anderen Clients machen müssen. Wichtig zu wissen ist also auch, dass wenn man bspw. etwas vom Raspberry Pi an den ESP8266 senden will, dies nicht an die IP Adresse des ESP8266 sendet, sondern eben an die IP Adresse des Raspberry Pi’s (bzw. localhost), da darunter der Broker zu finden ist. Dieser leitet die Nachricht dann weiter.
Im Intervall ESP8266 MQTT Nachrichten an den Raspberry Pi senden
Wir beginnen mit dem Code des ESP8266. Die MQTT Subscription kann erst nachdem die Netzwerkverbindung steht, hergestellt werden. Öffne deinen ESPlorer und füge folgenden Code ein (neue Datei: „mqtt_connect.lua“):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
local SSID = "xxxxxxxxxxxxx" local SSID_PASSWORD = "xxxxxxxxxxxxx" local SIGNAL_MODE = wifi.PHYMODE_N MQTT_CLIENT_ID = node.chipid() MQTT_CLIENT_USER = "openhabian" MQTT_CLIENT_PASSWORD = "openhabian" MQTT_CLIENT_KEEPALIVE_TIME = 120 MQTT_BROKER = "192.168.1.6" MQTT_BROKER_PORT = 1883 MQTT_TOPIC_IN = "/esp8266_station123/in" -- commands MQTT_TOPIC_OUT = "/esp8266_station123/out" -- send values MQTT_BROKER_SECURE = 0 m = nil function wait_for_wifi_conn ( callback ) tmr.alarm (1, 1000, 1, function ( ) if wifi.sta.getip ( ) == nil then print ("Waiting for Wifi connection") else tmr.stop (1) print("\n====================================") print ("ESP8266 mode is: " .. wifi.getmode ( )) print ("The module MAC address is: " .. wifi.ap.getmac ( )) print ("Config done, IP is " .. wifi.sta.getip ( )) print("====================================") callback() end end) end function mqtt_handler() m = mqtt.Client(MQTT_CLIENT_ID, MQTT_CLIENT_KEEPALIVE_TIME, MQTT_CLIENT_USER, MQTT_CLIENT_PASSWORD) -- on publish message receive event m:on("message", function(client, topic, data) print("Received:" .. topic .. ":" ) if data ~= nil then --print(data) if data == "req" then sendValue() end end end) m:on("offline", function(m) print ("\n\nDisconnected from broker") print("Heap: ", node.heap()) end) m:connect(MQTT_BROKER, MQTT_BROKER_PORT, MQTT_BROKER_SECURE, function(client) print("connected") client:subscribe(MQTT_TOPIC_IN, 0, function(client) print("subscribe success") end) end, function(client, reason) print("failed reason: " .. reason) end) -- send all 30 sec tmr.alarm (2, 30*1000, tmr.ALARM_AUTO, function ( ) sendValue() end) end function sendValue() -- do stuff local temperature = 20 + math.random()*20 -- publish to broker on topic m:publish(MQTT_TOPIC_OUT, temperature, 0, 0, function(client) print("sent value="..temperature) end) end -- Configure the ESP as a station (client) wifi.setmode(wifi.STATION) wifi.setphymode(SIGNAL_MODE) wifi.sta.config {ssid=SSID, pwd=SSID_PASSWORD} wifi.sta.autoconnect(1) -- Hang out until we get a wifi connection before the httpd server is started. wait_for_wifi_conn( mqtt_handler ) |
Passe deinen Code entsprechend (SSID, IP des Brokers, Passwörter, etc.) an. Nutzt du mehrere ESP8266, so sollte jeder ein eigenes Topic bekommen (hier: „esp8266_station123“). Erstelle ggf. noch eine „init.lua“ mit dem Inhalt:
1 |
dofile("mqtt_connect.lua"); |
Wir lesen hier keine wirklichen Werte aus (dies kann aber ganz einfach gemacht werden). Alle 30 Sekunden wird ein Wert an den MQTT Broker gesendet. Außerdem reagieren wir auf Kommandos im „in“-Topic. Hier könnten wir z.B. verschiedene Befehle (außer „req“) definieren und unterschiedliche Werte (Temperatur, Luftfeuchte, etc.) an verschiedene Topics senden. Diese Funktion wird nur zur manuellen Anfrage gebraucht (nächstes Kapitel).
Weiter geht es mit dem Raspberry Pi. Wir gehen den Fall für OpenHAB durch, jedoch könnte auch einfach der Mosquitto Broker genutzt werden (Zum Senden / Empfangen ist ein Blick ins andere Tutorial hilfreich).
Zunächst einmal müssen wir die Broker Einstellungen setzen. Da wir das OpenHAB MQTT Package nutzen, müssen wir diese Konfigurationsdatei bearbeiten:
sudo nano /etc/openhab2/services/mqtt.cfg
An das Ende der Datei kommen diese Zeilen (ggf. anpassen):
broker.url=tcp://localhost:1883 broker.user=openhabian broker.pwd=openhabian
Diese Daten (User und Passwort) müssen wir auch auf dem ESP8266 angeben. Falls du es ohne OpenHAB und bspw. Mosquitto lösen willst, so nimm die gesetzten Raspbian Logindaten (Standard Username: „pi“, Passwort: „raspberry“).
Nun erstellen wir ein Item, das die Abfrage an den ESP8266 sendet:
sudo nano /etc/openhab2/items/esp8266.items
Number ESP_Temperature "ESP8266 Temperatur [%.1f°]" { mqtt="<[broker:/esp8266_station123/out:state:REGEX((.*?))]"}
Nach dem Speichern (STRG+O, STRG+X) erstellen wir noch eine Sitemap, worin wir die Daten anzeigen lassen (oder inkludieren es in eine bestehende Sitemap):
sudo nano /etc/openhab2/sitemaps/esp8266.sitemap
1 2 3 4 |
sitemap esp8266 label="ESP8266 MQTT" { Frame label="ESP8266 MQTT Abfragen" { Text item=ESP_Temperature |
Rufe nach dem Speichern die Seite auf (http://openhabianpi:8080/basicui/app?sitemap=esp8266) und sieh wie sich der Wert jede Minute verändert.
Das ganze kann natürlich auch mit Deepsleep kombiniert werden, um Strom / Batterieleistung zu sparen.
ESP8266 MQTT Antwort auf Anfrage des Raspberry Pi
Die andere Möglichkeit (neben dem automatischen Senden im Intervall vom ESP8266), ist die Abfrage. Dazu senden wir vom Raspberry Pi ein Signal über MQTT an den ESP8266 NodeMCU. Dieser analysiert das Signal und publishst ggf. in einem anderen Topic seinen Wert. Den nötigen ESP8266 Code haben wir bereits inkludiert (on:message).
Um ein MQTT Signal vom Raspberry Pi absenden zu können, sollten wir Mosquitto installiert haben. Das Topic, welches wir wählen ist im ESP Code definiert unter „MQTT_TOPIC_OUT“:
mosquitto_pub -d -t /esp8266_station123/in -m "req"
Anschließend wirst du sehen, wie sich der Wert in der OpenHAB BasicUI (Sitemap) aktualisiert. Wir können den Befehl auch über Rules einbinden, in dem er bspw. in einem bestimmten Intervall vom Raspberry Pi angefragt wird (und nicht vom ESP8266 gesendet wird). Das hat den Vorteil, dass wir die Daten nur dann abfragen, wenn wir sie auch wirklich brauchen.
Bei einem solchen Szenario ist aber zu beachten, dass dabei Deep Sleep nicht zu verwenden ist. Die Entscheidung ist dir überlassen.
19 Kommentare
====================================
ESP8266 mode is: 1
The module MAC address is: a2:20:a6:14:8a:43
Config done, IP is 192.168.0.121
====================================
failed reason: -5
Es wird kein Wert auf der Sitemap angezeigt. Hier feheln übrigens die zwei schließende Klammern.
Was könnte die Ursache sein?
das Problem liegt ermaß auf dem Raspberry. Ich bekomme den MQTT nicht zum laufen.
—–
10:25:22.861 [INFO ] [rt.mqtt.internal.MqttBrokerConnection] – Starting MQTT broker connection ‚broker‘
10:25:22.900 [ERROR] [openhab.io.transport.mqtt.MqttService] – Error starting broker connection
org.eclipse.paho.client.mqttv3.MqttException: Unable to connect to server
at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:79) [215:org.openhab.io.transport.mqtt:1.11.0]
at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:650) [215:org.openhab.io.transport.mqtt:1.11.0]
at java.lang.Thread.run(Thread.java:748) [?:?]
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method) ~[?:?]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[?:?]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[?:?]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[?:?]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[?:?]
at java.net.Socket.connect(Socket.java:589) ~[?:?]
at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:70) ~[?:?]
—–
Hat jemand eine Idee woran des liegt?
Das Configfile mqtt.cfg habe ich, wie beschrieben, gefüllt.
https://tutorials-raspberrypi.de/datenaustausch-raspberry-pi-mqtt-broker-client/
Mosquitto installieren und das log wird besser. dann kann das Binding starten.
Leider erhalte ich immer noch keine Werte vom ESP8266.
Jetzt funktioniert die ganze Geschichte.
geholfen, hat wie so oft, ein Neustart aller Teilnehmer.
Was auch noch hilfreich ist, in in der Konsole dem Channel von Hand mitzuhören mit:
mosquitto_sub -h localhost -v -t /esp8266_station123/out
bzw. selbst einen Wert abzusetzen um zu sehen ob das Binding richtig funktioniert mit:
mosquitto_pub -h localhost -t /esp8266_station123/out -m 5000
Hatte das gleiche Problem.
Du hast im Lua Skript die falsche MQTT_BROKER IP Adresse angegeben (nimm die von deinem PI)
I think I did everything as described, but something does not work.
I describe the situation:
In the LuaLoader monitor I see the temperature data update every 30 sec.
in a Putty window on the Raspberry, if I type:
mosquitto_sub -h localhost -v -t / esp8266_station123 / out
I see the temperature data update every 30 sec.
if in another putty window, I type:
mosquitto_pub -d -t / esp8266_station123 / in -m „req“
I see the request arrive at ESP8266, which immediately responds with the data I see both in the LuaLoader monitor and in the Putty window with waiting mosquitto.
The thing that I do not get instead is that at:
http: // openhabianpi: 8080 / basicui / app? sitemap = esp8266
I see the layout but the temperature is not present.
Please do you have any idea how to solve?
Thank you
Did you find the problem, i also have the same problem now.
The Borker seems to work (can see the data using MQTT.fx) but the temperature is not shown in the sitemap.
Only Esp8266 Temperature -°
Beim Aufruf der Seite
http://openhabianpi:8080/basicui/app?sitemap=esp8266
wird bei mir nur gemeldet: Willkommen, verfügbare Sitemaps Sie haben noch keine Sitemaps definiert.
Die esp8266.sitemap enthält aber defintiv den Inhalt entsprechend der Codebox oben
sitemap esp8266 label=“ESP8266 MQTT“ {
Frame label=“ESP8266 MQTT Abfragen“ {
Text item=ESP_Temperature
Woran könnte das liegen?
Das selbe Problem habe ich auch.
Wäre nette wenn der Autor bitte antworten würde.
Bei mir klappt es mit diesen Code. Diesen unter
sitemap our_home label=“Our Home“ {
Frame label=“ESP8266 MQTT Abfragen“ {
Text item=ESP_Temperature
}
}
diesen Code speicherst du unter
/etc/openhab2/sitemaps/esp8266.sitemap
Unter
http://openhabianpi:8080/basicui/app?sitemap=esp8266
kannst du dir dann die Sitemap angucken.
Leider klappt bei mir noch nicht die Verbindung Broker Openhab Anzeige auf der sitemap
Der ESP Sendet allerdings Signale an den Broker, da ich diese auch per Mqtt.fx sehen kann.
Ich merke gerade, dass Openhab ein neues MQTT Binding erhalten hat (für Version 2.4) hier ist das Einbinden von MQTT Subsribtions einfacher..scheinbar.. bei mir läufts immer noch nicht.
Servus,
ich habe auch keine Anzeige im Openhab2.
In der Console von openhab auf dem Raspi kommen aber die Temperaturen an.
Was kann ich tun ?
Hallo,
ich habe es tatsächlich geschafft Temperatur von einem DHT22 über ESP8266 an Openhab2 zu schicken. Jetzt komme ich nicht drauf wie ich die „mqtt_connect.lua“ aus dem Beispiel so verändere um 2 Werte an das mqtt zu senden. Ich würde gerne noch die Luftfeuchtigkeit an den Openhab2 senden.
Hoffe jemand kann mich da in die richtige Richtung schupsen.
Gruß,
Iwan
Hej zusammen und danke für das Tutorial!
Ich bekomme beim Start des ESP leider immer folgenden Fehler:
NodeMCU custom build by frightanic.com
branch: master
commit: 4905381c004bdeaf744a60bb940c1906c2e052d4
SSL: false
modules: dht,file,gpio,mqtt,net,node,tmr,uart,wifi
build created on 2019-05-04 10:28
powered by Lua 5.1.4 on SDK 2.2.1(6ab97e9)
lua: mqtt_connect.lua:19: attempt to call field ‚alarm‘ (a nil value)
stack traceback:
mqtt_connect.lua:19: in function ‚wait_for_wifi_conn‘
mqtt_connect.lua:85: in main chunk
[C]: in function ‚dofile‘
init.lua:1: in main chunk
[C]: ?
Die Wifi Verbindung stellt sich trotzdem erfolgreich her. Nach meiner Recherche scheint es in meiner Firmware kein tmr.alarm zu geben?! Das tmr Paket ist ja aber definitiv drauf.
Hat jemand eine Idee?
Siehe mein Kommentar unten:
„Wenn jemand das 2019 probiert: die Benutzung der timer ist veraltet
Erstellt einen timer bevor ihr ihn benutzt, erwa so:
t = tmr.create()
danach könnt ihr ihn so verwenden:
t:alarm (1000, 1, function ( )
statt delete benutzt ihr folgendes:
t:unregister()
„
Wenn jemand das 2019 probiert: die Benutzung der timer ist veraltet
Erstellt einen timer bevor ihr ihn benutzt, erwa so:
t = tmr.create()
danach könnt ihr ihn so verwenden:
t:alarm (1000, 1, function ( )
statt delete benutzt ihr folgendes:
t:unregister()
Ich denke da fehlt noch ein bisschen mehr vom Autor des Scriptes ausser den zwei schließenden klammern. Man muss egal welchen Broker man nimmt immer bei der Abfrage den Usernamen und Passwort mit angeben sonst reagiert der Broker überhaupt nicht auf eine Anfrage. Denn wenn einmal ein User und ein Password vergeben ist muss man dieses auch bei einer Abfrage angeben egal ob in der Console bei einer Abfrage der Daten bzw. Messwerte, oder in Openhab um dort die Daten auszugeben. In der Console kann ich alle Daten bei mir Abfragen in Openhab aber noch nicht darstellen. Da ist irgend wo noch ein Fehler bei mir im Script der Sitemap oder unter den Items. Das muss ich noch herausbekommen. Es gibt noch andere Seiten im Netz wo die vorgehensweise mit einen Broker beschrieben ist. Einfach mal googeln unter Mqtt Datenausgeben mit ESP8266
Bei mir funktioniert folgender Sketch:
#include
#include
#include
#include
#include
#define DHTTYPE DHT22
#define DHTPIN 5
DHT dht(DHTPIN, DHTTYPE, 22);
float temperature, humidity;
// Update these with values suitable for your network.
const char* ssid = „xxxxxxxxxxxx“;
const char* password = „yyyyyyyyyyyyyyyy“;
const char* mqtt_server = „zzzzzzzzzzzzzzzzz“;
const char* mqtt_user = „XXXXXXX“; // wenn vorhanden
const char* mqtt_password = „YYYYYYYY“; //wenn vorhanden
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup_wifi() {
delay(100);
// We start by connecting to a WiFi network
// Serial.print(„Connecting to „);
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(„.“);
}
randomSeed(micros());
Serial.println(„“);
Serial.println(„WiFi connected“);
Serial.println(„IP address: „);
Serial.println(WiFi.localIP());
}
void reconnect() {
// Loop until we’re reconnected
while (!client.connected())
{
// Serial.print(„Attempting MQTT connection…“);
// Create a random client ID
String clientId = „ESP8266Client-„;
clientId += String(random(0xffff), HEX);
// Attempt to connect
//if you MQTT broker has clientID,username and password
//please change following line to if (client.connect(clientId,userName,passWord))
//if (client.connect(clientId.c_str()))
//{
if (client.connect(„ESP8266Client“, mqtt_user, mqtt_password))
{
Serial.println(„connected“);
//once connected to MQTT broker, subscribe command if any
client.subscribe(„OsoyooCommand“);
} else {
// Serial.print(„failed, rc=“);
Serial.print(client.state());
Serial.println(“ try again in 5 seconds“);
// Wait 6 seconds before retrying
delay(6000);
}
}
} //end reconnect()
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // LED als Output definieren
digitalWrite(LED_BUILTIN, HIGH); // Ausschalten
Serial.begin(115200);
Serial.setTimeout(2000);
// Wait for serial to initialize.
while(!Serial) { }
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
dht.begin();
humidity = dht.readHumidity();
temperature = dht.readTemperature();
if (!client.connected()) {
reconnect();
}
}
void loop() {
dht.begin();
humidity = dht.readHumidity();
temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature)) {
return;
}
if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
// read DHT11 sensor every 6 seconds
if (now – lastMsg > 10000) {
lastMsg = now;
String msg = (String)humidity;
char messagehumidity[58];
msg.toCharArray(messagehumidity, 58);
Serial.println(messagehumidity);
//publish sensor data to MQTT broker
client.publish(„Feuchtigkeit“, messagehumidity);
String msg2 = (String)temperature;
char messagetemperature[58];
msg2.toCharArray(messagetemperature, 58);
Serial.println(messagetemperature);
//publish sensor data to MQTT broker
client.publish(„Temperatur“, messagetemperature);
}
}
Hallo Felix
Besten Dank für das Tutorial, ich finde es gut geschrieben und einfach nachzuvollziehen. Leider scheitere ich an dieser Zeile:
sudo nano /etc/openhab2/services/mqtt.cfg
Diese Datei existiert bei mir nicht obwohl das MQTT Binding erfolgreich installiert wurde. Da hänge ich leider jetzt fest…ich wäre sehr froh um eine Antwort!
Vielen Dank!