Update scan interval of a sensor

Hi,

I tried updating the scan interval of my GET request because of max 10k requests per day.
I tried like so:

  - platform: rest
    name: 'Contact sensor Dog'
    resource: !secret switchbot_contact_sensor_dog_status_url
    method: GET
    scan_interval: >
        {% if is_state('switch.nofood', 'off') %}
          10
        {% else %}
          6000
        {% endif %}
    headers:
      Authorization: !secret switchbot_api
      Content-Type: 'application/json'
    value_template: '{{ value_json.body.openState }}'
    json_attributes_path: "$.body"
    json_attributes:
      - deviceId
      - deviceType
      - hubDeviceId
      - moveDetected
      - brightness
      - openState

which errors to:
Invalid config for [sensor]: offset {% if is_state('switch.nofood', 'off') %} 10 {% else %} 6000 {% endif %} should be format 'HH:MM', 'HH:MM:SS' or 'HH:MM:SS.F' for dictionary value @ data['scan_interval']. Got None. (See /config/configuration.yaml, line 317).

I also tried the following automation:

alias: Update dog sensor scan interval
description: ""
trigger:
  - platform: time_pattern
    seconds: "5"
condition: []
action:
  - service: homeassistant.update_entity
    data:
      scan_interval: 10
    target:
      entity_id: sensor.contact_sensor_dog
mode: single

But I do not see the value updated in the configuration.yaml and it also does not seem to be updated. It must be because the scan_interval is not an attribute.

Do you have any ideas how to make this work?

You can’t template or programmatically update the scan interval.

You are half way to the solution though.

Set a really long interval in the configuration (years). And use an automation to call the update entity service (without any data) when you want it to update. The trigger is the tricky part. Maybe something like this (untested):

trigger:
  platform: template
  value_template: >
    {% set secs = 10 if is_state('switch.nofood', 'off') else 6000 %}
    {{ now().timestamp()|int % secs == 0 }}
action:
  - service: homeassistant.update_entity
    target:
      entity_id: sensor.contact_sensor_dog

Though I think that template may only update every minute. If so, use a 10 second time pattern trigger and use that as a template condition instead.

trigger:
  platform: time_pattern
  seconds: "/10"
condition:
  condition: template
  value_template: >
    {% set secs = 10 if is_state('switch.nofood', 'off') else 6000 %}
    {{ now().timestamp()|int % secs == 0 }}
action:
  - service: homeassistant.update_entity
    target:
      entity_id: sensor.contact_sensor_dog

The sensor will be updated once after a restart though. If that is an issue there are ways around it (another condition that checks the uptime).

1 Like

Thank you you @tom_l for your prompt reply.
So I set scan_interval: 31556926 and tested with the first recommendation.
I switched the nofood to off and:

Triggered by the switch.nofood via template at April 3, 2023 at 10:14:40 PM
Home Assistant Core Integration: Update entity Contact sensor Dog
Finished at April 3, 2023 at 10:14:40 PM (runtime: 0.25 seconds)

changed variables:

this:
  entity_id: automation.update_dog_sensor_scan_interval
  state: 'on'
  attributes:
    last_triggered: '2023-04-03T20:13:00.126744+00:00'
    mode: single
    current: 0
    id: '1680541704962'
    friendly_name: Update dog sensor scan interval
  last_changed: '2023-04-03T20:12:32.765794+00:00'
  last_updated: '2023-04-03T20:13:00.393463+00:00'
  context:
    id: 01GX4C0RAY5299VT8TCX6RZSSN
    parent_id: null
    user_id: null
trigger:
  platform: template
  entity_id: switch.nofood
  from_state:
    entity_id: switch.nofood
    state: 'on'
    attributes:
      assumed_state: true
      friendly_name: nofood
    last_changed: '2023-04-03T20:14:18.827481+00:00'
    last_updated: '2023-04-03T20:14:18.827481+00:00'
    context:
      id: 01GX4C355Q5RV2V2ZY84MXAAA4
      parent_id: null
      user_id: cee1498fa5f546269368e2bc0d9d07b2
  to_state:
    entity_id: switch.nofood
    state: 'off'
    attributes:
      assumed_state: true
      friendly_name: nofood
    last_changed: '2023-04-03T20:14:40.701338+00:00'
    last_updated: '2023-04-03T20:14:40.701338+00:00'
    context:
      id: 01GX4C3THRQ3YXQ2BW6R0PFB42
      parent_id: null
      user_id: cee1498fa5f546269368e2bc0d9d07b2
  id: '0'
  idx: '0'
  alias: null
  for: null
  description: switch.nofood via template

What is this secs variable about? I renamed to scan_interval, but also no luck.
The value didnt change in the end. (my automation didnt trigger when opening the door)

It’s just a variable to store the scan interval in, the name does not matter. The timestamp in seconds is divided by this variable and if the remainder is zero the sensor is updated. The variable changes depending on the state of the door. Looks like the trigger template is only updated every minute (so use the second version I posted)…

Because the door state is in the template that will trigger the template to be evaluated too, but the timestamp still has to be evenly divisible by the scan interval for it to trigger.

I had also tested the second version but I had a time constraint mismatch in my automation trigger when the door openes. Now it works as expected. I was waiting for a value change in the configuration.yaml, but that doesnt happen, hence my confusion.
Now I can switch the nofood based on time which drastically limits my api calls :slight_smile:
Still not clear though how actually the scan_interval is set since scan_interval is not mentioned anywhere in the automation. Either way thank you!

The scan interval is not changed. It stays the huge number you specified.

The homeassistant update entity service overrides this whenever it is called by the automaton and forces an update of the sensor. That’s all the service does, it does not update the configuration.

1 Like

If you’d care to explain that would be awesome.

>>> int(datetime.datetime.now().timestamp()) % 10 == 0
True
>>> int(datetime.datetime.now().timestamp()) % 10 == 0
False
>>> int(datetime.datetime.now().timestamp()) % 10 == 0
False
>>> int(datetime.datetime.now().timestamp()) % 10 == 0
False
>>> int(datetime.datetime.now().timestamp()) % 10 == 0
True
>>> int(datetime.datetime.now().timestamp()) % 10 == 0
False
>>> int(datetime.datetime.now().timestamp()) % 10 == 0
False

so after some triggers, the eq. evaluates to true. That is when it allowes to sensor to update, correct?
With the true flag, How does it

  • know which variable from the sensor to update (why scan_interval and not some json_attribute or so?)
  • and to which value does it update the scan interval to?

And what happens to the sensor if the door is opened and closed during an automation trigger period when only False is evaluated?

Yes, when all conditions are true the actions run. But…

It does not know or do any of those things.

This service: homeassistant.update_entity forces the entity (that you specify in the target) to evaluate its state. The entity ignores any of its usual polling or scan interval settings and does a state update.