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
-
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 -
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.
- 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é