That’s a string representation of a state object. The only deprecation is the forecast attribute. Meaning, only the forecast.
It’s my understanding that only the forecast
attribute will be eliminated. The rest of it will continue to exist and be periodically updated by your chosen weather integration.
Ninja’d by petro.
I have a Markdown Card, the first line reading:
{% set forcast = state_attr( 'weather.city_hourly_forecast', 'forecast' ) %}
From that point, I can get forcast[0]-[23]
and everything is rainbows and unicorns.
How do I get/make that first line 5 months from now?
Thank you,
MrGrey.
Use the example in the documentation for Trigger-based Template Sensor.
Trigger-based handling of service response data
Assuming you name the new Trigger-based Template Sensor sensor.city_hourly_forecast
then your Markdown card will use:
{% set forcast = state_attr( 'sensor.city_hourly_forecast', 'forecast' ) %}
Thank you, it’s working perfectly.
For anyone following along, placing the example code in VSCode produced a warning.
I ignored the warning and everything works great. I suspect some validation stuff in VSCode needs updating.
Thank you again,
MrGrey.
If someone still uses a third party weather card that was not updated yet, you can find here template sensors that you can copy and adapt:
They provides the forecast as state attributes and also forward the normal state attributes.
Hi,
As a worked example, here’s my update to my previous code query above.
Old
service: tts.google_say
data:
entity_id: media_player.1234
message: >-
Good morning.
It is {{ now().hour}} {{ now().minute }}
and the forecast is {{ states('weather.home') }}
New
action:
- service: weather.get_forecast
data:
type: daily
target:
entity_id: weather.home
response_variable: forecast_daily
- service: tts.google_say
data:
entity_id: media_player.1234
message: >-
Good morning. It is {{ now().hour}} {{ now().minute }}
The forecast is {{ forecast_daily.forecast[0].condition }}.
With a temperature of {{ forecast_daily.forecast[0].temperature|round(1) }}, wind speed of {{ forecast_daily.forecast[0].wind_speed|round(0) }}, and precip of {{ forecast_daily.forecast[0].precipitation|round(0) }}
At {{ as_timestamp(forecast_daily.forecast[0].datetime) | timestamp_custom('%H %M %A') }}
Notes
- The service call to
weather.get_forecast
using the default service seems to bring back six days of forecasts. - After some experimentation with loops, only the first is read out for brevity and
forecast_daily.forecast[0]
is used to get the first entry. - A few
round()
calls are used to make the numeric values easier to listen to. - The time and day of the forecast is read out at the end as a check that it is current (in case the service changes).
- The ability to call specific weather services and process different elements of the result is interesting, but less relevant in this “alarm clock” use-case.
Thanks to all who added to this discussion as many of your ideas and code snippets helped with this update!
Hi,
After banging my head against more deeply nested JSON returned by the newly changed 2023.12 weather.get_forecasts
(note the extra s
on get_forecast
s
), here’s an updated, updated implementation:
# weather.get_forecasts example service call and TTS template functions
action:
- service: weather.get_forecasts
data:
type: daily
target:
entity_id: weather.home
response_variable: forecast_daily
- service: tts.google_say
data:
entity_id: media_player.nesthub1234
message: >-
Good morning.
It is {{ now().hour}} {{ now().minute }} on {{ states('sensor.date_in_text') }}.
The forecast is {{ forecast_daily['weather.home']['forecast'][0].condition }}.
With a temperature of {{ forecast_daily['weather.home']['forecast'][0].temperature|round(1) }}, wind speed of {{ forecast_daily['weather.home']['forecast'][0].wind_speed|round(0) }}, and precip of {{ forecast_daily['weather.home']['forecast'][0].precipitation|round(0) }}
At {{ as_timestamp(forecast_daily['weather.home']['forecast'][0].datetime) | timestamp_custom('%H %M %A') }}
Hopefully by the time you read this post, the HASS docs will have been updated with the 2023.12 changes to weather.get_forecasts
. Last I checked, the PR was being reviewed in GitHub, and the docs are moving around so I can’t provide a link at the moment.
APIs get changed, designs don’t workout, but this one has become a bit of a pain.
Why the multiple nested brackets?
Old return format:
forecast:
- condition: rainy
New 2023.12 return format:
weather.home: <-- NEW: forecast location
forecast:
- condition: rainy
This suggests the service call can return forecasts for several different locations, hence the extra level of nesting.
If this helps, this post!
You should’ve just asked. We helped many people in beta transition to the new format. I suggest you check out the discord channel in the future.
I was also looking for this info and I’m unfortunately not a regular user of the Discord channels. It’s just too much info I can’t keep up with, given my day.
I truly think the release notes could’ve said just a little bit more than just “the schema changed”.
I think a number of people will trip over how to index the fields, because one can usually just use dot notation. It’s a done deal now (and not upset about it in any way), but if I caught this earlier I would’ve suggested to not use the entity ID, but just the slug part of it, e.g. forecast_daily.home.forecast...
. Now that I’ve written this, I realise you need to use the indexing notation anyway on lists, so maybe this is moot.
TBH, I usually do this:
action:
- variables:
target: weather.home
- service: weather.get_forecasts
data:
type: daily
target:
entity_id: "{{ target }}"
response_variable: raw
- variables:
forecast_daily: "{{ raw[target] }}"
or some derivation of that. So it never crossed my mind that you couldn’t use dot notation.
I’m sure it probably didn’t cross the dev’s mind either. This type of syntax is unique to Jinja, it’s not standard in python.
Hi,
i currently have a sensor for get the forcast with the service weather.get_forecast. How do i switch my attributes to work with weather.get_forecasts?
template:
- trigger:
- platform: time_pattern
minutes: "/1"
action:
- service: weather.get_forecast
target:
entity_id: weather.worms_worms
data:
type: daily
response_variable: forecast
sensor:
- name: Weather Forcast
unique_id: 6ef16182-4089-4f16-bbee-d4fc79722079
availability: "true"
icon: mdi:weather-cloudy-clock
state: "OK"
attributes:
weather_rain_today: >
{{ forecast.forecast[0].precipitation | round(1) }}
weather_temperature_today: >
{{ forecast.forecast[0].temperature | round(1) }}
weather_templow_today: >
{{ forecast.forecast[0].templow | round(1) }}
Why are you triggering every minute for a daily value?
...
sensor:
- name: Weather Forcast
unique_id: 6ef16182-4089-4f16-bbee-d4fc79722079
availability: "true"
icon: mdi:weather-cloudy-clock
state: "OK"
attributes:
weather_rain_today: >
{{ forecast['weather.worms_worms'].forecast[0].precipitation | round(1) }}
weather_temperature_today: >
{{ forecast['weather.worms_worms'].forecast[0].temperature | round(1) }}
weather_templow_today: >
{{ forecast['weather.worms_worms'].forecast[0].templow | round(1) }}
Thank you! And you are right make no sense to update it every minute. Currently only a test setup
Right I’m still confused and don’t see an example of how to reproduce my logic / workings. As I understand my configurations I have some logic that I use both in a template sensor and an automation, that evaluates the next 12 hours forecasts. The sensor records the lowest temperature for graphing / historical purposes. The automation does a point in time evaluation everynight as a prompt if I need to do things because of the temperature.
The sensor which records the lowest temp (don’t forget I’ve got 4 of these for each weather service).
- sensor:
- name: "12 hours ahead temp low onecall_hourly"
unit_of_measurement: "°C"
state:
"{% set next12hours = (as_timestamp(now() + timedelta(hours=12)) |
timestamp_utc) .replace(' ', 'T') ~ '+00:00' %} {% set today =
state_attr('weather.openweathermap_onecall_hourly', 'forecast') |
selectattr('datetime', 'lt', next12hours) | map(attribute='temperature') |
list %}
{{ today | min }}"
Then an automation on a daily schedule of 20:30 that sends a prompt to my phone giving me mins and max’s overnight.
service: notify.mobile_app_iphone_13_pro
data:
title: Tonights temperature
message: >-
{% set tomorrow = (as_timestamp(now() + timedelta(hours=12)) |
timestamp_utc) .replace(' ', 'T') ~ '+00:00' %} {% set today =
state_attr('weather.openweathermap_onecall_hourly', 'forecast') |
selectattr('datetime', 'lt', tomorrow) | map(attribute='temperature') | list
%} Openweather says it is now
{{state_attr('weather.openweathermap_onecall_hourly', 'temperature')}} °C
outsid and they say the forecast for the next 12 hours today says it will be
max {{ today | max }} °C with a low of {{ today | min }} °C
data:
push:
interruption-level: time-sensitive
tag: daily-weather-update
sticky: "true"
I can’t see how I can reproduce this with the service calls etc?
This was my initial use case and reason for setting up and getting into HA in the first place some 2 years ago, and now I am looking to try and use some new weather integrations only to stumble across this and that my existing setup will stop working in 4 months.
Right another night and I’ve made progress, I even managed to use the new get_forcecasts, but I’m sure someone will tell me a better way of doing this.
New sensor
- trigger:
- platform: state
entity_id: weather.forecast_home
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.forecast_home
response_variable: hourly
sensor:
- name: Weather Forecasts Hourly New
unique_id: weather_forecasts_hourly_new
state: "{{ now().isoformat() }}"
attributes:
forecast: "{{ hourly['weather.forecast_home'].forecast }}"
And I can query it with
state:
"{% set next12hours = (as_timestamp(now() + timedelta(hours=12)) |
timestamp_utc) .replace(' ', 'T') ~ '+00:00' %} {% set today =
state_attr('sensor.weather_forecasts_hourly_new', 'forecast') |
selectattr('datetime', 'lt', next12hours) | map(attribute='temperature') |
list %}
{{ today | min }}"
The forecast seems to include a lot more data that before, so might look to limit its scope to the temperature for the next 12 hours.
THIS IS THE ANWER!!! Thanks! Undid all the “progress” in the latest releases making my things all work again…thanks!
When I test that template, it produces a result containing two instances of 00:00
If you want to add 12 hours to the current time and report the result as a UTC datetime string, you can simply do this:
{% set next12hours = (utcnow() + timedelta(hours=12)).isoformat() %}
Thanks, it wasn’t broken, but its less broken now!
Also I figured out how to limit the returned forecast items to a days worth, couldn’t just limit to the temperature, but its good enough for my use case.
forecast: "{{ (hourly['weather.forecast_home'].forecast)[:24] }}"
the :24 on the end was all I needed.
A small variation on creating one single forecast sensor, one can also create dedicated template sensors for each forecast element of interest. In the example below temperature
, wind_speed
and precipitation
. The data size of these sensors is kept minimal, as the forecast lists only contain the values for that sensor
- trigger:
- platform: state
entity_id:
- weather.Home57
action:
- service: weather.get_forecasts
data:
type: hourly
target:
entity_id: weather.home
response_variable: hourly
- variables:
hourly_forecast: "{{ hourly['weather.home'].forecast }}"
sensor:
- unique_id: weather_forecast_temp
name: Forecast temperature
unit_of_measurement: '°C'
state: "{{ hourly_forecast[0].temperature }}"
device_class: temperature
attributes:
time: "{{ hourly_forecast[0].datetime }}"
forecast: "{{ hourly_forecast | map(attribute='temperature') | list }}"
- unique_id: weather_forecast_wind_speed
name: weather Forecast wind speed
unit_of_measurement: 'km/h'
state: "{{ hourly_forecast[0].wind_speed }}"
device_class: wind_speed
attributes:
time: "{{ hourly_forecast[0].datetime }}"
forecast: "{{ hourly_forecast | map(attribute='wind_speed') | list }}"
- unique_id: weather_forecast_precipitation
name: weather Forecast precipitation
unit_of_measurement: 'mm'
state: "{{ hourly_forecast[0].precipitation }}"
device_class: precipitation
attributes:
time: "{{ hourly_forecast[0].datetime }}"
forecast: "{{ hourly_forecast | map(attribute='precipitation') | list }}"
`
these sensors have two attributes:
time
which is the forecast time of the first entryforecast
with the forecast values per hour
In the dev tools it then looks like this:
Best Eric
Note: removing the attributes from the weather sensor I can understand, but deprecating weather.get_forecast
caused me a lot of extra work, and seems just a variation of weather.get_forecasts
with a single entity.