feature-requests icon indicating copy to clipboard operation
feature-requests copied to clipboard

Deep sleep enter : make "until" templatable or add a set_time_until parameter

Open sduponch opened this issue 2 years ago • 10 comments

Describe the problem you have/What new integration you would like

I use an ESP32-S2 to control the power of a battery powered device using Home Assistant and a Calendar to turn off or turn on the device. To minimize consumption, i want to set the ESP32 in deep sleep mode until the start (or the end) of the next event using the internal RTC clock.

Please describe your use case for this integration and alternatives you've tried:

I tried to set the "until" parameter of deep_sleep.enter action using lambda but this parameter is not templatable. I searched to build a DeepSleepEnterAction using lambda code but i could not find any exemple, i saw interesting function like set_until(hh,mm,ss) but did not managed to use it.

Additional context

I saw another merged pull request for adding "deep sleep duration" as parameter of deep_sleep.enter function, maybe we should do something similar for until and time_id "set_until(time_id, hh, mm, ss)"

sduponch avatar Dec 23 '23 22:12 sduponch

The until: option is not templatable, but why would that even be useful? If you're going to try to calculate an end time, why not just calculate the duration instead?

ssieb avatar Dec 24 '23 00:12 ssieb

To not have to do the calculations, i get the start_time and the end_time directly from the event. In lambda code, i have to parse the dates to timestamp (but i did not find a function for that), then do the diff with now().

I tried something like that, but i prefere to not copy/paste the set_until(...) code in lamdba.

      - lambda: !lambda |-
            // Get only the HH:MM:SS part from "YYYY-MM-DD HH:MM:SS"
            ESP_LOGD("main", "Google calendar start_time %s", id(start_time).state.substr(11,8).c_str());
            ESP_LOGD("main", "Google calendar end_time %s", id(end_time).state.substr(11,8).c_str());
            int hh = 0;
            int mm = 0;
            int ss = 0;
            if(strcmp(id(enabled).state.c_str(), "off") == 0) {
              hh = atoi(id(start_time).state.substr(11,2).c_str());
              mm = atoi(id(start_time).state.substr(14,2).c_str());
              ss = atoi(id(start_time).state.substr(17,2).c_str());
            } else if(strcmp(id(enabled).state.c_str(), "on") == 0) {
              hh = atoi(id(end_time).state.substr(11,2).c_str());
              mm = atoi(id(end_time).state.substr(14,2).c_str());
              ss = atoi(id(end_time).state.substr(17,2).c_str());
            }
            ESP_LOGD("main", "Next wakeup at %d:%d:%d", hh, mm, ss);
            id(deepsleep).set_until(hh,mm,ss);
            //id(deepsleep).set_sleep_duration(....;
            //id(deepsleep).begin_sleep();

if until is templatable this should be something like this :

- deep_sleep.enter:
  id: deepsleep
  time_id: sntp_time
  until: !lambda return id(start_time).state.substr(11,8).c_str());

This is a bit more fancy.

Best regards, Sebastian.

sduponch avatar Dec 24 '23 08:12 sduponch

I managed to do a workaround via lamdba code using strptime for my use case.

      - lambda: !lambda |-
            ESP_LOGD("update_state_from_calendar", "Google calendar is %s", id(enabled).state.c_str());
            ESP_LOGD("main", "Google calendar start_time %s", id(start_time).state.c_str());
            ESP_LOGD("main", "Google calendar end_time %s", id(end_time).state.c_str());
            std::tm next_event_tm = {};

            if(strcmp(id(enabled).state.c_str(), "off") == 0) {
              strptime(id(start_time).state.c_str(), "%Y-%m-%d %H:%M:%S", &next_event_tm);
            } else if(strcmp(id(enabled).state.c_str(), "on") == 0) {
              strptime(id(end_time).state.c_str(), "%Y-%m-%d %H:%M:%S", &next_event_tm);
            }
            long int next = mktime(&next_event_tm) - id(sntp_time).now().timestamp;
            ESP_LOGD("main", "Next event in %ld seconds", next);
            id(deepsleep).set_sleep_duration(next * 1000);
            id(deepsleep).begin_sleep(false);

I do not understand what is the difference between duration sleep and RTC sleep then why RTC sleep require a time_id...

sduponch avatar Dec 28 '23 09:12 sduponch

If your enabled was a binary sensor, it would be easier. If by "RTC sleep" you mean the until: option, it has to calculate the duration from the given time, so it needs a time component. You don't have to specify the id, it will automatically use the configured one.

ssieb avatar Dec 28 '23 09:12 ssieb

I'd love to see this as well. I have a battery powered light sensor running off an esp32c3 and I want it to sleep all night when there is no lux value to report to extend battery life.

Instead of a simple until: !lambda 'return id(sunrise).state;' I have to manually calculate the time difference between time.now and sunrise and use that in sleep_duration. Annoying and ugly code.

voska avatar Feb 02 '24 11:02 voska

This would be very useful. I have a standard wake-up time that I'd like to change every now and then without having to recompile the firmware, by reading it from a HA sensor.

francodutch avatar Mar 24 '24 01:03 francodutch

until: !lambda 'return id(sunrise).state;' would be great for my bumblebee box monitors. They are only active during the day and I'd love to save as much battery as I could.

ZingPow avatar Apr 16 '24 07:04 ZingPow

Instead of a simple until: !lambda 'return id(sunrise).state;' I have to manually calculate the time difference between time.now and sunrise and use that in sleep_duration. Annoying and ugly code.

That should be a trivial subtract and multiply if you're using the sun component.

ssieb avatar Apr 16 '24 07:04 ssieb

So I'm stuck here. All I want to do is put an ESP32 device to sleep at sunset and wake it up at sunrise. I would think this is a common use case for solar powered devices.

text_sensor:

  • platform: sun name: NextSunrise id: NextSunriseTime type: sunrise
  • platform: sun name: NextSunset type: sunset
  • platform: homeassistant id: ha_next_sunrise name: ha_next_sunrise entity_id: sensor.sun_next_rising

time:

  • platform: homeassistant id: homeassistant_time

deep_sleep: id: big_snooze

sun: id: sun_component latitude: x° longitude: y°

on_sunset: then: - deep_sleep.enter: id: big_snooze

until: NextSunrise - would be the perfered as it would be the easiest

until: ha_next_sunrise - how do you get the 'string' for this

      until: "00:06:00"
      time_id: homeassistant_time

ZingPow avatar Apr 19 '24 18:04 ZingPow