SD-Datei zeilenweise auslesen und per JSON an Webserver

Hi zusammen,

ich hab aktuell das "Problem", dass ich eine Datei, die sich auf einer SD-Karte befindet, "stücklesweise", wie man im schwäbischen sagt auslesen und nach und nach als JSON -Array an einen Webserver schaufeln will.

Die Beispiel-Datei enthält hunderte Temperaturmessungen daher das stücklesweise auslesen da ansonsten der JSON-Array zu groß werden würde.

Hier mein aktueller Ansatz.
Ein Javascript (Ajax)-Aufruf übergibt eine Startposition (am Anfang 0) und eine Endposition (z.B. 20) an die Funktion "tagesauswertung". Dort wird dann die entsprechende Stelle der Datei gehüpft und dann bis zur Endposition die nächsten x-Messungen ausgelesen und per JSON an den Webserver übergeben.
Sobald dieser die Messungen erhalten hat, fordert er die nächsten x Messungen an, d.h. Startposition ist dann die 21 und Endposition z.B. die 41 usw.

Ich hab zwar schon eine funktionierende Funktion aber Problem dabei ist, dass jedesmal die gesamte Datei durchlaufen wird - das kann man bestimmt eleganter machen.
Daher die Frage:
Kann man (mit der "Standard-SD-Library") auch direkt sagen: Spring an Position 31 und les die nächsten 20 OHNE immer wieder bei 0 anzufangen?

Bestimmt geht das mit der SD-Fat Library besser aber in dem Fall wäre es mir extrem Recht, wenn ich die Standard-Library verwenden könnte.

struct data {
  uint16_t tag;
  uint16_t messung_nr;
  uint16_t temp;
};

void tagesauswertung (char* datum_select, int startpos, int endpos) {
    struct data Messung;
    DynamicJsonDocument auswertung_arr(4800);
    sprintf(filename_auswertung, "/e/%s.bin", datum_select);
    auswertungenFile = SD.open(filename_auswertung, FILE_READ);
    if (auswertungenFile) {
        int i = 0;
        int alive = 0;
        while (auswertungenFile.available()) {
            auswertungenFile.read((uint8_t *)&Messung, sizeof(Messung));
            if (i >= startpos && i <= endpos) {
                alive = 1;
                auswertung_arr[i - startpos]["tag"] = Messung.tag;
                auswertung_arr[i - startpos]["messung_nr"] = Messung.messung_nr;
                auswertung_arr[i - startpos]["temp"] = Messung.temp;
            }
            i++;
        }

        if (alive == 1) {
            String jsonString;
            serializeJson(auswertung_arr, jsonString);
            Serial.println(jsonString);
            server.send(200, "application/json", jsonString);
        } else {
            server.send(200, "text/plain", "Fertig");
        }
    } else {
        Serial.println("Datei konnte nicht geöffnet werden");
    }
}

Die Variable "alive" verwende ich, um meinem Javascript auf dem Webserver zu sagen, dass er jetzt aufhören kann, weil die Datei zu Ende ist. Kann man bestimmt auch besser machen.

Wäre sehr dankbar, wenn ihr mir beim optimieren dieser Funktion helfen könntet.

LG Daniel

Wie sind die Daten auf der SD organisiert?

a) zeilenweise mit unterschiedlicher Länge und Zeilenvorschub hinten dran
b) (danach sieht es aus) binär mit fester Länge der Datensätze

Wenn b), dann kannst Du mit seek positionieren.

Gruß Tommy

Hi Tommy,

korrekt b) :grinning:

Wäre voll nett, wenn du (ausnahmsweise) in meinem Code mal demonstrieren könntest, wie man das mit seek umsetzt? Bei dem Link von dir gibts leider kein Beispiel ;-(

Oder einfach so:

struct data {
  uint16_t tag;
  uint16_t messung_nr;
  uint16_t temp;
};

void tagesauswertung (char* datum_select, int startpos, int endpos) {
    struct data Messung;
    DynamicJsonDocument auswertung_arr(4800);
    sprintf(filename_auswertung, "/e/%s.bin", datum_select);
    auswertungenFile = SD.open(filename_auswertung, FILE_READ);
    if (auswertungenFile) {
        int i = 0;
        int alive = 0;
        while (auswertungenFile.available()) {
            auswertungenFile.seek(startpos); //ÄNDERUNG 1
            auswertungenFile.read((uint8_t *)&Messung, sizeof(Messung));
           
            if (i <= endpos) { //ÄNDERUNG 2
                alive = 1;
                auswertung_arr[i - startpos]["tag"] = Messung.tag;
                auswertung_arr[i - startpos]["messung_nr"] = Messung.messung_nr;
                auswertung_arr[i - startpos]["temp"] = Messung.temp;
            }
            i++;
        }

        if (alive == 1) {
            String jsonString;
            serializeJson(auswertung_arr, jsonString);
            Serial.println(jsonString);
            server.send(200, "application/json", jsonString);
        } else {
            server.send(200, "text/plain", "Fertig");
        }
    } else {
        Serial.println("Datei konnte nicht geöffnet werden");
    }
}

Bin grad noch im Büro in der Mittagspause und kanns ned ausprobieren :hot_face:

Über ein Beispiel würde ich mich freuen :wink:

LG Daniel

auswertungenFile = SD.open(filename_auswertung, FILE_READ);
if (auswertungenFile) {
  auswertungenFile.seek(sizeof(Messung) * startpos); // 0 = Anfang, Anzahl der Sätze die übersprungen werden
...

Ich würde eher mit der Anzahl der Sätze, als mit der Stoppos arbeiten.

Gruß Tommy

1 Like

Danke dir, probier ich.
Ist definitiv der bessere Ansatz :wink:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.