From 16a58bd1cf0087dc793f25bd48d00b50d3b0459c Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Fri, 31 Aug 2018 10:17:11 +0200 Subject: [PATCH] Fix LIFX effects (#16309) --- CODEOWNERS | 3 + homeassistant/components/light/lifx.py | 125 ++++++++++++------------- 2 files changed, 64 insertions(+), 64 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index c756cb383d4..b86e09a6b72 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -52,6 +52,8 @@ homeassistant/components/cover/template.py @PhracturedBlue homeassistant/components/device_tracker/automatic.py @armills homeassistant/components/device_tracker/tile.py @bachya homeassistant/components/history_graph.py @andrey-git +homeassistant/components/light/lifx.py @amelchio +homeassistant/components/light/lifx_legacy.py @amelchio homeassistant/components/light/tplink.py @rytilahti homeassistant/components/light/yeelight.py @rytilahti homeassistant/components/lock/nello.py @pschmitt @@ -65,6 +67,7 @@ homeassistant/components/media_player/sonos.py @amelchio homeassistant/components/media_player/xiaomi_tv.py @fattdev homeassistant/components/media_player/yamaha_musiccast.py @jalmeroth homeassistant/components/plant.py @ChristianKuehnel +homeassistant/components/scene/lifx_cloud.py @amelchio homeassistant/components/sensor/airvisual.py @bachya homeassistant/components/sensor/filter.py @dgomes homeassistant/components/sensor/gearbest.py @HerrHofrat diff --git a/homeassistant/components/light/lifx.py b/homeassistant/components/light/lifx.py index cf5d6fef704..bea39354e1b 100644 --- a/homeassistant/components/light/lifx.py +++ b/homeassistant/components/light/lifx.py @@ -167,9 +167,9 @@ async def async_setup_platform(hass, return True -def lifx_features(device): - """Return a feature map for this device, or a default map if unknown.""" - return aiolifx().products.features_map.get(device.product) or \ +def lifx_features(bulb): + """Return a feature map for this bulb, or a default map if unknown.""" + return aiolifx().products.features_map.get(bulb.product) or \ aiolifx().products.features_map.get(1) @@ -256,7 +256,7 @@ class LIFXManager: async def start_effect(self, entities, service, **kwargs): """Start a light effect on entities.""" - devices = [light.device for light in entities] + bulbs = [light.bulb for light in entities] if service == SERVICE_EFFECT_PULSE: effect = aiolifx_effects().EffectPulse( @@ -266,7 +266,7 @@ class LIFXManager: mode=kwargs.get(ATTR_MODE), hsbk=find_hsbk(**kwargs), ) - await self.effects_conductor.start(effect, devices) + await self.effects_conductor.start(effect, bulbs) elif service == SERVICE_EFFECT_COLORLOOP: preprocess_turn_on_alternatives(kwargs) @@ -282,12 +282,12 @@ class LIFXManager: transition=kwargs.get(ATTR_TRANSITION), brightness=brightness, ) - await self.effects_conductor.start(effect, devices) + await self.effects_conductor.start(effect, bulbs) elif service == SERVICE_EFFECT_STOP: - await self.effects_conductor.stop(devices) + await self.effects_conductor.stop(bulbs) def service_to_entities(self, service): - """Return the known devices that a service call mentions.""" + """Return the known entities that a service call mentions.""" entity_ids = extract_entity_ids(self.hass, service) if entity_ids: entities = [entity for entity in self.entities.values() @@ -298,50 +298,50 @@ class LIFXManager: return entities @callback - def register(self, device): + def register(self, bulb): """Handle aiolifx detected bulb.""" - self.hass.async_add_job(self.register_new_device(device)) + self.hass.async_add_job(self.register_new_bulb(bulb)) - async def register_new_device(self, device): + async def register_new_bulb(self, bulb): """Handle newly detected bulb.""" - if device.mac_addr in self.entities: - entity = self.entities[device.mac_addr] + if bulb.mac_addr in self.entities: + entity = self.entities[bulb.mac_addr] entity.registered = True _LOGGER.debug("%s register AGAIN", entity.who) await entity.update_hass() else: - _LOGGER.debug("%s register NEW", device.ip_addr) + _LOGGER.debug("%s register NEW", bulb.ip_addr) # Read initial state ack = AwaitAioLIFX().wait - color_resp = await ack(device.get_color) + color_resp = await ack(bulb.get_color) if color_resp: - version_resp = await ack(device.get_version) + version_resp = await ack(bulb.get_version) if color_resp is None or version_resp is None: - _LOGGER.error("Failed to initialize %s", device.ip_addr) - device.registered = False + _LOGGER.error("Failed to initialize %s", bulb.ip_addr) + bulb.registered = False else: - device.timeout = MESSAGE_TIMEOUT - device.retry_count = MESSAGE_RETRIES - device.unregister_timeout = UNAVAILABLE_GRACE + bulb.timeout = MESSAGE_TIMEOUT + bulb.retry_count = MESSAGE_RETRIES + bulb.unregister_timeout = UNAVAILABLE_GRACE - if lifx_features(device)["multizone"]: - entity = LIFXStrip(device, self.effects_conductor) - elif lifx_features(device)["color"]: - entity = LIFXColor(device, self.effects_conductor) + if lifx_features(bulb)["multizone"]: + entity = LIFXStrip(bulb, self.effects_conductor) + elif lifx_features(bulb)["color"]: + entity = LIFXColor(bulb, self.effects_conductor) else: - entity = LIFXWhite(device, self.effects_conductor) + entity = LIFXWhite(bulb, self.effects_conductor) _LOGGER.debug("%s register READY", entity.who) - self.entities[device.mac_addr] = entity + self.entities[bulb.mac_addr] = entity self.async_add_entities([entity], True) @callback - def unregister(self, device): + def unregister(self, bulb): """Handle aiolifx disappearing bulbs.""" - if device.mac_addr in self.entities: - entity = self.entities[device.mac_addr] + if bulb.mac_addr in self.entities: + entity = self.entities[bulb.mac_addr] _LOGGER.debug("%s unregister", entity.who) entity.registered = False self.hass.async_add_job(entity.async_update_ha_state()) @@ -352,20 +352,17 @@ class AwaitAioLIFX: def __init__(self): """Initialize the wrapper.""" - self.device = None self.message = None self.event = asyncio.Event() @callback - def callback(self, device, message): + def callback(self, bulb, message): """Handle responses.""" - self.device = device self.message = message self.event.set() async def wait(self, method): """Call an aiolifx method and wait for its response.""" - self.device = None self.message = None self.event.clear() method(callb=self.callback) @@ -387,9 +384,9 @@ def convert_16_to_8(value): class LIFXLight(Light): """Representation of a LIFX light.""" - def __init__(self, device, effects_conductor): + def __init__(self, bulb, effects_conductor): """Initialize the light.""" - self.light = device + self.bulb = bulb self.effects_conductor = effects_conductor self.registered = True self.postponed_update = None @@ -397,34 +394,34 @@ class LIFXLight(Light): @property def available(self): - """Return the availability of the device.""" + """Return the availability of the bulb.""" return self.registered @property def unique_id(self): """Return a unique ID.""" - return self.light.mac_addr + return self.bulb.mac_addr @property def name(self): - """Return the name of the device.""" - return self.light.label + """Return the name of the bulb.""" + return self.bulb.label @property def who(self): - """Return a string identifying the device.""" - return "%s (%s)" % (self.light.ip_addr, self.name) + """Return a string identifying the bulb.""" + return "%s (%s)" % (self.bulb.ip_addr, self.name) @property def min_mireds(self): """Return the coldest color_temp that this light supports.""" - kelvin = lifx_features(self.light)['max_kelvin'] + kelvin = lifx_features(self.bulb)['max_kelvin'] return math.floor(color_util.color_temperature_kelvin_to_mired(kelvin)) @property def max_mireds(self): """Return the warmest color_temp that this light supports.""" - kelvin = lifx_features(self.light)['min_kelvin'] + kelvin = lifx_features(self.bulb)['min_kelvin'] return math.ceil(color_util.color_temperature_kelvin_to_mired(kelvin)) @property @@ -432,8 +429,8 @@ class LIFXLight(Light): """Flag supported features.""" support = SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION | SUPPORT_EFFECT - device_features = lifx_features(self.light) - if device_features['min_kelvin'] != device_features['max_kelvin']: + bulb_features = lifx_features(self.bulb) + if bulb_features['min_kelvin'] != bulb_features['max_kelvin']: support |= SUPPORT_COLOR_TEMP return support @@ -441,25 +438,25 @@ class LIFXLight(Light): @property def brightness(self): """Return the brightness of this light between 0..255.""" - return convert_16_to_8(self.light.color[2]) + return convert_16_to_8(self.bulb.color[2]) @property def color_temp(self): """Return the color temperature.""" - _, sat, _, kelvin = self.light.color + _, sat, _, kelvin = self.bulb.color if sat: return None return color_util.color_temperature_kelvin_to_mired(kelvin) @property def is_on(self): - """Return true if device is on.""" - return self.light.power_level != 0 + """Return true if light is on.""" + return self.bulb.power_level != 0 @property def effect(self): """Return the name of the currently running effect.""" - effect = self.effects_conductor.effect(self.light) + effect = self.effects_conductor.effect(self.bulb) if effect: return 'lifx_effect_' + effect.name return None @@ -485,19 +482,19 @@ class LIFXLight(Light): util.dt.utcnow() + timedelta(milliseconds=when)) async def async_turn_on(self, **kwargs): - """Turn the device on.""" + """Turn the light on.""" kwargs[ATTR_POWER] = True self.hass.async_add_job(self.set_state(**kwargs)) async def async_turn_off(self, **kwargs): - """Turn the device off.""" + """Turn the light off.""" kwargs[ATTR_POWER] = False self.hass.async_add_job(self.set_state(**kwargs)) async def set_state(self, **kwargs): """Set a color on the light and turn it on/off.""" async with self.lock: - bulb = self.light + bulb = self.bulb await self.effects_conductor.stop([bulb]) @@ -544,13 +541,13 @@ class LIFXLight(Light): await self.update_during_transition(fade) async def set_power(self, ack, pwr, duration=0): - """Send a power change to the device.""" - await ack(partial(self.light.set_power, pwr, duration=duration)) + """Send a power change to the bulb.""" + await ack(partial(self.bulb.set_power, pwr, duration=duration)) async def set_color(self, ack, hsbk, kwargs, duration=0): - """Send a color change to the device.""" - hsbk = merge_hsbk(self.light.color, hsbk) - await ack(partial(self.light.set_color, hsbk, duration=duration)) + """Send a color change to the bulb.""" + hsbk = merge_hsbk(self.bulb.color, hsbk) + await ack(partial(self.bulb.set_color, hsbk, duration=duration)) async def default_effect(self, **kwargs): """Start an effect with default parameters.""" @@ -563,7 +560,7 @@ class LIFXLight(Light): async def async_update(self): """Update bulb status.""" if self.available and not self.lock.locked(): - await AwaitAioLIFX().wait(self.light.get_color) + await AwaitAioLIFX().wait(self.bulb.get_color) class LIFXWhite(LIFXLight): @@ -600,7 +597,7 @@ class LIFXColor(LIFXLight): @property def hs_color(self): """Return the hs value.""" - hue, sat, _, _ = self.light.color + hue, sat, _, _ = self.bulb.color hue = hue / 65535 * 360 sat = sat / 65535 * 100 return (hue, sat) if sat else None @@ -610,8 +607,8 @@ class LIFXStrip(LIFXColor): """Representation of a LIFX light strip with multiple zones.""" async def set_color(self, ack, hsbk, kwargs, duration=0): - """Send a color change to the device.""" - bulb = self.light + """Send a color change to the bulb.""" + bulb = self.bulb num_zones = len(bulb.color_zones) zones = kwargs.get(ATTR_ZONES) @@ -659,7 +656,7 @@ class LIFXStrip(LIFXColor): while self.available and zone < top: # Each get_color_zones can update 8 zones at once resp = await AwaitAioLIFX().wait(partial( - self.light.get_color_zones, + self.bulb.get_color_zones, start_index=zone)) if resp: zone += 8