Wetterprognosen mit JsonMod

Begonnen von Pnemenz, 15 November 2024, 11:01:39

Vorheriges Thema - Nächstes Thema

Pnemenz

Ich habe ein JSON-File mit Wetterprognosedaten. Ich möchte daraus die Daten nach dem, im File angegebenen Timestams als Readings bekommen. Die Readings sollen den Timestamp aus dem File (Zeitpunkt, für den die Werte Vorhergesagt werden) | Parameter| Wert enthalten.
Ich bekommen beim versuch
multi(jsonPath("\$.timestamps"),property('grad_p10'))immer diese Fehlermeldung:
warning: JsonPath filter property timestamps failure at ./FHEM/98_JsonMod.pm line 1368. in 'multi(jsonPath("\$.timestamps"),property('timestamps'))'Wie bekomme ich die Die Daten aus meinem Json in diese Form?

betateilchen

Wenn Du mit multi() arbeitest, muss der jsonPath zu einem array auflösen.

Steht auch explizit in der commandref:

ZitatJsonpath expression must translate into an array of objects or values.

Außerdem ist die Syntax in Deinem multi() unvollständig, es werden drei Parameter benötigt und Du hast nur zwei angegeben.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Pnemenz

Hallo Betateilchen,
Danke für deine Antwort, die lässt mich genauso ratlos zurück, wie davor :)

Wenn ich den jsonPath \$.timestamps in den JsonPath online Evaluuator eingebe (https://jsonpath.com/) bekomme ich ein Array der Timestamps zurückgeliefert.

Meine Frage war ja, wie muss der jsonPath aussehen, damit ich Timestamp und Values der Vorhersagen bekomme. Bzw. kann der Timestamp der Vorhersage überhaup der Timstamp im Devices sein? Ich habe bereits eine Tag lang versucht aus dem Json eine für mich sinnvolle Tabelle zu bekommen und bin daran kläglich gescheitert. Deswegen bitte ich ja auch hier um Hilfe.
 
Anscheinend hab ich da grundsätzliches nicht begriffen und alle Anleitungen bzw Erklärungen gehen immer von einen json Struktur aus, die "key":"Value" Paare beinhaltet und nicht so wie in meinem json keys mit einer Liste von Values, und auch nochdazu unterschiedlichen tiefen.

betateilchen

Um Dir helfen zu können, muss ich mir Dein Json erstmal näher anschauen. Dazu hatte ich aber gestern Abend keine Zeit und heute wird es auch noch ein bisschen dauern.

Du könntest hier aber schonmal ein konkretes Beispiel posten, wie ein reading aus Deinem Json am Ende tatsächlich aussehen soll.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Pnemenz

Ich bin mir nicht sicher, wie es am besten ist. Ich möchte die Prognose für zwei Dinge verwenden:

1) zur grafischen Darstellung als SVG: Da möchte ich die Prognosen in meine mySQL Datenbak schreiben und benötige daher den Timestamp aus der Spalte Timestamp aus dem json, jeweils features.properties.parameters als Reading und data als Value.

2) zur Berechung der Stündlichen Erzwugung meiner PhV Anlage. Da könnte das Reading so ausshen:
timestamp_Parametername | jeweiliges dazugehörige data
($timestamp_$.$.features.properties.parameters."name" | $.features.properties.parameters."name".data
ergibt pro name 60 Readings

Wenn das jsonMod nur die Variante 2 erzeugen kann, dann kann ich die Einträge in die Datenbank, bzw das aufteilen in mehrere Dummy Devices scripten.

Ich weiss nicht was gescheiter ist, alles in einem Device zu haben oder für jeden parameter ein Dummy anlegen.


betateilchen

Für das, was Du machen möchtest, solltest Du das parsen besser in eine eigene Funktion in die 99_myUtils.pm verpacken.

Du möchtest ja letztendlich Werte aus mehreren im json-Input vorhandenen arrays zu einem "FHEM Datensatz" für das Logging zusammenfügen und verwenden. Dafür ist JsonMod nicht vorgesehen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

betateilchen

Zitat von: betateilchen am 16 November 2024, 16:45:40Für das, was Du machen möchtest, solltest Du das parsen besser in eine eigene Funktion in die 99_myUtils.pm verpacken.

Mal eben schnell aus der Hüfte geschossen - relevant sind nur die letzten 5 Zeilen.

sub wt {
   my $input = '{
  "reference_time": "2024-11-15T00:00+00:00",
  "media_type": "application/json",
  "type": "FeatureCollection",
  "version": "v1",
  "timestamps": [
    "2024-11-15T09:00+00:00",
    "2024-11-15T10:00+00:00",
    "2024-11-15T11:00+00:00",
    "2024-11-15T12:00+00:00",
    "2024-11-15T13:00+00:00",
    "2024-11-15T14:00+00:00",
    "2024-11-15T15:00+00:00",
    "2024-11-15T16:00+00:00",
    "2024-11-15T17:00+00:00",
    "2024-11-15T18:00+00:00",
    "2024-11-15T19:00+00:00",
    "2024-11-15T20:00+00:00",
    "2024-11-15T21:00+00:00",
    "2024-11-15T22:00+00:00",
    "2024-11-15T23:00+00:00",
    "2024-11-16T00:00+00:00",
    "2024-11-16T01:00+00:00",
    "2024-11-16T02:00+00:00",
    "2024-11-16T03:00+00:00",
    "2024-11-16T04:00+00:00",
    "2024-11-16T05:00+00:00",
    "2024-11-16T06:00+00:00",
    "2024-11-16T07:00+00:00",
    "2024-11-16T08:00+00:00",
    "2024-11-16T09:00+00:00",
    "2024-11-16T10:00+00:00",
    "2024-11-16T11:00+00:00",
    "2024-11-16T12:00+00:00",
    "2024-11-16T13:00+00:00",
    "2024-11-16T14:00+00:00",
    "2024-11-16T15:00+00:00",
    "2024-11-16T16:00+00:00",
    "2024-11-16T17:00+00:00",
    "2024-11-16T18:00+00:00",
    "2024-11-16T19:00+00:00",
    "2024-11-16T20:00+00:00",
    "2024-11-16T21:00+00:00",
    "2024-11-16T22:00+00:00",
    "2024-11-16T23:00+00:00",
    "2024-11-17T00:00+00:00",
    "2024-11-17T01:00+00:00",
    "2024-11-17T02:00+00:00",
    "2024-11-17T03:00+00:00",
    "2024-11-17T04:00+00:00",
    "2024-11-17T05:00+00:00",
    "2024-11-17T06:00+00:00",
    "2024-11-17T07:00+00:00",
    "2024-11-17T08:00+00:00",
    "2024-11-17T09:00+00:00",
    "2024-11-17T10:00+00:00",
    "2024-11-17T11:00+00:00",
    "2024-11-17T12:00+00:00"
  ],
  "features": [
    {
      "type": "Feature",   
      "properties": {
        "parameters": {
          "grad_p10": {
            "name": "surface global radiation (10th percentile)",
            "unit": "W m-2",
            "data": [
              125.5,
              165.1,
              220.2,
              116,
              99.7,
              47.8,
              21.4,
              0.4,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              31.5,
              142.7,
              252.5,
              329.4,
              359.7,
              342.2,
              278.2,
              176.9,
              62.2,
              0.7,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              9.2,
              44.1,
              106,
              199.6,
              281.9,
              266.4
            ]
          },
          "grad_p50": {
            "name": "surface global radiation (50th percentile)",
            "unit": "W m-2",
            "data": [
              201.7,
              239.5,
              282.2,
              221.3,
              142,
              86.8,
              34.4,
              0.6,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              33.9,
              144.6,
              253.9,
              330.7,
              361.6,
              343.9,
              279.6,
              178.1,
              62.8,
              0.8,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              12.9,
              60,
              143.5,
              298.8,
              353.1,
              337
            ]
          },
          "grad_p90": {
            "name": "surface global radiation (90th percentile)",
            "unit": "W m-2",
            "data": [
              210.5,
              312.5,
              346.9,
              312.2,
              215.9,
              145.7,
              55.2,
              0.9,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              34.1,
              145.3,
              254.7,
              332.6,
              364,
              346.8,
              282.2,
              179.9,
              63.4,
              0.9,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              0,
              15.4,
              75.8,
              206.3,
              326,
              359.2,
              342.1
            ]
          }
        }
      }
    }
  ]
}';

   my $prognose = json2nameValue($input);
   for (my $i = 1; $i <=52; $i++) {
      Debug $prognose->{'timestamps_'.$i}." - ".$prognose->{'features_1_properties_parameters_grad_p10_data_'.$i};
   }
}

Damit bekommst Du eine Zuordnung von timestamp zu p10_data.
Anstatt Debug() könnte man natürlich auch ein setreading erzeugen, das dann auch entsprechend gelogged würde. Oder die Daten direkt in die Datenbank loggen, ohne erst readings erzeugen zu müssen, wenn man sie wirklich nur für SVG braucht.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

ch.eick

#7
Zitat von: Pnemenz am 16 November 2024, 09:17:41Ich bin mir nicht sicher, wie es am besten ist. Ich möchte die Prognose für zwei Dinge verwenden:

1) zur grafischen Darstellung als SVG: Da möchte ich die Prognosen in meine mySQL Datenbak schreiben und benötige daher den Timestamp aus der Spalte Timestamp aus dem json, jeweils features.properties.parameters als Reading und data als Value.

2) zur Berechung der Stündlichen Erzwugung meiner PhV Anlage. Da könnte das Reading so ausshen:
timestamp_Parametername | jeweiliges dazugehörige data
($timestamp_$.$.features.properties.parameters."name" | $.features.properties.parameters."name".data
ergibt pro name 60 Readings
Moin,
für die PV Leistungsprognose gibt es bereits zwei Varianten, die Dir ja eventuell gefallen könnten.

1) 76_SolarForecast Modul
2) Mit einer MySQL Procedure und einem Python Skript , dass "KI" verwendet.
   https://wiki.fhem.de/wiki/Kostal_Plenticore_10_Plus#Wetter-/Leistungs-Prognose
   Als MySQL wird der original Oracle MySQL docker Container verwendet SQLight reicht in den meisten Fällen nicht aus.
   Dort findest Du auch Links zu den verwendeten Devices.
   Die stundenbasierte Aufbereitung der Prognose Daten findet in den userReadings der Devices statt.

VG   Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

Pnemenz

ZitatDamit bekommst Du eine Zuordnung von timestamp zu p10_data.
Anstatt Debug() könnte man natürlich auch ein setreading erzeugen, das dann auch entsprechend gelogged würde. Oder die Daten direkt in die Datenbank loggen, ohne erst readings erzeugen zu müssen, wenn man sie wirklich nur für SVG braucht.
Vielen Dank, ich schau mir das mal genauer an. Hab inzwischen eine Ähnliche Lösung für myUtils geschrieben.
Als Reading in einem Dummy hab ich immer nur den letzten Wert, ist das dbLog schnell genug um alle Prognosen zu schreiben, wenn ich in einer Schleife die Readins erzeuge?
Irgendwie funktioniert der setreading aufruf
setreading GeospherePrognose "2024-11-16 23:00" t2m_p90 1.9 nicht, es wird der Timestamp nicht übernommen. Das Reading sieht dann so aus:
2024-11-16 | 23:00 t2m_p90 1.9 | 2024-11-18 18:49:23erwarte mir dieses:
2m_p90 | 9.7 | 2024-11-16 23:00

Pnemenz

Zitat von: ch.eick am 17 November 2024, 13:30:37Moin,
für die PV Leistungsprognose gibt es bereits zwei Varianten, die Dir ja eventuell gefallen könnten.

1) 76_SolarForecast Modul
2) Mit einer MySQL Procedure und einem Python Skript , dass "KI" verwendet.
  https://wiki.fhem.de/wiki/Kostal_Plenticore_10_Plus#Wetter-/Leistungs-Prognose
  Als MySQL wird der original Oracle MySQL docker Container verwendet SQLight reicht in den meisten Fällen nicht aus.
  Dort findest Du auch Links zu den verwendeten Devices.
  Die stundenbasierte Aufbereitung der Prognose Daten findet in den userReadings der Devices statt.

VG  Christian
Soweit ich sehe werden hier Daten verwendet, die für Wien zu ungenau sind. Meine Daten stammen von der Geosphere Austria. Sowohl DWD als auch die anderen Dienste sind zu ungenau bzw liefern keine Strahlungsdaten für Wien.

betateilchen

DbLog ist auf jeden Fall schnell genug für Dein Vorhaben.
Du kannst Werte auch direkt in die Datenbank schreiben, ohne den Umweg über setreading gehen zu müssen.

Schau mal in der commandref zu DbLog unter "set ... addCacheLine ...":

set <name> addCacheLine YYYY-MM-DD HH:MM:SS|<device>|<type>|<event>|<reading>|<value>|[<unit>]
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Pnemenz

Zitat von: betateilchen am 18 November 2024, 19:54:46DbLog ist auf jeden Fall schnell genug für Dein Vorhaben.
Du kannst Werte auch direkt in die Datenbank schreiben, ohne den Umweg über setreading gehen zu müssen.

Schau mal in der commandref zu DbLog unter "set ... addCacheLine ...":

set <name> addCacheLine YYYY-MM-DD HH:MM:SS|<device>|<type>|<event>|<reading>|<value>|[<unit>]
Danke, werd ich mir anschauen.

zu setreading:
laut Commanmdref:
setreading <devspec> [YYYY-MM-DD HH:MM:SS] <reading> <value>was ist dan an meinem Befehl falsch?


betateilchen

Zitat von: Pnemenz am 18 November 2024, 20:10:17zu setreading:
laut Commanmdref:
setreading <devspec> [YYYY-MM-DD HH:MM:SS] <reading> <value>was ist dan an meinem Befehl falsch?
setreading GeospherePrognose "2024-11-16 23:00" t2m_p90 1.9

Fehler 1: die Sekunden fehlen in der Zeitangabe
Fehler 2: die Anführungszeichen um Deine Zeitangabe sind falsch

Es müsste also so aussehen:

setreading GeospherePrognose 2024-11-16 23:00:00 t2m_p90 1.9
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

Pnemenz

Danke, alle möglichen Varianten hab ich probiert, auf die fehlenden Sekunden bin ich nicht gekommen.

betateilchen

Zitat von: Pnemenz am 19 November 2024, 06:39:29auf die fehlenden Sekunden bin ich nicht gekommen.

Ohne die Sekunden passt halt die regex nicht, mit der setreading prüft und erkennt, ob eine Zeitangabe mitgegeben wurde :)
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!