Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use asyncio Lock for fibaro light #18622

Merged
merged 4 commits into from
Nov 26, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 84 additions & 66 deletions homeassistant/components/light/fibaro.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"""

import logging
import threading
import asyncio
from functools import partial

from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_HS_COLOR, ATTR_WHITE_VALUE, ENTITY_ID_FORMAT,
Expand Down Expand Up @@ -37,12 +38,15 @@ def scaleto100(value):
return max(0, min(100, ((value * 100.4) / 255.0)))


def setup_platform(hass, config, add_entities, discovery_info=None):
async def async_setup_platform(hass,
config,
async_add_entities,
discovery_info=None):
"""Perform the setup for Fibaro controller devices."""
if discovery_info is None:
return

add_entities(
async_add_entities(
[FibaroLight(device, hass.data[FIBARO_CONTROLLER])
for device in hass.data[FIBARO_DEVICES]['light']], True)

Expand All @@ -58,7 +62,7 @@ def __init__(self, fibaro_device, controller):
self._brightness = None
self._white = 0

self._update_lock = threading.RLock()
self._update_lock = asyncio.Lock()
if 'levelChange' in fibaro_device.interfaces:
self._supported_flags |= SUPPORT_BRIGHTNESS
if 'color' in fibaro_device.properties:
Expand Down Expand Up @@ -88,78 +92,92 @@ def supported_features(self):
"""Flag supported features."""
return self._supported_flags

def turn_on(self, **kwargs):
async def async_turn_on(self, **kwargs):
"""Turn the light on."""
with self._update_lock:
if self._supported_flags & SUPPORT_BRIGHTNESS:
target_brightness = kwargs.get(ATTR_BRIGHTNESS)

# No brightness specified, so we either restore it to
# last brightness or switch it on at maximum level
if target_brightness is None:
if self._brightness == 0:
if self._last_brightness:
self._brightness = self._last_brightness
else:
self._brightness = 100
else:
# We set it to the target brightness and turn it on
self._brightness = scaleto100(target_brightness)

if self._supported_flags & SUPPORT_COLOR:
# Update based on parameters
self._white = kwargs.get(ATTR_WHITE_VALUE, self._white)
self._color = kwargs.get(ATTR_HS_COLOR, self._color)
rgb = color_util.color_hs_to_RGB(*self._color)
self.call_set_color(
int(rgb[0] * self._brightness / 99.0 + 0.5),
int(rgb[1] * self._brightness / 99.0 + 0.5),
int(rgb[2] * self._brightness / 99.0 + 0.5),
int(self._white * self._brightness / 99.0 +
0.5))
if self.state == 'off':
self.set_level(int(self._brightness))
return

if self._supported_flags & SUPPORT_BRIGHTNESS:
async with self._update_lock:
await self.hass.async_add_executor_job(
partial(self._turn_on, **kwargs))

def _turn_on(self, **kwargs):
"""Really turn the light on."""
if self._supported_flags & SUPPORT_BRIGHTNESS:
target_brightness = kwargs.get(ATTR_BRIGHTNESS)

# No brightness specified, so we either restore it to
# last brightness or switch it on at maximum level
if target_brightness is None:
if self._brightness == 0:
if self._last_brightness:
self._brightness = self._last_brightness
else:
self._brightness = 100
else:
# We set it to the target brightness and turn it on
self._brightness = scaleto100(target_brightness)

if self._supported_flags & SUPPORT_COLOR:
# Update based on parameters
self._white = kwargs.get(ATTR_WHITE_VALUE, self._white)
self._color = kwargs.get(ATTR_HS_COLOR, self._color)
rgb = color_util.color_hs_to_RGB(*self._color)
self.call_set_color(
int(rgb[0] * self._brightness / 99.0 + 0.5),
int(rgb[1] * self._brightness / 99.0 + 0.5),
int(rgb[2] * self._brightness / 99.0 + 0.5),
int(self._white * self._brightness / 99.0 +
0.5))
if self.state == 'off':
self.set_level(int(self._brightness))
return
return

# The simplest case is left for last. No dimming, just switch on
self.call_turn_on()
if self._supported_flags & SUPPORT_BRIGHTNESS:
self.set_level(int(self._brightness))
return

def turn_off(self, **kwargs):
# The simplest case is left for last. No dimming, just switch on
self.call_turn_on()

async def async_turn_off(self, **kwargs):
"""Turn the light off."""
async with self._update_lock:
await self.hass.async_add_executor_job(
partial(self._turn_off, **kwargs))

def _turn_off(self, **kwargs):
"""Really turn the light off."""
# Let's save the last brightness level before we switch it off
with self._update_lock:
if (self._supported_flags & SUPPORT_BRIGHTNESS) and \
self._brightness and self._brightness > 0:
self._last_brightness = self._brightness
self._brightness = 0
self.call_turn_off()
if (self._supported_flags & SUPPORT_BRIGHTNESS) and \
self._brightness and self._brightness > 0:
self._last_brightness = self._brightness
self._brightness = 0
self.call_turn_off()

@property
def is_on(self):
"""Return true if device is on."""
return self.current_binary_state

def update(self):
"""Call to update state."""
async def async_update(self):
"""Update the state."""
async with self._update_lock:
await self.hass.async_add_executor_job(self._update)

def _update(self):
"""Really update the state."""
# Brightness handling
with self._update_lock:
if self._supported_flags & SUPPORT_BRIGHTNESS:
self._brightness = float(self.fibaro_device.properties.value)
# Color handling
if self._supported_flags & SUPPORT_COLOR:
# Fibaro communicates the color as an 'R, G, B, W' string
rgbw_s = self.fibaro_device.properties.color
if rgbw_s == '0,0,0,0' and\
'lastColorSet' in self.fibaro_device.properties:
rgbw_s = self.fibaro_device.properties.lastColorSet
rgbw_list = [int(i) for i in rgbw_s.split(",")][:4]
if rgbw_list[0] or rgbw_list[1] or rgbw_list[2]:
self._color = color_util.color_RGB_to_hs(*rgbw_list[:3])
if (self._supported_flags & SUPPORT_WHITE_VALUE) and \
self.brightness != 0:
self._white = min(255, max(0, rgbw_list[3]*100.0 /
self._brightness))
if self._supported_flags & SUPPORT_BRIGHTNESS:
self._brightness = float(self.fibaro_device.properties.value)
# Color handling
if self._supported_flags & SUPPORT_COLOR:
# Fibaro communicates the color as an 'R, G, B, W' string
rgbw_s = self.fibaro_device.properties.color
if rgbw_s == '0,0,0,0' and\
'lastColorSet' in self.fibaro_device.properties:
rgbw_s = self.fibaro_device.properties.lastColorSet
rgbw_list = [int(i) for i in rgbw_s.split(",")][:4]
if rgbw_list[0] or rgbw_list[1] or rgbw_list[2]:
self._color = color_util.color_RGB_to_hs(*rgbw_list[:3])
if (self._supported_flags & SUPPORT_WHITE_VALUE) and \
self.brightness != 0:
self._white = min(255, max(0, rgbw_list[3]*100.0 /
self._brightness))