From 7f9cc104476025e01d6b818ff3687e0ed64cd4cc Mon Sep 17 00:00:00 2001 From: pbalogh77 Date: Fri, 14 Dec 2018 13:35:12 +0100 Subject: [PATCH] Device config for Fibaro hub integration (#19171) --- .../components/binary_sensor/fibaro.py | 6 ++ homeassistant/components/fibaro.py | 56 +++++++++++++------ homeassistant/components/light/fibaro.py | 41 ++++++++++---- 3 files changed, 77 insertions(+), 26 deletions(-) diff --git a/homeassistant/components/binary_sensor/fibaro.py b/homeassistant/components/binary_sensor/fibaro.py index ae8029e13f8..8af2bde10ad 100644 --- a/homeassistant/components/binary_sensor/fibaro.py +++ b/homeassistant/components/binary_sensor/fibaro.py @@ -10,6 +10,7 @@ from homeassistant.components.binary_sensor import ( BinarySensorDevice, ENTITY_ID_FORMAT) from homeassistant.components.fibaro import ( FIBARO_CONTROLLER, FIBARO_DEVICES, FibaroDevice) +from homeassistant.const import (CONF_DEVICE_CLASS, CONF_ICON) DEPENDENCIES = ['fibaro'] @@ -45,6 +46,7 @@ class FibaroBinarySensor(FibaroDevice, BinarySensorDevice): super().__init__(fibaro_device, controller) self.entity_id = ENTITY_ID_FORMAT.format(self.ha_id) stype = None + devconf = fibaro_device.device_config if fibaro_device.type in SENSOR_TYPES: stype = fibaro_device.type elif fibaro_device.baseType in SENSOR_TYPES: @@ -55,6 +57,10 @@ class FibaroBinarySensor(FibaroDevice, BinarySensorDevice): else: self._device_class = None self._icon = None + # device_config overrides: + self._device_class = devconf.get(CONF_DEVICE_CLASS, + self._device_class) + self._icon = devconf.get(CONF_ICON, self._icon) @property def icon(self): diff --git a/homeassistant/components/fibaro.py b/homeassistant/components/fibaro.py index 5813b194890..d506f6c471d 100644 --- a/homeassistant/components/fibaro.py +++ b/homeassistant/components/fibaro.py @@ -10,13 +10,14 @@ from collections import defaultdict from typing import Optional import voluptuous as vol -from homeassistant.const import (ATTR_ARMED, ATTR_BATTERY_LEVEL, - CONF_PASSWORD, CONF_URL, CONF_USERNAME, - EVENT_HOMEASSISTANT_STOP) -import homeassistant.helpers.config_validation as cv -from homeassistant.util import convert, slugify +from homeassistant.const import ( + ATTR_ARMED, ATTR_BATTERY_LEVEL, CONF_DEVICE_CLASS, + CONF_EXCLUDE, CONF_ICON, CONF_PASSWORD, CONF_URL, CONF_USERNAME, + CONF_WHITE_VALUE, EVENT_HOMEASSISTANT_STOP) from homeassistant.helpers import discovery +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity +from homeassistant.util import convert, slugify REQUIREMENTS = ['fiblary3==0.1.7'] @@ -27,6 +28,10 @@ FIBARO_CONTROLLER = 'fibaro_controller' ATTR_CURRENT_POWER_W = "current_power_w" ATTR_CURRENT_ENERGY_KWH = "current_energy_kwh" CONF_PLUGINS = "plugins" +CONF_DIMMING = "dimming" +CONF_COLOR = "color" +CONF_RESET_COLOR = "reset_color" +CONF_DEVICE_CONFIG = "device_config" FIBARO_COMPONENTS = ['binary_sensor', 'cover', 'light', 'scene', 'sensor', 'switch'] @@ -49,12 +54,26 @@ FIBARO_TYPEMAP = { 'com.fibaro.securitySensor': 'binary_sensor' } +DEVICE_CONFIG_SCHEMA_ENTRY = vol.Schema({ + vol.Optional(CONF_DIMMING): cv.boolean, + vol.Optional(CONF_COLOR): cv.boolean, + vol.Optional(CONF_WHITE_VALUE): cv.boolean, + vol.Optional(CONF_RESET_COLOR): cv.boolean, + vol.Optional(CONF_DEVICE_CLASS): cv.string, + vol.Optional(CONF_ICON): cv.string, +}) + +FIBARO_ID_LIST_SCHEMA = vol.Schema([cv.string]) + CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ vol.Required(CONF_PASSWORD): cv.string, vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_URL): cv.url, vol.Optional(CONF_PLUGINS, default=False): cv.boolean, + vol.Optional(CONF_EXCLUDE, default=[]): FIBARO_ID_LIST_SCHEMA, + vol.Optional(CONF_DEVICE_CONFIG, default={}): + vol.Schema({cv.string: DEVICE_CONFIG_SCHEMA_ENTRY}) }) }, extra=vol.ALLOW_EXTRA) @@ -62,19 +81,20 @@ CONFIG_SCHEMA = vol.Schema({ class FibaroController(): """Initiate Fibaro Controller Class.""" - _room_map = None # Dict for mapping roomId to room object - _device_map = None # Dict for mapping deviceId to device object - fibaro_devices = None # List of devices by type - _callbacks = {} # Dict of update value callbacks by deviceId - _client = None # Fiblary's Client object for communication - _state_handler = None # Fiblary's StateHandler object - _import_plugins = None # Whether to import devices from plugins - - def __init__(self, username, password, url, import_plugins): + def __init__(self, username, password, url, import_plugins, config): """Initialize the Fibaro controller.""" from fiblary3.client.v4.client import Client as FibaroClient self._client = FibaroClient(url, username, password) self._scene_map = None + # Whether to import devices from plugins + self._import_plugins = import_plugins + self._device_config = config[CONF_DEVICE_CONFIG] + self._room_map = None # Mapping roomId to room object + self._device_map = None # Mapping deviceId to device object + self.fibaro_devices = None # List of devices by type + self._callbacks = {} # Update value callbacks by deviceId + self._state_handler = None # Fiblary's StateHandler object + self._excluded_devices = config.get(CONF_EXCLUDE, []) self.hub_serial = None # Unique serial number of the hub def connect(self): @@ -210,8 +230,11 @@ class FibaroController(): slugify(room_name), slugify(device.name), device.id) if device.enabled and \ ('isPlugin' not in device or - (not device.isPlugin or self._import_plugins)): + (not device.isPlugin or self._import_plugins)) and \ + device.ha_id not in self._excluded_devices: device.mapped_type = self._map_device_to_type(device) + device.device_config = \ + self._device_config.get(device.ha_id, {}) else: device.mapped_type = None if device.mapped_type: @@ -233,7 +256,8 @@ def setup(hass, config): FibaroController(config[DOMAIN][CONF_USERNAME], config[DOMAIN][CONF_PASSWORD], config[DOMAIN][CONF_URL], - config[DOMAIN][CONF_PLUGINS]) + config[DOMAIN][CONF_PLUGINS], + config[DOMAIN]) def stop_fibaro(event): """Stop Fibaro Thread.""" diff --git a/homeassistant/components/light/fibaro.py b/homeassistant/components/light/fibaro.py index 636e4376ae2..6f2842524a2 100644 --- a/homeassistant/components/light/fibaro.py +++ b/homeassistant/components/light/fibaro.py @@ -9,12 +9,15 @@ import logging import asyncio from functools import partial +from homeassistant.const import ( + CONF_WHITE_VALUE) +from homeassistant.components.fibaro import ( + FIBARO_CONTROLLER, FIBARO_DEVICES, FibaroDevice, + CONF_DIMMING, CONF_COLOR, CONF_RESET_COLOR) from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_WHITE_VALUE, ENTITY_ID_FORMAT, SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_WHITE_VALUE, Light) import homeassistant.util.color as color_util -from homeassistant.components.fibaro import ( - FIBARO_CONTROLLER, FIBARO_DEVICES, FibaroDevice) _LOGGER = logging.getLogger(__name__) @@ -56,20 +59,28 @@ class FibaroLight(FibaroDevice, Light): def __init__(self, fibaro_device, controller): """Initialize the light.""" - self._supported_flags = 0 - self._last_brightness = 0 - self._color = (0, 0) self._brightness = None + self._color = (0, 0) + self._last_brightness = 0 + self._supported_flags = 0 + self._update_lock = asyncio.Lock() self._white = 0 - self._update_lock = asyncio.Lock() - if 'levelChange' in fibaro_device.interfaces: + devconf = fibaro_device.device_config + self._reset_color = devconf.get(CONF_RESET_COLOR, False) + supports_color = 'color' in fibaro_device.properties and \ + 'setColor' in fibaro_device.actions + supports_dimming = 'levelChange' in fibaro_device.interfaces + supports_white_v = 'setW' in fibaro_device.actions + + # Configuration can overrride default capability detection + if devconf.get(CONF_DIMMING, supports_dimming): self._supported_flags |= SUPPORT_BRIGHTNESS - if 'color' in fibaro_device.properties and \ - 'setColor' in fibaro_device.actions: + if devconf.get(CONF_COLOR, supports_color): self._supported_flags |= SUPPORT_COLOR - if 'setW' in fibaro_device.actions: + if devconf.get(CONF_WHITE_VALUE, supports_white_v): self._supported_flags |= SUPPORT_WHITE_VALUE + super().__init__(fibaro_device, controller) self.entity_id = ENTITY_ID_FORMAT.format(self.ha_id) @@ -117,6 +128,12 @@ class FibaroLight(FibaroDevice, Light): self._brightness = scaleto100(target_brightness) if self._supported_flags & SUPPORT_COLOR: + if self._reset_color and \ + kwargs.get(ATTR_WHITE_VALUE) is None and \ + kwargs.get(ATTR_HS_COLOR) is None and \ + kwargs.get(ATTR_BRIGHTNESS) is None: + self._color = (100, 0) + # Update based on parameters self._white = kwargs.get(ATTR_WHITE_VALUE, self._white) self._color = kwargs.get(ATTR_HS_COLOR, self._color) @@ -131,6 +148,10 @@ class FibaroLight(FibaroDevice, Light): self.set_level(int(self._brightness)) return + if self._reset_color: + bri255 = scaleto255(self._brightness) + self.call_set_color(bri255, bri255, bri255, bri255) + if self._supported_flags & SUPPORT_BRIGHTNESS: self.set_level(int(self._brightness)) return