* Initial sketches of rflink component. * Add requirement. * Properly load configuration. * Bump rflink for graceful parse errors and protocol callback. * Cleanup, documentation and linting. * More documentation, first sensor implementation (temp & hum). * Add brightness/dim support for newkaku protocol. * Use separate class for dimmables. * Make sure non-dimmable newkaku devices are turned on. * Move some code around, add switches. Support loading from config. * Fix bug in ignoring devices. * Fix initial state assumption. * Improve reliability on invalid conditions. * Allow configuration of group for new devices. * Sensor icons. * Fix parsing negative numbers. * Correct icon. * Allow sending commands serial. * Pluralize. * Allow adding sensors from config. * Fix ignoring devices and bugs in previous commit. * Share know devices so devices from configuration don't get added as lights. * Lookup unit from value_key. * Remove debug. * Start implementing event protocol in place of packet protocol. - Added first test suite for sensors. - This currently breaks light and switch. * Refactor switch component to fit new rflink changes. Add test suite. * Fix style. * Refactor and test lights. Bring coverage to 100%. * Use non-broken and production tested rflink module. * Update requirements. * Bump for logging. * Improve readability. * Do not use global variable but keep known device state in intended place. * Improve docs. * Make icon support generic. * Disable overriding icons in config, as it belongs in customization. Only keep custom icon for entities that are able to detect a icon based on the thing they represent (sensors in this case). * Implement configuration schema, overall refactor of magic values. * Fix bug in config/test wait_for_ack. * Small refactors. * Move command logic into separate class. * Convert command sending logic to class based pattern instead of using the event bus. * Start not using bus for rflink event propagation to platforms. * Do not use event bus for all entity types. * Fire an event on the bus for every switch incoming rflink command. * Resolve lint errors, remove some old code. * Known devices no longer need to be registered separately. * Log bus events. * Event callback is a..... callback. * Use full entity id for events. * Move event sending to entity. * Log incoming events. * Make firing events optional inline with rfxtrx. * Add foundation for signal repetition. * Add signal repetition config and tests. * Make plain switchable type explicitly configurable. * Enable default entity settings for automatically added entities as well. * Prevent default configuration leaking accross entities. * Make sure device defaults don't get overwritten by defaults further down. * Don't let fast state switching and repetitions turn your house into a disco. * Make repetitions more responsive. * Disable on/off fallback on dimmables as it currently doesn't play nice with repetitions. * Use rflink that allows send_command_ack to be safely cancelled. * Reduce duplication and make repeat work for non-ack. * Implement reconnection logic. * Improve reconnection logic. * Also cancel repetitions when entity state is changed due to external command. * Update requirements. * Fix linting. * Fix spelling. * Don't lie. * Fix lint. * Support for automatically creating protocol translation (fixes spaces in device names). * Returned support for dimmable and on/off entity. * Duplicate code to fix linting issues with inheritance. * Allow overriding unit of measurement from config.
141 lines
4.5 KiB
Python
141 lines
4.5 KiB
Python
"""Support for Rflink sensors.
|
|
|
|
For more details about this platform, please refer to the documentation
|
|
at https://home-assistant.io/components/light.rflink/
|
|
|
|
"""
|
|
import asyncio
|
|
from functools import partial
|
|
import logging
|
|
|
|
from homeassistant.components import group
|
|
from homeassistant.components.rflink import (
|
|
CONF_ALIASSES, CONF_DEVICES, CONF_NEW_DEVICES_GROUP, DATA_DEVICE_REGISTER,
|
|
DATA_ENTITY_LOOKUP, DOMAIN, EVENT_KEY_ID, EVENT_KEY_SENSOR, EVENT_KEY_UNIT,
|
|
RflinkDevice, cv, vol)
|
|
from homeassistant.const import (
|
|
ATTR_UNIT_OF_MEASUREMENT, CONF_NAME, CONF_PLATFORM,
|
|
CONF_UNIT_OF_MEASUREMENT)
|
|
|
|
DEPENDENCIES = ['rflink']
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
SENSOR_ICONS = {
|
|
'humidity': 'mdi:water-percent',
|
|
'battery': 'mdi:battery',
|
|
'temperature': 'mdi:thermometer',
|
|
}
|
|
|
|
CONF_SENSOR_TYPE = 'sensor_type'
|
|
|
|
PLATFORM_SCHEMA = vol.Schema({
|
|
vol.Required(CONF_PLATFORM): DOMAIN,
|
|
vol.Optional(CONF_NEW_DEVICES_GROUP, default=None): cv.string,
|
|
vol.Optional(CONF_DEVICES, default={}): vol.Schema({
|
|
cv.string: {
|
|
vol.Optional(CONF_NAME): cv.string,
|
|
vol.Required(CONF_SENSOR_TYPE): cv.string,
|
|
vol.Optional(CONF_UNIT_OF_MEASUREMENT, default=None): cv.string,
|
|
vol.Optional(CONF_ALIASSES, default=[]):
|
|
vol.All(cv.ensure_list, [cv.string]),
|
|
},
|
|
}),
|
|
})
|
|
|
|
|
|
def lookup_unit_for_sensor_type(sensor_type):
|
|
"""Get unit for sensor type.
|
|
|
|
Async friendly.
|
|
|
|
"""
|
|
from rflink.parser import UNITS, PACKET_FIELDS
|
|
field_abbrev = {v: k for k, v in PACKET_FIELDS.items()}
|
|
|
|
return UNITS.get(field_abbrev.get(sensor_type))
|
|
|
|
|
|
def devices_from_config(domain_config, hass=None):
|
|
"""Parse config and add rflink sensor devices."""
|
|
devices = []
|
|
for device_id, config in domain_config[CONF_DEVICES].items():
|
|
if not config[ATTR_UNIT_OF_MEASUREMENT]:
|
|
config[ATTR_UNIT_OF_MEASUREMENT] = lookup_unit_for_sensor_type(
|
|
config[CONF_SENSOR_TYPE])
|
|
device = RflinkSensor(device_id, hass, **config)
|
|
devices.append(device)
|
|
|
|
# register entity to listen to incoming rflink events
|
|
hass.data[DATA_ENTITY_LOOKUP][
|
|
EVENT_KEY_SENSOR][device_id].append(device)
|
|
return devices
|
|
|
|
|
|
@asyncio.coroutine
|
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|
"""Setup the Rflink platform."""
|
|
# add devices from config
|
|
yield from async_add_devices(devices_from_config(config, hass))
|
|
|
|
# add new (unconfigured) devices to user desired group
|
|
if config[CONF_NEW_DEVICES_GROUP]:
|
|
new_devices_group = yield from group.Group.async_create_group(
|
|
hass, config[CONF_NEW_DEVICES_GROUP], [], True)
|
|
else:
|
|
new_devices_group = None
|
|
|
|
@asyncio.coroutine
|
|
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])
|
|
# add device entity
|
|
yield from async_add_devices([device])
|
|
|
|
# register entity to listen to incoming rflink events
|
|
hass.data[DATA_ENTITY_LOOKUP][
|
|
EVENT_KEY_SENSOR][device_id].append(device)
|
|
|
|
# make sure the event is processed by the new entity
|
|
device.handle_event(event)
|
|
|
|
# maybe add to new devices group
|
|
if new_devices_group:
|
|
yield from new_devices_group.async_update_tracked_entity_ids(
|
|
list(new_devices_group.tracking) + [device.entity_id])
|
|
|
|
hass.data[DATA_DEVICE_REGISTER][EVENT_KEY_SENSOR] = add_new_device
|
|
|
|
|
|
class RflinkSensor(RflinkDevice):
|
|
"""Representation of a Rflink sensor."""
|
|
|
|
def __init__(self, device_id, hass, sensor_type,
|
|
unit_of_measurement, **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)
|
|
|
|
def _handle_event(self, event):
|
|
"""Domain specific event handler."""
|
|
self._state = event['value']
|
|
|
|
@property
|
|
def unit_of_measurement(self):
|
|
"""Return measurement unit."""
|
|
return self._unit_of_measurement
|
|
|
|
@property
|
|
def state(self):
|
|
"""Return value."""
|
|
return self._state
|
|
|
|
@property
|
|
def icon(self):
|
|
"""Return possible sensor specific icon."""
|
|
if self._sensor_type in SENSOR_ICONS:
|
|
return SENSOR_ICONS[self._sensor_type]
|