Go Down

Topic: [gelöst] Fetch API mit Json (Read 434 times) previous topic - next topic

Rentner

Nov 21, 2020, 07:51 pm Last Edit: Nov 21, 2020, 11:25 pm by Rentner
Hallo,

ich bin derzeit dabei eine Webseite zu Erstellen auf der sich Messertreihen grafisch darstelllen lassen. Dazu nutze ich Chart.js.Dar Webserver ist auf einen ESP 8266 NodeMCU. Grundlage Hallo Server abgeändert mit LittleFS. Die HTML Seite liegt also auf dem Filesystem.Es gibt derzeit ein Chart mit zwei Messreihen. Die Messreihen sollen als JSON mit Fetch abgerufen werden. Dazu AdruinoJson.Lib verwendet.

Im Moment hängt es an der Stelle die Daten auf der Webseite auzulesen. Der Brauser meldet einen Fehler im Json.

SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data

Mit dem Heifisch hab ich mir die Daten angesehen , der erkennt das richtig und gibt die beiden Member Key´s und Array´s des Objekt richtig an.
Auf der Webseite habe ich zum testen ein paar zeilen um ein paar Testwerte auf das Chart zu bringen das klappt soweit.

kann mir einer da weiterhelfen

Danke Heinz

Hier der Sketch


Code: [Select]

#include <LittleFS.h>
#include <ArduinoJson.h>
#include <ESP8266WebServer.h>

const byte maxbuffer = 20;
const size_t capacity = JSON_ARRAY_SIZE(2 * maxbuffer) + JSON_OBJECT_SIZE(2) + 30;

const char* ssid = "xxxx";
const char* password = "yyyy";

int wert1, wert2;
int buffer1[maxbuffer];
int buffer2[maxbuffer];

uint32_t altzeit;

// Server Instanz erstellen
ESP8266WebServer server(80);

//--------------- Setup --------------
void setup() {

  Serial.begin(115200);


  Serial.println();
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("Size ");
  Serial.println(capacity);

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  LittleFS.begin(); // Filesystem starten
  FSzeigen();       // Info anzeigen

  // --Server Handle einrichten---
  server.serveStatic("/", LittleFS, "/chart2.html");
  server.on("/daten", sendeDaten);
  server.onNotFound(handleNotFound);   // Fehler bearbeiten

  server.begin();
  Serial.println("HTTP server started");
}

// ------------- Loop ---------------
void loop() {
  server.handleClient();// hier passiert sonst nichts

  if (millis() - altzeit >= 1000) { // Messwerte simulieren
    altzeit = millis();
    wert1 = 200+random(10);
    wert2 = 500+random(10);
    Serial.print(wert1); Serial.print("\t");
    Serial.print(wert2); Serial.println();
    fillbuffer();
  }

}// ------- loop ende -----------


// ------------ Fehler Seite
void handleNotFound() {
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
}

// --------------- Fillesystem anzeigen ---------------------
void FSzeigen() {
  FSInfo fs_info;
  LittleFS.info(fs_info);
  float fileTotalKB = fs_info.totalBytes / 1024.0;
  float fileUsedKB = fs_info.usedBytes / 1024.0;
  Serial.print("\nFilesystem Total KB "); Serial.print(fileTotalKB);
  Serial.print(" benutzt KB "); Serial.println(fileUsedKB);

  Dir dir = LittleFS.openDir("/");  // Dir ausgeben
  while (dir.next()) {
    Serial.print(dir.fileName()); Serial.print("\t");
    File f = dir.openFile("r");
    Serial.println(f.size());
  }
}

void fillbuffer() {
  static int zeiger = -1;
  if (zeiger < maxbuffer-1) {
    zeiger++;
    
  }
  else { // Array Pos verschieben
    for (byte i = 1; i < maxbuffer; i++) {
      buffer1[i - 1] = buffer1[i];
      buffer2[i - 1] = buffer2[i];

    }
  }
  buffer1[zeiger] = wert1;
  buffer2[zeiger] = wert2;
  //Serial.print(zeiger);
}

void sendeDaten() {
  String json = "";
  DynamicJsonDocument doc(2048);
  JsonArray value1 = doc.createNestedArray("wert1");
  Serial.println();
  for (byte i = 0; i < maxbuffer; i++) {
    value1.add(buffer1[i]);
    //Serial.print(buffer1[i]);
  }

  Serial.println();
  JsonArray value2 = doc.createNestedArray("wert2");
  for (byte i = 0; i < maxbuffer; i++) {
    value2.add(buffer2[i]);
    //Serial.print(buffer2[i]);
  }

  Serial.println();
  serializeJson(doc, json);
  Serial.println(json);
  server.send(200, "application/json", json);

}



und hier die HTML Fehlerstelle ist markiert.

Code: [Select]


<!DOCTYPE html>
<html lang="de">
<head>
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
<meta charset = "UTF-8">
<title>Messwerte</title>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>

<style>
button{
width:5.5em;
height:2em;
font-size:1em
}
</style>
</head>

<body>
 <br>
<div style="width:70%">
<canvas id="chart"> </canvas>      
 </div>
<br><br>
<button type="button" onclick="loadDaten()">neu</button>

<script>
//setInterval(loadDaten, 1000);
myjson='{"wert1":[20,21,22,23,22,22,22,24,22,25],"wert2":[8,10,11,12,11,13,11,10,12,12,13,13,12,13,13,14]}'
const max_x=50; // max Anzahl der Messwerte
var xachse= [];
var wert=[];
var ctx = document.getElementById("chart").getContext('2d');
var config={
type: 'line',
data: {
labels: xachse,
datasets: [{
label: 'Reihe 1',
borderColor: "red",
backgroundColor:"black",
data:wert,
fill:false,
},{
label: 'Reihe 2',
borderColor: "blue",
backgroundColor:"black",
data:wert,
fill:false,
}]
},
options:{
animation: {
            duration: 0 // general animation time
},

scales:{
xAxes:[{
display: true,
scaleLabel: {
display: true,
labelString: 'letzte Messung'
}
}],
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: '°C'
}
}]
}
} // options ende
};
laden();
function laden(){
for (var i=0;i<=max_x-1;i++){ // X-Achse beschriften
xachse[i]=max_x-i;
}

var ctx = document.getElementById("chart").getContext('2d');
window.myChart = new Chart(ctx,config);

// zum testen
var obj=JSON.parse(myjson);
config.data.datasets[0].data =obj.wert1;
config.data.datasets[1].data =obj.wert2;
window.myChart.update();

}

function loadDaten(){
fetch('/daten')
.then( function(response){
return response.json();
})
.then(function(myjson){
var obj=JSON.parse(myjson); // hier tritt der Fehler auf.
config.data.datasets[0].data =obj.wert1;
config.data.datasets[1].data =obj.wert2;
window.myChart.update();

});
}


</script>

</body>
</html>





Derfips

Ein Blick in die Konsole von deiner Brause sollte helfen.

F12

Gruß Fips
Meine Esp8266 & ESP32 Projekte => https://fipsok.de

wno158

Hmm. Ich habe Dein html in ein File gespeichert und mit Edge, FF und Chrome aufgemacht. Alle sind damit zufrieden.
Zeile 1, Spalte 2 im myjson wäre ja das Anführungszeichen " - innerhalb eines Strings. Ich habe das testweise mal mit Backslash verziert. Dann geht es immer noch.
Ob das aber hilft...
Code: [Select]
myjson='{\"wert1\":[20,21,22,23,22,22,22,24,22,25],\"wert2\":[8,10,11,12,11,13,11,10,12,12,13,13,12,13,13,14]}'



Gruß Walter

Rentner

Hallo Fips,

ist mir schon klar soweit, desshalb hab ich ja die Fehlermeldung mit angegeben. Problem ist ich kann an dem zweiten Zeichen in der 1. Zeile keinen Fehler erkennen.

Ausgabe Serial auf dem ESP

Code: [Select]


{"wert1":[200,204,206,204,204,207,209,209,200,209,202,201,204,207,204,208,202,206,200,203],"wert2":[507,507,500,507,507,503,508,504,504,503,507,506,506,507,508,506,503,509,505,506,506]}



So sieht das aus was ich mit dem ESP absende.

@won158

Ja das ist richtig, als Datei auf dem PC läuft das.  Die Daten stammen von den Testdaten die ich mit des test Json eingegeben habe.


das Problem tritt innerhalb des Fetch auf wenn die Daten vom ESP kommen , dazu mal det Button auf der Seite drücken , das löst den Fetch aus. F12 im Brause zeigt dann den Fehler beim parsen des Json an.

ich kann nicht den Unterschied zwischen dem test JSON und dem vom ESP erkennen.


Derfips

#4
Nov 21, 2020, 08:59 pm Last Edit: Nov 21, 2020, 09:00 pm by Derfips
Im FF steht das ankommende Json unter Netzwerkanalyse / Antwort / Antwortinhalt

Zeig das bitte hier.

Habe die ArduinoJson.h nicht installiert, sonst hätte ich deinen Sketch getestet!


Gruß Fips
Meine Esp8266 & ESP32 Projekte => https://fipsok.de

Rentner

#5
Nov 21, 2020, 09:20 pm Last Edit: Nov 21, 2020, 09:24 pm by Rentner
Hallo,

antwort Zeile aus dem Brauser

{"wert1":[209,208,203,200,208,208,208,203,208,202,201,209,206,205,203,201,205,209,200,209],"wert2":[504,503,500,504,506,501,501,500,500,504,503,502,505,502,502,500,507,509,501,505]}







wno158

#6
Nov 21, 2020, 09:55 pm Last Edit: Nov 21, 2020, 10:25 pm by wno158
Hab mir das mal installiert; zufällig liegt ein ESP8266 wg. eines anderen Projekts auf dem Tisch. Firefox 83.0 auf Win 10 Pro / 2004.

Die Antwortdaten sehen vernünftig aus:
Code: [Select]
{"wert1":[208,208,205,201,206,208,202,208,203,207,206,209,202,204,204,206,207,209,205,203],"wert2":[506,501,504,506,506,502,505,508,500,507,507,507,506,509,509,503,505,504,505,500]}

EDIT: Fehlermeldung in der Konsole wie beschrieben.

Hmm - kann ich noch was für Euch ausprobieren?

EDIT2: Mein Spieltrieb hat mir keine Ruhe gelassen. Ich habe ganz am Anfang vor der ersten öffnenden geschweiften Klammer ein Leerzeichein eingefügt - alles gut. Kein Fehler mehr; warum auch immer.

Ach Sch... - beim Druck auf den Knopf kommt der Fehler doch wieder.
Gruß Walter

Derfips

Hallo Heinz,

das ankommende Json sieht für mich Fehlerfrei aus.

Code: [Select]

<script>
var myjson = '{"wert1":[209,208,203,200,208,208,208,203,208,202,201,209,206,205,203,201,205,209,200,209],"wert2":[504,503,500,504,506,501,501,500,500,504,503,502,505,502,502,500,507,509,501,505]}';
var obj=JSON.parse(myjson);
console.log(obj.wert1);
</script>



Das parsen funktioniert im Test auch.


Mit der Lib habe ich mich noch beschäftigt, ich bau mein Json ja immer zu Fuß zusammen.

Wenn bis morgen keine Lösung gefunden wurde installiere ich die Lib und probiere deinen Sketch aus.


Gruß Fips


Meine Esp8266 & ESP32 Projekte => https://fipsok.de

Rentner

#8
Nov 21, 2020, 10:41 pm Last Edit: Nov 21, 2020, 10:55 pm by Rentner
Hallo Fips,

ich hab mich bei Dir blöd gesucht nix mit einer JSON lib gefunden. Ja ich wollte zuerst das Json auch zu Fuss aufbauen, letzlich plane ich aber für jede Messreihe 100 Messungen, und da hab ich gedacht da muss es doch was geben und hab mir die lib installiert.

Komischerweise kappt das ja auch mit dem Test JSON und das vom ESP sieht ja ebenso aus. Eventuell gibts noc eine andere lib die das kann, wüsste aber nicht woran es liegen sollte.

https://arduinojson.org/ Link zu der lib


@wno158 ich wüsste auch nicht wie ich das Json auf der ESP seite mit lib aändern sollte. Es gibt ein beispiel Server da wird das so ähnlich gemacht. Allerdings mit client.print() . Das was ankommt sieht ja auch nicht falsch aus.  :'(

Ausschnitt aus dem Heifisch



Heinz

wno158

Heinz & Fips,
vielleicht hab' ich da was für Euch.

Hier bei Stackoverflow bin ich fündig geworden.

Mit dieser Änderung in chart2.html in der Funktion loadDaten() funktioniert es:
Code: [Select]
//var obj=JSON.parse(myjson); // hier tritt der Fehler auf.
var obj=myjson; // Fehler weg (?)

Sehe jetzt bei jedem Drücken auf "neu" lustige andere simulierte Daten (die blauen so um 500, die roten um 200) ohne Fehlermeldung in der Konsole.

Gute Nacht!
Gruß Walter

Rentner

#10
Nov 21, 2020, 11:23 pm Last Edit: Nov 22, 2020, 11:26 am by Rentner
Hallo,

das wars



danke

Heinz

Das gab ein Karma ;)  danke nochals

Derfips

#11
Nov 22, 2020, 06:43 am Last Edit: Nov 22, 2020, 11:50 am by Derfips
Heinz & Fips,
vielleicht hab' ich da was für Euch.

Hier bei Stackoverflow bin ich fündig geworden.
Das muss ich mal probieren.


@heinz

Mit Chart.js wollte ich auch schon länger mal was bauen.

Auf gehts!


Gruß Fips

Meine Esp8266 & ESP32 Projekte => https://fipsok.de

Rentner

#12
Nov 22, 2020, 11:07 am Last Edit: Nov 22, 2020, 11:08 am by Rentner
Heinz & Fips,
vielleicht hab' ich da was für Euch.

Hier bei Stackoverflow bin ich fündig geworden.

Das muss ich mal probieren.


@heinz

Mit Chart.js wollte ich auch schon länger mal was bauen.

Auf gehts!

Hallo,

wollte ich auch schon länger mal machen, durch einen Post hier vor ein paar Tagen bin ich dann wieder draufgekommen. Muss das jetzt noch verschönen. Aber das Grund geht es.

Bietete sich doch für einen BME an, Messreihe der letzten 24 Stunden oder sowas in der Art. Eigendlich jede Art von Datalogger.

schönen Sonntag noch
 Gruß Heinz





noiasca

Heinz was hast noch vor? Kommt noch was, oder bleibt es dabei?

Meine Wunschliste wäre:
- eine "kleinere" Anzahl an Werten pro Graph lokal halten, damit man beim erstmaligen Laden der Seite schon ein wenig gekurve sieht
- eine Aktualisierung (rechts dazuschiebeben)
- ab einer bestimmten Anzahl an Werten "links" den ältesten Wert rausschieben wenn recht was dazu kommt

sonst muss ich da mal selber ran ^^



how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

Rentner

Hallo,

ja sowas hab ich auch vor. Ich wollte  20-50 Messwerte im ESP in je  Reihe einem Array halten . Die dann von rechts an darstellen und die ältesten links rausschieben. Ähnlich wie das bei dem Windows Taskmanager ist.

Bin da derzeit noch am basteln , Grundsätzlich klappt das ja jetzt so, Die Richtung muss man halt noch drehen und verschönen. Auf einem Handy sieht das derzeit noch wenig schön aus. Linien dünner Messpunkte weg,Grösse usw.

Letztich bietet die Chart.js auch eine Treppendarstellung , damit gingen auch digitale Signale. Ich bin da derzeit in der Findungs-Phase. Link zur Seite war ja angegeben.

Ich mache jetzt erst mal was für z.B einen BME mit Speicher der letzten 8-24 Stunden mit Darstellung von 3 Charts auf einer Seite. Wird aber noch was dauern.

Mit der Änderung auf der Webseite läuft der Code jetzt aber. Der erstellt zwei zufällige Messreihen und schiebt die alten links raus.  Anzahl anpassen im Sketch und auf der Webseite. Auf der Webseite das Testgedöns rausnehmen.


Heinz

Go Up