Refactor RFLink component (#17402)
* Start refactor of RFLink component * alias _id not added correctly Aliases for sensor not added correctly And some debug traces. * Update rflink.py * Cleanup, fix review comments * Call event handlers directly when processing initial event * Use hass.async_create_task when adding discovered device * Review comments * Review comments
This commit is contained in:
parent
0904ff45fe
commit
2ceb4d2d1e
5 changed files with 168 additions and 184 deletions
|
@ -9,8 +9,9 @@ import logging
|
|||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.rflink import (
|
||||
DATA_ENTITY_GROUP_LOOKUP, DATA_ENTITY_LOOKUP,
|
||||
DEVICE_DEFAULTS_SCHEMA, EVENT_KEY_COMMAND, RflinkCommand)
|
||||
CONF_ALIASES, CONF_DEVICE_DEFAULTS, CONF_DEVICES, CONF_FIRE_EVENT,
|
||||
CONF_GROUP, CONF_GROUP_ALIASES, CONF_NOGROUP_ALIASES,
|
||||
CONF_SIGNAL_REPETITIONS, DEVICE_DEFAULTS_SCHEMA, RflinkCommand)
|
||||
from homeassistant.components.cover import (
|
||||
CoverDevice, PLATFORM_SCHEMA)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
@ -22,19 +23,6 @@ DEPENDENCIES = ['rflink']
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
CONF_ALIASES = 'aliases'
|
||||
CONF_GROUP_ALIASES = 'group_aliases'
|
||||
CONF_GROUP = 'group'
|
||||
CONF_NOGROUP_ALIASES = 'nogroup_aliases'
|
||||
CONF_DEVICE_DEFAULTS = 'device_defaults'
|
||||
CONF_DEVICES = 'devices'
|
||||
CONF_AUTOMATIC_ADD = 'automatic_add'
|
||||
CONF_FIRE_EVENT = 'fire_event'
|
||||
CONF_IGNORE_DEVICES = 'ignore_devices'
|
||||
CONF_RECONNECT_INTERVAL = 'reconnect_interval'
|
||||
CONF_SIGNAL_REPETITIONS = 'signal_repetitions'
|
||||
CONF_WAIT_FOR_ACK = 'wait_for_ack'
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Optional(CONF_DEVICE_DEFAULTS, default=DEVICE_DEFAULTS_SCHEMA({})):
|
||||
DEVICE_DEFAULTS_SCHEMA,
|
||||
|
@ -55,33 +43,21 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||
})
|
||||
|
||||
|
||||
def devices_from_config(domain_config, hass=None):
|
||||
def devices_from_config(domain_config):
|
||||
"""Parse configuration and add Rflink cover devices."""
|
||||
devices = []
|
||||
for device_id, config in domain_config[CONF_DEVICES].items():
|
||||
device_config = dict(domain_config[CONF_DEVICE_DEFAULTS], **config)
|
||||
device = RflinkCover(device_id, hass, **device_config)
|
||||
device = RflinkCover(device_id, **device_config)
|
||||
devices.append(device)
|
||||
|
||||
# Register entity (and aliases) to listen to incoming rflink events
|
||||
# Device id and normal aliases respond to normal and group command
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][device_id].append(device)
|
||||
if config[CONF_GROUP]:
|
||||
hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][device_id].append(device)
|
||||
for _id in config[CONF_ALIASES]:
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(device)
|
||||
hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(device)
|
||||
return devices
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
"""Set up the Rflink cover platform."""
|
||||
async_add_entities(devices_from_config(config, hass))
|
||||
async_add_entities(devices_from_config(config))
|
||||
|
||||
|
||||
class RflinkCover(RflinkCommand, CoverDevice):
|
||||
|
|
|
@ -7,18 +7,16 @@ https://home-assistant.io/components/light.rflink/
|
|||
import logging
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light)
|
||||
ATTR_BRIGHTNESS, PLATFORM_SCHEMA, SUPPORT_BRIGHTNESS, Light)
|
||||
from homeassistant.components.rflink import (
|
||||
CONF_ALIASES, CONF_ALIASSES, CONF_AUTOMATIC_ADD, CONF_DEVICE_DEFAULTS,
|
||||
CONF_DEVICES, CONF_FIRE_EVENT, CONF_GROUP, CONF_GROUP_ALIASES,
|
||||
CONF_GROUP_ALIASSES, CONF_IGNORE_DEVICES, CONF_NOGROUP_ALIASES,
|
||||
CONF_NOGROUP_ALIASSES, CONF_SIGNAL_REPETITIONS, DATA_DEVICE_REGISTER,
|
||||
DATA_ENTITY_GROUP_LOOKUP, DATA_ENTITY_LOOKUP, DEVICE_DEFAULTS_SCHEMA,
|
||||
DOMAIN, EVENT_KEY_COMMAND, EVENT_KEY_ID, SwitchableRflinkDevice, cv,
|
||||
DEVICE_DEFAULTS_SCHEMA,
|
||||
EVENT_KEY_COMMAND, EVENT_KEY_ID, SwitchableRflinkDevice, cv,
|
||||
remove_deprecated, vol)
|
||||
from homeassistant.const import (
|
||||
CONF_NAME, CONF_PLATFORM, CONF_TYPE, STATE_UNKNOWN)
|
||||
from homeassistant.helpers.deprecation import get_deprecated
|
||||
from homeassistant.const import (CONF_NAME, CONF_TYPE)
|
||||
|
||||
DEPENDENCIES = ['rflink']
|
||||
|
||||
|
@ -29,14 +27,13 @@ TYPE_SWITCHABLE = 'switchable'
|
|||
TYPE_HYBRID = 'hybrid'
|
||||
TYPE_TOGGLE = 'toggle'
|
||||
|
||||
PLATFORM_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_PLATFORM): DOMAIN,
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Optional(CONF_IGNORE_DEVICES): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(CONF_DEVICE_DEFAULTS, default=DEVICE_DEFAULTS_SCHEMA({})):
|
||||
DEVICE_DEFAULTS_SCHEMA,
|
||||
DEVICE_DEFAULTS_SCHEMA,
|
||||
vol.Optional(CONF_AUTOMATIC_ADD, default=True): cv.boolean,
|
||||
vol.Optional(CONF_DEVICES, default={}): vol.Schema({
|
||||
cv.string: {
|
||||
vol.Optional(CONF_DEVICES, default={}): {
|
||||
cv.string: vol.Schema({
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_TYPE):
|
||||
vol.Any(TYPE_DIMMABLE, TYPE_SWITCHABLE,
|
||||
|
@ -57,9 +54,9 @@ PLATFORM_SCHEMA = vol.Schema({
|
|||
vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(CONF_NOGROUP_ALIASSES):
|
||||
vol.All(cv.ensure_list, [cv.string]),
|
||||
},
|
||||
}),
|
||||
})
|
||||
})
|
||||
},
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
def entity_type_for_device_id(device_id):
|
||||
|
@ -98,7 +95,7 @@ def entity_class_for_type(entity_type):
|
|||
return entity_device_mapping.get(entity_type, RflinkLight)
|
||||
|
||||
|
||||
def devices_from_config(domain_config, hass=None):
|
||||
def devices_from_config(domain_config):
|
||||
"""Parse configuration and add Rflink light devices."""
|
||||
devices = []
|
||||
for device_id, config in domain_config[CONF_DEVICES].items():
|
||||
|
@ -124,40 +121,16 @@ def devices_from_config(domain_config, hass=None):
|
|||
"repetitions. Please set 'dimmable' or 'switchable' "
|
||||
"type explicitly in configuration", device_id)
|
||||
|
||||
device = entity_class(device_id, hass, **device_config)
|
||||
device = entity_class(device_id, **device_config)
|
||||
devices.append(device)
|
||||
|
||||
# Register entity (and aliases) to listen to incoming rflink events
|
||||
|
||||
# Device id and normal aliases respond to normal and group command
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][device_id].append(device)
|
||||
if config[CONF_GROUP]:
|
||||
hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][device_id].append(device)
|
||||
for _id in get_deprecated(config, CONF_ALIASES, CONF_ALIASSES):
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(device)
|
||||
hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(device)
|
||||
# group_aliases only respond to group commands
|
||||
for _id in get_deprecated(
|
||||
config, CONF_GROUP_ALIASES, CONF_GROUP_ALIASSES):
|
||||
hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(device)
|
||||
# nogroup_aliases only respond to normal commands
|
||||
for _id in get_deprecated(
|
||||
config, CONF_NOGROUP_ALIASES, CONF_NOGROUP_ALIASSES):
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(device)
|
||||
|
||||
return devices
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
"""Set up the Rflink light platform."""
|
||||
async_add_entities(devices_from_config(config, hass))
|
||||
async_add_entities(devices_from_config(config))
|
||||
|
||||
async def add_new_device(event):
|
||||
"""Check if device is known, otherwise add to list of known devices."""
|
||||
|
@ -167,16 +140,9 @@ async def async_setup_platform(hass, config, async_add_entities,
|
|||
entity_class = entity_class_for_type(entity_type)
|
||||
|
||||
device_config = config[CONF_DEVICE_DEFAULTS]
|
||||
device = entity_class(device_id, hass, **device_config)
|
||||
device = entity_class(device_id, initial_event=event, **device_config)
|
||||
async_add_entities([device])
|
||||
|
||||
# Register entity to listen to incoming Rflink events
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][device_id].append(device)
|
||||
|
||||
# Schedule task to process event after entity is created
|
||||
hass.async_add_job(device.handle_event, event)
|
||||
|
||||
if config[CONF_AUTOMATIC_ADD]:
|
||||
hass.data[DATA_DEVICE_REGISTER][EVENT_KEY_COMMAND] = add_new_device
|
||||
|
||||
|
@ -277,7 +243,7 @@ class ToggleRflinkLight(SwitchableRflinkDevice, Light):
|
|||
if command == 'on':
|
||||
# if the state is unknown or false, it gets set as true
|
||||
# if the state is true, it gets set as false
|
||||
self._state = self._state in [STATE_UNKNOWN, False]
|
||||
self._state = self._state in [None, False]
|
||||
|
||||
async def async_turn_on(self, **kwargs):
|
||||
"""Turn the device on."""
|
||||
|
|
|
@ -6,7 +6,6 @@ https://home-assistant.io/components/rflink/
|
|||
"""
|
||||
import asyncio
|
||||
from collections import defaultdict
|
||||
import functools as ft
|
||||
import logging
|
||||
import async_timeout
|
||||
|
||||
|
@ -14,7 +13,7 @@ import voluptuous as vol
|
|||
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, CONF_COMMAND, CONF_HOST, CONF_PORT,
|
||||
EVENT_HOMEASSISTANT_STOP, STATE_UNKNOWN)
|
||||
EVENT_HOMEASSISTANT_STOP)
|
||||
from homeassistant.core import CoreState, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
@ -68,6 +67,9 @@ DOMAIN = 'rflink'
|
|||
SERVICE_SEND_COMMAND = 'send_command'
|
||||
|
||||
SIGNAL_AVAILABILITY = 'rflink_device_available'
|
||||
SIGNAL_HANDLE_EVENT = 'rflink_handle_event_{}'
|
||||
|
||||
TMP_ENTITY = 'tmp.{}'
|
||||
|
||||
DEVICE_DEFAULTS_SCHEMA = vol.Schema({
|
||||
vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean,
|
||||
|
@ -153,28 +155,38 @@ async def async_setup(hass, config):
|
|||
return
|
||||
|
||||
# Lookup entities who registered this device id as device id or alias
|
||||
event_id = event.get('id', None)
|
||||
event_id = event.get(EVENT_KEY_ID, None)
|
||||
|
||||
is_group_event = (event_type == EVENT_KEY_COMMAND and
|
||||
event[EVENT_KEY_COMMAND] in RFLINK_GROUP_COMMANDS)
|
||||
if is_group_event:
|
||||
entities = hass.data[DATA_ENTITY_GROUP_LOOKUP][event_type].get(
|
||||
entity_ids = hass.data[DATA_ENTITY_GROUP_LOOKUP][event_type].get(
|
||||
event_id, [])
|
||||
else:
|
||||
entities = hass.data[DATA_ENTITY_LOOKUP][event_type][event_id]
|
||||
entity_ids = hass.data[DATA_ENTITY_LOOKUP][event_type][event_id]
|
||||
|
||||
if entities:
|
||||
_LOGGER.debug('entity_ids: %s', entity_ids)
|
||||
if entity_ids:
|
||||
# Propagate event to every entity matching the device id
|
||||
for entity in entities:
|
||||
_LOGGER.debug('passing event to %s', entities)
|
||||
entity.handle_event(event)
|
||||
else:
|
||||
_LOGGER.debug('device_id not known, adding new device')
|
||||
|
||||
for entity in entity_ids:
|
||||
_LOGGER.debug('passing event to %s', entity)
|
||||
async_dispatcher_send(hass,
|
||||
SIGNAL_HANDLE_EVENT.format(entity),
|
||||
event)
|
||||
elif not is_group_event:
|
||||
# If device is not yet known, register with platform (if loaded)
|
||||
if event_type in hass.data[DATA_DEVICE_REGISTER]:
|
||||
hass.async_run_job(
|
||||
hass.data[DATA_DEVICE_REGISTER][event_type], event)
|
||||
_LOGGER.debug('device_id not known, adding new device')
|
||||
# Add bogus event_id first to avoid race if we get another
|
||||
# event before the device is created
|
||||
# Any additional events recevied before the device has been
|
||||
# created will thus be ignored.
|
||||
hass.data[DATA_ENTITY_LOOKUP][event_type][
|
||||
event_id].append(TMP_ENTITY.format(event_id))
|
||||
hass.async_create_task(
|
||||
hass.data[DATA_DEVICE_REGISTER][event_type](event))
|
||||
else:
|
||||
_LOGGER.debug('device_id not known and automatic add disabled')
|
||||
|
||||
# When connecting to tcp host instead of serial port (optional)
|
||||
host = config[DOMAIN].get(CONF_HOST)
|
||||
|
@ -192,7 +204,7 @@ async def async_setup(hass, config):
|
|||
# If HA is not stopping, initiate new connection
|
||||
if hass.state != CoreState.stopping:
|
||||
_LOGGER.warning('disconnected from Rflink, reconnecting')
|
||||
hass.async_add_job(connect)
|
||||
hass.async_create_task(connect())
|
||||
|
||||
async def connect():
|
||||
"""Set up connection and hook it into HA for reconnect/shutdown."""
|
||||
|
@ -242,7 +254,7 @@ async def async_setup(hass, config):
|
|||
|
||||
_LOGGER.info('Connected to Rflink')
|
||||
|
||||
hass.async_add_job(connect)
|
||||
hass.async_create_task(connect())
|
||||
return True
|
||||
|
||||
|
||||
|
@ -253,26 +265,31 @@ class RflinkDevice(Entity):
|
|||
"""
|
||||
|
||||
platform = None
|
||||
_state = STATE_UNKNOWN
|
||||
_state = None
|
||||
_available = True
|
||||
|
||||
def __init__(self, device_id, hass, name=None, aliases=None, group=True,
|
||||
group_aliases=None, nogroup_aliases=None, fire_event=False,
|
||||
def __init__(self, device_id, initial_event=None, name=None, aliases=None,
|
||||
group=True, group_aliases=None, nogroup_aliases=None,
|
||||
fire_event=False,
|
||||
signal_repetitions=DEFAULT_SIGNAL_REPETITIONS):
|
||||
"""Initialize the device."""
|
||||
self.hass = hass
|
||||
|
||||
# Rflink specific attributes for every component type
|
||||
self._initial_event = initial_event
|
||||
self._device_id = device_id
|
||||
if name:
|
||||
self._name = name
|
||||
else:
|
||||
self._name = device_id
|
||||
|
||||
self._aliases = aliases
|
||||
self._group = group
|
||||
self._group_aliases = group_aliases
|
||||
self._nogroup_aliases = nogroup_aliases
|
||||
self._should_fire_event = fire_event
|
||||
self._signal_repetitions = signal_repetitions
|
||||
|
||||
def handle_event(self, event):
|
||||
@callback
|
||||
def handle_event_callback(self, event):
|
||||
"""Handle incoming event for device type."""
|
||||
# Call platform specific event handler
|
||||
self._handle_event(event)
|
||||
|
@ -283,7 +300,7 @@ class RflinkDevice(Entity):
|
|||
# Put command onto bus for user to subscribe to
|
||||
if self._should_fire_event and identify_event_type(
|
||||
event) == EVENT_KEY_COMMAND:
|
||||
self.hass.bus.fire(EVENT_BUTTON_PRESSED, {
|
||||
self.hass.bus.async_fire(EVENT_BUTTON_PRESSED, {
|
||||
ATTR_ENTITY_ID: self.entity_id,
|
||||
ATTR_STATE: event[EVENT_KEY_COMMAND],
|
||||
})
|
||||
|
@ -314,7 +331,7 @@ class RflinkDevice(Entity):
|
|||
@property
|
||||
def assumed_state(self):
|
||||
"""Assume device state until first device event sets state."""
|
||||
return self._state is STATE_UNKNOWN
|
||||
return self._state is None
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
|
@ -322,15 +339,52 @@ class RflinkDevice(Entity):
|
|||
return self._available
|
||||
|
||||
@callback
|
||||
def set_availability(self, availability):
|
||||
def _availability_callback(self, availability):
|
||||
"""Update availability state."""
|
||||
self._available = availability
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register update callback."""
|
||||
# Remove temporary bogus entity_id if added
|
||||
tmp_entity = TMP_ENTITY.format(self._device_id)
|
||||
if tmp_entity in self.hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_SENSOR][self._device_id]:
|
||||
self.hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_SENSOR][self._device_id].remove(tmp_entity)
|
||||
|
||||
# Register id and aliases
|
||||
self.hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][self._device_id].append(self.entity_id)
|
||||
if self._group:
|
||||
self.hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][self._device_id].append(self.entity_id)
|
||||
# aliases respond to both normal and group commands (allon/alloff)
|
||||
if self._aliases:
|
||||
for _id in self._aliases:
|
||||
self.hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(self.entity_id)
|
||||
self.hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(self.entity_id)
|
||||
# group_aliases only respond to group commands (allon/alloff)
|
||||
if self._group_aliases:
|
||||
for _id in self._group_aliases:
|
||||
self.hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(self.entity_id)
|
||||
# nogroup_aliases only respond to normal commands
|
||||
if self._nogroup_aliases:
|
||||
for _id in self._nogroup_aliases:
|
||||
self.hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(self.entity_id)
|
||||
async_dispatcher_connect(self.hass, SIGNAL_AVAILABILITY,
|
||||
self.set_availability)
|
||||
self._availability_callback)
|
||||
async_dispatcher_connect(self.hass,
|
||||
SIGNAL_HANDLE_EVENT.format(self.entity_id),
|
||||
self.handle_event_callback)
|
||||
|
||||
# Process the initial event now that the entity is created
|
||||
if self._initial_event:
|
||||
self.handle_event_callback(self._initial_event)
|
||||
|
||||
|
||||
class RflinkCommand(RflinkDevice):
|
||||
|
@ -388,7 +442,7 @@ class RflinkCommand(RflinkDevice):
|
|||
cmd = 'on'
|
||||
# if the state is unknown or false, it gets set as true
|
||||
# if the state is true, it gets set as false
|
||||
self._state = self._state in [STATE_UNKNOWN, False]
|
||||
self._state = self._state in [None, False]
|
||||
|
||||
# Cover options for RFlink
|
||||
elif command == 'close_cover':
|
||||
|
@ -439,8 +493,8 @@ class RflinkCommand(RflinkDevice):
|
|||
# Rflink protocol/transport handles asynchronous writing of buffer
|
||||
# to serial/tcp device. Does not wait for command send
|
||||
# confirmation.
|
||||
self.hass.async_add_job(ft.partial(
|
||||
self._protocol.send_command, self._device_id, cmd))
|
||||
self.hass.async_create_task(self._protocol.send_command(
|
||||
self._device_id, cmd))
|
||||
|
||||
if repetitions > 1:
|
||||
self._repetition_task = self.hass.async_create_task(
|
||||
|
|
|
@ -4,16 +4,18 @@ Support for Rflink sensors.
|
|||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/light.rflink/
|
||||
"""
|
||||
from functools import partial
|
||||
import logging
|
||||
|
||||
from homeassistant.components.rflink import (
|
||||
CONF_ALIASES, CONF_ALIASSES, CONF_AUTOMATIC_ADD, CONF_DEVICES,
|
||||
DATA_DEVICE_REGISTER, DATA_ENTITY_LOOKUP, DOMAIN, EVENT_KEY_ID,
|
||||
EVENT_KEY_SENSOR, EVENT_KEY_UNIT, RflinkDevice, cv, remove_deprecated, vol)
|
||||
DATA_DEVICE_REGISTER, DATA_ENTITY_LOOKUP, EVENT_KEY_ID,
|
||||
EVENT_KEY_SENSOR, EVENT_KEY_UNIT, RflinkDevice, cv, remove_deprecated, vol,
|
||||
SIGNAL_AVAILABILITY, SIGNAL_HANDLE_EVENT, TMP_ENTITY)
|
||||
from homeassistant.components.sensor import (
|
||||
PLATFORM_SCHEMA)
|
||||
from homeassistant.const import (
|
||||
ATTR_UNIT_OF_MEASUREMENT, CONF_NAME, CONF_PLATFORM,
|
||||
CONF_UNIT_OF_MEASUREMENT)
|
||||
ATTR_UNIT_OF_MEASUREMENT, CONF_NAME, CONF_UNIT_OF_MEASUREMENT)
|
||||
from homeassistant.helpers.dispatcher import (async_dispatcher_connect)
|
||||
|
||||
DEPENDENCIES = ['rflink']
|
||||
|
||||
|
@ -27,11 +29,10 @@ SENSOR_ICONS = {
|
|||
|
||||
CONF_SENSOR_TYPE = 'sensor_type'
|
||||
|
||||
PLATFORM_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_PLATFORM): DOMAIN,
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Optional(CONF_AUTOMATIC_ADD, default=True): cv.boolean,
|
||||
vol.Optional(CONF_DEVICES, default={}): vol.Schema({
|
||||
cv.string: {
|
||||
vol.Optional(CONF_DEVICES, default={}): {
|
||||
cv.string: vol.Schema({
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Required(CONF_SENSOR_TYPE): cv.string,
|
||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
|
||||
|
@ -40,9 +41,9 @@ PLATFORM_SCHEMA = vol.Schema({
|
|||
# deprecated config options
|
||||
vol.Optional(CONF_ALIASSES):
|
||||
vol.All(cv.ensure_list, [cv.string]),
|
||||
},
|
||||
}),
|
||||
})
|
||||
})
|
||||
},
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
def lookup_unit_for_sensor_type(sensor_type):
|
||||
|
@ -56,7 +57,7 @@ def lookup_unit_for_sensor_type(sensor_type):
|
|||
return UNITS.get(field_abbrev.get(sensor_type))
|
||||
|
||||
|
||||
def devices_from_config(domain_config, hass=None):
|
||||
def devices_from_config(domain_config):
|
||||
"""Parse configuration and add Rflink sensor devices."""
|
||||
devices = []
|
||||
for device_id, config in domain_config[CONF_DEVICES].items():
|
||||
|
@ -64,41 +65,26 @@ def devices_from_config(domain_config, hass=None):
|
|||
config[ATTR_UNIT_OF_MEASUREMENT] = lookup_unit_for_sensor_type(
|
||||
config[CONF_SENSOR_TYPE])
|
||||
remove_deprecated(config)
|
||||
device = RflinkSensor(device_id, hass, **config)
|
||||
device = RflinkSensor(device_id, **config)
|
||||
devices.append(device)
|
||||
|
||||
# Register entity (and aliases) to listen to incoming rflink events
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_SENSOR][device_id].append(device)
|
||||
aliases = config.get(CONF_ALIASES)
|
||||
if aliases:
|
||||
for _id in aliases:
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_SENSOR][_id].append(device)
|
||||
return devices
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
"""Set up the Rflink platform."""
|
||||
async_add_entities(devices_from_config(config, hass))
|
||||
async_add_entities(devices_from_config(config))
|
||||
|
||||
async def add_new_device(event):
|
||||
"""Check if device is known, otherwise create device entity."""
|
||||
device_id = event[EVENT_KEY_ID]
|
||||
|
||||
rflinksensor = partial(RflinkSensor, device_id, hass)
|
||||
device = rflinksensor(event[EVENT_KEY_SENSOR], event[EVENT_KEY_UNIT])
|
||||
device = RflinkSensor(device_id, event[EVENT_KEY_SENSOR],
|
||||
event[EVENT_KEY_UNIT], initial_event=event)
|
||||
# Add device entity
|
||||
async_add_entities([device])
|
||||
|
||||
# Register entity to listen to incoming rflink events
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_SENSOR][device_id].append(device)
|
||||
|
||||
# Schedule task to process event after entity is created
|
||||
hass.async_add_job(device.handle_event, event)
|
||||
|
||||
if config[CONF_AUTOMATIC_ADD]:
|
||||
hass.data[DATA_DEVICE_REGISTER][EVENT_KEY_SENSOR] = add_new_device
|
||||
|
||||
|
@ -106,17 +92,43 @@ async def async_setup_platform(hass, config, async_add_entities,
|
|||
class RflinkSensor(RflinkDevice):
|
||||
"""Representation of a Rflink sensor."""
|
||||
|
||||
def __init__(self, device_id, hass, sensor_type, unit_of_measurement,
|
||||
**kwargs):
|
||||
def __init__(self, device_id, sensor_type, unit_of_measurement,
|
||||
initial_event=None, **kwargs):
|
||||
"""Handle sensor specific args and super init."""
|
||||
self._sensor_type = sensor_type
|
||||
self._unit_of_measurement = unit_of_measurement
|
||||
super().__init__(device_id, hass, **kwargs)
|
||||
super().__init__(device_id, initial_event=initial_event, **kwargs)
|
||||
|
||||
def _handle_event(self, event):
|
||||
"""Domain specific event handler."""
|
||||
self._state = event['value']
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register update callback."""
|
||||
# Remove temporary bogus entity_id if added
|
||||
tmp_entity = TMP_ENTITY.format(self._device_id)
|
||||
if tmp_entity in self.hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_SENSOR][self._device_id]:
|
||||
self.hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_SENSOR][self._device_id].remove(tmp_entity)
|
||||
|
||||
# Register id and aliases
|
||||
self.hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_SENSOR][self._device_id].append(self.entity_id)
|
||||
if self._aliases:
|
||||
for _id in self._aliases:
|
||||
self.hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_SENSOR][_id].append(self.entity_id)
|
||||
async_dispatcher_connect(self.hass, SIGNAL_AVAILABILITY,
|
||||
self._availability_callback)
|
||||
async_dispatcher_connect(self.hass,
|
||||
SIGNAL_HANDLE_EVENT.format(self.entity_id),
|
||||
self.handle_event_callback)
|
||||
|
||||
# Process the initial event now that the entity is created
|
||||
if self._initial_event:
|
||||
self.handle_event_callback(self._initial_event)
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return measurement unit."""
|
||||
|
|
|
@ -10,23 +10,22 @@ from homeassistant.components.rflink import (
|
|||
CONF_ALIASES, CONF_ALIASSES, CONF_DEVICE_DEFAULTS, CONF_DEVICES,
|
||||
CONF_FIRE_EVENT, CONF_GROUP, CONF_GROUP_ALIASES, CONF_GROUP_ALIASSES,
|
||||
CONF_NOGROUP_ALIASES, CONF_NOGROUP_ALIASSES, CONF_SIGNAL_REPETITIONS,
|
||||
DATA_ENTITY_GROUP_LOOKUP, DATA_ENTITY_LOOKUP, DEVICE_DEFAULTS_SCHEMA,
|
||||
DOMAIN, EVENT_KEY_COMMAND, SwitchableRflinkDevice, cv, remove_deprecated,
|
||||
vol)
|
||||
from homeassistant.components.switch import SwitchDevice
|
||||
from homeassistant.const import CONF_NAME, CONF_PLATFORM
|
||||
from homeassistant.helpers.deprecation import get_deprecated
|
||||
DEVICE_DEFAULTS_SCHEMA, SwitchableRflinkDevice, cv,
|
||||
remove_deprecated, vol)
|
||||
from homeassistant.components.switch import (
|
||||
PLATFORM_SCHEMA, SwitchDevice)
|
||||
|
||||
from homeassistant.const import CONF_NAME
|
||||
|
||||
DEPENDENCIES = ['rflink']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PLATFORM_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_PLATFORM): DOMAIN,
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Optional(CONF_DEVICE_DEFAULTS, default=DEVICE_DEFAULTS_SCHEMA({})):
|
||||
DEVICE_DEFAULTS_SCHEMA,
|
||||
vol.Optional(CONF_DEVICES, default={}): vol.Schema({
|
||||
cv.string: {
|
||||
DEVICE_DEFAULTS_SCHEMA,
|
||||
vol.Optional(CONF_DEVICES, default={}): {
|
||||
cv.string: vol.Schema({
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_ALIASES, default=[]):
|
||||
vol.All(cv.ensure_list, [cv.string]),
|
||||
|
@ -44,50 +43,27 @@ PLATFORM_SCHEMA = vol.Schema({
|
|||
vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(CONF_NOGROUP_ALIASSES):
|
||||
vol.All(cv.ensure_list, [cv.string]),
|
||||
},
|
||||
}),
|
||||
})
|
||||
})
|
||||
},
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
def devices_from_config(domain_config, hass=None):
|
||||
def devices_from_config(domain_config):
|
||||
"""Parse configuration and add Rflink switch devices."""
|
||||
devices = []
|
||||
for device_id, config in domain_config[CONF_DEVICES].items():
|
||||
device_config = dict(domain_config[CONF_DEVICE_DEFAULTS], **config)
|
||||
remove_deprecated(device_config)
|
||||
device = RflinkSwitch(device_id, hass, **device_config)
|
||||
device = RflinkSwitch(device_id, **device_config)
|
||||
devices.append(device)
|
||||
|
||||
# Register entity (and aliases) to listen to incoming rflink events
|
||||
# Device id and normal aliases respond to normal and group command
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][device_id].append(device)
|
||||
if config[CONF_GROUP]:
|
||||
hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][device_id].append(device)
|
||||
for _id in get_deprecated(config, CONF_ALIASES, CONF_ALIASSES):
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(device)
|
||||
hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(device)
|
||||
# group_aliases only respond to group commands
|
||||
for _id in get_deprecated(
|
||||
config, CONF_GROUP_ALIASES, CONF_GROUP_ALIASSES):
|
||||
hass.data[DATA_ENTITY_GROUP_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(device)
|
||||
# nogroup_aliases only respond to normal commands
|
||||
for _id in get_deprecated(
|
||||
config, CONF_NOGROUP_ALIASES, CONF_NOGROUP_ALIASSES):
|
||||
hass.data[DATA_ENTITY_LOOKUP][
|
||||
EVENT_KEY_COMMAND][_id].append(device)
|
||||
|
||||
return devices
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
"""Set up the Rflink platform."""
|
||||
async_add_entities(devices_from_config(config, hass))
|
||||
async_add_entities(devices_from_config(config))
|
||||
|
||||
|
||||
class RflinkSwitch(SwitchableRflinkDevice, SwitchDevice):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue