Extracting values from weather.forecast_home

This must have been asked before, but my search skills have failed me.

Weather.home provides the following information:-

temperature: 6.5
temperature_unit: °C
humidity: 77
pressure: 990.2
pressure_unit: hPa
wind_bearing: 227.6
wind_speed: 13.3
wind_speed_unit: km/h
visibility_unit: km
precipitation_unit: mm
forecast:
  - condition: partlycloudy
    datetime: '2023-01-09T12:00:00+00:00'
    wind_bearing: 290.9
    temperature: 8.2
    templow: 4.6
    wind_speed: 33.1
    precipitation: 0
  - condition: rainy
    datetime: '2023-01-10T12:00:00+00:00'
    wind_bearing: 219.5
    temperature: 12.9
    templow: 4.9
    wind_speed: 30.2
    precipitation: 8.5
  - condition: rainy
    datetime: '2023-01-11T12:00:00+00:00'
    wind_bearing: 240
    temperature: 8.5
    templow: 6.8
    wind_speed: 31.7
    precipitation: 0.6
  - condition: rainy
    datetime: '2023-01-12T12:00:00+00:00'
    wind_bearing: 232.8
    temperature: 11.7
    templow: 8.4
    wind_speed: 29.9
    precipitation: 12.2
  - condition: cloudy
    datetime: '2023-01-13T12:00:00+00:00'
    wind_bearing: 242.4
    temperature: 10.1
    templow: 7.3
    wind_speed: 19.4
    precipitation: 0.4
attribution: >-
  Weather forecast from met.no, delivered by the Norwegian Meteorological
  Institute.
friendly_name: Forecast Home

Using states() and state_attr() I can easily get the top level attributes, but how would I get to the data in the forecast array.

When using (in dev tools):-

{{state_attr('weather.forecast_home','forecast')}}

returns a json array:-

[{'condition': 'partlycloudy', 'datetime': '2023-01-09T12:00:00+00:00', 'wind_bearing': 290.9, 'temperature': 8.2, 'templow': 4.6, 'wind_speed': 33.1, 'precipitation': 0.0}, {'condition': 'rainy', 'datetime': '2023-01-10T12:00:00+00:00', 'wind_bearing': 219.5, 'temperature': 12.9, 'templow': 4.9, 'wind_speed': 30.2, 'precipitation': 8.5}, {'condition': 'rainy', 'datetime': '2023-01-11T12:00:00+00:00', 'wind_bearing': 240.0, 'temperature': 8.5, 'templow': 6.8, 'wind_speed': 31.7, 'precipitation': 0.6}, {'condition': 'rainy', 'datetime': '2023-01-12T12:00:00+00:00', 'wind_bearing': 232.8, 'temperature': 11.7, 'templow': 8.4, 'wind_speed': 29.9, 'precipitation': 12.2}, {'condition': 'cloudy', 'datetime': '2023-01-13T12:00:00+00:00', 'wind_bearing': 242.4, 'temperature': 10.1, 'templow': 7.3, 'wind_speed': 19.4, 'precipitation': 0.4}]

So if I wanted to extract for example, the high and low temperature for the day, or if any of the forecast array elements contained rain ?

The idea is to extend my morning TTS to provide this information, which already does:-

Good Morning! The temperature is outside currently
{{state_attr('weather.forecast_home','temperature')}} degrees, and the
weather is forecast to be {{states('weather.forecast_home')}}

You are asking many different approaches so there will not be a single answer… can give you some of my stuff so you can think it over

-- max of various forecast values today
{{ (state_attr('weather.openweathermap', 'forecast')|selectattr('datetime', 'lt', (now().replace(hour=23,minute=59)).isoformat()))| map(attribute='temperature') | list | max }}
{{ ('temperature: -1.3 oc').split(': ',1)[1].split(' oc')[0] }}

-- value of weather attrib specific time
{% set tomorrow = (today_at('00:00') + timedelta(days=1)).strftime('%F') %}
{{ weather | selectattr('datetime', 'match', '^'~tomorrow) | selectattr('datetime', 'match', '^.*0(3|6):00') | map(attribute='precipitation_probability') | list }}

{{ (state_attr('weather.home', 'forecast')|selectattr('datetime', 'eq', (today_at('5:00').astimezone(utcnow().tzinfo) + timedelta (days=1)).isoformat())|list|first).temperature }}
1 Like

Here is an example of extracting it from the hourly data. Since the hourly data can span days, and I want the max / min for today. The first clause extract elements for todays date.


sensor:
  - platform: template
    sensors:
      weather_forecast_high:
        unit_of_measurement: "°F"
        value_template: >-
          {{ state_attr('weather.home_hourly','forecast') |
             selectattr('datetime', 'search', now().timestamp() | timestamp_custom('%Y-%m-%d')) | 
             map(attribute='temperature') | max
          }}
        device_class: temperature
      weather_forecast_low:
        unit_of_measurement: "°F"
        value_template: >-
          {{ state_attr('weather.home_hourly','forecast') |
             selectattr('datetime', 'search', now().timestamp() | timestamp_custom('%Y-%m-%d')) | 
             map(attribute='temperature') | min
          }}
        device_class: temperature
      weather_current_condition:
        value_template: >-
          {{ state_attr('weather.home_hourly','forecast') |
             selectattr('datetime', 'search', now().timestamp() | timestamp_custom('%Y-%m-%d')) | 
             map(attribute='condition') | first
          }}

Thanks both.

I’m familiar with using split to break apart strings, I was wondering if there was a more elegant way given its json.

Map however is new to me (as is most jinja2 stuff!), which looks interesting.

ok map and selectattr are seriously useful. I didn’t expect to get the answer for whether its going to rain or not today so easily:-

{% set will_rain = state_attr('weather.forecast_home','forecast') | selectattr('condition','equalto','rainy') | map(attribute='condition') | first
%}

{{will_rain}}

The only issue I have is that if the json array doesn’t contain the word ‘rainy’, I get this error:-

UndefinedError: No first item, sequence was empty.

How would I go about handling that exception ? Basically I want will_rain to be true if the word rainy is in that json array, or false if not.

That is an excellent question. I do not know. Hopefully someone does. I have the same problem when the hourly forecast no longer contains data for today and it Is still today (11 pm).

I’m not sure if jinaj2 has proper exception handling, but I managed to get around the issue like so:-

set will_it_rain = state_attr('weather.forecast_home','forecast') | selectattr('condition','equalto','rainy') | list
%}
{% if will_it_rain  is defined and will_it_rain %}
It will rain
{% else %}
No Rain
{%endif%}

2 Likes

This is my current final version using @PeteRage script heavily as the basis, with some additional if statements to avoid when no data is avaialable.

I use this as part of a google TTS speech in the morning:-

      msg: >-
        Good Morning! The temperature outside is currently
        {{state_attr('weather.forecast_home_hourly','temperature')}} degrees, 
        {%set highof = state_attr('weather.forecast_home_hourly','forecast') |      
        selectattr('datetime', 'search', now().timestamp() | timestamp_custom('%Y-%m-%d')) | map(attribute='temperature') | max %}
        {% if highof is defined and highof %}
        with a high of {{highof}} degrees
        {%endif%}
        {%set lowof = state_attr('weather.forecast_home_hourly','forecast') |   
        selectattr('datetime', 'search', now().timestamp() | timestamp_custom('%Y-%m-%d')) | map(attribute='temperature') | min %}
        {% if lowof is defined and lowof %}
        with a low of {{lowof}}
        {%endif%}
        .The weather is forecast to be
        {{states('weather.forecast_home_hourly')}} 
        {%set check_for_rain = state_attr('weather.forecast_home_hourly','forecast') |
        selectattr('datetime', 'search', now().timestamp() | timestamp_custom('%Y-%m-%d')) | selectattr('condition','equalto','rainy') | list%}
        {% if check_for_rain is defined and check_for_rain %} and rainy. {% else %} with no rain.
        {%endif%}The house is currently
        {{state_attr('climate.main_house','current_temperature')}} degrees.

3 Likes

You can access any value by using


{{ state_attr('weather.forecast_home','forecast')[0]['templow'] }}

where [0] represents the first list entry.

6 Likes

how do I use this code?

You don’t. The weather integration has changed and the earlier posts no longer apply.

Read all of this:

and if you still need help, start a new topic explaining which weather integration you’re using and what you’re trying to achieve.

2 Likes