New configuration for rfxtrx sensor

pull/1905/head
Daniel 2016-04-23 19:55:05 +02:00
parent 2333c0ca3b
commit 74022a3978
2 changed files with 128 additions and 92 deletions
homeassistant/components

View File

@ -5,6 +5,7 @@ For more details about this component, please refer to the documentation at
https://home-assistant.io/components/rfxtrx/
"""
import logging
from collections import OrderedDict
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
@ -22,7 +23,6 @@ ATTR_DEVICE = 'device'
ATTR_DEBUG = 'debug'
ATTR_STATE = 'state'
ATTR_NAME = 'name'
ATTR_PACKETID = 'packetid'
ATTR_FIREEVENT = 'fire_event'
ATTR_DATA_TYPE = 'data_type'
ATTR_DUMMY = 'dummy'
@ -45,21 +45,39 @@ def validate_packetid(value):
else:
raise vol.Invalid('invalid packet id for {}'.format(value))
# Share between rfxtrx platforms
VALID_DEVICE_ID = vol.All(cv.string, vol.Lower)
VALID_SENSOR_DEVICE_ID = vol.All(VALID_DEVICE_ID,
vol.truth(lambda val:
val.startswith('sensor_')))
DEVICE_SCHEMA = vol.Schema({
vol.Required(ATTR_NAME): cv.string,
vol.Required(ATTR_PACKETID): validate_packetid,
vol.Optional(ATTR_FIREEVENT, default=False): cv.boolean,
})
def _valid_device(value):
"""Validate a dictionary of devices definitions."""
config = OrderedDict()
for key, device in value.items():
# Still accept old configuration
if 'packetid' in device.keys():
print(key, device.keys(), device, config)
msg = 'You are using an outdated configuration of the rfxtrx ' +\
'devuce, {}. Your new config should be:\n{}: \n\t name:{}\n'\
.format(key, device.get('packetid'),
device.get(ATTR_NAME, 'deivce_name'))
_LOGGER.warning(msg)
key = device.get('packetid')
device.pop('packetid')
try:
key = validate_packetid(key)
config[key] = DEVICE_SCHEMA(device)
if not config[key][ATTR_NAME]:
config[key][ATTR_NAME] = key
except vol.MultipleInvalid as ex:
raise vol.Invalid('Rfxtrx deive {} is invalid: {}'
.format(key, ex))
return config
DEFAULT_SCHEMA = vol.Schema({
vol.Required("platform"): DOMAIN,
vol.Required(CONF_DEVICES): {cv.slug: DEVICE_SCHEMA},
vol.Required(CONF_DEVICES): vol.All(dict, _valid_device),
vol.Optional(ATTR_AUTOMATIC_ADD, default=False): cv.boolean,
vol.Optional(CONF_SIGNAL_REPETITIONS, default=DEFAULT_SIGNAL_REPETITIONS):
vol.Coerce(int),
@ -141,7 +159,9 @@ def get_devices_from_config(config, device):
signal_repetitions = config[CONF_SIGNAL_REPETITIONS]
devices = []
for device_id, entity_info in config[CONF_DEVICES].items():
for packet_id, entity_info in config[CONF_DEVICES].items():
event = get_rfx_object(packet_id)
device_id = slugify(event.device.id_string.lower())
if device_id in RFX_DEVICES:
continue
_LOGGER.info("Add %s rfxtrx", entity_info[ATTR_NAME])
@ -150,8 +170,7 @@ def get_devices_from_config(config, device):
fire_event = entity_info[ATTR_FIREEVENT]
datas = {ATTR_STATE: False, ATTR_FIREEVENT: fire_event}
rfxobject = get_rfx_object(entity_info[ATTR_PACKETID])
new_device = device(entity_info[ATTR_NAME], rfxobject, datas,
new_device = device(entity_info[ATTR_NAME], event, datas,
signal_repetitions)
RFX_DEVICES[device_id] = new_device
devices.append(new_device)
@ -161,68 +180,67 @@ def get_devices_from_config(config, device):
def get_new_device(event, config, device):
"""Add entity if not exist and the automatic_add is True."""
device_id = slugify(event.device.id_string.lower())
if device_id not in RFX_DEVICES:
automatic_add = config[ATTR_AUTOMATIC_ADD]
if not automatic_add:
return
if device_id in RFX_DEVICES:
return
_LOGGER.info(
"Automatic add %s rfxtrx device (Class: %s Sub: %s)",
device_id,
event.device.__class__.__name__,
event.device.subtype
)
pkt_id = "".join("{0:02x}".format(x) for x in event.data)
entity_name = "%s : %s" % (device_id, pkt_id)
datas = {ATTR_STATE: False, ATTR_FIREEVENT: False}
signal_repetitions = config[CONF_SIGNAL_REPETITIONS]
new_device = device(entity_name, event, datas,
signal_repetitions)
RFX_DEVICES[device_id] = new_device
return new_device
automatic_add = config[ATTR_AUTOMATIC_ADD]
if not automatic_add:
return
_LOGGER.info(
"Automatic add %s rfxtrx device (Class: %s Sub: %s)",
device_id,
event.device.__class__.__name__,
event.device.subtype
)
pkt_id = "".join("{0:02x}".format(x) for x in event.data)
entity_name = "%s : %s" % (device_id, pkt_id)
datas = {ATTR_STATE: False, ATTR_FIREEVENT: False}
signal_repetitions = config[CONF_SIGNAL_REPETITIONS]
new_device = device(entity_name, event, datas,
signal_repetitions)
RFX_DEVICES[device_id] = new_device
return new_device
def apply_received_command(event):
"""Apply command from rfxtrx."""
device_id = slugify(event.device.id_string.lower())
# Check if entity exists or previously added automatically
if device_id in RFX_DEVICES:
_LOGGER.debug(
"EntityID: %s device_update. Command: %s",
device_id,
event.values['Command']
if device_id not in RFX_DEVICES:
return
_LOGGER.debug(
"EntityID: %s device_update. Command: %s",
device_id,
event.values['Command']
)
if event.values['Command'] == 'On'\
or event.values['Command'] == 'Off':
# Update the rfxtrx device state
is_on = event.values['Command'] == 'On'
RFX_DEVICES[device_id].update_state(is_on)
elif hasattr(RFX_DEVICES[device_id], 'brightness')\
and event.values['Command'] == 'Set level':
_brightness = (event.values['Dim level'] * 255 // 100)
# Update the rfxtrx device state
is_on = _brightness > 0
RFX_DEVICES[device_id].update_state(is_on, _brightness)
# Fire event
if RFX_DEVICES[device_id].should_fire_event:
RFX_DEVICES[device_id].hass.bus.fire(
EVENT_BUTTON_PRESSED, {
ATTR_ENTITY_ID:
RFX_DEVICES[device_id].entity_id,
ATTR_STATE: event.values['Command'].lower()
}
)
if event.values['Command'] == 'On'\
or event.values['Command'] == 'Off':
# Update the rfxtrx device state
is_on = event.values['Command'] == 'On'
# pylint: disable=protected-access
RFX_DEVICES[device_id]._state = is_on
RFX_DEVICES[device_id].update_ha_state()
elif hasattr(RFX_DEVICES[device_id], 'brightness')\
and event.values['Command'] == 'Set level':
# pylint: disable=protected-access
RFX_DEVICES[device_id]._brightness = \
(event.values['Dim level'] * 255 // 100)
# Update the rfxtrx device state
is_on = RFX_DEVICES[device_id]._brightness > 0
RFX_DEVICES[device_id]._state = is_on
RFX_DEVICES[device_id].update_ha_state()
# Fire event
if RFX_DEVICES[device_id].should_fire_event:
RFX_DEVICES[device_id].hass.bus.fire(
EVENT_BUTTON_PRESSED, {
ATTR_ENTITY_ID:
RFX_DEVICES[device_id].entity_id,
ATTR_STATE: event.values['Command'].lower()
}
)
class RfxtrxDevice(Entity):
"""Represents a Rfxtrx device.
@ -233,11 +251,11 @@ class RfxtrxDevice(Entity):
def __init__(self, name, event, datas, signal_repetitions):
"""Initialize the device."""
self.signal_repetitions = signal_repetitions
self._name = name
self._event = event
self._state = datas[ATTR_STATE]
self._should_fire_event = datas[ATTR_FIREEVENT]
self.signal_repetitions = signal_repetitions
self._brightness = 0
@property
@ -269,6 +287,12 @@ class RfxtrxDevice(Entity):
"""Turn the device off."""
self._send_command("turn_off")
def update_state(self, state, brightness=0):
"""Update det state of the device."""
self._state = state
self._brightness = brightness
self.update_ha_state()
def _send_command(self, command, brightness=0):
if not self._event:
return

View File

@ -14,7 +14,7 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.util import slugify
from homeassistant.components.rfxtrx import (
ATTR_AUTOMATIC_ADD, ATTR_PACKETID, ATTR_NAME,
ATTR_AUTOMATIC_ADD, ATTR_NAME,
CONF_DEVICES, ATTR_DATA_TYPE)
DEPENDENCIES = ['rfxtrx']
@ -31,18 +31,27 @@ _LOGGER = logging.getLogger(__name__)
DEVICE_SCHEMA = vol.Schema({
vol.Optional(ATTR_NAME, default=None): cv.string,
vol.Required(ATTR_PACKETID): rfxtrx.validate_packetid,
vol.Optional(ATTR_DATA_TYPE, default=None):
vol.In(list(DATA_TYPES.keys())),
vol.Optional(ATTR_DATA_TYPE, default=[]):
vol.All(cv.ensure_list, [vol.In(DATA_TYPES.keys())]),
})
def _valid_device(value):
def _valid_sensor(value):
"""Validate a dictionary of devices definitions."""
config = OrderedDict()
for key, device in value.items():
# Still accept old configuration
if 'packetid' in device.keys():
print(key, device.keys(), device, config)
msg = 'You are using an outdated configuration of the rfxtrx ' +\
'sensor, {}. Your new config should be:\n{}: \n\t name:{}\n'\
.format(key, device.get('packetid'),
device.get(ATTR_NAME, 'sensor_name'))
_LOGGER.warning(msg)
key = device.get('packetid')
device.pop('packetid')
try:
key = rfxtrx.VALID_SENSOR_DEVICE_ID(key)
key = rfxtrx.validate_packetid(key)
config[key] = DEVICE_SCHEMA(device)
if not config[key][ATTR_NAME]:
config[key][ATTR_NAME] = key
@ -54,7 +63,7 @@ def _valid_device(value):
PLATFORM_SCHEMA = vol.Schema({
vol.Required("platform"): rfxtrx.DOMAIN,
vol.Required(CONF_DEVICES): vol.All(dict, _valid_device),
vol.Required(CONF_DEVICES): vol.All(dict, _valid_sensor),
vol.Optional(ATTR_AUTOMATIC_ADD, default=False): cv.boolean,
}, extra=vol.ALLOW_EXTRA)
@ -64,15 +73,20 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
from RFXtrx import SensorEvent
sensors = []
for device_id, entity_info in config['devices'].items():
for packet_id, entity_info in config['devices'].items():
event = rfxtrx.get_rfx_object(packet_id)
device_id = "sensor_" + slugify(event.device.id_string.lower())
if device_id in rfxtrx.RFX_DEVICES:
continue
_LOGGER.info("Add %s rfxtrx.sensor", entity_info[ATTR_NAME])
event = rfxtrx.get_rfx_object(entity_info[ATTR_PACKETID])
new_sensor = RfxtrxSensor(event, entity_info[ATTR_NAME],
entity_info[ATTR_DATA_TYPE])
rfxtrx.RFX_DEVICES[slugify(device_id)] = new_sensor
sensors.append(new_sensor)
sub_sensors = {}
for _data_type in cv.ensure_list(entity_info[ATTR_DATA_TYPE]):
new_sensor = RfxtrxSensor(event, entity_info[ATTR_NAME],
_data_type)
sensors.append(new_sensor)
sub_sensors[_data_type] = new_sensor
rfxtrx.RFX_DEVICES[slugify(device_id)] = sub_sensors
add_devices_callback(sensors)
@ -84,13 +98,9 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
device_id = "sensor_" + slugify(event.device.id_string.lower())
if device_id in rfxtrx.RFX_DEVICES:
rfxtrx.RFX_DEVICES[device_id].event = event
k = 2
_device_id = device_id + "_" + str(k)
while _device_id in rfxtrx.RFX_DEVICES:
rfxtrx.RFX_DEVICES[_device_id].event = event
k = k + 1
_device_id = device_id + "_" + str(k)
sensors = rfxtrx.RFX_DEVICES[device_id]
for key in sensors:
sensors[key].event = event
return
# Add entity if not exist and the automatic_add is True
@ -103,7 +113,9 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
pkt_id)
new_sensor = RfxtrxSensor(event, entity_name)
rfxtrx.RFX_DEVICES[device_id] = new_sensor
sub_sensors = {}
sub_sensors[new_sensor.data_type] = new_sensor
rfxtrx.RFX_DEVICES[device_id] = sub_sensors
add_devices_callback([new_sensor])
if sensor_update not in rfxtrx.RECEIVED_EVT_SUBSCRIBERS:
@ -117,16 +129,16 @@ class RfxtrxSensor(Entity):
"""Initialize the sensor."""
self.event = event
self._unit_of_measurement = None
self._data_type = None
self.data_type = None
self._name = name
if data_type:
self._data_type = data_type
self.data_type = data_type
self._unit_of_measurement = DATA_TYPES[data_type]
return
for data_type in DATA_TYPES:
if data_type in self.event.values:
self._unit_of_measurement = DATA_TYPES[data_type]
self._data_type = data_type
self.data_type = data_type
break
def __str__(self):
@ -136,8 +148,8 @@ class RfxtrxSensor(Entity):
@property
def state(self):
"""Return the state of the sensor."""
if self._data_type:
return self.event.values[self._data_type]
if self.data_type:
return self.event.values[self.data_type]
return None
@property