Forum: Mikrocontroller und Digitale Elektronik ESP32 Webserver mitJSON Datenaustausch


von Thorsten M. (cortex_user)


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))

: Bearbeitet durch User
von Vincent H. (vinci)


Lesenswert?

Espressif hat ein GitHub Repo namens "json_generator"
https://github.com/espressif/json_generator

So wies aussieht gibts da für jeden fundamentalen Typen eine eigene 
Funktion.

von Thorsten M. (cortex_user)


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.

von Thorsten M. (cortex_user)


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
}

von Thorsten M. (cortex_user)


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
}

: Bearbeitet durch User
von J. S. (jojos)


Lesenswert?

https://arduinojson.org/
ist eine beliebte und umfangreiche Lib für JSON.

von Thorsten M. (cortex_user)


Lesenswert?

J. S. schrieb:
> ist eine beliebte und umfangreiche Lib für JSON.

Ja, nur das was ich möchte muss ich da erstmal finden. Was muss ich tun, 
um Zeit in eine eigene Unterstruktur zu verschieben?

: Bearbeitet durch User
von Johnny B. (johnnyb)


Lesenswert?

Für so eine fixe Struktur kann man auch einfach mit ein paar printf() 
das JSON erzeugen.

von Thorsten M. (cortex_user)


Lesenswert?

Johnny B. schrieb:
> Für so eine fixe Struktur kann man auch einfach mit ein paar printf()
> das JSON erzeugen.

Da lerne ich aber nichts bei.

von Marcel (Gast)


Angehängte Dateien:

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.

von Thorsten M. (cortex_user)


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.

: Bearbeitet durch User
von J. S. (jojos)


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.

von Thorsten M. (cortex_user)


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
  }
}

: Bearbeitet durch User
von Johnny B. (johnnyb)


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.

von Thorsten M. (cortex_user)


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.

: Bearbeitet durch User
von Thorsten M. (cortex_user)


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.

von Sascha W. (sascha-w)


Lesenswert?

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

Sascha

von Thorsten M. (cortex_user)


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.

: Bearbeitet durch User
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.