Improve tracking of existing entities in deconz (#40265)

* Store all entities in dict

* Use stored unique id to select if to create entity or not

* Remove unnecessary init

* Change so same physical sensor doesnt try to create multiple battery sensors
Change so groups get created properly

* Add controls in tests that entities are logged correctly
This commit is contained in:
Robert Svensson 2020-09-25 22:49:28 +02:00 committed by GitHub
parent e30acfbfee
commit 203c556ba3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 147 additions and 58 deletions

View file

@ -8,6 +8,7 @@ from homeassistant.components.binary_sensor import (
DEVICE_CLASS_OPENING,
DEVICE_CLASS_SMOKE,
DEVICE_CLASS_VIBRATION,
DOMAIN,
BinarySensorEntity,
)
from homeassistant.const import ATTR_TEMPERATURE
@ -39,17 +40,18 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the deCONZ binary sensor."""
gateway = get_gateway_from_config_entry(hass, config_entry)
gateway.entities[DOMAIN] = set()
@callback
def async_add_sensor(sensors, new=True):
def async_add_sensor(sensors):
"""Add binary sensor from deCONZ."""
entities = []
for sensor in sensors:
if (
new
and sensor.BINARY
sensor.BINARY
and sensor.uniqueid not in gateway.entities[DOMAIN]
and (
gateway.option_allow_clip_sensor
or not sensor.type.startswith("CLIP")
@ -73,6 +75,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class DeconzBinarySensor(DeconzDevice, BinarySensorEntity):
"""Representation of a deCONZ binary sensor."""
TYPE = DOMAIN
@callback
def async_update_callback(self, force_update=False, ignore_update=False):
"""Update the sensor's state."""

View file

@ -1,7 +1,7 @@
"""Support for deCONZ climate devices."""
from pydeconz.sensor import Thermostat
from homeassistant.components.climate import ClimateEntity
from homeassistant.components.climate import DOMAIN, ClimateEntity
from homeassistant.components.climate.const import (
HVAC_MODE_AUTO,
HVAC_MODE_HEAT,
@ -29,17 +29,18 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
Thermostats are based on the same device class as sensors in deCONZ.
"""
gateway = get_gateway_from_config_entry(hass, config_entry)
gateway.entities[DOMAIN] = set()
@callback
def async_add_climate(sensors, new=True):
def async_add_climate(sensors):
"""Add climate devices from deCONZ."""
entities = []
for sensor in sensors:
if (
new
and sensor.type in Thermostat.ZHATYPE
sensor.type in Thermostat.ZHATYPE
and sensor.uniqueid not in gateway.entities[DOMAIN]
and (
gateway.option_allow_clip_sensor
or not sensor.type.startswith("CLIP")
@ -61,6 +62,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class DeconzThermostat(DeconzDevice, ClimateEntity):
"""Representation of a deCONZ thermostat."""
TYPE = DOMAIN
@property
def supported_features(self):
"""Return the list of supported features."""

View file

@ -2,6 +2,7 @@
from homeassistant.components.cover import (
ATTR_POSITION,
DEVICE_CLASS_WINDOW,
DOMAIN,
SUPPORT_CLOSE,
SUPPORT_OPEN,
SUPPORT_SET_POSITION,
@ -23,9 +24,10 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up covers for deCONZ component.
Covers are based on same device class as lights in deCONZ.
Covers are based on the same device class as lights in deCONZ.
"""
gateway = get_gateway_from_config_entry(hass, config_entry)
gateway.entities[DOMAIN] = set()
@callback
def async_add_cover(lights):
@ -33,7 +35,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
entities = []
for light in lights:
if light.type in COVER_TYPES:
if (
light.type in COVER_TYPES
and light.uniqueid not in gateway.entities[DOMAIN]
):
entities.append(DeconzCover(light, gateway))
async_add_entities(entities, True)
@ -50,6 +55,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class DeconzCover(DeconzDevice, CoverEntity):
"""Representation of a deCONZ cover."""
TYPE = DOMAIN
def __init__(self, device, gateway):
"""Set up cover device."""
super().__init__(device, gateway)

View file

@ -10,11 +10,17 @@ from .const import DOMAIN as DECONZ_DOMAIN
class DeconzBase:
"""Common base for deconz entities and events."""
TYPE = ""
def __init__(self, device, gateway):
"""Set up device and add update callback to get data from websocket."""
self._device = device
self.gateway = gateway
self.listeners = []
self.gateway.entities[self.TYPE].add(self.unique_id)
async def async_will_remove_from_hass(self) -> None:
"""Remove unique id."""
self.gateway.entities[self.TYPE].remove(self.unique_id)
@property
def unique_id(self):
@ -51,12 +57,6 @@ class DeconzBase:
class DeconzDevice(DeconzBase, Entity):
"""Representation of a deCONZ device."""
def __init__(self, device, gateway):
"""Set up device and add update callback to get data from websocket."""
super().__init__(device, gateway)
self.unsub_dispatcher = None
@property
def entity_registry_enabled_default(self):
"""Return if the entity should be enabled when first added to the entity registry.
@ -72,7 +72,7 @@ class DeconzDevice(DeconzBase, Entity):
"""Subscribe to device events."""
self._device.register_callback(self.async_update_callback)
self.gateway.deconz_ids[self.entity_id] = self._device.deconz_id
self.listeners.append(
self.async_on_remove(
async_dispatcher_connect(
self.hass, self.gateway.signal_reachable, self.async_update_callback
)
@ -83,8 +83,7 @@ class DeconzDevice(DeconzBase, Entity):
self._device.remove_callback(self.async_update_callback)
if self.entity_id in self.gateway.deconz_ids:
del self.gateway.deconz_ids[self.entity_id]
for unsub_dispatcher in self.listeners:
unsub_dispatcher()
await super().async_will_remove_from_hass()
@callback
def async_update_callback(self, force_update=False, ignore_update=False):

View file

@ -11,19 +11,25 @@ from .deconz_device import DeconzBase
CONF_DECONZ_EVENT = "deconz_event"
EVENT = "Event"
async def async_setup_events(gateway) -> None:
"""Set up the deCONZ events."""
gateway.entities[EVENT] = set()
@callback
def async_add_sensor(sensors, new=True):
def async_add_sensor(sensors):
"""Create DeconzEvent."""
for sensor in sensors:
if not gateway.option_allow_clip_sensor and sensor.type.startswith("CLIP"):
continue
if not new or sensor.type not in Switch.ZHATYPE:
if (
sensor.type not in Switch.ZHATYPE
or sensor.uniqueid in gateway.entities[EVENT]
):
continue
new_event = DeconzEvent(sensor, gateway)
@ -44,7 +50,7 @@ async def async_setup_events(gateway) -> None:
async def async_unload_events(gateway) -> None:
"""Unload all deCONZ events."""
for event in gateway.events:
event.async_will_remove_from_hass()
await event.async_will_remove_from_hass()
gateway.events.clear()
@ -56,6 +62,8 @@ class DeconzEvent(DeconzBase):
instead of a sensor entity in hass.
"""
TYPE = EVENT
def __init__(self, device, gateway):
"""Register callback that will be used for signals."""
super().__init__(device, gateway)
@ -71,11 +79,10 @@ class DeconzEvent(DeconzBase):
"""Return Event device."""
return self._device
@callback
def async_will_remove_from_hass(self) -> None:
async def async_will_remove_from_hass(self) -> None:
"""Disconnect event object when removed."""
self._device.remove_callback(self.async_update_callback)
self._device = None
await super().async_will_remove_from_hass()
@callback
def async_update_callback(self, force_update=False, ignore_update=False):

View file

@ -49,6 +49,8 @@ class DeconzGateway:
self.events = []
self.listeners = []
self.entities = {}
self._current_option_allow_clip_sensor = self.option_allow_clip_sensor
self._current_option_allow_deconz_groups = self.option_allow_deconz_groups

View file

@ -6,6 +6,7 @@ from homeassistant.components.light import (
ATTR_FLASH,
ATTR_HS_COLOR,
ATTR_TRANSITION,
DOMAIN,
EFFECT_COLORLOOP,
FLASH_LONG,
FLASH_SHORT,
@ -40,6 +41,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the deCONZ lights and groups from a config entry."""
gateway = get_gateway_from_config_entry(hass, config_entry)
gateway.entities[DOMAIN] = set()
@callback
def async_add_light(lights):
@ -47,7 +49,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
entities = []
for light in lights:
if light.type not in COVER_TYPES + SWITCH_TYPES:
if (
light.type not in COVER_TYPES + SWITCH_TYPES
and light.uniqueid not in gateway.entities[DOMAIN]
):
entities.append(DeconzLight(light, gateway))
async_add_entities(entities, True)
@ -67,8 +72,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
entities = []
for group in groups:
if group.lights:
entities.append(DeconzGroup(group, gateway))
if not group.lights:
continue
known_groups = list(gateway.entities[DOMAIN])
new_group = DeconzGroup(group, gateway)
if new_group.unique_id not in known_groups:
entities.append(new_group)
async_add_entities(entities, True)
@ -85,6 +95,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class DeconzBaseLight(DeconzDevice, LightEntity):
"""Representation of a deCONZ light."""
TYPE = DOMAIN
def __init__(self, device, gateway):
"""Set up light."""
super().__init__(device, gateway)
@ -223,14 +235,13 @@ class DeconzGroup(DeconzBaseLight):
def __init__(self, device, gateway):
"""Set up group and create an unique id."""
group_id_base = gateway.config_entry.unique_id
if CONF_GROUP_ID_BASE in gateway.config_entry.data:
group_id_base = gateway.config_entry.data[CONF_GROUP_ID_BASE]
self._unique_id = f"{group_id_base}-{device.deconz_id}"
super().__init__(device, gateway)
group_id_base = self.gateway.config_entry.unique_id
if CONF_GROUP_ID_BASE in self.gateway.config_entry.data:
group_id_base = self.gateway.config_entry.data[CONF_GROUP_ID_BASE]
self._unique_id = f"{group_id_base}-{self._device.deconz_id}"
@property
def unique_id(self):
"""Return a unique identifier for this device."""

View file

@ -12,6 +12,7 @@ from pydeconz.sensor import (
Thermostat,
)
from homeassistant.components.sensor import DOMAIN
from homeassistant.const import (
ATTR_TEMPERATURE,
ATTR_VOLTAGE,
@ -74,43 +75,43 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the deCONZ sensors."""
gateway = get_gateway_from_config_entry(hass, config_entry)
gateway.entities[DOMAIN] = set()
batteries = set()
battery_handler = DeconzBatteryHandler(gateway)
@callback
def async_add_sensor(sensors, new=True):
def async_add_sensor(sensors):
"""Add sensors from deCONZ.
Create DeconzSensor if not a ZHAType and not a binary sensor.
Create DeconzBattery if sensor has a battery attribute.
If new is false it means an existing sensor has got a battery state reported.
Create DeconzSensor if not a battery, switch or thermostat and not a binary sensor.
"""
entities = []
for sensor in sensors:
if (
new
and sensor.BINARY is False
and sensor.type
not in Battery.ZHATYPE + Switch.ZHATYPE + Thermostat.ZHATYPE
and (
gateway.option_allow_clip_sensor
or not sensor.type.startswith("CLIP")
)
):
entities.append(DeconzSensor(sensor, gateway))
if not gateway.option_allow_clip_sensor and sensor.type.startswith("CLIP"):
continue
if sensor.battery is not None:
battery_handler.remove_tracker(sensor)
known_batteries = list(gateway.entities[DOMAIN])
new_battery = DeconzBattery(sensor, gateway)
if new_battery.unique_id not in batteries:
batteries.add(new_battery.unique_id)
if new_battery.unique_id not in known_batteries:
entities.append(new_battery)
battery_handler.remove_tracker(sensor)
else:
battery_handler.create_tracker(sensor)
if (
not sensor.BINARY
and sensor.type
not in Battery.ZHATYPE + Switch.ZHATYPE + Thermostat.ZHATYPE
and sensor.uniqueid not in gateway.entities[DOMAIN]
):
entities.append(DeconzSensor(sensor, gateway))
async_add_entities(entities, True)
gateway.listeners.append(
@ -127,6 +128,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class DeconzSensor(DeconzDevice):
"""Representation of a deCONZ sensor."""
TYPE = DOMAIN
@callback
def async_update_callback(self, force_update=False, ignore_update=False):
"""Update the sensor's state."""
@ -192,6 +195,8 @@ class DeconzSensor(DeconzDevice):
class DeconzBattery(DeconzDevice):
"""Battery class for when a device is only represented as an event."""
TYPE = DOMAIN
@callback
def async_update_callback(self, force_update=False, ignore_update=False):
"""Update the battery's state, if needed."""
@ -264,7 +269,6 @@ class DeconzSensorStateTracker:
self.gateway.hass,
self.gateway.async_signal_new_device(NEW_SENSOR),
[self.sensor],
False,
)

View file

@ -1,5 +1,5 @@
"""Support for deCONZ switches."""
from homeassistant.components.switch import SwitchEntity
from homeassistant.components.switch import DOMAIN, SwitchEntity
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
@ -15,9 +15,10 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up switches for deCONZ component.
Switches are based same device class as lights in deCONZ.
Switches are based on the same device class as lights in deCONZ.
"""
gateway = get_gateway_from_config_entry(hass, config_entry)
gateway.entities[DOMAIN] = set()
@callback
def async_add_switch(lights):
@ -26,10 +27,15 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
for light in lights:
if light.type in POWER_PLUGS:
if (
light.type in POWER_PLUGS
and light.uniqueid not in gateway.entities[DOMAIN]
):
entities.append(DeconzPowerPlug(light, gateway))
elif light.type in SIRENS:
elif (
light.type in SIRENS and light.uniqueid not in gateway.entities[DOMAIN]
):
entities.append(DeconzSiren(light, gateway))
async_add_entities(entities, True)
@ -46,6 +52,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class DeconzPowerPlug(DeconzDevice, SwitchEntity):
"""Representation of a deCONZ power plug."""
TYPE = DOMAIN
@property
def is_on(self):
"""Return true if switch is on."""
@ -65,6 +73,8 @@ class DeconzPowerPlug(DeconzDevice, SwitchEntity):
class DeconzSiren(DeconzDevice, SwitchEntity):
"""Representation of a deCONZ siren."""
TYPE = DOMAIN
@property
def is_on(self):
"""Return true if switch is on."""

View file

@ -67,6 +67,7 @@ async def test_no_binary_sensors(hass):
"""Test that no sensors in deconz results in no sensor entities."""
gateway = await setup_deconz_integration(hass)
assert len(gateway.deconz_ids) == 0
assert len(gateway.entities[binary_sensor.DOMAIN]) == 0
assert len(hass.states.async_all()) == 0
@ -80,6 +81,7 @@ async def test_binary_sensors(hass):
assert "binary_sensor.clip_presence_sensor" not in gateway.deconz_ids
assert "binary_sensor.vibration_sensor" in gateway.deconz_ids
assert len(hass.states.async_all()) == 3
assert len(gateway.entities[binary_sensor.DOMAIN]) == 2
presence_sensor = hass.states.get("binary_sensor.presence_sensor")
assert presence_sensor.state == "off"
@ -111,6 +113,7 @@ async def test_binary_sensors(hass):
await gateway.async_reset()
assert len(hass.states.async_all()) == 0
assert len(gateway.entities[binary_sensor.DOMAIN]) == 0
async def test_allow_clip_sensor(hass):
@ -127,6 +130,7 @@ async def test_allow_clip_sensor(hass):
assert "binary_sensor.clip_presence_sensor" in gateway.deconz_ids
assert "binary_sensor.vibration_sensor" in gateway.deconz_ids
assert len(hass.states.async_all()) == 4
assert len(gateway.entities[binary_sensor.DOMAIN]) == 3
presence_sensor = hass.states.get("binary_sensor.presence_sensor")
assert presence_sensor.state == "off"
@ -150,6 +154,7 @@ async def test_allow_clip_sensor(hass):
assert "binary_sensor.clip_presence_sensor" not in gateway.deconz_ids
assert "binary_sensor.vibration_sensor" in gateway.deconz_ids
assert len(hass.states.async_all()) == 3
assert len(gateway.entities[binary_sensor.DOMAIN]) == 2
hass.config_entries.async_update_entry(
gateway.config_entry, options={deconz.gateway.CONF_ALLOW_CLIP_SENSOR: True}
@ -161,12 +166,14 @@ async def test_allow_clip_sensor(hass):
assert "binary_sensor.clip_presence_sensor" in gateway.deconz_ids
assert "binary_sensor.vibration_sensor" in gateway.deconz_ids
assert len(hass.states.async_all()) == 4
assert len(gateway.entities[binary_sensor.DOMAIN]) == 3
async def test_add_new_binary_sensor(hass):
"""Test that adding a new binary sensor works."""
gateway = await setup_deconz_integration(hass)
assert len(gateway.deconz_ids) == 0
assert len(gateway.entities[binary_sensor.DOMAIN]) == 0
state_added_event = {
"t": "event",
@ -182,3 +189,4 @@ async def test_add_new_binary_sensor(hass):
presence_sensor = hass.states.get("binary_sensor.presence_sensor")
assert presence_sensor.state == "off"
assert len(gateway.entities[binary_sensor.DOMAIN]) == 1

View file

@ -59,6 +59,7 @@ async def test_no_sensors(hass):
gateway = await setup_deconz_integration(hass)
assert len(gateway.deconz_ids) == 0
assert len(hass.states.async_all()) == 0
assert len(gateway.entities[climate.DOMAIN]) == 0
async def test_climate_devices(hass):
@ -72,6 +73,7 @@ async def test_climate_devices(hass):
assert "climate.presence_sensor" not in gateway.deconz_ids
assert "climate.clip_thermostat" not in gateway.deconz_ids
assert len(hass.states.async_all()) == 3
assert len(gateway.entities[climate.DOMAIN]) == 1
thermostat = hass.states.get("climate.thermostat")
assert thermostat.state == "auto"
@ -181,6 +183,7 @@ async def test_climate_devices(hass):
await gateway.async_reset()
assert len(hass.states.async_all()) == 0
assert len(gateway.entities[climate.DOMAIN]) == 0
async def test_clip_climate_device(hass):
@ -198,6 +201,7 @@ async def test_clip_climate_device(hass):
assert "climate.presence_sensor" not in gateway.deconz_ids
assert "climate.clip_thermostat" in gateway.deconz_ids
assert len(hass.states.async_all()) == 4
assert len(gateway.entities[climate.DOMAIN]) == 2
thermostat = hass.states.get("climate.thermostat")
assert thermostat.state == "auto"
@ -225,6 +229,7 @@ async def test_clip_climate_device(hass):
assert "climate.presence_sensor" not in gateway.deconz_ids
assert "climate.clip_thermostat" not in gateway.deconz_ids
assert len(hass.states.async_all()) == 3
assert len(gateway.entities[climate.DOMAIN]) == 1
hass.config_entries.async_update_entry(
gateway.config_entry, options={deconz.gateway.CONF_ALLOW_CLIP_SENSOR: True}
@ -237,6 +242,7 @@ async def test_clip_climate_device(hass):
assert "climate.presence_sensor" not in gateway.deconz_ids
assert "climate.clip_thermostat" in gateway.deconz_ids
assert len(hass.states.async_all()) == 4
assert len(gateway.entities[climate.DOMAIN]) == 2
async def test_verify_state_update(hass):
@ -268,6 +274,7 @@ async def test_add_new_climate_device(hass):
"""Test that adding a new climate device works."""
gateway = await setup_deconz_integration(hass)
assert len(gateway.deconz_ids) == 0
assert len(gateway.entities[climate.DOMAIN]) == 0
state_added_event = {
"t": "event",
@ -283,3 +290,4 @@ async def test_add_new_climate_device(hass):
thermostat = hass.states.get("climate.thermostat")
assert thermostat.state == "auto"
assert len(gateway.entities[climate.DOMAIN]) == 1

View file

@ -67,6 +67,7 @@ async def test_no_covers(hass):
"""Test that no cover entities are created."""
gateway = await setup_deconz_integration(hass)
assert len(gateway.deconz_ids) == 0
assert len(gateway.entities[cover.DOMAIN]) == 0
assert len(hass.states.async_all()) == 0
@ -81,6 +82,7 @@ async def test_cover(hass):
assert "cover.deconz_old_brightness_cover" in gateway.deconz_ids
assert "cover.window_covering_controller" in gateway.deconz_ids
assert len(hass.states.async_all()) == 5
assert len(gateway.entities[cover.DOMAIN]) == 4
level_controllable_cover = hass.states.get("cover.level_controllable_cover")
assert level_controllable_cover.state == "open"
@ -158,3 +160,4 @@ async def test_cover(hass):
await gateway.async_reset()
assert len(hass.states.async_all()) == 0
assert len(gateway.entities[cover.DOMAIN]) == 0

View file

@ -1,7 +1,7 @@
"""Test deCONZ remote events."""
from copy import deepcopy
from homeassistant.components.deconz.deconz_event import CONF_DECONZ_EVENT
from homeassistant.components.deconz.deconz_event import CONF_DECONZ_EVENT, EVENT
from .test_gateway import DECONZ_WEB_REQUEST, setup_deconz_integration
@ -62,6 +62,7 @@ async def test_deconz_events(hass):
assert "sensor.switch_2_battery_level" in gateway.deconz_ids
assert len(hass.states.async_all()) == 3
assert len(gateway.events) == 5
assert len(gateway.entities[EVENT]) == 5
switch_1 = hass.states.get("sensor.switch_1")
assert switch_1 is None
@ -127,3 +128,4 @@ async def test_deconz_events(hass):
assert len(hass.states.async_all()) == 0
assert len(gateway.events) == 0
assert len(gateway.entities[EVENT]) == 0

View file

@ -95,6 +95,7 @@ async def test_no_lights_or_groups(hass):
gateway = await setup_deconz_integration(hass)
assert len(gateway.deconz_ids) == 0
assert len(hass.states.async_all()) == 0
assert len(gateway.entities[light.DOMAIN]) == 0
async def test_lights_and_groups(hass):
@ -111,6 +112,7 @@ async def test_lights_and_groups(hass):
assert "light.on_off_light" in gateway.deconz_ids
assert len(hass.states.async_all()) == 6
assert len(gateway.entities[light.DOMAIN]) == 5
rgb_light = hass.states.get("light.rgb_light")
assert rgb_light.state == "on"
@ -256,6 +258,7 @@ async def test_lights_and_groups(hass):
await gateway.async_reset()
assert len(hass.states.async_all()) == 0
assert len(gateway.entities[light.DOMAIN]) == 0
async def test_disable_light_groups(hass):
@ -275,6 +278,7 @@ async def test_disable_light_groups(hass):
assert "light.on_off_switch" not in gateway.deconz_ids
# 3 entities
assert len(hass.states.async_all()) == 5
assert len(gateway.entities[light.DOMAIN]) == 4
rgb_light = hass.states.get("light.rgb_light")
assert rgb_light is not None
@ -300,6 +304,7 @@ async def test_disable_light_groups(hass):
assert "light.on_off_switch" not in gateway.deconz_ids
# 3 entities
assert len(hass.states.async_all()) == 6
assert len(gateway.entities[light.DOMAIN]) == 5
hass.config_entries.async_update_entry(
gateway.config_entry, options={deconz.gateway.CONF_ALLOW_DECONZ_GROUPS: False}
@ -313,3 +318,4 @@ async def test_disable_light_groups(hass):
assert "light.on_off_switch" not in gateway.deconz_ids
# 3 entities
assert len(hass.states.async_all()) == 5
assert len(gateway.entities[light.DOMAIN]) == 4

View file

@ -2,6 +2,7 @@
from copy import deepcopy
from homeassistant.components import deconz
from homeassistant.components.deconz.deconz_event import EVENT
import homeassistant.components.sensor as sensor
from homeassistant.const import (
DEVICE_CLASS_BATTERY,
@ -96,6 +97,7 @@ async def test_no_sensors(hass):
gateway = await setup_deconz_integration(hass)
assert len(gateway.deconz_ids) == 0
assert len(hass.states.async_all()) == 0
assert len(gateway.entities[sensor.DOMAIN]) == 0
async def test_sensors(hass):
@ -114,6 +116,7 @@ async def test_sensors(hass):
assert "sensor.consumption_sensor" in gateway.deconz_ids
assert "sensor.clip_light_level_sensor" not in gateway.deconz_ids
assert len(hass.states.async_all()) == 5
assert len(gateway.entities[sensor.DOMAIN]) == 5
light_level_sensor = hass.states.get("sensor.light_level_sensor")
assert light_level_sensor.state == "999.8"
@ -174,6 +177,8 @@ async def test_sensors(hass):
await gateway.async_reset()
assert len(hass.states.async_all()) == 0
# Daylight sensor from deCONZ is added to set but is disabled by default
assert len(gateway.entities[sensor.DOMAIN]) == 1
async def test_allow_clip_sensors(hass):
@ -196,6 +201,7 @@ async def test_allow_clip_sensors(hass):
assert "sensor.consumption_sensor" in gateway.deconz_ids
assert "sensor.clip_light_level_sensor" in gateway.deconz_ids
assert len(hass.states.async_all()) == 6
assert len(gateway.entities[sensor.DOMAIN]) == 6
light_level_sensor = hass.states.get("sensor.light_level_sensor")
assert light_level_sensor.state == "999.8"
@ -243,6 +249,7 @@ async def test_allow_clip_sensors(hass):
assert "sensor.consumption_sensor" in gateway.deconz_ids
assert "sensor.clip_light_level_sensor" not in gateway.deconz_ids
assert len(hass.states.async_all()) == 5
assert len(gateway.entities[sensor.DOMAIN]) == 5
hass.config_entries.async_update_entry(
gateway.config_entry, options={deconz.gateway.CONF_ALLOW_CLIP_SENSOR: True}
@ -260,6 +267,7 @@ async def test_allow_clip_sensors(hass):
assert "sensor.consumption_sensor" in gateway.deconz_ids
assert "sensor.clip_light_level_sensor" in gateway.deconz_ids
assert len(hass.states.async_all()) == 6
assert len(gateway.entities[sensor.DOMAIN]) == 6
async def test_add_new_sensor(hass):
@ -292,6 +300,8 @@ async def test_add_battery_later(hass):
assert len(gateway.deconz_ids) == 0
assert len(gateway.events) == 1
assert len(remote._callbacks) == 2
assert len(gateway.entities[sensor.DOMAIN]) == 0
assert len(gateway.entities[EVENT]) == 1
remote.update({"config": {"battery": 50}})
await hass.async_block_till_done()
@ -302,3 +312,5 @@ async def test_add_battery_later(hass):
battery_sensor = hass.states.get("sensor.switch_1_battery_level")
assert battery_sensor is not None
assert len(gateway.entities[sensor.DOMAIN]) == 1
assert len(gateway.entities[EVENT]) == 1

View file

@ -64,6 +64,7 @@ async def test_no_switches(hass):
gateway = await setup_deconz_integration(hass)
assert len(gateway.deconz_ids) == 0
assert len(hass.states.async_all()) == 0
assert len(gateway.entities[switch.DOMAIN]) == 0
async def test_switches(hass):
@ -77,6 +78,7 @@ async def test_switches(hass):
assert "switch.unsupported_switch" not in gateway.deconz_ids
assert "switch.on_off_relay" in gateway.deconz_ids
assert len(hass.states.async_all()) == 5
assert len(gateway.entities[switch.DOMAIN]) == 4
on_off_switch = hass.states.get("switch.on_off_switch")
assert on_off_switch.state == "on"
@ -173,3 +175,4 @@ async def test_switches(hass):
await gateway.async_reset()
assert len(hass.states.async_all()) == 0
assert len(gateway.entities[switch.DOMAIN]) == 0