Weather in ESPHome

Hi, all.

I am trying to figure out how to use weather from Home Assistant in ESPHome. I have read many threads on here, including:

I also visited the linked posts in those posts.

I am able to get the current conditions, but I am still not able to get anything from weather.forecast_home.forecast – that is, I can’t read any of the array.

I have tried loading this into my configuration.yaml file:

- platform: template
  sensors:
    wx_temp_low:
      friendly_name: "Today Low Temperature"
      value_template: >-
        {{ state_attr('weather.forecast_home','forecast')[0].templow }}
    wx_temp_high:
      friendly_name: "Today High Temperature"
      value_template: >-
        {{ state_attr('weather.forecast_home','forecast')[0].temperature }}

Then I added this to my ESPHome device file:

  - platform: homeassistant
    id: temp_low
    entity_id: sensor.wx_temp_low
    internal: True
  - platform: homeassistant
    id: temp_high
    entity_id: sensor.wx_temp_high
    internal: True

I tried printing that like this:

      it.printf(0,0,id(font_roboto_medium22), id(my_red), TextAlign::TOP_LEFT, "min/max: %.0f/%.0f", id(temp_low).state, id(temp_high).state);

But that does not work.

I tried using this value – {{ state_attr('weather.home', 'forecast')[0].temperature }} – like this, but this does not work either:

      it.printf(0,50,id(font_roboto_medium22), id(my_red), TextAlign::TOP_LEFT, "min/max: %.0f", {{ state_attr('weather.forecast_home', 'forecast')[0].templow }}, {{ state_attr('weather.forecast_home', 'forecast')[0].temperature }});

That complains about the curly braces, but when I remove those, I get an error that state_attr is not defined.

For the life of me, I cannot read anything under the weather.forecast_home.forecast array.

Can someone please point me in the right direction here?

Thanks.

try to take small steps

esphome

  1. display “text” print_on_screen: “hello world”
  2. declare a_variable: “hello world” & then print_on_screen: $a_variable
  • HA
  1. declare variable in HA + previous step
  2. adding multiple variables
  3. external source

the error “not defined” → it can be that you need to declare the variable on boot, aka “its a string” or number and some initial/default value (if/when no HA connection)

This project does it for an e-ink screen, and has working code that also prevents too frequent updates to limit e-ink refreshes.

The only adjustment needed is that you will need to change the use of the forecast attribute to a service call. That isn’t very hard to do. I can post an example once I’m behind my laptop.

Thanks @vso1 . I am able to read lots of variables and print them… it’s just the weather forecast array that I’m having trouble with.

Thanks Edwin … I have been looking at that project too. It is a very good example, and it is a project I would like to implement.

It looks like it’s not possible to access the array directly in ESPHome, but that you access the array in the HA configuration and in that file you export variables that ESPHome can read, then you read those variables in ESPHome.

I plan to buy a Waveshare e-ink display to do it, but for now I am trying to get the data out of HA and display it on my m5stack.

Weather forecast attributes are deprecated anyway. See here:

Yes, that is why I stated above it should be replaced with a service call. I did, I’ll post the code adjustments later. My iPad cannot copy/paste from Visual Code Server. It isn’t hard: you put an action in the template sensor to call the service, place the result in a variable (that holds the same data as the attribute) and use the variable where you would previously use the attribute.

1 Like

I’m still super new at this, and don’t yet understand a lot of this. In particular, I’m not yet familiar with service calls.

The end goal here is to have a display (I’m using an m5stack) showing a weather forecast.

I’m hoping to try again later tonight, adding the sensors to my HA config. Hopefully after that, I will be able to display data on the m5stack. And then I’ll start working on getting a better source for the data.

Just found out ESPHome can do service calls too if you enable it for that esp device.

That way you can have the esp call the service and parse the entire data on the ESP. But the weatherman approach works well too.

Thanks, I’ll look into that.

Well, I’m not figuring out how to do any service calls in ESPHome, but I’m not sure I need to. I’m finding lots of references to creating a sensor in HA that references the weather forecast, then using that in ESPHome.

I have added this code to my configuration.yaml file, but it errors out. The code I added is:

sensors:
  weather_fivedays:
    friendly_name: "Five day weather"
    value_template: >-
         {% set weather = {
            "sunny": "sunny",
            "clear-day": "clear-day", 
            "clear-night": "clear-night", 
            "cloudy": "cloudy", 
            "rainy": "rainy", 
            "sleet": "sleet", 
            "snow": "snow", 
            "wind": "wind", 
            "fog": "fog", 
            "partlycloudy": "partlycloudy", 
          } %}

            {% for state in states.weather.forecast_home.attributes.forecast[1:3] -%}

            {{ as_timestamp(state.datetime)| timestamp_custom("%a") }};{{state.templow}}-{{ state.temperature }}°;{{ state.precipitation }}in;{{ weather[state.condition] }}#
            
            {%- endfor %}

There are lots of examples on here of people using this code.

However, HA tells me that I have an error in the config:

Invalid config
The following integrations and platforms could not be set up:

sensors (Show logs)
Please check your config and logs.

Log files say indicate that: Setup failed for 'sensors': Integration not found.

Any idea how to fix this? I haven’t found it yet here on the forums, and I have not found a “Sensors” integration.

@Edwin_D can you share that example. Im not able to figure it out! Thanks!

Sorry I forgot to post the example. I was about to, and then the service was changed again, so I first had to change mine too so I would not post an outdated examlpe.

Below is the weatherman example I referenced to before, that still relies on the old attribute.

Below I posted the part about waether that I adjusted to use the service. From this you can tell the difference. I added an action to call the service, and I replaced state_attr('weather.valhalla_hourly', 'forecast') with hourly["weather.valhalla_hourly"].forecast in all places. Be sure to replace weather.valhalla_hourly with your own weather service that supports hourly predictions.

  - trigger:
      platform: time_pattern
      minutes: "/1"
    action:
      - service: weather.get_forecasts
        data:
          type: hourly
        target:
          entity_id: weather.valhalla_hourly
        response_variable: hourly
    sensor:
      - name: Weatherman Data
        state: "OK"
        attributes:
          weather_condition_now: >
            {% set cond_now = states('weather.valhalla_hourly') %}
            {% if states('sun.sun') == 'below_horizon' %}
                {% if cond_now == 'sunny' %} night {% elif cond_now == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond_now }} {% endif %}
            {% else %}
                {{ cond_now }}
            {% endif %}

          weather_condition_0: >
            {% set cond0 = hourly["weather.valhalla_hourly"].forecast[0].condition %}
            {% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
            {% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
            {% set cond0_time = as_timestamp(hourly["weather.valhalla_hourly"].forecast[0].datetime) %}
            {% if cond0_time < next_rising and next_rising < next_setting %}
                {% if cond0 == 'sunny' %} night {% elif cond0 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond0 }} {% endif %}
            {% else %}
                {{ cond0 }}
            {% endif %}
          weather_temperature_0: >
            {{ hourly["weather.valhalla_hourly"].forecast[0].temperature | round }}
          weather_timestamp_0: >
            {{ as_timestamp(hourly["weather.valhalla_hourly"].forecast[0].datetime) | timestamp_custom('%I') | int }} {{ as_timestamp(hourly["weather.valhalla_hourly"].forecast[0].datetime) | timestamp_custom('%p') }}

          weather_condition_1: >
            {% set cond1 = hourly["weather.valhalla_hourly"].forecast[1].condition %}
            {% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
            {% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
            {% set cond1_time = as_timestamp(hourly["weather.valhalla_hourly"].forecast[1].datetime) %}
            {% if cond1_time < next_rising and next_rising < next_setting %}
                {% if cond1 == 'sunny' %} night {% elif cond1 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond1 }} {% endif %}
            {% else %}
                {{ cond1 }}
            {% endif %}
          weather_temperature_1: >
            {{ hourly["weather.valhalla_hourly"].forecast[1].temperature | round }}
          weather_timestamp_1: >
            {{ as_timestamp(hourly["weather.valhalla_hourly"].forecast[1].datetime) | timestamp_custom('%I') | int }} {{ as_timestamp(hourly["weather.valhalla_hourly"].forecast[1].datetime) | timestamp_custom('%p') }}

          weather_condition_2: >
            {% set cond2 = hourly["weather.valhalla_hourly"].forecast[2].condition %}
            {% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
            {% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
            {% set cond2_time = as_timestamp(hourly["weather.valhalla_hourly"].forecast[2].datetime) %}
            {% if cond2_time < next_rising and next_rising < next_setting %}
                {% if cond2 == 'sunny' %} night {% elif cond2 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond2 }} {% endif %}
            {% else %}
                {{ cond2 }}
            {% endif %}
          weather_temperature_2: >
            {{ hourly["weather.valhalla_hourly"].forecast[2].temperature | round }}
          weather_timestamp_2: >
            {{ as_timestamp(hourly["weather.valhalla_hourly"].forecast[2].datetime) | timestamp_custom('%I') | int }} {{ as_timestamp(hourly["weather.valhalla_hourly"].forecast[2].datetime) | timestamp_custom('%p') }}

          weather_condition_3: >
            {% set cond3 = hourly["weather.valhalla_hourly"].forecast[3].condition %}
            {% set next_setting = as_timestamp(state_attr('sun.sun', 'next_setting')) %}
            {% set next_rising = as_timestamp(state_attr('sun.sun', 'next_rising')) %}
            {% set cond3_time = as_timestamp(hourly["weather.valhalla_hourly"].forecast[3].datetime) %}
            {% if cond3_time < next_rising and next_rising < next_setting %}
                {% if cond3 == 'sunny' %} night {% elif cond3 == 'partlycloudy' %} night-partly-cloudy {% else %} {{ cond3 }} {% endif %}
            {% else %}
                {{ cond3 }}
            {% endif %}
          weather_temperature_3: >
            {{ hourly["weather.valhalla_hourly"].forecast[3].temperature | round }}
          weather_timestamp_3: >
            {{ as_timestamp(hourly["weather.valhalla_hourly"].forecast[3].datetime) | timestamp_custom('%I') | int }} {{ as_timestamp(hourly["weather.valhalla_hourly"].forecast[3].datetime) | timestamp_custom('%p') }}

AH! You are doing all this in HA not ESPHome…that seems to be the only way but not really ideal. I was hunting for a way to just call HA, get this object and process it as I need there. It is so odd to me that they removed this array to make us remake it in templates. I dont get it…

As linked in a post above, you can do a service call and parse json in the esp, but the fact that some one had already posted a fully working axample made it easier.

If you want to parse at the ESP side, I would look for a rest call straight to the weather provider. The. it isn’t depending on HA at all.

Thanks for the replies, Edwin. I was finally able to get it working.