From 5c2af99520815e3648d86f76a923a3407326651c Mon Sep 17 00:00:00 2001 From: Stackie Jia Date: Thu, 6 Apr 2023 00:35:47 +0800 Subject: [PATCH] Improve the HomeKit (de)humidifier min/max humidity handling (#90854) --- .../components/homekit/type_humidifiers.py | 28 +++++++---- .../homekit/test_type_humidifiers.py | 48 +++++++++++++++++-- 2 files changed, 63 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/homekit/type_humidifiers.py b/homeassistant/components/homekit/type_humidifiers.py index b585f38e981..33c35908cd1 100644 --- a/homeassistant/components/homekit/type_humidifiers.py +++ b/homeassistant/components/homekit/type_humidifiers.py @@ -115,20 +115,12 @@ class HumidifierDehumidifier(HomeAccessory): CHAR_CURRENT_HUMIDITY, value=0 ) - max_humidity = state.attributes.get(ATTR_MAX_HUMIDITY, DEFAULT_MAX_HUMIDITY) - max_humidity = round(max_humidity) - max_humidity = min(max_humidity, 100) - - min_humidity = state.attributes.get(ATTR_MIN_HUMIDITY, DEFAULT_MIN_HUMIDITY) - min_humidity = round(min_humidity) - min_humidity = max(min_humidity, 0) - self.char_target_humidity = serv_humidifier_dehumidifier.configure_char( self._target_humidity_char_name, value=45, properties={ - PROP_MIN_VALUE: min_humidity, - PROP_MAX_VALUE: max_humidity, + PROP_MIN_VALUE: DEFAULT_MIN_HUMIDITY, + PROP_MAX_VALUE: DEFAULT_MAX_HUMIDITY, PROP_MIN_STEP: 1, }, ) @@ -219,7 +211,23 @@ class HumidifierDehumidifier(HomeAccessory): ) if self._target_humidity_char_name in char_values: + state = self.hass.states.get(self.entity_id) + max_humidity = state.attributes.get(ATTR_MAX_HUMIDITY, DEFAULT_MAX_HUMIDITY) + max_humidity = round(max_humidity) + max_humidity = min(max_humidity, 100) + + min_humidity = state.attributes.get(ATTR_MIN_HUMIDITY, DEFAULT_MIN_HUMIDITY) + min_humidity = round(min_humidity) + min_humidity = max(min_humidity, 0) + humidity = round(char_values[self._target_humidity_char_name]) + + if (humidity < min_humidity) or (humidity > max_humidity): + humidity = min(max_humidity, max(min_humidity, humidity)) + # Update the HomeKit value to the clamped humidity, so the user will get a visual feedback that they + # cannot not set to a value below/above the min/max. + self.char_target_humidity.set_value(humidity) + self.async_call_service( DOMAIN, SERVICE_SET_HUMIDITY, diff --git a/tests/components/homekit/test_type_humidifiers.py b/tests/components/homekit/test_type_humidifiers.py index 27580c05969..f3e4f96573d 100644 --- a/tests/components/homekit/test_type_humidifiers.py +++ b/tests/components/homekit/test_type_humidifiers.py @@ -286,7 +286,9 @@ async def test_hygrostat_power_state(hass: HomeAssistant, hk_driver, events) -> assert events[-1].data[ATTR_VALUE] == "Active to 0" -async def test_hygrostat_get_humidity_range(hass: HomeAssistant, hk_driver) -> None: +async def test_hygrostat_get_humidity_range( + hass: HomeAssistant, hk_driver, events +) -> None: """Test if humidity range is evaluated correctly.""" entity_id = "humidifier.test" @@ -302,8 +304,48 @@ async def test_hygrostat_get_humidity_range(hass: HomeAssistant, hk_driver) -> N await acc.run() await hass.async_block_till_done() - assert acc.char_target_humidity.properties[PROP_MAX_VALUE] == 45 - assert acc.char_target_humidity.properties[PROP_MIN_VALUE] == 40 + # Set from HomeKit + call_set_humidity = async_mock_service(hass, DOMAIN, SERVICE_SET_HUMIDITY) + + char_target_humidity_iid = acc.char_target_humidity.to_HAP()[HAP_REPR_IID] + + hk_driver.set_characteristics( + { + HAP_REPR_CHARS: [ + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_target_humidity_iid, + HAP_REPR_VALUE: 12.0, + }, + ] + }, + "mock_addr", + ) + + await hass.async_block_till_done() + assert call_set_humidity[-1].data[ATTR_ENTITY_ID] == entity_id + assert call_set_humidity[-1].data[ATTR_HUMIDITY] == 40.0 + assert acc.char_target_humidity.value == 40.0 + assert events[-1].data[ATTR_VALUE] == "RelativeHumidityHumidifierThreshold to 12.0%" + + hk_driver.set_characteristics( + { + HAP_REPR_CHARS: [ + { + HAP_REPR_AID: acc.aid, + HAP_REPR_IID: char_target_humidity_iid, + HAP_REPR_VALUE: 80.0, + }, + ] + }, + "mock_addr", + ) + + await hass.async_block_till_done() + assert call_set_humidity[-1].data[ATTR_ENTITY_ID] == entity_id + assert call_set_humidity[-1].data[ATTR_HUMIDITY] == 45.0 + assert acc.char_target_humidity.value == 45.0 + assert events[-1].data[ATTR_VALUE] == "RelativeHumidityHumidifierThreshold to 80.0%" async def test_humidifier_with_linked_humidity_sensor(