diff --git a/homeassistant/components/switcher_kis/__init__.py b/homeassistant/components/switcher_kis/__init__.py index 6a23f1bb453..7be726388f0 100644 --- a/homeassistant/components/switcher_kis/__init__.py +++ b/homeassistant/components/switcher_kis/__init__.py @@ -1,6 +1,7 @@ """The Switcher integration.""" from __future__ import annotations +import asyncio from datetime import timedelta import logging @@ -75,10 +76,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: # Existing device update device data if device.device_id in hass.data[DOMAIN][DATA_DEVICE]: - wrapper: SwitcherDeviceWrapper = hass.data[DOMAIN][DATA_DEVICE][ + coordinator: SwitcherDataUpdateCoordinator = hass.data[DOMAIN][DATA_DEVICE][ device.device_id ] - wrapper.async_set_updated_data(device) + coordinator.async_set_updated_data(device) return # New device - create device @@ -90,15 +91,19 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: device.device_type.hex_rep, ) - wrapper = hass.data[DOMAIN][DATA_DEVICE][ + coordinator = hass.data[DOMAIN][DATA_DEVICE][ device.device_id - ] = SwitcherDeviceWrapper(hass, entry, device) - hass.async_create_task(wrapper.async_setup()) + ] = SwitcherDataUpdateCoordinator(hass, entry, device) + coordinator.async_setup() async def platforms_setup_task() -> None: # Must be ready before dispatcher is called - for platform in PLATFORMS: - await hass.config_entries.async_forward_entry_setup(entry, platform) + await asyncio.gather( + *( + hass.config_entries.async_forward_entry_setup(entry, platform) + for platform in PLATFORMS + ) + ) discovery_task = hass.data[DOMAIN].pop(DATA_DISCOVERY, None) if discovery_task is not None: @@ -114,25 +119,26 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def stop_bridge(event: Event) -> None: await async_stop_bridge(hass) - hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_bridge) + entry.async_on_unload( + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_bridge) + ) return True -class SwitcherDeviceWrapper(update_coordinator.DataUpdateCoordinator): - """Wrapper for a Switcher device with Home Assistant specific functions.""" +class SwitcherDataUpdateCoordinator(update_coordinator.DataUpdateCoordinator): + """Switcher device data update coordinator.""" def __init__( self, hass: HomeAssistant, entry: ConfigEntry, device: SwitcherBase ) -> None: - """Initialize the Switcher device wrapper.""" + """Initialize the Switcher device coordinator.""" super().__init__( hass, _LOGGER, name=device.name, update_interval=timedelta(seconds=MAX_UPDATE_INTERVAL_SEC), ) - self.hass = hass self.entry = entry self.data = device @@ -157,9 +163,10 @@ class SwitcherDeviceWrapper(update_coordinator.DataUpdateCoordinator): """Switcher device mac address.""" return self.data.mac_address # type: ignore[no-any-return] - async def async_setup(self) -> None: - """Set up the wrapper.""" - dev_reg = await device_registry.async_get_registry(self.hass) + @callback + def async_setup(self) -> None: + """Set up the coordinator.""" + dev_reg = device_registry.async_get(self.hass) dev_reg.async_get_or_create( config_entry_id=self.entry.entry_id, connections={(device_registry.CONNECTION_NETWORK_MAC, self.mac_address)}, diff --git a/homeassistant/components/switcher_kis/sensor.py b/homeassistant/components/switcher_kis/sensor.py index e070bd52d0d..d694bfee380 100644 --- a/homeassistant/components/switcher_kis/sensor.py +++ b/homeassistant/components/switcher_kis/sensor.py @@ -20,7 +20,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType from homeassistant.helpers.update_coordinator import CoordinatorEntity -from . import SwitcherDeviceWrapper +from . import SwitcherDataUpdateCoordinator from .const import SIGNAL_DEVICE_ADD @@ -75,16 +75,16 @@ async def async_setup_entry( """Set up Switcher sensor from config entry.""" @callback - def async_add_sensors(wrapper: SwitcherDeviceWrapper) -> None: + def async_add_sensors(coordinator: SwitcherDataUpdateCoordinator) -> None: """Add sensors from Switcher device.""" - if wrapper.data.device_type.category == DeviceCategory.POWER_PLUG: + if coordinator.data.device_type.category == DeviceCategory.POWER_PLUG: async_add_entities( - SwitcherSensorEntity(wrapper, attribute, info) + SwitcherSensorEntity(coordinator, attribute, info) for attribute, info in POWER_PLUG_SENSORS.items() ) - elif wrapper.data.device_type.category == DeviceCategory.WATER_HEATER: + elif coordinator.data.device_type.category == DeviceCategory.WATER_HEATER: async_add_entities( - SwitcherSensorEntity(wrapper, attribute, info) + SwitcherSensorEntity(coordinator, attribute, info) for attribute, info in WATER_HEATER_SENSORS.items() ) @@ -98,30 +98,31 @@ class SwitcherSensorEntity(CoordinatorEntity, SensorEntity): def __init__( self, - wrapper: SwitcherDeviceWrapper, + coordinator: SwitcherDataUpdateCoordinator, attribute: str, description: AttributeDescription, ) -> None: """Initialize the entity.""" - super().__init__(wrapper) - self.wrapper = wrapper + super().__init__(coordinator) self.attribute = attribute # Entity class attributes - self._attr_name = f"{wrapper.name} {description.name}" + self._attr_name = f"{coordinator.name} {description.name}" self._attr_icon = description.icon self._attr_native_unit_of_measurement = description.unit self._attr_device_class = description.device_class self._attr_entity_registry_enabled_default = description.default_enabled - self._attr_unique_id = f"{wrapper.device_id}-{wrapper.mac_address}-{attribute}" + self._attr_unique_id = ( + f"{coordinator.device_id}-{coordinator.mac_address}-{attribute}" + ) self._attr_device_info = { "connections": { - (device_registry.CONNECTION_NETWORK_MAC, wrapper.mac_address) + (device_registry.CONNECTION_NETWORK_MAC, coordinator.mac_address) } } @property def native_value(self) -> StateType: """Return value of sensor.""" - return getattr(self.wrapper.data, self.attribute) # type: ignore[no-any-return] + return getattr(self.coordinator.data, self.attribute) # type: ignore[no-any-return] diff --git a/homeassistant/components/switcher_kis/switch.py b/homeassistant/components/switcher_kis/switch.py index 0eeeb881f45..8b93e422e2a 100644 --- a/homeassistant/components/switcher_kis/switch.py +++ b/homeassistant/components/switcher_kis/switch.py @@ -26,7 +26,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity -from . import SwitcherDeviceWrapper +from . import SwitcherDataUpdateCoordinator from .const import ( CONF_AUTO_OFF, CONF_TIMER_MINUTES, @@ -69,12 +69,12 @@ async def async_setup_entry( ) @callback - def async_add_switch(wrapper: SwitcherDeviceWrapper) -> None: + def async_add_switch(coordinator: SwitcherDataUpdateCoordinator) -> None: """Add switch from Switcher device.""" - if wrapper.data.device_type.category == DeviceCategory.POWER_PLUG: - async_add_entities([SwitcherPowerPlugSwitchEntity(wrapper)]) - elif wrapper.data.device_type.category == DeviceCategory.WATER_HEATER: - async_add_entities([SwitcherWaterHeaterSwitchEntity(wrapper)]) + if coordinator.data.device_type.category == DeviceCategory.POWER_PLUG: + async_add_entities([SwitcherPowerPlugSwitchEntity(coordinator)]) + elif coordinator.data.device_type.category == DeviceCategory.WATER_HEATER: + async_add_entities([SwitcherWaterHeaterSwitchEntity(coordinator)]) config_entry.async_on_unload( async_dispatcher_connect(hass, SIGNAL_DEVICE_ADD, async_add_switch) @@ -84,18 +84,17 @@ async def async_setup_entry( class SwitcherBaseSwitchEntity(CoordinatorEntity, SwitchEntity): """Representation of a Switcher switch entity.""" - def __init__(self, wrapper: SwitcherDeviceWrapper) -> None: + def __init__(self, coordinator: SwitcherDataUpdateCoordinator) -> None: """Initialize the entity.""" - super().__init__(wrapper) - self.wrapper = wrapper + super().__init__(coordinator) self.control_result: bool | None = None # Entity class attributes - self._attr_name = wrapper.name - self._attr_unique_id = f"{wrapper.device_id}-{wrapper.mac_address}" + self._attr_name = coordinator.name + self._attr_unique_id = f"{coordinator.device_id}-{coordinator.mac_address}" self._attr_device_info = { "connections": { - (device_registry.CONNECTION_NETWORK_MAC, wrapper.mac_address) + (device_registry.CONNECTION_NETWORK_MAC, coordinator.mac_address) } } @@ -113,7 +112,7 @@ class SwitcherBaseSwitchEntity(CoordinatorEntity, SwitchEntity): try: async with SwitcherApi( - self.wrapper.data.ip_address, self.wrapper.device_id + self.coordinator.data.ip_address, self.coordinator.data.device_id ) as swapi: response = await getattr(swapi, api)(*args) except (asyncio.TimeoutError, OSError, RuntimeError) as err: @@ -127,7 +126,7 @@ class SwitcherBaseSwitchEntity(CoordinatorEntity, SwitchEntity): args, response or error, ) - self.wrapper.last_update_success = False + self.coordinator.last_update_success = False @property def is_on(self) -> bool: @@ -135,7 +134,7 @@ class SwitcherBaseSwitchEntity(CoordinatorEntity, SwitchEntity): if self.control_result is not None: return self.control_result - return bool(self.wrapper.data.device_state == DeviceState.ON) + return bool(self.coordinator.data.device_state == DeviceState.ON) async def async_turn_on(self, **kwargs: Any) -> None: """Turn the entity on.""" diff --git a/tests/components/switcher_kis/test_config_flow.py b/tests/components/switcher_kis/test_config_flow.py index 07a2396a0d9..2029e4a8ef3 100644 --- a/tests/components/switcher_kis/test_config_flow.py +++ b/tests/components/switcher_kis/test_config_flow.py @@ -44,10 +44,11 @@ async def test_import(hass): ) async def test_user_setup(hass, mock_bridge): """Test we can finish a config flow.""" - with patch("homeassistant.components.switcher_kis.utils.asyncio.sleep"): + with patch("homeassistant.components.switcher_kis.utils.DISCOVERY_TIME_SEC", 0): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) + await hass.async_block_till_done() assert mock_bridge.is_running is False assert len(hass.data[DOMAIN][DATA_DISCOVERY].result()) == 2 @@ -68,10 +69,11 @@ async def test_user_setup(hass, mock_bridge): async def test_user_setup_abort_no_devices_found(hass, mock_bridge): """Test we abort a config flow if no devices found.""" - with patch("homeassistant.components.switcher_kis.utils.asyncio.sleep"): + with patch("homeassistant.components.switcher_kis.utils.DISCOVERY_TIME_SEC", 0): result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_USER} ) + await hass.async_block_till_done() assert mock_bridge.is_running is False assert len(hass.data[DOMAIN][DATA_DISCOVERY].result()) == 0