Belgium weather provider: IRM / KMI (meteo.be)

- triggers:
    - trigger: time_pattern
      hours: /1
    - trigger: homeassistant
      event: start      
  actions:
    - action: weather.get_forecasts
      target:
        entity_id: weather.home
      data:
        type: daily
      response_variable: daily
  sensor:
    - name: "Voorspelde dagtemperatuur"
      unique_id: temperature_forecast_today
      state_class: measurement
      unit_of_measurement: "°C"
      state: >
        {% set forecast = result['weather.home'].forecast %}
        {% if forecast and forecast | length > 0 %}
          {{ forecast[0].temperature | round(0) }}
        {% else %}
          Forecast unavailable.
        {% endif %}
1 Like

Thanks but that’s not returning any data either. After a few minutes it goes to ‘Not available’ with an exclamation mark. Is there a way to capture the output of the template on the command line?

@Nick4 Ran it through the template editor and it returns UndefinedError: 'result' is undefined.

Edit: Turns out the editor doesn’t call services, so I ran it through Actions, then daily gets populated from what I can tell. The template output I get through Actions is this:

{% set daily = {"weather.home":{"forecast":[{"datetime":"2025-08-27","condition":"cloudy","condition_2":"partlycloudy","condition_evol":"one_way","precipitation_probability":0,"wind_bearing":180,"is_daytime":true,"text":"Vandaag is het gedeeltelijk bewolkt met in de voormiddag kans op hier en daar wat regen over het centrum en de zuidoostelijke landshelft. In de namiddag trekt deze zwakke regenzone weg en blijft het vrijwel overal droog. De maxima schommelen tussen 22 of 23 graden aan zee en op de Ardense hoogten en tot 27 graden in de Kempen. De wind is zwak uit het zuiden en wordt nadien matig uit zuidwest. Aan de kust steekt in de namiddag een zeebries op.","sunrise":"2025-08-27T06:49:00+02:00","sunset":"2025-08-27T20:38:00+02:00","temperature":25,"templow":18,"wind_speed":6,"precipitation":0},{"datetime":"2025-08-28","condition":"partlycloudy","condition_2":"cloudy","condition_evol":"one_way","precipitation_probability":50,"wind_bearing":225,"is_daytime":true,"text":"Mogen trekt een zwak koufront van west naar oost door het land waarbij er hier en daar wat regen kan vallen en het vaak bewolkt is. In het oosten blijft het nog vrij lang droog en vrij zonnig. Achter de storing wordt het in de namiddag vanaf het westen veelal droog met breder wordende opklaringen. Over het oosten echter kan de storing later in de namiddag en tegen de avond wat actiever worden met wat intensere buien en lokaal een donderslag. De maxima schommelen tussen 20 en 25 graden. De wind is meestal matig uit zuidwestelijke richtingen. Aan zee wordt de wind soms vrij krachtig achter de storing.","sunrise":"2025-08-28T06:50:00+02:00","sunset":"2025-08-28T20:36:00+02:00","temperature":23,"templow":18,"wind_speed":12,"precipitation":0},{"datetime":"2025-08-29","condition":"sunny","condition_2":"pouring","condition_evol":"one_way","precipitation_probability":100,"wind_bearing":180,"is_daytime":true,"text":"Vrijdagvoormiddag is het nog vrij zonnig en droog. Geleidelijk neemt de bewolking toe en in de namiddag trekt een neerslagzone van west naar oost over het land. Een onweer is niet uitgesloten. De maxima schommelen tussen 19 en 23 graden. De wind is matig uit zuid tot zuidwest.","sunrise":"2025-08-29T06:52:00+02:00","sunset":"2025-08-29T20:34:00+02:00","temperature":20,"templow":15,"wind_speed":20,"precipitation":4},{"datetime":"2025-08-30","condition":"partlycloudy","condition_2":"rainy","condition_evol":"one_way","precipitation_probability":100,"wind_bearing":225,"is_daytime":true,"text":"Zaterdag wordt het wisselend tot vaak zwaarbewolkt met kans op een plaatselijke bui. Tijdens de nacht wordt een actievere regenzone verwacht. De maxima liggen tussen 18 en 22 graden, bij een matige zuidwestenwind.","sunrise":"2025-08-30T06:53:00+02:00","sunset":"2025-08-30T20:32:00+02:00","temperature":22,"templow":14,"wind_speed":12,"precipitation":1},{"datetime":"2025-08-31","condition":"rainy","condition_2":null,"condition_evol":"stable","precipitation_probability":100,"wind_bearing":225,"is_daytime":true,"text":"Zondagochtend verlaat de regenzone snel ons land via het oosten. Daarachter wordt het wisselend bewolkt met kans op een lokaal buitje. De maxima schommelen rond 20 graden in het centrum van het land. De wind is matig tot soms vrij krachtig uit het zuidwesten.","sunrise":"2025-08-31T06:55:00+02:00","sunset":"2025-08-31T20:30:00+02:00","temperature":21,"templow":17,"wind_speed":12,"precipitation":1},{"datetime":"2025-09-01","condition":"sunny","condition_2":"pouring","condition_evol":"one_way","precipitation_probability":100,"wind_bearing":225,"is_daytime":true,"text":"Maandag en dinsdag blijft het licht wisselvallig met bewolkte periodes en opklaringen en enkele lokale buien. De maxima schommelen rond 20 graden in het centrum van het land.","sunrise":"2025-09-01T06:57:00+02:00","sunset":"2025-09-01T20:27:00+02:00","temperature":20,"templow":14,"wind_speed":12,"precipitation":1},{"datetime":"2025-09-02","condition":"partlycloudy","condition_2":"pouring","condition_evol":"one_way","precipitation_probability":100,"wind_bearing":225,"is_daytime":true,"text":"Maandag en dinsdag blijft het licht wisselvallig met bewolkte periodes en opklaringen en enkele lokale buien. De maxima schommelen rond 20 graden in het centrum van het land.","sunrise":"2025-09-02T06:58:00+02:00","sunset":"2025-09-02T20:25:00+02:00","temperature":20,"templow":13,"wind_speed":12,"precipitation":1}]}} %}

Yet when I run your code through the template editor after it still comes back with 'result' is undefined.

Update: when I change result to daily, it works as intended. Thanks!

1 Like

Hello, trying to display a rain radar, mine doesn’t seem to log :

Any idea what the issue could be ?
The entities seems to be ok :

but look like the image is not lading.
so I see this :

and my code :

          - type: heading
            heading: Rain RADAR
            heading_style: title
          - show_state: false
            show_name: false
            camera_view: live
            type: picture-entity
            entity: camera.radar_maison
            camera_image: camera.local_file_2
            image: /config/www/Camera-snapshots/doorbel-snapshot2.jpg

Many Thanks !

Can you pls share your code fir the rain radar part ?
Can’t figure out out to display the “live” view animation …
;-(

Many thanks

Hello, today the metro in Brussels will not have rain, though the icon shows rain :

      - type: vertical-stack
        cards:
          - type: custom:clock-weather-card
            entity: weather.maison_2
            tap_action:
              action: navigate
              navigation_path: /lenovo-m10-plus-meteo/0
            card_mod:
              style: |
                ha-card {
                  color: white;
                  background: black;
                  border: 0px;
                }

The entity weather.maison_2 is well provided by IRM / KMI but as tou can see shows cloudy in the top, and rain at the bottom …

The KMI website is not talking about any rain son, so where is this wrong information coming from ??

Many Thanks

Hello,

I can get your confusion about the weather conditions showing here. There are multiple things to keep in mind:

  1. The data is pulled from their app, not the website. It shouldn’t change anything, but sometimes it does.
  2. Home Assistant does not support two weather conditions per day (like you have on the IRM screenshot for Tuesday, tonight, and Wednesday). Therefore, only the first icon is taken into account. This is mentioned in the limitations section on the Github repository.
  3. Home Assistant has a limited number (15) of weather conditions that can be expressed. For example, there is no equivalent of the ‘partly cloudy with a bit of rain’ (like you have for Tuesday on the IRM screenshot). Because of this, I had to map the icons of the IRM to weather conditions supported by Home Assistant. The mapping is shown in a table on the Github repository.
  4. Different cards might show different icons for the same weather condition.

All of those things lead to what you observe. Taking Tuesday’s forecast as an example: Home Assistant only considers the first of the two icons on the IRM website. It maps it to a weather condition supported by Home Assistant (here rainy). Then, each card on your dashboard choose the icon to show. The default card shows clouds with small raindrops for rainy. The custom card at the top probably opted to just show raindrops for rainy.

The same logic applies for Wednesday: the icon is a bit different on the IRM website, but it also maps to rainy weather condition in Home Assistant.

Hope this helps you understand how it works :slight_smile:

Many thanks !!

Some news about this integration. A first version has been merged in Home Assistant Core 2025.10! Currently, the integration in Core only supports the weather entity. More features will be added in future versions, when I have some time.

Feel free to test the Core version if you can and provide feedback, either in Home Assistant Core issues for any bugs or here :slight_smile:

2 Likes

Thank you for this nice integration! I just tried the one from HA Core, it works well!

I just have two questions about the forecast:

  • (I think) I followed the documentation to get the forecast using this action:

    action:
      - service: weather.get_forecasts
        data:
          type: daily
        target:
          entity_id: weather.irmkmi
        response_variable: daily
    sensor:
      - name: Weather Forecast Daily
        unique_id: weather_forecast_daily
        icon: mdi:weather-cloudy
        state: "{{ daily['weather.irmkmi'].forecast[0].condition }}"
        attributes:
          forecast: "{{ daily['weather.irmkmi'].forecast }}"
          temp_today: "{{ daily['weather.irmkmi'].forecast[0].temperature }}"
    
    • Does it look correct?
    • When I look at the forecast attribute, it contains a list of dict: e.g. [{'datetime': '2025-10-13', 'condition': 'partlycloudy', (...))
    • But… inside a string: {{ states.sensor.weather_forecast_daily.attributes.forecast | typeof }} returns str.
    • In other words, I cannot use (...).attributes.forecast[0], but (...).attributes.temp_today is valid.
    • Note that with the weather from met.no, the forecast attribute is a list, not a string.
  • With temp_today, I have a good value in the morning, but not in the evening where it is None. Is it normal? Is it still possible to get the maximum temperature of the day even in the evening?

I’ve installed it on both my instances: one dockerised installation running on a rpi04 and a HASSOS setup running on a dedicated x64 system.

Both installed without issues and I could recover the existing entities, but because a lot of entities are not yet available, I had to revert to the HACS version, because some of the entities are used in automations and/or notifications.

Would be nice if the map changed to light/dark depending on sun above/below horizon

Hello,

It may be off-topic, but I have seen several people asking for relative humidity which is not provided by the IRM app API. However, for those lucky enough to live close from a IRM measurement station, it is possible to easily retrieve live data through the REST API by adding this to the configuration.yaml (this is for Ernage station, just change the station code to the one of the nearest station):

rest:
  - resource: "https://opendata.meteo.be/service/wfs?service=WFS&version=2.0.0&request=GetFeature&typeName=aws:aws_10min&outputFormat=application/json&cql_filter=code=6459&sortBy=timestamp+D&count=1"
    method: GET
    headers:
      User-Agent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
      Accept: "application/json"
    scan_interval: 300 # This is 5 minutes while server is updated every 10 minutes
    timeout: 30
    sensor:
      - name: "IRM_station_code"
        value_template: "{{ value_json.features[0].properties.code | int }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.code is not none }}"
      - name: "IRM_station_timestamp"
        value_template: "{{ value_json.features[0].properties.timestamp }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.timestamp is not none }}"
        device_class: timestamp
      - name: "IRM_station_temp_dry_shelter_avg"
        value_template: "{{ value_json.features[0].properties.temp_dry_shelter_avg | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.temp_dry_shelter_avg is not none }}"
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
      - name: "IRM_station_temp_grass_pt100_avg"
        value_template: "{{ value_json.features[0].properties.temp_grass_pt100_avg | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.temp_grass_pt100_avg is not none }}"
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
      - name: "IRM_station_temp_soil_avg"
        value_template: "{{ value_json.features[0].properties.temp_soil_avg | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.temp_soil_avg is not none }}"
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
      - name: "IRM_station_temp_soil_avg_5cm"
        value_template: "{{ value_json.features[0].properties.temp_soil_avg_5cm | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.temp_soil_avg_5cm is not none }}"
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
      - name: "IRM_station_temp_soil_avg_10cm"
        value_template: "{{ value_json.features[0].properties.temp_soil_avg_10cm | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.temp_soil_avg_10cm is not none }}"
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
      - name: "IRM_station_temp_soil_avg_20cm"
        value_template: "{{ value_json.features[0].properties.temp_soil_avg_20cm | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.temp_soil_avg_20cm is not none }}"
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
      - name: "IRM_station_temp_soil_avg_50cm"
        value_template: "{{ value_json.features[0].properties.temp_soil_avg_50cm | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.temp_soil_avg_50cm is not none }}"
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
      - name: "IRM_station_wind_speed_10m"
        value_template: "{{ value_json.features[0].properties.wind_speed_10m | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.wind_speed_10m is not none }}"
        unit_of_measurement: "m/s"
        device_class: wind_speed
        state_class: measurement
      - name: "IRM_station_wind_speed_avg_30m"
        value_template: "{{ value_json.features[0].properties.wind_speed_avg_30m | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.wind_speed_avg_30m is not none }}"
        unit_of_measurement: "m/s"
        device_class: wind_speed
        state_class: measurement
      - name: "IRM_station_wind_direction"
        value_template: "{{ value_json.features[0].properties.wind_direction | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.wind_direction is not none }}"
        unit_of_measurement: "°"
        state_class: measurement
      - name: "IRM_station_wind_gusts_speed"
        value_template: "{{ value_json.features[0].properties.wind_gusts_speed | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.wind_gusts_speed is not none }}"
        unit_of_measurement: "m/s"
        device_class: wind_speed
        state_class: measurement
      - name: "IRM_station_precip_quantity"
        value_template: "{{ value_json.features[0].properties.precip_quantity | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.precip_quantity is not none }}"
        unit_of_measurement: "mm"
        device_class: precipitation
        state_class: measurement
      - name: "IRM_station_humidity_rel_shelter_avg"
        value_template: "{{ value_json.features[0].properties.humidity_rel_shelter_avg | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.humidity_rel_shelter_avg is not none }}"
        unit_of_measurement: "%"
        device_class: humidity
        state_class: measurement
      - name: "IRM_station_pressure"
        value_template: "{{ value_json.features[0].properties.pressure | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.pressure is not none }}"
        unit_of_measurement: "hPa"
        device_class: atmospheric_pressure
        state_class: measurement
      - name: "IRM_station_sun_duration"
        value_template: "{{ value_json.features[0].properties.sun_duration | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.sun_duration is not none }}"
        unit_of_measurement: "s"
        device_class: duration
        state_class: measurement
      - name: "IRM_station_short_wave_from_sky_avg"
        value_template: "{{ value_json.features[0].properties.short_wave_from_sky_avg | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.short_wave_from_sky_avg is not none }}"
        unit_of_measurement: "W/m²"
        device_class: irradiance
        state_class: measurement
      - name: "IRM_station_sun_int_avg"
        value_template: "{{ value_json.features[0].properties.sun_int_avg | float }}"
        availability: "{{ value_json.features is defined and value_json.features | count > 0 and value_json.features[0].properties.sun_int_avg is not none }}"
        unit_of_measurement: "W/m²"
        device_class: irradiance
        state_class: measurement

Description of the measurements are here:

Station codes are in page 12 of this document: