Reduce bond fallback polling interval when BPUP is alive (#90871)
* Reduce bond fallback polling interval when BPUP is alive If push updates are alive we should not check every 10 seconds. * tweak * tweak * coverage * coverage * coverage
This commit is contained in:
parent
8fe597b7c6
commit
59872f1914
4 changed files with 93 additions and 12 deletions
|
@ -17,9 +17,9 @@ from homeassistant.const import (
|
||||||
ATTR_SW_VERSION,
|
ATTR_SW_VERSION,
|
||||||
ATTR_VIA_DEVICE,
|
ATTR_VIA_DEVICE,
|
||||||
)
|
)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import CALLBACK_TYPE, callback
|
||||||
from homeassistant.helpers.entity import DeviceInfo, Entity
|
from homeassistant.helpers.entity import DeviceInfo, Entity
|
||||||
from homeassistant.helpers.event import async_track_time_interval
|
from homeassistant.helpers.event import async_call_later
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .utils import BondDevice, BondHub
|
from .utils import BondDevice, BondHub
|
||||||
|
@ -27,6 +27,7 @@ from .utils import BondDevice, BondHub
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
_FALLBACK_SCAN_INTERVAL = timedelta(seconds=10)
|
_FALLBACK_SCAN_INTERVAL = timedelta(seconds=10)
|
||||||
|
_BPUP_ALIVE_SCAN_INTERVAL = timedelta(seconds=60)
|
||||||
|
|
||||||
|
|
||||||
class BondEntity(Entity):
|
class BondEntity(Entity):
|
||||||
|
@ -65,6 +66,7 @@ class BondEntity(Entity):
|
||||||
self._attr_name = device.name
|
self._attr_name = device.name
|
||||||
self._attr_assumed_state = self._hub.is_bridge and not self._device.trust_state
|
self._attr_assumed_state = self._hub.is_bridge and not self._device.trust_state
|
||||||
self._apply_state()
|
self._apply_state()
|
||||||
|
self._bpup_polling_fallback: CALLBACK_TYPE | None = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> DeviceInfo:
|
def device_info(self) -> DeviceInfo:
|
||||||
|
@ -100,12 +102,13 @@ class BondEntity(Entity):
|
||||||
return device_info
|
return device_info
|
||||||
|
|
||||||
async def async_update(self) -> None:
|
async def async_update(self) -> None:
|
||||||
"""Fetch assumed state of the cover from the hub using API."""
|
"""Perform a manual update from API."""
|
||||||
await self._async_update_from_api()
|
await self._async_update_from_api()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_if_bpup_not_alive(self, now: datetime) -> None:
|
def _async_update_if_bpup_not_alive(self, now: datetime) -> None:
|
||||||
"""Fetch via the API if BPUP is not alive."""
|
"""Fetch via the API if BPUP is not alive."""
|
||||||
|
self._async_schedule_bpup_alive_or_poll()
|
||||||
if (
|
if (
|
||||||
self.hass.is_stopping
|
self.hass.is_stopping
|
||||||
or self._bpup_subs.alive
|
or self._bpup_subs.alive
|
||||||
|
@ -172,16 +175,22 @@ class BondEntity(Entity):
|
||||||
"""Subscribe to BPUP and start polling."""
|
"""Subscribe to BPUP and start polling."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
self._bpup_subs.subscribe(self._device_id, self._async_bpup_callback)
|
self._bpup_subs.subscribe(self._device_id, self._async_bpup_callback)
|
||||||
self.async_on_remove(
|
self._async_schedule_bpup_alive_or_poll()
|
||||||
async_track_time_interval(
|
|
||||||
self.hass,
|
@callback
|
||||||
self._async_update_if_bpup_not_alive,
|
def _async_schedule_bpup_alive_or_poll(self) -> None:
|
||||||
_FALLBACK_SCAN_INTERVAL,
|
"""Schedule the BPUP alive or poll."""
|
||||||
name=f"Bond {self.entity_id} fallback polling",
|
alive = self._bpup_subs.alive
|
||||||
)
|
self._bpup_polling_fallback = async_call_later(
|
||||||
|
self.hass,
|
||||||
|
_BPUP_ALIVE_SCAN_INTERVAL if alive else _FALLBACK_SCAN_INTERVAL,
|
||||||
|
self._async_update_if_bpup_not_alive,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Unsubscribe from BPUP data on remove."""
|
"""Unsubscribe from BPUP data on remove."""
|
||||||
await super().async_will_remove_from_hass()
|
await super().async_will_remove_from_hass()
|
||||||
self._bpup_subs.unsubscribe(self._device_id, self._async_bpup_callback)
|
self._bpup_subs.unsubscribe(self._device_id, self._async_bpup_callback)
|
||||||
|
if self._bpup_polling_fallback:
|
||||||
|
self._bpup_polling_fallback()
|
||||||
|
self._bpup_polling_fallback = None
|
||||||
|
|
|
@ -127,7 +127,12 @@ def patch_bond_version(
|
||||||
return nullcontext()
|
return nullcontext()
|
||||||
|
|
||||||
if return_value is None:
|
if return_value is None:
|
||||||
return_value = {"bondid": "ZXXX12345"}
|
return_value = {
|
||||||
|
"bondid": "ZXXX12345",
|
||||||
|
"target": "test-model",
|
||||||
|
"fw_ver": "test-version",
|
||||||
|
"mcu_ver": "test-hw-version",
|
||||||
|
}
|
||||||
|
|
||||||
return patch(
|
return patch(
|
||||||
"homeassistant.components.bond.Bond.version",
|
"homeassistant.components.bond.Bond.version",
|
||||||
|
|
|
@ -42,5 +42,12 @@ async def test_diagnostics(
|
||||||
"data": {"access_token": "**REDACTED**", "host": "some host"},
|
"data": {"access_token": "**REDACTED**", "host": "some host"},
|
||||||
"title": "Mock Title",
|
"title": "Mock Title",
|
||||||
},
|
},
|
||||||
"hub": {"version": {"bondid": "ZXXX12345"}},
|
"hub": {
|
||||||
|
"version": {
|
||||||
|
"bondid": "ZXXX12345",
|
||||||
|
"fw_ver": "test-version",
|
||||||
|
"mcu_ver": "test-hw-version",
|
||||||
|
"target": "test-model",
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,3 +468,63 @@ async def test_fan_available(hass: HomeAssistant) -> None:
|
||||||
await help_test_entity_available(
|
await help_test_entity_available(
|
||||||
hass, FAN_DOMAIN, ceiling_fan("name-1"), "fan.name_1"
|
hass, FAN_DOMAIN, ceiling_fan("name-1"), "fan.name_1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_setup_smart_by_bond_fan(hass: HomeAssistant) -> None:
|
||||||
|
"""Test setting up a fan without a hub."""
|
||||||
|
config_entry = await setup_platform(
|
||||||
|
hass,
|
||||||
|
FAN_DOMAIN,
|
||||||
|
ceiling_fan("name-1"),
|
||||||
|
bond_device_id="test-device-id",
|
||||||
|
bond_version={
|
||||||
|
"bondid": "KXXX12345",
|
||||||
|
"target": "test-model",
|
||||||
|
"fw_ver": "test-version",
|
||||||
|
"mcu_ver": "test-hw-version",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert hass.states.get("fan.name_1") is not None
|
||||||
|
registry = er.async_get(hass)
|
||||||
|
entry = registry.async_get("fan.name_1")
|
||||||
|
assert entry.device_id is not None
|
||||||
|
device_registry = dr.async_get(hass)
|
||||||
|
device = device_registry.async_get(entry.device_id)
|
||||||
|
assert device is not None
|
||||||
|
assert device.sw_version == "test-version"
|
||||||
|
assert device.manufacturer == "Olibra"
|
||||||
|
assert device.identifiers == {("bond", "KXXX12345", "test-device-id")}
|
||||||
|
assert device.hw_version == "test-hw-version"
|
||||||
|
await hass.config_entries.async_unload(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_setup_hub_template_fan(hass: HomeAssistant) -> None:
|
||||||
|
"""Test setting up a fan on a hub created from a template."""
|
||||||
|
config_entry = await setup_platform(
|
||||||
|
hass,
|
||||||
|
FAN_DOMAIN,
|
||||||
|
{**ceiling_fan("name-1"), "template": "test-template"},
|
||||||
|
bond_device_id="test-device-id",
|
||||||
|
props={"branding_profile": "test-branding-profile"},
|
||||||
|
bond_version={
|
||||||
|
"bondid": "ZXXX12345",
|
||||||
|
"target": "test-model",
|
||||||
|
"fw_ver": "test-version",
|
||||||
|
"mcu_ver": "test-hw-version",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert hass.states.get("fan.name_1") is not None
|
||||||
|
registry = er.async_get(hass)
|
||||||
|
entry = registry.async_get("fan.name_1")
|
||||||
|
assert entry.device_id is not None
|
||||||
|
device_registry = dr.async_get(hass)
|
||||||
|
device = device_registry.async_get(entry.device_id)
|
||||||
|
assert device is not None
|
||||||
|
assert device.sw_version is None
|
||||||
|
assert device.model == "test-branding-profile test-template"
|
||||||
|
assert device.manufacturer == "Olibra"
|
||||||
|
assert device.identifiers == {("bond", "ZXXX12345", "test-device-id")}
|
||||||
|
assert device.hw_version is None
|
||||||
|
await hass.config_entries.async_unload(config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
Loading…
Add table
Reference in a new issue