Change time of on_time trigger

Hi, I am making a travel day/night clock for my daughter. At the moment the times are hard coded and if we want to change them, i need to re-install the ymal. The idea is this clock comes traveling with us, so i want the ability to change the times vie the esphome’s device web server.

this the ymal file:


esphome:
  name: travel-day-nigh

esp8266:
  board: nodemcuv2

# Enable logging
logger:

web_server:
  port: 80

# Enable Home Assistant API
#api:

ota:
  password: "c48fbbc4253a683ec8df2f168952a9ab"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Travel-Day-Nigh Fallback Hotspot"
    password: "daynight"

captive_portal:

time:
  - platform: sntp
    id: sntptime
    on_time:
      - minutes: 0
        hours: 7
        then:
          - switch.turn_on: playtime
          - switch.turn_off: daytime
          - switch.turn_off: nighttime
          
      - minutes: 30
        hours: 7
        then:
          - switch.turn_on: daytime
          - switch.turn_off: playtime
          - switch.turn_off: nighttime
          
      - minutes: 15
        hours: 19
        then:
          - switch.turn_on: nighttime
          - switch.turn_off: playtime
          - switch.turn_off: daytime   
      
          
      
switch:
  - platform: gpio
    name: "DayTime"
    id: daytime
    pin: D3
    restore_mode: RESTORE_DEFAULT_OFF 
  - platform: gpio
    name: "PlayTime"
    id: playtime
    pin: D1
    restore_mode: RESTORE_DEFAULT_OFF 
  - platform: gpio
    name: "NightTime"
    id: nighttime
    restore_mode: RESTORE_DEFAULT_ON 
    pin: D2

binary_sensor:
  - platform: gpio
    pin: 
      number: D4
      mode:
        input: true
        pullup: true
    name: "set lighrs"
    filters:
      - delayed_off: 1s
    on_press:
      then:
        lambda: |-
          if ( id(i) == 1){
            id(nighttime).turn_on();
            id(playtime).turn_off();
            id(daytime).turn_off();
            id(i) = 2;
          }else if (id(i) == 2){
            id(nighttime).turn_off();
            id(playtime).turn_on();
            id(daytime).turn_off();
            id(i) = 3;
          }else {
            id(nighttime).turn_off();
            id(playtime).turn_off();
            id(daytime).turn_on();
            id(i) = 1;
          }
            
globals:
   - id: i
     type: int
     initial_value: '1'

is there away to allow using a number imput (or anything) to change these values with out connecting it to home assistant?

on_time:
      - minutes: 0
        hours: 7

Many Thanks

Unfortunately on_time trigger is not templatable - so no easy way.

You could trigger every hour, then compare an input_number with the current hour in the action’s lambda.

1 Like

Hi thanks for the advice, I am trying to do this and tried many thing, but keep getting this error:

My code currently looks like this: error: ISO C++ forbids comparison between pointer and integer

time:
  - platform: sntp
    id: sntptime
    on_time:
      - minutes: 1
        then:
        - lambda: |-
            char str_cur_hour[4];
            int int_cur_hour;
            std::time_t tz1time = id(sntptime).now().timestamp;
            std::tm *tz1time_astm = localtime(&tz1time);
            strftime(str_cur_hour, 6, "%H", tz1time_astm);
            int_cur_hour = std::stoi(str_cur_hour);
            if ( int_cur_hour > id(day_s_h) ){
              id(daytime).turn_on();
            }else{
              id(daytime).turn_off();
            }

number:
  - platform: template
    id: day_s_h
    name: "Day start hour"
    optimistic: true
    min_value: 0
    max_value: 24
    step: 1
    mode: box

I have also tried using strftime and just returning %H but get the same error.

How do i convert the time in to an int, so i can compare it?

Ok - I had a play - and from your other post figured you would probably want to also set the current timezone without re-compiling.

The following lets you set the daytime value from a drop-down on the ESP web interface as well as the offset for the current time zone. It then compares the current timezone hr and minute with the daytime setting and prints a log message.

esphome:
  name: webinterface

esp32:
  board: esp32dev
  framework:
    type: arduino
      
# Enable logging
logger:

# Enable Home Assistant API
api:

ota:
  password: xx

wifi:
 ssid: xx
 password: xx

captive_portal:
    
web_server:
  port: 80

globals:
   # you will need globals for any other alarm times
   - id: daytime_hr
     type: int
     restore_value: true
   - id: daytime_min
     type: int
     restore_value: true
   - id: tz_hr
     type: int
     restore_value: true
   - id: tz_min
     type: int
     restore_value: true

select:
  # I did the lists using Excel - slightly quicker doing some formulas and auto fill
  - platform: template
    name: "Current TZ select"
    restore_value: true
    optimistic: true
    options:
      - '-12:00'
      - '-11:45'
      - '-11:30'
      - '-11:15'
      - '-11:00'
      - '-10:45'
      - '-10:30'
      - '-10:15'
      - '-10:00'
      - '-09:45'
      - '-09:30'
      - '-09:15'
      - '-09:00'
      - '-08:45'
      - '-08:30'
      - '-08:15'
      - '-08:00'
      - '-07:45'
      - '-07:30'
      - '-07:15'
      - '-07:00'
      - '-06:45'
      - '-06:30'
      - '-06:15'
      - '-06:00'
      - '-05:45'
      - '-05:30'
      - '-05:15'
      - '-05:00'
      - '-04:45'
      - '-04:30'
      - '-04:15'
      - '-04:00'
      - '-03:45'
      - '-03:30'
      - '-03:15'
      - '-03:00'
      - '-02:45'
      - '-02:30'
      - '-02:15'
      - '-02:00'
      - '-01:45'
      - '-01:30'
      - '-01:15'
      - '-01:00'
      - '-00:45'
      - '-00:30'
      - '-00:15'
      - ' 00:00'
      - ' 00:15'
      - ' 00:30'
      - ' 00:45'
      - ' 01:00'
      - ' 01:15'
      - ' 01:30'
      - ' 01:45'
      - ' 02:00'
      - ' 02:15'
      - ' 02:30'
      - ' 02:45'
      - ' 03:00'
      - ' 03:15'
      - ' 03:30'
      - ' 03:45'
      - ' 04:00'
      - ' 04:15'
      - ' 04:30'
      - ' 04:45'
      - ' 05:00'
      - ' 05:15'
      - ' 05:30'
      - ' 05:45'
      - ' 06:00'
      - ' 06:15'
      - ' 06:30'
      - ' 06:45'
      - ' 07:00'
      - ' 07:15'
      - ' 07:30'
      - ' 07:45'
      - ' 08:00'
      - ' 08:15'
      - ' 08:30'
      - ' 08:45'
      - ' 09:00'
      - ' 09:15'
      - ' 09:30'
      - ' 09:45'
      - ' 10:00'
      - ' 10:15'
      - ' 10:30'
      - ' 10:45'
      - ' 11:00'
      - ' 11:15'
      - ' 11:30'
      - ' 11:45'
      - ' 12:00'
    initial_option: ' 10:00'
    # note leading space instead of + for positive offsets - there is an ESPhome bug that stops you using +
    on_value:
      then:
        lambda: |-
          id(tz_hr) = atoi(x.substr(0,3).c_str());
          id(tz_min) = atoi(x.substr(4,2).c_str());
          ESP_LOGD("main", "TZ Hr global value is: %d", id(tz_hr));
          ESP_LOGD("main", "TZ Min global value is: %d", id(tz_min));

  - platform: template
    name: "Daytime select"
    restore_value: true
    optimistic: true
    options:
      - '07:15'
      - '07:30'
      - '07:45'
      - '08:00'
      - '08:15'
      - '08:30'
      - '08:45'
      - '09:00'
      - '09:15'
      - '09:30'
      - '09:45'
      - '10:00'
      - '10:15'
      - '10:30'
      - '10:45'
      - '11:00'
      - '11:15'
      - '11:30'
      - '11:45'
      - '12:00' #etc
    initial_option: '07:30'
    on_value:
      then:
        lambda: |-
          id(daytime_hr) = atoi(x.substr(0,2).c_str());
          id(daytime_min) = atoi(x.substr(3,2).c_str());
          ESP_LOGD("main", "Daytime Hr global value is: %d", id(daytime_hr));
          ESP_LOGD("main", "Daytime Min global value is: %d", id(daytime_min));

time:
  - platform: sntp
    id: sntptime
    timezone: GMT
    # note specifically set GMT as timezone as we will calculate local time using offset
    on_time:
      - seconds: 0
        minutes: /1
        # note minutes: /1, not minutes: 1, the latter only does the first minute of each hour rather than every minute
        then:
        - lambda: |-
            char displaytz1[6];
            std::time_t tz1time = id(sntptime).now().timestamp+(60*60*id(tz_hr)+60*id(tz_min));
            std::tm *tz1time_astm = localtime(&tz1time);
            int tzhr = tz1time_astm->tm_hour;
            int tzmin = tz1time_astm->tm_min;
            ESP_LOGD("main", "Hour: %d", tzhr);
            ESP_LOGD("main", "Minute: %d", tzmin);
            if (id(daytime_hr) == tzhr && id(daytime_min) == tzmin) {
              ESP_LOGD("main", "Here I would have turned on output pin");
            };

Log output below - here I set the time zone to GMT+9.5 and the alarm time to 10:45. Ignore the time stamp on the left - that’s my local computer time.

Time	level	Tag	Message
11:12:00	[D]	[main:201]	
Hour: 10
11:12:00	[D]	[main:202]	
Minute: 57
11:12:15	[D]	[select:062]	
'Current TZ select' - Setting
11:12:15	[D]	[select:115]	
'Current TZ select' - Set selected option to:  09:30
11:12:15	[D]	[select:015]	
'Current TZ select': Sending state  09:30 (index 86)
11:12:15	[D]	[select:015]	
'Current TZ select': Sending state  09:30 (index 86)
11:12:15	[D]	[main:150]	
TZ Hr global value is: 9
11:12:15	[D]	[main:151]	
TZ Min global value is: 30
11:12:25	[D]	[select:062]	
'Daytime select' - Setting
11:12:25	[D]	[select:115]	
'Daytime select' - Set selected option to: 10:45
11:12:25	[D]	[select:015]	
'Daytime select': Sending state 10:45 (index 14)
11:12:25	[D]	[main:184]	
Daytime Hr global value is: 10
11:12:25	[D]	[main:185]	
Daytime Min global value is: 45
11:13:00	[D]	[main:201]	
Hour: 10
11:13:00	[D]	[main:202]	
Minute: 43
11:13:08	[D]	[esp32.preferences:114]	
Saving preferences to flash...
11:14:00	[D]	[main:201]	
Hour: 10
11:14:00	[D]	[main:202]	
Minute: 44
11:15:00	[D]	[main:201]	
Hour: 10
11:15:00	[D]	[main:202]	
Minute: 45
11:15:00	[D]	[main:204]	
Here I would have turned on output pin
1 Like

Actually I read the other post and you seem to have solved the timezone issue - but the rest of this is still relevant.

Edit: Also I just realised negative TZ values that don’t fall on the hour won’t work with my code - Doh! :slight_smile:

Further edit: If you didn’t get your timezones working I have a reasonable solution using timezonedb.com

The answer to this question is very interesting. I think from the conditions of time you need to refuse and create a binary sensor that will be turned on at a certain time. and automate the sensor.

Thanks Daryl, Thats is some impressive work.