ESP32 E-Paper 2.9" Display MQTT Daten von ESP01 (Tasmota) anzeigen

Ich befürchte, da hat er am Sender (ESP01 mit Tasmota) keinen Einfluss drauf.

Für Arduino gibt es auch eine JSON Bibliothek, mit der man
{"Time":"2024-06-02T17:23:04","ANALOG":{"Range":4184}}
zerlegen kann.
Man kann natürlich auch aus strPayload wieder das Original payload rausholen und dieses hartcodiert per strtok in zwei Teile, den zweiten nochmal in Name:Wert aufspalten und dann in Wert den Teil <{"Range":> und schließlich den interessanten Rest aufteilen.
Alternativ nach dem Ende von Range": suchen (oder wissen, dass es Position 48 ist) und dort das toFloat (? oder toInt?) ansetzen.

[ In JSON wäre es uint32_t wert = jsondoc["ANALOG"]["Range"]; ]

Bin Neugierig ob der TO sich meldet und antwortet :wink:

Wenn ich MQTT Telegramme parsen muss, schaue ich immer auf der ArduinoJson Assistant 6 Site nach. Da purzelt am Ende ein Code Snippet raus, das man in sein Programm einbauen kann.

Was schreibt dir Serial.println(strPayload);?
Kommt ein wert, string oder irgend was?
oder ganzer Telegramm "Time":"2024-06-03T19:59:24","ANALOG":{"Range":4023}}]
Habe aber auch 0 Ahnung vom dem Telegramm und wie man den zerlegt

Es kommt nur 0.00 V auf dem Display an.

Ich habe im Netz noch etwas gefunden
Bei tele/Solar6/LWT geändert

display.print(strPayload.toFloat());

auf

display.print(strPayload.c_str());

dann zeigt mir das Display den Status Online oder Offline an, an der Aktualisierung vom Display muss ich auch noch arbeiten.

Ändere ich es so auch bei tele/Solar6/SENSOR, wird mir
"Time":"2024-06-03T19:59:24","ANALOG":{"Range":4023}}]
angezeigt.

Es ist richtig das es sich um den Wert 4023 handelt, sind halt in mV.

So sieht es momentan aus


Beim unterem Bild kommt nicht Spannung, da der ESP01 gerade im DeepSleep ist.

Man muss nur wissen wie es geht und wo man etwas einfügt, da ich absoluter Anfänger in Sachen Arduino bin, stehe ich an der Wand.

String p ="\"Time\":\"2024-06-03T19:59:24\",\"ANALOG\":{\"Range\":4023}}]";
Serial.println(p.toFloat()); // ergibt 0.00, was hättest du sonst erwartet?

Auch wenn du gültige json Syntax verwendest, gilt lt. Referenz

Wenn keine gültige Konvertierung durchgeführt werden konnte, weil die Zeichenfolge nicht mit einer Ziffer beginnt, wird eine Null zurückgegeben.

Du musst nur lesen, was dir geschrieben wurde und wenn du etwas nicht verstehst, nochmal nachfragen.

Ich habe den Sketch aus dem Netz übernommen, wo jemand per mqtt seine Temperaturen auf dem Display anzeigen läßt.
Dachte er kommt sehr nah an dem ran, was ich möchte.
Deshalb steht display.print(strPayload.toFloat()); noch im Sketch.

Wie sich herraustellt ist aber nicht so einfach es umzustricken auf meine Bedürfnisse.

Bin ja schon froh das Ihr mir hier Tipp's gebt und euch damit auseinander setzt.

Danke schon mal dafür. :+1:

Hier weiss ich zb. nicht womit ich anfangen soll um es umzusetzen, die Bibliothek kann ich einfügen aber dann hört es bei mir auf. :roll_eyes:

Wie man eine Bib anwendet, lernen die meisten durch Ausprobieren der Beispiele.
Wenn die mitgelieferten Beispiele funktionieren, kann man sie anpassen.

Das JSON Format kann man zwar zu Fuß auseinander fummeln. Aber einfacher und weniger fehleranfällig ist es die interessanten Elemente per Parser zu verwenden, d.h. eine Library Funktion zu benutzen, die für JSON Handling geschrieben wurde. Der Link aus meinem Post #24 von oben hilft dir dabei.
Step 1: Auswählen der CPU und des Modes
In deinem Fall eben ein ESP32, und der input ist ein char*

Step 2: Json Input

Step 3: Berechnung der Size

Step 4: Code Snippet

Dieses Snippet kannst du nun in die callback Funktion packen, die Variablen noch etwas anpassen, fertig: input wird zu payload und inputLength wird zu length

Also ich würde z.B. das hier mal einbauen und testen....

// MQTT Callback
void callback(char* topic, byte* payload, unsigned int length) {
  payload[length] = '\0';

...

  if (strTopic == "tele/Solar6/LWT") {
    StaticJsonDocument<48> doc;
    DeserializationError error = deserializeJson(doc, payload, length);

    if (error) {
      Serial.print("deserializeJson() failed: ");
      Serial.println(error.c_str());
      return;
    }
    const char* Time = doc["Time"]; // "2024-06-02T17:23:04"
    float ANALOG_Range = doc["ANALOG"]["Range"]; // 4184
    ANALOG_Range /= 1000; // convert mV to V

    Serial.println(strPayload);
    uint16_t box_x = 10;
    uint16_t box_y = 85;
    uint16_t box_w = 200;//380;
    uint16_t box_h = 20;
    uint16_t cursor_y = box_y + 16;
    display.fillRect(box_x, box_y, box_w, box_h, GxEPD_WHITE);
    display.setCursor(box_x, cursor_y);
    display.print("Status "); 
    display.setCursor(box_x + 180, cursor_y);   
    display.print(ANALOG_Range); 
    display.print(" S");
    display.updateWindow(box_x, box_y, box_w, box_h, true);  
  }
}

Hi Andreas,
vielen Dank für Deine Ausführliche Anleitung.
Ich werde es testen und gebe dan Rückmeldung, heute schaffe ich es nicht mehr.

Funktioniert super mit Deiner Lösung, muss echt nur viel lesen und testen um einiges zu verstehen.

{"DeepSleep":{"Time":"2024-06-06T20:45:00","DeepSleep":1717705847,"Wakeup":1717706700}}

ist es möglich aus dem DeepSleep nur die Uhrzeit "20:45" rauszuholen ohne Datum, würde ich gern mit auf dem Display darstellen um zu wissen wann der ESP01 wieder online ist um evtl. Änderungen vorzunehmen und DeepSleep auszuschalten, ohne andere Progrmme wie zb. MQTT.FX zu nutzen.

Wäre es so richtig ?

// char* input;
// size_t inputLength; (optional)

StaticJsonDocument<32> doc;

DeserializationError error = deserializeJson(doc, input, inputLength);

if (error) {
  Serial.print("deserializeJson() failed: ");
  Serial.println(error.c_str());
  return;
}

const char* DeepSleep_Time = doc["DeepSleep"]["Time"]; // "T20:45"

Danke

ist natürlich "2024-06-06T20:45:00"

Da das Format aber fest ist, und du den hinteren Teil haben willst, ist es einfach:

const char* TimeOnly = DeepSleep_Time + 11;
Serial.println(TimeOnly);

Das hat jetzt nichts mit json zu tun, sondern ist fundamentales C / C++

ok danke, werde ich mal probieren.
Kannst Du mir noch sagen warum oder wofür die + 11 steht ?

Hhmm, also ich würde erstmal denselben Weg einschlagen, wie in Post #23 beschrieben. Dann sollte ein const char* Time Objekt herauskommen mit dem Inhalt "2024-06-06T20:45:00".

Diesen 0-terminierten c-String kannst du weiter zerlegen z.B. händisch mit mit strtok() und als token vielleicht "T" verwenden um das Datum von der Zeit zu trennen, und dann halt ein zweiter Aufruf mit dem Token ":" um die Stunden, Minuten und Sekunden herauszulösen.

Oder schau dir mal die Funktion strptime() an, die sollte das Parsen erledigen können. Dabei musst du eben mit dem Formatstring spielen, also vielleicht sowas wie: "%Y-%m-%dT%T" bis es so herauskommt wie du es benötigst. Das tm Struckt enthält dann die einzelnen Elemente für Stunde und Minute.

edit: typo

Ganz allgemein, Zeiger-Arithmetik. Bei Texten:
Serial.println("Hallo" + 1); // Ausgabe: "allo"
Serial.println("Blumenkohl" + 6); // Ausgabe: "kohl"

Flexibler bist du natürlich, wenn du ein eindeutiges Trennzeichen suchst.

Hi Michael,
bin erst jetzt zum testen gekommen, leider klappt es nicht.
Ich bekomme immer den Fehler

Compilation error: 'DeepSleep_Time' was not declared in this scope

Kannst Du mir sagen wo ich es einfügen soll ?
Ich habe es an dieser Stelle eingefügt

  if (strTopic == "tele/Solar6/DeepSleep")

  {
    
  const char* TimeOnly = DeepSleep_Time + 11;
  Serial.println(TimeOnly);

  Serial.println(strPayload);
  uint16_t box_x = 10;
  uint16_t box_y = 50;
  uint16_t box_w = 280;//380;
  uint16_t box_h = 20;
  uint16_t cursor_y = box_y + 16;
  display.fillRect(box_x, box_y, box_w, box_h, GxEPD_WHITE);
  display.setCursor(box_x, cursor_y);
  display.print("Online um"); display.setCursor(box_x + 180, cursor_y); //
  display.print(TimeOnly);
  display.updateWindow(box_x, box_y, box_w, box_h, true);  
  }

Danke

So ein bisschen sollte man schon das Prinzip einer Programmiersprache verstehen.

Hier: dass Variable mit ihrem Datentyp definiert werden müssen, bevor sie in anderen Anweisungen verwendet werden können.
(

aus deinem #34 (der seinersets den schnipsel davor braucht) wäre die erforderliche Definition, mit Datentyp const char*
dem Namen DeepSleep_Time
und der Initialisierung mit dem Wert "2024-06-06T20:45:00" durch die Ausführung von
doc["DeepSleep"]["Time"]