Migrate homekit_controller light to color_mode (#69261)
This commit is contained in:
parent
2abe551eef
commit
7c0b0f7cc1
8 changed files with 128 additions and 30 deletions
|
@ -10,9 +10,10 @@ from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS,
|
ATTR_BRIGHTNESS,
|
||||||
ATTR_COLOR_TEMP,
|
ATTR_COLOR_TEMP,
|
||||||
ATTR_HS_COLOR,
|
ATTR_HS_COLOR,
|
||||||
SUPPORT_BRIGHTNESS,
|
COLOR_MODE_BRIGHTNESS,
|
||||||
SUPPORT_COLOR,
|
COLOR_MODE_COLOR_TEMP,
|
||||||
SUPPORT_COLOR_TEMP,
|
COLOR_MODE_HS,
|
||||||
|
COLOR_MODE_ONOFF,
|
||||||
LightEntity,
|
LightEntity,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
@ -79,23 +80,43 @@ class HomeKitLight(HomeKitEntity, LightEntity):
|
||||||
return self.service.value(CharacteristicsTypes.COLOR_TEMPERATURE)
|
return self.service.value(CharacteristicsTypes.COLOR_TEMPERATURE)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self) -> int:
|
def color_mode(self) -> str:
|
||||||
"""Flag supported features."""
|
"""Return the color mode of the light."""
|
||||||
features = 0
|
# aiohomekit does not keep track of the light's color mode, report
|
||||||
|
# hs for light supporting both hs and ct
|
||||||
if self.service.has(CharacteristicsTypes.BRIGHTNESS):
|
if self.service.has(CharacteristicsTypes.HUE) or self.service.has(
|
||||||
features |= SUPPORT_BRIGHTNESS
|
CharacteristicsTypes.SATURATION
|
||||||
|
):
|
||||||
|
return COLOR_MODE_HS
|
||||||
|
|
||||||
if self.service.has(CharacteristicsTypes.COLOR_TEMPERATURE):
|
if self.service.has(CharacteristicsTypes.COLOR_TEMPERATURE):
|
||||||
features |= SUPPORT_COLOR_TEMP
|
return COLOR_MODE_COLOR_TEMP
|
||||||
|
|
||||||
if self.service.has(CharacteristicsTypes.HUE):
|
if self.service.has(CharacteristicsTypes.BRIGHTNESS):
|
||||||
features |= SUPPORT_COLOR
|
return COLOR_MODE_BRIGHTNESS
|
||||||
|
|
||||||
if self.service.has(CharacteristicsTypes.SATURATION):
|
return COLOR_MODE_ONOFF
|
||||||
features |= SUPPORT_COLOR
|
|
||||||
|
|
||||||
return features
|
@property
|
||||||
|
def supported_color_modes(self) -> set[str] | None:
|
||||||
|
"""Flag supported color modes."""
|
||||||
|
color_modes = set()
|
||||||
|
|
||||||
|
if self.service.has(CharacteristicsTypes.HUE) or self.service.has(
|
||||||
|
CharacteristicsTypes.SATURATION
|
||||||
|
):
|
||||||
|
color_modes.add(COLOR_MODE_HS)
|
||||||
|
|
||||||
|
if self.service.has(CharacteristicsTypes.COLOR_TEMPERATURE):
|
||||||
|
color_modes.add(COLOR_MODE_COLOR_TEMP)
|
||||||
|
|
||||||
|
if not color_modes and self.service.has(CharacteristicsTypes.BRIGHTNESS):
|
||||||
|
color_modes.add(COLOR_MODE_BRIGHTNESS)
|
||||||
|
|
||||||
|
if not color_modes:
|
||||||
|
color_modes.add(COLOR_MODE_ONOFF)
|
||||||
|
|
||||||
|
return color_modes
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the specified light on."""
|
"""Turn the specified light on."""
|
||||||
|
|
|
@ -8,7 +8,6 @@ from homeassistant.components.alarm_control_panel import (
|
||||||
SUPPORT_ALARM_ARM_HOME,
|
SUPPORT_ALARM_ARM_HOME,
|
||||||
SUPPORT_ALARM_ARM_NIGHT,
|
SUPPORT_ALARM_ARM_NIGHT,
|
||||||
)
|
)
|
||||||
from homeassistant.components.light import SUPPORT_BRIGHTNESS, SUPPORT_COLOR
|
|
||||||
from homeassistant.components.number import NumberMode
|
from homeassistant.components.number import NumberMode
|
||||||
from homeassistant.helpers.entity import EntityCategory
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
|
|
||||||
|
@ -52,7 +51,7 @@ async def test_aqara_gateway_setup(hass):
|
||||||
"light.aqara_hub_1563",
|
"light.aqara_hub_1563",
|
||||||
friendly_name="Aqara Hub-1563",
|
friendly_name="Aqara Hub-1563",
|
||||||
unique_id="homekit-0000000123456789-65792",
|
unique_id="homekit-0000000123456789-65792",
|
||||||
supported_features=SUPPORT_BRIGHTNESS | SUPPORT_COLOR,
|
supported_features=0,
|
||||||
capabilities={"supported_color_modes": ["hs"]},
|
capabilities={"supported_color_modes": ["hs"]},
|
||||||
state="off",
|
state="off",
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
"""Make sure that an Arlo Baby can be setup."""
|
"""Make sure that an Arlo Baby can be setup."""
|
||||||
|
|
||||||
from homeassistant.components.light import SUPPORT_BRIGHTNESS, SUPPORT_COLOR
|
|
||||||
from homeassistant.components.sensor import SensorStateClass
|
from homeassistant.components.sensor import SensorStateClass
|
||||||
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS
|
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS
|
||||||
|
|
||||||
|
@ -75,7 +74,7 @@ async def test_arlo_baby_setup(hass):
|
||||||
entity_id="light.arlobabya0",
|
entity_id="light.arlobabya0",
|
||||||
unique_id="homekit-00A0000000000-1100",
|
unique_id="homekit-00A0000000000-1100",
|
||||||
friendly_name="ArloBabyA0",
|
friendly_name="ArloBabyA0",
|
||||||
supported_features=SUPPORT_BRIGHTNESS | SUPPORT_COLOR,
|
supported_features=0,
|
||||||
capabilities={"supported_color_modes": ["hs"]},
|
capabilities={"supported_color_modes": ["hs"]},
|
||||||
state="off",
|
state="off",
|
||||||
),
|
),
|
||||||
|
|
|
@ -8,7 +8,6 @@ from aiohomekit.model import CharacteristicsTypes, ServicesTypes
|
||||||
from aiohomekit.testing import FakePairing
|
from aiohomekit.testing import FakePairing
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from homeassistant.components.light import SUPPORT_BRIGHTNESS, SUPPORT_COLOR
|
|
||||||
from homeassistant.helpers.entity import EntityCategory
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
|
@ -47,7 +46,7 @@ async def test_koogeek_ls1_setup(hass):
|
||||||
entity_id="light.koogeek_ls1_20833f",
|
entity_id="light.koogeek_ls1_20833f",
|
||||||
friendly_name="Koogeek-LS1-20833F",
|
friendly_name="Koogeek-LS1-20833F",
|
||||||
unique_id="homekit-AAAA011111111111-7",
|
unique_id="homekit-AAAA011111111111-7",
|
||||||
supported_features=SUPPORT_BRIGHTNESS | SUPPORT_COLOR,
|
supported_features=0,
|
||||||
capabilities={"supported_color_modes": ["hs"]},
|
capabilities={"supported_color_modes": ["hs"]},
|
||||||
state="off",
|
state="off",
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
"""Make sure that Mysa Living is enumerated properly."""
|
"""Make sure that Mysa Living is enumerated properly."""
|
||||||
|
|
||||||
from homeassistant.components.climate import SUPPORT_TARGET_TEMPERATURE
|
from homeassistant.components.climate import SUPPORT_TARGET_TEMPERATURE
|
||||||
from homeassistant.components.light import SUPPORT_BRIGHTNESS
|
|
||||||
from homeassistant.components.sensor import SensorStateClass
|
from homeassistant.components.sensor import SensorStateClass
|
||||||
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS
|
from homeassistant.const import PERCENTAGE, TEMP_CELSIUS
|
||||||
|
|
||||||
|
@ -64,7 +63,7 @@ async def test_mysa_living_setup(hass):
|
||||||
entity_id="light.mysa_85dda9",
|
entity_id="light.mysa_85dda9",
|
||||||
friendly_name="Mysa-85dda9",
|
friendly_name="Mysa-85dda9",
|
||||||
unique_id="homekit-AAAAAAA000-40",
|
unique_id="homekit-AAAAAAA000-40",
|
||||||
supported_features=SUPPORT_BRIGHTNESS,
|
supported_features=0,
|
||||||
capabilities={"supported_color_modes": ["brightness"]},
|
capabilities={"supported_color_modes": ["brightness"]},
|
||||||
state="off",
|
state="off",
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
"""Make sure that Vocolinc Flowerbud is enumerated properly."""
|
"""Make sure that Vocolinc Flowerbud is enumerated properly."""
|
||||||
|
|
||||||
from homeassistant.components.humidifier.const import SUPPORT_MODES
|
from homeassistant.components.humidifier.const import SUPPORT_MODES
|
||||||
from homeassistant.components.light import SUPPORT_BRIGHTNESS, SUPPORT_COLOR
|
|
||||||
from homeassistant.components.number import NumberMode
|
from homeassistant.components.number import NumberMode
|
||||||
from homeassistant.components.sensor import SensorStateClass
|
from homeassistant.components.sensor import SensorStateClass
|
||||||
from homeassistant.const import PERCENTAGE
|
from homeassistant.const import PERCENTAGE
|
||||||
|
@ -50,7 +49,7 @@ async def test_vocolinc_flowerbud_setup(hass):
|
||||||
entity_id="light.vocolinc_flowerbud_0d324b",
|
entity_id="light.vocolinc_flowerbud_0d324b",
|
||||||
friendly_name="VOCOlinc-Flowerbud-0d324b",
|
friendly_name="VOCOlinc-Flowerbud-0d324b",
|
||||||
unique_id="homekit-AM01121849000327-9",
|
unique_id="homekit-AM01121849000327-9",
|
||||||
supported_features=SUPPORT_BRIGHTNESS | SUPPORT_COLOR,
|
supported_features=0,
|
||||||
capabilities={"supported_color_modes": ["hs"]},
|
capabilities={"supported_color_modes": ["hs"]},
|
||||||
state="on",
|
state="on",
|
||||||
),
|
),
|
||||||
|
|
|
@ -250,7 +250,7 @@ async def test_config_entry(hass: HomeAssistant, hass_client: ClientSession, utc
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"supported_color_modes": ["hs"],
|
"supported_color_modes": ["hs"],
|
||||||
"friendly_name": "Koogeek-LS1-20833F",
|
"friendly_name": "Koogeek-LS1-20833F",
|
||||||
"supported_features": 17,
|
"supported_features": 0,
|
||||||
},
|
},
|
||||||
"last_changed": "2023-01-01T00:00:00+00:00",
|
"last_changed": "2023-01-01T00:00:00+00:00",
|
||||||
"last_updated": "2023-01-01T00:00:00+00:00",
|
"last_updated": "2023-01-01T00:00:00+00:00",
|
||||||
|
@ -520,7 +520,7 @@ async def test_device(hass: HomeAssistant, hass_client: ClientSession, utcnow):
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"supported_color_modes": ["hs"],
|
"supported_color_modes": ["hs"],
|
||||||
"friendly_name": "Koogeek-LS1-20833F",
|
"friendly_name": "Koogeek-LS1-20833F",
|
||||||
"supported_features": 17,
|
"supported_features": 0,
|
||||||
},
|
},
|
||||||
"last_changed": "2023-01-01T00:00:00+00:00",
|
"last_changed": "2023-01-01T00:00:00+00:00",
|
||||||
"last_updated": "2023-01-01T00:00:00+00:00",
|
"last_updated": "2023-01-01T00:00:00+00:00",
|
||||||
|
|
|
@ -3,7 +3,14 @@ from aiohomekit.model.characteristics import CharacteristicsTypes
|
||||||
from aiohomekit.model.services import ServicesTypes
|
from aiohomekit.model.services import ServicesTypes
|
||||||
|
|
||||||
from homeassistant.components.homekit_controller.const import KNOWN_DEVICES
|
from homeassistant.components.homekit_controller.const import KNOWN_DEVICES
|
||||||
from homeassistant.const import STATE_UNAVAILABLE
|
from homeassistant.components.light import (
|
||||||
|
ATTR_COLOR_MODE,
|
||||||
|
ATTR_SUPPORTED_COLOR_MODES,
|
||||||
|
COLOR_MODE_BRIGHTNESS,
|
||||||
|
COLOR_MODE_COLOR_TEMP,
|
||||||
|
COLOR_MODE_HS,
|
||||||
|
)
|
||||||
|
from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_UNAVAILABLE
|
||||||
|
|
||||||
from tests.components.homekit_controller.common import setup_test_component
|
from tests.components.homekit_controller.common import setup_test_component
|
||||||
|
|
||||||
|
@ -98,13 +105,79 @@ async def test_switch_change_light_state_color_temp(hass, utcnow):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_switch_read_light_state(hass, utcnow):
|
async def test_switch_read_light_state_dimmer(hass, utcnow):
|
||||||
|
"""Test that we can read the state of a HomeKit light accessory."""
|
||||||
|
helper = await setup_test_component(hass, create_lightbulb_service)
|
||||||
|
|
||||||
|
# Initial state is that the light is off
|
||||||
|
state = await helper.poll_and_get_state()
|
||||||
|
assert state.state == "off"
|
||||||
|
assert ATTR_COLOR_MODE not in state.attributes
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [COLOR_MODE_BRIGHTNESS]
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
|
||||||
|
# Simulate that someone switched on the device in the real world not via HA
|
||||||
|
state = await helper.async_update(
|
||||||
|
ServicesTypes.LIGHTBULB,
|
||||||
|
{
|
||||||
|
CharacteristicsTypes.ON: True,
|
||||||
|
CharacteristicsTypes.BRIGHTNESS: 100,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert state.state == "on"
|
||||||
|
assert state.attributes["brightness"] == 255
|
||||||
|
assert state.attributes[ATTR_COLOR_MODE] == COLOR_MODE_BRIGHTNESS
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [COLOR_MODE_BRIGHTNESS]
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
|
||||||
|
# Simulate that device switched off in the real world not via HA
|
||||||
|
state = await helper.async_update(
|
||||||
|
ServicesTypes.LIGHTBULB,
|
||||||
|
{
|
||||||
|
CharacteristicsTypes.ON: False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert state.state == "off"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_switch_push_light_state_dimmer(hass, utcnow):
|
||||||
|
"""Test that we can read the state of a HomeKit light accessory."""
|
||||||
|
helper = await setup_test_component(hass, create_lightbulb_service)
|
||||||
|
|
||||||
|
# Initial state is that the light is off
|
||||||
|
state = hass.states.get(LIGHT_BULB_ENTITY_ID)
|
||||||
|
assert state.state == "off"
|
||||||
|
|
||||||
|
state = await helper.async_update(
|
||||||
|
ServicesTypes.LIGHTBULB,
|
||||||
|
{
|
||||||
|
CharacteristicsTypes.ON: True,
|
||||||
|
CharacteristicsTypes.BRIGHTNESS: 100,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert state.state == "on"
|
||||||
|
assert state.attributes["brightness"] == 255
|
||||||
|
|
||||||
|
# Simulate that device switched off in the real world not via HA
|
||||||
|
state = await helper.async_update(
|
||||||
|
ServicesTypes.LIGHTBULB,
|
||||||
|
{
|
||||||
|
CharacteristicsTypes.ON: False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert state.state == "off"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_switch_read_light_state_hs(hass, utcnow):
|
||||||
"""Test that we can read the state of a HomeKit light accessory."""
|
"""Test that we can read the state of a HomeKit light accessory."""
|
||||||
helper = await setup_test_component(hass, create_lightbulb_service_with_hs)
|
helper = await setup_test_component(hass, create_lightbulb_service_with_hs)
|
||||||
|
|
||||||
# Initial state is that the light is off
|
# Initial state is that the light is off
|
||||||
state = await helper.poll_and_get_state()
|
state = await helper.poll_and_get_state()
|
||||||
assert state.state == "off"
|
assert state.state == "off"
|
||||||
|
assert ATTR_COLOR_MODE not in state.attributes
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [COLOR_MODE_HS]
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
|
||||||
# Simulate that someone switched on the device in the real world not via HA
|
# Simulate that someone switched on the device in the real world not via HA
|
||||||
state = await helper.async_update(
|
state = await helper.async_update(
|
||||||
|
@ -119,6 +192,9 @@ async def test_switch_read_light_state(hass, utcnow):
|
||||||
assert state.state == "on"
|
assert state.state == "on"
|
||||||
assert state.attributes["brightness"] == 255
|
assert state.attributes["brightness"] == 255
|
||||||
assert state.attributes["hs_color"] == (4, 5)
|
assert state.attributes["hs_color"] == (4, 5)
|
||||||
|
assert state.attributes[ATTR_COLOR_MODE] == COLOR_MODE_HS
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [COLOR_MODE_HS]
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
|
||||||
# Simulate that device switched off in the real world not via HA
|
# Simulate that device switched off in the real world not via HA
|
||||||
state = await helper.async_update(
|
state = await helper.async_update(
|
||||||
|
@ -130,7 +206,7 @@ async def test_switch_read_light_state(hass, utcnow):
|
||||||
assert state.state == "off"
|
assert state.state == "off"
|
||||||
|
|
||||||
|
|
||||||
async def test_switch_push_light_state(hass, utcnow):
|
async def test_switch_push_light_state_hs(hass, utcnow):
|
||||||
"""Test that we can read the state of a HomeKit light accessory."""
|
"""Test that we can read the state of a HomeKit light accessory."""
|
||||||
helper = await setup_test_component(hass, create_lightbulb_service_with_hs)
|
helper = await setup_test_component(hass, create_lightbulb_service_with_hs)
|
||||||
|
|
||||||
|
@ -168,6 +244,9 @@ async def test_switch_read_light_state_color_temp(hass, utcnow):
|
||||||
# Initial state is that the light is off
|
# Initial state is that the light is off
|
||||||
state = await helper.poll_and_get_state()
|
state = await helper.poll_and_get_state()
|
||||||
assert state.state == "off"
|
assert state.state == "off"
|
||||||
|
assert ATTR_COLOR_MODE not in state.attributes
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [COLOR_MODE_COLOR_TEMP]
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
|
||||||
# Simulate that someone switched on the device in the real world not via HA
|
# Simulate that someone switched on the device in the real world not via HA
|
||||||
state = await helper.async_update(
|
state = await helper.async_update(
|
||||||
|
@ -181,6 +260,9 @@ async def test_switch_read_light_state_color_temp(hass, utcnow):
|
||||||
assert state.state == "on"
|
assert state.state == "on"
|
||||||
assert state.attributes["brightness"] == 255
|
assert state.attributes["brightness"] == 255
|
||||||
assert state.attributes["color_temp"] == 400
|
assert state.attributes["color_temp"] == 400
|
||||||
|
assert state.attributes[ATTR_COLOR_MODE] == COLOR_MODE_COLOR_TEMP
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [COLOR_MODE_COLOR_TEMP]
|
||||||
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
|
||||||
|
|
||||||
|
|
||||||
async def test_switch_push_light_state_color_temp(hass, utcnow):
|
async def test_switch_push_light_state_color_temp(hass, utcnow):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue