ESP32 Webserver mitJSON Datenaustausch

Gast #7329690
Lesenswert?

Hallo,

ich möchte ohne die bekannten Apps wie Home Automation etc. meinen ESP32, der aktuell als WIFI AP aktiv ist eine einfache Webseite bereitstellen lassen für einen Client (Anzeigetafel), damit dieser die Messwerte abgreift und darstellt.

Leider bin ich kein Web Experte und frage mich, wie ich unten stehenden Struct in einen JSOn Container verpacken kann? D.h. wie erzeuge ich daraus eine Struktur, die das abbildet und die im Client wieder in Daten zerlegt wird.

Kann da mal jemand Starthilfe geben?

1
/* Globaler Datenstruct */
2
typedef struct
3
{
4
  double UBatt;    // Batterie in Volt
5
  double PWLast, PWSolar; // Watt von Last und Solar
6
  double IALast, IASolar; // Ströme von Last und Solar
7
  double ISolSensorCal;  // Kalibrationswerte der Stromwandler
8
  double ILastSensorCal;
9
  double PWhSolarTag, PWhLastTag; // Wattstunden summiert auf den Tag
10
  double PWhSolarStd, PWhLastStd; // Wattstunden summiert auf die Stunde
11
  uint16_t WhStdSolarWeek[8]; // Wh Historie pro Tag eine Woche lang
12
  uint16_t WhStdLastWeek[8];
13
  uint8_t WhWeekidx = 0; // Indexcounter
14
} attribute((packed))
Gast #7329717
Lesenswert?

So, wie meine schwachen Kenntnisse sind muss man erst ein JSON Objekt erzeugen und in diesem wird dann ein JSON Document erzeugt, was eine Struktur hat. Dieses Dokument kann man dann mit Daten füllen, z.b

myobjekt["Variable"][Nr] = 123;

Nur wie man das anstellt ... keine Ahnung.

Gast #7329769
Lesenswert?

So vielleicht? Ich hätte die Zeit allerdings gern noch als Untergruppe....

1
bool CreaJSONFromStruct(data_t* daten)
2
{
3
  static int satznr;
4
  DynamicJsonDocument doc(256);
5
  doc["Satz"] = satznr++;
6
  doc["UBatt"] = daten->UBatt;
7
  doc["PWLast"] = daten->PWLast;
8
  doc["PWSolar"] = daten->PWSolar;
9
  doc["IALast"] = daten->IALast;
10
  doc["IASolar"] = daten->IASolar;
11
  doc["Stunde"] = zeit.hour;
12
  doc["Minute"] = zeit.min;
13
  doc["Sekunde"] = zeit.sec;
14
}
Gast #7329784
Lesenswert?

Ok, das klappt in der Ausgabe mit serializeJsonPretty(doc, Serial) Eine flache Strktur, die es aber erstmal tun sollte. Wäre gut, wenn root einen Namen hätte aber keine Ahnung wie man den erzeugt. ESPO32 resett aber nach 4 Ausgaben leider.

Meldung Backtrace: 0xfffffffe:0x8008a1e8 |<-CORRUPTED

Leier erzeugt DynamicJSON Object auch eine Heap Verletzung und der ESP32 resettet. Dafür finde ich leider keine Lösung und im Netz steht auch nichts.

Niemand hier, der da schon was mit gemacht hat? Das Ganze muss dann ja vom Webserver in eine Webseite verpackt werden, die den Anforderungen an deren Aufbau entspricht, so dass der Client genau das zu sehen bekommt was da steht.

{ "Satz": 6, "UBatt": 0, "PWLast": 0, "PWSolar": 0, "IALast": 0, "IASolar": 0, "Stunde": 14, "Minute": 30, "Sekunde": 20 }

Code

1
bool CreateJSONFromStruct(data_t *daten)
2
{
3
  static int satznr;
4
  StaticJsonDocument<512> doc;
5
  doc["Satz"] = satznr++;
6
  doc["UBatt"] = daten->UBatt;
7
  doc["PWLast"] = daten->PWLast;
8
  doc["PWSolar"] = daten->PWSolar;
9
  doc["IALast"] = daten->IALast;
10
  doc["IASolar"] = daten->IASolar;
11
  doc["Stunde"] = Zeit.hour;
12
  doc["Minute"] = Zeit.min;
13
  doc["Sekunde"] = Zeit.sec;
14
  serializeJsonPretty(doc, Serial);
15

16
}
Gast #7329869
Lesenswert?

Wie auf der Startseite! direkt beschrieben, indem du einen Subindex benutzt.

1
bool CreateJSONFromStruct(data_t *daten)
2
{
3
  static int satznr;
4
  StaticJsonDocument<512> doc;
5
  doc["Satz"] = satznr++;
6
  doc["UBatt"] = daten->UBatt;
7
  doc["PWLast"] = daten->PWLast;
8
  doc["PWSolar"] = daten->PWSolar;
9
  doc["IALast"] = daten->IALast;
10
  doc["IASolar"] = daten->IASolar;
11
  doc["Zeit"]["Stunde"] = Zeit.hour;
12
  doc["Zeit"]["Minute"] = Zeit.min;
13
  doc["Zeit"]["Sekunde"] = Zeit.sec;
14
  serializeJsonPretty(doc, Serial);
15
}

Deine Programmabstürze kann ich mir nicht erklären. Das StaticJsonDocument<512> sollte eigentlich wieder aufräumen, wenn der Scope verlassen wird.

Angehängte Dateien:
Gast #7329870
Lesenswert?

Marcel schrieb:

Deine Programmabstürze kann ich mir nicht erklären. Das StaticJsonDocument<512> sollte eigentlich wieder aufräumen, wenn der Scope verlassen wird.

Der ESP32 stürzt gerne ab, wenn man bei Funktionen keinen return setzt, mit oder ohne Wert. Ich habe überall return reingeschrieben und es war weg. Stand irgendwo im Internet bei stackoveerflow, dass dem so ist. Ursache war eine ISR ohne return, also weit weg von diesem Thema. Die wurde jede Sekunde aufgerufen und erzeugte einen Überlauf. Es ist gibt ja Unterschiede zwischen RET und REFI bei einer CPU.

#7329880
Lesenswert?

Dann aber schleunigst die Warnungen im Compiler aktivieren, Funktionen die mit Rückgabewert definiert sind aber keinen liefern werden dann angemeckert. Einem Interrupt eine Funktion mit Rückgabewert unterzuschieben sollte einen Fehler liefern weil die Signatur nicht passt. Mit Typecast würde man das unterdrücken, aber man macht sich den Stack kaputt.

Gast #7329891
Lesenswert?

J. S. schrieb:

Einem Interrupt eine Funktion mit Rückgabewert unterzuschieben

Wer macht denn sowas ???? Leider erzeugen sehr viel Libarys der Arduino Welt etliche Warnungen, so dass man erschlagen wird von Meldungen die gar nicht zum Projekt gehören. Da reicht schon ein uint_8t mit char oder byte zu kreuzen.

Ach ja... sieht gut aus! Das muss ich dann nur noch in eine Webseite verpacken, die vom Browser akzeptiert wird bzw. vom anderen ESP32. Hoffe das geht ohne den Zertifkate Kram. Wird zusammen mit dem OTA Interface gemacht, wenn es soweit ist.

{ "Satz": 363, "UBatt": 0, "PWLast": 0, "PWSolar": 0, "IALast": 0, "IASolar": 0, "Zeit": { "hour": 16, "min": 15, "sec": 41, "month": 1, "day": 27, "year": 23, "dow": 5, "MinOfDay": 975 } }

#7329912
Lesenswert?

Thorsten M. schrieb:

Das muss ich dann nur noch in eine Webseite verpacken

Üblicherweise lässt man die Webseite das JSON mit den veränderlichen Daten separat nachladen und füllt diese Daten dann nachher in die Webseite bzw. den DOM ein. Das hat den Vorteil, dass man danach jeweils nur die Daten bei Bedarf oder periodisch nachladen muss und nicht immer die komplette Webseite.

Das kann man direkt mit JavaScript realisieren oder etwas komfortabler mit der Verwendung von JQuery. Es ist kein Hexenwerk, auch wenn es erst kompliziert klingt.

Gast #7330089
Lesenswert?

Johnny B. schrieb:

Das kann man direkt mit JavaScript realisieren oder etwas komfortabler mit der Verwendung von JQuery. Es ist kein Hexenwerk, auch wenn es erst kompliziert klingt.

Dumme Frage: Wenn sowieso nur ein ESP32 (Master, Client) über das Wlan der Fritzbox mit dem anderen ESP32 (Slave, Server) kommúniziert ... könnte man da nicht das ganze Browserzeugs weglassen? Ich brauche doch gar keinen Interpreter für HTML, CSS usw. Lässt sich mit wget nicht der ASCII JSON String direkt einlesen zum parsen mit der JSON Lib? Ich plane nicht das fern abrufbar zu machen, denn dann hätte ich wohl eine dieser fertigen Lösungen ioBroker und wie sie alle heissen genommen wo man in Skriptsprache die ESP als Datenpunkte einfügt.

Gast #7330100
Lesenswert?

Wobei, diesen Gedanken weiter gesponnnen, brauche ich auch kein JSON Es reicht alle Daten in einen String zu packen, Komma dazwischen und diesen String auf der Zielseite wieder zu zerlegen, so wie NMEA, CSV und viele andere Formate es auch machen.

Gast #7330216
Lesenswert?

Sascha W. schrieb:

Dann brauchst du auch keinen String, da kannst du deinen Stuct auch gleich als Bytefolge senden.

Und wie macht man das durch einen TCP/IP Socket? Denn den muss ich ja benutzen.

2 ESP32 hängen an der Fritzbox mit eigenen IP Adressen. Sie können sich sehen und aufeinander zugreifen. Leider ist das für mich alles Neuland, was mit dem Web und seinen Diensten zu tun hat.

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