mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 07:07:28 +00:00
Correctly support humidification and dehumidification in Nexia Thermostats (#139792)
* Add set_dehumidify_setpoint service. Refactor set_humidify_setpoint. * Add closest_value function in utils * Refactor target humidity * Update tests for util.py * Refactor target humidity. Update tests. * Remove duplicate constant * Add humidify and dehumidfy sensors * Update sensor names * Remove clamping and commented code * Iplement suggestions from review * Switch order check order * remove closest_value() * Update strings for clarity/grammar * Update strings for grammar/clarity * tweaks --------- Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
2876e5d0cd
commit
691cb378a0
@ -53,13 +53,18 @@ PARALLEL_UPDATES = 1 # keep data in sync with only one connection at a time
|
|||||||
|
|
||||||
SERVICE_SET_AIRCLEANER_MODE = "set_aircleaner_mode"
|
SERVICE_SET_AIRCLEANER_MODE = "set_aircleaner_mode"
|
||||||
SERVICE_SET_HUMIDIFY_SETPOINT = "set_humidify_setpoint"
|
SERVICE_SET_HUMIDIFY_SETPOINT = "set_humidify_setpoint"
|
||||||
|
SERVICE_SET_DEHUMIDIFY_SETPOINT = "set_dehumidify_setpoint"
|
||||||
SERVICE_SET_HVAC_RUN_MODE = "set_hvac_run_mode"
|
SERVICE_SET_HVAC_RUN_MODE = "set_hvac_run_mode"
|
||||||
|
|
||||||
SET_AIRCLEANER_SCHEMA: VolDictType = {
|
SET_AIRCLEANER_SCHEMA: VolDictType = {
|
||||||
vol.Required(ATTR_AIRCLEANER_MODE): cv.string,
|
vol.Required(ATTR_AIRCLEANER_MODE): cv.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_HUMIDITY_SCHEMA: VolDictType = {
|
SET_HUMIDIFY_SCHEMA: VolDictType = {
|
||||||
|
vol.Required(ATTR_HUMIDITY): vol.All(vol.Coerce(int), vol.Range(min=10, max=45)),
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_DEHUMIDIFY_SCHEMA: VolDictType = {
|
||||||
vol.Required(ATTR_HUMIDITY): vol.All(vol.Coerce(int), vol.Range(min=35, max=65)),
|
vol.Required(ATTR_HUMIDITY): vol.All(vol.Coerce(int), vol.Range(min=35, max=65)),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,9 +131,14 @@ async def async_setup_entry(
|
|||||||
|
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_SET_HUMIDIFY_SETPOINT,
|
SERVICE_SET_HUMIDIFY_SETPOINT,
|
||||||
SET_HUMIDITY_SCHEMA,
|
SET_HUMIDIFY_SCHEMA,
|
||||||
f"async_{SERVICE_SET_HUMIDIFY_SETPOINT}",
|
f"async_{SERVICE_SET_HUMIDIFY_SETPOINT}",
|
||||||
)
|
)
|
||||||
|
platform.async_register_entity_service(
|
||||||
|
SERVICE_SET_DEHUMIDIFY_SETPOINT,
|
||||||
|
SET_DEHUMIDIFY_SCHEMA,
|
||||||
|
f"async_{SERVICE_SET_DEHUMIDIFY_SETPOINT}",
|
||||||
|
)
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_SET_AIRCLEANER_MODE,
|
SERVICE_SET_AIRCLEANER_MODE,
|
||||||
SET_AIRCLEANER_SCHEMA,
|
SET_AIRCLEANER_SCHEMA,
|
||||||
@ -224,20 +234,48 @@ class NexiaZone(NexiaThermostatZoneEntity, ClimateEntity):
|
|||||||
return self._zone.get_preset()
|
return self._zone.get_preset()
|
||||||
|
|
||||||
async def async_set_humidity(self, humidity: int) -> None:
|
async def async_set_humidity(self, humidity: int) -> None:
|
||||||
"""Dehumidify target."""
|
"""Set humidity targets.
|
||||||
if self._thermostat.has_dehumidify_support():
|
|
||||||
await self.async_set_dehumidify_setpoint(humidity)
|
HA doesn't support separate humidify and dehumidify targets.
|
||||||
|
Set the target for the current mode if in [heat, cool]
|
||||||
|
otherwise set both targets to the clamped values.
|
||||||
|
"""
|
||||||
|
zone_current_mode = self._zone.get_current_mode()
|
||||||
|
if zone_current_mode == OPERATION_MODE_HEAT:
|
||||||
|
if self._thermostat.has_humidify_support():
|
||||||
|
await self.async_set_humidify_setpoint(humidity)
|
||||||
|
elif zone_current_mode == OPERATION_MODE_COOL:
|
||||||
|
if self._thermostat.has_dehumidify_support():
|
||||||
|
await self.async_set_dehumidify_setpoint(humidity)
|
||||||
else:
|
else:
|
||||||
await self.async_set_humidify_setpoint(humidity)
|
if self._thermostat.has_humidify_support():
|
||||||
|
await self.async_set_humidify_setpoint(humidity)
|
||||||
|
if self._thermostat.has_dehumidify_support():
|
||||||
|
await self.async_set_dehumidify_setpoint(humidity)
|
||||||
self._signal_thermostat_update()
|
self._signal_thermostat_update()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_humidity(self):
|
def target_humidity(self) -> float | None:
|
||||||
"""Humidity indoors setpoint."""
|
"""Humidity indoors setpoint.
|
||||||
|
|
||||||
|
In systems that support both humidification and dehumidification,
|
||||||
|
two values for target exist. We must choose one to return.
|
||||||
|
|
||||||
|
:return: The target humidity setpoint.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# If heat is on, always return humidify value first
|
||||||
|
if (
|
||||||
|
self._has_humidify_support
|
||||||
|
and self._zone.get_current_mode() == OPERATION_MODE_HEAT
|
||||||
|
):
|
||||||
|
return percent_conv(self._thermostat.get_humidify_setpoint())
|
||||||
|
# Fall back to previous behavior of returning dehumidify value then humidify
|
||||||
if self._has_dehumidify_support:
|
if self._has_dehumidify_support:
|
||||||
return percent_conv(self._thermostat.get_dehumidify_setpoint())
|
return percent_conv(self._thermostat.get_dehumidify_setpoint())
|
||||||
if self._has_humidify_support:
|
if self._has_humidify_support:
|
||||||
return percent_conv(self._thermostat.get_humidify_setpoint())
|
return percent_conv(self._thermostat.get_humidify_setpoint())
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -26,6 +26,9 @@
|
|||||||
"set_humidify_setpoint": {
|
"set_humidify_setpoint": {
|
||||||
"service": "mdi:water-percent"
|
"service": "mdi:water-percent"
|
||||||
},
|
},
|
||||||
|
"set_dehumidify_setpoint": {
|
||||||
|
"service": "mdi:water-percent"
|
||||||
|
},
|
||||||
"set_hvac_run_mode": {
|
"set_hvac_run_mode": {
|
||||||
"service": "mdi:hvac"
|
"service": "mdi:hvac"
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,35 @@ async def async_setup_entry(
|
|||||||
percent_conv,
|
percent_conv,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
# Heating Humidification Setpoint
|
||||||
|
if thermostat.has_humidify_support():
|
||||||
|
entities.append(
|
||||||
|
NexiaThermostatSensor(
|
||||||
|
coordinator,
|
||||||
|
thermostat,
|
||||||
|
"get_humidify_setpoint",
|
||||||
|
"get_humidify_setpoint",
|
||||||
|
SensorDeviceClass.HUMIDITY,
|
||||||
|
PERCENTAGE,
|
||||||
|
SensorStateClass.MEASUREMENT,
|
||||||
|
percent_conv,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Cooling Dehumidification Setpoint
|
||||||
|
if thermostat.has_dehumidify_support():
|
||||||
|
entities.append(
|
||||||
|
NexiaThermostatSensor(
|
||||||
|
coordinator,
|
||||||
|
thermostat,
|
||||||
|
"get_dehumidify_setpoint",
|
||||||
|
"get_dehumidify_setpoint",
|
||||||
|
SensorDeviceClass.HUMIDITY,
|
||||||
|
PERCENTAGE,
|
||||||
|
SensorStateClass.MEASUREMENT,
|
||||||
|
percent_conv,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Zone Sensors
|
# Zone Sensors
|
||||||
for zone_id in thermostat.get_zone_ids():
|
for zone_id in thermostat.get_zone_ids():
|
||||||
|
@ -14,6 +14,20 @@ set_aircleaner_mode:
|
|||||||
- "quick"
|
- "quick"
|
||||||
|
|
||||||
set_humidify_setpoint:
|
set_humidify_setpoint:
|
||||||
|
target:
|
||||||
|
entity:
|
||||||
|
integration: nexia
|
||||||
|
domain: climate
|
||||||
|
fields:
|
||||||
|
humidity:
|
||||||
|
required: true
|
||||||
|
selector:
|
||||||
|
number:
|
||||||
|
min: 10
|
||||||
|
max: 45
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
|
||||||
|
set_dehumidify_setpoint:
|
||||||
target:
|
target:
|
||||||
entity:
|
entity:
|
||||||
integration: nexia
|
integration: nexia
|
||||||
|
@ -53,6 +53,12 @@
|
|||||||
},
|
},
|
||||||
"zone_setpoint_status": {
|
"zone_setpoint_status": {
|
||||||
"name": "Zone setpoint status"
|
"name": "Zone setpoint status"
|
||||||
|
},
|
||||||
|
"get_humidify_setpoint": {
|
||||||
|
"name": "Heating humidify setpoint"
|
||||||
|
},
|
||||||
|
"get_dehumidify_setpoint": {
|
||||||
|
"name": "Cooling dehumidify setpoint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"switch": {
|
"switch": {
|
||||||
@ -76,12 +82,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"set_humidify_setpoint": {
|
"set_humidify_setpoint": {
|
||||||
"name": "Set humidify set point",
|
"name": "Set humidify setpoint",
|
||||||
"description": "Sets the target humidity.",
|
"description": "Sets the target humidity for heating.",
|
||||||
"fields": {
|
"fields": {
|
||||||
"humidity": {
|
"humidity": {
|
||||||
"name": "Humidity",
|
"name": "Humidity",
|
||||||
"description": "The humidification setpoint."
|
"description": "The setpoint for humidification when heating."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"set_dehumidify_setpoint": {
|
||||||
|
"name": "Set dehumidify setpoint",
|
||||||
|
"description": "Sets the target humidity for cooling.",
|
||||||
|
"fields": {
|
||||||
|
"humidity": {
|
||||||
|
"name": "Humidity",
|
||||||
|
"description": "The setpoint for dehumidification when cooling."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user