Fix matter color temperature light (#87677)

* Adds tests for each matter light type and fixes small issue with color temperature lights not being detected properly

* Removes commented out code

* Changed matter light tests to pytest.mark.parametrize to reduce duplicate code
This commit is contained in:
Arturo 2023-02-08 16:41:04 -06:00 committed by GitHub
parent 1a7c99382c
commit 1c02f19d9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 2320 additions and 142 deletions

View File

@ -421,6 +421,7 @@ DEVICE_ENTITY: dict[
subscribe_attributes=( subscribe_attributes=(
clusters.OnOff.Attributes.OnOff, clusters.OnOff.Attributes.OnOff,
clusters.LevelControl.Attributes.CurrentLevel, clusters.LevelControl.Attributes.CurrentLevel,
clusters.ColorControl.Attributes.ColorMode,
clusters.ColorControl.Attributes.ColorTemperatureMireds, clusters.ColorControl.Attributes.ColorTemperatureMireds,
), ),
), ),

File diff suppressed because it is too large Load Diff

View File

@ -2,9 +2,9 @@
from unittest.mock import MagicMock, call from unittest.mock import MagicMock, call
from chip.clusters import Objects as clusters from chip.clusters import Objects as clusters
from matter_server.common.models.node import MatterNode
import pytest import pytest
from homeassistant.components.light import ColorMode
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from .common import ( from .common import (
@ -14,29 +14,69 @@ from .common import (
) )
@pytest.fixture(name="light_node") @pytest.mark.parametrize(
async def light_node_fixture( "fixture, entity_id",
hass: HomeAssistant, matter_client: MagicMock [
) -> MatterNode: ("extended-color-light", "light.mock_extended_color_light"),
"""Fixture for a light node.""" ("color-temperature-light", "light.mock_color_temperature_light"),
return await setup_integration_with_node_fixture( ("dimmable-light", "light.mock_dimmable_light"),
hass, "extended-color-light", matter_client ("onoff-light", "light.mock_onoff_light"),
) ],
)
async def test_on_off_light(
async def test_turn_on(
hass: HomeAssistant, hass: HomeAssistant,
matter_client: MagicMock, matter_client: MagicMock,
light_node: MatterNode, fixture: str,
entity_id: str,
) -> None: ) -> None:
"""Test turning on a light.""" """Test an on/off light."""
# OnOff test light_node = await setup_integration_with_node_fixture(
hass,
fixture,
matter_client,
)
# Test that the light is off
set_node_attribute(light_node, 1, 6, 0, False)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get(entity_id)
assert state is not None
assert state.state == "off"
# Test that the light is on
set_node_attribute(light_node, 1, 6, 0, True)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get(entity_id)
assert state is not None
assert state.state == "on"
# Turn the light off
await hass.services.async_call(
"light",
"turn_off",
{
"entity_id": entity_id,
},
blocking=True,
)
assert matter_client.send_device_command.call_count == 1
assert matter_client.send_device_command.call_args == call(
node_id=light_node.node_id,
endpoint=1,
command=clusters.OnOff.Commands.Off(),
)
matter_client.send_device_command.reset_mock()
# Turn the light on
await hass.services.async_call( await hass.services.async_call(
"light", "light",
"turn_on", "turn_on",
{ {
"entity_id": "light.mock_extended_color_light", "entity_id": entity_id,
}, },
blocking=True, blocking=True,
) )
@ -49,12 +89,44 @@ async def test_turn_on(
) )
matter_client.send_device_command.reset_mock() matter_client.send_device_command.reset_mock()
# Brightness test
@pytest.mark.parametrize(
"fixture, entity_id",
[
("extended-color-light", "light.mock_extended_color_light"),
("color-temperature-light", "light.mock_color_temperature_light"),
("dimmable-light", "light.mock_dimmable_light"),
],
)
async def test_dimmable_light(
hass: HomeAssistant,
matter_client: MagicMock,
fixture: str,
entity_id: str,
) -> None:
"""Test a dimmable light."""
light_node = await setup_integration_with_node_fixture(
hass,
fixture,
matter_client,
)
# Test that the light brightness is 50 (out of 254)
set_node_attribute(light_node, 1, 8, 0, 50)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get(entity_id)
assert state is not None
assert state.state == "on"
assert state.attributes["brightness"] == 49
# Change brightness
await hass.services.async_call( await hass.services.async_call(
"light", "light",
"turn_on", "turn_on",
{ {
"entity_id": "light.mock_extended_color_light", "entity_id": entity_id,
"brightness": 128, "brightness": 128,
}, },
blocking=True, blocking=True,
@ -71,77 +143,46 @@ async def test_turn_on(
) )
matter_client.send_device_command.reset_mock() matter_client.send_device_command.reset_mock()
# HS Color test
@pytest.mark.parametrize(
"fixture, entity_id",
[
("extended-color-light", "light.mock_extended_color_light"),
("color-temperature-light", "light.mock_color_temperature_light"),
],
)
async def test_color_temperature_light(
hass: HomeAssistant,
matter_client: MagicMock,
fixture: str,
entity_id: str,
) -> None:
"""Test a color temperature light."""
light_node = await setup_integration_with_node_fixture(
hass,
fixture,
matter_client,
)
# Test that the light color temperature is 3000 (out of 50000)
set_node_attribute(light_node, 1, 768, 8, 2)
set_node_attribute(light_node, 1, 768, 7, 3000)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get(entity_id)
assert state is not None
assert state.state == "on"
assert state.attributes["color_mode"] == ColorMode.COLOR_TEMP
assert state.attributes["color_temp"] == 3003
# Change color temperature
await hass.services.async_call( await hass.services.async_call(
"light", "light",
"turn_on", "turn_on",
{ {
"entity_id": "light.mock_extended_color_light", "entity_id": entity_id,
"hs_color": [0, 0], "color_temp": 3000,
},
blocking=True,
)
assert matter_client.send_device_command.call_count == 2
matter_client.send_device_command.assert_has_calls(
[
call(
node_id=light_node.node_id,
endpoint=1,
command=clusters.ColorControl.Commands.MoveToHueAndSaturation(
hue=0,
saturation=0,
transitionTime=0,
),
),
call(
node_id=light_node.node_id,
endpoint=1,
command=clusters.OnOff.Commands.On(),
),
]
)
matter_client.send_device_command.reset_mock()
# XY Color test
await hass.services.async_call(
"light",
"turn_on",
{
"entity_id": "light.mock_extended_color_light",
"xy_color": [0.5, 0.5],
},
blocking=True,
)
assert matter_client.send_device_command.call_count == 2
matter_client.send_device_command.assert_has_calls(
[
call(
node_id=light_node.node_id,
endpoint=1,
command=clusters.ColorControl.Commands.MoveToColor(
colorX=(0.5 * 65536),
colorY=(0.5 * 65536),
transitionTime=0,
),
),
call(
node_id=light_node.node_id,
endpoint=1,
command=clusters.OnOff.Commands.On(),
),
]
)
matter_client.send_device_command.reset_mock()
# Color Temperature test
await hass.services.async_call(
"light",
"turn_on",
{
"entity_id": "light.mock_extended_color_light",
"color_temp": 300,
}, },
blocking=True, blocking=True,
) )
@ -153,7 +194,7 @@ async def test_turn_on(
node_id=light_node.node_id, node_id=light_node.node_id,
endpoint=1, endpoint=1,
command=clusters.ColorControl.Commands.MoveToColorTemperature( command=clusters.ColorControl.Commands.MoveToColorTemperature(
colorTemperature=300, colorTemperature=3003,
transitionTime=0, transitionTime=0,
), ),
), ),
@ -166,81 +207,107 @@ async def test_turn_on(
) )
matter_client.send_device_command.reset_mock() matter_client.send_device_command.reset_mock()
state = hass.states.get("light.mock_extended_color_light")
assert state
assert state.state == "on"
# HS Color Test @pytest.mark.parametrize(
set_node_attribute(light_node, 1, 768, 8, 0) "fixture, entity_id",
set_node_attribute(light_node, 1, 768, 1, 50) [
set_node_attribute(light_node, 1, 768, 0, 100) ("extended-color-light", "light.mock_extended_color_light"),
await trigger_subscription_callback(hass, matter_client) ],
)
async def test_extended_color_light(
hass: HomeAssistant,
matter_client: MagicMock,
fixture: str,
entity_id: str,
) -> None:
"""Test an extended color light."""
state = hass.states.get("light.mock_extended_color_light") light_node = await setup_integration_with_node_fixture(
assert state hass,
assert state.attributes["color_mode"] == "hs" fixture,
assert state.attributes["hs_color"] == (141.732, 19.685) matter_client,
)
# XY Color Test # Test that the XY color changes
set_node_attribute(light_node, 1, 768, 8, 1) set_node_attribute(light_node, 1, 768, 8, 1)
set_node_attribute(light_node, 1, 768, 3, 50) set_node_attribute(light_node, 1, 768, 3, 50)
set_node_attribute(light_node, 1, 768, 4, 100) set_node_attribute(light_node, 1, 768, 4, 100)
await trigger_subscription_callback(hass, matter_client) await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("light.mock_extended_color_light") state = hass.states.get(entity_id)
assert state assert state is not None
assert state.attributes["color_mode"] == "xy" assert state.state == "on"
assert state.attributes["color_mode"] == ColorMode.XY
assert state.attributes["xy_color"] == (0.0007630, 0.001526) assert state.attributes["xy_color"] == (0.0007630, 0.001526)
# Color Temperature Test # Test that the HS color changes
set_node_attribute(light_node, 1, 768, 8, 2) set_node_attribute(light_node, 1, 768, 8, 0)
set_node_attribute(light_node, 1, 768, 7, 100) set_node_attribute(light_node, 1, 768, 1, 50)
set_node_attribute(light_node, 1, 768, 0, 100)
await trigger_subscription_callback(hass, matter_client) await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("light.mock_extended_color_light") state = hass.states.get(entity_id)
assert state assert state is not None
assert state.attributes["color_mode"] == "color_temp"
assert state.attributes["color_temp"] == 100
# Brightness state test
set_node_attribute(light_node, 1, 8, 0, 50)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("light.mock_extended_color_light")
assert state
assert state.attributes["brightness"] == 49
# Off state test
set_node_attribute(light_node, 1, 6, 0, False)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("light.mock_extended_color_light")
assert state
assert state.state == "off"
async def test_turn_off(
hass: HomeAssistant,
matter_client: MagicMock,
light_node: MatterNode,
) -> None:
"""Test turning off a light."""
state = hass.states.get("light.mock_extended_color_light")
assert state
assert state.state == "on" assert state.state == "on"
assert state.attributes["color_mode"] == ColorMode.HS
assert state.attributes["hs_color"] == (141.732, 19.685)
# Turn the light on with XY color
await hass.services.async_call( await hass.services.async_call(
"light", "light",
"turn_off", "turn_on",
{ {
"entity_id": "light.mock_extended_color_light", "entity_id": entity_id,
"xy_color": (0.5, 0.5),
}, },
blocking=True, blocking=True,
) )
assert matter_client.send_device_command.call_count == 1 assert matter_client.send_device_command.call_count == 2
assert matter_client.send_device_command.call_args == call( matter_client.send_device_command.assert_has_calls(
node_id=light_node.node_id, [
endpoint=1, call(
command=clusters.OnOff.Commands.Off(), node_id=light_node.node_id,
endpoint=1,
command=clusters.ColorControl.Commands.MoveToColor(
colorX=0.5 * 65536, colorY=0.5 * 65536, transitionTime=0
),
),
call(
node_id=light_node.node_id,
endpoint=1,
command=clusters.OnOff.Commands.On(),
),
]
) )
matter_client.send_device_command.reset_mock()
# Turn the light on with HS color
await hass.services.async_call(
"light",
"turn_on",
{
"entity_id": entity_id,
"hs_color": (0, 0),
},
blocking=True,
)
assert matter_client.send_device_command.call_count == 2
matter_client.send_device_command.assert_has_calls(
[
call(
node_id=light_node.node_id,
endpoint=1,
command=clusters.ColorControl.Commands.MoveToHueAndSaturation(
hue=0, saturation=0, transitionTime=0
),
),
call(
node_id=light_node.node_id,
endpoint=1,
command=clusters.OnOff.Commands.On(),
),
]
)
matter_client.send_device_command.reset_mock()