Improve precision of HSV color conversion (#130880)

This commit is contained in:
Petar Petrov 2024-11-19 23:06:57 +02:00 committed by GitHub
parent 6f0139389f
commit c68cadad7a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 102 additions and 102 deletions

View File

@ -377,7 +377,7 @@ def color_hsv_to_RGB(iH: float, iS: float, iV: float) -> tuple[int, int, int]:
Val is scaled 0-100 Val is scaled 0-100
""" """
fRGB = colorsys.hsv_to_rgb(iH / 360, iS / 100, iV / 100) fRGB = colorsys.hsv_to_rgb(iH / 360, iS / 100, iV / 100)
return (int(fRGB[0] * 255), int(fRGB[1] * 255), int(fRGB[2] * 255)) return (round(fRGB[0] * 255), round(fRGB[1] * 255), round(fRGB[2] * 255))
def color_hs_to_RGB(iH: float, iS: float) -> tuple[int, int, int]: def color_hs_to_RGB(iH: float, iS: float) -> tuple[int, int, int]:

View File

@ -45,7 +45,7 @@ async def test_attributes(hass: HomeAssistant) -> None:
state = hass.states.get(DEVICE_ID) state = hass.states.get(DEVICE_ID)
assert state.state == STATE_ON assert state.state == STATE_ON
assert state.attributes.get(ATTR_BRIGHTNESS) == 204 assert state.attributes.get(ATTR_BRIGHTNESS) == 204
assert state.attributes.get(ATTR_RGB_COLOR) == (0, 63, 255) assert state.attributes.get(ATTR_RGB_COLOR) == (0, 64, 255)
assert state.attributes.get(ATTR_COLOR_TEMP) is None assert state.attributes.get(ATTR_COLOR_TEMP) is None
assert state.attributes.get(ATTR_DEVICE_ID) == "ZB:db5b1a" assert state.attributes.get(ATTR_DEVICE_ID) == "ZB:db5b1a"
assert not state.attributes.get("battery_low") assert not state.attributes.get("battery_low")

View File

@ -78,7 +78,7 @@ async def setup_light(hass: HomeAssistant):
# Validate starting values # Validate starting values
assert state.state == STATE_ON assert state.state == STATE_ON
assert state.attributes.get(ATTR_BRIGHTNESS) == 180 assert state.attributes.get(ATTR_BRIGHTNESS) == 180
assert state.attributes.get(ATTR_RGB_COLOR) == (255, 63, 111) assert state.attributes.get(ATTR_RGB_COLOR) == (255, 64, 112)
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,

View File

@ -125,7 +125,7 @@
'min_mireds': 153, 'min_mireds': 153,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
67, 68,
0, 0,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
@ -134,7 +134,7 @@
]), ]),
'supported_features': <LightEntityFeature: 44>, 'supported_features': <LightEntityFeature: 44>,
'xy_color': tuple( 'xy_color': tuple(
0.674, 0.673,
0.322, 0.322,
), ),
}), }),
@ -283,7 +283,7 @@
'min_mireds': 155, 'min_mireds': 155,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
67, 68,
0, 0,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
@ -291,7 +291,7 @@
]), ]),
'supported_features': <LightEntityFeature: 0>, 'supported_features': <LightEntityFeature: 0>,
'xy_color': tuple( 'xy_color': tuple(
0.674, 0.673,
0.322, 0.322,
), ),
}), }),
@ -429,7 +429,7 @@
'min_mireds': 153, 'min_mireds': 153,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
67, 68,
0, 0,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
@ -438,7 +438,7 @@
]), ]),
'supported_features': <LightEntityFeature: 44>, 'supported_features': <LightEntityFeature: 44>,
'xy_color': tuple( 'xy_color': tuple(
0.674, 0.673,
0.322, 0.322,
), ),
}), }),
@ -587,7 +587,7 @@
'min_mireds': 155, 'min_mireds': 155,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
67, 68,
0, 0,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
@ -595,7 +595,7 @@
]), ]),
'supported_features': <LightEntityFeature: 0>, 'supported_features': <LightEntityFeature: 0>,
'xy_color': tuple( 'xy_color': tuple(
0.674, 0.673,
0.322, 0.322,
), ),
}), }),
@ -891,7 +891,7 @@
'min_mireds': 155, 'min_mireds': 155,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
67, 68,
0, 0,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
@ -899,7 +899,7 @@
]), ]),
'supported_features': <LightEntityFeature: 0>, 'supported_features': <LightEntityFeature: 0>,
'xy_color': tuple( 'xy_color': tuple(
0.674, 0.673,
0.322, 0.322,
), ),
}), }),
@ -981,7 +981,7 @@
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
165, 165,
84, 85,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>, <ColorMode.COLOR_TEMP: 'color_temp'>,
@ -990,8 +990,8 @@
]), ]),
'supported_features': <LightEntityFeature: 44>, 'supported_features': <LightEntityFeature: 44>,
'xy_color': tuple( 'xy_color': tuple(
0.53, 0.529,
0.388, 0.387,
), ),
}), }),
'context': <ANY>, 'context': <ANY>,
@ -1180,7 +1180,7 @@
'is_deconz_group': False, 'is_deconz_group': False,
'rgb_color': tuple( 'rgb_color': tuple(
243, 243,
113, 114,
255, 255,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
@ -1189,7 +1189,7 @@
'supported_features': <LightEntityFeature: 44>, 'supported_features': <LightEntityFeature: 44>,
'xy_color': tuple( 'xy_color': tuple(
0.357, 0.357,
0.188, 0.189,
), ),
}), }),
'context': <ANY>, 'context': <ANY>,

View File

@ -830,7 +830,7 @@ async def test_groups(
}, },
{ {
"on": True, "on": True,
"xy": (0.235, 0.164), "xy": (0.236, 0.166),
}, },
), ),
( # Turn on group with short color loop ( # Turn on group with short color loop
@ -845,7 +845,7 @@ async def test_groups(
}, },
{ {
"on": True, "on": True,
"xy": (0.235, 0.164), "xy": (0.236, 0.166),
}, },
), ),
], ],

View File

@ -73,8 +73,8 @@ async def test_state_attributes(hass: HomeAssistant) -> None:
) )
state = hass.states.get(ENTITY_LIGHT) state = hass.states.get(ENTITY_LIGHT)
assert state.attributes.get(ATTR_RGB_COLOR) == (250, 252, 255) assert state.attributes.get(ATTR_RGB_COLOR) == (251, 253, 255)
assert state.attributes.get(ATTR_XY_COLOR) == (0.319, 0.326) assert state.attributes.get(ATTR_XY_COLOR) == (0.319, 0.327)
await hass.services.async_call( await hass.services.async_call(
LIGHT_DOMAIN, LIGHT_DOMAIN,

View File

@ -17,7 +17,7 @@
'min_mireds': 143, 'min_mireds': 143,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
188, 189,
133, 133,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
@ -25,8 +25,8 @@
]), ]),
'supported_features': <LightEntityFeature: 0>, 'supported_features': <LightEntityFeature: 0>,
'xy_color': tuple( 'xy_color': tuple(
0.465, 0.464,
0.376, 0.377,
), ),
}), }),
'context': <ANY>, 'context': <ANY>,
@ -132,7 +132,7 @@
'min_mireds': 153, 'min_mireds': 153,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
188, 189,
133, 133,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
@ -141,8 +141,8 @@
]), ]),
'supported_features': <LightEntityFeature: 0>, 'supported_features': <LightEntityFeature: 0>,
'xy_color': tuple( 'xy_color': tuple(
0.465, 0.464,
0.376, 0.377,
), ),
}), }),
'context': <ANY>, 'context': <ANY>,
@ -249,7 +249,7 @@
'min_mireds': 153, 'min_mireds': 153,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
239, 240,
240, 240,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
@ -258,8 +258,8 @@
]), ]),
'supported_features': <LightEntityFeature: 0>, 'supported_features': <LightEntityFeature: 0>,
'xy_color': tuple( 'xy_color': tuple(
0.34, 0.339,
0.327, 0.328,
), ),
}), }),
'context': <ANY>, 'context': <ANY>,

View File

@ -676,7 +676,7 @@ async def test_light_rgb(
color_mode=LightColorCapability.RGB color_mode=LightColorCapability.RGB
| LightColorCapability.ON_OFF | LightColorCapability.ON_OFF
| LightColorCapability.BRIGHTNESS, | LightColorCapability.BRIGHTNESS,
rgb=(pytest.approx(0.32941176470588235), 1.0, 0.0), rgb=(pytest.approx(0.3333333333333333), 1.0, 0.0),
brightness=pytest.approx(0.4980392156862745), brightness=pytest.approx(0.4980392156862745),
) )
] ]
@ -814,7 +814,7 @@ async def test_light_rgbw(
| LightColorCapability.ON_OFF | LightColorCapability.ON_OFF
| LightColorCapability.BRIGHTNESS, | LightColorCapability.BRIGHTNESS,
white=0, white=0,
rgb=(pytest.approx(0.32941176470588235), 1.0, 0.0), rgb=(pytest.approx(0.3333333333333333), 1.0, 0.0),
brightness=pytest.approx(0.4980392156862745), brightness=pytest.approx(0.4980392156862745),
) )
] ]
@ -993,7 +993,7 @@ async def test_light_rgbww_with_cold_warm_white_support(
| LightColorCapability.BRIGHTNESS, | LightColorCapability.BRIGHTNESS,
cold_white=0, cold_white=0,
warm_white=0, warm_white=0,
rgb=(pytest.approx(0.32941176470588235), 1.0, 0.0), rgb=(pytest.approx(0.3333333333333333), 1.0, 0.0),
brightness=pytest.approx(0.4980392156862745), brightness=pytest.approx(0.4980392156862745),
) )
] ]
@ -1226,7 +1226,7 @@ async def test_light_rgbww_without_cold_warm_white_support(
| LightColorCapability.ON_OFF | LightColorCapability.ON_OFF
| LightColorCapability.BRIGHTNESS, | LightColorCapability.BRIGHTNESS,
white=0, white=0,
rgb=(pytest.approx(0.32941176470588235), 1.0, 0.0), rgb=(pytest.approx(0.3333333333333333), 1.0, 0.0),
brightness=pytest.approx(0.4980392156862745), brightness=pytest.approx(0.4980392156862745),
) )
] ]

View File

@ -517,7 +517,7 @@ async def test_rgbw_light_auto_on(hass: HomeAssistant) -> None:
# enough resolution to determine which color to display # enough resolution to determine which color to display
bulb.async_turn_on.assert_not_called() bulb.async_turn_on.assert_not_called()
bulb.async_set_brightness.assert_not_called() bulb.async_set_brightness.assert_not_called()
bulb.async_set_levels.assert_called_with(2, 0, 0, 0) bulb.async_set_levels.assert_called_with(3, 0, 0, 0)
bulb.async_set_levels.reset_mock() bulb.async_set_levels.reset_mock()
await hass.services.async_call( await hass.services.async_call(
@ -534,7 +534,7 @@ async def test_rgbw_light_auto_on(hass: HomeAssistant) -> None:
# enough resolution to determine which color to display # enough resolution to determine which color to display
bulb.async_turn_on.assert_not_called() bulb.async_turn_on.assert_not_called()
bulb.async_set_brightness.assert_not_called() bulb.async_set_brightness.assert_not_called()
bulb.async_set_levels.assert_called_with(2, 0, 0, 56) bulb.async_set_levels.assert_called_with(3, 0, 0, 56)
bulb.async_set_levels.reset_mock() bulb.async_set_levels.reset_mock()
bulb.brightness = 128 bulb.brightness = 128
@ -652,7 +652,7 @@ async def test_rgbww_light_auto_on(hass: HomeAssistant) -> None:
# which color to display # which color to display
bulb.async_turn_on.assert_not_called() bulb.async_turn_on.assert_not_called()
bulb.async_set_brightness.assert_not_called() bulb.async_set_brightness.assert_not_called()
bulb.async_set_levels.assert_called_with(2, 0, 0, 0, 0) bulb.async_set_levels.assert_called_with(3, 0, 0, 0, 0)
bulb.async_set_levels.reset_mock() bulb.async_set_levels.reset_mock()
bulb.brightness = 128 bulb.brightness = 128

View File

@ -11400,15 +11400,15 @@
'min_mireds': 153, 'min_mireds': 153,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
167, 168,
89, 90,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>, <ColorMode.COLOR_TEMP: 'color_temp'>,
]), ]),
'supported_features': <LightEntityFeature: 0>, 'supported_features': <LightEntityFeature: 0>,
'xy_color': tuple( 'xy_color': tuple(
0.524, 0.522,
0.387, 0.387,
), ),
}), }),
@ -11548,15 +11548,15 @@
'min_mireds': 153, 'min_mireds': 153,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
167, 168,
89, 90,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>, <ColorMode.COLOR_TEMP: 'color_temp'>,
]), ]),
'supported_features': <LightEntityFeature: 0>, 'supported_features': <LightEntityFeature: 0>,
'xy_color': tuple( 'xy_color': tuple(
0.524, 0.522,
0.387, 0.387,
), ),
}), }),
@ -14883,7 +14883,7 @@
'min_mireds': 153, 'min_mireds': 153,
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
141, 142,
28, 28,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
@ -14892,8 +14892,8 @@
]), ]),
'supported_features': <LightEntityFeature: 0>, 'supported_features': <LightEntityFeature: 0>,
'xy_color': tuple( 'xy_color': tuple(
0.589, 0.588,
0.385, 0.386,
), ),
}), }),
'entity_id': 'light.nanoleaf_strip_3b32_nanoleaf_light_strip', 'entity_id': 'light.nanoleaf_strip_3b32_nanoleaf_light_strip',

View File

@ -1098,8 +1098,8 @@ async def test_color_light_with_temp(
ColorMode.HS, ColorMode.HS,
] ]
assert attributes[ATTR_HS_COLOR] == (30.754, 7.122) assert attributes[ATTR_HS_COLOR] == (30.754, 7.122)
assert attributes[ATTR_RGB_COLOR] == (255, 246, 236) assert attributes[ATTR_RGB_COLOR] == (255, 246, 237)
assert attributes[ATTR_XY_COLOR] == (0.34, 0.339) assert attributes[ATTR_XY_COLOR] == (0.339, 0.338)
bulb.color = [65535, 65535, 65535, 65535] bulb.color = [65535, 65535, 65535, 65535]
await hass.services.async_call( await hass.services.async_call(

View File

@ -1287,9 +1287,9 @@ async def test_light_backwards_compatibility_color_mode(hass: HomeAssistant) ->
state = hass.states.get(entity2.entity_id) state = hass.states.get(entity2.entity_id)
assert state.attributes["supported_color_modes"] == [light.ColorMode.COLOR_TEMP] assert state.attributes["supported_color_modes"] == [light.ColorMode.COLOR_TEMP]
assert state.attributes["color_mode"] == light.ColorMode.COLOR_TEMP assert state.attributes["color_mode"] == light.ColorMode.COLOR_TEMP
assert state.attributes["rgb_color"] == (201, 218, 255) assert state.attributes["rgb_color"] == (202, 218, 255)
assert state.attributes["hs_color"] == (221.575, 20.9) assert state.attributes["hs_color"] == (221.575, 20.9)
assert state.attributes["xy_color"] == (0.277, 0.287) assert state.attributes["xy_color"] == (0.278, 0.287)
state = hass.states.get(entity3.entity_id) state = hass.states.get(entity3.entity_id)
assert state.attributes["supported_color_modes"] == [light.ColorMode.HS] assert state.attributes["supported_color_modes"] == [light.ColorMode.HS]

View File

@ -59,15 +59,15 @@
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
193, 193,
141, 142,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>, <ColorMode.COLOR_TEMP: 'color_temp'>,
]), ]),
'supported_features': <LightEntityFeature: 32>, 'supported_features': <LightEntityFeature: 32>,
'xy_color': tuple( 'xy_color': tuple(
0.453, 0.452,
0.374, 0.373,
), ),
}), }),
'context': <ANY>, 'context': <ANY>,
@ -252,7 +252,7 @@
'rgb_color': tuple( 'rgb_color': tuple(
255, 255,
247, 247,
203, 204,
), ),
'supported_color_modes': list([ 'supported_color_modes': list([
<ColorMode.COLOR_TEMP: 'color_temp'>, <ColorMode.COLOR_TEMP: 'color_temp'>,
@ -261,8 +261,8 @@
]), ]),
'supported_features': <LightEntityFeature: 32>, 'supported_features': <LightEntityFeature: 32>,
'xy_color': tuple( 'xy_color': tuple(
0.363, 0.362,
0.374, 0.373,
), ),
}), }),
'context': <ANY>, 'context': <ANY>,

View File

@ -721,12 +721,12 @@ async def test_invalid_state_via_topic(
state = hass.states.get("light.test") state = hass.states.get("light.test")
assert state.state == STATE_ON assert state.state == STATE_ON
assert state.attributes.get("rgb_color") == (255, 254, 250) assert state.attributes.get("rgb_color") == (255, 255, 251)
assert state.attributes.get("brightness") == 255 assert state.attributes.get("brightness") == 255
assert state.attributes.get("color_temp") == 153 assert state.attributes.get("color_temp") == 153
assert state.attributes.get("effect") == "none" assert state.attributes.get("effect") == "none"
assert state.attributes.get("hs_color") == (54.768, 1.6) assert state.attributes.get("hs_color") == (54.768, 1.6)
assert state.attributes.get("xy_color") == (0.326, 0.333) assert state.attributes.get("xy_color") == (0.325, 0.333)
async_fire_mqtt_message(hass, "test_light_rgb/color_temp/status", "") async_fire_mqtt_message(hass, "test_light_rgb/color_temp/status", "")
light_state = hass.states.get("light.test") light_state = hass.states.get("light.test")

View File

@ -674,12 +674,12 @@ async def test_controlling_state_via_topic(
assert state.attributes.get("rgb_color") == ( assert state.attributes.get("rgb_color") == (
255, 255,
253, 253,
248, 249,
) # temp converted to color ) # temp converted to color
assert state.attributes.get("brightness") == 255 assert state.attributes.get("brightness") == 255
assert state.attributes.get("color_temp") == 155 assert state.attributes.get("color_temp") == 155
assert state.attributes.get("effect") == "colorloop" assert state.attributes.get("effect") == "colorloop"
assert state.attributes.get("xy_color") == (0.328, 0.334) # temp converted to color assert state.attributes.get("xy_color") == (0.328, 0.333) # temp converted to color
assert state.attributes.get("hs_color") == (44.098, 2.43) # temp converted to color assert state.attributes.get("hs_color") == (44.098, 2.43) # temp converted to color
# Turn the light off # Turn the light off
@ -706,7 +706,7 @@ async def test_controlling_state_via_topic(
) )
light_state = hass.states.get("light.test") light_state = hass.states.get("light.test")
assert light_state.attributes.get("xy_color") == (0.141, 0.14) assert light_state.attributes.get("xy_color") == (0.141, 0.141)
async_fire_mqtt_message( async_fire_mqtt_message(
hass, "test_light_rgb", '{"state":"ON", "color":{"h":180,"s":50}}' hass, "test_light_rgb", '{"state":"ON", "color":{"h":180,"s":50}}'
@ -1015,10 +1015,10 @@ async def test_controlling_the_state_with_legacy_color_handling(
assert state.attributes.get("color_temp") == 353 assert state.attributes.get("color_temp") == 353
assert state.attributes.get("effect") is None assert state.attributes.get("effect") is None
assert state.attributes.get("hs_color") == (28.125, 61.661) assert state.attributes.get("hs_color") == (28.125, 61.661)
assert state.attributes.get("rgb_color") == (255, 171, 97) assert state.attributes.get("rgb_color") == (255, 171, 98)
assert state.attributes.get("rgbw_color") is None assert state.attributes.get("rgbw_color") is None
assert state.attributes.get("rgbww_color") is None assert state.attributes.get("rgbww_color") is None
assert state.attributes.get("xy_color") == (0.513, 0.386) assert state.attributes.get("xy_color") == (0.512, 0.385)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -1113,8 +1113,8 @@ async def test_sending_mqtt_commands_and_optimistic(
mqtt_mock.async_publish.assert_called_once_with( mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set", "test_light_rgb/set",
JsonValidator( JsonValidator(
'{"state": "ON", "color": {"r": 0, "g": 123, "b": 255,' '{"state": "ON", "color": {"r": 0, "g": 124, "b": 255,'
' "x": 0.14, "y": 0.131, "h": 210.824, "s": 100.0},' ' "x": 0.14, "y": 0.133, "h": 210.824, "s": 100.0},'
' "brightness": 50}' ' "brightness": 50}'
), ),
2, 2,
@ -1125,8 +1125,8 @@ async def test_sending_mqtt_commands_and_optimistic(
assert state.attributes.get("color_mode") == light.ColorMode.HS assert state.attributes.get("color_mode") == light.ColorMode.HS
assert state.attributes["brightness"] == 50 assert state.attributes["brightness"] == 50
assert state.attributes["hs_color"] == (210.824, 100.0) assert state.attributes["hs_color"] == (210.824, 100.0)
assert state.attributes["rgb_color"] == (0, 123, 255) assert state.attributes["rgb_color"] == (0, 124, 255)
assert state.attributes["xy_color"] == (0.14, 0.131) assert state.attributes["xy_color"] == (0.14, 0.133)
await common.async_turn_on(hass, "light.test", brightness=50, hs_color=(359, 78)) await common.async_turn_on(hass, "light.test", brightness=50, hs_color=(359, 78))
mqtt_mock.async_publish.assert_called_once_with( mqtt_mock.async_publish.assert_called_once_with(
@ -1514,7 +1514,7 @@ async def test_sending_rgb_color_no_brightness(
), ),
call( call(
"test_light_rgb/set", "test_light_rgb/set",
JsonValidator('{"state": "ON", "color": {"r": 50, "g": 11, "b": 11}}'), JsonValidator('{"state": "ON", "color": {"r": 50, "g": 11, "b": 12}}'),
0, 0,
False, False,
), ),
@ -1646,7 +1646,7 @@ async def test_sending_rgb_color_with_brightness(
call( call(
"test_light_rgb/set", "test_light_rgb/set",
JsonValidator( JsonValidator(
'{"state": "ON", "color": {"r": 0, "g": 123, "b": 255},' '{"state": "ON", "color": {"r": 0, "g": 124, "b": 255},'
' "brightness": 50}' ' "brightness": 50}'
), ),
0, 0,
@ -1716,7 +1716,7 @@ async def test_sending_rgb_color_with_scaled_brightness(
call( call(
"test_light_rgb/set", "test_light_rgb/set",
JsonValidator( JsonValidator(
'{"state": "ON", "color": {"r": 0, "g": 123, "b": 255},' '{"state": "ON", "color": {"r": 0, "g": 124, "b": 255},'
' "brightness": 20}' ' "brightness": 20}'
), ),
0, 0,
@ -1830,7 +1830,7 @@ async def test_sending_xy_color(
call( call(
"test_light_rgb/set", "test_light_rgb/set",
JsonValidator( JsonValidator(
'{"state": "ON", "color": {"x": 0.14, "y": 0.131},' '{"state": "ON", "color": {"x": 0.14, "y": 0.133},'
' "brightness": 50}' ' "brightness": 50}'
), ),
0, 0,

View File

@ -322,7 +322,7 @@ async def test_state_brightness_color_effect_temp_change_via_topic(
state = hass.states.get("light.test") state = hass.states.get("light.test")
assert state.state == STATE_ON assert state.state == STATE_ON
assert state.attributes.get("rgb_color") == (255, 128, 63) assert state.attributes.get("rgb_color") == (255, 128, 64)
assert state.attributes.get("brightness") == 255 assert state.attributes.get("brightness") == 255
assert state.attributes.get("color_temp") is None # rgb color has priority assert state.attributes.get("color_temp") is None # rgb color has priority
assert state.attributes.get("effect") is None assert state.attributes.get("effect") is None
@ -494,12 +494,12 @@ async def test_sending_mqtt_commands_and_optimistic(
# Full brightness - normalization of RGB values sent over MQTT # Full brightness - normalization of RGB values sent over MQTT
await common.async_turn_on(hass, "light.test", rgb_color=(128, 64, 0)) await common.async_turn_on(hass, "light.test", rgb_color=(128, 64, 0))
mqtt_mock.async_publish.assert_called_once_with( mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set", "on,,,255-127-0,30.0-100.0", 2, False "test_light_rgb/set", "on,,,255-128-0,30.0-100.0", 2, False
) )
mqtt_mock.async_publish.reset_mock() mqtt_mock.async_publish.reset_mock()
state = hass.states.get("light.test") state = hass.states.get("light.test")
assert state.state == STATE_ON assert state.state == STATE_ON
assert state.attributes.get("rgb_color") == (255, 127, 0) assert state.attributes.get("rgb_color") == (255, 128, 0)
# Set half brightness # Set half brightness
await common.async_turn_on(hass, "light.test", brightness=128) await common.async_turn_on(hass, "light.test", brightness=128)
@ -528,7 +528,7 @@ async def test_sending_mqtt_commands_and_optimistic(
mqtt_mock.async_publish.reset_mock() mqtt_mock.async_publish.reset_mock()
state = hass.states.get("light.test") state = hass.states.get("light.test")
assert state.state == STATE_ON assert state.state == STATE_ON
assert state.attributes.get("rgb_color") == (0, 255, 127) assert state.attributes.get("rgb_color") == (0, 255, 128)
@pytest.mark.parametrize( @pytest.mark.parametrize(
@ -626,7 +626,7 @@ async def test_sending_mqtt_commands_non_optimistic_brightness_template(
# Full brightness - normalization of RGB values sent over MQTT # Full brightness - normalization of RGB values sent over MQTT
await common.async_turn_on(hass, "light.test", rgb_color=(128, 64, 0)) await common.async_turn_on(hass, "light.test", rgb_color=(128, 64, 0))
mqtt_mock.async_publish.assert_called_once_with( mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set", "on,,,255-127-0,30.0-100.0", 0, False "test_light_rgb/set", "on,,,255-128-0,30.0-100.0", 0, False
) )
mqtt_mock.async_publish.reset_mock() mqtt_mock.async_publish.reset_mock()
@ -648,7 +648,7 @@ async def test_sending_mqtt_commands_non_optimistic_brightness_template(
# Half brightness - normalization but no scaling of RGB values sent over MQTT # Half brightness - normalization but no scaling of RGB values sent over MQTT
await common.async_turn_on(hass, "light.test", rgb_color=(0, 32, 16)) await common.async_turn_on(hass, "light.test", rgb_color=(0, 32, 16))
mqtt_mock.async_publish.assert_called_once_with( mqtt_mock.async_publish.assert_called_once_with(
"test_light_rgb/set", "on,,,0-255-127,150.0-100.0", 0, False "test_light_rgb/set", "on,,,0-255-128,150.0-100.0", 0, False
) )
mqtt_mock.async_publish.reset_mock() mqtt_mock.async_publish.reset_mock()
state = hass.states.get("light.test") state = hass.states.get("light.test")

View File

@ -52,13 +52,13 @@ async def test_light(
{"entity_id": entity_id, ATTR_HS_COLOR: [300, 70]}, {"entity_id": entity_id, ATTR_HS_COLOR: [300, 70]},
) )
await hass.async_block_till_done() await hass.async_block_till_done()
vera_device.set_color.assert_called_with((255, 76, 255)) vera_device.set_color.assert_called_with((255, 77, 255))
vera_device.is_switched_on.return_value = True vera_device.is_switched_on.return_value = True
vera_device.get_color.return_value = (255, 76, 255) vera_device.get_color.return_value = (255, 77, 255)
update_callback(vera_device) update_callback(vera_device)
await hass.async_block_till_done() await hass.async_block_till_done()
assert hass.states.get(entity_id).state == "on" assert hass.states.get(entity_id).state == "on"
assert hass.states.get(entity_id).attributes["hs_color"] == (300.0, 70.196) assert hass.states.get(entity_id).attributes["hs_color"] == (300.0, 69.804)
await hass.services.async_call( await hass.services.async_call(
"light", "light",

View File

@ -946,8 +946,8 @@ async def test_device_types(
"color_mode": "color_temp", "color_mode": "color_temp",
"supported_color_modes": ["color_temp", "hs", "rgb"], "supported_color_modes": ["color_temp", "hs", "rgb"],
"hs_color": (26.812, 34.87), "hs_color": (26.812, 34.87),
"rgb_color": (255, 205, 166), "rgb_color": (255, 206, 166),
"xy_color": (0.421, 0.364), "xy_color": (0.42, 0.365),
}, },
nightlight_entity_properties={ nightlight_entity_properties={
"supported_features": 0, "supported_features": 0,
@ -959,8 +959,8 @@ async def test_device_types(
"effect": None, "effect": None,
"supported_features": SUPPORT_YEELIGHT, "supported_features": SUPPORT_YEELIGHT,
"hs_color": (28.401, 100.0), "hs_color": (28.401, 100.0),
"rgb_color": (255, 120, 0), "rgb_color": (255, 121, 0),
"xy_color": (0.621, 0.367), "xy_color": (0.62, 0.368),
"min_color_temp_kelvin": model_specs["color_temp"]["min"], "min_color_temp_kelvin": model_specs["color_temp"]["min"],
"max_color_temp_kelvin": color_temperature_mired_to_kelvin( "max_color_temp_kelvin": color_temperature_mired_to_kelvin(
color_temperature_kelvin_to_mired(model_specs["color_temp"]["max"]) color_temperature_kelvin_to_mired(model_specs["color_temp"]["max"])
@ -1191,8 +1191,8 @@ async def test_device_types(
"color_mode": "color_temp", "color_mode": "color_temp",
"supported_color_modes": ["color_temp"], "supported_color_modes": ["color_temp"],
"hs_color": (26.812, 34.87), "hs_color": (26.812, 34.87),
"rgb_color": (255, 205, 166), "rgb_color": (255, 206, 166),
"xy_color": (0.421, 0.364), "xy_color": (0.42, 0.365),
}, },
nightlight_entity_properties={ nightlight_entity_properties={
"supported_features": 0, "supported_features": 0,
@ -1226,8 +1226,8 @@ async def test_device_types(
"color_mode": "color_temp", "color_mode": "color_temp",
"supported_color_modes": ["color_temp"], "supported_color_modes": ["color_temp"],
"hs_color": (28.391, 65.659), "hs_color": (28.391, 65.659),
"rgb_color": (255, 166, 87), "rgb_color": (255, 167, 88),
"xy_color": (0.526, 0.387), "xy_color": (0.524, 0.388),
}, },
) )
@ -1263,8 +1263,8 @@ async def test_device_types(
"color_mode": "color_temp", "color_mode": "color_temp",
"supported_color_modes": ["color_temp"], "supported_color_modes": ["color_temp"],
"hs_color": (26.812, 34.87), "hs_color": (26.812, 34.87),
"rgb_color": (255, 205, 166), "rgb_color": (255, 206, 166),
"xy_color": (0.421, 0.364), "xy_color": (0.42, 0.365),
}, },
nightlight_entity_properties={ nightlight_entity_properties={
"supported_features": 0, "supported_features": 0,
@ -1301,8 +1301,8 @@ async def test_device_types(
"color_mode": "color_temp", "color_mode": "color_temp",
"supported_color_modes": ["color_temp"], "supported_color_modes": ["color_temp"],
"hs_color": (28.391, 65.659), "hs_color": (28.391, 65.659),
"rgb_color": (255, 166, 87), "rgb_color": (255, 167, 88),
"xy_color": (0.526, 0.387), "xy_color": (0.524, 0.388),
}, },
) )
# Background light - color mode CT # Background light - color mode CT
@ -1326,8 +1326,8 @@ async def test_device_types(
"color_mode": "color_temp", "color_mode": "color_temp",
"supported_color_modes": ["color_temp", "hs", "rgb"], "supported_color_modes": ["color_temp", "hs", "rgb"],
"hs_color": (27.001, 19.243), "hs_color": (27.001, 19.243),
"rgb_color": (255, 228, 205), "rgb_color": (255, 228, 206),
"xy_color": (0.372, 0.35), "xy_color": (0.371, 0.349),
}, },
name=f"{UNIQUE_FRIENDLY_NAME} Ambilight", name=f"{UNIQUE_FRIENDLY_NAME} Ambilight",
entity_id=f"{ENTITY_LIGHT}_ambilight", entity_id=f"{ENTITY_LIGHT}_ambilight",

View File

@ -215,7 +215,7 @@ async def test_light_turn_on(hass: HomeAssistant, mock_light) -> None:
) )
await hass.async_block_till_done() await hass.async_block_till_done()
mock_set_color.assert_called_with(19, 17, 25) mock_set_color.assert_called_with(20, 17, 25)
with patch.object(mock_light, "set_color") as mock_set_color: with patch.object(mock_light, "set_color") as mock_set_color:
await hass.services.async_call( await hass.services.async_call(
@ -226,7 +226,7 @@ async def test_light_turn_on(hass: HomeAssistant, mock_light) -> None:
) )
await hass.async_block_till_done() await hass.async_block_till_done()
mock_set_color.assert_called_with(220, 201, 110) mock_set_color.assert_called_with(220, 202, 110)
with patch.object( with patch.object(
mock_light, mock_light,
@ -246,7 +246,7 @@ async def test_light_turn_on(hass: HomeAssistant, mock_light) -> None:
) )
await hass.async_block_till_done() await hass.async_block_till_done()
mock_set_color.assert_called_with(75, 68, 37) mock_set_color.assert_called_with(75, 69, 38)
with patch.object(mock_light, "set_color") as mock_set_color: with patch.object(mock_light, "set_color") as mock_set_color:
await hass.services.async_call( await hass.services.async_call(
@ -261,7 +261,7 @@ async def test_light_turn_on(hass: HomeAssistant, mock_light) -> None:
) )
await hass.async_block_till_done() await hass.async_block_till_done()
mock_set_color.assert_called_with(162, 200, 50) mock_set_color.assert_called_with(163, 200, 50)
async def test_light_turn_off(hass: HomeAssistant, mock_light) -> None: async def test_light_turn_off(hass: HomeAssistant, mock_light) -> None:
@ -352,6 +352,6 @@ async def test_light_update(hass: HomeAssistant, mock_light) -> None:
ATTR_COLOR_MODE: ColorMode.HS, ATTR_COLOR_MODE: ColorMode.HS,
ATTR_BRIGHTNESS: 220, ATTR_BRIGHTNESS: 220,
ATTR_HS_COLOR: (261.429, 31.818), ATTR_HS_COLOR: (261.429, 31.818),
ATTR_RGB_COLOR: (202, 173, 255), ATTR_RGB_COLOR: (203, 174, 255),
ATTR_XY_COLOR: (0.291, 0.232), ATTR_XY_COLOR: (0.292, 0.234),
} }

View File

@ -181,7 +181,7 @@ def test_color_hs_to_xy() -> None:
assert color_util.color_hs_to_xy(350, 12.5) == (0.356, 0.321) assert color_util.color_hs_to_xy(350, 12.5) == (0.356, 0.321)
assert color_util.color_hs_to_xy(140, 50) == (0.229, 0.474) assert color_util.color_hs_to_xy(140, 50) == (0.23, 0.474)
assert color_util.color_hs_to_xy(0, 40) == (0.474, 0.317) assert color_util.color_hs_to_xy(0, 40) == (0.474, 0.317)