OpenWeather supports different modes so you’d need to add another entry to support that. For example I have 2 OpenWeatherMap integration entries, one using onecall_daily
and the other with onecall_hourly
. The hourly forecasts are working for me with that hourly integration.
Well, happy it works for you but I ma still struggling You code is a great base but I cannot make it work.
template:
- trigger:
- platform: time_pattern
minutes: /1
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.domov
response_variable: hourly
weather:
name: weather_domov_weather
temperature_template: "{{ state_attr('weather.domov', 'temperature') }}"
humidity_template: "{{ state_attr('weather.domov', 'humidity') }}"
condition_template: "{{ state_attr('weather.domov', 'condition') }}"
forecast_hourly_template: "{{ hourly['weather.domov'].forecast }}"
This example is a bit non-sense as it just tries to duplicate the weather entity. But I need to do more tricks there later. This is jsut a base.
The big BUT is that I cannot get the forecast in the newly created entity. The Weather Card shows only current state. In developer tools in States also no forecast is shown.
And if run the service get_forecasts
I got an error I cannot explain myself
2024-04-05 14:45:21.915 INFO (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Running websocket_api script
2024-04-05 14:45:21.915 INFO (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Executing step call service
2024-04-05 14:45:21.915 ERROR (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Error executing script. Unexpected error for call_service at pos 1: dictionary update sequence element #0 has length 1; 2 is required
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 504, in _async_step
await getattr(self, handler)()
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 733, in _async_call_service_step
response_data = await self._async_run_long_action(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 696, in _async_run_long_action
return await long_task
^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/core.py", line 2542, in async_call
response_data = await coro
^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/core.py", line 2579, in _execute_service
return await target(service_call)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 971, in entity_service_call
single_response = await _handle_entity_call(
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 1043, in _handle_entity_call
result = await task
^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/weather/__init__.py", line 1075, in async_get_forecasts_service
converted_forecast_list = weather._convert_forecast(native_forecast_list)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/weather/__init__.py", line 722, in _convert_forecast
forecast_entry: dict[str, Any] = dict(_forecast_entry)
^^^^^^^^^^^^^^^^^^^^^
ValueError: dictionary update sequence element #0 has length 1; 2 is required
Any hints guys?
If I create sensor template instead of weather there is no issue to get forecast attribute filled by an array of forecast values. But that’s unusable for Weather Card of course.
I’m not arguing the benefits of this change, which there clearly are, but how convoluted its adoption is. Using the forecast
attribute of a weather integration made this seamless. Now, it requires manually analysing the structure of the weather.get_forecasts
response to know how to process it in the trigger-based sensors. The high friction of implementing this makes it certainly prone to mistakes and trial and error. Proof of this are the several threads with people tripping trying to get this working the new way.
By the way, what’s the reason for moving away from using attributes?
I am not a dev, but as I understand it, the main reason is to help keep the database as small as possible. The entity’s state object is saved to the database every time the state or an attribute updates. That means every time a weather
entity’s state goes from “cloudy” to “partlycloudy” or the temperature
attribute changes (which can happen multiple times an hour) the entire object, including the large forecast
attribute, is saved again, even though the values of the forecast haven’t changed since they only update hourly or daily based on their source integration.
I still have issues with this new way of getting the forecasts. This is my code and it results in a complete empty sensor:
- trigger:
- platform: time_pattern
hours: "/1"
- platform: homeassistant
event: start
action:
- service: weather.get_forecasts
data:
type: daily
target:
entity_id: weather.home
response_variable: daily
sensor:
- name: weathertomorrow
state: "{{ daily['weather.home'].forecast[1].temperature }}"
attributes:
date: "{{ as_timestamp(daily['weather.home'].forecast[1].datetime) | timestamp_custom('%-d') }}"
lowtemp: "{{ daily['weather.home'].forecast[1].templow }}"
percipitation: "{{ daily['weather.home'].forecast[1].precipitation_probability }}"
icon: "{{ daily['weather.home'].forecast[1].condition }}"
day: "{{ as_timestamp(daily['weather.home'].forecast[1].datetime) | timestamp_custom('%A') | upper }}"
month: "{{ as_timestamp(daily['weather.home'].forecast[1].datetime) | timestamp_custom('%B') }}"
I have tried the service call in developer tools and it gives this result:
weather.home:
forecast:
- datetime: "2024-04-07"
condition: partlycloudy
precipitation_probability: 0
wind_bearing: 202
is_daytime: true
text: ""
temperature: 19
templow: 10
wind_gust_speed: 50
wind_speed: 20
precipitation: 0
- datetime: "2024-04-08"
condition: lightning-rainy
precipitation_probability: 100
wind_bearing: 135
is_daytime: true
text: ""
temperature: 19
templow: 10
wind_speed: 12
precipitation: 6
- datetime: "2024-04-09"
condition: rainy
precipitation_probability: 100
wind_bearing: 225
is_daytime: true
text: ""
temperature: 13
templow: 13
wind_gust_speed: 80
wind_speed: 39
precipitation: 1
- datetime: "2024-04-10"
condition: sunny
precipitation_probability: 0
etc..
So what am I doing wrong?
It will contain data only after it’s triggered by either one of its two triggers. That means either by restarting Home Assistant or by waiting until the Time Pattern Trigger runs every hour (on the hour).
If you have restarted Home Assistant, or waited for more than an hour, and it still reports nothing, check the Log for errors.
You shouldn’t need to go into the attributes to get forecast information. They should be separate entities. The forecast attribute should only be for things like weather cards and voice responses.
Check your weather providers integration and look for forecast information as entities. Chances are, they exist now. I.e. still easy to access, just not in an attribute.
I see. If the weather integration supports it already, I should be able to feed off its new interval forecast entity, which will have the data already formatted.
I’m using OpenWeatherMap, which doesn’t have this yet, but good to know the above.
So I created my new weather forecast attribute sensor which works (thanks to the community):
template:
- trigger:
- platform: state
entity_id: weather.weather_met_no
- platform: homeassistant
event: start
- platform: event
event_type: event_template_reloaded
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.weather_met_no
response_variable: hourly
sensor:
- name: Weather metno Hourly Forecast
unique_id: weather_forecast_metno_hourly
state: "{{ states('weather.weather_met_no') }}"
attributes:
forecast: "{{ hourly['weather.weather_met_no'].forecast }}"
However, when I try to combine this new sensor into my optimised weather entity, the forecast is no longer populated (it was popuplated previously to 2024.04). What am I doing wrong?
weather:
- platform: template
name: "Weather optimised hourly"
condition_template: "{{ states('sensor.weather_local_merged') }}"
temperature_template: "{{ states('sensor.weather_local_temperature') | float}}"
humidity_template: "{{ states('sensor.weather_local_humidity')| int }}"
pressure_template: "{{ states('sensor.weather_local_sea_level_pressure')| float }}"
wind_speed_template: "{{ ( states('sensor.weather_local_wind_speed_avg') | float * 18 / 5 ) | round(2) }}"
wind_bearing_template: "{{ states('sensor.weather_local_wind_bearing_avg')| int }}"
visibility_template: "{{ states('sensor.weather_local_visibility')| float }}"
forecast_hourly_template: "{{ state_attr('sensor.weather_metno_hourly_forecast', 'forecast') }}"
When I put the hourly forecast
forecast_hourly_template: "{{ state_attr('sensor.weather_metno_hourly_forecast', 'forecast') }}"
in the dev tools template editor, I get a big array the entiry hourly forecast as a result, so that alone works, but it no longer does return the attributes in the new weather sensor - is that on purpose, so the forecast attributes are also no longer displayed even for template weather entities??
That should work and it’s the same way I finally got mine going. However, updating the sensor for first time was kind of weird, so I initially set a trigger of every 1 minute to ensure it did it soon enough. After verifying that the forecast was working again I then set the proper triggers.
Well, in fact I face the same problem as you and the “big array” you mentioned is probably not correct by my latest finding.
But still do no know how to move on.
My latest conclusion is that the integration is not ready for the new situation.
If I use Open Weather Map entity in my templates it works fine. If I use custom integration for Czech forecasts it does not work. And the “big array” looks different. The templates code is the same, only difference is source weather entity.
Ok, so having read all the replies and browsing the interweb a lot. I got myself a solution. A lot is repeat of earlier posts but I hope to add some gaps that made it hard for me to understand what I needed to do.
Situation: My goal is to have a sensor that shows the forecasted temperature of today. This to have logic on whether the shutters and skylight cover need to be closed for keeping the heat out. Or to have the sun help keep our heating bill low.
- So at first let’s be clear where we need to add these trigger template sensors. It has it’s own section so I added this line to my configurations.yaml
template: !include templates.yaml
- I created an actual templates.yaml in the home assistant home directory and added the following code:
- trigger:
- platform: time_pattern
hours: "/4"
- platform: state
entity_id: weather.huis
- platform: homeassistant
event: start
- platform: event
event_type: event_template_reloaded
action:
- service: weather.get_forecasts
data:
type: daily
target:
entity_id: weather.huis
response_variable: daily
sensor:
- name: "Today's Temperature"
state: "{{ daily['weather.huis'].forecast[0].temperature|float }}"
attributes:
forecast: "{{ daily['weather.huis'].forecast }}"
Important here is to use the weather.huis that is actually your weather entity. Mine is from buienradar.
The entity at first shows the full array as an attribute so there you can look for the available data and its position and key name. If it’s empty check whether the weather entity has daily, hourly or twice-daily data. Change it throughout the codesnippet.
For me the trick is to have the actual number I required in the state declaration of the sensor. So change that Where you can you use the array position (in between the [#] )and the key ( .temperature in my case) to get the right information you need. In the code above it’s the;
“{{ daily[‘weather.huis’].forecast[0].temperature|float }}”
The float is only necessary if you want an actual number.
And yes I know I went overboard on the events where in the service gets triggered, but I wanted to be sure.
- First time you have the templates.yaml created you need to restart home assistant. Afterwards a reload of the template entities from the developer page is enough.
Hope this helps a lot of you out.
There is a issue on github related to this: Weather template validation is too strict and/or NWS integration returns bad forecasts · Issue #114799 · home-assistant/core · GitHub
Streamlining is great and I love the HA project. I think feature upgrades should make everyone’s life easier, however this one clearly went into the opposite, you now need a bachelor’s degree to sort out the weather forecast, if possible at all.
Mistakes can happen, no problem. But I think it would be better from the responsible people to own and address this problem.
Is it a problem? Well, from a user point of view, clearly yes. So many people are struggling at this stage, which means to me either its not communicated well, or not documented well. Honestly, I think for this one, both is the case plus the template weather is currently not working either.
I really hope this is getting addressed with one of the next releases. Thanks for all the work that is been done - this upgrade needs some tweaks though
How do I use separate forecast entities in a template weather provider? Specifically, how do I use e.g. the 10 separate daily high/low temperature forecast entities that AccuWeather provides me, and squeeze them into the forecast_daily_template
of a custom weather provider?
That’s the correct structure. Template weather entities then expect:
forecast:
- condition: sunny
...
If I have gotten this correct the only way is by organizing the forecast data with the structure shown here. The template weather entity accepts a list of dictionaries with a predefined set of keys as shown on the linked table.
Existing weather integrations should respond to get_forecasts
with the data already formatted as such.
My sensor responses in exaclty this way with all the keys, example of the state itself (incl. formatting):
forecast:
- datetime: "2024-04-09"
condition: rainy
temperature: 21
templow: 6
precipitation: 8.7
- datetime: "2024-04-10"
condition: rainy
temperature: 10
templow: 5
precipitation: 2.3
However, when putting the sensor into the template the format is weird, the array is no longer structured (if that makes sense):
forecast_daily_template: "{{ state_attr('sensor.weather_daily_forecast', 'forecast') }}"
the response is this:
forecast_daily_template: "[{'datetime': '2024-04-09', 'condition': 'rainy', 'temperature': 21.0, 'templow': 7.0, 'precipitation': 8.7}, {'datetime': '2024-04-10', 'condition': 'rainy', 'temperature': 10.0, 'templow': 5.0, 'precipitation': 2.3}, {'datetime': '2024-04-11', 'condition': 'partlycloudy', 'temperature': 18.0, 'templow': 5.0, 'precipitation': 0.0}, {'datetime': '2024-04-12', 'condition': 'partlycloudy', 'temperature': 21.0, 'templow': 7.0, 'precipitation': 0.0}, {'datetime': '2024-04-13', 'condition': 'sunny', 'temperature': 25.0, 'templow': 9.0, 'precipitation': 0.0}, {'datetime': '2024-04-14', 'condition': 'sunny', 'temperature': 24.0, 'templow': 13.0, 'precipitation': 0.0}]"
→
you mentioned you got the template weather sensor up and running, can you post an example from the devtools using this?: forecast_daily_template: "{{ state_attr('sensor.weather_daily_forecast', 'forecast') }}"
Thank you
Ok, that is the structure that I explained above in Python terminology - a list of dictionaries (each dictionary is enclosed by { }
). Yaml represents that in a pretty-printed way. The only difference here is that the list itself is contained in a dictionary, under the forecast
key.
Now you have to extract the list and feed it to the template weather.
I get the expected dictionary, as you:
forecast_daily_template: "{{ state_attr('sensor.openweathermap_hourly_forecast', 'forecast') }}"
→
forecast_daily_template: "[{'condition': 'clear-night', 'precipitation_probability': 0, 'datetime': '2024-04-09T06:00:00+00:00', 'wind_bearing': 123, 'cloud_coverage': 0, 'temperature': 45, 'pressure': 30.12, 'wind_speed': 6.64, 'precipitation': 0.0, 'humidity': 58},...]"
For thoroughness, this my complete hierarchy:
get_forecasts response from OpenWeatherMap
service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.openweathermap
→
weather.openweathermap:
forecast:
- condition: cloudy
precipitation_probability: 0
datetime: "2024-04-09T06:00:00+00:00"
wind_bearing: 123
cloud_coverage: 100
temperature: 45
pressure: 30.12
wind_speed: 6.64
precipitation: 0
humidity: 62
- condition: cloudy
...
Poll the service and massage the response in the trigger-based template sensor
template:
- trigger:
- platform: time_pattern
hours: /1
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.openweathermap
response_variable: hourly_forecast
sensor:
- name: OpenWeatherMap Hourly Forecast
unique_id: openweathermap_hourly_forecast
state: "{{ now().isoformat() }}"
attributes:
forecast: "{{ hourly_forecast['weather.openweathermap'].forecast }}"
Feed the data to the template weather entity
weather:
- platform: template
unique_id: home_weather
name: Home Weather
condition_template: "{{ states('sensor.openweathermap_condition') }}"
temperature_template: "{{ states('sensor.temperature_sensor_air_temperature') }}"
temperature_unit: °F
humidity_template: "{{ states('sensor.temperature_sensor_humidity') }}"
wind_speed_template: "{{ states('sensor.openweathermap_wind_speed') }}"
wind_speed_unit: mph
wind_bearing_template: "{{ states('sensor.openweathermap_wind_bearing') }}"
forecast_hourly_template: "{{ state_attr('sensor.openweathermap_hourly_forecast', 'forecast') }}"
Ok, ive been using ha for a couple of years. Mostly im a homekit person but delve into ha when i need to do something complex. Not an expert but i get by. Never used templates before and got to say the old method was far more easier to get my head around than this one. Bit im stuck on is where do you initiate the template, ie is it directly into the yaml config files. I cant see any gui or intergration wizard that can do it, and under the debug menu its only got a place to try the template out.
yes, the template entities/sensors must be placed in the configuration.yaml and then reboot HA