Update HomeKit humidifiers to handle current humidity (#101964)
This commit is contained in:
parent
8fd5d89d43
commit
f8f39a29de
2 changed files with 94 additions and 27 deletions
|
@ -5,6 +5,7 @@ from typing import Any
|
|||
from pyhap.const import CATEGORY_HUMIDIFIER
|
||||
|
||||
from homeassistant.components.humidifier import (
|
||||
ATTR_CURRENT_HUMIDITY,
|
||||
ATTR_HUMIDITY,
|
||||
ATTR_MAX_HUMIDITY,
|
||||
ATTR_MIN_HUMIDITY,
|
||||
|
@ -64,11 +65,28 @@ HC_DEVICE_CLASS_TO_TARGET_CHAR = {
|
|||
HC_DEHUMIDIFIER: CHAR_DEHUMIDIFIER_THRESHOLD_HUMIDITY,
|
||||
}
|
||||
|
||||
|
||||
HC_STATE_INACTIVE = 0
|
||||
HC_STATE_IDLE = 1
|
||||
HC_STATE_HUMIDIFYING = 2
|
||||
HC_STATE_DEHUMIDIFYING = 3
|
||||
|
||||
BASE_VALID_VALUES = {
|
||||
"Inactive": HC_STATE_INACTIVE,
|
||||
"Idle": HC_STATE_IDLE,
|
||||
}
|
||||
|
||||
VALID_VALUES_BY_DEVICE_CLASS = {
|
||||
HumidifierDeviceClass.HUMIDIFIER: {
|
||||
**BASE_VALID_VALUES,
|
||||
"Humidifying": HC_STATE_HUMIDIFYING,
|
||||
},
|
||||
HumidifierDeviceClass.DEHUMIDIFIER: {
|
||||
**BASE_VALID_VALUES,
|
||||
"Dehumidifying": HC_STATE_DEHUMIDIFYING,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@TYPES.register("HumidifierDehumidifier")
|
||||
class HumidifierDehumidifier(HomeAccessory):
|
||||
|
@ -85,7 +103,8 @@ class HumidifierDehumidifier(HomeAccessory):
|
|||
)
|
||||
|
||||
self.chars: list[str] = []
|
||||
state = self.hass.states.get(self.entity_id)
|
||||
states = self.hass.states
|
||||
state = states.get(self.entity_id)
|
||||
assert state
|
||||
device_class = state.attributes.get(
|
||||
ATTR_DEVICE_CLASS, HumidifierDeviceClass.HUMIDIFIER
|
||||
|
@ -104,7 +123,9 @@ class HumidifierDehumidifier(HomeAccessory):
|
|||
# Current and target mode characteristics
|
||||
self.char_current_humidifier_dehumidifier = (
|
||||
serv_humidifier_dehumidifier.configure_char(
|
||||
CHAR_CURRENT_HUMIDIFIER_DEHUMIDIFIER, value=0
|
||||
CHAR_CURRENT_HUMIDIFIER_DEHUMIDIFIER,
|
||||
value=0,
|
||||
valid_values=VALID_VALUES_BY_DEVICE_CLASS[device_class],
|
||||
)
|
||||
)
|
||||
self.char_target_humidifier_dehumidifier = (
|
||||
|
@ -149,8 +170,7 @@ class HumidifierDehumidifier(HomeAccessory):
|
|||
|
||||
self.linked_humidity_sensor = self.config.get(CONF_LINKED_HUMIDITY_SENSOR)
|
||||
if self.linked_humidity_sensor:
|
||||
humidity_state = self.hass.states.get(self.linked_humidity_sensor)
|
||||
if humidity_state:
|
||||
if humidity_state := states.get(self.linked_humidity_sensor):
|
||||
self._async_update_current_humidity(humidity_state)
|
||||
|
||||
async def run(self) -> None:
|
||||
|
@ -191,14 +211,6 @@ class HumidifierDehumidifier(HomeAccessory):
|
|||
return
|
||||
try:
|
||||
current_humidity = float(new_state.state)
|
||||
if self.char_current_humidity.value != current_humidity:
|
||||
_LOGGER.debug(
|
||||
"%s: Linked humidity sensor %s changed to %d",
|
||||
self.entity_id,
|
||||
self.linked_humidity_sensor,
|
||||
current_humidity,
|
||||
)
|
||||
self.char_current_humidity.set_value(current_humidity)
|
||||
except ValueError as ex:
|
||||
_LOGGER.debug(
|
||||
"%s: Unable to update from linked humidity sensor %s: %s",
|
||||
|
@ -206,6 +218,20 @@ class HumidifierDehumidifier(HomeAccessory):
|
|||
self.linked_humidity_sensor,
|
||||
ex,
|
||||
)
|
||||
return
|
||||
self._async_update_current_humidity_value(current_humidity)
|
||||
|
||||
@callback
|
||||
def _async_update_current_humidity_value(self, current_humidity: float) -> None:
|
||||
"""Handle linked humidity or built-in humidity."""
|
||||
if self.char_current_humidity.value != current_humidity:
|
||||
_LOGGER.debug(
|
||||
"%s: Linked humidity sensor %s changed to %d",
|
||||
self.entity_id,
|
||||
self.linked_humidity_sensor,
|
||||
current_humidity,
|
||||
)
|
||||
self.char_current_humidity.set_value(current_humidity)
|
||||
|
||||
def _set_chars(self, char_values: dict[str, Any]) -> None:
|
||||
"""Set characteristics based on the data coming from HomeKit."""
|
||||
|
@ -229,19 +255,7 @@ class HumidifierDehumidifier(HomeAccessory):
|
|||
if self._target_humidity_char_name in char_values:
|
||||
state = self.hass.states.get(self.entity_id)
|
||||
assert state
|
||||
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)
|
||||
# The min/max humidity values here should be clamped to the HomeKit
|
||||
# min/max that was set when the accessory was added to HomeKit so
|
||||
# that the user cannot set a value outside of the range that was
|
||||
# originally set as it could cause HomeKit to report the accessory
|
||||
# as not responding.
|
||||
|
||||
min_humidity, max_humidity = self.get_humidity_range(state)
|
||||
humidity = round(char_values[self._target_humidity_char_name])
|
||||
|
||||
if (humidity < min_humidity) or (humidity > max_humidity):
|
||||
|
@ -260,10 +274,22 @@ class HumidifierDehumidifier(HomeAccessory):
|
|||
),
|
||||
)
|
||||
|
||||
def get_humidity_range(self, state: State) -> tuple[int, int]:
|
||||
"""Return min and max humidity range."""
|
||||
attributes = state.attributes
|
||||
min_humidity = max(
|
||||
int(round(attributes.get(ATTR_MIN_HUMIDITY, DEFAULT_MIN_HUMIDITY))), 0
|
||||
)
|
||||
max_humidity = min(
|
||||
int(round(attributes.get(ATTR_MAX_HUMIDITY, DEFAULT_MAX_HUMIDITY))), 100
|
||||
)
|
||||
return min_humidity, max_humidity
|
||||
|
||||
@callback
|
||||
def async_update_state(self, new_state: State) -> None:
|
||||
"""Update state without rechecking the device features."""
|
||||
is_active = new_state.state == STATE_ON
|
||||
attributes = new_state.attributes
|
||||
|
||||
# Update active state
|
||||
self.char_active.set_value(is_active)
|
||||
|
@ -279,6 +305,9 @@ class HumidifierDehumidifier(HomeAccessory):
|
|||
self.char_current_humidifier_dehumidifier.set_value(current_state)
|
||||
|
||||
# Update target humidity
|
||||
target_humidity = new_state.attributes.get(ATTR_HUMIDITY)
|
||||
target_humidity = attributes.get(ATTR_HUMIDITY)
|
||||
if isinstance(target_humidity, (int, float)):
|
||||
self.char_target_humidity.set_value(target_humidity)
|
||||
current_humidity = attributes.get(ATTR_CURRENT_HUMIDITY)
|
||||
if isinstance(current_humidity, (int, float)):
|
||||
self.char_current_humidity.set_value(current_humidity)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue