Qualité d'air

Yes!
Une âme charitable saurai développer une intégration associée ? :mega:

1 « J'aime »

Je pense qu’il y moyen de faire quelque chose sans une vraimnt integration, mais il faudra créer un login :
https://admindata.atmo-france.org/api/doc

@Caillema
Faire avec « scrape »( n’est plus en Yaml!")
ou « multi-scrape » devrait être simple !
Un test chez moi :innocent: sur Météo « France »

Je test pour ma part le nouveau Ikea avec un nom imprononçable :

Mais je ne pourrais pas dire si les valeurs de qualité sont juste ! J’ai un différence énorme sur l’humidité 8% entre le Ikea et une sonde Sonoff


1 « J'aime »

Si j’ai bien compris, le site atmo-france.org, regroupe les données fournis par « AASQA » des régions

( L'AASQA de votre région | Atmo France )

Donc, autant aller à la source pour ma région : http://www.atmo-auvergnerhonealpes.fr/

Cela tombe bien, la page web est simplimisme et donc facile a parser.

J’ai donc crée ces entrées dans mon multiscrape.yaml : (avec multiscrape: !include multiscrape.yaml dans le configuration.yml )

Code multiscrape
# Qualité de l'air
- name: qualite_air_aujourdhuit
  resource: https://www.atmo-auvergnerhonealpes.fr/air-commune/Grenoble/38185/indice-atmo?date={{ now().strftime("%Y-%m-%d") }}
  scan_interval: 864000
  button:
    - unique_id: air_refresh
      name: Qualite Air refresh
  sensor:
    - unique_id: qualite_air_2_5
      name: Particules fines, diamètre < 2,5 µm
      icon: mdi:air-filter
      select: '#\36 001-qualificatif'
    - unique_id: qualite_air_10
      name: Particules fines, diamètre < 10 µm
      icon: mdi:air-filter
      select: '#\35 -qualificatif'
    - unique_id: qualite_air_SO2
      name: Dioxyde de soufre
      icon: mdi:air-filter
      select: '#\31 -qualificatif'
    - unique_id: qualite_air_O3
      name: Ozone
      icon: mdi:air-filter
      select: '#\37 -qualificatif'
    - unique_id: qualite_air_NO2
      name: Dioxyde d'azote
      icon: mdi:air-filter
      select: '#\38 -qualificatif'
    - unique_id: qualite_air_info_today
      name: "Information aujourd'huit"
      icon: mdi:air-filter
      select: '#indice-comment'
- name: qualite_air_demain
  resource: https://www.atmo-auvergnerhonealpes.fr/air-commune/Grenoble/38185/indice-atmo?date={{ (now()+ timedelta(days=1)).strftime("%Y-%m-%d") }}
  scan_interval: 864000
  button:
    - unique_id: air_refresh_demain
      name: Qualite Air refresh Demain
  sensor:
    - unique_id: qualite_air_info_tomorrow
      name: Information Demain
      icon: mdi:air-filter
      select: '#indice-comment'
- name: qualite_air_apres_demain
  resource: https://www.atmo-auvergnerhonealpes.fr/air-commune/Grenoble/38185/indice-atmo?date={{ (now()+ timedelta(days=2)).strftime("%Y-%m-%d") }}
  scan_interval: 864000
  button:
    - unique_id: air_refresh_apres_demain
      name: Qualite Air refresh Après-demain
  sensor:
    - unique_id: qualite_air_info_post_tomorrow
      name: Information Après-demain
      icon: mdi:air-filter
      select: '#indice-comment'

Puis j’ai crée un dashboard (simple pour l’instant)

dashboard
type: entities
entities:
  - entity: sensor.qualite_air_2_5
  - entity: sensor.qualite_air_10
  - entity: sensor.qualite_air_so2
  - entity: sensor.qualite_air_o3
  - entity: sensor.qualite_air_no2
  - entity: sensor.qualite_air_info_today
  - entity: sensor.qualite_air_info_tomorrow
  - entity: sensor.qualite_air_info_post_tomorrow
  - entity: button.air_refresh
    name: Force refresh
title: 'Qualité de l''air à Grenoble'

Et voici le résultat :

PS : j’ai un bug que j’ai pas (encore) compris, Je tente de récupérer les infos du lendemain (et sur-lendemain), pour cela j’utilise une autre URL qu’avec le jour qui change :

https://www.atmo-auvergnerhonealpes.fr/air-commune/Grenoble/38185/indice-atmo?date={{ (now()+ timedelta(days=1)).strftime("%Y-%m-%d") }}

Mais, ca ne fonctionne pas, pourtant dans les outils de dev, {{ (now()+ timedelta(days=1)).strftime(« %Y-%m-%d ») }} correspond a 2023-04-20 et l’url avec https://www.atmo-auvergnerhonealpes.fr/air-commune/Grenoble/38185/indice-atmo?date=2023-04-20 est bonne sur mon navigateur

3 « J'aime »

Pas mal. :+1:
Bon après comme les différentes sources sont différentes sur la partie scraping (le site pour le Val de Loire est complément différent (et moche)), l’avantage de atmo-france, c’est d’avoir les même données uniformisées quelque soit la région

Avec des sensor rest pour commencer , ou un peu de node red ( cf par ex ici, sujet différent, mais contexte technique similaire)

Le scrape c’est le Mal :wink:
Une intégration, en tout cas officielle, est assez ardue, via hacs, c’est un peu plus léger, mais faut quand même pas mal de compétences python. J’aurais souhaité le faire pour hydrao, mais pas encore de mon niveau et le temps fait défaut…

J’ai demandé (et j’ai eu) un login pour utiliser les api sur API d'Atmo Data, l'agrégateur des flux open data des AASQA.

Mais je sèche comment faire ça (de manière propre) :
car il faut :

1/ Utiliser l’url avec api/login
ca répond un token
2/ mettre ce token dans les header de la commande suivant :
api/data/112/{"code_zone":{"operator":"=","value":"38185"},"date_ech":{"operator":">=","value":"2023-04-19"}}

  • 38185 correspond au code INSEE de la ville qu’on veut.

au début, je penser utiliser le restfull sensor ( RESTful - Home Assistant )
mais je ne vois pas comment enchaîner ces 2 requêtes

J’ai vu un truc (dégueu) là : Rest Authentication Sensor - #5 by MacXatu - Configuration - Home Assistant Community
mais c’est vraiment pas terrible comme solution de mon point de vue.

Je pense qu’un petit module serait effectivement la bonne solution surtout que cela ne semble pas super compliqué,

Pour info voici le json en retour de requete « la plus utile » de mon point de vue : ( api/data/112/{"code_zone":{"operator":"=","value":"38185"},"date_ech":{"operator":">=","value":"2023-04-19"}} )

json

{
« type »: « FeatureCollection »,
« name »: « national_data.national_ind_atmo »,
« crs »: {
« type »: « name »,
« properties »: {
« name »: « urn:ogc:def:crs:EPSG::3857 »
}
},
« features »: [
{
« type »: « Feature »,
« properties »: {
« gml_id »: 123767779,
« aasqa »: « 84 »,
« date_maj »: « 2023/04/19 13:07:22.873+02 »,
« partition_field »: « 842023w16 »,
« code_no2 »: 2,
« code_o3 »: 2,
« code_pm10 »: 1,
« code_pm25 »: 2,
« code_qual »: 2,
« code_so2 »: 1,
« code_zone »: « 38185 »,
« coul_qual »: « #50ccaa »,
« date_dif »: « 2023/04/18 »,
« date_ech »: « 2023-04-19 »,
« epsg_reg »: « 2154 »,
« lib_qual »: « Moyen »,
« lib_zone »: « Grenoble »,
« source »: « Atmo Auvergne-Rhône-Alpes »,
« type_zone »: « commune »,
« x_reg »: 914869.3,
« x_wgs84 »: 5.73644208367544,
« y_reg »: 6457849.8,
« y_wgs84 »: 45.1864477777476
},
« geometry »: {
« type »: « Point »,
« coordinates »: [
638577.8117198545,
5650921.7868237775
]
}
},
{
« type »: « Feature »,
« properties »: {
« gml_id »: 123771883,
« aasqa »: « 84 »,
« date_maj »: « 2023/04/19 13:07:22.873+02 »,
« partition_field »: « 842023w16 »,
« code_no2 »: 1,
« code_o3 »: 2,
« code_pm10 »: 1,
« code_pm25 »: 2,
« code_qual »: 2,
« code_so2 »: 1,
« code_zone »: « 38185 »,
« coul_qual »: « #50ccaa »,
« date_dif »: « 2023/04/18 »,
« date_ech »: « 2023-04-20 »,
« epsg_reg »: « 2154 »,
« lib_qual »: « Moyen »,
« lib_zone »: « Grenoble »,
« source »: « Atmo Auvergne-Rhône-Alpes »,
« type_zone »: « commune »,
« x_reg »: 914869.3,
« x_wgs84 »: 5.73644208367544,
« y_reg »: 6457849.8,
« y_wgs84 »: 45.1864477777476
},
« geometry »: {
« type »: « Point »,
« coordinates »: [
638577.8117198545,
5650921.7868237775
]
}
}
]
}

Ah ouaip et le token est valable 1h a ce que je lis,…

Les données sont mise à jour 2 fois par jour … Donc le token d’une heure c’est large

image

Salut …
Quand plus simple chez Météo France en mode « scrape » !!
Pour moi « Atmo Fance » n’est pas possible ici ! :portugal:, et site Europe un peu caca !

Looks good !
Pourrais tu partager ton code pour faire du Multiscrape ?
(j’arrive à afficher une page web, mais pas uniquement le contenu qui m’intéresse, et ce malgré la lecture du tuto de Pulpy-Luke sur le prix de l’essence)

Merci beaucoup !

Montre moi la page que tu veux récupérer, avec entourer ce que tu veux .

Pour info maître @Pulpy-Luke :innocent:a fait c’est vrai de bon tuto, encore faut-il que tu saches te se servir des outils !

ça y est maintenant on va croire que je suis gourou d’une secte, celle des multicrapers fous ? :rofl:

Pas facile de reconnaître quand on Bon !

:rofl:

Bonsoir,
De ce que j’ai compris c’est qu’il faut effectivement se créer un compte en conservant le token
Après dans mon fichier sensors.yaml j’ai créé cela :

##Indices air
  - platform: rest
    scan_interval: '06:00:00'
    name: Indice global du jour
    resource: http://api.atmo-aura.fr/api/v1/communes/XXX/indices/atmo?api_token=XXX&date_calcul=yesterday&echeance=1
    value_template: "{{ value_json.data[0].indice }}"
    json_attributes_path: "$.data[0]"
    json_attributes:
      - qualificatif
  - platform: rest
    scan_interval: '06:00:00'
    name: Indice Particules fines PM2.5 du jour
    resource: http://api.atmo-aura.fr/api/v1/communes/XXX/indices/atmo?api_token=XXX&date_calcul=yesterday&echeance=1
    value_template: "{{ value_json.data[0].sous_indices[0].indice }}"
    json_attributes_path: "$.data[0].sous_indices[0]"
    json_attributes:
      - polluant_nom
      - concentration
  - platform: rest
    scan_interval: '06:00:00'
    name: Indice Particules fines PM10 du jour
    resource: http://api.atmo-aura.fr/api/v1/communes/XXX/indices/atmo?api_token=XXX&date_calcul=yesterday&echeance=1
    value_template: "{{ value_json.data[0].sous_indices[1].indice }}"
    json_attributes_path: "$.data[0].sous_indices[1]"
    json_attributes:
      - polluant_nom
      - concentration
  - platform: rest
    scan_interval: '06:00:00'
    name: Indice Dioxyde de soufre SO2 du jour
    resource: http://api.atmo-aura.fr/api/v1/communes/XXX/indices/atmo?api_token=XXX&date_calcul=yesterday&echeance=1
    value_template: "{{ value_json.data[0].sous_indices[2].indice }}"
    json_attributes_path: "$.data[0].sous_indices[2]"
    json_attributes:
      - polluant_nom
      - concentration
  - platform: rest
    scan_interval: '06:00:00'
    name: Indice Ozone O3 du jour
    resource: http://api.atmo-aura.fr/api/v1/communes/XXX/indices/atmo?api_token=XXX&date_calcul=yesterday&echeance=1
    value_template: "{{ value_json.data[0].sous_indices[3].indice }}"
    json_attributes_path: "$.data[0].sous_indices[3]"
    json_attributes:
      - polluant_nom
      - concentration
  - platform: rest
    scan_interval: '06:00:00'
    name: Indice Dioxyde d'azote No2 du jour
    resource: http://api.atmo-aura.fr/api/v1/communes/XXX/indices/atmo?api_token=XXX&date_calcul=yesterday&echeance=1
    value_template: "{{ value_json.data[0].sous_indices[4].indice }}"
    json_attributes_path: "$.data[0].sous_indices[4]"
    json_attributes:
      - polluant_nom
      - concentration

Ce qui me permet de récupérer ce qui m’intéresse et j’ai crée un dashboard comme ceci :

type: vertical-stack
cards:
  - type: custom:mod-card
    style:
      .: |
        :host {
          --text-divider-color: rgb(68, 115, 158);
          --text-divider-line-size: 1px;
          --border-width: 0px !important;
        }
    card:
      type: custom:text-divider-row
      text: Indice global du jour
      align: center
  - type: custom:flex-table-card
    entities:
      include:
        - sensor.indice_global_du_jour
    columns:
      - data: qualificatif
        name: ' '
        align: center
  - type: gauge
    min: 0.5
    max: 6.5
    needle: true
    segments:
      - from: 0.5
        color: blue
      - from: 1.5
        color: green
      - from: 2.5
        color: yellow
      - from: 3.5
        color: orange
      - from: 4.5
        color: '#db4437'
      - from: 5.5
        color: purple
    name: ''
    entity: sensor.indice_global_du_jour
  - type: custom:mod-card
    style:
      .: |
        :host {
          --text-divider-color: rgb(68, 115, 158);
          --text-divider-line-size: 1px;
          --border-width: 0px !important;
        }
    card:
      type: custom:text-divider-row
      text: Indices
      align: center
  - type: custom:auto-entities
    card:
      type: grid
      columns: 4
      square: true
    card_param: cards
    filter:
      include:
        - entity_id: sensor.indice_*
          attributes: ''
          options:
            type: custom:button-card
            color_type: icon
            show_name: true
            show_state: false
            style: |
              ha-card {
                background: none;
                box-shadow: #ccffcc;
                border-width: 0px;
              }
            styles:
              card:
                - height: 100px
                - width: 100px
              name:
                - font-size: 14px
            state:
              - value: '1'
                color: blue
                icon: mdi:rectangle
              - value: '2'
                operator: '=='
                color: green
                icon: mdi:rectangle
              - value: '3'
                operator: '=='
                color: yellow
                icon: mdi:rectangle
              - value: '4'
                operator: '=='
                color: orange
                icon: mdi:rectangle
              - value: '5'
                operator: '=='
                color: red
                icon: mdi:rectangle
              - value: '6'
                operator: '=='
                color: purple
                icon: mdi:rectangle
            size: 30%
            name: |
              [[[
               return entity.attributes.polluant_nom
              ]]]
      exclude:
        - entity_id: sensor.indice_dioxyde_d_azote_no2_de_demain
        - entity_id: sensor.indice_global_*
        - entity_id: sensor.indice_dioxyde_de_soufre_so2_de_demain
        - entity_id: sensor.indice_ozone_o3_de_demain
        - entity_id: sensor.indice_particules_fines_pm10_de_demain
        - entity_id: sensor.indice_particules_fines_pm2_5_de_demain
    sort:
      method: state
      reverse: true
      ignore_case: true
      numeric: false

Dans la formule il y a mentionné yesterday&echeance1 car avec now&echeance0 j’ai des problèmes de récupération

Si cela peut aider

Merci pour ton messages et les infos mais comment fait pour la partie api_token

Dans leur documentation, c’est écrit que ce token n’est valide que 6h , …

Bonjour,
Le mien est valable tout le temps après inscription il me semble

Merci !
J’ai compris, tu n’utilise pas le site français mais celui de rhone-alpes ( api.atmo-aura.fr )

Ça me dérange pas étant moi-même dans cette région :slight_smile:

Et oui, sur ce site, le token n’expire pas tous les heure et semble être valide longtemps.

Par contre, pour info, les données retourner par les api avec yesterday&echeance1 et now&echeance0 ne sont pas identique (sûrement car hier c’était une estimation et là, c’est des vrais mesure ?)

Ce site est encore mieux que le site français car il donne aussi les valeurs en µg/m³ (et pas seulement un indice), du coup, je vais pouvoir enregistrer ces infos dans un influxdb par la suite …

Si ça peut servir, j’ai convertir les 6 requêtes rest en une seul via le multiscrape et aussi rajouter les device_class qui vont bien (mais j’ai pas trouver le device classe pour le Dioxyde de soufre ) ( la liste est là : Sensor Entity | Home Assistant Developer Docs ) et rajouter un attribut label pour afficher en mode texte le niveau de pollution.

Mon dashbard crée est de type markdown et j’affiche 2 villes :

home assistant qualite air

Code Multiscrape :

Le code est relativement long a cause de l’implementation des indices de pollution « en mode texte »

# TODO : utiliser today&echeance=0
# Et si data[] est vide (le matin)  ( aka value_json.data[0] n'hexiste pas, il faut utiliser yesterday&echeance=1
- name: Qualité de l'air ville1
  resource: http://api.atmo-aura.fr/api/v1/communes/XXXXX/indices/atmo?api_token=YYYYYY&date_calcul=yesterday&echeance=1
  scan_interval: 86400
  button:
    - unique_id: air_qualite_ville1_refresh
      name: Qualite Air Refresh
  sensor:
    - unique_id: air_qualite_ville1_indice_global
      name: Qualite Air Indice global du jour
      value_template: "{{ value_json.data[0].indice }}"
      attributes:
        - name: Qualificatif
          value_template: "{{ value_json.data[0].qualificatif }}"
        - name: Date
          value_template: "{{ value_json.data[0].date_calcul }}"
      icon: mdi:air-filter
    - unique_id: air_qualite_ville1_pm2.5
      name: Particules fines PM2.5
      device_class: PM25
      unit_of_measurement: µg/m³
      value_template: "{{ value_json.data[0].sous_indices[0].concentration }}"
      icon: mdi:air-filter
      attributes:
        - name: indice
          value_template: "{{ value_json.data[0].sous_indices[0].indice }}"
        - name: label
          value_template: >
            {% set value = value_json.data[0].sous_indices[0].indice %}
            {% if (value == 0) %}
              Indisponible
            {% elif (value == 1) %}
              Bon
            {% elif (value == 2) %}
              Moyen
            {% elif (value == 3) %}
              Dégradé
            {% elif (value == 4) %}
              Mauvais
            {% elif (value == 5) %}
              Très mauvais
            {% elif (value == 6) %}
              Extrêmement mauvais
            {% elif (value == 7) %}
              Evénement
            {% else %}
              {{ value }}
            {% endif %}
    - unique_id: air_qualite_ville1_pm10
      name: Particules fines PM10
      device_class: PM10
      unit_of_measurement: µg/m³
      value_template: "{{ value_json.data[0].sous_indices[1].concentration }}"
      icon: mdi:air-filter
      attributes:
        - name: indice
          value_template: "{{ value_json.data[0].sous_indices[1].indice }}"
        - name: label
          value_template: >
            {% set value = value_json.data[0].sous_indices[1].indice %}
            {% if (value == 0) %}
              Indisponible
            {% elif (value == 1) %}
              Bon
            {% elif (value == 2) %}
              Moyen
            {% elif (value == 3) %}
              Dégradé
            {% elif (value == 4) %}
              Mauvais
            {% elif (value == 5) %}
              Très mauvais
            {% elif (value == 6) %}
              Extrêmement mauvais
            {% elif (value == 7) %}
              Evénement
            {% else %}
              {{ value }}
            {% endif %}
    - unique_id: air_qualite_ville1_s02
      name: Qualite Air Dioxyde de soufre
      # device_class: ???
      unit_of_measurement: µg/m³
      value_template: "{{ value_json.data[0].sous_indices[2].concentration }}"
      icon: mdi:air-filter
      attributes:
        - name: indice
          value_template: "{{ value_json.data[0].sous_indices[2].indice }}"
        - name: label
          value_template: >
            {% set value = value_json.data[0].sous_indices[2].indice %}
            {% if (value == 0) %}
              Indisponible
            {% elif (value == 1) %}
              Bon
            {% elif (value == 2) %}
              Moyen
            {% elif (value == 3) %}
              Dégradé
            {% elif (value == 4) %}
              Mauvais
            {% elif (value == 5) %}
              Très mauvais
            {% elif (value == 6) %}
              Extrêmement mauvais
            {% elif (value == 7) %}
              Evénement
            {% else %}
              {{ value }}
            {% endif %}
    - unique_id: air_qualite_ville1_o3
      name: Qualite Air Ozone
      device_class: OZONE
      unit_of_measurement: µg/m³
      value_template: "{{ value_json.data[0].sous_indices[3].concentration }}"
      icon: mdi:air-filter
      attributes:
        - name: indice
          value_template: "{{ value_json.data[0].sous_indices[3].indice }}"
        - name: label
          value_template: >
            {% set value = value_json.data[0].sous_indices[3].indice %}
            {% if (value == 0) %}
              Indisponible
            {% elif (value == 1) %}
              Bon
            {% elif (value == 2) %}
              Moyen
            {% elif (value == 3) %}
              Dégradé
            {% elif (value == 4) %}
              Mauvais
            {% elif (value == 5) %}
              Très mauvais
            {% elif (value == 6) %}
              Extrêmement mauvais
            {% elif (value == 7) %}
              Evénement
            {% else %}
              {{ value }}
            {% endif %}
    - unique_id: air_qualite_ville1_no2
      name: Qualite Air Dioxyde d'azote
      device_class: NITROGEN_DIOXIDE
      unit_of_measurement: µg/m³
      value_template: "{{ value_json.data[0].sous_indices[4].concentration }}"
      icon: mdi:air-filter
      attributes:
        - name: indice
          value_template: "{{ value_json.data[0].sous_indices[4].indice }}"
        - name: label
          value_template: >
            {% set value = value_json.data[0].sous_indices[4].indice %}
            {% if (value == 0) %}
              Indisponible
            {% elif (value == 1) %}
              Bon
            {% elif (value == 2) %}
              Moyen
            {% elif (value == 3) %}
              Dégradé
            {% elif (value == 4) %}
              Mauvais
            {% elif (value == 5) %}
              Très mauvais
            {% elif (value == 6) %}
              Extrêmement mauvais
            {% elif (value == 7) %}
              Evénement
            {% else %}
              {{ value }}
            {% endif %}

- name: Qualité de l'air ville2
  resource: http://api.atmo-aura.fr/api/v1/communes/XXXXX/indices/atmo?api_token=YYYYYY&date_calcul=yesterday&echeance=1
  scan_interval: 86400
  button:
    - unique_id: air_qualite_ville2_refresh
      name: Qualite Air Refresh
  sensor:
    - unique_id: air_qualite_ville2_indice_global
      name: Qualite Air Indice global du jour
      value_template: "{{ value_json.data[0].indice }}"
      attributes:
        - name: Qualificatif
          value_template: "{{ value_json.data[0].qualificatif }}"
        - name: Date
          value_template: "{{ value_json.data[0].date_calcul }}"
      icon: mdi:air-filter
    - unique_id: air_qualite_ville2_pm2.5
      name: Particules fines PM2.5
      device_class: PM25
      unit_of_measurement: µg/m³
      value_template: "{{ value_json.data[0].sous_indices[0].concentration }}"
      icon: mdi:air-filter
      attributes:
        - name: indice
          value_template: "{{ value_json.data[0].sous_indices[0].indice }}"
        - name: label
          value_template: >
            {% set value = value_json.data[0].sous_indices[0].indice %}
            {% if (value == 0) %}
              Indisponible
            {% elif (value == 1) %}
              Bon
            {% elif (value == 2) %}
              Moyen
            {% elif (value == 3) %}
              Dégradé
            {% elif (value == 4) %}
              Mauvais
            {% elif (value == 5) %}
              Très mauvais
            {% elif (value == 6) %}
              Extrêmement mauvais
            {% elif (value == 7) %}
              Evénement
            {% else %}
              {{ value }}
            {% endif %}
    - unique_id: air_qualite_ville2_pm10
      name: Particules fines PM10
      device_class: PM10
      unit_of_measurement: µg/m³
      value_template: "{{ value_json.data[0].sous_indices[1].concentration }}"
      icon: mdi:air-filter
      attributes:
        - name: indice
          value_template: "{{ value_json.data[0].sous_indices[1].indice }}"
        - name: label
          value_template: >
            {% set value = value_json.data[0].sous_indices[1].indice %}
            {% if (value == 0) %}
              Indisponible
            {% elif (value == 1) %}
              Bon
            {% elif (value == 2) %}
              Moyen
            {% elif (value == 3) %}
              Dégradé
            {% elif (value == 4) %}
              Mauvais
            {% elif (value == 5) %}
              Très mauvais
            {% elif (value == 6) %}
              Extrêmement mauvais
            {% elif (value == 7) %}
              Evénement
            {% else %}
              {{ value }}
            {% endif %}
    - unique_id: air_qualite_ville2_s02
      name: Qualite Air Dioxyde de soufre
      # device_class: ???
      unit_of_measurement: µg/m³
      value_template: "{{ value_json.data[0].sous_indices[2].concentration }}"
      icon: mdi:air-filter
      attributes:
        - name: indice
          value_template: "{{ value_json.data[0].sous_indices[2].indice }}"
        - name: label
          value_template: >
            {% set value = value_json.data[0].sous_indices[2].indice %}
            {% if (value == 0) %}
              Indisponible
            {% elif (value == 1) %}
              Bon
            {% elif (value == 2) %}
              Moyen
            {% elif (value == 3) %}
              Dégradé
            {% elif (value == 4) %}
              Mauvais
            {% elif (value == 5) %}
              Très mauvais
            {% elif (value == 6) %}
              Extrêmement mauvais
            {% elif (value == 7) %}
              Evénement
            {% else %}
              {{ value }}
            {% endif %}
    - unique_id: air_qualite_ville2_o3
      name: Qualite Air Ozone
      device_class: OZONE
      unit_of_measurement: µg/m³
      value_template: "{{ value_json.data[0].sous_indices[3].concentration }}"
      icon: mdi:air-filter
      attributes:
        - name: indice
          value_template: "{{ value_json.data[0].sous_indices[3].indice }}"
        - name: label
          value_template: >
            {% set value = value_json.data[0].sous_indices[3].indice %}
            {% if (value == 0) %}
              Indisponible
            {% elif (value == 1) %}
              Bon
            {% elif (value == 2) %}
              Moyen
            {% elif (value == 3) %}
              Dégradé
            {% elif (value == 4) %}
              Mauvais
            {% elif (value == 5) %}
              Très mauvais
            {% elif (value == 6) %}
              Extrêmement mauvais
            {% elif (value == 7) %}
              Evénement
            {% else %}
              {{ value }}
            {% endif %}
    - unique_id: air_qualite_ville2_no2
      name: Qualite Air Dioxyde d'azote
      device_class: NITROGEN_DIOXIDE
      unit_of_measurement: µg/m³
      value_template: "{{ value_json.data[0].sous_indices[4].concentration }}"
      icon: mdi:air-filter
      attributes:
        - name: indice
          value_template: "{{ value_json.data[0].sous_indices[4].indice }}"
        - name: label
          value_template: >
            {% set value = value_json.data[0].sous_indices[4].indice %}
            {% if (value == 0) %}
              Indisponible
            {% elif (value == 1) %}
              Bon
            {% elif (value == 2) %}
              Moyen
            {% elif (value == 3) %}
              Dégradé
            {% elif (value == 4) %}
              Mauvais
            {% elif (value == 5) %}
              Très mauvais
            {% elif (value == 6) %}
              Extrêmement mauvais
            {% elif (value == 7) %}
              Evénement
            {% else %}
              {{ value }}
            {% endif %}
Code Dashboard Type markdown
type: vertical-stack
cards:
  - type: markdown
    content: >-
      Résultat pour le {{
      state_attr("sensor.air_qualite_ville1_indice_global","date") }} : 

      | Ville | Global | PM 2.5 | PM 10 | Dioxyde de soufre | Ozone | Dioxyde
      d'azote |

      |:---:|:---:|:---:|:---:|:---:|:---:|:---:|

      | ville1 | {{ state_attr("sensor.air_qualite_ville1_indice_global",
      "qualificatif") }} | {{ state_attr("sensor.air_qualite_ville1_pm2_5",
      "label") }} | {{ state_attr("sensor.air_qualite_ville1_pm10", "label")
      }} | {{ state_attr("sensor.air_qualite_ville1_s02", "label") }} | {{
      state_attr("sensor.air_qualite_ville1_o3", "label") }} | {{
      state_attr("sensor.air_qualite_ville1_no2", "label") }} |

      |  | | {{ states('sensor.air_qualite_ville1_pm2_5') }} | {{
      states('sensor.air_qualite_ville1_pm10') }} | {{
      states('sensor.air_qualite_ville1_s02') }} | {{
      states('sensor.air_qualite_ville1_o3') }} | {{
      states('sensor.air_qualite_ville1_no2') }} |

      | ville2 | {{
      state_attr("sensor.air_qualite_ville2_indice_global", "qualificatif")
      }} | {{ state_attr("sensor.air_qualite_ville2_pm2_5", "label") }} | {{
      state_attr("sensor.air_qualite_ville2_pm10", "label") }} | {{
      state_attr("sensor.air_qualite_ville2_s02", "label") }} | {{
      state_attr("sensor.air_qualite_ville2_o3", "label") }} | {{
      state_attr("sensor.air_qualite_ville2_no2", "label") }} |

      | | | {{ states('sensor.air_qualite_ville2_pm2_5') }} | {{
      states('sensor.air_qualite_ville2_pm10') }} | {{
      states('sensor.air_qualite_ville2_s02') }} | {{
      states('sensor.air_qualite_ville2_o3') }} | {{
      states('sensor.air_qualite_ville2_no2') }} |
    title: Qualité de l'air
  - type: entities
    entities:
      - entity: button.air_qualite_ville1_refresh
        name: Refresh ville1
      - entity: button.air_qualite_ville2_refresh
        name: Refresh ville2

Salut,
Il n’y a que les imbéciles qui ne changent pas d’avis parait il… Je retire donc une partie de mes [propos] (Qualité d'air - #68 par SebCaps)], ayant trouvé ,le temps l’envie et grandement aidé par le fabuleux tuto sur le dev d’une intégration, je me suis lancé dans le dev d’une intégration pour récupérer les données d’air Atmo.
Pour le moment il reste des coups de tournevis à donner, mais sont OK :

  • la configuration via l’interface (saisie des identifiants, du code postal (gestion du multi code)
  • création de 5 capteurs

L’Api n’est pas hyper bien documentée, mais je pars sur l’appel du endpoint 112 avec code INSEE et récupére les données du jour.
Si vous avez d’autres idées / souhait je suis preneur, dans la limite de mes capacités :wink:

Reste à faire => pas mal de tests, optimisation et savoir comment publier sur HACS…
J’espére fin de semaine prochaine pour une publication…
Stay tuned.

Un pt’it screen pour me rajouter un peu de pression et donner envie ;-)…

3 « J'aime »