Custom component scan_interval

Hello,

I’ve developped a custom component, and for the moment, I defined the scan interval as this in the binary_sensor :

SCAN_INTERVAL = timedelta(minutes=2)

With a global variable.
It works great.

But I’d like to make it configurable through the configuration.yaml file.

So I added this to my init file, in the voluptuous schema :

vol.Optional(CONF_SCAN_INTERVAL): cv.time_period,

But it doesn’t work. My component uses the 30s update interval by default of HASS.

Any idea how I can do it ?
Thanks.

1 Like

Without knowing much of anything about how your code works one option is using the Throttle utility.

Hello,

What is the throttle utility ?

What do you need to know about my code ?

I only have a update method/function that is called every X time (defined by scan_interval), in my binary_sensor.py

This update function update the state value of my binary_sensor.

Do you need more details ?

Here is the Throttle utility:

https://github.com/home-assistant/home-assistant/blob/67c56c860da42c531e93fa420a558023c22e8dce/homeassistant/util/init.py#L153

Here is an example of modifying the Throttle time based on a parameter:

Thanks.

Is it the Throttle utility that override the SCAN_INTERVAL global variable ?

My understanding is that the SCAN_INTERVAL sets how often your platform entity will call it’s update or async_update method. Throttle prevents the same method from being called more often than the supplied interval parameter. So you can use the default scan_internal and then Throttle it to only actually update to the configured time Delta.

To be more clear, Throttle does not stop the update method from being called every 30s for example, but it bypasses the method if the Throttle internal time hasn’t elapsed.

apparently that’s the way it should be.

it’s already there. just add

scan_interval: 120

in yaml an you’ll see the result.

it lives here. Here is an example of how it is used in a custom component.

I would use @AhmadK’s method. It is already there.

That was my understanding, and tried it. But it doesn’t override the SCAN_INTERVAL in the composent :frowning:

you said nothing about it. in fact, you said this

All I know is it works for ping component and many others. As @MatthewFlamm said,

we can only guess.
Make sure your class is inherited from Entity. More info is in ping code or here

Hello,

Here are some more information about my code. Please tell me if it is enough ? Because I still can’t get it to work.

Configuration.yaml. My custom component protexiom.

protexiom:
  scan_interval: 20 
  url: !secret protexiom_url

My init.py file for my custom component.

import voluptuous as vol
from homeassistant.const import CONF_URL, CONF_PASSWORD, CONF_SCAN_INTERVAL
from homeassistant.helpers import config_validation as cv, discovery
from homeassistant.helpers.entity import Entity
from .const import DOMAIN, SENSOR_TYPES, PROTEXIOM_COMPONENTS, PROTEXIOM_DEVICES_TYPE, CONF_CODES, DEFAULT_SCAN_INTERVAL

_LOGGER = logging.getLogger(__name__)

CONFIG_SCHEMA = vol.Schema(
    {
        DOMAIN: vol.Schema(
            {
                vol.Required(CONF_URL): cv.string,
                vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): cv.time_period,
            }
        )
    },
    extra=vol.ALLOW_EXTRA,
)

def setup(hass, config):
    url = config[DOMAIN][CONF_URL]
    
    try: 
        protexiom = Protexiom(url)
    except:
        _LOGGER.exception("Error when trying to log in")
        return False
    
    for component in PROTEXIOM_COMPONENTS:
        _LOGGER.info("Components : ")
        _LOGGER.info(component)
        discovery.load_platform(hass, component, DOMAIN, {}, config)
        
    return True

And my binary_sensor.py :

import voluptuous as vol

from homeassistant.components.binary_sensor import *
from homeassistant.const import (
    STATE_OFF, 
    STATE_ON,
)

from . import DOMAIN as PROTEXIOM_DOMAIN
from .const import *

_LOGGER = logging.getLogger(__name__)

DEFAULT_DEVICE_CLASS = "None"

SCAN_INTERVAL = timedelta(minutes=2)

def setup_platform(hass, config, add_entities, discovery_info=None):
    _hass = hass
    controller = hass.data[PROTEXIOM_DOMAIN]["controller"]
    protexiom_devices = []
    for device, deviceTypeList in hass.data[PROTEXIOM_DOMAIN]["devices"].items():
        protexiom_devices.append(ProtexiomBinarySensor(hass, controller, device, deviceType))
    add_entities(protexiom_devices, True)


class ProtexiomBinarySensor(BinarySensorDevice):

    def __init__(self, hass, protexiom, protexiom_device, deviceType):
        self.protexiom = protexiom
        self._attributes = {}
        self._state = None
        self._state_attr = {}
        self._hass = hass
        self._device = protexiom_device
        self._name = "protexiom_"+self._device+"_"+SENSOR_TYPES[deviceType][0]
        self._fname = ""
        self._deviceType = deviceType

    def update(self):
        return protexiom.get_value()

When using a component configuration like this, I don’t have any direct experience. But I don’t think you can use scan_internal here, you might be able to use it still in a PLATFORM_SCHEMA inside binary_sensor module. You might not.

You can also turn off polling in your binary sensor entity and schedule updates in the __init__.py module in setup. Unfortunately this requires moving the logic of device interaction into that module.

In fact, that’s my issue. I don’t want to remove the logic of hass. I want hass to handle this. :frowning:

Have you simply tried removing the CONF_SCAN_INTERVAL line(s) from your SCHEMA in the __init__.py and try to add scan_interval to your configuration?

Yes and I got schema error.

Setup failed for protexiom: Invalid config.

Sorry, I’m pretty new to custom components and cannot help further.
Maybe it’s a good idea to go on Discord and ask devs on an appropriate channel?

Thanks.
Devs don’t come to the forum and help ?! :frowning:

sometimes they do, but imho you might get help much faster if you ask at Discord.

I know this thread was from a while ago, but I was trying to figure out how to get the entities that my component created to be polled when the component was completely configured at the top level, rather than at platform level where a scan_interval could be specified. This thread is the most relevant top search result so I thought I’d document how I managed to get this to work here.

The solution appears to be to use homeassistant.helpers.event.track_time_interval to schedule your own timer for an entity (or set of entities) to any scan interval. You can see this helper function in action in the arlo component. You also probably need to overload should_poll to return false too and/or remove any SCAN_INTERVAL definition in the platform code, so that the platform doesn’t start another timer for it’s entities.