Dynamically change update_interval

I have made a unit using a ESP32, a ultrasonic detector and a OLED display to help when parking the car in the garage. It works great but I would like to change update_interval for the sensor/display based on how close to zero the measured distance is. Have implemented a template sensor and set it to ‘1s’ or ‘10s’ based on criteria, but I am struggling to get ESPHome to accept how do I transfer this value to the ultrasonic update_interval setting for the sensor and display…

This example throws an error:

update_interval: !lambda |-
  return id(update_interval_var).state;

Any tips?

Did you ever figure this out?

I have a task where I want to poll a temperature measurement every 2 seconds or so when I’m paying attention to it, but stop polling when I don’t care. I was hoping that I’d at least be able to set a very long polling interval, but I’m having no luck at all. It looks like the update_interval is set in the constructor for Component and there are functions to change it, but they don’t seem to affect the already-running instance. I’ll continue poking around, but I feel like I’m going off in the weeds and there must be a better option. Anything in YAML or C++ would be fine.

Nope, gave up.

Yes, probably not possible to change after it has been constructed.
I am a novice, and was unsuccessful using any Lambda to set update_interval at all. Only way I can get it to not throw errors is using a parameter or Substitution.

In my example I was planning on checking for garage_door_open, and adjust update_interval based on that. Probably not elegant if you’d ask a professional programmer, but since this, at least in mye case, does not change more than once or twice a day, maybe one solution would be a controlled reboot with the new set of update_interval values?

I guess that would require a persistent variable for update_interval and being able to reboot via a command in the yaml. Not sure if that is even possible.

Okay, I’ll ask on Discord tomorrow. Thanks for the quick response.

1 Like

Love it or not, here’s what I did to solve my problem:

  • Create a dummy custom switch to control the timing behavior
  • Set a long update_interval to satisfy the require to have one, but not have it interfere unnecessarily
  • Create a separate “interval:” section to handle updates

Here’s what my YAML looks like:

switch:
  - platform: custom
    lambda: |-
      auto my_custom_switch = new MyCustomSwitch();
      App.register_component(my_custom_switch);
      return {my_custom_switch};
  
    switches:
      name: Monitor Temp
      id: monitor_temp

# Temp Sensor on D02/GPIO4
dallas:
  - pin: 4
    update_interval: 60min
    id: mbath_water_temp
    
# Individual sensors
sensor:
  - platform: dallas
    index: 0
    name: mbath_water_temp
    filters:
      - lambda: return x * (9.0/5.0) + 32.0;
    unit_of_measurement: "°F"
    accuracy_decimals: 2
    
interval:
  - interval: 2sec
    then:
      - if:
          condition:
            - switch.is_on: monitor_temp
          then:
            - component.update: mbath_water_temp
4 Likes

Yeah, would prefer a thumbs_up or someting for the ‘Like’ :+1:

‘Interval’ is probably what I was looking for.
Will try something like this when I get home from work:

substitutions:
  update_interval_fast: 1s
  update_interval_slow: 60s

...

display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    address: 0x3C
    id: esp32nodemcu01_display
    update_interval: ${update_interval_slow}
    lambda: |-
      if (id(esp32nodemcu01_ultrasonic).has_state()) {
      ...

sensor:
  - platform: ultrasonic
    trigger_pin: GPIO17
    echo_pin: GPIO16
    id: esp32nodemcu01_ultrasonic
    update_interval: ${update_interval_slow}
    internal: true
    filters:
      - filter_out: nan
    on_value:
        then:
          - if:
            ...

  - platform: template
    name: "Distance Measure"
    id: distance_report
    unit_of_measurement: "cm"
    icon: "mdi:tape-measure"
    lambda: |-
      return id(esp32nodemcu01_ultrasonic).state;
    filters:
      - filter_out: nan
      - lambda: return x * 100;
    update_interval: ${update_interval_slow}

...

binary_sensor:
  - platform: homeassistant
    name: "Garage door 1 is open"
    id: garage_door_1_open
    entity_id: binary_sensor.garage_door_2
    internal: true

...

interval:
  - interval: ${update_interval_fast}
    then:
      - if:
          condition:
            - lambda: 'return id(garage_door_1_open).state;'
          then:
            - component.update: esp32nodemcu01_ultrasonic
            - component.update: esp32nodemcu01_display

Thanks!

Works :slight_smile:
There is a dual sensor/display update each 60s in my case, but I can live width that.

Thanks again

1 Like

Excellent! Glad to help. I feel like there has to be a more elegant solution, but I’ve been away from C++ for too long :slight_smile:

Yes, this is the solution. OttoWinter has also suggested the same here. here
Although in his solution he recommends to define the initial interval as never and then define time intervals. I know I have had issues with using time intervals along with other things - the esp simply crashes , so dont know how best is it.

I know this is old but, I found a solution and I’d like to share:

I created an input boolean in Home Assistant to enable “high speed” update intervals for a power meter:

binary_sensor:
  - platform: homeassistant
    id: high_speed_update
    entity_id: input_boolean.high_speed_update
    on_state:
      - lambda: !lambda |-
          // This is to revert back to the default update interval when needed
          static uint32_t default_update_interval = id(my_sensor).get_update_interval();
          // 3000 = 3 secs = New "high speed" interval
          int update_interval = x ? 3000 : default_update_interval;

          id(my_sensor).set_update_interval(update_interval);
          id(my_sensor).call_setup();

I need to call call_setup because it will update the interval internally, depending on the sensor, this may have a side effect.

Changing the switch on the home assistant, it’ll configure the new interval and start updating faster, turning off, will revert.

What you could do is pull an input_number in from HA as well as the boolean to use to change the interval. Here’s an example of how I use it.

sensor:
  - platform: homeassistant
    id: grow_pump_duration
    internal: true
    accuracy_decimals: 0
    entity_id: input_number.grow_pump_duration

then I use it to set a delay to turn a switch off

...
    on_turn_on:
    - delay: !lambda 'return id(grow_pump_duration).state * 1000;'
    - switch.turn_off: relay