1 """Support for Venstar WiFi Thermostats."""
3 from __future__
import annotations
5 import voluptuous
as vol
13 PLATFORM_SCHEMA
as CLIMATE_PLATFORM_SCHEMA,
46 HOLD_MODE_TEMPERATURE,
48 from .coordinator
import VenstarDataUpdateCoordinator
49 from .entity
import VenstarEntity
51 PLATFORM_SCHEMA = CLIMATE_PLATFORM_SCHEMA.extend(
53 vol.Required(CONF_HOST): cv.string,
54 vol.Optional(CONF_PASSWORD): cv.string,
55 vol.Optional(CONF_HUMIDIFIER, default=
True): cv.boolean,
56 vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
57 vol.Optional(CONF_TIMEOUT, default=5): vol.All(
58 vol.Coerce(int), vol.Range(min=1)
60 vol.Optional(CONF_USERNAME): cv.string,
61 vol.Optional(CONF_PIN): cv.string,
68 config_entry: ConfigEntry,
69 async_add_entities: AddEntitiesCallback,
71 """Set up the Venstar thermostat."""
72 venstar_data_coordinator = hass.data[DOMAIN][config_entry.entry_id]
76 venstar_data_coordinator,
86 add_entities: AddEntitiesCallback,
87 discovery_info: DiscoveryInfoType |
None =
None,
89 """Set up the Venstar thermostat platform.
91 Venstar uses config flow for configuration now. If an entry exists in
92 configuration.yaml, the import flow will attempt to import it and create
96 "Loading venstar via platform config is deprecated; The configuration"
97 " has been migrated to a config entry and can be safely removed"
100 if not hass.config_entries.async_entries(DOMAIN):
101 await hass.config_entries.flow.async_init(
102 DOMAIN, context={
"source": SOURCE_IMPORT}, data=config
107 """Representation of a Venstar thermostat."""
109 _attr_fan_modes = [FAN_ON, FAN_AUTO]
110 _attr_hvac_modes = [HVACMode.HEAT, HVACMode.COOL, HVACMode.OFF, HVACMode.AUTO]
111 _attr_precision = PRECISION_HALVES
113 _enable_turn_on_off_backwards_compatibility =
False
117 venstar_data_coordinator: VenstarDataUpdateCoordinator,
120 """Initialize the thermostat."""
121 super().
__init__(venstar_data_coordinator, config)
123 HVACMode.HEAT: self.
_client_client.MODE_HEAT,
124 HVACMode.COOL: self.
_client_client.MODE_COOL,
125 HVACMode.AUTO: self.
_client_client.MODE_AUTO,
131 """Return the list of supported features."""
133 ClimateEntityFeature.TARGET_TEMPERATURE
134 | ClimateEntityFeature.FAN_MODE
135 | ClimateEntityFeature.PRESET_MODE
136 | ClimateEntityFeature.TURN_OFF
137 | ClimateEntityFeature.TURN_ON
141 features |= ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
143 if self.
_client_client.hum_setpoint
is not None:
144 features |= ClimateEntityFeature.TARGET_HUMIDITY
150 """Return the unit of measurement, as defined by the API."""
151 if self.
_client_client.tempunits == self.
_client_client.TEMPUNITS_F:
152 return UnitOfTemperature.FAHRENHEIT
153 return UnitOfTemperature.CELSIUS
157 """Return the current temperature."""
158 return self.
_client_client.get_indoor_temp()
162 """Return the current humidity."""
163 return self.
_client_client.get_indoor_humidity()
167 """Return current operation mode ie. heat, cool, auto."""
178 """Return current operation mode ie. heat, cool, auto."""
180 return HVACAction.IDLE
181 if self.
_client_client.state == self.
_client_client.STATE_HEATING:
182 return HVACAction.HEATING
183 if self.
_client_client.state == self.
_client_client.STATE_COOLING:
184 return HVACAction.COOLING
185 return HVACAction.OFF
189 """Return the current fan mode."""
196 """Return the optional state attributes."""
198 ATTR_FAN_STATE: self.
_client_client.fanstate,
199 ATTR_HVAC_STATE: self.
_client_client.state,
204 """Return the target temperature we try to reach."""
206 return self.
_client_client.heattemp
208 return self.
_client_client.cooltemp
213 """Return the lower bound temp if auto mode is on."""
215 return self.
_client_client.heattemp
220 """Return the upper bound temp if auto mode is on."""
222 return self.
_client_client.cooltemp
227 """Return the humidity we try to reach."""
228 return self.
_client_client.hum_setpoint
232 """Return the minimum humidity. Hardcoded to 0 in API."""
237 """Return the maximum humidity. Hardcoded to 60 in API."""
242 """Return current preset."""
245 if self.
_client_client.schedule == 0:
246 return HOLD_MODE_TEMPERATURE
251 """Return valid preset modes."""
252 return [PRESET_NONE, PRESET_AWAY, HOLD_MODE_TEMPERATURE]
255 """Change the operation mode (internal)."""
256 if operation_mode == HVACMode.HEAT:
257 success = self.
_client_client.set_mode(self.
_client_client.MODE_HEAT)
258 elif operation_mode == HVACMode.COOL:
259 success = self.
_client_client.set_mode(self.
_client_client.MODE_COOL)
260 elif operation_mode == HVACMode.AUTO:
261 success = self.
_client_client.set_mode(self.
_client_client.MODE_AUTO)
263 success = self.
_client_client.set_mode(self.
_client_client.MODE_OFF)
266 _LOGGER.error(
"Failed to change the operation mode")
270 """Set a new target temperature."""
272 operation_mode = kwargs.get(ATTR_HVAC_MODE)
273 temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW)
274 temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH)
275 temperature = kwargs.get(ATTR_TEMPERATURE)
277 if operation_mode
and self.
_mode_map_mode_map.
get(operation_mode) != self.
_client_client.mode:
283 == self.
_client_client.MODE_HEAT
285 success = self.
_client_client.set_setpoints(temperature, self.
_client_client.cooltemp)
288 == self.
_client_client.MODE_COOL
290 success = self.
_client_client.set_setpoints(self.
_client_client.heattemp, temperature)
293 == self.
_client_client.MODE_AUTO
295 success = self.
_client_client.set_setpoints(temp_low, temp_high)
300 "The thermostat is currently not in a mode "
301 "that supports target temperature: %s"
307 _LOGGER.error(
"Failed to change the temperature")
311 """Set new target fan mode."""
312 if fan_mode == STATE_ON:
315 success = self.
_client_client.set_fan(self.
_client_client.FAN_AUTO)
318 _LOGGER.error(
"Failed to change the fan mode")
322 """Set new target operation mode."""
327 """Set new target humidity."""
328 success = self.
_client_client.set_hum_setpoint(humidity)
331 _LOGGER.error(
"Failed to change the target humidity level")
335 """Set the hold mode."""
336 if preset_mode == PRESET_AWAY:
337 success = self.
_client_client.set_away(self.
_client_client.AWAY_AWAY)
338 elif preset_mode == HOLD_MODE_TEMPERATURE:
339 success = self.
_client_client.set_away(self.
_client_client.AWAY_HOME)
340 success = success
and self.
_client_client.set_schedule(0)
341 elif preset_mode == PRESET_NONE:
342 success = self.
_client_client.set_away(self.
_client_client.AWAY_HOME)
343 success = success
and self.
_client_client.set_schedule(1)
345 _LOGGER.error(
"Unknown hold mode: %s", preset_mode)
349 _LOGGER.error(
"Failed to change the schedule/hold state")
None set_fan_mode(self, str fan_mode)
None set_preset_mode(self, str preset_mode)
str temperature_unit(self)
ClimateEntityFeature supported_features(self)
def current_humidity(self)
None set_hvac_mode(self, HVACMode hvac_mode)
def current_temperature(self)
def _set_operation_mode(self, HVACMode operation_mode)
HVACAction hvac_action(self)
None set_humidity(self, int humidity)
def target_temperature(self)
def set_temperature(self, **kwargs)
def extra_state_attributes(self)
def target_humidity(self)
def target_temperature_low(self)
def target_temperature_high(self)
None __init__(self, VenstarDataUpdateCoordinator venstar_data_coordinator, ConfigEntry config)
None schedule_update_ha_state(self, bool force_refresh=False)
web.Response get(self, web.Request request, str config_key)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)