How to use datetime from Home Assistant in ESPhome?

Is it possible to use the datetime from a sensor in Home Assistant in ESPhome?
So I have a sensor in Home Assistant that has an attribute datetime with the value: '2022-09-24T11:00:00+00:00'
I then import this sensor in ESPhome in the following way:

text_sensor:
  - platform: homeassistant
    id: datetime
    entity_id: sensor.WeahterPredictions
    attribute: datetime

I then try to print this on my e-paper with lambda as such:

display:
  - platform: waveshare_epaper
    cs_pin: 22
    dc_pin: 23
    busy_pin: 32
    reset_pin: 21
    model: 7.50in-hd-b
    update_interval: 30sec
    reset_duration: 2ms
    rotation: 90°
    lambda: |-
      it.strftime(75, 518, id(tm24), color_white, TextAlign::TOP_CENTER, "%B", id(timedate).state);

This generates an error while compiling:

error: no matching function for call to 'esphome::display::DisplayBuffer::strftime(int, int, esphome::display::Font*&, esphome::Color&, esphome::display::TextAlign, const char [3], std::__cxx11::string&)'
       it.strftime(75, 518, id(tm24), color_white, TextAlign::TOP_CENTER, "%B", id(timedate1).state);
                                                                                            ^

I understand that somehow I am using the wrong format in for strftime. But I cannot figure out what format to use in order use the datetime from Home Assistant and show different aspects of that datetime in different formats throughout the dispaly, without having to make a sensor for each format. I am trying to limit the number of sensors as ram is limited for the esp32

Any help would be greatly appreciated.

There may be multiple way of doing this, I half-a-beginnger but this is what I do for my nspanel >esphome

time:
  - platform: homeassistant
    id: homeassistant_time
    on_time:
      - seconds: 0
        minutes: /1
        then:
          - lambda: id(disp1).set_component_text_printf("Home.time", "%02i:%02i", id(homeassistant_time).now().hour, id(homeassistant_time).now().minute);
          - lambda: id(disp1).set_component_text_printf("Home.date", "%i-%02i-%02i", id(homeassistant_time).now().year, id(homeassistant_time).now().month, id(homeassistant_time).now().day_of_month);
    on_time_sync:
        then:
          - wait_until:
              switch.is_on: nextion_init
          - lambda: id(disp1).set_component_text_printf("Home.time", "%02i:%02i", id(homeassistant_time).now().hour, id(homeassistant_time).now().minute);
          - lambda: id(disp1).set_component_text_printf("Home.date", "%i-%02i-%02i", id(homeassistant_time).now().year, id(homeassistant_time).now().month, id(homeassistant_time).now().day_of_month);

‘home’ is my first /main page on the nextion

Thanks @vingerha, but that is just taking the time from Home Assistant (the time function). I need the datetime that is provided by the weahter forecast to be put in several different formats around my e-paper display.

For example I would like the date (which is a date anywhere in the future) and the month of that date and the name of the day of that date, on different places on the display. How I do it now is create three different text_sensors with that information. I would like to use one text_sensor that gets the datetime and then through strftime extract the date, day and month.

I know how to to do that with the current time:

it.strftime(75, 518, id(tm24), color_white, TextAlign::TOP_CENTER, "%B", id(ha_time).now()); -> which gives the month
it.strftime(75, 518, id(tm24), color_white, TextAlign::TOP_CENTER, "%d", id(ha_time).now()); -> which gives the date.
it.strftime(75, 518, id(tm24), color_white, TextAlign::TOP_CENTER, "%A", id(ha_time).now()); -> which gives the full day name

Now I would like to do the same yet not with id(ha_time).now(), but with sensor of HA that supplies the datetime, i.e. id(datetime).state

So far I have only seen examples with the current date, but not with random date.

Clear, I only looked at the title and less your sensor … sorry for that. Cannot help further as lack of time (to gain knowledge)
Here it mentions to use a sensor with time as numeric… maybe it helps
Help with time / string conversion : Esphome (reddit.com)

Thanks for the link. Exactly the same question and almost as usual the same solution. Do the formatting with HA and then sent it as a sensor over. No-one seems to be able to do it any other way.

sensor.WeahterPredictions

Is invalid. Entity ids are lower case.

Would that create the problem? I will try when i get back and can change this.
ESPhome seems to correct this automatically, at least according to the logs. But perhaps not with the strftime command.

Hey!!!
I’m using nspanel as you but I getthe wrong hour. same code as you… but insted of 23:16 I get 06:16. Is like I get +7 hours. My time zone is GMT-3 (Santiago, Chile)
any thougth?!

A thing from the past is that the device should be connected to HA (to get ha data)… so might be a stupid question but did you add it as a device to HA ?

EDIT, there was also another thing, add this to the ha time setup

timezone: UTC-3

might also be 03:00 instead of 3

I think the issue is that HA sends, besides the state, everything in json. So the values are actually json values. I haven’t found away yet to decode the json value to a normal value. It might work then.
I now just resort to having HA do all the conversion and send the values seperately to MQTT.

Going back to your first post. You print id(tm24) but I don’t see a definition of that id.

It is a reference to a font. I haven’t included that in the logs or scripts. But that part does work.

Sorry my mistake.

I had the same issue/question and couldn’t really find anything except for this post.
I did some more digging and found a workaround on this Reddit post

The workaround is working with substrings on the text_sensor instead of trying to convert it to a datetime, but like this person I also encountered some issues getting the substring to work, so I found a workaround for the workaround :upside_down:

I have a text_sensor in my ESPHome config which gets the next sunrise time from the PirateWeather integration in Home Assistant. Just the basic stuff here.

text_sensor:
  - platform: homeassistant
    id: sunrise
    entity_id: sun.sun
    attribute: next_rising
    internal: true
# 2023-03-27T05:33:35.358757+00:00

Next, in my display config, I create a new string based on the text_sensor state.
I then erase the first 11 characters from that string which gives me 05:33:35.358757+00:00. In my it.printf lamda for the display I perform a substring to keep the first 5 charasters, which gives exactly what I was looking for 05:33.

display:
  - platform: waveshare_epaper
    id: einkdisplay
    cs_pin: GPIO5
    dc_pin: GPIO19
    busy_pin: GPIO25
    reset_pin: GPIO26
    model: 5.83inv2
    rotation: 180
    update_interval: 10s
    reset_duration: 2ms
    lambda: |-
      std::string sunrise_time = id(sunrise).state;
      sunrise_time.erase(0, 11);
      it.printf(408, 246, id(font14), TextAlign::TOP_RIGHT, "%s", sunrise_time.substr(0,5).c_str());

The issue what both with the .erase() method and .substr() that I could not get it to work (ESP would not boot) if the first argument was something else than a 0. So sunrise_time.erase(3, 11) or sunrise.substr(12,17) would not work. That is why I both have an .erase() and .substr() in my display lambda.

But of course, I would prefer a more “decent” solution by working with datetimes or with the strftime function.

EDIT:
Because of timezones, I also had to implement another imo dirty workaround. In my display lambdas I also added following line to add “2” to the “hour” part of the string as my timezone currently is UTC+2 (and the text_sensor is in UTC+0).

sunrise_time[1] = (sunrise_time[1] + 2);

Luckily I do not have to worry about changing this again soon as we’ve changed to summer time today. I do hope to find a more permanent solution though else this is a problem for future me when winter time hits in October. :sweat_smile:

1 Like

I was not really satisfied with my previous solution so I looked into working with templates on Home Assistant as @vingerha mentioned in post #4 and it’s a lot easier and cleaner working with Home Assistant templates.

For everyone else stumbling upon this issue. I’ve added following code in my configuration.yaml file on Home Assistant.

template:
  - sensor:
      - name: "Sunrise time"
        unique_id: sunrise_time
        state: "{{ as_timestamp(state_attr('sun.sun', 'next_rising')) | timestamp_custom('%R') }}"
      - name: "Sunset time"
        unique_id: sunset_time
        state: "{{ as_timestamp(state_attr('sun.sun', 'next_setting')) | timestamp_custom('%R') }}"

Next, in my ESPHome yaml file, I’ve added 2 text sensors which fetches both those custom sensors from Home Assistant.

text_sensor:
  - platform: homeassistant
    id: sunrise
    entity_id: sensor.sunrise_time
    internal: true
  - platform: homeassistant
    id: sunset
    entity_id: sensor.sunset_time
    internal: true

At last, in the display config I have

display:
  - platform: waveshare_epaper
    id: einkdisplay
    cs_pin: GPIO5
    dc_pin: GPIO19
    busy_pin: GPIO25
    reset_pin: GPIO26
    model: 5.83inv2
    rotation: 180
    update_interval: 30s
    reset_duration: 2ms
    lambda: |-
      it.printf(408, 246, id(font14), TextAlign::TOP_RIGHT, "%s", id(sunrise).state.c_str());
      it.printf(420, 246, id(font14), TextAlign::TOP_LEFT, "%s", id(sunset).state.c_str());

If you forget the .c_str() on the state you will have some errors while running

4 Likes