Allow Humidifier.current_humidity to be a float (#111297)
* Allow Humidifier.current_humidity to be a float * Code review * Allow climate humidity values to be float * Update demo integrationpull/114293/head
parent
b190cdceaf
commit
44eeb2eb5e
homeassistant/components
climate
comelit
generic_hygrostat
homekit_controller
humidifier
pylint/plugins
tests/components
google_assistant
|
@ -292,9 +292,9 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||
_attr_hvac_mode: HVACMode | None
|
||||
_attr_hvac_modes: list[HVACMode]
|
||||
_attr_is_aux_heat: bool | None
|
||||
_attr_max_humidity: int = DEFAULT_MAX_HUMIDITY
|
||||
_attr_max_humidity: float = DEFAULT_MAX_HUMIDITY
|
||||
_attr_max_temp: float
|
||||
_attr_min_humidity: int = DEFAULT_MIN_HUMIDITY
|
||||
_attr_min_humidity: float = DEFAULT_MIN_HUMIDITY
|
||||
_attr_min_temp: float
|
||||
_attr_precision: float
|
||||
_attr_preset_mode: str | None
|
||||
|
@ -302,7 +302,7 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||
_attr_supported_features: ClimateEntityFeature = ClimateEntityFeature(0)
|
||||
_attr_swing_mode: str | None
|
||||
_attr_swing_modes: list[str] | None
|
||||
_attr_target_humidity: int | None = None
|
||||
_attr_target_humidity: float | None = None
|
||||
_attr_target_temperature_high: float | None
|
||||
_attr_target_temperature_low: float | None
|
||||
_attr_target_temperature_step: float | None = None
|
||||
|
@ -517,12 +517,12 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||
return self._attr_temperature_unit
|
||||
|
||||
@cached_property
|
||||
def current_humidity(self) -> int | None:
|
||||
def current_humidity(self) -> float | None:
|
||||
"""Return the current humidity."""
|
||||
return self._attr_current_humidity
|
||||
|
||||
@cached_property
|
||||
def target_humidity(self) -> int | None:
|
||||
def target_humidity(self) -> float | None:
|
||||
"""Return the humidity we try to reach."""
|
||||
return self._attr_target_humidity
|
||||
|
||||
|
@ -826,12 +826,12 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
|||
return self._attr_max_temp
|
||||
|
||||
@cached_property
|
||||
def min_humidity(self) -> int:
|
||||
def min_humidity(self) -> float:
|
||||
"""Return the minimum humidity."""
|
||||
return self._attr_min_humidity
|
||||
|
||||
@cached_property
|
||||
def max_humidity(self) -> int:
|
||||
def max_humidity(self) -> float:
|
||||
"""Return the maximum humidity."""
|
||||
return self._attr_max_humidity
|
||||
|
||||
|
|
|
@ -148,12 +148,12 @@ class ComelitHumidifierEntity(CoordinatorEntity[ComelitSerialBridge], Humidifier
|
|||
return self._humidifier[3] == HumidifierComelitMode.AUTO
|
||||
|
||||
@property
|
||||
def target_humidity(self) -> int:
|
||||
def target_humidity(self) -> float:
|
||||
"""Set target humidity."""
|
||||
return self._humidifier[4] / 10
|
||||
|
||||
@property
|
||||
def current_humidity(self) -> int:
|
||||
def current_humidity(self) -> float:
|
||||
"""Return current humidity."""
|
||||
return self._humidifier[0] / 10
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ async def async_setup_entry(
|
|||
preset=None,
|
||||
current_temperature=22,
|
||||
fan_mode="on_high",
|
||||
target_humidity=67,
|
||||
current_humidity=54,
|
||||
target_humidity=67.4,
|
||||
current_humidity=54.2,
|
||||
swing_mode="off",
|
||||
hvac_mode=HVACMode.COOL,
|
||||
hvac_action=HVACAction.COOLING,
|
||||
|
@ -106,8 +106,8 @@ class DemoClimate(ClimateEntity):
|
|||
preset: str | None,
|
||||
current_temperature: float,
|
||||
fan_mode: str | None,
|
||||
target_humidity: int | None,
|
||||
current_humidity: int | None,
|
||||
target_humidity: float | None,
|
||||
current_humidity: float | None,
|
||||
swing_mode: str | None,
|
||||
hvac_mode: HVACMode,
|
||||
hvac_action: HVACAction | None,
|
||||
|
@ -188,12 +188,12 @@ class DemoClimate(ClimateEntity):
|
|||
return self._target_temperature_low
|
||||
|
||||
@property
|
||||
def current_humidity(self) -> int | None:
|
||||
def current_humidity(self) -> float | None:
|
||||
"""Return the current humidity."""
|
||||
return self._current_humidity
|
||||
|
||||
@property
|
||||
def target_humidity(self) -> int | None:
|
||||
def target_humidity(self) -> float | None:
|
||||
"""Return the humidity we try to reach."""
|
||||
return self._target_humidity
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ async def async_setup_entry(
|
|||
DemoHumidifier(
|
||||
name="Dehumidifier",
|
||||
mode=None,
|
||||
target_humidity=54,
|
||||
current_humidity=59,
|
||||
target_humidity=54.2,
|
||||
current_humidity=59.4,
|
||||
action=HumidifierAction.DRYING,
|
||||
device_class=HumidifierDeviceClass.DEHUMIDIFIER,
|
||||
),
|
||||
|
@ -60,8 +60,8 @@ class DemoHumidifier(HumidifierEntity):
|
|||
self,
|
||||
name: str,
|
||||
mode: str | None,
|
||||
target_humidity: int,
|
||||
current_humidity: int | None = None,
|
||||
target_humidity: float,
|
||||
current_humidity: float | None = None,
|
||||
available_modes: list[str] | None = None,
|
||||
is_on: bool = True,
|
||||
action: HumidifierAction | None = None,
|
||||
|
|
|
@ -36,13 +36,13 @@ HYGROSTAT_SCHEMA = vol.Schema(
|
|||
vol.Optional(CONF_DEVICE_CLASS): vol.In(
|
||||
[HumidifierDeviceClass.HUMIDIFIER, HumidifierDeviceClass.DEHUMIDIFIER]
|
||||
),
|
||||
vol.Optional(CONF_MAX_HUMIDITY): vol.Coerce(int),
|
||||
vol.Optional(CONF_MAX_HUMIDITY): vol.Coerce(float),
|
||||
vol.Optional(CONF_MIN_DUR): vol.All(cv.time_period, cv.positive_timedelta),
|
||||
vol.Optional(CONF_MIN_HUMIDITY): vol.Coerce(int),
|
||||
vol.Optional(CONF_MIN_HUMIDITY): vol.Coerce(float),
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_DRY_TOLERANCE, default=DEFAULT_TOLERANCE): vol.Coerce(float),
|
||||
vol.Optional(CONF_WET_TOLERANCE, default=DEFAULT_TOLERANCE): vol.Coerce(float),
|
||||
vol.Optional(CONF_TARGET_HUMIDITY): vol.Coerce(int),
|
||||
vol.Optional(CONF_TARGET_HUMIDITY): vol.Coerce(float),
|
||||
vol.Optional(CONF_KEEP_ALIVE): vol.All(cv.time_period, cv.positive_timedelta),
|
||||
vol.Optional(CONF_INITIAL_STATE): cv.boolean,
|
||||
vol.Optional(CONF_AWAY_HUMIDITY): vol.Coerce(int),
|
||||
|
|
|
@ -85,9 +85,9 @@ async def async_setup_platform(
|
|||
name: str = config[CONF_NAME]
|
||||
switch_entity_id: str = config[CONF_HUMIDIFIER]
|
||||
sensor_entity_id: str = config[CONF_SENSOR]
|
||||
min_humidity: int | None = config.get(CONF_MIN_HUMIDITY)
|
||||
max_humidity: int | None = config.get(CONF_MAX_HUMIDITY)
|
||||
target_humidity: int | None = config.get(CONF_TARGET_HUMIDITY)
|
||||
min_humidity: float | None = config.get(CONF_MIN_HUMIDITY)
|
||||
max_humidity: float | None = config.get(CONF_MAX_HUMIDITY)
|
||||
target_humidity: float | None = config.get(CONF_TARGET_HUMIDITY)
|
||||
device_class: HumidifierDeviceClass | None = config.get(CONF_DEVICE_CLASS)
|
||||
min_cycle_duration: timedelta | None = config.get(CONF_MIN_DUR)
|
||||
sensor_stale_duration: timedelta | None = config.get(CONF_STALE_DURATION)
|
||||
|
@ -133,9 +133,9 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
|||
name: str,
|
||||
switch_entity_id: str,
|
||||
sensor_entity_id: str,
|
||||
min_humidity: int | None,
|
||||
max_humidity: int | None,
|
||||
target_humidity: int | None,
|
||||
min_humidity: float | None,
|
||||
max_humidity: float | None,
|
||||
target_humidity: float | None,
|
||||
device_class: HumidifierDeviceClass | None,
|
||||
min_cycle_duration: timedelta | None,
|
||||
dry_tolerance: float,
|
||||
|
@ -264,12 +264,12 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
|||
return self._state
|
||||
|
||||
@property
|
||||
def current_humidity(self) -> int | None:
|
||||
def current_humidity(self) -> float | None:
|
||||
"""Return the measured humidity."""
|
||||
return int(self._cur_humidity) if self._cur_humidity is not None else None
|
||||
return self._cur_humidity
|
||||
|
||||
@property
|
||||
def target_humidity(self) -> int | None:
|
||||
def target_humidity(self) -> float | None:
|
||||
"""Return the humidity we try to reach."""
|
||||
return self._target_humidity
|
||||
|
||||
|
@ -326,7 +326,7 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
|||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
def min_humidity(self) -> int:
|
||||
def min_humidity(self) -> float:
|
||||
"""Return the minimum humidity."""
|
||||
if self._min_humidity:
|
||||
return self._min_humidity
|
||||
|
@ -335,7 +335,7 @@ class GenericHygrostat(HumidifierEntity, RestoreEntity):
|
|||
return super().min_humidity
|
||||
|
||||
@property
|
||||
def max_humidity(self) -> int:
|
||||
def max_humidity(self) -> float:
|
||||
"""Return the maximum humidity."""
|
||||
if self._max_humidity:
|
||||
return self._max_humidity
|
||||
|
|
|
@ -637,7 +637,7 @@ class HomeKitClimateEntity(HomeKitBaseClimateEntity):
|
|||
return self.service.value(CharacteristicsTypes.RELATIVE_HUMIDITY_TARGET)
|
||||
|
||||
@property
|
||||
def min_humidity(self) -> int:
|
||||
def min_humidity(self) -> float:
|
||||
"""Return the minimum humidity."""
|
||||
min_humidity = self.service[
|
||||
CharacteristicsTypes.RELATIVE_HUMIDITY_TARGET
|
||||
|
@ -647,7 +647,7 @@ class HomeKitClimateEntity(HomeKitBaseClimateEntity):
|
|||
return super().min_humidity
|
||||
|
||||
@property
|
||||
def max_humidity(self) -> int:
|
||||
def max_humidity(self) -> float:
|
||||
"""Return the maximum humidity."""
|
||||
max_humidity = self.service[
|
||||
CharacteristicsTypes.RELATIVE_HUMIDITY_TARGET
|
||||
|
|
|
@ -165,18 +165,18 @@ class HumidifierEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_AT
|
|||
entity_description: HumidifierEntityDescription
|
||||
_attr_action: HumidifierAction | None = None
|
||||
_attr_available_modes: list[str] | None
|
||||
_attr_current_humidity: int | None = None
|
||||
_attr_current_humidity: float | None = None
|
||||
_attr_device_class: HumidifierDeviceClass | None
|
||||
_attr_max_humidity: int = DEFAULT_MAX_HUMIDITY
|
||||
_attr_min_humidity: int = DEFAULT_MIN_HUMIDITY
|
||||
_attr_max_humidity: float = DEFAULT_MAX_HUMIDITY
|
||||
_attr_min_humidity: float = DEFAULT_MIN_HUMIDITY
|
||||
_attr_mode: str | None
|
||||
_attr_supported_features: HumidifierEntityFeature = HumidifierEntityFeature(0)
|
||||
_attr_target_humidity: int | None = None
|
||||
_attr_target_humidity: float | None = None
|
||||
|
||||
@property
|
||||
def capability_attributes(self) -> dict[str, Any]:
|
||||
"""Return capability attributes."""
|
||||
data: dict[str, int | list[str] | None] = {
|
||||
data: dict[str, Any] = {
|
||||
ATTR_MIN_HUMIDITY: self.min_humidity,
|
||||
ATTR_MAX_HUMIDITY: self.max_humidity,
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ class HumidifierEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_AT
|
|||
@property
|
||||
def state_attributes(self) -> dict[str, Any]:
|
||||
"""Return the optional state attributes."""
|
||||
data: dict[str, int | str | None] = {}
|
||||
data: dict[str, Any] = {}
|
||||
|
||||
if self.action is not None:
|
||||
data[ATTR_ACTION] = self.action if self.is_on else HumidifierAction.OFF
|
||||
|
@ -221,12 +221,12 @@ class HumidifierEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_AT
|
|||
return self._attr_action
|
||||
|
||||
@cached_property
|
||||
def current_humidity(self) -> int | None:
|
||||
def current_humidity(self) -> float | None:
|
||||
"""Return the current humidity."""
|
||||
return self._attr_current_humidity
|
||||
|
||||
@cached_property
|
||||
def target_humidity(self) -> int | None:
|
||||
def target_humidity(self) -> float | None:
|
||||
"""Return the humidity we try to reach."""
|
||||
return self._attr_target_humidity
|
||||
|
||||
|
@ -263,12 +263,12 @@ class HumidifierEntity(ToggleEntity, cached_properties=CACHED_PROPERTIES_WITH_AT
|
|||
await self.hass.async_add_executor_job(self.set_mode, mode)
|
||||
|
||||
@cached_property
|
||||
def min_humidity(self) -> int:
|
||||
def min_humidity(self) -> float:
|
||||
"""Return the minimum humidity."""
|
||||
return self._attr_min_humidity
|
||||
|
||||
@cached_property
|
||||
def max_humidity(self) -> int:
|
||||
def max_humidity(self) -> float:
|
||||
"""Return the maximum humidity."""
|
||||
return self._attr_max_humidity
|
||||
|
||||
|
|
|
@ -1025,11 +1025,11 @@ _INHERITANCE_MATCH: dict[str, list[ClassTypeHintMatch]] = {
|
|||
),
|
||||
TypeHintMatch(
|
||||
function_name="current_humidity",
|
||||
return_type=["int", None],
|
||||
return_type=["float", None],
|
||||
),
|
||||
TypeHintMatch(
|
||||
function_name="target_humidity",
|
||||
return_type=["int", None],
|
||||
return_type=["float", None],
|
||||
),
|
||||
TypeHintMatch(
|
||||
function_name="hvac_mode",
|
||||
|
@ -1171,11 +1171,11 @@ _INHERITANCE_MATCH: dict[str, list[ClassTypeHintMatch]] = {
|
|||
),
|
||||
TypeHintMatch(
|
||||
function_name="min_humidity",
|
||||
return_type="int",
|
||||
return_type="float",
|
||||
),
|
||||
TypeHintMatch(
|
||||
function_name="max_humidity",
|
||||
return_type="int",
|
||||
return_type="float",
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -1549,11 +1549,11 @@ _INHERITANCE_MATCH: dict[str, list[ClassTypeHintMatch]] = {
|
|||
),
|
||||
TypeHintMatch(
|
||||
function_name="min_humidity",
|
||||
return_type=["int"],
|
||||
return_type=["float"],
|
||||
),
|
||||
TypeHintMatch(
|
||||
function_name="max_humidity",
|
||||
return_type=["int"],
|
||||
return_type=["float"],
|
||||
),
|
||||
TypeHintMatch(
|
||||
function_name="mode",
|
||||
|
@ -1565,7 +1565,7 @@ _INHERITANCE_MATCH: dict[str, list[ClassTypeHintMatch]] = {
|
|||
),
|
||||
TypeHintMatch(
|
||||
function_name="target_humidity",
|
||||
return_type=["int", None],
|
||||
return_type=["float", None],
|
||||
),
|
||||
TypeHintMatch(
|
||||
function_name="set_humidity",
|
||||
|
|
|
@ -74,8 +74,8 @@ def test_setup_params(hass: HomeAssistant) -> None:
|
|||
assert state.attributes.get(ATTR_TEMPERATURE) == 21
|
||||
assert state.attributes.get(ATTR_CURRENT_TEMPERATURE) == 22
|
||||
assert state.attributes.get(ATTR_FAN_MODE) == "on_high"
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 67
|
||||
assert state.attributes.get(ATTR_CURRENT_HUMIDITY) == 54
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 67.4
|
||||
assert state.attributes.get(ATTR_CURRENT_HUMIDITY) == 54.2
|
||||
assert state.attributes.get(ATTR_SWING_MODE) == "off"
|
||||
assert state.attributes.get(ATTR_HVAC_MODES) == [
|
||||
HVACMode.OFF,
|
||||
|
@ -219,7 +219,7 @@ async def test_set_temp_with_hvac_mode(hass: HomeAssistant) -> None:
|
|||
async def test_set_target_humidity_bad_attr(hass: HomeAssistant) -> None:
|
||||
"""Test setting the target humidity without required attribute."""
|
||||
state = hass.states.get(ENTITY_CLIMATE)
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 67
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 67.4
|
||||
|
||||
with pytest.raises(vol.Invalid):
|
||||
await hass.services.async_call(
|
||||
|
@ -230,13 +230,13 @@ async def test_set_target_humidity_bad_attr(hass: HomeAssistant) -> None:
|
|||
)
|
||||
|
||||
state = hass.states.get(ENTITY_CLIMATE)
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 67
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 67.4
|
||||
|
||||
|
||||
async def test_set_target_humidity(hass: HomeAssistant) -> None:
|
||||
"""Test the setting of the target humidity."""
|
||||
state = hass.states.get(ENTITY_CLIMATE)
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 67
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 67.4
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
|
|
|
@ -57,8 +57,8 @@ def test_setup_params(hass: HomeAssistant) -> None:
|
|||
"""Test the initial parameters."""
|
||||
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
||||
assert state.state == STATE_ON
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 54
|
||||
assert state.attributes.get(ATTR_CURRENT_HUMIDITY) == 59
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 54.2
|
||||
assert state.attributes.get(ATTR_CURRENT_HUMIDITY) == 59.4
|
||||
assert state.attributes.get(ATTR_ACTION) == "drying"
|
||||
|
||||
|
||||
|
@ -72,7 +72,7 @@ def test_default_setup_params(hass: HomeAssistant) -> None:
|
|||
async def test_set_target_humidity_bad_attr(hass: HomeAssistant) -> None:
|
||||
"""Test setting the target humidity without required attribute."""
|
||||
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 54
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 54.2
|
||||
|
||||
with pytest.raises(vol.Invalid):
|
||||
await hass.services.async_call(
|
||||
|
@ -84,13 +84,13 @@ async def test_set_target_humidity_bad_attr(hass: HomeAssistant) -> None:
|
|||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 54
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 54.2
|
||||
|
||||
|
||||
async def test_set_target_humidity(hass: HomeAssistant) -> None:
|
||||
"""Test the setting of the target humidity."""
|
||||
state = hass.states.get(ENTITY_DEHUMIDIFIER)
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 54
|
||||
assert state.attributes.get(ATTR_HUMIDITY) == 54.2
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
|
|
|
@ -254,7 +254,7 @@ async def test_query_climate_request(
|
|||
"thermostatTemperatureSetpoint": 21,
|
||||
"thermostatTemperatureAmbient": 22,
|
||||
"thermostatMode": "cool",
|
||||
"thermostatHumidityAmbient": 54,
|
||||
"thermostatHumidityAmbient": 54.2,
|
||||
"currentFanSpeedSetting": "on_high",
|
||||
}
|
||||
|
||||
|
@ -318,7 +318,7 @@ async def test_query_climate_request_f(
|
|||
"thermostatTemperatureSetpoint": -6.1,
|
||||
"thermostatTemperatureAmbient": -5.6,
|
||||
"thermostatMode": "cool",
|
||||
"thermostatHumidityAmbient": 54,
|
||||
"thermostatHumidityAmbient": 54.2,
|
||||
"currentFanSpeedSetting": "on_high",
|
||||
}
|
||||
hass_fixture.config.units.temperature_unit = UnitOfTemperature.CELSIUS
|
||||
|
@ -363,8 +363,8 @@ async def test_query_humidifier_request(
|
|||
assert devices["humidifier.dehumidifier"] == {
|
||||
"on": True,
|
||||
"online": True,
|
||||
"humiditySetpointPercent": 54,
|
||||
"humidityAmbientPercent": 59,
|
||||
"humiditySetpointPercent": 54.2,
|
||||
"humidityAmbientPercent": 59.4,
|
||||
}
|
||||
assert devices["humidifier.hygrostat"] == {
|
||||
"on": True,
|
||||
|
|
Loading…
Reference in New Issue