Hallo,
leider ist für mich C++ böhmische Dörfer und die Denkweise hinter der
JSON API noch nicht ganz klar. Ich möchte einfach nur einen Satz von 10
Wetterberichten, der sich bereits im JSON Buffer befindet als Feld
auswerten.
Bisher habe ich mir nur das zusammen gesucht, was auch klappt:
Das Parsen... ich hole 10 Datensätze von der OpenweatherMap, d.h. 10*3
Stunde = 30 Stunde Vorhersagen
Wurzel der Liste festlegen:
JsonArray& list = root["list"];
/* 2 Sätze auslesen: now und later */
1
JsonObject&now=list[0];
2
JsonObject&later=list[1];
3
4
PressureNow=now["main"]["pressure"];
5
TempNow=now["main"]["temp"];
6
WSpeedNow=now["wind"]["speed"];
usw.
Was nicht klappt ist ein Feld an zu legen, wo ich zb 10 Sätze
hineinschreibe :-( Mit now und later habe ich zwei aber ich will das in
einem Array haben. also zb feld[n]
JsonObject& feld[10]; <- Compiler Mecker: declaration of feld as
array of referces.
for (int i = 0; i < 10; i++) {
Auswertung.....
}
Kann da mal jemand helfen? Möglichst mit Code?
Christian J. schrieb:> und die Denkweise hinter der JSON API noch nicht ganz klar
"die JSON API" - C++ selbst kennt kein JSON; Du benutzt also irgendeine
Library/irgendwelchen Code.
Welchen? Woher kommt der? Ist der dokumentiert?
Ja, die Arduino Lib für esp8266.... und da ist alles dokuemntiert,
erschlagend sogar. Ich will nur dieses eine Problem lösen.
https://arduinojson.org/v5/doc/
das ist eines mit 2 Datensätzen, ich kann aber auch 10 abrufen. Und
genau das will ich jetzt tun. Natürlich erzeuge ich nicht 10 Variablen
now,later,nochlater,viellater etc. sondern will die 10 Sätze einfach nur
auslesen und in meine eigenen Vars packen, damit ich auf vertrauten
Boden komme und weiterverarbeiten kann.
JsonObject& now = list[0];
JsonObject& later = list[1];
Damit habe ich schon die Infos, die ich brauche für die ersten beiden
Sätze, die 3h auseinander liegen. 0 für jetzt und 1 für in 3 Stunden.
Und nun nur noch das ganze erweitern auf 10 Sätze. Aber JsonObject& mit
dem & hinter dem Typ ist mir aus C nicht bekannt, das scheint eine
Instanz eines Objektes zu sein. Now wird zum Zeiger auf den Inhalt bzw
die Methoden dieser Klasse. So mein rudimentäres Verständnis von c++....
Und da soll es alles rein:
1
/* Wetter Datensatz */
2
typedefstruct{
3
intFC_Hours;/* Stunden in Zukunft: 0,3,6,9,12,15,.... */
Christian J. schrieb:> JsonObject& feld[10]; <- Compiler Mecker
Zu recht.
C++ Standard §8.3.2/4:
There shall be no references to references, no arrays of references,
and no pointers to references.
Rufus Τ. F. schrieb:> Oder hab' ich das Problem jetzt komplett missverstanden?
Nee, ich denke schon richtig. Das problem vieler Anleitungen wie auch
bei dieser ist, dass sie von leuten geschrieben werden, die so tief in
der Materie stecken, dass sie die Fragen eines Neulings nicht
"verstehen". Im Grund ist diese nur, wie die Daten in dem Container
abgelegt sind (nach dem Parsen) und wie der Zugriff erfolgt. Json an
sich ist nix Besonders, ein Datenformat wie xml, lesbar von Menschen und
Maschinen zur strukturierten Ablage von Daten, die eine hierarische
Ordnung haben können. Ihc probiers mal heute abend aus, wenn ich Zeit
habe...
Weisst du zufällig was diese 0 da bedeutet?
WeatherIDNow = now["weather"][0]["id"];
Ist auch nur abgeschrieben.....
PS: Deine Lösung kompiliert schonmal durch.... das gibt Hoffung.
PSS: Und sie funktioniert auch :-)))) Klasse, danke Meister!
Christian J. schrieb:> Weisst du zufällig was diese 0 da bedeutet?> WeatherIDNow = now["weather"][0]["id"];
Das ist der Index für ein Array.
Hier (http://json.org/) ist die JSON Syntax ganz gut dargestellt. Wenn
du die Daten genau anschaust, dann siehst du, dass weather ein Array
ist.
Ah ok. Es reicht wennn man das versteht, was man grad braucht denke ich.
Bin ja kein Entwickler für solche Anwendungen.
Und warum muss ich solche Verrenkungen machen über die foo Variablen?
Direkte Zuweisung auf den gleichen Typ (global) geht nicht. Da wird
gemeckert. Es können auch keine rechnungen gemacht werden. Die Ausdrücke
müssen so da stehen wie sie sind. Also die *3.6 kann nicht geklammert
werden.
Christian J. schrieb:> Direkte Zuweisung auf den gleichen Typ (global) geht nicht. Da wird> gemeckert.
Aha. Der Compiler gibt eine Meldung "Gemecker" aus, oder wie muss man
sich das vorstellen?
Fehlermeldungen haben in der Regel eine Bedeutung, der man entnehmen
kann, was das Problem ist.
Rufus Τ. F. schrieb:> Aha. Der Compiler gibt eine Meldung "Gemecker" aus, oder wie muss man> sich das vorstellen?
Es ist ein ganzer Wust, der sich nicht auf die Zeile bezieht, sondern
aus den Quelltext der Json Lib. U.a. dass keine passende Methode
gefunden wurde. Nur der Typ String macht diese probleme, die anderen
nicht.
Ich habe mal etwas gekürzt :-)
Arduino: 1.8.5 (Windows 7), Board: "NodeMCU 1.0 (ESP-12E Module), 80
MHz, Flash, 4M (1M SPIFFS), v2 Lower Memory, Disabled, None, Only
Sketch, 256000"
Build-Optionen wurden verändert, alles wird neu kompiliert
K:\ESP8266\WetterOled\tools.ino: In function 'int GetWeatherData()':
tools:186: error: ambiguous overload for 'operator=' (operand types are
'String' and 'ArduinoJson::Internals::EnableIf<true,
ArduinoJson::Internals::JsonObjectSubscript<const char*> >::type {aka
ArduinoJson::Internals::JsonObjectSubscript<const char*>}')
wetter[i].DateStamp = list[i]["dt_txt"];
exit status 1
ambiguous overload for 'operator=' (operand types are 'String' and
'ArduinoJson::Internals::EnableIf<true,
ArduinoJson::Internals::JsonObjectSubscript<const char*> >::type {aka
ArduinoJson::Internals::JsonObjectSubscript<const char*>}')
Dieser Bericht wäre detaillierter, wenn die Option
"Ausführliche Ausgabe während der Kompilierung"
in Datei -> Voreinstellungen aktiviert wäre.
Probier' doch mal aus, was passiert, wenn Du in die betreffende Zeile
einen typecast nach String einbaust, d.h.
> wetter[i].DateStamp = (String) list[i]["dt_txt"];
Was passiert dann?
Rufus Τ. F. schrieb:> Was passiert dann?
K:\ESP8266\WetterOled\tools.ino: In function 'int GetWeatherData()':
tools:186: error: call of overloaded
'String(ArduinoJson::Internals::EnableIf<true,
ArduinoJson::Internals::JsonObjectSubscript<const char*> >::type)' is
ambiguous
wetter[i].DateStamp = (String)list[i]["dt_txt"];
Das Problem bezieht sich nur auf die String Klasse, die ja ohnehin mit
Vorsicht zu genießen ist und auf "double".
Nur das ist kompilierbar und liefert das richtige Eregbnis:
String foo1 = list[i]["dt_txt"];
wetter[i].DateStamp = foo1;
Das hier aber läuft durch. Ohne den Cast aber nicht.
wetter[i].WSpeed = 3.6 * (double)list[i]["wind"]["speed"];
ich hoffe doch, dass die Json Klasse einen Destruktor hat, der den
dynamischen Speicher wieder frei gibt, wenn die Routine verlassen wird.
Due legt das nämlich auf dem Heap an wie ich meine und nicht auf dem
Stack.
Naja, einfach geht es nicht mehr als hier:
https://arduinojson.org/v5/assistant/
Man trägt seinen Satz ein und bekommt alles geliefert mit fertigem Code,
um kreuz und quer darauf zu zu greifen.....