ESP8266 - Datenübermittlung aus FRAM und als Download über Webserver zur verfügung stellen

OP #7384048
Lesenswert?

Grüß euch!

Ich möchte gerne mit einen ESP8266-01S Sensor Daten aus einen FRAM Chip auslesen und über Webserver zum Download zur Verfügung stellen. Ich habe mich explizit für eine FRAM Variante entschieden und auf einen Schreiben/Lesen über SPIFFS verzichtet aufgrund der Häufigkeit der Schreibzyklen.

Daher war mein Zugang der, dass ich die Daten zur Laufzeit hin über aus dem FRAM Auslese und über die ESPAsyncWebServer events.send an den Webserver Client übetrage und anschließend die Daten mit JavaScript auslese und zu einer .csv File zusammenbaue.

Das ganze funktioniert nur leider nicht mit den Übertragen der Daten zwischen den Webserver und den ESP8266. Ca. 10 Messwerte werden erfolgreich übertragen - anschließend kommt immer die Meldung "Event Disconnected".

Die Funktion zum Übertragen der daten an den Client ist:

1
 
2
 void SensorJSONReadup(unsigned long intervall, bool _DownloadRequest){
3
  unsigned long currentMillis = millis();
4
  if((currentMillis - lastTime >= intervall) && !_DownloadRequest){
5
    events.send("ping",NULL,currentMillis);
6
    events.send(getSensorReadings().c_str(),"new_readings", currentMillis);
7
    lastTime = currentMillis;
8
  }
9
  //Read Sensor Data for Download by Webserver!
10
  if(_DownloadRequest){
11
    // Json Variable to hold sensor readings 4 Download
12
    JSONVar downloadData;
13
    //Serial.println(_DownloadRequest);
14
    //Serial.println("Enter READING Sensor Data from FRAM");
15
        if (!DataRecived) { //Confirm 
16
          PowerValues get_data = ConvertSensorDataFromFRam(_i_down);
17
          PowerValues_print(get_data);
18
        
19
          downloadData["cur"] = String(get_data.current);
20
          downloadData["pow"] = String(get_data.power);
21
          downloadData["loadvol"] = String(get_data.loadvoltage);
22
          downloadData["time"] = String(get_data.timestamp);
23
        
24
          String jsonStringforDownload = JSON.stringify(downloadData);
25
          events.send(jsonStringforDownload.c_str(),"download_Data_csv", millis());
26
          
27
          DataRecived = 1;
28
          
29
          _i_down=_i_down+16;         
30
        }
31
        if(_i_down >= j){
32
          Serial.println("Download Data DONE");
33
          DownloadTriggerd = 0;
34
          _i_down = 0;
35
        };
36
      };
37
    };

Anschließend warte ich bis über die Websocket bestätigt wird, dass Daten empfangen wurden:

1
  //Confirm Data Recived
2
  server.on("/download_Data_done", HTTP_GET, [](AsyncWebServerRequest *request){
3
    if(DataRecived){
4
      DataRecived = 0;
5
    }    
6
    request->send(200, "text/plain", "OK!");
7
  });

Im JavaScript code habe ich einen EventListener wie folgt angelegt der mir dann die Daten empfängt und in der Konsole plottet bzw. bestätigt:

1
source.addEventListener('download_Data_csv', function(e) {
2
  var xhr = new XMLHttpRequest();
3
  console.log("download_Data_csv, e.data");
4
  var myObj = JSON.parse(e.data);
5
  console.log(myObj);
6
  xhr.open("GET", "/download_Data_done", true);
7
  xhr.send();
8
}, false);

Ich glaube ja das mein Hauptproblem noch darin liegt wie ich den Datenempfang an den ESP8266 erfolgreich/nicht erfolgreich zurück "checke" um den Event erfolgreich/nicht erfolgreich zu schließen bevor der nächste Datensatz übermittelt wird?!?

Vielleicht hat ja jemand schon mal so was ähnliches realisiert...

mfg

Gast #7384054
Lesenswert?

Johannes R. schrieb:

Daher war mein Zugang der, dass ich die Daten zur Laufzeit hin über aus dem FRAM Auslese und über die ESPAsyncWebServer events.send an den Webserver Client übetrage und anschließend die Daten mit JavaScript auslese und zu einer .csv File zusammenbaue.

Bist du sicher, dass das Konzept so sinnvoll ist? Events und der ganze asynchrone Kram sind hier meiner Meinung nach gar nicht nötig. Hat dein ESP für diese komplexe Sache genug RAM (ich frage, weil genau das hier in den letzten Monaten mehrfach der Knackpunkt war)? Funktioniert dein Konzept mit mehreren zeitgleichen Anfragen?

Viel einfacher wäre doch ein ganz normales REST (HTTP GET Request). Der Browser fordert die Datei an, und bekommt sie dann in einem Rutsch als Response geliefert. Das ist so simpel, dafür muss man nicht mal einen vollwertigen HTTP Server verwenden.

Gast #7384073
Lesenswert?

Hier mal ein einfaches Beispiel wie man so einen REST Request in Javascript implementiert:

1
/* Load navigation HTML fragment into the destination div
2
   id = id of the destination div
3
   url = url of the navigation HTML fragment
4
*/
5
function navi_load(id,url) {
6
  try {
7
    var request = new XMLHttpRequest();
8
    request.open("GET", url, true);
9
    request.onreadystatechange = function () {
10
      if (request.readyState == 4) {
11

12
         // response received
13
         document.getElementById(id).innerHTML = request.responseText;
14

15
      }
16
    };
17
    request.send(null);
18
  }
19
  catch (e) {
20
    console.error(e, e.stack);
21
  }
22
}

In diesem Fall wird ein Stück HTML Text vom Server geladen und in einen <div id="..."></div> eingefügt. Auf die gleiche Weise kannst du auch JSON Dokumente laden. Die Verarbeitung des Inhaltes überlasse ich dir.

Um dein Problem weiter zu untersuchen empfehle die Benutzung von Wireshark. Damit kannst du die HTTP Kommunikation aufzeichnen und (hoffentlich) erkennen, an welchen Schritt es scheitert.

OP #7384206
Lesenswert?

Stefan F. schrieb:

Events und der ganze asynchrone Kram sind hier meiner Meinung nach gar nicht nötig. Hat dein ESP für diese komplexe Sache genug RAM (ich frage, weil genau das hier in den letzten Monaten mehrfach der Knackpunkt war)? Funktioniert dein Konzept mit mehreren zeitgleichen Anfragen?

Danke dir Stefan für die rasche Rückmeldung!

Die Asynchronen Events sind Basis des gesamten Projektes, daher war mein Ansatz dieser, mit den events.... Um den Thema mit den Ram gleich vorweg entgegen zu wirken und nicht die ganze wurscht auf einmal zu übermitteln (im Worst-Case sind es nämlich der gesamte RAM Inhalt mit den 32KB an Daten....) habe ich eben diesen Ansatz entsprechend gewählt das ganze zu stückeln und mal Zeile für Zeile zu übertragen. Wenn dies funktioniert kann ich das ganze ja erweitern und z.B. immer 100 oder 1000 Datensätze auf einmal übermitteln...

Wenn ich auf dein Beispiel eingehe, sehe ich halt das Problem dass mir der RAM wsl ausgehen wird oder wie siehst du das wenn ich hier ein Array mit 32KB statisch definiere und dann in einem Übertrage? Zudem der Halbe RAM bereits für OTA verwendet wird.... A Pro Pos OTA - spielt mir das gegen die Karten?

Wireshark installiere ich mal - eventuell kann ich hier Rückschluss ziehen woran die Übertragung scheitert.

mfg

Gast #7384221
Lesenswert?

Johannes R. schrieb:

Wenn ich auf dein Beispiel eingehe, sehe ich halt das Problem dass mir der RAM wsl ausgehen wird oder wie siehst du das wenn ich hier ein Array mit 32KB statisch definiere und dann in einem Übertrage?

Ich würde die Datei zeilenweise (oder in Blöcken von 1 kB) lesen und senden. Niemand sagt, dass die gesamte HTTP Response an einem Stück im RAM liegen muss.

A Pro Pos OTA - spielt mir das gegen die Karten?

Damit habe ich keine Erfahrung. Bei meinen Projekten war das immer entweder unnötig oder zu unsicher. Ich bin auch nicht von der Mögloichkeit begeistert, das BIOS meines PC "einfach so" updaten zu können, ohne dafür wenigstens einen Jumper umstecken zu müssen.

Wireshark installiere ich mal - eventuell kann ich hier Rückschluss ziehen woran die Übertragung scheitert.

Mache das. Ich habe einen Webserver für PC in C++ und einen für AVR Mikrocontroller in C implementiert. Bei beiden war mit Wireshark sehr nützlich. Viele Fehler markiert es sogar farblich.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren