async def test_immediate_works(hass): """Test immediate works.""" calls = [] debouncer = debounce.Debouncer( hass, None, cooldown=0.01, immediate=True, function=CoroutineMock(side_effect=lambda: calls.append(None)), ) await debouncer.async_call() assert len(calls) == 1 assert debouncer._timer_task is not None assert debouncer._execute_at_end_of_timer is False await debouncer.async_call() assert len(calls) == 1 assert debouncer._timer_task is not None assert debouncer._execute_at_end_of_timer is True debouncer.async_cancel() assert debouncer._timer_task is None assert debouncer._execute_at_end_of_timer is False await debouncer.async_call() assert len(calls) == 2 await debouncer._handle_timer_finish() assert len(calls) == 2 assert debouncer._timer_task is None assert debouncer._execute_at_end_of_timer is False
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up BOM from a config entry.""" collector = Collector( entry.data[CONF_LATITUDE], entry.data[CONF_LONGITUDE] ) await collector.get_location_name() coordinator = DataUpdateCoordinator( hass, _LOGGER, name=f"BOM observation {collector.location_name}", update_method=collector.async_update, update_interval=DEFAULT_SCAN_INTERVAL, request_refresh_debouncer=debounce.Debouncer( hass, _LOGGER, cooldown=DEBOUNCE_TIME, immediate=True ) ) await coordinator.async_refresh() hass_data = hass.data.setdefault(DOMAIN, {}) hass_data[entry.entry_id] = { COLLECTOR: collector, COORDINATOR: coordinator, } for component in PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component) ) return True
async def test_immediate_works_with_function_swapped(hass): """Test immediate works and we can change out the function.""" calls = [] one_function = AsyncMock(side_effect=lambda: calls.append(1)) two_function = AsyncMock(side_effect=lambda: calls.append(2)) debouncer = debounce.Debouncer( hass, None, cooldown=0.01, immediate=True, function=one_function, ) # Call when nothing happening await debouncer.async_call() assert len(calls) == 1 assert debouncer._timer_task is not None assert debouncer._execute_at_end_of_timer is False assert debouncer._job.target == debouncer.function # Call when cooldown active setting execute at end to True await debouncer.async_call() assert len(calls) == 1 assert debouncer._timer_task is not None assert debouncer._execute_at_end_of_timer is True assert debouncer._job.target == debouncer.function # Canceling debounce in cooldown debouncer.async_cancel() assert debouncer._timer_task is None assert debouncer._execute_at_end_of_timer is False assert debouncer._job.target == debouncer.function before_job = debouncer._job debouncer.function = two_function # Call and let timer run out await debouncer.async_call() assert len(calls) == 2 assert calls == [1, 2] await debouncer._handle_timer_finish() assert len(calls) == 2 assert calls == [1, 2] assert debouncer._timer_task is None assert debouncer._execute_at_end_of_timer is False assert debouncer._job.target == debouncer.function assert debouncer._job != before_job # Test calling doesn't execute/cooldown if currently executing. await debouncer._execute_lock.acquire() await debouncer.async_call() assert len(calls) == 2 assert calls == [1, 2] assert debouncer._timer_task is None assert debouncer._execute_at_end_of_timer is False debouncer._execute_lock.release() assert debouncer._job.target == debouncer.function
def __init__(self, bridge): """Initialize the sensor manager.""" self.bridge = bridge self._component_add_entities = {} self.current = {} self.coordinator = DataUpdateCoordinator( bridge.hass, _LOGGER, "sensor", self.async_update_data, self.SCAN_INTERVAL, debounce.Debouncer(bridge.hass, _LOGGER, REQUEST_REFRESH_DELAY, True), )
def __init__(self, bridge): """Initialize the sensor manager.""" self.bridge = bridge self._component_add_entities = {} self.current = {} self.coordinator = DataUpdateCoordinator( bridge.hass, _LOGGER, name="sensor", update_method=self.async_update_data, update_interval=self.SCAN_INTERVAL, request_refresh_debouncer=debounce.Debouncer( bridge.hass, _LOGGER, cooldown=REQUEST_REFRESH_DELAY, immediate=True ), )
async def test_not_immediate_works(hass): """Test immediate works.""" calls = [] debouncer = debounce.Debouncer( hass, None, cooldown=0.01, immediate=False, function=AsyncMock(side_effect=lambda: calls.append(None)), ) # Call when nothing happening await debouncer.async_call() assert len(calls) == 0 assert debouncer._timer_task is not None assert debouncer._execute_at_end_of_timer is True # Call while still on cooldown await debouncer.async_call() assert len(calls) == 0 assert debouncer._timer_task is not None assert debouncer._execute_at_end_of_timer is True # Canceling while on cooldown debouncer.async_cancel() assert debouncer._timer_task is None assert debouncer._execute_at_end_of_timer is False # Call and let timer run out await debouncer.async_call() assert len(calls) == 0 await debouncer._handle_timer_finish() assert len(calls) == 1 assert debouncer._timer_task is not None assert debouncer._execute_at_end_of_timer is False assert debouncer._job.target == debouncer.function # Reset debouncer debouncer.async_cancel() # Test calling doesn't schedule if currently executing. await debouncer._execute_lock.acquire() await debouncer.async_call() assert len(calls) == 1 assert debouncer._timer_task is None assert debouncer._execute_at_end_of_timer is False debouncer._execute_lock.release() assert debouncer._job.target == debouncer.function
def __init__(self, hass: HomeAssistant, collector: Collector) -> None: """Initialise the data update coordinator.""" self.collector = collector super().__init__( hass=hass, logger=_LOGGER, name=DOMAIN, update_method=self.collector.async_update, update_interval=DEFAULT_SCAN_INTERVAL, request_refresh_debouncer=debounce.Debouncer( hass, _LOGGER, cooldown=DEBOUNCE_TIME, immediate=True ), ) self.entity_registry_updated_unsub = self.hass.bus.async_listen( er.EVENT_ENTITY_REGISTRY_UPDATED, self.entity_registry_updated )
async def test_immediate_works(hass): """Test immediate works.""" calls = [] debouncer = debounce.Debouncer( hass, None, cooldown=0.01, immediate=True, function=AsyncMock(side_effect=lambda: calls.append(None)), ) # Call when nothing happening await debouncer.async_call() assert len(calls) == 1 assert debouncer._timer_task is not None assert debouncer._execute_at_end_of_timer is False # Call when cooldown active setting execute at end to True await debouncer.async_call() assert len(calls) == 1 assert debouncer._timer_task is not None assert debouncer._execute_at_end_of_timer is True # Canceling debounce in cooldown debouncer.async_cancel() assert debouncer._timer_task is None assert debouncer._execute_at_end_of_timer is False # Call and let timer run out await debouncer.async_call() assert len(calls) == 2 await debouncer._handle_timer_finish() assert len(calls) == 2 assert debouncer._timer_task is None assert debouncer._execute_at_end_of_timer is False # Test calling doesn't execute/cooldown if currently executing. await debouncer._execute_lock.acquire() await debouncer.async_call() assert len(calls) == 2 assert debouncer._timer_task is None assert debouncer._execute_at_end_of_timer is False debouncer._execute_lock.release()
async def async_setup_platform( hass: HomeAssistant, config: ConfigType, async_add_entities: AddEntitiesCallback, discovery_info: DiscoveryInfoType | None = None, ) -> None: """Platform setup.""" config_host = config[CONF_HOST] config_port = config[CONF_PORT] config_name = config[CONF_NAME] try: async with async_timeout.timeout(PLATFORM_TIMEOUT): api = await real_time_api(config_host, config_port) except (IamMeterError, asyncio.TimeoutError) as err: _LOGGER.error("Device is not ready") raise PlatformNotReady from err async def async_update_data(): try: async with async_timeout.timeout(PLATFORM_TIMEOUT): return await api.get_data() except (IamMeterError, asyncio.TimeoutError) as err: raise UpdateFailed from err coordinator = DataUpdateCoordinator( hass, _LOGGER, name=DEFAULT_DEVICE_NAME, update_method=async_update_data, update_interval=SCAN_INTERVAL, request_refresh_debouncer=debounce.Debouncer(hass, _LOGGER, cooldown=0.3, immediate=True), ) await coordinator.async_refresh() entities = [] for sensor_name, (row, idx, unit) in api.iammeter.sensor_map().items(): serial_number = api.iammeter.serial_number uid = f"{serial_number}-{row}-{idx}" entities.append( IamMeter(coordinator, uid, sensor_name, unit, config_name)) async_add_entities(entities)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up a National Weather Service entry.""" latitude = entry.data[CONF_LATITUDE] longitude = entry.data[CONF_LONGITUDE] api_key = entry.data[CONF_API_KEY] station = entry.data[CONF_STATION] client_session = async_get_clientsession(hass) # set_station only does IO when station is None nws_data = SimpleNWS(latitude, longitude, api_key, client_session) await nws_data.set_station(station) coordinator_observation = NwsDataUpdateCoordinator( hass, _LOGGER, name=f"NWS observation station {station}", update_method=nws_data.update_observation, update_interval=DEFAULT_SCAN_INTERVAL, failed_update_interval=FAILED_SCAN_INTERVAL, request_refresh_debouncer=debounce.Debouncer(hass, _LOGGER, cooldown=DEBOUNCE_TIME, immediate=True), ) coordinator_forecast = NwsDataUpdateCoordinator( hass, _LOGGER, name=f"NWS forecast station {station}", update_method=nws_data.update_forecast, update_interval=DEFAULT_SCAN_INTERVAL, failed_update_interval=FAILED_SCAN_INTERVAL, request_refresh_debouncer=debounce.Debouncer(hass, _LOGGER, cooldown=DEBOUNCE_TIME, immediate=True), ) coordinator_forecast_hourly = NwsDataUpdateCoordinator( hass, _LOGGER, name=f"NWS forecast hourly station {station}", update_method=nws_data.update_forecast_hourly, update_interval=DEFAULT_SCAN_INTERVAL, failed_update_interval=FAILED_SCAN_INTERVAL, request_refresh_debouncer=debounce.Debouncer(hass, _LOGGER, cooldown=DEBOUNCE_TIME, immediate=True), ) nws_hass_data = hass.data.setdefault(DOMAIN, {}) nws_hass_data[entry.entry_id] = { NWS_DATA: nws_data, COORDINATOR_OBSERVATION: coordinator_observation, COORDINATOR_FORECAST: coordinator_forecast, COORDINATOR_FORECAST_HOURLY: coordinator_forecast_hourly, } # Fetch initial data so we have data when entities subscribe await coordinator_observation.async_refresh() await coordinator_forecast.async_refresh() await coordinator_forecast_hourly.async_refresh() hass.config_entries.async_setup_platforms(entry, PLATFORMS) return True