Ankündigung

Einklappen
Keine Ankündigung bisher.

Support-Thread zum OpenWeatherMap Plugin

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Sollte dann pluginname oder „bezeichner“ angegeben werden..? Bei mir gibt es die Methode offenbar aber es wird nichts gefunden

    Kommentar


      Ich bekomme irgendwie recht viele API Fehler.. soweit ich das gesehen habe, müsste man Zahlungsdaten hinterlegen, um onecall Abfragen zu nutzen. Kommt für mich nicht in Frage, insofern fällt es mir auch schwer, das Problem zu fixen.
      Aus meiner Sicht sollte die Eval-Sache aus dem Struct raus und direkt ins Plugin mit einem zusätzlichen Part für current/wind_gust/beaufort

      Ich hab mal einen PR dazu erstellt, müsste aber bitte jemand testen.
      Zuletzt geändert von Onkelandy; 13.12.2024, 14:27.

      Kommentar


        Ich versuche gerade, mich da etwas einzuarbeiten... ohne V3.0-Account bekomme ich in den structs gar keine Daten, im Web-Interface kann ich mit "alle downloaden" aber durchaus Daten über die V2.5-API bekommen.

        Verstehe ich das richtig, dass die Structs alle auf den Onecall-API aufbauen? Also müsste man die structs anpassen, wenn man keine V3.0 nutzen möchte?

        Und wenn ich nur die owm_raw_files haben möchte, wird gar nicht gelesen, weil die von keinem Item gefragt sind...??
        Zuletzt geändert von Morg; 24.06.2025, 11:15.

        Kommentar


          Noch ein Nachtrag - hat mal jemand visualcrossing genutzt? Gibt es dazu "sinnvolle" Migrationshinweise, oder muss man sich das struct komplett selber bauen?

          Kommentar


            Kann leider zu beidem nicht sonderlich viel beitragen. Zur API könnte ich vielleicht wieder mal reinschauen, aber ich bin auch pirateweather umgestiegen, nachdem ich hier Probleme hatte.

            Kommentar


              Ich hatte mir mal visualcrossing angesehen aber mich dann später für open-meteo entschieden. Ich brauche nur die zukünftigen Temperaturen der nächsten 48 Stunden und das reicht so aus. Allerdings habe ich kein Plugin im Einsatz sondern parse schlicht ein wenig das Ergebnis der API in einer Logik.

              Kommentar


                Morg ,

                kannst Du das Plugin so konfigurierbar machen, dass es das Onecall-API v3 und alternativ das kostenlose API v2.5 unterstützt? Letzteres benötigt halt 2 Aufrufe für current und forecast (plus ggfls. weitere je nach benötigten Daten). Wenn man in den Plugin-Versionen weit genug zurück geht, müsste sogar noch der Code auffindbar sein, der vor der Einführung des Onecall-API v2.5 gültig war.​

                Für diejenigen, die v3 nutzen und aus Kostengründen die Anzahl der API-Aufrufe begrenzen wollen, wäre es m.E. sinnvoll, die Wetter-Widgets in smartVISU so zu erweitern, dass sie vollständig aus items versorgt werden können und die Visu dann keine eigenen Aufrufe mehr macht. Bei weather.current geht das ja schon, nur findet der API-Aufruf trotzdem noch statt. Dazu wäre eine standardisierte item-Benennung hilfreich, über die wir uns noch verständigen müssten.

                Gruß
                Wolfram



                Kommentar


                  Muss ich mal schauen. Ich hab immer noch das database-Plugin am Wickel (wobei ich da momentan ehrlicherweise nicht wirklich weiter komme...) und denke noch auf lib.orb rum.

                  Das Aufwändigste an der Flexibilisierung des Plugins ist, die passenden json-Pfade zu Wetterdatenpunkten zu finden und je nach Abfrage zu setzen. Dann könnte das Plugin standardisierte Wetteritems anbieten.
                  Alternativ wäre wirklich nur der Aufruf (und die data_source-Parameter) anzupassen, und jeder muss weiter mit den Pfad-Suchmustern arbeiten. Das braucht dann (s.o.) entsprechend aufwändige structs und ist aus meiner Sicht daher auch nicht schön...

                  Ich habe jetzt openmeteo ausprobiert und fülle (und erstelle) den Itembaum einmal am Tag mit einer Logik, dann passen die Benennungen der Vorhersageitems (.daily.d0, .daily.d1, .daily.d2... für heute, morgen, übermorgen; genauso .hourly.h001, .hourly.h002, .hourly.h003...) und man könnte mit simpler Arithmetik das passende Item finden (ich brauche eigentlich nur d0, also die Vorhersage für den aktuellen Tag).

                  Ist vielleicht etwas ... overpowered aber es tut seinen Job, und wenn ich die Abrufparameter ändere, bau ich mir schnell und einfach den passenden Itembaum (Vorhersage für 150+ Stunden * jeweils 12 Items + 12 Einheiten...)


                  Code:
                  #!/usr/bin/env python3
                  #
                  # This file contains a logic for use with SmartHomeNG
                  #
                  # Name of the logic: openmeteo.py
                  #
                  
                  #
                  # get weather data and forecast from openmeteo and
                  # - create matching item file and/or
                  # - fill items with values
                  #
                    
                      
                  import json
                  import requests
                  
                  # Startpunkte für Items (level = Einrückung * 4)
                  base_item = 'd.wetter'
                  base_level = 2
                  
                  
                  def walk(node, name, parent, level, method):
                      """ dict rekursiv durchlaufen """
                      for key in sorted(node.keys()):
                          method(node[key], key, parent + ('.' if parent else '') + str(name), level)
                          if isinstance(node[key], dict):
                              walk(node[key], key, parent + ('.' if parent else '') + str(name), level + 1, method)
                  
                  
                  def print_item(node, name, parent, level):
                      """ Item für yaml ausgeben """
                      def pitem(text, level):
                          print(f'{"    " * level}{text}')
                  
                      if type(node) is dict:
                          print(f'{"    " * level}{name}:')
                      else:
                          off = 0
                          if name.endswith('.unit'):
                              name = 'unit'
                              off = 1
                          if type(node) in (int, float):
                              typ = "num"
                          elif type(node) is str:
                              typ = 'str'
                          else:
                              typ = 'foo'
                          pitem(f'{name}:', level + off)
                          pitem(f'type: {typ}', level + 1 + off)
                  
                  
                  def set_item(node, name, parent, level):
                      """ Item-Wert setzen """
                      if type(node) not in (str, int, float):
                          return
                  
                      item = sh.return_item(f'{parent}.{name}')
                      if item is not None:
                          try:
                              item(node)
                          except Exception:
                              pass
                          
                  
                  lon = sh.env.location.lon()
                  lat = sh.env.location.lat()
                  
                  base_url = "https://api.open-meteo.com/v1/forecast"
                  
                  # Bernd: urlparam = f"{url}?latitude={lat}&longitude={lon}&current=temperature_2m&timezone=auto"
                  url = f"{base_url}?latitude={lat}&longitude={lon}&daily=temperature_2m_max,temperature_2m_min,apparent_temperature_max,apparent_temperature_min,sunrise,sunset,daylight_duration,sunshine_duration,precipitation_sum,rain_sum,showers_sum&hourly=temperature_2m,relative_humidity_2m,dew_point_2m,apparent_temperature,precipitation_probability,precipitation,rain,showers,surface_pressure,visibility,evapotranspiration,et0_fao_evapotranspiration,wind_speed_10m,wind_direction_10m,uv_index,direct_radiation&current=temperature_2m,relative_humidity_2m,apparent_temperature,precipitation,rain,showers,snowfall,cloud_cover,surface_pressure&timezone=auto"
                  # mit timezone=auto wird eine lokale Zeit passend zu lat/lon wiedergegeben
                  
                  session = requests.session()
                  response = session.get(url)
                  num_bytes = len(response.content)
                  if num_bytes < 50:
                     raise LeaveLogic()
                  
                  json_obj = response.json()
                  
                  # logger.warning(f"{json_obj=}")
                  
                  data = {}
                  # Abschnitte, die geparst werden
                  for interval in ['current', 'daily', 'hourly']:
                  
                      j = json_obj[interval]
                  
                      data[interval] = {}
                      pad = '000'
                  
                      # aktuellen Abschnitt parsen
                      if isinstance(j['time'], list):
                          pl = len(str(len(j['time'])))
                          for idx in range(len(j['time'])):
                              pi = pad + str(idx)
                              data[interval][interval[0] + pi[-pl:]] = {k: v[idx] for k, v in j.items()}
                      else:
                          data[interval] = j.copy()
                  
                      # Einheiten für aktuellen Abschnitt parsen
                      ju = json_obj[interval + '_units']
                      attrs = list(ju.keys())
                      if 'time' not in data[interval]:
                          e_len = len(data[interval])
                          pl = len(str(e_len))
                          for attr in attrs:
                              for idx in range(e_len):
                                  pi = pad + str(idx)
                                  data[interval][interval[0] + pi[-pl:]][attr + '.unit'] = ju.get(attr, '')
                      else:
                          for attr in attrs:
                              data[interval][attr + '.unit'] = ju.get(attr, '')
                  
                  # Item-Definition erzeugen (auf Konsole ausgeben)
                  # walk(data, base_item, '', base_level, print_item)
                  
                  # Item-Werte befüllen
                  walk(data, base_item, '', base_level, set_item)
                  Zuletzt geändert von Morg; 26.06.2025, 23:01.

                  Kommentar

                  Lädt...
                  X