Forum: Mikrocontroller und Digitale Elektronik ESP 8266 ESP-NOW Webserver


von Daniel K. (daniel_k620)


Angehängte Dateien:

Lesenswert?

Hallo,

ich arbeite zurzeit an einer kleinen Wetterstation mit dem ESP 8266 D1 
mini.

Ich habe momentan einen Sender (es werden dann aber mehr) und einen 
Empfänger.

Das Master/Slave-Prinzip funktioniert gut und die Messwerte der 
Temperatursensoren werden zum Schluss auf einem Webserver angezeigt, so 
weit so gut.

Mir ist nur aufgefallen, dass das, was als Letztes empfangen wurde, 
nicht gespeichert wird. Besser gesagt, dass mein Webserver mir keine 
Werte anzeigen kann, wenn ich die Seite neu aktualisieren tue oder wenn 
sie zum ersten Mal aufgerufen wird, da theoretisch der µController immer 
arbeitet, habe ich mir gedacht, dass die Werte da sein sollten.

Mein Sender liefert mir die Werte alle 2 Minuten und dann geht er 
schlafen.
Über den USB-Port kann ich sehen, dass alles empfangen wird und 
funktioniert.

Ich habe die Webseite nicht immer offen, aber ich möchte, wenn ich sie 
aufrufe, dass die letzten Messwerten, die empfangen wurden, mir 
angezeigt werden.

Da habe ich noch keine Lösung.

Ich werde mich sehr freuen, wenn jemand da mir weiter helfen könnte.

von Stefan F. (Gast)


Lesenswert?

Dann musst du dir halt ein strukturiertes Array auf dem Sammler anlegen, 
wo er die Daten ablegt. Die Webseite kann die Daten aus dem Array lesen, 
anstatt auf Signale von den Sensoren zu warten.

Ob und wie ESP-Now das kann, weiß ich allerdings nicht. Ich würde so 
etwas selbst programmieren, weil mir das eh Spaß macht.

von Mario M. (thelonging)


Lesenswert?

Daniel K. schrieb:
> Besser gesagt, dass mein Webserver mir keine
> Werte anzeigen kann, wenn ich die Seite neu aktualisieren tue oder wenn
> sie zum ersten Mal aufgerufen wird

Das wird einfach daran liegen, dass der Browser die Seite im Cache hält. 
Das muss man verhindern, z.B. mit "expires"-Headern.

https://ekiwi.de/index.php/56/caching-einer-html-seite-verhindern/

von Stefan F. (Gast)


Lesenswert?

Oha, da hat der Mario die Problembeschreibung ganz anders interpretiert, 
als ich. Vielleicht sollte man das klären, bevor wie weiter diskutieren, 
denn einer von uns beiden liegt mit Sicherheit völlig daneben.

Daniel, starte den Browser mal neu, lade dann die Webseite, und lade sie 
dann sofort erneut (durch Klick auf den Reload Button). Werden dann die 
letzten Messwerte aller Sensoren angezeigt, oder nicht?

von Daniel K. (daniel_k620)


Lesenswert?

Nein, sie werden nicht angezeigt. Sie bleiben nicht da

von Mario M. (thelonging)


Lesenswert?

Drücke mal im Browser Strg+F5. Das erzwingt das Neuladen der Seite.

von Daniel K. (daniel_k620)


Lesenswert?

naja, das ist das, was ich immer tue!! trotzdem gehen alle Werte 
verloren

von Mario M. (thelonging)


Lesenswert?

Dann liegt es wohl nicht am Caching und Du solltest mehr Details zu dem 
Projekt veröffentlichen.

von Daniel K. (daniel_k620)


Lesenswert?

Ich habe den Code als Text-Datei hochgeladen ^^

: Bearbeitet durch User
von Mario M. (thelonging)


Lesenswert?

Oh, voll übersehen. 🤓
Mach mal lastEventTime global und schreibe das "lastEventTime = 
millis();" in die setup().

: Bearbeitet durch User
von Daniel K. (daniel_k620)


Lesenswert?

das da in setup?

static unsigned long lastEventTime = millis();
  static const unsigned long EVENT_INTERVAL_MS = 5000;
  if ((millis() - lastEventTime) > EVENT_INTERVAL_MS) {
    events.send("ping",NULL,millis());
    lastEventTime = millis();
  }

von Mario M. (thelonging)


Lesenswert?

Ich weiß nicht was passiert, wenn man in loop() lastEventTime auf 
millis() setzt und danach die Differenz zu millis() abfragt. Kann die 
jemals die 5000 erreichen?

von Daniel K. (daniel_k620)


Lesenswert?

Ich denke nicht.

Ich könnte eine char-Variable nutzen, um die daten zu speichern, dennoch 
weiß ich noch nicht, ob das besser wäre.

von J. S. (jojos)


Lesenswert?

die Daten werden ja im Prinzip im Client gesammelt, und wenn der sich 
neu verbindet fängt der bei 0 an.
Also muss das Sammeln in den Server verlagert werden wie auch schon 
StefanUS schrieb. Die Sensoren haben ja eine einzigartige ID, die MAC. 
Die kann man als Key in einem key/value store nehmen (was das JSONVar 
schon macht). Also wenn neue MAC ankommt, dann neues Element mit MAC und 
Daten anlegen. Wenn die MAC schon vorhanden ist, dann Daten 
überschreiben.
In der Webseite dann beim Start aus den vorhandenen Datensätzen die 
Cards erzeugen.
Jetzt ist das Konzept nicht gut wie ich finde, wenn es einen weiteren 
Sensor gibt muss die Message für alle Sensoren erweitert werden. Als 
Message reicht ja id (eigntlich überflüssig durch die MAC), Temp, Hum, 
Voltage.

: Bearbeitet durch User
Beitrag #7113002 wurde von einem Moderator gelöscht.
von Daniel K. (daniel_k620)


Lesenswert?

Aber wenn das ganze im Abschnitt passiert:

JSONVar board;

AsyncWebServer server(80);
AsyncEventSource events("/events");

// callback function that will be executed when data is received
void OnDataRecv(uint8_t * mac_addr, uint8_t *incomingData, uint8_t len) 
{
  // Copies the sender mac address to a string
  char macStr[18];

  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], 
mac_addr[4], mac_addr[5]);
  Serial.println(macStr);
  memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));

  board["id"] = incomingReadings.id;
  board["temperature"] = incomingReadings.temp;
  board["humidity"] = incomingReadings.hum;
  board["temp1"] = incomingReadings.temp1;
  board["temp2"] = incomingReadings.temp2;
  board["temp3"] = incomingReadings.temp3;
  board["temp4"] = incomingReadings.temp4;
  board["voltage"] = incomingReadings.volt;
  board["readingId"] = String(incomingReadings.readingId);

  String jsonString = JSON.stringify(board);

  events.send(jsonString.c_str(), "new_readings", millis());

  Serial.printf("Board ID %u: %u bytes\n", incomingReadings.id, len);
  Serial.printf("t value: %4.2f \n", incomingReadings.temp);
  Serial.printf("h value: %4.2f \n", incomingReadings.hum);
  Serial.printf("temp1 value: %4.2f \n", incomingReadings.temp1);
  Serial.printf("temp2 value: %4.2f \n", incomingReadings.temp2);
  Serial.printf("temp3 value: %4.2f \n", incomingReadings.temp3);
  Serial.printf("temp4 value: %4.2f \n", incomingReadings.temp4);
  Serial.printf("v value: %4.2f \n", incomingReadings.volt);
  Serial.printf("readingID value: %d \n", incomingReadings.readingId);
  Serial.println();
}


Könnte man da eine char-Variable schreiben und diese statt jsonString 
in das Event "events.send" schicken?

von Stefan F. (Gast)


Lesenswert?

Daniel K. schrieb:
> Könnte man da eine char-Variable schreiben und diese statt jsonString
> in das Event "events.send" schicken?

Ja, aber das wäre noch keine Lösung.

Außerdem musst du nämlich nach dem laden der Webseite einen Aufruf von 
events.send() auslösen. Oder der Browser muss sich die Daten selbst über 
eine andere URL/Funktion (die noch nicht existiert) holen.

von J. S. (jojos)


Lesenswert?

um die Daten für einen Sensor zu speichern/übertragen kann man die 
JSONVar auch als Array von Strukturen gebrauchen:
1
    String id(iid);
2
3
    board[id]["id"] = iid;
4
    board[id]["temperature"] = temperatureX;
5
    board[id]["humidity"] = 66.2f;
6
    board[id]["voltage"] = 3.05f;
7
    board[id]["readingId"] = 11;
8
9
    String jsonString = JSON.stringify(board[id]); // send current dataset
10
    String jsonString = JSON.stringify(board);     // send all datasets
11
12
    events.send(jsonString.c_str(), "new_readings", millis());

beim Init der Seite würde man dann einmal 'board' Senden, beim update 
eines Sensors dann 'board[id]'.
Im html muss man dann in einer Schleife einfach alle elemente 
durchlaufen die ankommen, das wären am Anfang alle und sonst nur das was 
aktualisiert wird.
Dann kann man die Cards auch dynmisch erzeugen und neue Sensoren ohne 
Codeänderung auf Serverseite hinzufügen.

von Forist (Gast)


Lesenswert?

Daniel K. schrieb:
> Ich habe den Code als Text-Datei hochgeladen ^^

Warum nicht als C-Datei?
Dann würde die deutlich lesefreundlicher angezeigt.

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.