mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Simplify vesync init loading (#135052)
This commit is contained in:
parent
475a2fb828
commit
bce7e9ba5e
@ -9,17 +9,14 @@ from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
|
||||
from .common import async_process_devices
|
||||
from .common import async_generate_device_list
|
||||
from .const import (
|
||||
DOMAIN,
|
||||
SERVICE_UPDATE_DEVS,
|
||||
VS_COORDINATOR,
|
||||
VS_DEVICES,
|
||||
VS_DISCOVERY,
|
||||
VS_FANS,
|
||||
VS_LIGHTS,
|
||||
VS_MANAGER,
|
||||
VS_SENSORS,
|
||||
VS_SWITCHES,
|
||||
)
|
||||
from .coordinator import VeSyncDataCoordinator
|
||||
|
||||
@ -43,10 +40,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
||||
_LOGGER.error("Unable to login to the VeSync server")
|
||||
return False
|
||||
|
||||
device_dict = await async_process_devices(hass, manager)
|
||||
|
||||
forward_setups = hass.config_entries.async_forward_entry_setups
|
||||
|
||||
hass.data[DOMAIN] = {}
|
||||
hass.data[DOMAIN][VS_MANAGER] = manager
|
||||
|
||||
@ -55,83 +48,25 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
||||
# Store coordinator at domain level since only single integration instance is permitted.
|
||||
hass.data[DOMAIN][VS_COORDINATOR] = coordinator
|
||||
|
||||
switches = hass.data[DOMAIN][VS_SWITCHES] = []
|
||||
fans = hass.data[DOMAIN][VS_FANS] = []
|
||||
lights = hass.data[DOMAIN][VS_LIGHTS] = []
|
||||
sensors = hass.data[DOMAIN][VS_SENSORS] = []
|
||||
platforms = []
|
||||
hass.data[DOMAIN][VS_DEVICES] = await async_generate_device_list(hass, manager)
|
||||
|
||||
if device_dict[VS_SWITCHES]:
|
||||
switches.extend(device_dict[VS_SWITCHES])
|
||||
platforms.append(Platform.SWITCH)
|
||||
|
||||
if device_dict[VS_FANS]:
|
||||
fans.extend(device_dict[VS_FANS])
|
||||
platforms.append(Platform.FAN)
|
||||
|
||||
if device_dict[VS_LIGHTS]:
|
||||
lights.extend(device_dict[VS_LIGHTS])
|
||||
platforms.append(Platform.LIGHT)
|
||||
|
||||
if device_dict[VS_SENSORS]:
|
||||
sensors.extend(device_dict[VS_SENSORS])
|
||||
platforms.append(Platform.SENSOR)
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(config_entry, platforms)
|
||||
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
|
||||
|
||||
async def async_new_device_discovery(service: ServiceCall) -> None:
|
||||
"""Discover if new devices should be added."""
|
||||
manager = hass.data[DOMAIN][VS_MANAGER]
|
||||
switches = hass.data[DOMAIN][VS_SWITCHES]
|
||||
fans = hass.data[DOMAIN][VS_FANS]
|
||||
lights = hass.data[DOMAIN][VS_LIGHTS]
|
||||
sensors = hass.data[DOMAIN][VS_SENSORS]
|
||||
devices = hass.data[DOMAIN][VS_DEVICES]
|
||||
|
||||
dev_dict = await async_process_devices(hass, manager)
|
||||
switch_devs = dev_dict.get(VS_SWITCHES, [])
|
||||
fan_devs = dev_dict.get(VS_FANS, [])
|
||||
light_devs = dev_dict.get(VS_LIGHTS, [])
|
||||
sensor_devs = dev_dict.get(VS_SENSORS, [])
|
||||
new_devices = await async_generate_device_list(hass, manager)
|
||||
|
||||
switch_set = set(switch_devs)
|
||||
new_switches = list(switch_set.difference(switches))
|
||||
if new_switches and switches:
|
||||
switches.extend(new_switches)
|
||||
async_dispatcher_send(hass, VS_DISCOVERY.format(VS_SWITCHES), new_switches)
|
||||
device_set = set(new_devices)
|
||||
new_devices = list(device_set.difference(devices))
|
||||
if new_devices and devices:
|
||||
devices.extend(new_devices)
|
||||
async_dispatcher_send(hass, VS_DISCOVERY.format(VS_DEVICES), new_devices)
|
||||
return
|
||||
if new_switches and not switches:
|
||||
switches.extend(new_switches)
|
||||
hass.async_create_task(forward_setups(config_entry, [Platform.SWITCH]))
|
||||
|
||||
fan_set = set(fan_devs)
|
||||
new_fans = list(fan_set.difference(fans))
|
||||
if new_fans and fans:
|
||||
fans.extend(new_fans)
|
||||
async_dispatcher_send(hass, VS_DISCOVERY.format(VS_FANS), new_fans)
|
||||
return
|
||||
if new_fans and not fans:
|
||||
fans.extend(new_fans)
|
||||
hass.async_create_task(forward_setups(config_entry, [Platform.FAN]))
|
||||
|
||||
light_set = set(light_devs)
|
||||
new_lights = list(light_set.difference(lights))
|
||||
if new_lights and lights:
|
||||
lights.extend(new_lights)
|
||||
async_dispatcher_send(hass, VS_DISCOVERY.format(VS_LIGHTS), new_lights)
|
||||
return
|
||||
if new_lights and not lights:
|
||||
lights.extend(new_lights)
|
||||
hass.async_create_task(forward_setups(config_entry, [Platform.LIGHT]))
|
||||
|
||||
sensor_set = set(sensor_devs)
|
||||
new_sensors = list(sensor_set.difference(sensors))
|
||||
if new_sensors and sensors:
|
||||
sensors.extend(new_sensors)
|
||||
async_dispatcher_send(hass, VS_DISCOVERY.format(VS_SENSORS), new_sensors)
|
||||
return
|
||||
if new_sensors and not sensors:
|
||||
sensors.extend(new_sensors)
|
||||
hass.async_create_task(forward_setups(config_entry, [Platform.SENSOR]))
|
||||
if new_devices and not devices:
|
||||
devices.extend(new_devices)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_UPDATE_DEVS, async_new_device_discovery
|
||||
@ -142,18 +77,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
in_use_platforms = []
|
||||
if hass.data[DOMAIN][VS_SWITCHES]:
|
||||
in_use_platforms.append(Platform.SWITCH)
|
||||
if hass.data[DOMAIN][VS_FANS]:
|
||||
in_use_platforms.append(Platform.FAN)
|
||||
if hass.data[DOMAIN][VS_LIGHTS]:
|
||||
in_use_platforms.append(Platform.LIGHT)
|
||||
if hass.data[DOMAIN][VS_SENSORS]:
|
||||
in_use_platforms.append(Platform.SENSOR)
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(
|
||||
entry, in_use_platforms
|
||||
)
|
||||
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
if unload_ok:
|
||||
hass.data.pop(DOMAIN)
|
||||
|
||||
|
@ -7,45 +7,20 @@ from pyvesync.vesyncbasedevice import VeSyncBaseDevice
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import VS_FANS, VS_LIGHTS, VS_SENSORS, VS_SWITCHES
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_process_devices(
|
||||
async def async_generate_device_list(
|
||||
hass: HomeAssistant, manager: VeSync
|
||||
) -> dict[str, list[VeSyncBaseDevice]]:
|
||||
) -> list[VeSyncBaseDevice]:
|
||||
"""Assign devices to proper component."""
|
||||
devices: dict[str, list[VeSyncBaseDevice]] = {}
|
||||
devices[VS_SWITCHES] = []
|
||||
devices[VS_FANS] = []
|
||||
devices[VS_LIGHTS] = []
|
||||
devices[VS_SENSORS] = []
|
||||
devices: list[VeSyncBaseDevice] = []
|
||||
|
||||
await hass.async_add_executor_job(manager.update)
|
||||
|
||||
if manager.fans:
|
||||
devices[VS_FANS].extend(manager.fans)
|
||||
# Expose fan sensors separately
|
||||
devices[VS_SENSORS].extend(manager.fans)
|
||||
_LOGGER.debug("%d VeSync fans found", len(manager.fans))
|
||||
|
||||
if manager.bulbs:
|
||||
devices[VS_LIGHTS].extend(manager.bulbs)
|
||||
_LOGGER.debug("%d VeSync lights found", len(manager.bulbs))
|
||||
|
||||
if manager.outlets:
|
||||
devices[VS_SWITCHES].extend(manager.outlets)
|
||||
# Expose outlets' voltage, power & energy usage as separate sensors
|
||||
devices[VS_SENSORS].extend(manager.outlets)
|
||||
_LOGGER.debug("%d VeSync outlets found", len(manager.outlets))
|
||||
|
||||
if manager.switches:
|
||||
for switch in manager.switches:
|
||||
if not switch.is_dimmable():
|
||||
devices[VS_SWITCHES].append(switch)
|
||||
else:
|
||||
devices[VS_LIGHTS].append(switch)
|
||||
_LOGGER.debug("%d VeSync switches found", len(manager.switches))
|
||||
devices.extend(manager.fans)
|
||||
devices.extend(manager.bulbs)
|
||||
devices.extend(manager.outlets)
|
||||
devices.extend(manager.switches)
|
||||
|
||||
return devices
|
||||
|
@ -17,11 +17,7 @@ total would be 2880.
|
||||
Using 30 seconds interval gives 8640 for 3 devices which
|
||||
exceeds the quota of 7700.
|
||||
"""
|
||||
|
||||
VS_SWITCHES = "switches"
|
||||
VS_FANS = "fans"
|
||||
VS_LIGHTS = "lights"
|
||||
VS_SENSORS = "sensors"
|
||||
VS_DEVICES = "devices"
|
||||
VS_COORDINATOR = "coordinator"
|
||||
VS_MANAGER = "manager"
|
||||
|
||||
|
@ -24,8 +24,8 @@ from .const import (
|
||||
DOMAIN,
|
||||
SKU_TO_BASE_DEVICE,
|
||||
VS_COORDINATOR,
|
||||
VS_DEVICES,
|
||||
VS_DISCOVERY,
|
||||
VS_FANS,
|
||||
)
|
||||
from .coordinator import VeSyncDataCoordinator
|
||||
from .entity import VeSyncBaseEntity
|
||||
@ -74,10 +74,10 @@ async def async_setup_entry(
|
||||
_setup_entities(devices, async_add_entities, coordinator)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_FANS), discover)
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_DEVICES), discover)
|
||||
)
|
||||
|
||||
_setup_entities(hass.data[DOMAIN][VS_FANS], async_add_entities, coordinator)
|
||||
_setup_entities(hass.data[DOMAIN][VS_DEVICES], async_add_entities, coordinator)
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -17,7 +17,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util import color as color_util
|
||||
|
||||
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_COORDINATOR, VS_DISCOVERY, VS_LIGHTS
|
||||
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_COORDINATOR, VS_DEVICES, VS_DISCOVERY
|
||||
from .coordinator import VeSyncDataCoordinator
|
||||
from .entity import VeSyncBaseEntity
|
||||
|
||||
@ -41,10 +41,10 @@ async def async_setup_entry(
|
||||
_setup_entities(devices, async_add_entities, coordinator)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_LIGHTS), discover)
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_DEVICES), discover)
|
||||
)
|
||||
|
||||
_setup_entities(hass.data[DOMAIN][VS_LIGHTS], async_add_entities, coordinator)
|
||||
_setup_entities(hass.data[DOMAIN][VS_DEVICES], async_add_entities, coordinator)
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -36,8 +36,8 @@ from .const import (
|
||||
DOMAIN,
|
||||
SKU_TO_BASE_DEVICE,
|
||||
VS_COORDINATOR,
|
||||
VS_DEVICES,
|
||||
VS_DISCOVERY,
|
||||
VS_SENSORS,
|
||||
)
|
||||
from .coordinator import VeSyncDataCoordinator
|
||||
from .entity import VeSyncBaseEntity
|
||||
@ -204,10 +204,10 @@ async def async_setup_entry(
|
||||
_setup_entities(devices, async_add_entities, coordinator)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_SENSORS), discover)
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_DEVICES), discover)
|
||||
)
|
||||
|
||||
_setup_entities(hass.data[DOMAIN][VS_SENSORS], async_add_entities, coordinator)
|
||||
_setup_entities(hass.data[DOMAIN][VS_DEVICES], async_add_entities, coordinator)
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -11,7 +11,7 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_COORDINATOR, VS_DISCOVERY, VS_SWITCHES
|
||||
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_COORDINATOR, VS_DEVICES, VS_DISCOVERY
|
||||
from .coordinator import VeSyncDataCoordinator
|
||||
from .entity import VeSyncBaseEntity
|
||||
|
||||
@ -33,10 +33,10 @@ async def async_setup_entry(
|
||||
_setup_entities(devices, async_add_entities, coordinator)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_SWITCHES), discover)
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_DEVICES), discover)
|
||||
)
|
||||
|
||||
_setup_entities(hass.data[DOMAIN][VS_SWITCHES], async_add_entities, coordinator)
|
||||
_setup_entities(hass.data[DOMAIN][VS_DEVICES], async_add_entities, coordinator)
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -5,16 +5,9 @@ from unittest.mock import Mock, patch
|
||||
import pytest
|
||||
from pyvesync import VeSync
|
||||
|
||||
from homeassistant.components.vesync import async_setup_entry
|
||||
from homeassistant.components.vesync.const import (
|
||||
DOMAIN,
|
||||
VS_FANS,
|
||||
VS_LIGHTS,
|
||||
VS_MANAGER,
|
||||
VS_SENSORS,
|
||||
VS_SWITCHES,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.components.vesync import SERVICE_UPDATE_DEVS, async_setup_entry
|
||||
from homeassistant.components.vesync.const import DOMAIN, VS_DEVICES, VS_MANAGER
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
@ -30,7 +23,9 @@ async def test_async_setup_entry__not_login(
|
||||
|
||||
with (
|
||||
patch.object(hass.config_entries, "async_forward_entry_setups") as setups_mock,
|
||||
patch("homeassistant.components.vesync.async_process_devices") as process_mock,
|
||||
patch(
|
||||
"homeassistant.components.vesync.async_generate_device_list"
|
||||
) as process_mock,
|
||||
):
|
||||
assert not await async_setup_entry(hass, config_entry)
|
||||
await hass.async_block_till_done()
|
||||
@ -52,20 +47,22 @@ async def test_async_setup_entry__no_devices(
|
||||
await hass.async_block_till_done()
|
||||
assert setups_mock.call_count == 1
|
||||
assert setups_mock.call_args.args[0] == config_entry
|
||||
assert setups_mock.call_args.args[1] == []
|
||||
assert setups_mock.call_args.args[1] == [
|
||||
Platform.FAN,
|
||||
Platform.LIGHT,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
]
|
||||
|
||||
assert manager.login.call_count == 1
|
||||
assert hass.data[DOMAIN][VS_MANAGER] == manager
|
||||
assert not hass.data[DOMAIN][VS_SWITCHES]
|
||||
assert not hass.data[DOMAIN][VS_FANS]
|
||||
assert not hass.data[DOMAIN][VS_LIGHTS]
|
||||
assert not hass.data[DOMAIN][VS_SENSORS]
|
||||
assert not hass.data[DOMAIN][VS_DEVICES]
|
||||
|
||||
|
||||
async def test_async_setup_entry__loads_fans(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry, manager: VeSync, fan
|
||||
) -> None:
|
||||
"""Test setup connects to vesync and loads fan platform."""
|
||||
"""Test setup connects to vesync and loads fan."""
|
||||
fans = [fan]
|
||||
manager.fans = fans
|
||||
manager._dev_list = {
|
||||
@ -78,10 +75,34 @@ async def test_async_setup_entry__loads_fans(
|
||||
await hass.async_block_till_done()
|
||||
assert setups_mock.call_count == 1
|
||||
assert setups_mock.call_args.args[0] == config_entry
|
||||
assert setups_mock.call_args.args[1] == [Platform.FAN, Platform.SENSOR]
|
||||
assert setups_mock.call_args.args[1] == [
|
||||
Platform.FAN,
|
||||
Platform.LIGHT,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
]
|
||||
assert manager.login.call_count == 1
|
||||
assert hass.data[DOMAIN][VS_MANAGER] == manager
|
||||
assert not hass.data[DOMAIN][VS_SWITCHES]
|
||||
assert hass.data[DOMAIN][VS_FANS] == [fan]
|
||||
assert not hass.data[DOMAIN][VS_LIGHTS]
|
||||
assert hass.data[DOMAIN][VS_SENSORS] == [fan]
|
||||
assert hass.data[DOMAIN][VS_DEVICES] == [fan]
|
||||
|
||||
|
||||
async def test_async_new_device_discovery__loads_fans(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry, manager: VeSync, fan
|
||||
) -> None:
|
||||
"""Test setup connects to vesync and loads fan as an update call."""
|
||||
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
# Assert platforms loaded
|
||||
await hass.async_block_till_done()
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
assert not hass.data[DOMAIN][VS_DEVICES]
|
||||
fans = [fan]
|
||||
manager.fans = fans
|
||||
manager._dev_list = {
|
||||
"fans": fans,
|
||||
}
|
||||
await hass.services.async_call(DOMAIN, SERVICE_UPDATE_DEVS, {}, blocking=True)
|
||||
|
||||
assert manager.login.call_count == 1
|
||||
assert hass.data[DOMAIN][VS_MANAGER] == manager
|
||||
assert hass.data[DOMAIN][VS_DEVICES] == [fan]
|
||||
|
Loading…
x
Reference in New Issue
Block a user