mirror of
https://github.com/home-assistant/core.git
synced 2025-07-15 09:17:10 +00:00
Reduce bond startup time (#73506)
This commit is contained in:
parent
c64b108789
commit
1e956bc52f
@ -287,10 +287,10 @@ class BondButtonEntity(BondEntity, ButtonEntity):
|
|||||||
description: BondButtonEntityDescription,
|
description: BondButtonEntityDescription,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Init Bond button."""
|
"""Init Bond button."""
|
||||||
|
self.entity_description = description
|
||||||
super().__init__(
|
super().__init__(
|
||||||
hub, device, bpup_subs, description.name, description.key.lower()
|
hub, device, bpup_subs, description.name, description.key.lower()
|
||||||
)
|
)
|
||||||
self.entity_description = description
|
|
||||||
|
|
||||||
async def async_press(self, **kwargs: Any) -> None:
|
async def async_press(self, **kwargs: Any) -> None:
|
||||||
"""Press the button."""
|
"""Press the button."""
|
||||||
@ -302,5 +302,5 @@ class BondButtonEntity(BondEntity, ButtonEntity):
|
|||||||
action = Action(self.entity_description.key)
|
action = Action(self.entity_description.key)
|
||||||
await self._hub.bond.action(self._device.device_id, action)
|
await self._hub.bond.action(self._device.device_id, action)
|
||||||
|
|
||||||
def _apply_state(self, state: dict) -> None:
|
def _apply_state(self) -> None:
|
||||||
"""Apply the state."""
|
"""Apply the state."""
|
||||||
|
@ -13,7 +13,6 @@ from homeassistant.components.cover import (
|
|||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity import Entity
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import BPUP_SUBS, DOMAIN, HUB
|
from .const import BPUP_SUBS, DOMAIN, HUB
|
||||||
@ -40,14 +39,11 @@ async def async_setup_entry(
|
|||||||
data = hass.data[DOMAIN][entry.entry_id]
|
data = hass.data[DOMAIN][entry.entry_id]
|
||||||
hub: BondHub = data[HUB]
|
hub: BondHub = data[HUB]
|
||||||
bpup_subs: BPUPSubscriptions = data[BPUP_SUBS]
|
bpup_subs: BPUPSubscriptions = data[BPUP_SUBS]
|
||||||
|
async_add_entities(
|
||||||
covers: list[Entity] = [
|
|
||||||
BondCover(hub, device, bpup_subs)
|
BondCover(hub, device, bpup_subs)
|
||||||
for device in hub.devices
|
for device in hub.devices
|
||||||
if device.type == DeviceType.MOTORIZED_SHADES
|
if device.type == DeviceType.MOTORIZED_SHADES
|
||||||
]
|
)
|
||||||
|
|
||||||
async_add_entities(covers, True)
|
|
||||||
|
|
||||||
|
|
||||||
class BondCover(BondEntity, CoverEntity):
|
class BondCover(BondEntity, CoverEntity):
|
||||||
@ -78,7 +74,8 @@ class BondCover(BondEntity, CoverEntity):
|
|||||||
supported_features |= CoverEntityFeature.STOP_TILT
|
supported_features |= CoverEntityFeature.STOP_TILT
|
||||||
self._attr_supported_features = supported_features
|
self._attr_supported_features = supported_features
|
||||||
|
|
||||||
def _apply_state(self, state: dict) -> None:
|
def _apply_state(self) -> None:
|
||||||
|
state = self._device.state
|
||||||
cover_open = state.get("open")
|
cover_open = state.get("open")
|
||||||
self._attr_is_closed = None if cover_open is None else cover_open == 0
|
self._attr_is_closed = None if cover_open is None else cover_open == 0
|
||||||
if (bond_position := state.get("position")) is not None:
|
if (bond_position := state.get("position")) is not None:
|
||||||
|
@ -64,6 +64,8 @@ class BondEntity(Entity):
|
|||||||
self._attr_name = f"{device.name} {sub_device_name}"
|
self._attr_name = f"{device.name} {sub_device_name}"
|
||||||
else:
|
else:
|
||||||
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._apply_state()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> DeviceInfo:
|
def device_info(self) -> DeviceInfo:
|
||||||
@ -137,10 +139,9 @@ class BondEntity(Entity):
|
|||||||
self._attr_available = False
|
self._attr_available = False
|
||||||
else:
|
else:
|
||||||
self._async_state_callback(state)
|
self._async_state_callback(state)
|
||||||
self._attr_assumed_state = self._hub.is_bridge and not self._device.trust_state
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def _apply_state(self, state: dict) -> None:
|
def _apply_state(self) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -153,7 +154,8 @@ class BondEntity(Entity):
|
|||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Device state for %s (%s) is:\n%s", self.name, self.entity_id, state
|
"Device state for %s (%s) is:\n%s", self.name, self.entity_id, state
|
||||||
)
|
)
|
||||||
self._apply_state(state)
|
self._device.state = state
|
||||||
|
self._apply_state()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_bpup_callback(self, json_msg: dict) -> None:
|
def _async_bpup_callback(self, json_msg: dict) -> None:
|
||||||
|
@ -19,7 +19,6 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import entity_platform
|
from homeassistant.helpers import entity_platform
|
||||||
from homeassistant.helpers.entity import Entity
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.util.percentage import (
|
from homeassistant.util.percentage import (
|
||||||
int_states_in_range,
|
int_states_in_range,
|
||||||
@ -46,20 +45,17 @@ async def async_setup_entry(
|
|||||||
hub: BondHub = data[HUB]
|
hub: BondHub = data[HUB]
|
||||||
bpup_subs: BPUPSubscriptions = data[BPUP_SUBS]
|
bpup_subs: BPUPSubscriptions = data[BPUP_SUBS]
|
||||||
platform = entity_platform.async_get_current_platform()
|
platform = entity_platform.async_get_current_platform()
|
||||||
|
|
||||||
fans: list[Entity] = [
|
|
||||||
BondFan(hub, device, bpup_subs)
|
|
||||||
for device in hub.devices
|
|
||||||
if DeviceType.is_fan(device.type)
|
|
||||||
]
|
|
||||||
|
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_SET_FAN_SPEED_TRACKED_STATE,
|
SERVICE_SET_FAN_SPEED_TRACKED_STATE,
|
||||||
{vol.Required("speed"): vol.All(vol.Number(scale=0), vol.Range(0, 100))},
|
{vol.Required("speed"): vol.All(vol.Number(scale=0), vol.Range(0, 100))},
|
||||||
"async_set_speed_belief",
|
"async_set_speed_belief",
|
||||||
)
|
)
|
||||||
|
|
||||||
async_add_entities(fans, True)
|
async_add_entities(
|
||||||
|
BondFan(hub, device, bpup_subs)
|
||||||
|
for device in hub.devices
|
||||||
|
if DeviceType.is_fan(device.type)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BondFan(BondEntity, FanEntity):
|
class BondFan(BondEntity, FanEntity):
|
||||||
@ -69,15 +65,15 @@ class BondFan(BondEntity, FanEntity):
|
|||||||
self, hub: BondHub, device: BondDevice, bpup_subs: BPUPSubscriptions
|
self, hub: BondHub, device: BondDevice, bpup_subs: BPUPSubscriptions
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Create HA entity representing Bond fan."""
|
"""Create HA entity representing Bond fan."""
|
||||||
super().__init__(hub, device, bpup_subs)
|
|
||||||
|
|
||||||
self._power: bool | None = None
|
self._power: bool | None = None
|
||||||
self._speed: int | None = None
|
self._speed: int | None = None
|
||||||
self._direction: int | None = None
|
self._direction: int | None = None
|
||||||
|
super().__init__(hub, device, bpup_subs)
|
||||||
if self._device.has_action(Action.BREEZE_ON):
|
if self._device.has_action(Action.BREEZE_ON):
|
||||||
self._attr_preset_modes = [PRESET_MODE_BREEZE]
|
self._attr_preset_modes = [PRESET_MODE_BREEZE]
|
||||||
|
|
||||||
def _apply_state(self, state: dict) -> None:
|
def _apply_state(self) -> None:
|
||||||
|
state = self._device.state
|
||||||
self._power = state.get("power")
|
self._power = state.get("power")
|
||||||
self._speed = state.get("speed")
|
self._speed = state.get("speed")
|
||||||
self._direction = state.get("direction")
|
self._direction = state.get("direction")
|
||||||
|
@ -115,7 +115,6 @@ async def async_setup_entry(
|
|||||||
|
|
||||||
async_add_entities(
|
async_add_entities(
|
||||||
fan_lights + fan_up_lights + fan_down_lights + fireplaces + fp_lights + lights,
|
fan_lights + fan_up_lights + fan_down_lights + fireplaces + fp_lights + lights,
|
||||||
True,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -170,7 +169,8 @@ class BondLight(BondBaseLight, BondEntity, LightEntity):
|
|||||||
self._attr_color_mode = ColorMode.BRIGHTNESS
|
self._attr_color_mode = ColorMode.BRIGHTNESS
|
||||||
self._attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
self._attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
||||||
|
|
||||||
def _apply_state(self, state: dict) -> None:
|
def _apply_state(self) -> None:
|
||||||
|
state = self._device.state
|
||||||
self._attr_is_on = state.get("light") == 1
|
self._attr_is_on = state.get("light") == 1
|
||||||
brightness = state.get("brightness")
|
brightness = state.get("brightness")
|
||||||
self._attr_brightness = round(brightness * 255 / 100) if brightness else None
|
self._attr_brightness = round(brightness * 255 / 100) if brightness else None
|
||||||
@ -227,7 +227,8 @@ class BondLight(BondBaseLight, BondEntity, LightEntity):
|
|||||||
class BondDownLight(BondBaseLight, BondEntity, LightEntity):
|
class BondDownLight(BondBaseLight, BondEntity, LightEntity):
|
||||||
"""Representation of a Bond light."""
|
"""Representation of a Bond light."""
|
||||||
|
|
||||||
def _apply_state(self, state: dict) -> None:
|
def _apply_state(self) -> None:
|
||||||
|
state = self._device.state
|
||||||
self._attr_is_on = bool(state.get("down_light") and state.get("light"))
|
self._attr_is_on = bool(state.get("down_light") and state.get("light"))
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
@ -246,7 +247,8 @@ class BondDownLight(BondBaseLight, BondEntity, LightEntity):
|
|||||||
class BondUpLight(BondBaseLight, BondEntity, LightEntity):
|
class BondUpLight(BondBaseLight, BondEntity, LightEntity):
|
||||||
"""Representation of a Bond light."""
|
"""Representation of a Bond light."""
|
||||||
|
|
||||||
def _apply_state(self, state: dict) -> None:
|
def _apply_state(self) -> None:
|
||||||
|
state = self._device.state
|
||||||
self._attr_is_on = bool(state.get("up_light") and state.get("light"))
|
self._attr_is_on = bool(state.get("up_light") and state.get("light"))
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
@ -268,7 +270,8 @@ class BondFireplace(BondEntity, LightEntity):
|
|||||||
_attr_color_mode = ColorMode.BRIGHTNESS
|
_attr_color_mode = ColorMode.BRIGHTNESS
|
||||||
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
||||||
|
|
||||||
def _apply_state(self, state: dict) -> None:
|
def _apply_state(self) -> None:
|
||||||
|
state = self._device.state
|
||||||
power = state.get("power")
|
power = state.get("power")
|
||||||
flame = state.get("flame")
|
flame = state.get("flame")
|
||||||
self._attr_is_on = power == 1
|
self._attr_is_on = power == 1
|
||||||
|
@ -12,7 +12,6 @@ from homeassistant.config_entries import ConfigEntry
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||||
from homeassistant.helpers.entity import Entity
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
@ -36,27 +35,24 @@ async def async_setup_entry(
|
|||||||
hub: BondHub = data[HUB]
|
hub: BondHub = data[HUB]
|
||||||
bpup_subs: BPUPSubscriptions = data[BPUP_SUBS]
|
bpup_subs: BPUPSubscriptions = data[BPUP_SUBS]
|
||||||
platform = entity_platform.async_get_current_platform()
|
platform = entity_platform.async_get_current_platform()
|
||||||
|
|
||||||
switches: list[Entity] = [
|
|
||||||
BondSwitch(hub, device, bpup_subs)
|
|
||||||
for device in hub.devices
|
|
||||||
if DeviceType.is_generic(device.type)
|
|
||||||
]
|
|
||||||
|
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_SET_POWER_TRACKED_STATE,
|
SERVICE_SET_POWER_TRACKED_STATE,
|
||||||
{vol.Required(ATTR_POWER_STATE): cv.boolean},
|
{vol.Required(ATTR_POWER_STATE): cv.boolean},
|
||||||
"async_set_power_belief",
|
"async_set_power_belief",
|
||||||
)
|
)
|
||||||
|
|
||||||
async_add_entities(switches, True)
|
async_add_entities(
|
||||||
|
BondSwitch(hub, device, bpup_subs)
|
||||||
|
for device in hub.devices
|
||||||
|
if DeviceType.is_generic(device.type)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class BondSwitch(BondEntity, SwitchEntity):
|
class BondSwitch(BondEntity, SwitchEntity):
|
||||||
"""Representation of a Bond generic device."""
|
"""Representation of a Bond generic device."""
|
||||||
|
|
||||||
def _apply_state(self, state: dict) -> None:
|
def _apply_state(self) -> None:
|
||||||
self._attr_is_on = state.get("power") == 1
|
self._attr_is_on = self._device.state.get("power") == 1
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device on."""
|
"""Turn the device on."""
|
||||||
|
@ -20,11 +20,16 @@ class BondDevice:
|
|||||||
"""Helper device class to hold ID and attributes together."""
|
"""Helper device class to hold ID and attributes together."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, device_id: str, attrs: dict[str, Any], props: dict[str, Any]
|
self,
|
||||||
|
device_id: str,
|
||||||
|
attrs: dict[str, Any],
|
||||||
|
props: dict[str, Any],
|
||||||
|
state: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Create a helper device from ID and attributes returned by API."""
|
"""Create a helper device from ID and attributes returned by API."""
|
||||||
self.device_id = device_id
|
self.device_id = device_id
|
||||||
self.props = props
|
self.props = props
|
||||||
|
self.state = state
|
||||||
self._attrs = attrs or {}
|
self._attrs = attrs or {}
|
||||||
self._supported_actions: set[str] = set(self._attrs.get("actions", []))
|
self._supported_actions: set[str] = set(self._attrs.get("actions", []))
|
||||||
|
|
||||||
@ -34,6 +39,7 @@ class BondDevice:
|
|||||||
"device_id": self.device_id,
|
"device_id": self.device_id,
|
||||||
"props": self.props,
|
"props": self.props,
|
||||||
"attrs": self._attrs,
|
"attrs": self._attrs,
|
||||||
|
"state": self.state,
|
||||||
}.__repr__()
|
}.__repr__()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -150,7 +156,11 @@ class BondHub:
|
|||||||
break
|
break
|
||||||
setup_device_ids.append(device_id)
|
setup_device_ids.append(device_id)
|
||||||
tasks.extend(
|
tasks.extend(
|
||||||
[self.bond.device(device_id), self.bond.device_properties(device_id)]
|
[
|
||||||
|
self.bond.device(device_id),
|
||||||
|
self.bond.device_properties(device_id),
|
||||||
|
self.bond.device_state(device_id),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
responses = await gather_with_concurrency(MAX_REQUESTS, *tasks)
|
responses = await gather_with_concurrency(MAX_REQUESTS, *tasks)
|
||||||
@ -158,10 +168,13 @@ class BondHub:
|
|||||||
for device_id in setup_device_ids:
|
for device_id in setup_device_ids:
|
||||||
self._devices.append(
|
self._devices.append(
|
||||||
BondDevice(
|
BondDevice(
|
||||||
device_id, responses[response_idx], responses[response_idx + 1]
|
device_id,
|
||||||
|
responses[response_idx],
|
||||||
|
responses[response_idx + 1],
|
||||||
|
responses[response_idx + 2],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
response_idx += 2
|
response_idx += 3
|
||||||
|
|
||||||
_LOGGER.debug("Discovered Bond devices: %s", self._devices)
|
_LOGGER.debug("Discovered Bond devices: %s", self._devices)
|
||||||
try:
|
try:
|
||||||
|
@ -18,6 +18,7 @@ from .common import (
|
|||||||
patch_bond_device,
|
patch_bond_device,
|
||||||
patch_bond_device_ids,
|
patch_bond_device_ids,
|
||||||
patch_bond_device_properties,
|
patch_bond_device_properties,
|
||||||
|
patch_bond_device_state,
|
||||||
patch_bond_token,
|
patch_bond_token,
|
||||||
patch_bond_version,
|
patch_bond_version,
|
||||||
)
|
)
|
||||||
@ -38,7 +39,7 @@ async def test_user_form(hass: core.HomeAssistant):
|
|||||||
return_value={"bondid": "ZXXX12345"}
|
return_value={"bondid": "ZXXX12345"}
|
||||||
), patch_bond_device_ids(
|
), patch_bond_device_ids(
|
||||||
return_value=["f6776c11", "f6776c12"]
|
return_value=["f6776c11", "f6776c12"]
|
||||||
), patch_bond_bridge(), patch_bond_device_properties(), patch_bond_device(), _patch_async_setup_entry() as mock_setup_entry:
|
), patch_bond_bridge(), patch_bond_device_properties(), patch_bond_device(), patch_bond_device_state(), _patch_async_setup_entry() as mock_setup_entry:
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{CONF_HOST: "some host", CONF_ACCESS_TOKEN: "test-token"},
|
{CONF_HOST: "some host", CONF_ACCESS_TOKEN: "test-token"},
|
||||||
@ -73,7 +74,7 @@ async def test_user_form_with_non_bridge(hass: core.HomeAssistant):
|
|||||||
}
|
}
|
||||||
), patch_bond_bridge(
|
), patch_bond_bridge(
|
||||||
return_value={}
|
return_value={}
|
||||||
), _patch_async_setup_entry() as mock_setup_entry:
|
), patch_bond_device_state(), _patch_async_setup_entry() as mock_setup_entry:
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{CONF_HOST: "some host", CONF_ACCESS_TOKEN: "test-token"},
|
{CONF_HOST: "some host", CONF_ACCESS_TOKEN: "test-token"},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user