mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Update nexia climate platform to use newer standards (#64186)
This commit is contained in:
parent
92b48cca7e
commit
187b4fad84
@ -731,6 +731,7 @@ omit =
|
||||
homeassistant/components/netgear_lte/*
|
||||
homeassistant/components/netio/switch.py
|
||||
homeassistant/components/neurio_energy/sensor.py
|
||||
homeassistant/components/nexia/entity.py
|
||||
homeassistant/components/nexia/climate.py
|
||||
homeassistant/components/nextcloud/*
|
||||
homeassistant/components/nfandroidtv/__init__.py
|
||||
|
@ -1,4 +1,6 @@
|
||||
"""Support for Nexia / Trane XL thermostats."""
|
||||
from __future__ import annotations
|
||||
|
||||
from nexia.const import (
|
||||
HOLD_PERMANENT,
|
||||
HOLD_RESUME_SCHEDULE,
|
||||
@ -9,17 +11,17 @@ from nexia.const import (
|
||||
SYSTEM_STATUS_COOL,
|
||||
SYSTEM_STATUS_HEAT,
|
||||
SYSTEM_STATUS_IDLE,
|
||||
UNIT_FAHRENHEIT,
|
||||
)
|
||||
from nexia.home import NexiaHome
|
||||
from nexia.thermostat import NexiaThermostat
|
||||
from nexia.util import find_humidity_setpoint
|
||||
from nexia.zone import NexiaThermostatZone
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.climate import ClimateEntity
|
||||
from homeassistant.components.climate.const import (
|
||||
ATTR_HUMIDITY,
|
||||
ATTR_HVAC_MODE,
|
||||
ATTR_MAX_HUMIDITY,
|
||||
ATTR_MIN_HUMIDITY,
|
||||
ATTR_TARGET_TEMP_HIGH,
|
||||
ATTR_TARGET_TEMP_LOW,
|
||||
CURRENT_HVAC_COOL,
|
||||
@ -43,7 +45,6 @@ from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_platform
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.dispatcher import dispatcher_send
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import (
|
||||
@ -55,8 +56,6 @@ from .const import (
|
||||
ATTR_RUN_MODE,
|
||||
ATTR_ZONE_STATUS,
|
||||
DOMAIN,
|
||||
SIGNAL_THERMOSTAT_UPDATE,
|
||||
SIGNAL_ZONE_UPDATE,
|
||||
)
|
||||
from .coordinator import NexiaDataUpdateCoordinator
|
||||
from .entity import NexiaThermostatZoneEntity
|
||||
@ -108,6 +107,21 @@ NEXIA_TO_HA_HVAC_MODE_MAP = {
|
||||
value: key for key, value in HA_TO_NEXIA_HVAC_MODE_MAP.items()
|
||||
}
|
||||
|
||||
HVAC_MODES = [
|
||||
HVAC_MODE_OFF,
|
||||
HVAC_MODE_AUTO,
|
||||
HVAC_MODE_HEAT_COOL,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_COOL,
|
||||
]
|
||||
|
||||
NEXIA_SUPPORTED = (
|
||||
SUPPORT_TARGET_TEMPERATURE_RANGE
|
||||
| SUPPORT_TARGET_TEMPERATURE
|
||||
| SUPPORT_FAN_MODE
|
||||
| SUPPORT_PRESET_MODE
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
@ -116,7 +130,7 @@ async def async_setup_entry(
|
||||
) -> None:
|
||||
"""Set up climate for a Nexia device."""
|
||||
coordinator: NexiaDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||
nexia_home = coordinator.nexia_home
|
||||
nexia_home: NexiaHome = coordinator.nexia_home
|
||||
|
||||
platform = entity_platform.async_get_current_platform()
|
||||
|
||||
@ -132,61 +146,57 @@ async def async_setup_entry(
|
||||
SERVICE_SET_HVAC_RUN_MODE, SET_HVAC_RUN_MODE_SCHEMA, SERVICE_SET_HVAC_RUN_MODE
|
||||
)
|
||||
|
||||
entities = []
|
||||
entities: list[NexiaZone] = []
|
||||
for thermostat_id in nexia_home.get_thermostat_ids():
|
||||
thermostat = nexia_home.get_thermostat_by_id(thermostat_id)
|
||||
thermostat: NexiaThermostat = nexia_home.get_thermostat_by_id(thermostat_id)
|
||||
for zone_id in thermostat.get_zone_ids():
|
||||
zone = thermostat.get_zone_by_id(zone_id)
|
||||
zone: NexiaThermostatZone = thermostat.get_zone_by_id(zone_id)
|
||||
entities.append(NexiaZone(coordinator, zone))
|
||||
|
||||
async_add_entities(entities, True)
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class NexiaZone(NexiaThermostatZoneEntity, ClimateEntity):
|
||||
"""Provides Nexia Climate support."""
|
||||
|
||||
def __init__(self, coordinator, zone):
|
||||
def __init__(
|
||||
self, coordinator: NexiaDataUpdateCoordinator, zone: NexiaThermostatZone
|
||||
) -> None:
|
||||
"""Initialize the thermostat."""
|
||||
super().__init__(
|
||||
coordinator, zone, name=zone.get_name(), unique_id=zone.zone_id
|
||||
)
|
||||
self._undo_humidfy_dispatcher = None
|
||||
self._undo_aircleaner_dispatcher = None
|
||||
unit = self._thermostat.get_unit()
|
||||
min_humidity, max_humidity = self._thermostat.get_humidity_setpoint_limits()
|
||||
min_setpoint, max_setpoint = self._thermostat.get_setpoint_limits()
|
||||
# The has_* calls are stable for the life of the device
|
||||
# and do not do I/O
|
||||
self._has_relative_humidity = self._thermostat.has_relative_humidity()
|
||||
self._has_emergency_heat = self._thermostat.has_emergency_heat()
|
||||
self._has_humidify_support = self._thermostat.has_humidify_support()
|
||||
self._has_dehumidify_support = self._thermostat.has_dehumidify_support()
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Return the list of supported features."""
|
||||
supported = (
|
||||
SUPPORT_TARGET_TEMPERATURE_RANGE
|
||||
| SUPPORT_TARGET_TEMPERATURE
|
||||
| SUPPORT_FAN_MODE
|
||||
| SUPPORT_PRESET_MODE
|
||||
)
|
||||
|
||||
supported = NEXIA_SUPPORTED
|
||||
if self._has_humidify_support or self._has_dehumidify_support:
|
||||
supported |= SUPPORT_TARGET_HUMIDITY
|
||||
|
||||
if self._has_emergency_heat:
|
||||
supported |= SUPPORT_AUX_HEAT
|
||||
|
||||
return supported
|
||||
self._attr_supported_features = supported
|
||||
self._attr_preset_modes = self._zone.get_presets()
|
||||
self._attr_fan_modes = self._thermostat.get_fan_modes()
|
||||
self._attr_hvac_modes = HVAC_MODES
|
||||
self._attr_min_humidity = percent_conv(min_humidity)
|
||||
self._attr_max_humidity = percent_conv(max_humidity)
|
||||
self._attr_min_temp = min_setpoint
|
||||
self._attr_max_temp = max_setpoint
|
||||
self._attr_temperature_unit = TEMP_CELSIUS if unit == "C" else TEMP_FAHRENHEIT
|
||||
self._attr_target_temperature_step = 0.5 if unit == "C" else 1.0
|
||||
self._attr_preset_modes = self._zone.get_presets()
|
||||
|
||||
@property
|
||||
def is_fan_on(self):
|
||||
"""Blower is on."""
|
||||
return self._thermostat.is_blower_active()
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
"""Return the unit of measurement."""
|
||||
return TEMP_CELSIUS if self._thermostat.get_unit() == "C" else TEMP_FAHRENHEIT
|
||||
|
||||
@property
|
||||
def current_temperature(self):
|
||||
"""Return the current temperature."""
|
||||
@ -197,21 +207,6 @@ class NexiaZone(NexiaThermostatZoneEntity, ClimateEntity):
|
||||
"""Return the fan setting."""
|
||||
return self._thermostat.get_fan_mode()
|
||||
|
||||
@property
|
||||
def fan_modes(self):
|
||||
"""Return the list of available fan modes."""
|
||||
return self._thermostat.get_fan_modes()
|
||||
|
||||
@property
|
||||
def min_temp(self):
|
||||
"""Minimum temp for the current setting."""
|
||||
return (self._thermostat.get_setpoint_limits())[0]
|
||||
|
||||
@property
|
||||
def max_temp(self):
|
||||
"""Maximum temp for the current setting."""
|
||||
return (self._thermostat.get_setpoint_limits())[1]
|
||||
|
||||
def set_fan_mode(self, fan_mode):
|
||||
"""Set new target fan mode."""
|
||||
self._thermostat.set_fan_mode(fan_mode)
|
||||
@ -233,11 +228,6 @@ class NexiaZone(NexiaThermostatZoneEntity, ClimateEntity):
|
||||
"""Preset that is active."""
|
||||
return self._zone.get_preset()
|
||||
|
||||
@property
|
||||
def preset_modes(self):
|
||||
"""All presets."""
|
||||
return self._zone.get_presets()
|
||||
|
||||
def set_humidity(self, humidity):
|
||||
"""Dehumidify target."""
|
||||
if self._thermostat.has_dehumidify_support():
|
||||
@ -273,13 +263,6 @@ class NexiaZone(NexiaThermostatZoneEntity, ClimateEntity):
|
||||
return self._zone.get_heating_setpoint()
|
||||
return None
|
||||
|
||||
@property
|
||||
def target_temperature_step(self):
|
||||
"""Step size of temperature units."""
|
||||
if self._thermostat.get_unit() == UNIT_FAHRENHEIT:
|
||||
return 1.0
|
||||
return 0.5
|
||||
|
||||
@property
|
||||
def target_temperature_high(self):
|
||||
"""Highest temperature we are trying to reach."""
|
||||
@ -332,17 +315,6 @@ class NexiaZone(NexiaThermostatZoneEntity, ClimateEntity):
|
||||
|
||||
return NEXIA_TO_HA_HVAC_MODE_MAP[mode]
|
||||
|
||||
@property
|
||||
def hvac_modes(self):
|
||||
"""List of HVAC available modes."""
|
||||
return [
|
||||
HVAC_MODE_OFF,
|
||||
HVAC_MODE_AUTO,
|
||||
HVAC_MODE_HEAT_COOL,
|
||||
HVAC_MODE_HEAT,
|
||||
HVAC_MODE_COOL,
|
||||
]
|
||||
|
||||
def set_temperature(self, **kwargs):
|
||||
"""Set target temperature."""
|
||||
new_heat_temp = kwargs.get(ATTR_TARGET_TEMP_LOW)
|
||||
@ -397,12 +369,8 @@ class NexiaZone(NexiaThermostatZoneEntity, ClimateEntity):
|
||||
if not self._has_relative_humidity:
|
||||
return data
|
||||
|
||||
min_humidity = percent_conv(self._thermostat.get_humidity_setpoint_limits()[0])
|
||||
max_humidity = percent_conv(self._thermostat.get_humidity_setpoint_limits()[1])
|
||||
data.update(
|
||||
{
|
||||
ATTR_MIN_HUMIDITY: min_humidity,
|
||||
ATTR_MAX_HUMIDITY: max_humidity,
|
||||
ATTR_DEHUMIDIFY_SUPPORTED: self._has_dehumidify_support,
|
||||
ATTR_HUMIDIFY_SUPPORTED: self._has_humidify_support,
|
||||
}
|
||||
@ -454,7 +422,7 @@ class NexiaZone(NexiaThermostatZoneEntity, ClimateEntity):
|
||||
self._zone.call_permanent_hold()
|
||||
self._zone.set_mode(mode=HA_TO_NEXIA_HVAC_MODE_MAP[hvac_mode])
|
||||
|
||||
self.schedule_update_ha_state()
|
||||
self._signal_zone_update()
|
||||
|
||||
def set_aircleaner_mode(self, aircleaner_mode):
|
||||
"""Set the aircleaner mode."""
|
||||
@ -480,26 +448,3 @@ class NexiaZone(NexiaThermostatZoneEntity, ClimateEntity):
|
||||
return
|
||||
self._thermostat.set_dehumidify_setpoint(target_humidity)
|
||||
self._signal_thermostat_update()
|
||||
|
||||
def _signal_thermostat_update(self):
|
||||
"""Signal a thermostat update.
|
||||
|
||||
Whenever the underlying library does an action against
|
||||
a thermostat, the data for the thermostat and all
|
||||
connected zone is updated.
|
||||
|
||||
Update all the zones on the thermostat.
|
||||
"""
|
||||
dispatcher_send(
|
||||
self.hass, f"{SIGNAL_THERMOSTAT_UPDATE}-{self._thermostat.thermostat_id}"
|
||||
)
|
||||
|
||||
def _signal_zone_update(self):
|
||||
"""Signal a zone update.
|
||||
|
||||
Whenever the underlying library does an action against
|
||||
a zone, the data for the zone is updated.
|
||||
|
||||
Update a single zone.
|
||||
"""
|
||||
dispatcher_send(self.hass, f"{SIGNAL_ZONE_UPDATE}-{self._zone.zone_id}")
|
||||
|
@ -1,6 +1,9 @@
|
||||
"""The nexia integration base entity."""
|
||||
from nexia.thermostat import NexiaThermostat
|
||||
from nexia.zone import NexiaThermostatZone
|
||||
|
||||
from homeassistant.const import ATTR_ATTRIBUTION
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect, dispatcher_send
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
@ -47,7 +50,7 @@ class NexiaThermostatEntity(NexiaEntity):
|
||||
def __init__(self, coordinator, thermostat, name, unique_id):
|
||||
"""Initialize the entity."""
|
||||
super().__init__(coordinator, name, unique_id)
|
||||
self._thermostat = thermostat
|
||||
self._thermostat: NexiaThermostat = thermostat
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
@ -73,6 +76,19 @@ class NexiaThermostatEntity(NexiaEntity):
|
||||
)
|
||||
)
|
||||
|
||||
def _signal_thermostat_update(self):
|
||||
"""Signal a thermostat update.
|
||||
|
||||
Whenever the underlying library does an action against
|
||||
a thermostat, the data for the thermostat and all
|
||||
connected zone is updated.
|
||||
|
||||
Update all the zones on the thermostat.
|
||||
"""
|
||||
dispatcher_send(
|
||||
self.hass, f"{SIGNAL_THERMOSTAT_UPDATE}-{self._thermostat.thermostat_id}"
|
||||
)
|
||||
|
||||
|
||||
class NexiaThermostatZoneEntity(NexiaThermostatEntity):
|
||||
"""Base class for nexia devices attached to a thermostat."""
|
||||
@ -80,7 +96,7 @@ class NexiaThermostatZoneEntity(NexiaThermostatEntity):
|
||||
def __init__(self, coordinator, zone, name, unique_id):
|
||||
"""Initialize the entity."""
|
||||
super().__init__(coordinator, zone.thermostat, name, unique_id)
|
||||
self._zone = zone
|
||||
self._zone: NexiaThermostatZone = zone
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
@ -107,3 +123,13 @@ class NexiaThermostatZoneEntity(NexiaThermostatEntity):
|
||||
self.async_write_ha_state,
|
||||
)
|
||||
)
|
||||
|
||||
def _signal_zone_update(self):
|
||||
"""Signal a zone update.
|
||||
|
||||
Whenever the underlying library does an action against
|
||||
a zone, the data for the zone is updated.
|
||||
|
||||
Update a single zone.
|
||||
"""
|
||||
dispatcher_send(self.hass, f"{SIGNAL_ZONE_UPDATE}-{self._zone.zone_id}")
|
||||
|
Loading…
x
Reference in New Issue
Block a user