Seite 1 von 6

AccuWeather Forecast Antwort File parsen

Verfasst: 10.06.2019, 09:29
von Jimbaem
Hallo zusammen,

zur Info vorweg.
Nach der Umstellung bei Wunderground Weather bin ich zu AccuWeather gewechselt. Soweit funktioniert auch alles, ich kann aktuelle und Forecast Wetterdaten abfragen, in SV schreiben und in Mediola anzeigen lassen. Um an die Werte zu kommen, dienen die enthaltenen Kommas.

Beispiel:

Code: Alles auswählen

TemperatureMin1 = (responce.StrValueByIndex(",",30)).StrValueByIndex(":",3).ToFloat();
Leider ändert AccuWeather ab und an das Antwort File so das die Positionen mit den benötigten Werten nicht mehr stimmen. Deshalb möchte ich das parsen des Files gerne umstellen und gezielt nach Suchbegriffen suchen und dann die Werte abgreifen, was soweit auch funktioniert.

Beispiel:

Code: Alles auswählen

string word = "Minimum";
integer word_laenge = word.Length();
integer word_position = responce.Find(word);
string daten = responce.Substr((word_position + word_laenge +11), 100);
Im Beispiel wird nach dem Wort "Minimum" gesucht, welches im File insgesamt 5 mal (5 Tage Forecast) vorkommt. Mittels '.Find' wird immer nur der erste Treffer gefunden und dann abgebrochen. Die Suche beginnt immer wieder am Anfang, so das ich an die nächsten 4 Werte für "Minimum" nicht rankomme.

Und genau da kommt jetzt mein Problem wo ich nicht weiter komme, bzw. nicht weis ob das so überhaupt machbar ist.
Danke schon mal für evtl. Lösungsansätze ......

Jürgen

Re: AccuWeather Forecast Antwort File parsen

Verfasst: 10.06.2019, 10:34
von Black
was für ein format hat die antwort ?

xml ? json ? irgendwas selbstgegartes ?

was hast du für eine CCU ? Raspberrymatik ? wenn raspberrymatik und json, guck dir mal das tool jq an, welches rmatik mitbringt. damit kann man recht gut durch json parsen.

black

Re: AccuWeather Forecast Antwort File parsen

Verfasst: 10.06.2019, 10:53
von Jimbaem
habe eine CCU2 mit aktueller Firmware 2.45.7

Anbei mal das Antwort File mit markierten Suchworten und Werten.
Keine Ahnung was das für ein Format ist. Bei XML oder JSON müsste das glaube ich im Header stehen?
Antwort Forecast.jpg

Re: AccuWeather Forecast Antwort File parsen

Verfasst: 10.06.2019, 13:01
von Black
Es ist ein json.

Ich hatte hier mal einen primitiv Parser script geschrieben.

Aber für komplex dieses nix. So aufgeaben dann an jq.
Oder bei mir direkt in iobroker unter JavaScript. Bringt auch direkt einen parser mit.

So stringgewürge geht ne Weile gut bis etwas kleines geändert wird dann passt nix mehr.

Re: AccuWeather Forecast Antwort File parsen

Verfasst: 10.06.2019, 13:27
von Jimbaem
Wenn ich das richtig verstanden habe, meinst du mit "jq" JQuery, oder?
Glaube hier gelesen zu haben das dies in der aktuellen Firmware von RaspberryMatic enthalten ist.

Mal schauen was ich sonst noch finde, war wohl doch keine so gute Idee auf AccuWeather umzustellen :roll:

Danke

Re: AccuWeather Forecast Antwort File parsen

Verfasst: 10.06.2019, 15:03
von Fonzo
Jimbaem hat geschrieben:
10.06.2019, 13:27
Mal schauen was ich sonst noch finde, war wohl doch keine so gute Idee auf AccuWeather umzustellen :roll:
Abgesehen davon das Du mit den Nutzungsbedingungen von AkkuWeather Probleme bekommst, würde ich eher OpenWeather empfehlen, das wird auch von Mediola selber in IQONTROL NEO für Wetterdaten genutzt und hat eine offene dokumentierte API. Wenn NEO genutzt wird, gibt es je nach NEO Plugin das genutzt wird, auch fertige Openweathermap Einbindungen, mit dem Du alle Daten aus Openweathermap in NEO anzeigen lassen kannst.

Re: AccuWeather Forecast Antwort File parsen

Verfasst: 10.06.2019, 16:57
von Jimbaem
Fonzo hat geschrieben:
10.06.2019, 15:03
Jimbaem hat geschrieben:
10.06.2019, 13:27
Mal schauen was ich sonst noch finde, war wohl doch keine so gute Idee auf AccuWeather umzustellen :roll:
Abgesehen davon das Du mit den Nutzungsbedingungen von AkkuWeather Probleme bekommst, würde ich eher OpenWeather empfehlen, das wird auch von Mediola selber in IQONTROL NEO für Wetterdaten genutzt und hat eine offene dokumentierte API. Wenn NEO genutzt wird, gibt es je nach NEO Plugin das genutzt wird, auch fertige Openweathermap Einbindungen, mit dem Du alle Daten aus Openweathermap in NEO anzeigen lassen kannst.
Weis jetzt grad nicht warum ich mit den Nutzungsbedingungen von AccuWeather Probleme bekommen soll :roll:.
Hab mich ganz normal registriert, API-Key erhalten, habe am Tag 50 Abrufe frei und hab sogar denen ihr Logo in der Visualisierung von Neo.

Bei Mediola finde ich zwar IQONTROL, für ein Plugin stolzer Preis, aber über Wetterdaten oder OpenWeatherMap hab ich selbst mit der Suchfunktion nix gefunden.

Trotzdem Danke für den Hinweis
Jürgen

Re: AccuWeather Forecast Antwort File parsen

Verfasst: 10.06.2019, 17:06
von Fonzo
Jimbaem hat geschrieben:
10.06.2019, 16:57
und hab sogar denen ihr Logo in der Visualisierung von Neo.
Dann ist ja alles prima, die meisten lassen so was nur weg und da muss man die Nutzungsbedingungen des jeweiligen Anbieters eben mal genau lesen. Sollte auch kein Vorwurf sein, da Du ja das Kleingedruckte bzw. die AGBs gelesen hast, was viele Nutzer einfach komplett übergehen.
Jimbaem hat geschrieben:
10.06.2019, 16:57
Bei Mediola finde ich zwar IQONTROL
IQONTROL NEO ist der Nachfolger, funktioniert aber nur bei Ansteuerung von Homematic mit einem AIO Gateway V5 Plus oder einem AIO Gateway V6 und nutzt Openweathermap. Wenn Du NEO selber nutzt müstest Du ein NEO Plugin nutzten, das Dir die Daten zur Visualisierung zur Verfügung stellt oder eben die CCU, die die Werte als Systemvariablen für NEO vorhält.

Re: AccuWeather Forecast Antwort File parsen

Verfasst: 10.06.2019, 18:36
von FBK2904
Jimbaem hat geschrieben:
10.06.2019, 09:29
Leider ändert AccuWeather ab und an das Antwort File so das die Positionen mit den benötigten Werten nicht mehr stimmen. Deshalb möchte ich das parsen des Files gerne umstellen und gezielt nach Suchbegriffen suchen und dann die Werte abgreifen, was soweit auch funktioniert.
Das Hauptproblem ist, dass Du nach "Kommas" "(,) suchst und das ist der Fehler !
Denn ab und zu kommen diese auch in "Weathertext" vor und dann hast Du ein Problem :x ,
da dann Deine Sucherei nicht mehr stimmt.
Jimbaem hat geschrieben:
10.06.2019, 09:29
Und genau da kommt jetzt mein Problem wo ich nicht weiter komme, bzw. nicht weis ob das so überhaupt machbar ist.
Hier einmal mein AccuWeather-Script, das seit mehren Wochen zuverlässig läuft und auch auf meiner NEO anzeigt.
(Alle unnötigen Sonderzeichen werden aus dem String ausgefiltert).
Es wird nach einem Startwort, einem dem zusuchenden vorherigen Wort/Wert und dem nächsten Hauptbegriff gesucht .
Es muss auch nicht umständlich mit "substr(0)" und/oder "StrValueByIndex" vor und zurück jonglieren :lol:
(geschrieben und zusammen gebastelt von einem Script-Laien wie mir :mrgreen: ).

Code: Alles auswählen

!#####    AccuWeather - API (v4.3)    #####
!#####      aktuelle Wetterdaten      #####
!#####  in Systemvariablen schreiben  #####
!#####      by FBK2904 (08.05.19)     #####

! Manuell anzulegende Systemvariablen:
! SV_WETTER_UpdateTime                Zeichenkette         Uhr    (EpochTime)
! SV_WETTER_Wettertext                Zeichenkette         ---    (WeatherText)
! SV_WETTER_Icon                      Zeichenkette         ---    (WeatherIcon)
! SV_WETTER_Temperatur                Zahl -50  bis  100   °C     (Temperature)
! SV_WETTER_Luftdruck                 Zahl   0  bis  100   hPa    (Pressure)
! SV_WETTER_Luftfeuchte               Zahl   0  bis  100   %      (RelativeHumidity)
! SV_WETTER_Windgeschwindigkeit       Zahl   0  bis  500   km/h   (WindSpeed)
! SV_WETTER_Windgeschwindigkeit_txt   Zeichenkette         ---    [Zahl (WindSpeed) zu Text]
! SV_WETTER_Windboen                  Zahl   0  bis  500   km/h   (WindGust)
! SV_WETTER_Windboen_txt              Zeichenkette         ---    (Zahl (WindGust) zu Text]
! SV_WETTER_Windrichtung_txt          Zeichenkette         ---    (WindDirection)
! SV_WETTER_Wolkendichte              Zahl   0  bis  100   %      (CloudCover)

! ###  Hier die WETTERSTATION-ID und API-KEY eintragen  ###
string wetterstation_id = "123456";
string api_key = "abcdefghijklmnopqrstuvwxyz";   !  KEY1

var url = "http://dataservice.accuweather.com/currentconditions/v1/"#wetterstation_id#"?apikey="#api_key#"&language=de-de&details=true&metric=true";
 dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("wget -q -O - '"#url#"'");
 dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
string Wetter_XML = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State().Replace('"', "").Replace("[", "").Replace("]", "").Replace("(", "").Replace(")", "").Replace("{", "").Replace("}", "");
!  WriteLine("Wetter_XML = "#Wetter_XML);

! #  Unix-Zeit suchen und umrechnen  #
string word = "EpochTime";
string param = ":";
integer param_laenge = param.Length();
integer word_position = Wetter_XML.Find(word);
integer word_pos_end = Wetter_XML.Find("WeatherText") - word_position;
string daten = Wetter_XML.Substr(word_position, word_pos_end);
word_position = daten.Find(param);
daten = daten.Substr(word_position + param_laenge, daten.Length());
word_pos_end = daten.Find(",");
daten = daten.Substr(0, (word_pos_end -0));
!var RealTime = daten.ToInteger().ToTime().Format("%d.%m.%Y  %H:%M Uhr");  ! Datum und Uhrzeit
var RealTime = daten.ToInteger().ToTime().Format("%H:%M");                 ! Nur Uhrzeit
 dom.GetObject("SV_WETTER_UpdateTime").State(RealTime);
!  WriteLine(daten);
!  WriteLine(RealTime);

! #  Wettertext suchen  #
string word = "WeatherText";
string param = ":";
integer param_laenge = param.Length();
integer word_position = Wetter_XML.Find(word);
integer word_pos_end = Wetter_XML.Find("WeatherIcon") - word_position;
string daten = Wetter_XML.Substr(word_position, word_pos_end);
word_position = daten.Find(param);
daten = daten.Substr(word_position + param_laenge, daten.Length());
word_pos_end = daten.Find(",");
daten = daten.Substr(0, (word_pos_end -0));
 dom.GetObject("SV_WETTER_Wettertext").State(daten.ToLatin());
!  WriteLine(daten);

! #  WetterIcon suchen  #
string word = "WeatherIcon";
string param = ":";
integer param_laenge = param.Length();
integer word_position = Wetter_XML.Find(word);
integer word_pos_end = Wetter_XML.Find("HasPrecipitation") - word_position;
string daten = Wetter_XML.Substr(word_position, word_pos_end);
word_position = daten.Find(param);
daten = daten.Substr(word_position + param_laenge, daten.Length());
word_pos_end = daten.Find(",");
daten = daten.Substr(0, (word_pos_end -0)).ToInteger();
 dom.GetObject("SV_WETTER_Icon").State(daten);
!  WriteLine(daten);

! #  Aktuelle Temperatur suchen und Wert korrigieren  #
string word = "Temperature";
string param = "Value:";
integer param_laenge = param.Length();
integer word_position = Wetter_XML.Find(word);
integer word_pos_end = Wetter_XML.Find("Unit") - word_position;
string daten = Wetter_XML.Substr(word_position, word_pos_end);
word_position = daten.Find(param);
daten = daten.Substr(word_position + param_laenge, daten.Length());
word_pos_end = daten.Find(",");
daten = daten.Substr(0, (word_pos_end -0)).ToFloat() + 1.5;    ! Wert um 1.5 erhöhen
 dom.GetObject("SV_WETTER_Temperatur").State(daten);
!  WriteLine(daten);

! #  Luftdruck suchen  #
string word = "Pressure";
string param = "Value:";
integer param_laenge = param.Length();
integer word_position = Wetter_XML.Find(word);
integer word_pos_end = Wetter_XML.Find("Unit") - word_position;
string daten = Wetter_XML.Substr(word_position, word_pos_end);
word_position = daten.Find(param);
daten = daten.Substr(word_position + param_laenge, daten.Length());
word_pos_end = daten.Find(",");
daten = daten.Substr(0, (word_pos_end -0)).ToInteger();
 dom.GetObject("SV_WETTER_Luftdruck").State(daten);
!  WriteLine(daten);

! #  Aktuelle Luftfeuchte suchen und Wert korrigieren  #
string word = "RelativeHumidity";
string param = ":";
integer param_laenge = param.Length();
integer word_position = Wetter_XML.Find(word);
integer word_pos_end = Wetter_XML.Find("DewPoint") - word_position;
string daten = Wetter_XML.Substr(word_position, word_pos_end);
word_position = daten.Find(param);
daten = daten.Substr(word_position + param_laenge, daten.Length());
word_pos_end = daten.Find(",");
daten = daten.Substr(0, (word_pos_end -0)).ToFloat() -5;    ! Wert um 5 verringern
 dom.GetObject("SV_WETTER_Luftfeuchte").State(daten);
!  WriteLine(daten);

! #  Windrichtung (Text) suchen  #
string word = "Wind:Direction";
string param = "Localized:";
integer param_laenge = param.Length();
integer word_position = Wetter_XML.Find(word);
integer word_pos_end = Wetter_XML.Find("English") - word_position;
string daten = Wetter_XML.Substr(word_position, word_pos_end);
word_position = daten.Find(param);
daten = daten.Substr(word_position + param_laenge, daten.Length());
word_pos_end = daten.Find(",");
daten = daten.Substr(0, (word_pos_end -0));
 dom.GetObject("SV_WETTER_Windrichtung_txt").State(daten.ToLatin());
!  WriteLine(daten);

! #  Windgeschwindigkeit suchen und in Text umwandeln  #
string word = "Speed:Metric";
string param = "Value:";
integer param_laenge = param.Length();
integer word_position = Wetter_XML.Find(word);
integer word_pos_end = Wetter_XML.Find("Unit") - word_position;
string daten = Wetter_XML.Substr(word_position, word_pos_end);
word_position = daten.Find(param);
daten = daten.Substr(word_position + param_laenge, daten.Length());
word_pos_end = daten.Find(",");
daten = daten.Substr(0, (word_pos_end -0)).ToFloat();
 dom.GetObject("SV_WETTER_Windgeschwindigkeit").State(daten);
!  WriteLine(daten);
!  #  Umsetzung in Wetterdienst-Windtexte  #
      if (daten <     0.00) {daten = "???"                          ;} else {
      if (daten <     1.00) {daten = "Windstille"                   ;} else {
      if (daten <     5.00) {daten = "Leiser Zug"                   ;} else {
      if (daten <    11.00) {daten = "Leichte Brise"                ;} else {
      if (daten <    19.00) {daten = "Schwacher Wind"               ;} else {
      if (daten <    28.00) {daten = "Mäßiger Wind"                 ;} else {
      if (daten <    38.00) {daten = "Auffrischender Wind"          ;} else {
      if (daten <    49.00) {daten = "Starker Wind"                 ;} else {
      if (daten <    61.00) {daten = "Starker bis stürmischer Wind" ;} else {
      if (daten <    74.00) {daten = "Stürmischer Wind"             ;} else {
      if (daten <    88.00) {daten = "Sturm"                        ;} else {
      if (daten <   102.00) {daten = "Schwerer Sturm"               ;} else {
      if (daten <   117.00) {daten = "Orkanartiger Sturm"           ;} else {
      if (daten >=  117.00) {daten = "Orkan"                        ;} }}}}}}}}}}}}}
 dom.GetObject("SV_WETTER_Windgeschwindigkeit_txt").State(daten);
!  WriteLine(daten);

! #  Windboen suchen  #
string word = "WindGust:Speed";
string param = "Value:";
integer param_laenge = param.Length();
integer word_position = Wetter_XML.Find(word);
integer word_pos_end = Wetter_XML.Find("Unit") - word_position;
string daten = Wetter_XML.Substr(word_position, word_pos_end);
word_position = daten.Find(param);
daten = daten.Substr(word_position + param_laenge, daten.Length());
word_pos_end = daten.Find(",");
daten = daten.Substr(0, (word_pos_end -0)).ToFloat();
 dom.GetObject("SV_WETTER_Windboen").State(daten);
!  WriteLine(daten);
!  #  Umsetzung in Wetterdienst-Böentexte  #
      if (daten <     0.00) {daten = "???"                              ;} else {
      if (daten <    11.00) {daten = "mit leichten Böen"                ;} else {
      if (daten <    19.00) {daten = "mit schwachen Böen"               ;} else {
      if (daten <    28.00) {daten = "mit mäßigen Böen"                 ;} else {
      if (daten <    38.00) {daten = "mit auffrischenden Böen"          ;} else {
      if (daten <    49.00) {daten = "mit starken Böen"                 ;} else {
      if (daten <    61.00) {daten = "mit starken bis stürmischen Böen" ;} else {
      if (daten <    74.00) {daten = "mit stürmischen Böen"             ;} else {
      if (daten <    88.00) {daten = "mit Sturmböen"                    ;} else {
      if (daten <   102.00) {daten = "mit schweren Sturmböen"           ;} else {
      if (daten <   117.00) {daten = "mit orkanartigen Sturmböen"       ;} else {
      if (daten >=  117.00) {daten = "mir Orkanböen"                    ;} }}}}}}}}}}}
 dom.GetObject("SV_WETTER_Windboen_txt").State(daten);
!  WriteLine(daten);

! #  Bewölkungsdichte suchen  #
string word = "CloudCover";
string param = ":";
integer param_laenge = param.Length();
integer word_position = Wetter_XML.Find(word);
integer word_pos_end = Wetter_XML.Find("Ceiling") - word_position;
string daten = Wetter_XML.Substr(word_position, word_pos_end);
word_position = daten.Find(param);
daten = daten.Substr(word_position + param_laenge, daten.Length());
word_pos_end = daten.Find(",");
daten = daten.Substr(0, (word_pos_end -0)).ToInteger();
 dom.GetObject("SV_WETTER_Wolkendichte").State(daten);
!  WriteLine(daten);
Dieses Script bezieht seine Daten aus dem "Currentconditions", lässt sich aber genauso auch auf die vier anderen
Wetterdaten-Strings umstellen.
Nutze es auch noch in ähnlicher Form, um mir eine 3-Tages-Vorschau (mit Tag/Nacht Daten) anzuzeigen lassen.

Mein Tipp, um die ganzen Datenstrom einmal übersichtlich zu sehen:
- Den ganzen XML-String aus dem Script-Editor kopieren.
- In einen Texteditor (z.B. Notepad++) kopieren und immer nach einem Komma ein Return machen.
- Dann sieht man(n) die ganzen Daten fein säuberlich aufgeschlüsselt.

Grüssle,
Frank

Re: AccuWeather Forecast Antwort File parsen

Verfasst: 10.06.2019, 19:16
von Jimbaem
@Fonzo:
Das hab ich gar nicht als Vorwurf aufgefasst, wusste nur nicht was man noch tun/beachten sollte. Ist ja keine öffentliche Homepage sondern alles lokal in Neo auf meinem Tab. Trotzdem Danke für den Hinweis.

Sorry, habs trotzdem noch nicht begriffen wie das in NEO aussehen soll und was ich dafür brauche. Aber egal, die ganzen Diskussionen bzgl. SUS und den gesalzenen Preisen haben mich so genervt das ich für mich entschieden habe in diese Richtung nichts mehr zu Investieren. Bin ganz zufrieden mit meiner 'alten' Version.

Danke dir für die Informationen
Jürgen