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?

1 Like

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
11 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!

4 Likes

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.

10 Likes

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
1 Like