diff --git a/homeassistant/components/homekit/type_lights.py b/homeassistant/components/homekit/type_lights.py index cb3c97fadb4..88e21272a4f 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -6,11 +6,13 @@ from pyhap.const import CATEGORY_LIGHTBULB from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, + ATTR_COLOR_MODE, ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_MAX_MIREDS, ATTR_MIN_MIREDS, ATTR_SUPPORTED_COLOR_MODES, + COLOR_MODE_COLOR_TEMP, DOMAIN, brightness_supported, color_supported, @@ -18,23 +20,18 @@ from homeassistant.components.light import ( ) from homeassistant.const import ( ATTR_ENTITY_ID, - ATTR_SUPPORTED_FEATURES, SERVICE_TURN_OFF, SERVICE_TURN_ON, - STATE_OFF, STATE_ON, ) from homeassistant.core import callback -from homeassistant.util.color import ( - color_temperature_mired_to_kelvin, - color_temperature_to_hs, -) from .accessories import TYPES, HomeAccessory from .const import ( CHAR_BRIGHTNESS, CHAR_COLOR_TEMPERATURE, CHAR_HUE, + CHAR_NAME, CHAR_ON, CHAR_SATURATION, PROP_MAX_VALUE, @@ -58,59 +55,99 @@ class Light(HomeAccessory): """Initialize a new Light accessory object.""" super().__init__(*args, category=CATEGORY_LIGHTBULB) - self.chars = [] + self.chars_primary = [] + self.chars_secondary = [] + state = self.hass.states.get(self.entity_id) + attributes = state.attributes + color_modes = attributes.get(ATTR_SUPPORTED_COLOR_MODES) + self.is_color_supported = color_supported(color_modes) + self.is_color_temp_supported = color_temp_supported(color_modes) + self.color_and_temp_supported = ( + self.is_color_supported and self.is_color_temp_supported + ) + self.is_brightness_supported = brightness_supported(color_modes) - self._features = state.attributes.get(ATTR_SUPPORTED_FEATURES, 0) - self._color_modes = state.attributes.get(ATTR_SUPPORTED_COLOR_MODES) + if self.is_brightness_supported: + self.chars_primary.append(CHAR_BRIGHTNESS) - if brightness_supported(self._color_modes): - self.chars.append(CHAR_BRIGHTNESS) + if self.is_color_supported: + self.chars_primary.append(CHAR_HUE) + self.chars_primary.append(CHAR_SATURATION) - if color_supported(self._color_modes): - self.chars.append(CHAR_HUE) - self.chars.append(CHAR_SATURATION) - elif color_temp_supported(self._color_modes): - # ColorTemperature and Hue characteristic should not be - # exposed both. Both states are tracked separately in HomeKit, - # causing "source of truth" problems. - self.chars.append(CHAR_COLOR_TEMPERATURE) + if self.is_color_temp_supported: + if self.color_and_temp_supported: + self.chars_primary.append(CHAR_NAME) + self.chars_secondary.append(CHAR_NAME) + self.chars_secondary.append(CHAR_COLOR_TEMPERATURE) + if self.is_brightness_supported: + self.chars_secondary.append(CHAR_BRIGHTNESS) + else: + self.chars_primary.append(CHAR_COLOR_TEMPERATURE) - serv_light = self.add_preload_service(SERV_LIGHTBULB, self.chars) + serv_light_primary = self.add_preload_service( + SERV_LIGHTBULB, self.chars_primary + ) + serv_light_secondary = None + self.char_on_primary = serv_light_primary.configure_char(CHAR_ON, value=0) - self.char_on = serv_light.configure_char(CHAR_ON, value=0) + if self.color_and_temp_supported: + serv_light_secondary = self.add_preload_service( + SERV_LIGHTBULB, self.chars_secondary + ) + serv_light_primary.add_linked_service(serv_light_secondary) + serv_light_primary.configure_char(CHAR_NAME, value="RGB") + self.char_on_secondary = serv_light_secondary.configure_char( + CHAR_ON, value=0 + ) + serv_light_secondary.configure_char(CHAR_NAME, value="Temperature") - if CHAR_BRIGHTNESS in self.chars: + if self.is_brightness_supported: # Initial value is set to 100 because 0 is a special value (off). 100 is # an arbitrary non-zero value. It is updated immediately by async_update_state # to set to the correct initial value. - self.char_brightness = serv_light.configure_char(CHAR_BRIGHTNESS, value=100) + self.char_brightness_primary = serv_light_primary.configure_char( + CHAR_BRIGHTNESS, value=100 + ) + if self.chars_secondary: + self.char_brightness_secondary = serv_light_secondary.configure_char( + CHAR_BRIGHTNESS, value=100 + ) - if CHAR_COLOR_TEMPERATURE in self.chars: - min_mireds = self.hass.states.get(self.entity_id).attributes.get( - ATTR_MIN_MIREDS, 153 - ) - max_mireds = self.hass.states.get(self.entity_id).attributes.get( - ATTR_MAX_MIREDS, 500 - ) + if self.is_color_temp_supported: + min_mireds = attributes.get(ATTR_MIN_MIREDS, 153) + max_mireds = attributes.get(ATTR_MAX_MIREDS, 500) + serv_light = serv_light_secondary or serv_light_primary self.char_color_temperature = serv_light.configure_char( CHAR_COLOR_TEMPERATURE, value=min_mireds, properties={PROP_MIN_VALUE: min_mireds, PROP_MAX_VALUE: max_mireds}, ) - if CHAR_HUE in self.chars: - self.char_hue = serv_light.configure_char(CHAR_HUE, value=0) - - if CHAR_SATURATION in self.chars: - self.char_saturation = serv_light.configure_char(CHAR_SATURATION, value=75) + if self.is_color_supported: + self.char_hue = serv_light_primary.configure_char(CHAR_HUE, value=0) + self.char_saturation = serv_light_primary.configure_char( + CHAR_SATURATION, value=75 + ) self.async_update_state(state) - serv_light.setter_callback = self._set_chars + if self.color_and_temp_supported: + serv_light_primary.setter_callback = self._set_chars_primary + serv_light_secondary.setter_callback = self._set_chars_secondary + else: + serv_light_primary.setter_callback = self._set_chars - def _set_chars(self, char_values): - _LOGGER.debug("Light _set_chars: %s", char_values) + def _set_chars_primary(self, char_values): + """Primary service is RGB or W if only color or color temp is supported.""" + self._set_chars(char_values, True) + + def _set_chars_secondary(self, char_values): + """Secondary service is W if both color or color temp are supported.""" + self._set_chars(char_values, False) + + def _set_chars(self, char_values, is_primary=None): + _LOGGER.debug("Light _set_chars: %s, is_primary: %s", char_values, is_primary) events = [] service = SERVICE_TURN_ON params = {ATTR_ENTITY_ID: self.entity_id} @@ -127,16 +164,28 @@ class Light(HomeAccessory): params[ATTR_BRIGHTNESS_PCT] = char_values[CHAR_BRIGHTNESS] events.append(f"brightness at {char_values[CHAR_BRIGHTNESS]}%") - if CHAR_COLOR_TEMPERATURE in char_values: - params[ATTR_COLOR_TEMP] = char_values[CHAR_COLOR_TEMPERATURE] - events.append(f"color temperature at {char_values[CHAR_COLOR_TEMPERATURE]}") + if service == SERVICE_TURN_OFF: + self.async_call_service( + DOMAIN, service, {ATTR_ENTITY_ID: self.entity_id}, ", ".join(events) + ) + return - if ( - color_supported(self._color_modes) - and CHAR_HUE in char_values - and CHAR_SATURATION in char_values + if self.is_color_temp_supported and ( + is_primary is False or CHAR_COLOR_TEMPERATURE in char_values ): - color = (char_values[CHAR_HUE], char_values[CHAR_SATURATION]) + params[ATTR_COLOR_TEMP] = char_values.get( + CHAR_COLOR_TEMPERATURE, self.char_color_temperature.value + ) + events.append(f"color temperature at {params[ATTR_COLOR_TEMP]}") + + if self.is_color_supported and ( + is_primary is True + or (CHAR_HUE in char_values and CHAR_SATURATION in char_values) + ): + color = ( + char_values.get(CHAR_HUE, self.char_hue.value), + char_values.get(CHAR_SATURATION, self.char_saturation.value), + ) _LOGGER.debug("%s: Set hs_color to %s", self.entity_id, color) params[ATTR_HS_COLOR] = color events.append(f"set color at {color}") @@ -148,14 +197,25 @@ class Light(HomeAccessory): """Update light after state change.""" # Handle State state = new_state.state - if state == STATE_ON and self.char_on.value != 1: - self.char_on.set_value(1) - elif state == STATE_OFF and self.char_on.value != 0: - self.char_on.set_value(0) + attributes = new_state.attributes + char_on_value = int(state == STATE_ON) + + if self.color_and_temp_supported: + color_mode = attributes.get(ATTR_COLOR_MODE) + color_temp_mode = color_mode == COLOR_MODE_COLOR_TEMP + primary_on_value = char_on_value if not color_temp_mode else 0 + secondary_on_value = char_on_value if color_temp_mode else 0 + if self.char_on_primary.value != primary_on_value: + self.char_on_primary.set_value(primary_on_value) + if self.char_on_secondary.value != secondary_on_value: + self.char_on_secondary.set_value(secondary_on_value) + else: + if self.char_on_primary.value != char_on_value: + self.char_on_primary.set_value(char_on_value) # Handle Brightness - if CHAR_BRIGHTNESS in self.chars: - brightness = new_state.attributes.get(ATTR_BRIGHTNESS) + if self.is_brightness_supported: + brightness = attributes.get(ATTR_BRIGHTNESS) if isinstance(brightness, (int, float)): brightness = round(brightness / 255 * 100, 0) # The homeassistant component might report its brightness as 0 but is @@ -170,29 +230,25 @@ class Light(HomeAccessory): # order to avoid this incorrect behavior. if brightness == 0 and state == STATE_ON: brightness = 1 - if self.char_brightness.value != brightness: - self.char_brightness.set_value(brightness) + if self.char_brightness_primary.value != brightness: + self.char_brightness_primary.set_value(brightness) + if ( + self.color_and_temp_supported + and self.char_brightness_secondary.value != brightness + ): + self.char_brightness_secondary.set_value(brightness) # Handle color temperature - if CHAR_COLOR_TEMPERATURE in self.chars: - color_temperature = new_state.attributes.get(ATTR_COLOR_TEMP) + if self.is_color_temp_supported: + color_temperature = attributes.get(ATTR_COLOR_TEMP) if isinstance(color_temperature, (int, float)): color_temperature = round(color_temperature, 0) if self.char_color_temperature.value != color_temperature: self.char_color_temperature.set_value(color_temperature) # Handle Color - if CHAR_SATURATION in self.chars and CHAR_HUE in self.chars: - if ATTR_HS_COLOR in new_state.attributes: - hue, saturation = new_state.attributes[ATTR_HS_COLOR] - elif ATTR_COLOR_TEMP in new_state.attributes: - hue, saturation = color_temperature_to_hs( - color_temperature_mired_to_kelvin( - new_state.attributes[ATTR_COLOR_TEMP] - ) - ) - else: - hue, saturation = None, None + if self.is_color_supported: + hue, saturation = attributes.get(ATTR_HS_COLOR, (None, None)) if isinstance(hue, (int, float)) and isinstance(saturation, (int, float)): hue = round(hue, 0) saturation = round(saturation, 0) diff --git a/tests/components/homekit/test_type_lights.py b/tests/components/homekit/test_type_lights.py index 53d6ee02be6..f75e6bf19ac 100644 --- a/tests/components/homekit/test_type_lights.py +++ b/tests/components/homekit/test_type_lights.py @@ -8,9 +8,14 @@ from homeassistant.components.homekit.type_lights import Light from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, + ATTR_COLOR_MODE, ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_SUPPORTED_COLOR_MODES, + COLOR_MODE_COLOR_TEMP, + COLOR_MODE_HS, + COLOR_MODE_RGB, + COLOR_MODE_XY, DOMAIN, ) from homeassistant.const import ( @@ -39,40 +44,44 @@ async def test_light_basic(hass, hk_driver, events): assert acc.aid == 1 assert acc.category == 5 # Lightbulb - assert acc.char_on.value + assert acc.char_on_primary.value await acc.run() await hass.async_block_till_done() - assert acc.char_on.value == 1 + assert acc.char_on_primary.value == 1 hass.states.async_set(entity_id, STATE_OFF, {ATTR_SUPPORTED_FEATURES: 0}) await hass.async_block_till_done() - assert acc.char_on.value == 0 + assert acc.char_on_primary.value == 0 hass.states.async_set(entity_id, STATE_UNKNOWN) await hass.async_block_till_done() - assert acc.char_on.value == 0 + assert acc.char_on_primary.value == 0 hass.states.async_remove(entity_id) await hass.async_block_till_done() - assert acc.char_on.value == 0 + assert acc.char_on_primary.value == 0 # Set from HomeKit call_turn_on = async_mock_service(hass, DOMAIN, "turn_on") call_turn_off = async_mock_service(hass, DOMAIN, "turn_off") - char_on_iid = acc.char_on.to_HAP()[HAP_REPR_IID] + char_on_primary_iid = acc.char_on_primary.to_HAP()[HAP_REPR_IID] hk_driver.set_characteristics( { HAP_REPR_CHARS: [ - {HAP_REPR_AID: acc.aid, HAP_REPR_IID: char_on_iid, HAP_REPR_VALUE: 1} + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_on_primary_iid, + HAP_REPR_VALUE: 1, + } ] }, "mock_addr", ) - await hass.async_add_executor_job(acc.char_on.client_update_value, 1) + await hass.async_add_executor_job(acc.char_on_primary.client_update_value, 1) await hass.async_block_till_done() assert call_turn_on assert call_turn_on[0].data[ATTR_ENTITY_ID] == entity_id @@ -85,7 +94,11 @@ async def test_light_basic(hass, hk_driver, events): hk_driver.set_characteristics( { HAP_REPR_CHARS: [ - {HAP_REPR_AID: acc.aid, HAP_REPR_IID: char_on_iid, HAP_REPR_VALUE: 0} + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_on_primary_iid, + HAP_REPR_VALUE: 0, + } ] }, "mock_addr", @@ -115,17 +128,17 @@ async def test_light_brightness(hass, hk_driver, events, supported_color_modes): # Initial value can be anything but 0. If it is 0, it might cause HomeKit to set the # brightness to 100 when turning on a light on a freshly booted up server. - assert acc.char_brightness.value != 0 - char_on_iid = acc.char_on.to_HAP()[HAP_REPR_IID] - char_brightness_iid = acc.char_brightness.to_HAP()[HAP_REPR_IID] + assert acc.char_brightness_primary.value != 0 + char_on_primary_iid = acc.char_on_primary.to_HAP()[HAP_REPR_IID] + char_brightness_primary_iid = acc.char_brightness_primary.to_HAP()[HAP_REPR_IID] await acc.run() await hass.async_block_till_done() - assert acc.char_brightness.value == 100 + assert acc.char_brightness_primary.value == 100 hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 102}) await hass.async_block_till_done() - assert acc.char_brightness.value == 40 + assert acc.char_brightness_primary.value == 40 # Set from HomeKit call_turn_on = async_mock_service(hass, DOMAIN, "turn_on") @@ -134,10 +147,14 @@ async def test_light_brightness(hass, hk_driver, events, supported_color_modes): hk_driver.set_characteristics( { HAP_REPR_CHARS: [ - {HAP_REPR_AID: acc.aid, HAP_REPR_IID: char_on_iid, HAP_REPR_VALUE: 1}, { HAP_REPR_AID: acc.aid, - HAP_REPR_IID: char_brightness_iid, + HAP_REPR_IID: char_on_primary_iid, + HAP_REPR_VALUE: 1, + }, + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_brightness_primary_iid, HAP_REPR_VALUE: 20, }, ] @@ -156,10 +173,14 @@ async def test_light_brightness(hass, hk_driver, events, supported_color_modes): hk_driver.set_characteristics( { HAP_REPR_CHARS: [ - {HAP_REPR_AID: acc.aid, HAP_REPR_IID: char_on_iid, HAP_REPR_VALUE: 1}, { HAP_REPR_AID: acc.aid, - HAP_REPR_IID: char_brightness_iid, + HAP_REPR_IID: char_on_primary_iid, + HAP_REPR_VALUE: 1, + }, + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_brightness_primary_iid, HAP_REPR_VALUE: 40, }, ] @@ -178,10 +199,14 @@ async def test_light_brightness(hass, hk_driver, events, supported_color_modes): hk_driver.set_characteristics( { HAP_REPR_CHARS: [ - {HAP_REPR_AID: acc.aid, HAP_REPR_IID: char_on_iid, HAP_REPR_VALUE: 1}, { HAP_REPR_AID: acc.aid, - HAP_REPR_IID: char_brightness_iid, + HAP_REPR_IID: char_on_primary_iid, + HAP_REPR_VALUE: 1, + }, + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_brightness_primary_iid, HAP_REPR_VALUE: 0, }, ] @@ -198,24 +223,24 @@ async def test_light_brightness(hass, hk_driver, events, supported_color_modes): # in update_state hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 0}) await hass.async_block_till_done() - assert acc.char_brightness.value == 1 + assert acc.char_brightness_primary.value == 1 hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 255}) await hass.async_block_till_done() - assert acc.char_brightness.value == 100 + assert acc.char_brightness_primary.value == 100 hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 0}) await hass.async_block_till_done() - assert acc.char_brightness.value == 1 + assert acc.char_brightness_primary.value == 1 # Ensure floats are handled hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 55.66}) await hass.async_block_till_done() - assert acc.char_brightness.value == 22 + assert acc.char_brightness_primary.value == 22 hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 108.4}) await hass.async_block_till_done() - assert acc.char_brightness.value == 43 + assert acc.char_brightness_primary.value == 43 hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 0.0}) await hass.async_block_till_done() - assert acc.char_brightness.value == 1 + assert acc.char_brightness_primary.value == 1 async def test_light_color_temperature(hass, hk_driver, events): @@ -266,7 +291,12 @@ async def test_light_color_temperature(hass, hk_driver, events): @pytest.mark.parametrize( - "supported_color_modes", [["ct", "hs"], ["ct", "rgb"], ["ct", "xy"]] + "supported_color_modes", + [ + [COLOR_MODE_COLOR_TEMP, COLOR_MODE_HS], + [COLOR_MODE_COLOR_TEMP, COLOR_MODE_RGB], + [COLOR_MODE_COLOR_TEMP, COLOR_MODE_XY], + ], ) async def test_light_color_temperature_and_rgb_color( hass, hk_driver, events, supported_color_modes @@ -280,29 +310,93 @@ async def test_light_color_temperature_and_rgb_color( { ATTR_SUPPORTED_COLOR_MODES: supported_color_modes, ATTR_COLOR_TEMP: 190, + ATTR_BRIGHTNESS: 255, + ATTR_COLOR_MODE: COLOR_MODE_RGB, ATTR_HS_COLOR: (260, 90), }, ) await hass.async_block_till_done() - acc = Light(hass, hk_driver, "Light", entity_id, 2, None) + acc = Light(hass, hk_driver, "Light", entity_id, 1, None) assert acc.char_hue.value == 260 assert acc.char_saturation.value == 90 + assert acc.char_on_primary.value == 1 + assert acc.char_on_secondary.value == 0 + assert acc.char_brightness_primary.value == 100 + assert acc.char_brightness_secondary.value == 100 - assert not hasattr(acc, "char_color_temperature") + assert hasattr(acc, "char_color_temperature") - hass.states.async_set(entity_id, STATE_ON, {ATTR_COLOR_TEMP: 224}) + hass.states.async_set( + entity_id, + STATE_ON, + { + ATTR_COLOR_TEMP: 224, + ATTR_COLOR_MODE: COLOR_MODE_COLOR_TEMP, + ATTR_BRIGHTNESS: 127, + }, + ) await hass.async_block_till_done() await acc.run() await hass.async_block_till_done() - assert acc.char_hue.value == 27 - assert acc.char_saturation.value == 27 + assert acc.char_color_temperature.value == 224 + assert acc.char_on_primary.value == 0 + assert acc.char_on_secondary.value == 1 + assert acc.char_brightness_primary.value == 50 + assert acc.char_brightness_secondary.value == 50 - hass.states.async_set(entity_id, STATE_ON, {ATTR_COLOR_TEMP: 352}) + hass.states.async_set( + entity_id, + STATE_ON, + { + ATTR_COLOR_TEMP: 352, + ATTR_COLOR_MODE: COLOR_MODE_COLOR_TEMP, + }, + ) await hass.async_block_till_done() await acc.run() await hass.async_block_till_done() - assert acc.char_hue.value == 28 - assert acc.char_saturation.value == 61 + assert acc.char_color_temperature.value == 352 + assert acc.char_on_primary.value == 0 + assert acc.char_on_secondary.value == 1 + hk_driver.add_accessory(acc) + + char_hue_iid = acc.char_hue.to_HAP()[HAP_REPR_IID] + char_saturation_iid = acc.char_saturation.to_HAP()[HAP_REPR_IID] + char_color_temperature_iid = acc.char_color_temperature.to_HAP()[HAP_REPR_IID] + + hk_driver.set_characteristics( + { + HAP_REPR_CHARS: [ + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_hue_iid, + HAP_REPR_VALUE: 145, + }, + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_saturation_iid, + HAP_REPR_VALUE: 75, + }, + ] + }, + "mock_addr", + ) + assert acc.char_hue.value == 145 + assert acc.char_saturation.value == 75 + + hk_driver.set_characteristics( + { + HAP_REPR_CHARS: [ + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_color_temperature_iid, + HAP_REPR_VALUE: 200, + }, + ] + }, + "mock_addr", + ) + assert acc.char_color_temperature.value == 200 @pytest.mark.parametrize("supported_color_modes", [["hs"], ["rgb"], ["xy"]]) @@ -382,13 +476,13 @@ async def test_light_restore(hass, hk_driver, events): hk_driver.add_accessory(acc) assert acc.category == 5 # Lightbulb - assert acc.chars == [] - assert acc.char_on.value == 0 + assert acc.chars_primary == [] + assert acc.char_on_primary.value == 0 acc = Light(hass, hk_driver, "Light", "light.all_info_set", 2, None) assert acc.category == 5 # Lightbulb - assert acc.chars == ["Brightness"] - assert acc.char_on.value == 0 + assert acc.chars_primary == ["Brightness"] + assert acc.char_on_primary.value == 0 async def test_light_set_brightness_and_color(hass, hk_driver, events): @@ -409,19 +503,19 @@ async def test_light_set_brightness_and_color(hass, hk_driver, events): # Initial value can be anything but 0. If it is 0, it might cause HomeKit to set the # brightness to 100 when turning on a light on a freshly booted up server. - assert acc.char_brightness.value != 0 - char_on_iid = acc.char_on.to_HAP()[HAP_REPR_IID] - char_brightness_iid = acc.char_brightness.to_HAP()[HAP_REPR_IID] + assert acc.char_brightness_primary.value != 0 + char_on_primary_iid = acc.char_on_primary.to_HAP()[HAP_REPR_IID] + char_brightness_primary_iid = acc.char_brightness_primary.to_HAP()[HAP_REPR_IID] char_hue_iid = acc.char_hue.to_HAP()[HAP_REPR_IID] char_saturation_iid = acc.char_saturation.to_HAP()[HAP_REPR_IID] await acc.run() await hass.async_block_till_done() - assert acc.char_brightness.value == 100 + assert acc.char_brightness_primary.value == 100 hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 102}) await hass.async_block_till_done() - assert acc.char_brightness.value == 40 + assert acc.char_brightness_primary.value == 40 hass.states.async_set(entity_id, STATE_ON, {ATTR_HS_COLOR: (4.5, 9.2)}) await hass.async_block_till_done() @@ -434,10 +528,14 @@ async def test_light_set_brightness_and_color(hass, hk_driver, events): hk_driver.set_characteristics( { HAP_REPR_CHARS: [ - {HAP_REPR_AID: acc.aid, HAP_REPR_IID: char_on_iid, HAP_REPR_VALUE: 1}, { HAP_REPR_AID: acc.aid, - HAP_REPR_IID: char_brightness_iid, + HAP_REPR_IID: char_on_primary_iid, + HAP_REPR_VALUE: 1, + }, + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_brightness_primary_iid, HAP_REPR_VALUE: 20, }, { @@ -485,18 +583,18 @@ async def test_light_set_brightness_and_color_temp(hass, hk_driver, events): # Initial value can be anything but 0. If it is 0, it might cause HomeKit to set the # brightness to 100 when turning on a light on a freshly booted up server. - assert acc.char_brightness.value != 0 - char_on_iid = acc.char_on.to_HAP()[HAP_REPR_IID] - char_brightness_iid = acc.char_brightness.to_HAP()[HAP_REPR_IID] + assert acc.char_brightness_primary.value != 0 + char_on_primary_iid = acc.char_on_primary.to_HAP()[HAP_REPR_IID] + char_brightness_primary_iid = acc.char_brightness_primary.to_HAP()[HAP_REPR_IID] char_color_temperature_iid = acc.char_color_temperature.to_HAP()[HAP_REPR_IID] await acc.run() await hass.async_block_till_done() - assert acc.char_brightness.value == 100 + assert acc.char_brightness_primary.value == 100 hass.states.async_set(entity_id, STATE_ON, {ATTR_BRIGHTNESS: 102}) await hass.async_block_till_done() - assert acc.char_brightness.value == 40 + assert acc.char_brightness_primary.value == 40 hass.states.async_set(entity_id, STATE_ON, {ATTR_COLOR_TEMP: (224.14)}) await hass.async_block_till_done() @@ -508,10 +606,14 @@ async def test_light_set_brightness_and_color_temp(hass, hk_driver, events): hk_driver.set_characteristics( { HAP_REPR_CHARS: [ - {HAP_REPR_AID: acc.aid, HAP_REPR_IID: char_on_iid, HAP_REPR_VALUE: 1}, { HAP_REPR_AID: acc.aid, - HAP_REPR_IID: char_brightness_iid, + HAP_REPR_IID: char_on_primary_iid, + HAP_REPR_VALUE: 1, + }, + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_brightness_primary_iid, HAP_REPR_VALUE: 20, }, {