mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 01:37:08 +00:00
Fix emulated_hue brightness off by one (#34185)
* Fix emulated_hue brightness off by one Hue uses a max brightness of 254, Home Assistant uses a max brightness of 255. Values > 127 were off by one. * use constant * fix test * add debug * Revert "add debug" This reverts commit 242220a02e8d8e9ec5e21930470b2adb97c75e2b.
This commit is contained in:
parent
813f8dd63f
commit
23f278e090
@ -367,7 +367,7 @@ class HueOneLightChangeView(HomeAssistantView):
|
|||||||
cover.DOMAIN,
|
cover.DOMAIN,
|
||||||
climate.DOMAIN,
|
climate.DOMAIN,
|
||||||
]:
|
]:
|
||||||
# Convert 0-255 to 0-100
|
# Convert 0-254 to 0-100
|
||||||
level = (parsed[STATE_BRIGHTNESS] / HUE_API_STATE_BRI_MAX) * 100
|
level = (parsed[STATE_BRIGHTNESS] / HUE_API_STATE_BRI_MAX) * 100
|
||||||
parsed[STATE_BRIGHTNESS] = round(level)
|
parsed[STATE_BRIGHTNESS] = round(level)
|
||||||
parsed[STATE_ON] = True
|
parsed[STATE_ON] = True
|
||||||
@ -390,7 +390,9 @@ class HueOneLightChangeView(HomeAssistantView):
|
|||||||
if parsed[STATE_ON]:
|
if parsed[STATE_ON]:
|
||||||
if entity_features & SUPPORT_BRIGHTNESS:
|
if entity_features & SUPPORT_BRIGHTNESS:
|
||||||
if parsed[STATE_BRIGHTNESS] is not None:
|
if parsed[STATE_BRIGHTNESS] is not None:
|
||||||
data[ATTR_BRIGHTNESS] = parsed[STATE_BRIGHTNESS]
|
data[ATTR_BRIGHTNESS] = hue_brightness_to_hass(
|
||||||
|
parsed[STATE_BRIGHTNESS]
|
||||||
|
)
|
||||||
|
|
||||||
if entity_features & SUPPORT_COLOR:
|
if entity_features & SUPPORT_COLOR:
|
||||||
if any((parsed[STATE_HUE], parsed[STATE_SATURATION])):
|
if any((parsed[STATE_HUE], parsed[STATE_SATURATION])):
|
||||||
@ -536,7 +538,9 @@ def get_entity_state(config, entity):
|
|||||||
data[STATE_ON] = entity.state != STATE_OFF
|
data[STATE_ON] = entity.state != STATE_OFF
|
||||||
|
|
||||||
if data[STATE_ON]:
|
if data[STATE_ON]:
|
||||||
data[STATE_BRIGHTNESS] = entity.attributes.get(ATTR_BRIGHTNESS, 0)
|
data[STATE_BRIGHTNESS] = hass_to_hue_brightness(
|
||||||
|
entity.attributes.get(ATTR_BRIGHTNESS, 0)
|
||||||
|
)
|
||||||
hue_sat = entity.attributes.get(ATTR_HS_COLOR)
|
hue_sat = entity.attributes.get(ATTR_HS_COLOR)
|
||||||
if hue_sat is not None:
|
if hue_sat is not None:
|
||||||
hue = hue_sat[0]
|
hue = hue_sat[0]
|
||||||
@ -563,32 +567,32 @@ def get_entity_state(config, entity):
|
|||||||
pass
|
pass
|
||||||
elif entity.domain == climate.DOMAIN:
|
elif entity.domain == climate.DOMAIN:
|
||||||
temperature = entity.attributes.get(ATTR_TEMPERATURE, 0)
|
temperature = entity.attributes.get(ATTR_TEMPERATURE, 0)
|
||||||
# Convert 0-100 to 0-255
|
# Convert 0-100 to 0-254
|
||||||
data[STATE_BRIGHTNESS] = round(temperature * 255 / 100)
|
data[STATE_BRIGHTNESS] = round(temperature * HUE_API_STATE_BRI_MAX / 100)
|
||||||
elif entity.domain == media_player.DOMAIN:
|
elif entity.domain == media_player.DOMAIN:
|
||||||
level = entity.attributes.get(
|
level = entity.attributes.get(
|
||||||
ATTR_MEDIA_VOLUME_LEVEL, 1.0 if data[STATE_ON] else 0.0
|
ATTR_MEDIA_VOLUME_LEVEL, 1.0 if data[STATE_ON] else 0.0
|
||||||
)
|
)
|
||||||
# Convert 0.0-1.0 to 0-255
|
# Convert 0.0-1.0 to 0-254
|
||||||
data[STATE_BRIGHTNESS] = round(min(1.0, level) * 255)
|
data[STATE_BRIGHTNESS] = round(min(1.0, level) * HUE_API_STATE_BRI_MAX)
|
||||||
elif entity.domain == fan.DOMAIN:
|
elif entity.domain == fan.DOMAIN:
|
||||||
speed = entity.attributes.get(ATTR_SPEED, 0)
|
speed = entity.attributes.get(ATTR_SPEED, 0)
|
||||||
# Convert 0.0-1.0 to 0-255
|
# Convert 0.0-1.0 to 0-254
|
||||||
data[STATE_BRIGHTNESS] = 0
|
data[STATE_BRIGHTNESS] = 0
|
||||||
if speed == SPEED_LOW:
|
if speed == SPEED_LOW:
|
||||||
data[STATE_BRIGHTNESS] = 85
|
data[STATE_BRIGHTNESS] = 85
|
||||||
elif speed == SPEED_MEDIUM:
|
elif speed == SPEED_MEDIUM:
|
||||||
data[STATE_BRIGHTNESS] = 170
|
data[STATE_BRIGHTNESS] = 170
|
||||||
elif speed == SPEED_HIGH:
|
elif speed == SPEED_HIGH:
|
||||||
data[STATE_BRIGHTNESS] = 255
|
data[STATE_BRIGHTNESS] = HUE_API_STATE_BRI_MAX
|
||||||
elif entity.domain == cover.DOMAIN:
|
elif entity.domain == cover.DOMAIN:
|
||||||
level = entity.attributes.get(ATTR_CURRENT_POSITION, 0)
|
level = entity.attributes.get(ATTR_CURRENT_POSITION, 0)
|
||||||
data[STATE_BRIGHTNESS] = round(level / 100 * 255)
|
data[STATE_BRIGHTNESS] = round(level / 100 * HUE_API_STATE_BRI_MAX)
|
||||||
else:
|
else:
|
||||||
data = cached_state
|
data = cached_state
|
||||||
# Make sure brightness is valid
|
# Make sure brightness is valid
|
||||||
if data[STATE_BRIGHTNESS] is None:
|
if data[STATE_BRIGHTNESS] is None:
|
||||||
data[STATE_BRIGHTNESS] = 255 if data[STATE_ON] else 0
|
data[STATE_BRIGHTNESS] = HUE_API_STATE_BRI_MAX if data[STATE_ON] else 0
|
||||||
|
|
||||||
# Make sure hue/saturation are valid
|
# Make sure hue/saturation are valid
|
||||||
if (data[STATE_HUE] is None) or (data[STATE_SATURATION] is None):
|
if (data[STATE_HUE] is None) or (data[STATE_SATURATION] is None):
|
||||||
@ -723,3 +727,13 @@ def create_list_of_entities(config, request):
|
|||||||
json_response[number] = entity_to_json(config, entity)
|
json_response[number] = entity_to_json(config, entity)
|
||||||
|
|
||||||
return json_response
|
return json_response
|
||||||
|
|
||||||
|
|
||||||
|
def hue_brightness_to_hass(value):
|
||||||
|
"""Convert hue brightness 1..254 to hass format 0..255."""
|
||||||
|
return min(255, round((value / HUE_API_STATE_BRI_MAX) * 255))
|
||||||
|
|
||||||
|
|
||||||
|
def hass_to_hue_brightness(value):
|
||||||
|
"""Convert hass brightness 0..255 to hue 1..254 scale."""
|
||||||
|
return max(1, round((value / 255) * HUE_API_STATE_BRI_MAX))
|
||||||
|
@ -384,7 +384,7 @@ async def test_get_light_state(hass_hue, hue_client):
|
|||||||
await perform_get_light_state(hue_client, "light.kitchen_lights", 401)
|
await perform_get_light_state(hue_client, "light.kitchen_lights", 401)
|
||||||
|
|
||||||
|
|
||||||
async def test_put_light_state(hass_hue, hue_client):
|
async def test_put_light_state(hass, hass_hue, hue_client):
|
||||||
"""Test the setting of light states."""
|
"""Test the setting of light states."""
|
||||||
await perform_put_test_on_ceiling_lights(hass_hue, hue_client)
|
await perform_put_test_on_ceiling_lights(hass_hue, hue_client)
|
||||||
|
|
||||||
@ -400,6 +400,21 @@ async def test_put_light_state(hass_hue, hue_client):
|
|||||||
assert ceiling_lights.state == STATE_ON
|
assert ceiling_lights.state == STATE_ON
|
||||||
assert ceiling_lights.attributes[light.ATTR_BRIGHTNESS] == 153
|
assert ceiling_lights.attributes[light.ATTR_BRIGHTNESS] == 153
|
||||||
|
|
||||||
|
# update light state through api
|
||||||
|
await perform_put_light_state(
|
||||||
|
hass_hue,
|
||||||
|
hue_client,
|
||||||
|
"light.ceiling_lights",
|
||||||
|
True,
|
||||||
|
hue=4369,
|
||||||
|
saturation=127,
|
||||||
|
brightness=128,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
hass.states.get("light.ceiling_lights").attributes[light.ATTR_BRIGHTNESS] == 129
|
||||||
|
)
|
||||||
|
|
||||||
# update light state through api
|
# update light state through api
|
||||||
await perform_put_light_state(
|
await perform_put_light_state(
|
||||||
hass_hue,
|
hass_hue,
|
||||||
@ -411,6 +426,10 @@ async def test_put_light_state(hass_hue, hue_client):
|
|||||||
brightness=123,
|
brightness=123,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
hass.states.get("light.ceiling_lights").attributes[light.ATTR_BRIGHTNESS] == 123
|
||||||
|
)
|
||||||
|
|
||||||
# go through api to get the state back
|
# go through api to get the state back
|
||||||
ceiling_json = await perform_get_light_state(
|
ceiling_json = await perform_get_light_state(
|
||||||
hue_client, "light.ceiling_lights", 200
|
hue_client, "light.ceiling_lights", 200
|
||||||
@ -419,6 +438,25 @@ async def test_put_light_state(hass_hue, hue_client):
|
|||||||
assert ceiling_json["state"][HUE_API_STATE_HUE] == 4369
|
assert ceiling_json["state"][HUE_API_STATE_HUE] == 4369
|
||||||
assert ceiling_json["state"][HUE_API_STATE_SAT] == 127
|
assert ceiling_json["state"][HUE_API_STATE_SAT] == 127
|
||||||
|
|
||||||
|
# update light state through api
|
||||||
|
await perform_put_light_state(
|
||||||
|
hass_hue,
|
||||||
|
hue_client,
|
||||||
|
"light.ceiling_lights",
|
||||||
|
True,
|
||||||
|
hue=4369,
|
||||||
|
saturation=127,
|
||||||
|
brightness=255,
|
||||||
|
)
|
||||||
|
|
||||||
|
# go through api to get the state back
|
||||||
|
ceiling_json = await perform_get_light_state(
|
||||||
|
hue_client, "light.ceiling_lights", 200
|
||||||
|
)
|
||||||
|
assert ceiling_json["state"][HUE_API_STATE_BRI] == 254
|
||||||
|
assert ceiling_json["state"][HUE_API_STATE_HUE] == 4369
|
||||||
|
assert ceiling_json["state"][HUE_API_STATE_SAT] == 127
|
||||||
|
|
||||||
# Go through the API to turn it off
|
# Go through the API to turn it off
|
||||||
ceiling_result = await perform_put_light_state(
|
ceiling_result = await perform_put_light_state(
|
||||||
hass_hue, hue_client, "light.ceiling_lights", False
|
hass_hue, hue_client, "light.ceiling_lights", False
|
||||||
@ -454,7 +492,7 @@ async def test_put_light_state(hass_hue, hue_client):
|
|||||||
assert kitchen_result.status == HTTP_NOT_FOUND
|
assert kitchen_result.status == HTTP_NOT_FOUND
|
||||||
|
|
||||||
|
|
||||||
async def test_put_light_state_script(hass_hue, hue_client):
|
async def test_put_light_state_script(hass, hass_hue, hue_client):
|
||||||
"""Test the setting of script variables."""
|
"""Test the setting of script variables."""
|
||||||
# Turn the kitchen light off first
|
# Turn the kitchen light off first
|
||||||
await hass_hue.services.async_call(
|
await hass_hue.services.async_call(
|
||||||
@ -464,9 +502,9 @@ async def test_put_light_state_script(hass_hue, hue_client):
|
|||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Emulated hue converts 0-100% to 0-255.
|
# Emulated hue converts 0-100% to 0-254.
|
||||||
level = 23
|
level = 23
|
||||||
brightness = round(level * 255 / 100)
|
brightness = round(level * 254 / 100)
|
||||||
|
|
||||||
script_result = await perform_put_light_state(
|
script_result = await perform_put_light_state(
|
||||||
hass_hue, hue_client, "script.set_kitchen_light", True, brightness
|
hass_hue, hue_client, "script.set_kitchen_light", True, brightness
|
||||||
@ -481,11 +519,15 @@ async def test_put_light_state_script(hass_hue, hue_client):
|
|||||||
assert kitchen_light.state == "on"
|
assert kitchen_light.state == "on"
|
||||||
assert kitchen_light.attributes[light.ATTR_BRIGHTNESS] == level
|
assert kitchen_light.attributes[light.ATTR_BRIGHTNESS] == level
|
||||||
|
|
||||||
|
assert (
|
||||||
|
hass.states.get("light.kitchen_lights").attributes[light.ATTR_BRIGHTNESS] == 23
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_put_light_state_climate_set_temperature(hass_hue, hue_client):
|
async def test_put_light_state_climate_set_temperature(hass_hue, hue_client):
|
||||||
"""Test setting climate temperature."""
|
"""Test setting climate temperature."""
|
||||||
brightness = 19
|
brightness = 19
|
||||||
temperature = round(brightness / 255 * 100)
|
temperature = round(brightness / 254 * 100)
|
||||||
|
|
||||||
hvac_result = await perform_put_light_state(
|
hvac_result = await perform_put_light_state(
|
||||||
hass_hue, hue_client, "climate.hvac", True, brightness
|
hass_hue, hue_client, "climate.hvac", True, brightness
|
||||||
@ -517,9 +559,9 @@ async def test_put_light_state_media_player(hass_hue, hue_client):
|
|||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Emulated hue converts 0.0-1.0 to 0-255.
|
# Emulated hue converts 0.0-1.0 to 0-254.
|
||||||
level = 0.25
|
level = 0.25
|
||||||
brightness = round(level * 255)
|
brightness = round(level * 254)
|
||||||
|
|
||||||
mp_result = await perform_put_light_state(
|
mp_result = await perform_put_light_state(
|
||||||
hass_hue, hue_client, "media_player.walkman", True, brightness
|
hass_hue, hue_client, "media_player.walkman", True, brightness
|
||||||
@ -602,7 +644,7 @@ async def test_set_position_cover(hass_hue, hue_client):
|
|||||||
assert cover_test.state == "closed"
|
assert cover_test.state == "closed"
|
||||||
|
|
||||||
level = 20
|
level = 20
|
||||||
brightness = round(level / 100 * 255)
|
brightness = round(level / 100 * 254)
|
||||||
|
|
||||||
# Go through the API to open
|
# Go through the API to open
|
||||||
cover_result = await perform_put_light_state(
|
cover_result = await perform_put_light_state(
|
||||||
@ -644,9 +686,9 @@ async def test_put_light_state_fan(hass_hue, hue_client):
|
|||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Emulated hue converts 0-100% to 0-255.
|
# Emulated hue converts 0-100% to 0-254.
|
||||||
level = 43
|
level = 43
|
||||||
brightness = round(level * 255 / 100)
|
brightness = round(level * 254 / 100)
|
||||||
|
|
||||||
fan_result = await perform_put_light_state(
|
fan_result = await perform_put_light_state(
|
||||||
hass_hue, hue_client, "fan.living_room_fan", True, brightness
|
hass_hue, hue_client, "fan.living_room_fan", True, brightness
|
||||||
|
Loading…
x
Reference in New Issue
Block a user