Fix light toggle service attributes (#35483)

This commit is contained in:
Xiaonan Shen 2020-05-11 03:58:59 -07:00 committed by GitHub
parent 823a44cd23
commit 5d8e6d5432
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 18 deletions

View File

@ -167,12 +167,19 @@ def preprocess_turn_on_alternatives(params):
if rgb_color is not None:
params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color)
return params
def filter_turn_off_params(params):
"""Filter out params not used in turn off."""
return {k: v for k, v in params.items() if k in (ATTR_TRANSITION, ATTR_FLASH)}
def preprocess_turn_off(params):
"""Process data for turning light off if brightness is 0."""
if ATTR_BRIGHTNESS in params and params[ATTR_BRIGHTNESS] == 0:
# Zero brightness: Light will be turned off
params = {k: v for k, v in params.items() if k in (ATTR_TRANSITION, ATTR_FLASH)}
params = filter_turn_off_params(params)
return (True, params) # Light should be turned off
return (False, None) # Light should be turned on
@ -198,13 +205,7 @@ async def async_setup(hass, config):
if entity_field in data
}
preprocess_turn_on_alternatives(data)
turn_lights_off, off_params = preprocess_turn_off(data)
base["params"] = data
base["turn_lights_off"] = turn_lights_off
base["off_params"] = off_params
base["params"] = preprocess_turn_on_alternatives(data)
return base
async def async_handle_light_on_service(light, call):
@ -213,8 +214,6 @@ async def async_setup(hass, config):
If brightness is set to 0, this service will turn the light off.
"""
params = call.data["params"]
turn_light_off = call.data["turn_lights_off"]
off_params = call.data["off_params"]
if not params:
default_profile = Profiles.get_default(light.entity_id)
@ -222,7 +221,6 @@ async def async_setup(hass, config):
if default_profile is not None:
params = {ATTR_PROFILE: default_profile}
preprocess_turn_on_alternatives(params)
turn_light_off, off_params = preprocess_turn_off(params)
elif ATTR_BRIGHTNESS_STEP in params or ATTR_BRIGHTNESS_STEP_PCT in params:
brightness = light.brightness if light.is_on else 0
@ -236,13 +234,24 @@ async def async_setup(hass, config):
brightness += round(params.pop(ATTR_BRIGHTNESS_STEP_PCT) / 100 * 255)
params[ATTR_BRIGHTNESS] = max(0, min(255, brightness))
turn_light_off, off_params = preprocess_turn_off(params)
turn_light_off, off_params = preprocess_turn_off(params)
if turn_light_off:
await light.async_turn_off(**off_params)
else:
await light.async_turn_on(**params)
async def async_handle_toggle_service(light, call):
"""Handle toggling a light.
If brightness is set to 0, this service will turn the light off.
"""
if light.is_on:
off_params = filter_turn_off_params(call.data["params"])
await light.async_turn_off(**off_params)
else:
await async_handle_light_on_service(light, call)
# Listen for light on and light off service calls.
component.async_register_entity_service(
@ -258,7 +267,9 @@ async def async_setup(hass, config):
)
component.async_register_entity_service(
SERVICE_TOGGLE, LIGHT_TURN_ON_SCHEMA, "async_toggle"
SERVICE_TOGGLE,
vol.All(cv.make_entity_service_schema(LIGHT_TURN_ON_SCHEMA), preprocess_data),
async_handle_toggle_service,
)
return True

View File

@ -128,16 +128,80 @@ async def async_turn_off(hass, entity_id=ENTITY_MATCH_ALL, transition=None):
@bind_hass
def toggle(hass, entity_id=ENTITY_MATCH_ALL, transition=None):
def toggle(
hass,
entity_id=ENTITY_MATCH_ALL,
transition=None,
brightness=None,
brightness_pct=None,
rgb_color=None,
xy_color=None,
hs_color=None,
color_temp=None,
kelvin=None,
white_value=None,
profile=None,
flash=None,
effect=None,
color_name=None,
):
"""Toggle all or specified light."""
hass.add_job(async_toggle, hass, entity_id, transition)
hass.add_job(
async_toggle,
hass,
entity_id,
transition,
brightness,
brightness_pct,
rgb_color,
xy_color,
hs_color,
color_temp,
kelvin,
white_value,
profile,
flash,
effect,
color_name,
)
async def async_toggle(hass, entity_id=ENTITY_MATCH_ALL, transition=None):
"""Toggle all or specified light."""
async def async_toggle(
hass,
entity_id=ENTITY_MATCH_ALL,
transition=None,
brightness=None,
brightness_pct=None,
rgb_color=None,
xy_color=None,
hs_color=None,
color_temp=None,
kelvin=None,
white_value=None,
profile=None,
flash=None,
effect=None,
color_name=None,
):
"""Turn all or specified light on."""
data = {
key: value
for key, value in [(ATTR_ENTITY_ID, entity_id), (ATTR_TRANSITION, transition)]
for key, value in [
(ATTR_ENTITY_ID, entity_id),
(ATTR_PROFILE, profile),
(ATTR_TRANSITION, transition),
(ATTR_BRIGHTNESS, brightness),
(ATTR_BRIGHTNESS_PCT, brightness_pct),
(ATTR_RGB_COLOR, rgb_color),
(ATTR_XY_COLOR, xy_color),
(ATTR_HS_COLOR, hs_color),
(ATTR_COLOR_TEMP, color_temp),
(ATTR_KELVIN, kelvin),
(ATTR_WHITE_VALUE, white_value),
(ATTR_FLASH, flash),
(ATTR_EFFECT, effect),
(ATTR_COLOR_NAME, color_name),
]
if value is not None
}

View File

@ -263,6 +263,15 @@ class TestLight(unittest.TestCase):
light.ATTR_HS_COLOR: (prof_h, prof_s),
} == data
# Test toggle with parameters
common.toggle(self.hass, ent3.entity_id, profile=prof_name, brightness_pct=100)
self.hass.block_till_done()
_, data = ent3.last_call("turn_on")
assert {
light.ATTR_BRIGHTNESS: 255,
light.ATTR_HS_COLOR: (prof_h, prof_s),
} == data
# Test bad data
common.turn_on(self.hass)
common.turn_on(self.hass, ent1.entity_id, profile="nonexisting")