diff --git a/.coveragerc b/.coveragerc index b62c7202abd..212affd29b5 100644 --- a/.coveragerc +++ b/.coveragerc @@ -265,6 +265,9 @@ omit = homeassistant/components/openuv/__init__.py homeassistant/components/*/openuv.py + homeassistant/components/plum_lightpad.py + homeassistant/components/*/plum_lightpad.py + homeassistant/components/pilight.py homeassistant/components/*/pilight.py diff --git a/homeassistant/components/light/plum_lightpad.py b/homeassistant/components/light/plum_lightpad.py new file mode 100644 index 00000000000..fa15c842deb --- /dev/null +++ b/homeassistant/components/light/plum_lightpad.py @@ -0,0 +1,185 @@ +""" +Support for Plum Lightpad switches. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/light.plum_lightpad/ +""" +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR, Light) +from homeassistant.components.plum_lightpad import PLUM_DATA +import homeassistant.util.color as color_util + +DEPENDENCIES = ['plum_lightpad'] + + +async def async_setup_platform(hass, config, async_add_entities, + discovery_info=None): + """Initialize the Plum Lightpad Light and GlowRing.""" + if discovery_info is None: + return + + plum = hass.data[PLUM_DATA] + + entities = [] + + if 'lpid' in discovery_info: + lightpad = plum.get_lightpad(discovery_info['lpid']) + entities.append(GlowRing(lightpad=lightpad)) + + if 'llid' in discovery_info: + logical_load = plum.get_load(discovery_info['llid']) + entities.append(PlumLight(load=logical_load)) + + if entities: + async_add_entities(entities) + + +class PlumLight(Light): + """Represenation of a Plum Lightpad dimmer.""" + + def __init__(self, load): + """Initialize the light.""" + self._load = load + self._brightness = load.level + + async def async_added_to_hass(self): + """Subscribe to dimmerchange events.""" + self._load.add_event_listener('dimmerchange', self.dimmerchange) + + def dimmerchange(self, event): + """Change event handler updating the brightness.""" + self._brightness = event['level'] + self.schedule_update_ha_state() + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def name(self): + """Return the name of the switch if any.""" + return self._load.name + + @property + def brightness(self) -> int: + """Return the brightness of this switch between 0..255.""" + return self._brightness + + @property + def is_on(self) -> bool: + """Return true if light is on.""" + return self._brightness > 0 + + @property + def supported_features(self): + """Flag supported features.""" + if self._load.dimmable: + return SUPPORT_BRIGHTNESS + return None + + async def async_turn_on(self, **kwargs): + """Turn the light on.""" + if ATTR_BRIGHTNESS in kwargs: + await self._load.turn_on(kwargs[ATTR_BRIGHTNESS]) + else: + await self._load.turn_on() + + async def async_turn_off(self, **kwargs): + """Turn the light off.""" + await self._load.turn_off() + + +class GlowRing(Light): + """Represenation of a Plum Lightpad dimmer glow ring.""" + + def __init__(self, lightpad): + """Initialize the light.""" + self._lightpad = lightpad + self._name = '{} Glow Ring'.format(lightpad.friendly_name) + + self._state = lightpad.glow_enabled + self._brightness = lightpad.glow_intensity * 255.0 + + self._red = lightpad.glow_color['red'] + self._green = lightpad.glow_color['green'] + self._blue = lightpad.glow_color['blue'] + + async def async_added_to_hass(self): + """Subscribe to configchange events.""" + self._lightpad.add_event_listener('configchange', + self.configchange_event) + + def configchange_event(self, event): + """Handle Configuration change event.""" + config = event['changes'] + + self._state = config['glowEnabled'] + self._brightness = config['glowIntensity'] * 255.0 + + self._red = config['glowColor']['red'] + self._green = config['glowColor']['green'] + self._blue = config['glowColor']['blue'] + + self.schedule_update_ha_state() + + @property + def hs_color(self): + """Return the hue and saturation color value [float, float].""" + return color_util.color_RGB_to_hs(self._red, self._green, self._blue) + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def name(self): + """Return the name of the switch if any.""" + return self._name + + @property + def brightness(self) -> int: + """Return the brightness of this switch between 0..255.""" + return self._brightness + + @property + def glow_intensity(self): + """Brightness in float form.""" + return self._brightness / 255.0 + + @property + def is_on(self) -> bool: + """Return true if light is on.""" + return self._state + + @property + def icon(self): + """Return the crop-portait icon representing the glow ring.""" + return 'mdi:crop-portrait' + + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_BRIGHTNESS | SUPPORT_COLOR + + async def async_turn_on(self, **kwargs): + """Turn the light on.""" + if ATTR_BRIGHTNESS in kwargs: + await self._lightpad.set_config( + {"glowIntensity": kwargs[ATTR_BRIGHTNESS]}) + elif ATTR_HS_COLOR in kwargs: + hs_color = kwargs[ATTR_HS_COLOR] + red, green, blue = color_util.color_hs_to_RGB(*hs_color) + await self._lightpad.set_glow_color(red, green, blue, 0) + else: + await self._lightpad.set_config({"glowEnabled": True}) + + async def async_turn_off(self, **kwargs): + """Turn the light off.""" + if ATTR_BRIGHTNESS in kwargs: + await self._lightpad.set_config( + {"glowIntensity": kwargs[ATTR_BRIGHTNESS]}) + else: + await self._lightpad.set_config( + {"glowEnabled": False}) diff --git a/homeassistant/components/plum_lightpad.py b/homeassistant/components/plum_lightpad.py new file mode 100644 index 00000000000..979f257f25f --- /dev/null +++ b/homeassistant/components/plum_lightpad.py @@ -0,0 +1,76 @@ +""" +Support for Plum Lightpad switches. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/plum_lightpad +""" +import asyncio +import logging + +import voluptuous as vol + +from homeassistant.const import ( + CONF_PASSWORD, CONF_USERNAME, EVENT_HOMEASSISTANT_STOP) +from homeassistant.helpers import discovery +from homeassistant.helpers.aiohttp_client import async_get_clientsession +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['plumlightpad==0.0.11'] + +_LOGGER = logging.getLogger(__name__) + +DOMAIN = 'plum_lightpad' + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_USERNAME): cv.string, + vol.Required(CONF_PASSWORD): cv.string, + }), +}, extra=vol.ALLOW_EXTRA) + +PLUM_DATA = 'plum' + + +async def async_setup(hass, config): + """Plum Lightpad Platform initialization.""" + from plumlightpad import Plum + + conf = config[DOMAIN] + plum = Plum(conf[CONF_USERNAME], conf[CONF_PASSWORD]) + + hass.data[PLUM_DATA] = plum + + def cleanup(event): + """Clean up resources.""" + plum.cleanup() + + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, cleanup) + + cloud_web_sesison = async_get_clientsession(hass, verify_ssl=True) + await plum.loadCloudData(cloud_web_sesison) + + async def new_load(device): + """Load light and sensor platforms when LogicalLoad is detected.""" + await asyncio.wait([ + hass.async_create_task( + discovery.async_load_platform( + hass, 'light', DOMAIN, + discovered=device, hass_config=conf)) + ]) + + async def new_lightpad(device): + """Load light and binary sensor platforms when Lightpad detected.""" + await asyncio.wait([ + hass.async_create_task( + discovery.async_load_platform( + hass, 'light', DOMAIN, + discovered=device, hass_config=conf)) + ]) + + device_web_session = async_get_clientsession(hass, verify_ssl=False) + hass.async_create_task( + plum.discover(hass.loop, + loadListener=new_load, lightpadListener=new_lightpad, + websession=device_web_session)) + + return True diff --git a/requirements_all.txt b/requirements_all.txt index ba282603cd0..41a8025fee1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -767,6 +767,9 @@ pizzapi==0.0.3 # homeassistant.components.sensor.plex plexapi==3.0.6 +# homeassistant.components.plum_lightpad +plumlightpad==0.0.11 + # homeassistant.components.sensor.mhz19 # homeassistant.components.sensor.serial_pm pmsensor==0.4