Hallo zusammen,
ich lese mich schon seit längeren in die Thematik Datenaustausch von ESP32 zu ESP32 ein und suche nach einer stabilen Lösung.
Was habe ich / will ich:
- 1 x ESP32 (Genannt: Master => Ist Hauptmodul, soll die Daten bekommen oder sich holen)
- 1 x ESP32 (Genannt: Client => mit einem BME280, welche die Daten (Temp, etc.)für den Master bereitstellen)
- Eigenes WLAN; extra für diese 2 ESP32 (Nicht über eine AP im ESP32, sondern WLAN) mit eigenem Netzwerk (10.10.1.0/30)
Nun suche ich nach einer Lösung, wie ich die Daten an den Master senden kann; lieber wäre mir, ich hole mir die Daten im Master vom Client.
Erst habe ich es über ESP-Now versucht; jedoch bin ich damit nicht zufrieden(Reichweite).
Nun habe weitere Möglichkeiten gelesen:
- Web- Server und WEB- Client
oder mein Gedanke:
- Ich lege die Daten mit SPIFFS auf den Client ab und der Master holt sich die Daten. Hier stellt sich dann aber die Frage, wie der Master die Daten vom Client lesen kann.
Könntet Ihr mir hier eure Erfahrung mitteilen, bzw. Eure Empfehlung.
Finde einfach keinen sauberen und sicheren Weg und wollte mal nachfragen, wie Ihr das am besten angehen würdet.
Gruß
Falke07
Für einfache Datenübermittlung von ESP zu ESP über das WLan verwende ich UDP.
Ok, könntest Du mir da bitte mal einen Link für einen Beispiel senden? Wäre super. Eiere gerade nur rum und steht voll auf dem Schlauch ;-(
Bei fips findest du Beispiele zu UDP.
Client und Master sind keine Partner, sondern eher dasselbe. Mindestens, wenn es darum geht, wer die Kommunikation bestimmt.
Wenn es nur zwei Partner sind, ist das allerdings relativ egal, und vor allem auch, welche Namen man den beiden Rollen gibt. Zu einem Master gehören ein oder mehrere Slaves, die tun was der Master will, aber heutzutage nicht mehr Slave genannt werden w/s-ollen.
Hä,
und was willst Du mir jetzt damit sagen?
Soll ich das jetzt Hauptmodul (Datenverarbeitung der vom Liefermodul bereitgestellten Daten) und Liefermodul (liefert die Daten ans Hauptmodul) benennen? Und was wenn es 2 "Liefermodule" für ein "Hauptmodul" gibt?
Versteh ich jetzt nicht so richtig.
du musst dich zunächst auf einen Weg festlegen.
soll dieses Hauptmodul die Daten aktiv abholen oder soll es passiv die Daten erhalten.
Also welches deiner Module wird die Kommunikation initieren.
Wenn das feststeht, kann man dir weitere Optionen vorschlagen.
Gehen tut alles - aber du musst dir erst mal klar werden wer die Übertragung initieren soll.
Auch kannst du beschreiben ob auf einem deiner Module bereits ein Server (Ein Webserver?) läuft oder geplant ist. Wenn ja auf welchem?
Am liebsten wäre es mir, das ESP32- Hauptmodul holt die Daten aktive vom ESP32- Client (2 Stück mit je einem BME280)
Da bin ich völlig offen für alles. Momentan läuft noch kein Web- Server auf dem ESP32- Hauptmodul.
Es besteht eine WiFi- Verbindung bei allen 3 ESP32. Die WiFi- Anbindung kommt aber nicht von einem ESP32- AP sondern es besteht ein eigenes WLAN für diese 3 ESP32, in welches diese integriert sind.
Dann ist dein Hauptmodul ein CLIENT und deine zwei Messstellen je ein SERVER.
Eine Variante wäre nun am Hauptmodul einen TCP CLIENT zu implementieren und auf den zwei Messstellen einen TCP SERVER
Das Hauptmodul initiert dann die Übetragung mittels TCP und holt sich die Daten ab.
wenn jetzt die Begrifflichkeiten klar sind, solltest du eigentlich Beispiele finden und auch wissen was wohin gehört.
Probier mal.
PS: in den ESP Wifi Beispielen könnte da was zu finden sein - leider nur eine Ausgangsbasis ...
Wie viele Werte willst du abholen? Temperatur, Druck und Luftfeuchte?
Hallo,
wenn Deine beiden Messstellen mit BME280 eventuell mal mit deep Sleep laufen sollen, weil Akubetrieb , dann solltst Du das noch mal überdenken. In dem Fall wäre es gescheiter den HauptESP zum Server zu machen und die beiden Messstellen senden z.B mittels TCP dann wenn sie wach geworden sind, z.B alle 15 oder 30 Minuten.
Was da extrem nützlich wäre:
Zwei Demo-Sketche TCP-Server und TCP-Client die per TCP ein struct übertragen (wenn das denn ohne Klimmzüge geht)
Oder wenn struct schwierig wäre dann Zeichenketten nach dem Muster
"identifier=Wert_Einheit"
Das ist sehr universell und einfach zu verstehen und an Millionen verschiedene Anwendungsfälle anpassbar.
client-Anfrage "Temp1"
Serverantwort "Temp1=20.5_°C"
client-Anfrage "relFeuchte2"
Serverantwort "relFeuchte2=53_%"
client-Anfrage "PumpenLaufZeit"
Serverantwort "PumpenLaufZeit=3_h"
client-Anfrage "EinschaltZeit"
Serverantwort "EinschaltZeit=7:49_"
usw. usw.
Also ein Grundgerüst in dem Identifier definiert werden.
eine function die den Identifier, den Wert und die Einheit extrahiert
und dann Beispiele wie man Werte in integer, float usw. umwandelt.
Das ergäbe ein Grundgerüst dass die Grundfunktionalität einer Datenübertragung per TCP zur Verfügung stellt.
Ich würde die Einheit weg lassen und evtl. pro Anfrage alle Werte senden.
Oder nur die Werte in fester Reihenfolge mit ; getrennt oder mit etwas Overhead als JSON.
Da es sich hier auf beiden Seiten um den gleichen MC handelt, käme auch eine binäre Übertragung als struct in Frage.
Es gibt viele mögliche Wege, der vom Menschen lesbare Weg ist manchmal verständlicher, aber meist der umständlichste Weg.
Gruß Tommy
ich habe vor ein Beispiel mit JSON zu basteln. Weil ein einfaches "identifier=Wert" ist auch nicht gerade "einfach" zu parsen. Also kann man es gleich mit der JSON lib machen.
Da bin ich ja mal gespannt wo da die Schwierigkeiten liegen wenn es eine function gibt der man den Identifier als array-of-char übergibt und die den Wert als Ergebnis zurück gibt.
also etwas in der Art
int myLuftFeuchte = extractInt(myTCP_Message,"relFeuchte1");
float myKellerTemp = extractFloat(myTCP_Message,"KellerTemp");
oder statt hardcodierter Strings array-of-char die den Identifier enthalten.
Wenn das mit JSON noch einfacher geht um so besser.
Für die leichte Nachvollziehbarkeit und leichte Anpassbarkeit wird entscheidend sein
ob da alles in kryptische Variablen verpackt wird
oder
ob die Identifier nur an einer Stelle definiert werden und dann im folgenden selbsterklärende Variablennamen verwendet werden.
Ich bin gespannt .....
Ja sicher. Das musst du mir jetzt mal im Detail erklären warum der verständlichere Weg der umständlichere ist.
Ich rede hier nicht von Hochgeschwindigkeitsdatenübertragung wo es auf jedes Quäntchen Effizienz und Zeitersparnis ankommt. Sondern von maximal im Sekundentakt 20 bis 500 Bytes übertragen. Und da wir schon bei ESP32 sind kommt es auch nicht mehr darauf an jedes mögliche Byte einzusparen.
Der Code soll leicht zu verstehen und leicht anzupassen sein. Wenn dann die Datenverarbeitung eine Zehntelsekunde länger dauert aber nach zwei bis vier Stunden Programmierarbeit läuft dann ist das meiner Meinung nach für ganz viele Anwendungen viel mehr Wert als hunderte Stunden programmieren zu lernen um dann die effizientest mögliche Art der Datenübertragung programmieren zu können.
Arduino ist mal genau dafür angetreten:
Mach es einfacher für Laien Microntroller zu nutzen.
Da das alles ganz freiwillig ist, ist diese Eigenschaft schon lange nicht mehr in allen Libraries und Dokumentationen so drin.
Du könntest eine Funktion schreiben.
Wenn sie mir gefällt und einfach genug ist, nehm ich sie.
das einzeln zu machen ist doch zu kompliziert
die send Funktion meines Messensor als Client sieht so aus. Bei Bedarf sendet er einfach drauf los. Er wartet auch nicht auf eine Antwort. TCP beinhaltete ja bereits ein Protokoll, da geht nichts verloren. Der Server ordnet das dann zu.
// -------------- send TCP -------------------------
void sendTCP() {
Serial.printf("connecting to %s %d \n", host, hostPort);
WiFiClient client;
if (!client.connect(host, hostPort)) {
Serial.println("connection failed");
return;
}
Serial.println("sending data to server");
Serial.printf("%4d;%4.2f;%4.2f;%4.2f;%4.2f\n", devAdress, temp, hum, pres, Vcc);
client.printf("%4d;%4.2f;%4.2f;%4.2f;%4.2f", devAdress, temp, hum, pres, Vcc);
Serial.println("closing connection");
delay(100); // vermutlich nicht nötig
client.stop(); // Verbindung beenden
}
Der server , Empfänger ließt alle empfangenen Zeichen in einen C- string ein und zerlegt die dann.
DevArress ist die laufende Nummer des Sensors, man könnte auch die IP Adresse der aktiven Verbindung des Client am Server auswerten. Die müsste dann aber immer gleich bleiben, Das mit einer Nummer als Kennung gefällt mir da besser.
// ----------------Daten umladen----------------
void CStringToWert(char *instr) {
// füllt daten aus einem C-String in Daten
int devAdress = atoi(strtok(instr, ";"));
if (devAdress == 1) {
temp = atof(strtok(NULL, ";"));
hum = atof(strtok(NULL, ";"));
pres = atof(strtok(NULL, ";"));
VCC = atof(strtok(NULL, ";"));
}
}
2-stufig mit strtok_r: außen nach ; und innen nach = halte ich nicht für kompliziert und man braucht nicht eine größere Lib.
Gruß Tommy
Der vom Menschen lesbare Weg muss die Werte als Zeichenkette enthalten, damit sie von diesem gelesen werden können. Des Weiteren müssen die Werte mit einem Trennzeichen voneinander zu trennen.
Du musst zum Senden also die Werte zu einer Zeichenkette zusammen setzen und beim Empfangen wieder trennen und in Zahlen umwandeln.
Wenn Du (wie hier) auf beiden Seiten den gleichen MC hast, definierst Du Dir in einer Headerdatei ein struct, dass Deine Werte beinhaltet, bindest diese in Sender und Empfänger ein, sendest diese mit xxx.write((byte*)Adresse_struct, sizeof(struct)) und empfängst sie entsprechend mit read. Fertig.
Bei unterschiedlichen MC (aber mit gleicher Bit-/Bytefolge) kann man sich mit #pragma pack helfen.
Gruß Tommy
läuft so weit, muss aber noch ein wenig zusammenräumen
teaser Client:
TCP request connected
{"runtime":1208,"temperature":25.9,"humidity":57.9,"pressure":1024.4}
Closing connection
Server data
runtime:1208
temperature:25.90
humidity:57.90
pressure:1024.40
teaser Server:
incomming TCP client has connected
just give me your data please
{"runtime":1208,"temperature":25.9,"humidity":57.9,"pressure":1024.4}
TCP client stopped
edit:
und hier die beiden Sketche zum Download:
https://werner.rothschopf.net/microcontroller/202403_esp_tcp_json_en.htm