Forum: Mikrocontroller und Digitale Elektronik ESP32 gleichzeitig MQTT und Webserver


von R. K. (rkr)


Lesenswert?

Hallo zusammen,

ich habe mal eine Frage zum gleichzeitigen Einsatz eines ESP32 als 
Webserver und als MQTT-Client. Ich möchte über MQTT Daten empfangen und 
diese über den Webserver als HTML darstellen.

Bisher benutze ich folgende Struktur (ich habe nur die relevanten Teile 
eingefügt):
1
#include <WiFi.h> 
2
#include <PubSubClient.h> 
3
4
WiFiClient espClient; 
5
PubSubClient client(espClient); 
6
7
// Set web server port number to 80 
8
WiFiServer server(80); 
9
10
void setup(){ 
11
    client.setServer(mqtt_server, 1883); 
12
    client.setCallback(callback); 
13
14
    //Subscribe to topics 
15
    ... 
16
}
17
18
void loop(){ 
19
    client.loop)=; 
20
21
    WiFiClient client = server.available();   // Listen for incoming clients 
22
23
    if (client) { 
24
        while (client.connected()){ 
25
            //Print HTML 
26
            ... 
27
        } 
28
    } 
29
}

Wenn der ESP32 rebootet funktioniert er als MQTT Client. Die Nachrichten 
sind auf dem seriellen Monitor sichtbar. Sobald ich allerdings die HTML 
über einen Browser aufrufe, empfängt er keine MQTT-Nachrichten mehr. Ich 
gehe davon aus, dass der HTTP-Request des Browsers den Client 
reinitialisiert und daher die MQTT-Einstellungen weg sind. Wie im Code 
zu sehen, habe ich auch das HTTP-Client-Objekt schon umbenannt, damit es 
nicht beides mal "client" heißt, hat aber nicht geholfen. Hat jemand 
eventuell eine Idee, wie man das lösen könnte? Oder vielleicht einen 
Beispiel-Code? Wäre sehr dankbar.

Beste Grüße

: Bearbeitet durch User
von Dunno.. (Gast)


Lesenswert?

Sorry, aber so gekürzt ist dein Codeschnipsel nichtssagend.

von Stefan F. (Gast)


Lesenswert?

Vermutlich hast du in deiner while Schleife blockierende Funktionen. Ich 
wette, du kannst auch nicht mehrere Webseiten gleichzeitig abrufen (über 
mehrere Verbindungen).

Es ist wichtig, dass du keine Warteschleifen baust und nur dann Daten an 
den Client sendest, wenn der ESP genug Pufferspeicher frei hat. 
Ansonsten wartet er nämlich doch.

Eventuell hilft Dir der Artikel 
http://stefanfrings.de/esp8266/index.html#tcpsketch . Dieses Code 
Beispiel kann mehrere Verbindungen gleichzeitig bedienen. Da siehst du, 
wie man auf Input warten kann, ohne zu blockieren, also ohne klassische 
Warteschleife.
Beim Senden habe ich es einfach, weil die Antworten so klein sind dass 
sie immer in den Sendepuffer passen. Da musst du für deine Anwendung 
vielleicht etwas mehr Hirnschmalz rein stecken.

Vielleicht hilft dazu auch der Artikel 
http://stefanfrings.de/multithreading_arduino/index.html

von Sascha W. (sascha-w)


Lesenswert?

@r.k.

wie hast du dir das vorgestellt, per HTML holt der Client Daten vom 
Server ab die zu diesem Zeitpunkt schon zur Verfügung stehen müssen. Er 
darf/kann nicht warten bis über MQTT wieder mal was kommt. Du musst die 
MQTT-Daten zwischenspeichern (wie lang?) und dann ausliefern wenn eine 
Anfrage kommt (Puffer dann leeren), der Client muss dann regelmäßig die 
Seite abrufen um Änderungen mitzubekommen. Geht aber nur mit genau einem 
Client. Das beste währe allerdings die Verwendung einer 
Websocket-Verbindung da kannst du die eingehenden Nachrichten zum 
Webclient live durchreichen.
Für den Webserver gibts auch eine Lib für AsyncHTMLServer oder 
AsyncWebServer (weiß grad nicht den genauen Namen) die wie der MQTT 
nicht blockierend arbeitet.

Sascha

von R. K. (rkr)


Lesenswert?

@Stefan
Danke für den Tipp! Tatsächlich war in der loop ein delay(1000) 
eingebaut. Nachdem ich das entfernt habe funktioniert es. Wäre nicht 
darauf gekommen, dass es daran liegt...

@Sascha
Die Daten werden von ESP zwischengespeichert und sind schon vorbereitet, 
wenn der HTTP-Request kommt. Da über MQTT nur etwa jede Stunde eine neue 
Nachricht kommt, ist es auch ok, wenn die Website die Daten nicht 
automatisch aktualisiert. Ich werde aber trotzdem mal auch eine Variante 
mit Websocket versuchen. Danke!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.