mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 15:17:35 +00:00
deCONZ - reflect hub status on entities (#18106)
* Support for controlling entity available attribute based on gateways availability * Fix string not being in imperative mood
This commit is contained in:
parent
3d4ff74761
commit
dcdae325ea
@ -6,8 +6,8 @@ https://home-assistant.io/components/binary_sensor.deconz/
|
|||||||
"""
|
"""
|
||||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||||
from homeassistant.components.deconz.const import (
|
from homeassistant.components.deconz.const import (
|
||||||
ATTR_DARK, ATTR_ON, CONF_ALLOW_CLIP_SENSOR, DOMAIN as DATA_DECONZ,
|
ATTR_DARK, ATTR_ON, CONF_ALLOW_CLIP_SENSOR, DECONZ_REACHABLE,
|
||||||
DECONZ_DOMAIN)
|
DOMAIN as DECONZ_DOMAIN)
|
||||||
from homeassistant.const import ATTR_BATTERY_LEVEL
|
from homeassistant.const import ATTR_BATTERY_LEVEL
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE
|
from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE
|
||||||
@ -24,6 +24,8 @@ async def async_setup_platform(hass, config, async_add_entities,
|
|||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
"""Set up the deCONZ binary sensor."""
|
"""Set up the deCONZ binary sensor."""
|
||||||
|
gateway = hass.data[DECONZ_DOMAIN]
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_sensor(sensors):
|
def async_add_sensor(sensors):
|
||||||
"""Add binary sensor from deCONZ."""
|
"""Add binary sensor from deCONZ."""
|
||||||
@ -33,30 +35,35 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
for sensor in sensors:
|
for sensor in sensors:
|
||||||
if sensor.type in DECONZ_BINARY_SENSOR and \
|
if sensor.type in DECONZ_BINARY_SENSOR and \
|
||||||
not (not allow_clip_sensor and sensor.type.startswith('CLIP')):
|
not (not allow_clip_sensor and sensor.type.startswith('CLIP')):
|
||||||
entities.append(DeconzBinarySensor(sensor))
|
entities.append(DeconzBinarySensor(sensor, gateway))
|
||||||
async_add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
hass.data[DATA_DECONZ].listeners.append(
|
gateway.listeners.append(
|
||||||
async_dispatcher_connect(hass, 'deconz_new_sensor', async_add_sensor))
|
async_dispatcher_connect(hass, 'deconz_new_sensor', async_add_sensor))
|
||||||
|
|
||||||
async_add_sensor(hass.data[DATA_DECONZ].api.sensors.values())
|
async_add_sensor(gateway.api.sensors.values())
|
||||||
|
|
||||||
|
|
||||||
class DeconzBinarySensor(BinarySensorDevice):
|
class DeconzBinarySensor(BinarySensorDevice):
|
||||||
"""Representation of a binary sensor."""
|
"""Representation of a binary sensor."""
|
||||||
|
|
||||||
def __init__(self, sensor):
|
def __init__(self, sensor, gateway):
|
||||||
"""Set up sensor and add update callback to get data from websocket."""
|
"""Set up sensor and add update callback to get data from websocket."""
|
||||||
self._sensor = sensor
|
self._sensor = sensor
|
||||||
|
self.gateway = gateway
|
||||||
|
self.unsub_dispatcher = None
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Subscribe sensors events."""
|
"""Subscribe sensors events."""
|
||||||
self._sensor.register_async_callback(self.async_update_callback)
|
self._sensor.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ].deconz_ids[self.entity_id] = \
|
self.gateway.deconz_ids[self.entity_id] = self._sensor.deconz_id
|
||||||
self._sensor.deconz_id
|
self.unsub_dispatcher = async_dispatcher_connect(
|
||||||
|
self.hass, DECONZ_REACHABLE, self.async_update_callback)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Disconnect sensor object when removed."""
|
"""Disconnect sensor object when removed."""
|
||||||
|
if self.unsub_dispatcher is not None:
|
||||||
|
self.unsub_dispatcher()
|
||||||
self._sensor.remove_callback(self.async_update_callback)
|
self._sensor.remove_callback(self.async_update_callback)
|
||||||
self._sensor = None
|
self._sensor = None
|
||||||
|
|
||||||
@ -101,7 +108,7 @@ class DeconzBinarySensor(BinarySensorDevice):
|
|||||||
@property
|
@property
|
||||||
def available(self):
|
def available(self):
|
||||||
"""Return True if sensor is available."""
|
"""Return True if sensor is available."""
|
||||||
return self._sensor.reachable
|
return self.gateway.available and self._sensor.reachable
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
@ -128,7 +135,7 @@ class DeconzBinarySensor(BinarySensorDevice):
|
|||||||
self._sensor.uniqueid.count(':') != 7):
|
self._sensor.uniqueid.count(':') != 7):
|
||||||
return None
|
return None
|
||||||
serial = self._sensor.uniqueid.split('-', 1)[0]
|
serial = self._sensor.uniqueid.split('-', 1)[0]
|
||||||
bridgeid = self.hass.data[DATA_DECONZ].api.config.bridgeid
|
bridgeid = self.gateway.api.config.bridgeid
|
||||||
return {
|
return {
|
||||||
'connections': {(CONNECTION_ZIGBEE, serial)},
|
'connections': {(CONNECTION_ZIGBEE, serial)},
|
||||||
'identifiers': {(DECONZ_DOMAIN, serial)},
|
'identifiers': {(DECONZ_DOMAIN, serial)},
|
||||||
|
@ -5,7 +5,8 @@ For more details about this platform, please refer to the documentation at
|
|||||||
https://home-assistant.io/components/cover.deconz/
|
https://home-assistant.io/components/cover.deconz/
|
||||||
"""
|
"""
|
||||||
from homeassistant.components.deconz.const import (
|
from homeassistant.components.deconz.const import (
|
||||||
COVER_TYPES, DAMPERS, DOMAIN as DATA_DECONZ, DECONZ_DOMAIN, WINDOW_COVERS)
|
COVER_TYPES, DAMPERS, DECONZ_REACHABLE, DOMAIN as DECONZ_DOMAIN,
|
||||||
|
WINDOW_COVERS)
|
||||||
from homeassistant.components.cover import (
|
from homeassistant.components.cover import (
|
||||||
ATTR_POSITION, CoverDevice, SUPPORT_CLOSE, SUPPORT_OPEN, SUPPORT_STOP,
|
ATTR_POSITION, CoverDevice, SUPPORT_CLOSE, SUPPORT_OPEN, SUPPORT_STOP,
|
||||||
SUPPORT_SET_POSITION)
|
SUPPORT_SET_POSITION)
|
||||||
@ -29,6 +30,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
|
|
||||||
Covers are based on same device class as lights in deCONZ.
|
Covers are based on same device class as lights in deCONZ.
|
||||||
"""
|
"""
|
||||||
|
gateway = hass.data[DECONZ_DOMAIN]
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_cover(lights):
|
def async_add_cover(lights):
|
||||||
"""Add cover from deCONZ."""
|
"""Add cover from deCONZ."""
|
||||||
@ -36,23 +39,26 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
for light in lights:
|
for light in lights:
|
||||||
if light.type in COVER_TYPES:
|
if light.type in COVER_TYPES:
|
||||||
if light.modelid in ZIGBEE_SPEC:
|
if light.modelid in ZIGBEE_SPEC:
|
||||||
entities.append(DeconzCoverZigbeeSpec(light))
|
entities.append(DeconzCoverZigbeeSpec(light, gateway))
|
||||||
else:
|
else:
|
||||||
entities.append(DeconzCover(light))
|
entities.append(DeconzCover(light, gateway))
|
||||||
async_add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
hass.data[DATA_DECONZ].listeners.append(
|
gateway.listeners.append(
|
||||||
async_dispatcher_connect(hass, 'deconz_new_light', async_add_cover))
|
async_dispatcher_connect(hass, 'deconz_new_light', async_add_cover))
|
||||||
|
|
||||||
async_add_cover(hass.data[DATA_DECONZ].api.lights.values())
|
async_add_cover(gateway.api.lights.values())
|
||||||
|
|
||||||
|
|
||||||
class DeconzCover(CoverDevice):
|
class DeconzCover(CoverDevice):
|
||||||
"""Representation of a deCONZ cover."""
|
"""Representation of a deCONZ cover."""
|
||||||
|
|
||||||
def __init__(self, cover):
|
def __init__(self, cover, gateway):
|
||||||
"""Set up cover and add update callback to get data from websocket."""
|
"""Set up cover and add update callback to get data from websocket."""
|
||||||
self._cover = cover
|
self._cover = cover
|
||||||
|
self.gateway = gateway
|
||||||
|
self.unsub_dispatcher = None
|
||||||
|
|
||||||
self._features = SUPPORT_OPEN
|
self._features = SUPPORT_OPEN
|
||||||
self._features |= SUPPORT_CLOSE
|
self._features |= SUPPORT_CLOSE
|
||||||
self._features |= SUPPORT_STOP
|
self._features |= SUPPORT_STOP
|
||||||
@ -61,11 +67,14 @@ class DeconzCover(CoverDevice):
|
|||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Subscribe to covers events."""
|
"""Subscribe to covers events."""
|
||||||
self._cover.register_async_callback(self.async_update_callback)
|
self._cover.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ].deconz_ids[self.entity_id] = \
|
self.gateway.deconz_ids[self.entity_id] = self._cover.deconz_id
|
||||||
self._cover.deconz_id
|
self.unsub_dispatcher = async_dispatcher_connect(
|
||||||
|
self.hass, DECONZ_REACHABLE, self.async_update_callback)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Disconnect cover object when removed."""
|
"""Disconnect cover object when removed."""
|
||||||
|
if self.unsub_dispatcher is not None:
|
||||||
|
self.unsub_dispatcher()
|
||||||
self._cover.remove_callback(self.async_update_callback)
|
self._cover.remove_callback(self.async_update_callback)
|
||||||
self._cover = None
|
self._cover = None
|
||||||
|
|
||||||
@ -112,7 +121,7 @@ class DeconzCover(CoverDevice):
|
|||||||
@property
|
@property
|
||||||
def available(self):
|
def available(self):
|
||||||
"""Return True if light is available."""
|
"""Return True if light is available."""
|
||||||
return self._cover.reachable
|
return self.gateway.available and self._cover.reachable
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
@ -150,7 +159,7 @@ class DeconzCover(CoverDevice):
|
|||||||
self._cover.uniqueid.count(':') != 7):
|
self._cover.uniqueid.count(':') != 7):
|
||||||
return None
|
return None
|
||||||
serial = self._cover.uniqueid.split('-', 1)[0]
|
serial = self._cover.uniqueid.split('-', 1)[0]
|
||||||
bridgeid = self.hass.data[DATA_DECONZ].api.config.bridgeid
|
bridgeid = self.gateway.api.config.bridgeid
|
||||||
return {
|
return {
|
||||||
'connections': {(CONNECTION_ZIGBEE, serial)},
|
'connections': {(CONNECTION_ZIGBEE, serial)},
|
||||||
'identifiers': {(DECONZ_DOMAIN, serial)},
|
'identifiers': {(DECONZ_DOMAIN, serial)},
|
||||||
|
@ -5,9 +5,6 @@ _LOGGER = logging.getLogger('homeassistant.components.deconz')
|
|||||||
|
|
||||||
DOMAIN = 'deconz'
|
DOMAIN = 'deconz'
|
||||||
CONFIG_FILE = 'deconz.conf'
|
CONFIG_FILE = 'deconz.conf'
|
||||||
DATA_DECONZ_EVENT = 'deconz_events'
|
|
||||||
DATA_DECONZ_ID = 'deconz_entities'
|
|
||||||
DATA_DECONZ_UNSUB = 'deconz_dispatchers'
|
|
||||||
DECONZ_DOMAIN = 'deconz'
|
DECONZ_DOMAIN = 'deconz'
|
||||||
|
|
||||||
CONF_ALLOW_CLIP_SENSOR = 'allow_clip_sensor'
|
CONF_ALLOW_CLIP_SENSOR = 'allow_clip_sensor'
|
||||||
@ -16,6 +13,8 @@ CONF_ALLOW_DECONZ_GROUPS = 'allow_deconz_groups'
|
|||||||
SUPPORTED_PLATFORMS = ['binary_sensor', 'cover',
|
SUPPORTED_PLATFORMS = ['binary_sensor', 'cover',
|
||||||
'light', 'scene', 'sensor', 'switch']
|
'light', 'scene', 'sensor', 'switch']
|
||||||
|
|
||||||
|
DECONZ_REACHABLE = 'deconz_reachable'
|
||||||
|
|
||||||
ATTR_DARK = 'dark'
|
ATTR_DARK = 'dark'
|
||||||
ATTR_ON = 'on'
|
ATTR_ON = 'on'
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ from homeassistant.helpers.dispatcher import (
|
|||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
_LOGGER, CONF_ALLOW_CLIP_SENSOR, SUPPORTED_PLATFORMS)
|
_LOGGER, DECONZ_REACHABLE, CONF_ALLOW_CLIP_SENSOR, SUPPORTED_PLATFORMS)
|
||||||
|
|
||||||
|
|
||||||
class DeconzGateway:
|
class DeconzGateway:
|
||||||
@ -18,6 +18,7 @@ class DeconzGateway:
|
|||||||
"""Initialize the system."""
|
"""Initialize the system."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.config_entry = config_entry
|
self.config_entry = config_entry
|
||||||
|
self.available = True
|
||||||
self.api = None
|
self.api = None
|
||||||
self._cancel_retry_setup = None
|
self._cancel_retry_setup = None
|
||||||
|
|
||||||
@ -30,7 +31,8 @@ class DeconzGateway:
|
|||||||
hass = self.hass
|
hass = self.hass
|
||||||
|
|
||||||
self.api = await get_gateway(
|
self.api = await get_gateway(
|
||||||
hass, self.config_entry.data, self.async_add_device_callback
|
hass, self.config_entry.data, self.async_add_device_callback,
|
||||||
|
self.async_connection_status_callback
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.api is False:
|
if self.api is False:
|
||||||
@ -65,6 +67,13 @@ class DeconzGateway:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_connection_status_callback(self, available):
|
||||||
|
"""Handle signals of gateway connection status."""
|
||||||
|
self.available = available
|
||||||
|
async_dispatcher_send(
|
||||||
|
self.hass, DECONZ_REACHABLE, {'state': True, 'attr': 'reachable'})
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_device_callback(self, device_type, device):
|
def async_add_device_callback(self, device_type, device):
|
||||||
"""Handle event of new device creation in deCONZ."""
|
"""Handle event of new device creation in deCONZ."""
|
||||||
@ -122,13 +131,15 @@ class DeconzGateway:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def get_gateway(hass, config, async_add_device_callback):
|
async def get_gateway(hass, config, async_add_device_callback,
|
||||||
|
async_connection_status_callback):
|
||||||
"""Create a gateway object and verify configuration."""
|
"""Create a gateway object and verify configuration."""
|
||||||
from pydeconz import DeconzSession
|
from pydeconz import DeconzSession
|
||||||
|
|
||||||
session = aiohttp_client.async_get_clientsession(hass)
|
session = aiohttp_client.async_get_clientsession(hass)
|
||||||
deconz = DeconzSession(hass.loop, session, **config,
|
deconz = DeconzSession(hass.loop, session, **config,
|
||||||
async_add_device=async_add_device_callback)
|
async_add_device=async_add_device_callback,
|
||||||
|
connection_status=async_connection_status_callback)
|
||||||
result = await deconz.async_load_parameters()
|
result = await deconz.async_load_parameters()
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
|
@ -5,7 +5,7 @@ For more details about this component, please refer to the documentation at
|
|||||||
https://home-assistant.io/components/light.deconz/
|
https://home-assistant.io/components/light.deconz/
|
||||||
"""
|
"""
|
||||||
from homeassistant.components.deconz.const import (
|
from homeassistant.components.deconz.const import (
|
||||||
CONF_ALLOW_DECONZ_GROUPS, DOMAIN as DATA_DECONZ, DECONZ_DOMAIN,
|
CONF_ALLOW_DECONZ_GROUPS, DECONZ_REACHABLE, DOMAIN as DECONZ_DOMAIN,
|
||||||
COVER_TYPES, SWITCH_TYPES)
|
COVER_TYPES, SWITCH_TYPES)
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_HS_COLOR,
|
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_EFFECT, ATTR_FLASH, ATTR_HS_COLOR,
|
||||||
@ -28,16 +28,18 @@ async def async_setup_platform(hass, config, async_add_entities,
|
|||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
"""Set up the deCONZ lights and groups from a config entry."""
|
"""Set up the deCONZ lights and groups from a config entry."""
|
||||||
|
gateway = hass.data[DECONZ_DOMAIN]
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_light(lights):
|
def async_add_light(lights):
|
||||||
"""Add light from deCONZ."""
|
"""Add light from deCONZ."""
|
||||||
entities = []
|
entities = []
|
||||||
for light in lights:
|
for light in lights:
|
||||||
if light.type not in COVER_TYPES + SWITCH_TYPES:
|
if light.type not in COVER_TYPES + SWITCH_TYPES:
|
||||||
entities.append(DeconzLight(light))
|
entities.append(DeconzLight(light, gateway))
|
||||||
async_add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
hass.data[DATA_DECONZ].listeners.append(
|
gateway.listeners.append(
|
||||||
async_dispatcher_connect(hass, 'deconz_new_light', async_add_light))
|
async_dispatcher_connect(hass, 'deconz_new_light', async_add_light))
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -47,22 +49,24 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
allow_group = config_entry.data.get(CONF_ALLOW_DECONZ_GROUPS, True)
|
allow_group = config_entry.data.get(CONF_ALLOW_DECONZ_GROUPS, True)
|
||||||
for group in groups:
|
for group in groups:
|
||||||
if group.lights and allow_group:
|
if group.lights and allow_group:
|
||||||
entities.append(DeconzLight(group))
|
entities.append(DeconzLight(group, gateway))
|
||||||
async_add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
hass.data[DATA_DECONZ].listeners.append(
|
gateway.listeners.append(
|
||||||
async_dispatcher_connect(hass, 'deconz_new_group', async_add_group))
|
async_dispatcher_connect(hass, 'deconz_new_group', async_add_group))
|
||||||
|
|
||||||
async_add_light(hass.data[DATA_DECONZ].api.lights.values())
|
async_add_light(gateway.api.lights.values())
|
||||||
async_add_group(hass.data[DATA_DECONZ].api.groups.values())
|
async_add_group(gateway.api.groups.values())
|
||||||
|
|
||||||
|
|
||||||
class DeconzLight(Light):
|
class DeconzLight(Light):
|
||||||
"""Representation of a deCONZ light."""
|
"""Representation of a deCONZ light."""
|
||||||
|
|
||||||
def __init__(self, light):
|
def __init__(self, light, gateway):
|
||||||
"""Set up light and add update callback to get data from websocket."""
|
"""Set up light and add update callback to get data from websocket."""
|
||||||
self._light = light
|
self._light = light
|
||||||
|
self.gateway = gateway
|
||||||
|
self.unsub_dispatcher = None
|
||||||
|
|
||||||
self._features = SUPPORT_BRIGHTNESS
|
self._features = SUPPORT_BRIGHTNESS
|
||||||
self._features |= SUPPORT_FLASH
|
self._features |= SUPPORT_FLASH
|
||||||
@ -80,11 +84,14 @@ class DeconzLight(Light):
|
|||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Subscribe to lights events."""
|
"""Subscribe to lights events."""
|
||||||
self._light.register_async_callback(self.async_update_callback)
|
self._light.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ].deconz_ids[self.entity_id] = \
|
self.gateway.deconz_ids[self.entity_id] = self._light.deconz_id
|
||||||
self._light.deconz_id
|
self.unsub_dispatcher = async_dispatcher_connect(
|
||||||
|
self.hass, DECONZ_REACHABLE, self.async_update_callback)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Disconnect light object when removed."""
|
"""Disconnect light object when removed."""
|
||||||
|
if self.unsub_dispatcher is not None:
|
||||||
|
self.unsub_dispatcher()
|
||||||
self._light.remove_callback(self.async_update_callback)
|
self._light.remove_callback(self.async_update_callback)
|
||||||
self._light = None
|
self._light = None
|
||||||
|
|
||||||
@ -141,7 +148,7 @@ class DeconzLight(Light):
|
|||||||
@property
|
@property
|
||||||
def available(self):
|
def available(self):
|
||||||
"""Return True if light is available."""
|
"""Return True if light is available."""
|
||||||
return self._light.reachable
|
return self.gateway.available and self._light.reachable
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
@ -214,7 +221,7 @@ class DeconzLight(Light):
|
|||||||
self._light.uniqueid.count(':') != 7):
|
self._light.uniqueid.count(':') != 7):
|
||||||
return None
|
return None
|
||||||
serial = self._light.uniqueid.split('-', 1)[0]
|
serial = self._light.uniqueid.split('-', 1)[0]
|
||||||
bridgeid = self.hass.data[DATA_DECONZ].api.config.bridgeid
|
bridgeid = self.gateway.api.config.bridgeid
|
||||||
return {
|
return {
|
||||||
'connections': {(CONNECTION_ZIGBEE, serial)},
|
'connections': {(CONNECTION_ZIGBEE, serial)},
|
||||||
'identifiers': {(DECONZ_DOMAIN, serial)},
|
'identifiers': {(DECONZ_DOMAIN, serial)},
|
||||||
|
@ -4,7 +4,7 @@ Support for deCONZ scenes.
|
|||||||
For more details about this platform, please refer to the documentation at
|
For more details about this platform, please refer to the documentation at
|
||||||
https://home-assistant.io/components/scene.deconz/
|
https://home-assistant.io/components/scene.deconz/
|
||||||
"""
|
"""
|
||||||
from homeassistant.components.deconz import DOMAIN as DATA_DECONZ
|
from homeassistant.components.deconz import DOMAIN as DECONZ_DOMAIN
|
||||||
from homeassistant.components.scene import Scene
|
from homeassistant.components.scene import Scene
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
@ -20,30 +20,32 @@ async def async_setup_platform(hass, config, async_add_entities,
|
|||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
"""Set up scenes for deCONZ component."""
|
"""Set up scenes for deCONZ component."""
|
||||||
|
gateway = hass.data[DECONZ_DOMAIN]
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_scene(scenes):
|
def async_add_scene(scenes):
|
||||||
"""Add scene from deCONZ."""
|
"""Add scene from deCONZ."""
|
||||||
entities = []
|
entities = []
|
||||||
for scene in scenes:
|
for scene in scenes:
|
||||||
entities.append(DeconzScene(scene))
|
entities.append(DeconzScene(scene, gateway))
|
||||||
async_add_entities(entities)
|
async_add_entities(entities)
|
||||||
hass.data[DATA_DECONZ].listeners.append(
|
gateway.listeners.append(
|
||||||
async_dispatcher_connect(hass, 'deconz_new_scene', async_add_scene))
|
async_dispatcher_connect(hass, 'deconz_new_scene', async_add_scene))
|
||||||
|
|
||||||
async_add_scene(hass.data[DATA_DECONZ].api.scenes.values())
|
async_add_scene(gateway.api.scenes.values())
|
||||||
|
|
||||||
|
|
||||||
class DeconzScene(Scene):
|
class DeconzScene(Scene):
|
||||||
"""Representation of a deCONZ scene."""
|
"""Representation of a deCONZ scene."""
|
||||||
|
|
||||||
def __init__(self, scene):
|
def __init__(self, scene, gateway):
|
||||||
"""Set up a scene."""
|
"""Set up a scene."""
|
||||||
self._scene = scene
|
self._scene = scene
|
||||||
|
self.gateway = gateway
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Subscribe to sensors events."""
|
"""Subscribe to sensors events."""
|
||||||
self.hass.data[DATA_DECONZ].deconz_ids[self.entity_id] = \
|
self.gateway.deconz_ids[self.entity_id] = self._scene.deconz_id
|
||||||
self._scene.deconz_id
|
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Disconnect scene object when removed."""
|
"""Disconnect scene object when removed."""
|
||||||
|
@ -5,8 +5,8 @@ For more details about this component, please refer to the documentation at
|
|||||||
https://home-assistant.io/components/sensor.deconz/
|
https://home-assistant.io/components/sensor.deconz/
|
||||||
"""
|
"""
|
||||||
from homeassistant.components.deconz.const import (
|
from homeassistant.components.deconz.const import (
|
||||||
ATTR_DARK, ATTR_ON, CONF_ALLOW_CLIP_SENSOR, DOMAIN as DATA_DECONZ,
|
ATTR_DARK, ATTR_ON, CONF_ALLOW_CLIP_SENSOR, DECONZ_REACHABLE,
|
||||||
DECONZ_DOMAIN)
|
DOMAIN as DECONZ_DOMAIN)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_BATTERY_LEVEL, ATTR_VOLTAGE, DEVICE_CLASS_BATTERY)
|
ATTR_BATTERY_LEVEL, ATTR_VOLTAGE, DEVICE_CLASS_BATTERY)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
@ -30,6 +30,8 @@ async def async_setup_platform(hass, config, async_add_entities,
|
|||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
"""Set up the deCONZ sensors."""
|
"""Set up the deCONZ sensors."""
|
||||||
|
gateway = hass.data[DECONZ_DOMAIN]
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_sensor(sensors):
|
def async_add_sensor(sensors):
|
||||||
"""Add sensors from deCONZ."""
|
"""Add sensors from deCONZ."""
|
||||||
@ -41,32 +43,37 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
not (not allow_clip_sensor and sensor.type.startswith('CLIP')):
|
not (not allow_clip_sensor and sensor.type.startswith('CLIP')):
|
||||||
if sensor.type in DECONZ_REMOTE:
|
if sensor.type in DECONZ_REMOTE:
|
||||||
if sensor.battery:
|
if sensor.battery:
|
||||||
entities.append(DeconzBattery(sensor))
|
entities.append(DeconzBattery(sensor, gateway))
|
||||||
else:
|
else:
|
||||||
entities.append(DeconzSensor(sensor))
|
entities.append(DeconzSensor(sensor, gateway))
|
||||||
async_add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
hass.data[DATA_DECONZ].listeners.append(
|
gateway.listeners.append(
|
||||||
async_dispatcher_connect(hass, 'deconz_new_sensor', async_add_sensor))
|
async_dispatcher_connect(hass, 'deconz_new_sensor', async_add_sensor))
|
||||||
|
|
||||||
async_add_sensor(hass.data[DATA_DECONZ].api.sensors.values())
|
async_add_sensor(gateway.api.sensors.values())
|
||||||
|
|
||||||
|
|
||||||
class DeconzSensor(Entity):
|
class DeconzSensor(Entity):
|
||||||
"""Representation of a sensor."""
|
"""Representation of a sensor."""
|
||||||
|
|
||||||
def __init__(self, sensor):
|
def __init__(self, sensor, gateway):
|
||||||
"""Set up sensor and add update callback to get data from websocket."""
|
"""Set up sensor and add update callback to get data from websocket."""
|
||||||
self._sensor = sensor
|
self._sensor = sensor
|
||||||
|
self.gateway = gateway
|
||||||
|
self.unsub_dispatcher = None
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Subscribe to sensors events."""
|
"""Subscribe to sensors events."""
|
||||||
self._sensor.register_async_callback(self.async_update_callback)
|
self._sensor.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ].deconz_ids[self.entity_id] = \
|
self.gateway.deconz_ids[self.entity_id] = self._sensor.deconz_id
|
||||||
self._sensor.deconz_id
|
self.unsub_dispatcher = async_dispatcher_connect(
|
||||||
|
self.hass, DECONZ_REACHABLE, self.async_update_callback)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Disconnect sensor object when removed."""
|
"""Disconnect sensor object when removed."""
|
||||||
|
if self.unsub_dispatcher is not None:
|
||||||
|
self.unsub_dispatcher()
|
||||||
self._sensor.remove_callback(self.async_update_callback)
|
self._sensor.remove_callback(self.async_update_callback)
|
||||||
self._sensor = None
|
self._sensor = None
|
||||||
|
|
||||||
@ -116,7 +123,7 @@ class DeconzSensor(Entity):
|
|||||||
@property
|
@property
|
||||||
def available(self):
|
def available(self):
|
||||||
"""Return true if sensor is available."""
|
"""Return true if sensor is available."""
|
||||||
return self._sensor.reachable
|
return self.gateway.available and self._sensor.reachable
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
@ -148,7 +155,7 @@ class DeconzSensor(Entity):
|
|||||||
self._sensor.uniqueid.count(':') != 7):
|
self._sensor.uniqueid.count(':') != 7):
|
||||||
return None
|
return None
|
||||||
serial = self._sensor.uniqueid.split('-', 1)[0]
|
serial = self._sensor.uniqueid.split('-', 1)[0]
|
||||||
bridgeid = self.hass.data[DATA_DECONZ].api.config.bridgeid
|
bridgeid = self.gateway.api.config.bridgeid
|
||||||
return {
|
return {
|
||||||
'connections': {(CONNECTION_ZIGBEE, serial)},
|
'connections': {(CONNECTION_ZIGBEE, serial)},
|
||||||
'identifiers': {(DECONZ_DOMAIN, serial)},
|
'identifiers': {(DECONZ_DOMAIN, serial)},
|
||||||
@ -163,20 +170,26 @@ 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, sensor):
|
def __init__(self, sensor, gateway):
|
||||||
"""Register dispatcher callback for update of battery state."""
|
"""Register dispatcher callback for update of battery state."""
|
||||||
self._sensor = sensor
|
self._sensor = sensor
|
||||||
|
self.gateway = gateway
|
||||||
|
self.unsub_dispatcher = None
|
||||||
|
|
||||||
self._name = '{} {}'.format(self._sensor.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._sensor.register_async_callback(self.async_update_callback)
|
self._sensor.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ].deconz_ids[self.entity_id] = \
|
self.gateway.deconz_ids[self.entity_id] = self._sensor.deconz_id
|
||||||
self._sensor.deconz_id
|
self.unsub_dispatcher = async_dispatcher_connect(
|
||||||
|
self.hass, DECONZ_REACHABLE, self.async_update_callback)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Disconnect sensor object when removed."""
|
"""Disconnect sensor object when removed."""
|
||||||
|
if self.unsub_dispatcher is not None:
|
||||||
|
self.unsub_dispatcher()
|
||||||
self._sensor.remove_callback(self.async_update_callback)
|
self._sensor.remove_callback(self.async_update_callback)
|
||||||
self._sensor = None
|
self._sensor = None
|
||||||
|
|
||||||
@ -211,6 +224,11 @@ class DeconzBattery(Entity):
|
|||||||
"""Return the unit of measurement of this entity."""
|
"""Return the unit of measurement of this entity."""
|
||||||
return self._unit_of_measurement
|
return self._unit_of_measurement
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self):
|
||||||
|
"""Return true if sensor is available."""
|
||||||
|
return self.gateway.available and self._sensor.reachable
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
"""No polling needed."""
|
"""No polling needed."""
|
||||||
@ -231,7 +249,7 @@ class DeconzBattery(Entity):
|
|||||||
self._sensor.uniqueid.count(':') != 7):
|
self._sensor.uniqueid.count(':') != 7):
|
||||||
return None
|
return None
|
||||||
serial = self._sensor.uniqueid.split('-', 1)[0]
|
serial = self._sensor.uniqueid.split('-', 1)[0]
|
||||||
bridgeid = self.hass.data[DATA_DECONZ].api.config.bridgeid
|
bridgeid = self.gateway.api.config.bridgeid
|
||||||
return {
|
return {
|
||||||
'connections': {(CONNECTION_ZIGBEE, serial)},
|
'connections': {(CONNECTION_ZIGBEE, serial)},
|
||||||
'identifiers': {(DECONZ_DOMAIN, serial)},
|
'identifiers': {(DECONZ_DOMAIN, serial)},
|
||||||
|
@ -5,7 +5,7 @@ For more details about this platform, please refer to the documentation at
|
|||||||
https://home-assistant.io/components/switch.deconz/
|
https://home-assistant.io/components/switch.deconz/
|
||||||
"""
|
"""
|
||||||
from homeassistant.components.deconz.const import (
|
from homeassistant.components.deconz.const import (
|
||||||
DOMAIN as DATA_DECONZ, DECONZ_DOMAIN, POWER_PLUGS, SIRENS)
|
DECONZ_REACHABLE, DOMAIN as DECONZ_DOMAIN, POWER_PLUGS, SIRENS)
|
||||||
from homeassistant.components.switch import SwitchDevice
|
from homeassistant.components.switch import SwitchDevice
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE
|
from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE
|
||||||
@ -25,38 +25,45 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
|
|
||||||
Switches are based same device class as lights in deCONZ.
|
Switches are based same device class as lights in deCONZ.
|
||||||
"""
|
"""
|
||||||
|
gateway = hass.data[DECONZ_DOMAIN]
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_switch(lights):
|
def async_add_switch(lights):
|
||||||
"""Add switch from deCONZ."""
|
"""Add switch from deCONZ."""
|
||||||
entities = []
|
entities = []
|
||||||
for light in lights:
|
for light in lights:
|
||||||
if light.type in POWER_PLUGS:
|
if light.type in POWER_PLUGS:
|
||||||
entities.append(DeconzPowerPlug(light))
|
entities.append(DeconzPowerPlug(light, gateway))
|
||||||
elif light.type in SIRENS:
|
elif light.type in SIRENS:
|
||||||
entities.append(DeconzSiren(light))
|
entities.append(DeconzSiren(light, gateway))
|
||||||
async_add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
hass.data[DATA_DECONZ].listeners.append(
|
gateway.listeners.append(
|
||||||
async_dispatcher_connect(hass, 'deconz_new_light', async_add_switch))
|
async_dispatcher_connect(hass, 'deconz_new_light', async_add_switch))
|
||||||
|
|
||||||
async_add_switch(hass.data[DATA_DECONZ].api.lights.values())
|
async_add_switch(gateway.api.lights.values())
|
||||||
|
|
||||||
|
|
||||||
class DeconzSwitch(SwitchDevice):
|
class DeconzSwitch(SwitchDevice):
|
||||||
"""Representation of a deCONZ switch."""
|
"""Representation of a deCONZ switch."""
|
||||||
|
|
||||||
def __init__(self, switch):
|
def __init__(self, switch, gateway):
|
||||||
"""Set up switch and add update callback to get data from websocket."""
|
"""Set up switch and add update callback to get data from websocket."""
|
||||||
self._switch = switch
|
self._switch = switch
|
||||||
|
self.gateway = gateway
|
||||||
|
self.unsub_dispatcher = None
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Subscribe to switches events."""
|
"""Subscribe to switches events."""
|
||||||
self._switch.register_async_callback(self.async_update_callback)
|
self._switch.register_async_callback(self.async_update_callback)
|
||||||
self.hass.data[DATA_DECONZ].deconz_ids[self.entity_id] = \
|
self.gateway.deconz_ids[self.entity_id] = self._switch.deconz_id
|
||||||
self._switch.deconz_id
|
self.unsub_dispatcher = async_dispatcher_connect(
|
||||||
|
self.hass, DECONZ_REACHABLE, self.async_update_callback)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Disconnect switch object when removed."""
|
"""Disconnect switch object when removed."""
|
||||||
|
if self.unsub_dispatcher is not None:
|
||||||
|
self.unsub_dispatcher()
|
||||||
self._switch.remove_callback(self.async_update_callback)
|
self._switch.remove_callback(self.async_update_callback)
|
||||||
self._switch = None
|
self._switch = None
|
||||||
|
|
||||||
@ -78,7 +85,7 @@ class DeconzSwitch(SwitchDevice):
|
|||||||
@property
|
@property
|
||||||
def available(self):
|
def available(self):
|
||||||
"""Return True if light is available."""
|
"""Return True if light is available."""
|
||||||
return self._switch.reachable
|
return self.gateway.available and self._switch.reachable
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
@ -92,7 +99,7 @@ class DeconzSwitch(SwitchDevice):
|
|||||||
self._switch.uniqueid.count(':') != 7):
|
self._switch.uniqueid.count(':') != 7):
|
||||||
return None
|
return None
|
||||||
serial = self._switch.uniqueid.split('-', 1)[0]
|
serial = self._switch.uniqueid.split('-', 1)[0]
|
||||||
bridgeid = self.hass.data[DATA_DECONZ].api.config.bridgeid
|
bridgeid = self.gateway.api.config.bridgeid
|
||||||
return {
|
return {
|
||||||
'connections': {(CONNECTION_ZIGBEE, serial)},
|
'connections': {(CONNECTION_ZIGBEE, serial)},
|
||||||
'identifiers': {(DECONZ_DOMAIN, serial)},
|
'identifiers': {(DECONZ_DOMAIN, serial)},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user