Kommunikation zwischen mehreren NodeMCUs - welche methode?

Hallo zusammen,
für mein Projekt (Gebäudeautomatisierung, momentan Jalousien und Bewäserung) möchte ich gerne ein NodeMCU welches als “Master” fungiert und seriell mit dem Display kommuniziert (habe da ein Nextion Display in Aussicht) und mehrere weitere NodeMCUs (momentan 2) die als “Außenstellen” fungieren, einsetzen.

Dazu habe ich auch eine kleine Skizze gezeichnet, ich hoffe sie ist halbwegs verständlich.

Im oberen Bereich sieht man das Display und den “Master”-MCU. Display und MCU sollen wie gesagt seriell miteinander reden. Aktuelle Zeit sowie Wetter holt sich der Node übers Internet (funktioniert auch schon soweit) weiters soll der Node mit meiner MySQL Datenbank kommunizieren (aktuell wird damit ein Terminkalender realisiert, funktioniert ebenfalls).
Die restlichen NodeMCUs sind über WLAN (bestehendes WLAN vom Router) eingebunden.

Hier mal ein kleines Beispiel der Parameter die übertragen werden sollen:

Von Master zu Display

  • MySQL Daten (Termine)
  • Wetter
  • aktuelle Zeit
  • Status der Außenstellen

Von Display zu Master

  • Verschiedene Variablen
  • Manuelle Steuerung

Von Master zu Außenstelle:

  • Wetter
  • Verschiedene Variablen
  • Manuelle Steuerung

Von Außenstelle zu Master:

  • Aktuelle Sensorwerte
  • Status der Aktoren
  • sonstige Status

Ich frage mich jetzt, wie ich die Kommunikation am besten umsetzen kann. Ich habe mich ein bisschen mit HTTP_GET beschäftigt, allerdings scheint mir diese Methode ein bisschen zu umständlich zu sein, wenn es um mehrere Daten geht.
Es wäre theoretisch auch Möglich, dass sich die Außenstellen die Wetterinformationen selbstständig holen, allerdings müsste ich dann mehr darauf achten, die API nicht zu fluten.

Sensorwerte, Status und Manuelle Steuerung sollten möglichst verzögerungsfrei übertragen werden. Parameterliste reicht alle paar Minuten bzw. bei Änderung sofort. Wetter reicht alle 10 Minuten.

Habe mir überlegt die Kommunikation mit Json umzusetzen, außer ihr habt einen besseren Vorschlag.
Wie würdet ihr sowas umsetzen?

IMG_20200501_0001.pdf (426 KB)

Wenn dir HTTP_GET zu kompliziert erscheint, befürchte ich, du baust da auf ein falsches Beispiel auf.
mit dem

ESP8266Webserver | HelloServer

ist es eigentlich sehr übersichtlich.

Grundsätzlich hättest du die Möglichkeit UDP oder TCP zu verwenden. HTTP ist ja dann "nur mehr eine Erweiterung" von TCP. Aber mit obigen Beispiel braucht man sich eigentlich nicht mehr um das darunter kümmern.

JSON ist ja dann nur mehr das Format mit dem die Daten ausgetauscht werden. Trotzdem brauchst du einen Transport-Layer - sei es via UDP oder TCP (oder eben HTTP on top).
Wenn du den obigen Webserver verwendest brauchst du aber nicht ein JSON zusammenbasteln. Wenn du deine Werte als Parameter übergibst, hast du sehr elegant einen Zugriff auf die einzelnen Werte und brauchst beim Empfänger auch kein JSON parsen.

Wenn du auf dem HTTP Weg bleiben willst, könntest du dir meine Seite über ESP webserver ansehen. Das Beispiel passt vieleicht nicht 100%ig - es erklärt aber, wie man Daten von einem ESP zu einem anderen mittels HTTP überträgt.

UDP Beispiele gabs die letzten Wochen hier im Forum auch ein paar. Einfach ein wenig suchen. Das kommt eh immer wieder, inkl. der herbeigeführten Diskussion ob UDP, TCP oder gar HTTP. In deinem Fall finde ich aber HTTP gar nicht so verkehrt: da kann man grundsätzlich mal jeden Node zunächst stand alone betrachten und sieht auch schon ein Ergebnis und am "Master" kommen halt nach und nach mehrere Daten hinzu. Ich finde das gut.

übrigens, karma+ für dein Übersichtsbild, da kann man sich ein gutes Bild machen was du vor hast.

Herzlichen Dank für die Info und auch fürs Karma :wink:
Werd ich mir demnächst mal genauer ansehen, danke :wink:

Off-topic: Funktionieren nur bei mir die email-benachrichtigungen bei Antworten nicht?

Deine Frage kann ich leider mangels Erfahrung (noch) nicht beantworten, aber ich hangle mich derzeit durch Esp8266 und Esp32 - Programmierung mit Arduino IDE. JSON ist wegen der Nähe zu JavaScript für die Aktualisierung von Webseiten ganz angenehm zu handhaben. Es läßt sich zwecks Überprüfung auch gut in Text wandeln. Das ist aber nicht Dein Thema. Außerdem bin ich über ESP-NOW gestolpert.

@Off-Topic
Zumindest über PMs werde ich nicht mehr informiert.
Über Antworten hatte ich vor langer Zeit schon deaktiviert - da ich eh immer Alles lese und die Flut an sinnlosen Mails die Sache nicht besser macht.

ESPAsyncWebServer heißt die Lib mit der ich mich schon etwas (wirklich nur etwas) beschäftigt habe.
Wenn ich jetzt, zum Beispiel, Wetterinformationen zur Übertragung bereit stellen möchte, wären das sehr viele server.on Einträge.

Hier die aktuelle Variablenliste für die Infos von OWM:

// Current
long current_dt; // 1586763444
long current_sunrise; // 1586751436
long current_sunset; // 1586800256
float current_temp; // 14.74
float current_feels_like; // 12.34
int current_pressure; // 1013
int current_humidity; // 62
float current_dew_point; // 7.54
int current_clouds; // 100
float current_uvi; // 4.62
int current_visibility; // 10000
float current_wind_speed; // 2.6
float current_wind_gust;
int current_wind_deg; // 270
float current_rain_1h; // 0.11
float current_snow_1h; // 0.11

int current_weather_id[maxWeatherEntries]; // 500
const char* current_weather_main[maxWeatherEntries]; // "Rain"
const char* current_weather_description[maxWeatherEntries]; // "Leichter Regen"
const char* current_weather_icon[maxWeatherEntries]; // "10d"
// Hourly
long hourly_dt[48]; // 1586761200
float hourly_temp[48]; // 14.74
float hourly_feels_like[48]; // 12.07
int hourly_pressure[48]; // 1013
int hourly_humidity[48]; // 62
float hourly_dew_point[48]; // 7.54
int hourly_clouds[48]; // 100
int hourly_visibility[48];
float hourly_wind_speed[48]; // 2.99
float hourly_wind_gust[48];
int hourly_wind_deg[48]; // 280
float hourly_rain_1h[48]; // 0.11
float hourly_snow_1h[48];

int hourly_weather_id[48][maxWeatherEntries]; // 500
const char* hourly_weather_main[48][maxWeatherEntries]; // "Rain"
const char* hourly_weather_description[48][maxWeatherEntries]; // "Leichter Regen"
const char* hourly_weather_icon[48][maxWeatherEntries]; // "10d"
// Daily
long daily_dt[8]; // 1586775600
long daily_sunrise[8]; // 1586751436
long daily_sunset[8]; // 1586800256

float daily_temp_day[8]; // 18.49
float daily_temp_min[8]; // 4.83
float daily_temp_max[8]; // 18.49
float daily_temp_night[8]; // 4.83
float daily_temp_eve[8]; // 10.11
float daily_temp_morn[8]; // 14.74

float daily_feels_like_day[8]; // 13.94
float daily_feels_like_night[8]; // 1.48
float daily_feels_like_eve[8]; // 7.09
float daily_feels_like_morn[8]; // 12.77

int daily_pressure[8]; // 1011
int daily_humidity[8]; // 50
float daily_dew_point[8]; // 7.88
float daily_wind_speed[8]; // 5.79
int daily_wind_deg[8]; // 275
float daily_wind_gust[8];
int daily_visibility[8];
int daily_clouds[8]; // 100
float daily_rain[8]; // 9.48
float daily_snow[8]; // 0.79
float daily_uvi[8]; // 4.62

int daily_weather_id[8][maxWeatherEntries]; // 600
const char* daily_weather_main[8][maxWeatherEntries]; // "Snow"
const char* daily_weather_description[8][maxWeatherEntries]; // "Mäßiger Schnee"
const char* daily_weather_icon[8][maxWeatherEntries]; // "13d"

Lässt sich das ganze in ein struct zusammenfassen und auf einmal übertragen?

Ich bin bei Kommunikation zwischen MC eher für UDP. Kleine Datenpakete, kein Overhead, aber auch keine Zugangskontrolle (das muss dann Dein Protokoll leisten - z.B. Antwort senden).

Gruß Tommy

firefist235:
...wären das sehr viele server.on Einträge.

Json

Bis zu 400 Werte, je nach Anzahl der eingestellten Schaltzeiten übertrage ich mit einmal.

Beispiel

Gruß Fips

Json möchte ich, wenn möglich nicht verwenden.

Spiele grade ein bisschen mit UDP rum. Bin aber noch ein wenig unschlüssig wie ich die Übergabe umsetzen soll.

Möglichkeit 1: Client schickt "GiveWeather" oÄ und Server schickt sämtliche Wetter Daten an den Client. Eine Variable pro Zeile.

Möglichkeit 2: Client schickt "Give_current_dt" und Server schickt nur current_dt an den Client.

Bei Möglichkeit 2 müsste es doch möglich sein, dass man die benötigte Variable anhand von "Give_current_dt" ermittelt indem Give_ weggeschnitten wird. Somit würde nur sehr wenig Code benötigt werden. Außer ich bin da völlig auf dem Holzweg.

Bei UDP nutzt man eher structs mit Binärdaten als Textzeilen, weil das den Vorteil von UDP (kleiner Overhead) wieder zunichte macht. Hier gibt es ein Beispiel dazu.

Gruß Tommy

firefist235:
Möglichkeit 2: Client schickt "Give_current_dt" und Server schickt nur current_dt an den Client.

Bei Möglichkeit 2 müsste es doch möglich sein, dass man die benötigte Variable anhand von "Give_current_dt" ermittelt indem Give_ weggeschnitten wird. Somit würde nur sehr wenig Code benötigt werden. Außer ich bin da völlig auf dem Holzweg.

das ist ein Holzweg. Der Controller kennt kein "Give_current_dt", daher kann er auch nicht vorne Give_wegschneiden. Das steht so nur bei dir in der IDE ... das hat sozusagen nichts mit dem zu tun, was der Controller sieht.

Außerdem worum gehts dir jetzt, eine schlanke Übertragen, ein schlanker Code? Bei den paar Daten (ja das sind nur ein paar), dann würde ich weder auf pseudo schlanke Übertragung noch auf pseudo schlanken Code achten sondern etwas was ich in 6 Monaten auch noch verstehe und 5 neue Felder mit einfachem Aufwand hinzufügen kann.

Und du bist da ja auch nicht in einem Protokoll wo du eine Payload Beschränkung hast. Falls doch gib bescheid, hier haben sicher einige etwas platzsparendes in ihren Wühlkiste - einfach ist das aber dann nicht mehr.

Imho solltest du Ordnung in die Daten bringen, welche Daten werden in welcher Aktualität benötigt werden.

die aktuelle Temperatur wird sich öfters ändern, als irgendwelche Stundenwerte oder 8 Messpunkte oder gar der morgendliche Sonnenaufgang, weil der ist für 24h so konstant wie der abendliche Sonnenuntergang.

Bei diesem kunterbunt an Daten mögest du mir ansonsten erklären warum es wirklich für dich relevant ist, ob die Übertragung 100, 50 oder 5ms dauert nur damit du dann weist, dass der heutige Sonnenuntergang um 20:15:32 ist.

Danke euch beiden für die Hilfe :wink:
Werde einfach jeder Variable einen eigenen "Befehl" zuteilen.
Also 0x20 zB ist Anforderung current_dt, 0x21 Anforderung current_sunrise usw.

Mal sehen :wink:

firefist235:
Json möchte ich, wenn möglich nicht verwenden.

Wenn es nicht Menschenlesbar sein muss dann schick halt ein struct, egal mit welcher Methode!

Also 0x20 zB ist Anforderung current_dt, 0x21 Anforderung current_sunrise usw.

Ein struct schicken ist einfacher zu handeln als die einzelnen Byte.

Danke euch beiden für die Hilfe

Oh, er hält mich für nicht Hilfreich!

Gruß Fips

... oder nur Dich?? :wink: (bin ja schon wieder lieb g )

Sorry fips, dich hab ich übersehen :wink:
Natürlich auch dir danke :wink: