Simplify setup of deCONZ platforms (#72453)

This commit is contained in:
Robert Svensson 2022-05-25 05:48:09 +02:00 committed by GitHub
parent fbeaf200e4
commit e60b247b51
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 130 additions and 134 deletions

View file

@ -83,16 +83,11 @@ async def async_setup_entry(
[DeconzAlarmControlPanel(sensor, gateway, alarm_system_id)]
)
config_entry.async_on_unload(
gateway.api.sensors.ancillary_control.subscribe(
gateway.evaluate_add_device(async_add_sensor),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_sensor,
gateway.api.sensors.ancillary_control,
)
for sensor_id in gateway.api.sensors.ancillary_control:
async_add_sensor(EventType.ADDED, sensor_id)
class DeconzAlarmControlPanel(DeconzDevice, AlarmControlPanelEntity):
"""Representation of a deCONZ alarm control panel."""

View file

@ -207,14 +207,10 @@ async def async_setup_entry(
async_add_entities([DeconzBinarySensor(sensor, gateway, description)])
config_entry.async_on_unload(
gateway.api.sensors.subscribe(
gateway.evaluate_add_device(async_add_sensor),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_sensor,
gateway.api.sensors,
)
for sensor_id in gateway.api.sensors:
async_add_sensor(EventType.ADDED, sensor_id)
@callback
def async_reload_clip_sensors() -> None:

View file

@ -65,16 +65,11 @@ async def async_setup_entry(
for description in ENTITY_DESCRIPTIONS.get(PydeconzScene, [])
)
config_entry.async_on_unload(
gateway.api.scenes.subscribe(
async_add_scene,
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_scene,
gateway.api.scenes,
)
for scene_id in gateway.api.scenes:
async_add_scene(EventType.ADDED, scene_id)
class DeconzButton(DeconzSceneMixin, ButtonEntity):
"""Representation of a deCONZ button entity."""

View file

@ -104,14 +104,10 @@ async def async_setup_entry(
return
async_add_entities([DeconzThermostat(climate, gateway)])
config_entry.async_on_unload(
gateway.api.sensors.thermostat.subscribe(
gateway.evaluate_add_device(async_add_climate),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_climate,
gateway.api.sensors.thermostat,
)
for climate_id in gateway.api.sensors.thermostat:
async_add_climate(EventType.ADDED, climate_id)
@callback
def async_reload_clip_sensors() -> None:

View file

@ -43,14 +43,10 @@ async def async_setup_entry(
cover = gateway.api.lights.covers[cover_id]
async_add_entities([DeconzCover(cover, gateway)])
config_entry.async_on_unload(
gateway.api.lights.covers.subscribe(
gateway.evaluate_add_device(async_add_cover),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_cover,
gateway.api.lights.covers,
)
for cover_id in gateway.api.lights.covers:
async_add_cover(EventType.ADDED, cover_id)
class DeconzCover(DeconzDevice, CoverEntity):

View file

@ -58,29 +58,18 @@ async def async_setup_events(gateway: DeconzGateway) -> None:
elif isinstance(sensor, AncillaryControl):
new_event = DeconzAlarmEvent(sensor, gateway)
else:
return None
gateway.hass.async_create_task(new_event.async_update_device_registry())
gateway.events.append(new_event)
gateway.config_entry.async_on_unload(
gateway.api.sensors.ancillary_control.subscribe(
gateway.evaluate_add_device(async_add_sensor),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_sensor,
gateway.api.sensors.switch,
)
gateway.config_entry.async_on_unload(
gateway.api.sensors.switch.subscribe(
gateway.evaluate_add_device(async_add_sensor),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_sensor,
gateway.api.sensors.ancillary_control,
)
for sensor_id in gateway.api.sensors:
async_add_sensor(EventType.ADDED, sensor_id)
@callback
def async_unload_events(gateway: DeconzGateway) -> None:

View file

@ -48,14 +48,10 @@ async def async_setup_entry(
fan = gateway.api.lights.fans[fan_id]
async_add_entities([DeconzFan(fan, gateway)])
config_entry.async_on_unload(
gateway.api.lights.fans.subscribe(
gateway.evaluate_add_device(async_add_fan),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_fan,
gateway.api.lights.fans,
)
for fan_id in gateway.api.lights.fans:
async_add_fan(EventType.ADDED, fan_id)
class DeconzFan(DeconzDevice, FanEntity):

View file

@ -9,6 +9,7 @@ from typing import TYPE_CHECKING, Any, cast
import async_timeout
from pydeconz import DeconzSession, errors
from pydeconz.interfaces.api import APIItems, GroupedAPIItems
from pydeconz.models.event import EventType
from homeassistant.config_entries import SOURCE_HASSIO, ConfigEntry
@ -105,9 +106,11 @@ class DeconzGateway:
)
@callback
def evaluate_add_device(
self, add_device_callback: Callable[[EventType, str], None]
) -> Callable[[EventType, str], None]:
def register_platform_add_device_callback(
self,
add_device_callback: Callable[[EventType, str], None],
deconz_device_interface: APIItems | GroupedAPIItems,
) -> None:
"""Wrap add_device_callback to check allow_new_devices option."""
def async_add_device(event: EventType, device_id: str) -> None:
@ -117,11 +120,19 @@ class DeconzGateway:
Device_refresh is expected to load new devices.
"""
if not self.option_allow_new_devices and not self.ignore_state_updates:
self.ignored_devices.add((add_device_callback, device_id))
self.ignored_devices.add((async_add_device, device_id))
return
add_device_callback(event, device_id)
return async_add_device
self.config_entry.async_on_unload(
deconz_device_interface.subscribe(
async_add_device,
EventType.ADDED,
)
)
for device_id in deconz_device_interface:
add_device_callback(EventType.ADDED, device_id)
@callback
def load_ignored_devices(self) -> None:
@ -191,6 +202,8 @@ class DeconzGateway:
"""Manage entities affected by config entry options."""
deconz_ids = []
# Allow CLIP sensors
if self.option_allow_clip_sensor:
async_dispatcher_send(self.hass, self.signal_reload_clip_sensors)
@ -201,6 +214,8 @@ class DeconzGateway:
if sensor.type.startswith("CLIP")
]
# Allow Groups
if self.option_allow_deconz_groups:
if not self._option_allow_deconz_groups:
async_dispatcher_send(self.hass, self.signal_reload_groups)
@ -209,13 +224,17 @@ class DeconzGateway:
self._option_allow_deconz_groups = self.option_allow_deconz_groups
# Allow adding new devices
option_allow_new_devices = self.config_entry.options.get(
CONF_ALLOW_NEW_DEVICES, DEFAULT_ALLOW_NEW_DEVICES
)
if option_allow_new_devices and not self.option_allow_new_devices:
self.load_ignored_devices()
if option_allow_new_devices != self.option_allow_new_devices:
self.option_allow_new_devices = option_allow_new_devices
if option_allow_new_devices:
self.load_ignored_devices()
self.option_allow_new_devices = option_allow_new_devices
# Remove entities based on above categories
entity_registry = er.async_get(self.hass)

View file

@ -93,23 +93,15 @@ async def async_setup_entry(
async_add_entities([DeconzLight(light, gateway)])
config_entry.async_on_unload(
gateway.api.lights.lights.subscribe(
gateway.evaluate_add_device(async_add_light),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_light,
gateway.api.lights.lights,
)
for light_id in gateway.api.lights.lights:
async_add_light(EventType.ADDED, light_id)
config_entry.async_on_unload(
gateway.api.lights.fans.subscribe(
async_add_light,
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_light,
gateway.api.lights.fans,
)
for light_id in gateway.api.lights.fans:
async_add_light(EventType.ADDED, light_id)
@callback
def async_add_group(_: EventType, group_id: str) -> None:

View file

@ -32,14 +32,10 @@ async def async_setup_entry(
lock = gateway.api.lights.locks[lock_id]
async_add_entities([DeconzLock(lock, gateway)])
config_entry.async_on_unload(
gateway.api.lights.locks.subscribe(
gateway.evaluate_add_device(async_add_lock_from_light),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_lock_from_light,
gateway.api.lights.locks,
)
for lock_id in gateway.api.lights.locks:
async_add_lock_from_light(EventType.ADDED, lock_id)
@callback
def async_add_lock_from_sensor(_: EventType, lock_id: str) -> None:
@ -47,14 +43,10 @@ async def async_setup_entry(
lock = gateway.api.sensors.door_lock[lock_id]
async_add_entities([DeconzLock(lock, gateway)])
config_entry.async_on_unload(
gateway.api.sensors.door_lock.subscribe(
gateway.evaluate_add_device(async_add_lock_from_sensor),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_lock_from_sensor,
gateway.api.sensors.door_lock,
)
for lock_id in gateway.api.sensors.door_lock:
async_add_lock_from_sensor(EventType.ADDED, lock_id)
class DeconzLock(DeconzDevice, LockEntity):

View file

@ -75,14 +75,10 @@ async def async_setup_entry(
continue
async_add_entities([DeconzNumber(sensor, gateway, description)])
config_entry.async_on_unload(
gateway.api.sensors.presence.subscribe(
gateway.evaluate_add_device(async_add_sensor),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_sensor,
gateway.api.sensors.presence,
)
for sensor_id in gateway.api.sensors.presence:
async_add_sensor(EventType.ADDED, sensor_id)
class DeconzNumber(DeconzDevice, NumberEntity):

View file

@ -30,16 +30,11 @@ async def async_setup_entry(
scene = gateway.api.scenes[scene_id]
async_add_entities([DeconzScene(scene, gateway)])
config_entry.async_on_unload(
gateway.api.scenes.subscribe(
async_add_scene,
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_scene,
gateway.api.scenes,
)
for scene_id in gateway.api.scenes:
async_add_scene(EventType.ADDED, scene_id)
class DeconzScene(DeconzSceneMixin, Scene):
"""Representation of a deCONZ scene."""

View file

@ -264,14 +264,10 @@ async def async_setup_entry(
async_add_entities([DeconzSensor(sensor, gateway, description)])
config_entry.async_on_unload(
gateway.api.sensors.subscribe(
gateway.evaluate_add_device(async_add_sensor),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_sensor,
gateway.api.sensors,
)
for sensor_id in gateway.api.sensors:
async_add_sensor(EventType.ADDED, sensor_id)
@callback
def async_reload_clip_sensors() -> None:

View file

@ -35,14 +35,10 @@ async def async_setup_entry(
siren = gateway.api.lights.sirens[siren_id]
async_add_entities([DeconzSiren(siren, gateway)])
config_entry.async_on_unload(
gateway.api.lights.sirens.subscribe(
gateway.evaluate_add_device(async_add_siren),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_siren,
gateway.api.lights.sirens,
)
for siren_id in gateway.api.lights.sirens:
async_add_siren(EventType.ADDED, siren_id)
class DeconzSiren(DeconzDevice, SirenEntity):

View file

@ -37,14 +37,10 @@ async def async_setup_entry(
return
async_add_entities([DeconzPowerPlug(switch, gateway)])
config_entry.async_on_unload(
gateway.api.lights.lights.subscribe(
gateway.evaluate_add_device(async_add_switch),
EventType.ADDED,
)
gateway.register_platform_add_device_callback(
async_add_switch,
gateway.api.lights.lights,
)
for switch_id in gateway.api.lights.lights:
async_add_switch(EventType.ADDED, switch_id)
class DeconzPowerPlug(DeconzDevice, SwitchEntity):

View file

@ -636,7 +636,7 @@ async def test_add_new_binary_sensor(hass, aioclient_mock, mock_deconz_websocket
assert hass.states.get("binary_sensor.presence_sensor").state == STATE_OFF
async def test_add_new_binary_sensor_ignored(
async def test_add_new_binary_sensor_ignored_load_entities_on_service_call(
hass, aioclient_mock, mock_deconz_websocket
):
"""Test that adding a new binary sensor is not allowed."""
@ -683,3 +683,54 @@ async def test_add_new_binary_sensor_ignored(
assert len(hass.states.async_all()) == 1
assert hass.states.get("binary_sensor.presence_sensor")
async def test_add_new_binary_sensor_ignored_load_entities_on_options_change(
hass, aioclient_mock, mock_deconz_websocket
):
"""Test that adding a new binary sensor is not allowed."""
sensor = {
"name": "Presence sensor",
"type": "ZHAPresence",
"state": {"presence": False},
"config": {"on": True, "reachable": True},
"uniqueid": "00:00:00:00:00:00:00:00-00",
}
event_added_sensor = {
"t": "event",
"e": "added",
"r": "sensors",
"id": "1",
"sensor": sensor,
}
config_entry = await setup_deconz_integration(
hass,
aioclient_mock,
options={CONF_MASTER_GATEWAY: True, CONF_ALLOW_NEW_DEVICES: False},
)
assert len(hass.states.async_all()) == 0
await mock_deconz_websocket(data=event_added_sensor)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 0
assert not hass.states.get("binary_sensor.presence_sensor")
entity_registry = er.async_get(hass)
assert (
len(async_entries_for_config_entry(entity_registry, config_entry.entry_id)) == 0
)
aioclient_mock.clear_requests()
data = {"config": {}, "groups": {}, "lights": {}, "sensors": {"1": sensor}}
mock_deconz_request(aioclient_mock, config_entry.data, data)
hass.config_entries.async_update_entry(
config_entry, options={CONF_ALLOW_NEW_DEVICES: True}
)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 1
assert hass.states.get("binary_sensor.presence_sensor")