Fix so that entities are properly unloaded with config entry (#16281)
This commit is contained in:
parent
88f72a654a
commit
645c3a67d8
8 changed files with 62 additions and 20 deletions
|
@ -54,6 +54,11 @@ class DeconzBinarySensor(BinarySensorDevice):
|
||||||
self._sensor.register_async_callback(self.async_update_callback)
|
self._sensor.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._sensor.deconz_id
|
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._sensor.deconz_id
|
||||||
|
|
||||||
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
|
"""Disconnect sensor object when removed."""
|
||||||
|
self._sensor.remove_callback(self.async_update_callback)
|
||||||
|
self._sensor = None
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_update_callback(self, reason):
|
def async_update_callback(self, reason):
|
||||||
"""Update the sensor's state.
|
"""Update the sensor's state.
|
||||||
|
|
|
@ -24,7 +24,7 @@ from .const import (
|
||||||
CONF_ALLOW_CLIP_SENSOR, CONFIG_FILE, DATA_DECONZ_EVENT,
|
CONF_ALLOW_CLIP_SENSOR, CONFIG_FILE, DATA_DECONZ_EVENT,
|
||||||
DATA_DECONZ_ID, DATA_DECONZ_UNSUB, DOMAIN, _LOGGER)
|
DATA_DECONZ_ID, DATA_DECONZ_UNSUB, DOMAIN, _LOGGER)
|
||||||
|
|
||||||
REQUIREMENTS = ['pydeconz==44']
|
REQUIREMENTS = ['pydeconz==45']
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: vol.Schema({
|
DOMAIN: vol.Schema({
|
||||||
|
@ -179,15 +179,22 @@ async def async_unload_entry(hass, config_entry):
|
||||||
deconz = hass.data.pop(DOMAIN)
|
deconz = hass.data.pop(DOMAIN)
|
||||||
hass.services.async_remove(DOMAIN, SERVICE_DECONZ)
|
hass.services.async_remove(DOMAIN, SERVICE_DECONZ)
|
||||||
deconz.close()
|
deconz.close()
|
||||||
for component in ['binary_sensor', 'light', 'scene', 'sensor']:
|
|
||||||
|
for component in ['binary_sensor', 'light', 'scene', 'sensor', 'switch']:
|
||||||
await hass.config_entries.async_forward_entry_unload(
|
await hass.config_entries.async_forward_entry_unload(
|
||||||
config_entry, component)
|
config_entry, component)
|
||||||
|
|
||||||
dispatchers = hass.data[DATA_DECONZ_UNSUB]
|
dispatchers = hass.data[DATA_DECONZ_UNSUB]
|
||||||
for unsub_dispatcher in dispatchers:
|
for unsub_dispatcher in dispatchers:
|
||||||
unsub_dispatcher()
|
unsub_dispatcher()
|
||||||
hass.data[DATA_DECONZ_UNSUB] = []
|
hass.data[DATA_DECONZ_UNSUB] = []
|
||||||
hass.data[DATA_DECONZ_EVENT] = []
|
|
||||||
|
for event in hass.data[DATA_DECONZ_EVENT]:
|
||||||
|
event.async_will_remove_from_hass()
|
||||||
|
hass.data[DATA_DECONZ_EVENT].remove(event)
|
||||||
|
|
||||||
hass.data[DATA_DECONZ_ID] = []
|
hass.data[DATA_DECONZ_ID] = []
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,6 +213,12 @@ class DeconzEvent:
|
||||||
self._event = 'deconz_{}'.format(CONF_EVENT)
|
self._event = 'deconz_{}'.format(CONF_EVENT)
|
||||||
self._id = slugify(self._device.name)
|
self._id = slugify(self._device.name)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_will_remove_from_hass(self) -> None:
|
||||||
|
"""Disconnect event object when removed."""
|
||||||
|
self._device.remove_callback(self.async_update_callback)
|
||||||
|
self._device = None
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_update_callback(self, reason):
|
def async_update_callback(self, reason):
|
||||||
"""Fire the event if reason is that state is updated."""
|
"""Fire the event if reason is that state is updated."""
|
||||||
|
|
|
@ -82,6 +82,11 @@ class DeconzLight(Light):
|
||||||
self._light.register_async_callback(self.async_update_callback)
|
self._light.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._light.deconz_id
|
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._light.deconz_id
|
||||||
|
|
||||||
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
|
"""Disconnect light object when removed."""
|
||||||
|
self._light.remove_callback(self.async_update_callback)
|
||||||
|
self._light = None
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_update_callback(self, reason):
|
def async_update_callback(self, reason):
|
||||||
"""Update the light's state."""
|
"""Update the light's state."""
|
||||||
|
|
|
@ -38,6 +38,10 @@ class DeconzScene(Scene):
|
||||||
"""Subscribe to sensors events."""
|
"""Subscribe to sensors events."""
|
||||||
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._scene.deconz_id
|
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._scene.deconz_id
|
||||||
|
|
||||||
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
|
"""Disconnect scene object when removed."""
|
||||||
|
self._scene = None
|
||||||
|
|
||||||
async def async_activate(self):
|
async def async_activate(self):
|
||||||
"""Activate the scene."""
|
"""Activate the scene."""
|
||||||
await self._scene.async_set_state({})
|
await self._scene.async_set_state({})
|
||||||
|
|
|
@ -64,6 +64,11 @@ class DeconzSensor(Entity):
|
||||||
self._sensor.register_async_callback(self.async_update_callback)
|
self._sensor.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._sensor.deconz_id
|
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._sensor.deconz_id
|
||||||
|
|
||||||
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
|
"""Disconnect sensor object when removed."""
|
||||||
|
self._sensor.remove_callback(self.async_update_callback)
|
||||||
|
self._sensor = None
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_update_callback(self, reason):
|
def async_update_callback(self, reason):
|
||||||
"""Update the sensor's state.
|
"""Update the sensor's state.
|
||||||
|
@ -155,16 +160,21 @@ class DeconzSensor(Entity):
|
||||||
class DeconzBattery(Entity):
|
class DeconzBattery(Entity):
|
||||||
"""Battery class for when a device is only represented as an event."""
|
"""Battery class for when a device is only represented as an event."""
|
||||||
|
|
||||||
def __init__(self, device):
|
def __init__(self, sensor):
|
||||||
"""Register dispatcher callback for update of battery state."""
|
"""Register dispatcher callback for update of battery state."""
|
||||||
self._device = device
|
self._sensor = sensor
|
||||||
self._name = '{} {}'.format(self._device.name, 'Battery Level')
|
self._name = '{} {}'.format(self._sensor.name, 'Battery Level')
|
||||||
self._unit_of_measurement = "%"
|
self._unit_of_measurement = "%"
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Subscribe to sensors events."""
|
"""Subscribe to sensors events."""
|
||||||
self._device.register_async_callback(self.async_update_callback)
|
self._sensor.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._device.deconz_id
|
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._sensor.deconz_id
|
||||||
|
|
||||||
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
|
"""Disconnect sensor object when removed."""
|
||||||
|
self._sensor.remove_callback(self.async_update_callback)
|
||||||
|
self._sensor = None
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_update_callback(self, reason):
|
def async_update_callback(self, reason):
|
||||||
|
@ -175,7 +185,7 @@ class DeconzBattery(Entity):
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
"""Return the state of the battery."""
|
"""Return the state of the battery."""
|
||||||
return self._device.battery
|
return self._sensor.battery
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -185,7 +195,7 @@ class DeconzBattery(Entity):
|
||||||
@property
|
@property
|
||||||
def unique_id(self):
|
def unique_id(self):
|
||||||
"""Return a unique identifier for the device."""
|
"""Return a unique identifier for the device."""
|
||||||
return self._device.uniqueid
|
return self._sensor.uniqueid
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_class(self):
|
def device_class(self):
|
||||||
|
@ -206,22 +216,22 @@ class DeconzBattery(Entity):
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the state attributes of the battery."""
|
"""Return the state attributes of the battery."""
|
||||||
attr = {
|
attr = {
|
||||||
ATTR_EVENT_ID: slugify(self._device.name),
|
ATTR_EVENT_ID: slugify(self._sensor.name),
|
||||||
}
|
}
|
||||||
return attr
|
return attr
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self):
|
def device_info(self):
|
||||||
"""Return a device description for device registry."""
|
"""Return a device description for device registry."""
|
||||||
if (self._device.uniqueid is None or
|
if (self._sensor.uniqueid is None or
|
||||||
self._device.uniqueid.count(':') != 7):
|
self._sensor.uniqueid.count(':') != 7):
|
||||||
return None
|
return None
|
||||||
serial = self._device.uniqueid.split('-', 1)[0]
|
serial = self._sensor.uniqueid.split('-', 1)[0]
|
||||||
return {
|
return {
|
||||||
'connections': {(CONNECTION_ZIGBEE, serial)},
|
'connections': {(CONNECTION_ZIGBEE, serial)},
|
||||||
'identifiers': {(DECONZ_DOMAIN, serial)},
|
'identifiers': {(DECONZ_DOMAIN, serial)},
|
||||||
'manufacturer': self._device.manufacturer,
|
'manufacturer': self._sensor.manufacturer,
|
||||||
'model': self._device.modelid,
|
'model': self._sensor.modelid,
|
||||||
'name': self._device.name,
|
'name': self._sensor.name,
|
||||||
'sw_version': self._device.swversion,
|
'sw_version': self._sensor.swversion,
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,11 @@ class DeconzSwitch(SwitchDevice):
|
||||||
self._switch.register_async_callback(self.async_update_callback)
|
self._switch.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._switch.deconz_id
|
self.hass.data[DATA_DECONZ_ID][self.entity_id] = self._switch.deconz_id
|
||||||
|
|
||||||
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
|
"""Disconnect switch object when removed."""
|
||||||
|
self._switch.remove_callback(self.async_update_callback)
|
||||||
|
self._switch = None
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_update_callback(self, reason):
|
def async_update_callback(self, reason):
|
||||||
"""Update the switch's state."""
|
"""Update the switch's state."""
|
||||||
|
|
|
@ -820,7 +820,7 @@ pycsspeechtts==1.0.2
|
||||||
pydaikin==0.4
|
pydaikin==0.4
|
||||||
|
|
||||||
# homeassistant.components.deconz
|
# homeassistant.components.deconz
|
||||||
pydeconz==44
|
pydeconz==45
|
||||||
|
|
||||||
# homeassistant.components.zwave
|
# homeassistant.components.zwave
|
||||||
pydispatcher==2.0.5
|
pydispatcher==2.0.5
|
||||||
|
|
|
@ -139,7 +139,7 @@ py-canary==0.5.0
|
||||||
pyblackbird==0.5
|
pyblackbird==0.5
|
||||||
|
|
||||||
# homeassistant.components.deconz
|
# homeassistant.components.deconz
|
||||||
pydeconz==44
|
pydeconz==45
|
||||||
|
|
||||||
# homeassistant.components.zwave
|
# homeassistant.components.zwave
|
||||||
pydispatcher==2.0.5
|
pydispatcher==2.0.5
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue