[PETITION] Don't delete the forecast attribute

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' ) %}
1 Like

Thank you, it’s working perfectly.

For anyone following along, placing the example code in VSCode produced a warning.

Weather

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.

1 Like

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!

1 Like

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_forecasts), 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, :heart: this post!

2 Likes

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. :slight_smile:

1 Like

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.

2 Likes

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) }}
2 Likes

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) }}
4 Likes

Thank you! And you are right make no sense to update it every minute. Currently only a test setup :wink:

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.

1 Like

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.

1 Like

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 entry
  • forecast 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.

Keeping those variations available causes a lot of confusion and frustration for new and less knowledgeable users… better to just rip the bandage off quickly.