METEO : utilisez l’API de Météo France

L’interrogation de la base de données de MF permet l’accès à des paramètres que l’on ne trouve généralement pas dans les modules ou cartes proposés habituellement sur HA.
Exemple : le rayonnement et l’ensoleillement peuvent intéresser les possesseurs de panneaux photovoltaïques, la visibilité a de l’intérêt pour un pilote de planeur, la nébulosité pour les amateurs de photos de paysages, …

On accède aussi à différents types de données. Pour les données d’observation, il y a les mesures toutes les 6 minutes (cas présenté ici), ou les données horaires suffisantes pour la plupart d’entre nous.

Exemple d’affichage

Comment obtenir l’autorisation d’accès de MF

  1. créer un compte sur MeteofranceWeb
    si besoin, vous pouvez trouver de l’aide dans MeteofranceWeb
    il faut souscrire à l’API Données d’observation (validité de la souscription pour 2 ans)
    plus tard, dans votre profil, vous pourrez accéder directement à mes API

  2. choisir votre station d’observation :
    dans la rubrique Documentation, puis Description
    de là, on accède un nouveau portail Données Publiques de Météo-France - Informations sur les stations (métadonnées)
    et dans l’onglet Informations sur les stations, vous pouvez trouver l’identifiant de la station la plus proche de chez vous
    ou alors, dans Documentation, on trouve Liste des stations
    exemple : Annecy-Meythet, id station 74182001

j’ai trouvé un jour une carte interactive des stations météo…mais impossible de remettre la main dessus.

  1. générer un token
    choisir le type API Key par exemple pour une durée de 31536000 secondes (1 an)
    copier-coller le token dans le fichier secrets.yaml
# météo
mf_key: 'eyJ4NXQiOiJZV0kxTT...'

Intégration dans HA :
Personnellement j’utilise les packages qui permettent de grouper toutes les entités d’un même thème dans un seul fichier

Code du package mameteo.yaml :

# fichier mameteo.yaml

# Template ##########################################################
template:
  - sensor:
    - name: rayonnement normalisé
      # sensor.rayonnement_normalise
      state: "{{ (state_attr('mameteo.data','raw') | from_json)['ray_glo01'] }}"
      unit_of_measurement: "J/m2@6mn"

# Automations #######################################################
automation:
  # Météo France - data 6mn
  # interrogation de l'API de Météo France : données d'observation (6'), fréquence de modif : 6 minutes
  - id: mameteo_data_6mn
    alias: MaMétéo - data 6mn
    description: 'interrogation de l''API de Météo France'
    mode: single
    trigger:
      - platform: time_pattern
        # toutes les 6 minutes
        minutes: "/6"
    condition: []
    action:
      - service: python_script.exec
        data:
          key: !secret mf_key_obs
          title: Python inline
          source: |
            from datetime import datetime
            import requests
            import urllib.parse  

            try:            
              serveur = 'https://public-api.meteofrance.fr/public/DPObs/v1'
              key = data.get("key", "")
              service = '/station/infrahoraire-6m'
              station = '74182001' # code de la station sélectionnée : Annecy Meythet
              datage = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")     # en UTC
            
              url = serveur + service + '?id_station=' + station + '&date=' + urllib.parse.quote(datage) + '&format=json&apikey=' + urllib.parse.quote(key)
              # print('url=', url)
              r = requests.get(url)
              rstr = str(r)
              print(r)
              if '<400>' in rstr:
                hass.states.set('mameteo.data', '400: Contrôle de paramètres en erreur')
              elif '<404>' in rstr:
                hass.states.set('mameteo.data', '404: Jeu de données inexistant')
              elif '<Response [200]>' in rstr:
                print('analyse du json')
                resp = r.json()[0]
                print('resp=', resp)
                # hass.states.set( 'mameteo.data', datetime.now().strftime("%d/%m/%Y %H:%M:%S"), { 'json': 'r' } )
                datage = datetime.strftime( datetime.strptime(resp['reference_time'], '%Y-%m-%dT%H:%M:%SZ'), '%d/%m/%Y %H:%M:%S' )
                hass.states.set( 'mameteo.data', datetime.now().strftime("%d/%m/%Y %H:%M:%S"), 
                                  {
                                    'raw': str(resp).replace('\'', '\"'),       # ainsi on peut faire : (state_attr('mameteo.data','raw') | from_json)['t']
                                    'raw2': str(resp),
                                    'reference_time': datage,                   # date and time of the production of the data in UTC
                                    'temperature': resp['t']-273.15,            # air temperature at 2 meters above the ground in Kelvin degrees -> °C
                                    'humidite': resp['u'],                      # hourly relative humidity at 2 meters 
                                    'pression': resp['pres']/100,               # station pressure in Pa -> hPa 
                                    'vent_direction': resp['dd'],               # mean wind direction at 10 meters above the ground in degrees
                                    'vent_force': resp['ff']*3.6,               # mean wind speed at 10 meters above the ground in m/s -> km/h
                                    'rafale_direction': resp['dxi10'],          # 10 minutes mean wind gust direction at 10 meters above the ground in degrees 
                                    'rafale_force': resp['fxi10']*3.6,          # 10 minutes mean wind gust speed at 10 meters above the ground in m/s
                                    'precipitation': resp['rr_per'],            # all precipitation over the previous 6 minutes in mm  
                                    'puissance_solaire': resp['ray_glo01']/360, # global radiation over the previous 6 minutes in J/m² = Wh/m² pendant 6mn -> puissance solaire W/m²
                                    'ensoleillement': resp['insolh'],           # sunshine duration over the previous 1H in min
                                    'visibilite': resp['vv'],                   # horizontal visibility in meters 
                                    'origine': 'Météo France, Données Observation 6mn'
                                  })
                hass.states.set( 'mameteo.reference_time',   datage,                 { 'unit_of_measurement': 'UTC' } )
                hass.states.set( 'mameteo.temperature',      resp['t']-273.15,       { 'unit_of_measurement': '°C' } )
                hass.states.set( 'mameteo.humidite',         resp['u'],              { 'unit_of_measurement': '%' } )
                hass.states.set( 'mameteo.pression',         resp['pres']/100,       { 'unit_of_measurement': 'hPa' } )
                hass.states.set( 'mameteo.vent_direction',   resp['dd'],             { 'unit_of_measurement': '°' } )
                hass.states.set( 'mameteo.vent_force',       resp['ff']*3.6,         { 'unit_of_measurement': 'km/h' } )
                hass.states.set( 'mameteo.rafale_direction', resp['dxi10'],          { 'unit_of_measurement': '°' } )
                hass.states.set( 'mameteo.rafale_force',     resp['fxi10']*3.6,      { 'unit_of_measurement': 'km/h' } )
                hass.states.set( 'mameteo.precipitation',    resp['rr_per'],         { 'unit_of_measurement': 'mm/1h' } )
                hass.states.set( 'mameteo.puissance_solaire',resp['ray_glo01']/360,  { 'unit_of_measurement': 'W/m²' } )
                hass.states.set( 'mameteo.ensoleillement',   resp['insolh'],         { 'unit_of_measurement': 'mn' } )
                hass.states.set( 'mameteo.visibilite',       resp['vv'],             { 'unit_of_measurement': 'm' } )
              else:
                hass.states.set('mameteo.data', 'erreur non définie: ' + rstr)
            except Exception as e:
                print(f'exception: {e=}')
            print('automation.mameteo_data_6mn: terminé')

Remarque : à partir de ce code, accès à une clé de l’attribut raw
Cf remarque sur l’initialisation de l’attribut raw

template:
  - sensor:
    - name: rayonnement normalisé
      state: "{{ (state_attr('mameteo.data','raw') | from_json)['ray_glo01'] }}"
      unit_of_measurement: "J/m2@6mn"

remarque sur le rafraichissement des données :
suite à un démarrage de HA, il faut un petit moment avant d’avoir les données disponibles (6 minutes max dans cet exemple)

Il n’est pas utile de relancer HA, le rechargement des automatisations suffit

Traces de HA :

2024-03-25 16:28:46.200 INFO (MainThread) [homeassistant.components.automation] _async_add_entity platform platform_name=automation entity=MaMétéo - data 6mn
2024-03-25 16:28:46.204 INFO (MainThread) [homeassistant.components.automation.ma_meteo_data_6mn] Initialized trigger MaMétéo - data 6mn

Traces de HA lors d’une exécution > :


2024-03-25 15:20:25.473 INFO (MainThread) [homeassistant.components.automation.ma_meteo_data_6mn] MaMétéo - data 1h: Running automation actions
2024-03-25 15:20:25.473 INFO (MainThread) [homeassistant.components.automation.ma_meteo_data_6mn] MaMétéo - data 1h: Executing step call service
<Response [200]>
analyse du json
resp= {‘lat’: 45.928167, ‘lon’: 6.094, ‘geo_id_insee’: ‘74182001’, ‘reference_time’: ‘2024-03-25T15:20:25Z’, ‘insert_time’: ‘2024-03-25T05:02:12Z’, ‘validity_time’: ‘2024-03-25T05:00:00Z’, ‘t’: 272.35, ‘td’: 271.35, ‘tx’: 272.85, ‘tn’: 272.35, ‘u’: 93, ‘ux’: 93, ‘un’: 92, ‘dd’: 10, ‘ff’: 1.4, ‘dxy’: 60, ‘fxy’: 3.2, ‘dxi’: 70, ‘fxi’: 3.7, ‘rr1’: 0.0, ‘t_10’: 280.05, ‘t_20’: 281.45, ‘t_50’: 283.35, ‘t_100’: 282.55, ‘vv’: 54570, ‘etat_sol’: None, ‘sss’: 0, ‘n’: None, ‘insolh’: None, ‘ray_glo01’: None, ‘pres’: 95590, ‘pmer’: 101160}
automation.mameteo_data_6mn: terminé

1 Like