I have the following template sensor that fetches an hourly forecast and returns the max temperature for the next few hours as its state:
- triggers:
- trigger: time_pattern
hours: 05
action:
- action: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.forecast_home
response_variable: response
sensor:
- name: "Max Morning Temp"
unique_id: max_morning_temp
device_class: temperature
unit_of_measurement: "°F"
state: >-
{{
response['weather.forecast_home'].forecast[1:6]
|selectattr('datetime', 'match', utcnow().strftime("%Y-%m-%d"))
|map(attribute='temperature')
|list
|max
}}
attributes:
future_temps: >-
{% set ns = namespace(stuff=[]) -%}
{% set temp_list =
response['weather.forecast_home'].forecast[1:6]
|selectattr('datetime', 'match', utcnow().strftime("%Y-%m-%d"))
-%}
{% for item in temp_list -%}
{%
set ns.stuff = ns.stuff + [
(item.datetime|as_datetime|as_local).strftime("%H:%M") ~ '=' ~
item.temperature ~ '°F'
]
%}
{% endfor -%}
{{ ns.stuff|list|join(', ') }}
I have three questions:
First, I’m repeating the same filter in both state:
and the attributes:
sections. Is there a way to filter response
into a variable and use that instead?
What I’d like to do is something like:
variables:
future_temps: >-
{{
response['weather.forecast_home'].forecast[1:6]
|selectattr('datetime', 'match', utcnow().strftime("%Y-%m-%d"))
}}
but response
is not available in that block.
Second, I’m wondering how to make it more robust, for example if the action fails. That one filter:
|selectattr('datetime', 'match', utcnow().strftime("%Y-%m-%d"))
is a bit of a sanity check to make sure I’m looking at today’s dates in the response
data. But what if the action (api call) fails? Or if the data is not what is expected? Should there be an availability:
that checks everything?
Note that if I change the key .forecast
to .x_forecast
(an invalid key) I get an excetpion in the logs and the state becomes unavailable
.
But if the match filter returns an empty list I get the following and the state is NOT updated.
2025-05-24 12:04:00.086 WARNING (MainThread) [homeassistant.helpers.template] Template variable warning: No aggregated item, sequence was empty. when rendering '{{
response['weather.forecast_home'].forecast[1:6]
|selectattr('datetime', 'match', utcnow().strftime("foo%Y-%m-%d"))
|map(attribute='temperature')
|list
|max
}}'
Is there a way to add a default()
?
Finally, is there any way to make testing faster? What I’m doing is changing my time_pattern
to:
- triggers:
- trigger: time_pattern
minutes: /1
And then reloading the template YAML. But, then I have to wait for the minute to come around. Would be nice if I could trigger it on a reload of the template YAML.
Update: Oddly, this works in a debug template but not in the template sensor.
In the sensor if I use selectattr('foo')
then it throws an exception in the logs but does NOT set the state to unavailable
.
availability: >-
{{
response['weather.forecast_home'].forecast[1:6]
|selectattr('datetime', 'match', utcnow().strftime("%Y-%m-%d"))
|selectattr('temperature')
|list
|count > 0
}}
Update 2: Oh, needed the defined
in the test:
availability: >-
{{
response['weather.forecast_home'].forecast[1:6]
|selectattr('datetime', 'match', utcnow().strftime("%Y-%m-%d"))
|selectattr('emperature','defined')
|list
|count > 0
}}
In a debug template it will return False with the dict key changed. Is that a bug?
Thanks,