From ff0788324c73ebecb57d67960c05870c93e680bd Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 4 Jan 2017 13:31:31 -0800 Subject: [PATCH] Add support for Tikteck Bluetooth bulbs (#4843) * Add support for Tikteck Bluetooth bulbs Adds support for the Tikteck RGBW BLE bulbs. These don't provide "true" RGBW support - at a certain point in RGB space, the white LEDs turn on. Each bulb has a specific key that needs to be extracted from the Android app. * Update tikteck.py --- .coveragerc | 1 + homeassistant/components/light/tikteck.py | 134 ++++++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 138 insertions(+) create mode 100644 homeassistant/components/light/tikteck.py diff --git a/.coveragerc b/.coveragerc index 38bea01387a00..d3bc2bf18e941 100644 --- a/.coveragerc +++ b/.coveragerc @@ -184,6 +184,7 @@ omit = homeassistant/components/light/lifx.py homeassistant/components/light/limitlessled.py homeassistant/components/light/osramlightify.py + homeassistant/components/light/tikteck.py homeassistant/components/light/x10.py homeassistant/components/light/yeelight.py homeassistant/components/lirc.py diff --git a/homeassistant/components/light/tikteck.py b/homeassistant/components/light/tikteck.py new file mode 100644 index 0000000000000..7b0222107a2ce --- /dev/null +++ b/homeassistant/components/light/tikteck.py @@ -0,0 +1,134 @@ +""" +Support for Tikteck lights. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/light.tikteck/ +""" +import logging + +import voluptuous as vol + +from homeassistant.const import CONF_DEVICES, CONF_NAME, CONF_PASSWORD +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, + Light, PLATFORM_SCHEMA) +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['tikteck==0.4'] + +_LOGGER = logging.getLogger(__name__) + +SUPPORT_TIKTECK_LED = (SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR) + +DEVICE_SCHEMA = vol.Schema({ + vol.Optional(CONF_NAME): cv.string, + vol.Required(CONF_PASSWORD): cv.string, +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_DEVICES, default={}): {cv.string: DEVICE_SCHEMA}, +}) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the Tikteck platform.""" + lights = [] + for address, device_config in config[CONF_DEVICES].items(): + device = {} + device['name'] = device_config[CONF_NAME] + device['password'] = device_config[CONF_PASSWORD] + device['address'] = address + light = TikteckLight(device) + if light.is_valid: + lights.append(light) + + add_devices(lights) + + +class TikteckLight(Light): + """Representation of a Tikteck light.""" + + def __init__(self, device): + """Initialize the light.""" + import tikteck + + self._name = device['name'] + self._address = device['address'] + self._password = device['password'] + self._brightness = 255 + self._rgb = [255, 255, 255] + self._state = False + self.is_valid = True + self._bulb = tikteck.tikteck(self._address, "Smart Light", + self._password) + if self._bulb.connect() is False: + self.is_valid = False + _LOGGER.error( + "Failed to connect to bulb %s, %s", self._address, self._name) + + @property + def unique_id(self): + """Return the ID of this light.""" + return "{}.{}".format(self.__class__, self._address) + + @property + def name(self): + """Return the name of the device if any.""" + return self._name + + @property + def is_on(self): + """Return true if device is on.""" + return self._state + + @property + def brightness(self): + """Return the brightness of this light between 0..255.""" + return self._brightness + + @property + def rgb_color(self): + """Return the color property.""" + return self._rgb + + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_TIKTECK_LED + + @property + def should_poll(self): + """Don't poll.""" + return False + + @property + def assumed_state(self): + """We can't read the actual state, so assume it matches.""" + return True + + def set_state(self, red, green, blue, brightness): + """Set the bulb state.""" + return self._bulb.set_state(red, green, blue, brightness) + + def turn_on(self, **kwargs): + """Turn the specified light on.""" + self._state = True + + rgb = kwargs.get(ATTR_RGB_COLOR) + brightness = kwargs.get(ATTR_BRIGHTNESS) + + if rgb is not None: + self._rgb = rgb + if brightness is not None: + self._brightness = brightness + + self.set_state(self._rgb[0], self._rgb[1], self._rgb[2], + self.brightness) + self.schedule_update_ha_state() + + def turn_off(self, **kwargs): + """Turn the specified light off.""" + self._state = False + self.set_state(0, 0, 0, 0) + self.schedule_update_ha_state() diff --git a/requirements_all.txt b/requirements_all.txt index 709f7ccd8ec8c..fed2d1296a02e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -583,6 +583,9 @@ temperusb==1.5.1 # homeassistant.components.thingspeak thingspeak==0.4.0 +# homeassistant.components.light.tikteck +tikteck==0.4 + # homeassistant.components.sensor.transmission # homeassistant.components.switch.transmission transmissionrpc==0.11