2015-01-06 08:10:33 +00:00
|
|
|
"""
|
|
|
|
homeassistant.components.thermostat
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Provides functionality to interact with thermostats.
|
|
|
|
"""
|
|
|
|
import logging
|
|
|
|
|
2015-03-22 02:37:18 +00:00
|
|
|
from homeassistant.helpers.entity_component import EntityComponent
|
2015-03-01 09:35:58 +00:00
|
|
|
|
2015-01-06 08:10:33 +00:00
|
|
|
import homeassistant.util as util
|
2015-03-22 02:16:13 +00:00
|
|
|
from homeassistant.helpers.entity import Entity
|
2015-01-06 08:10:33 +00:00
|
|
|
from homeassistant.const import (
|
2015-07-23 16:13:46 +00:00
|
|
|
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, TEMP_CELCIUS)
|
2015-01-06 08:10:33 +00:00
|
|
|
|
|
|
|
DOMAIN = "thermostat"
|
|
|
|
DEPENDENCIES = []
|
|
|
|
|
2015-03-01 09:35:58 +00:00
|
|
|
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
|
|
|
SCAN_INTERVAL = 60
|
|
|
|
|
2015-02-28 16:36:37 +00:00
|
|
|
SERVICE_SET_AWAY_MODE = "set_away_mode"
|
2015-01-06 08:10:33 +00:00
|
|
|
SERVICE_SET_TEMPERATURE = "set_temperature"
|
|
|
|
|
2015-01-12 05:21:18 +00:00
|
|
|
ATTR_CURRENT_TEMPERATURE = "current_temperature"
|
2015-01-06 08:10:33 +00:00
|
|
|
ATTR_AWAY_MODE = "away_mode"
|
2015-07-23 16:13:46 +00:00
|
|
|
ATTR_MAX_TEMP = "max_temp"
|
|
|
|
ATTR_MIN_TEMP = "min_temp"
|
2015-01-06 08:10:33 +00:00
|
|
|
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2015-03-01 09:35:58 +00:00
|
|
|
def set_away_mode(hass, away_mode, entity_id=None):
|
2015-01-06 08:10:33 +00:00
|
|
|
""" Turn all or specified thermostat away mode on. """
|
2015-02-28 16:36:37 +00:00
|
|
|
data = {
|
2015-03-01 09:35:58 +00:00
|
|
|
ATTR_AWAY_MODE: away_mode
|
2015-02-28 16:36:37 +00:00
|
|
|
}
|
2015-01-06 08:10:33 +00:00
|
|
|
|
2015-02-28 16:36:37 +00:00
|
|
|
if entity_id:
|
|
|
|
data[ATTR_ENTITY_ID] = entity_id
|
|
|
|
|
|
|
|
hass.services.call(DOMAIN, SERVICE_SET_AWAY_MODE, data)
|
2015-01-06 08:10:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
def set_temperature(hass, temperature, entity_id=None):
|
|
|
|
""" Set new target temperature. """
|
|
|
|
data = {ATTR_TEMPERATURE: temperature}
|
|
|
|
|
|
|
|
if entity_id is not None:
|
|
|
|
data[ATTR_ENTITY_ID] = entity_id
|
|
|
|
|
|
|
|
hass.services.call(DOMAIN, SERVICE_SET_TEMPERATURE, data)
|
|
|
|
|
|
|
|
|
|
|
|
def setup(hass, config):
|
|
|
|
""" Setup thermostats. """
|
2015-03-22 02:37:18 +00:00
|
|
|
component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
|
2015-03-01 09:35:58 +00:00
|
|
|
component.setup(config)
|
2015-01-06 08:10:33 +00:00
|
|
|
|
|
|
|
def thermostat_service(service):
|
|
|
|
""" Handles calls to the services. """
|
2015-02-17 18:12:27 +00:00
|
|
|
|
2015-01-06 08:10:33 +00:00
|
|
|
# Convert the entity ids to valid light ids
|
2015-03-06 07:17:05 +00:00
|
|
|
target_thermostats = component.extract_from_service(service)
|
2015-01-06 08:10:33 +00:00
|
|
|
|
2015-02-28 16:36:37 +00:00
|
|
|
if service.service == SERVICE_SET_AWAY_MODE:
|
|
|
|
away_mode = service.data.get(ATTR_AWAY_MODE)
|
2015-01-06 08:10:33 +00:00
|
|
|
|
2015-02-28 16:36:37 +00:00
|
|
|
if away_mode is None:
|
|
|
|
_LOGGER.error(
|
|
|
|
"Received call to %s without attribute %s",
|
|
|
|
SERVICE_SET_AWAY_MODE, ATTR_AWAY_MODE)
|
|
|
|
|
|
|
|
elif away_mode:
|
|
|
|
for thermostat in target_thermostats:
|
|
|
|
thermostat.turn_away_mode_on()
|
|
|
|
else:
|
|
|
|
for thermostat in target_thermostats:
|
|
|
|
thermostat.turn_away_mode_off()
|
2015-01-06 08:10:33 +00:00
|
|
|
|
|
|
|
elif service.service == SERVICE_SET_TEMPERATURE:
|
|
|
|
temperature = util.convert(
|
|
|
|
service.data.get(ATTR_TEMPERATURE), float)
|
|
|
|
|
|
|
|
if temperature is None:
|
|
|
|
return
|
|
|
|
|
|
|
|
for thermostat in target_thermostats:
|
2015-02-17 18:12:27 +00:00
|
|
|
thermostat.set_temperature(temperature)
|
2015-01-06 08:10:33 +00:00
|
|
|
|
|
|
|
for thermostat in target_thermostats:
|
2015-03-01 06:33:44 +00:00
|
|
|
thermostat.update_ha_state(True)
|
2015-01-06 08:10:33 +00:00
|
|
|
|
|
|
|
hass.services.register(
|
2015-02-28 16:36:37 +00:00
|
|
|
DOMAIN, SERVICE_SET_AWAY_MODE, thermostat_service)
|
2015-01-06 08:10:33 +00:00
|
|
|
|
|
|
|
hass.services.register(
|
|
|
|
DOMAIN, SERVICE_SET_TEMPERATURE, thermostat_service)
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2015-03-22 02:16:13 +00:00
|
|
|
class ThermostatDevice(Entity):
|
2015-01-06 08:10:33 +00:00
|
|
|
""" Represents a thermostat within Home Assistant. """
|
|
|
|
|
|
|
|
# pylint: disable=no-self-use
|
|
|
|
|
2015-01-12 05:21:18 +00:00
|
|
|
@property
|
|
|
|
def state(self):
|
|
|
|
""" Returns the current state. """
|
|
|
|
return self.target_temperature
|
2015-01-06 08:10:33 +00:00
|
|
|
|
2015-01-12 05:21:18 +00:00
|
|
|
@property
|
|
|
|
def device_state_attributes(self):
|
2015-01-06 08:10:33 +00:00
|
|
|
""" Returns device specific state attributes. """
|
2015-01-12 05:21:18 +00:00
|
|
|
return None
|
2015-01-06 08:10:33 +00:00
|
|
|
|
2015-01-12 05:21:18 +00:00
|
|
|
@property
|
|
|
|
def state_attributes(self):
|
2015-01-06 08:10:33 +00:00
|
|
|
""" Returns optional state attributes. """
|
|
|
|
data = {
|
2015-03-19 06:02:58 +00:00
|
|
|
ATTR_CURRENT_TEMPERATURE: self.hass.config.temperature(
|
|
|
|
self.current_temperature, self.unit_of_measurement)[0]
|
2015-01-06 08:10:33 +00:00
|
|
|
}
|
|
|
|
|
2015-01-12 05:21:18 +00:00
|
|
|
is_away = self.is_away_mode_on
|
|
|
|
|
|
|
|
if is_away is not None:
|
|
|
|
data[ATTR_AWAY_MODE] = STATE_ON if is_away else STATE_OFF
|
2015-01-06 08:10:33 +00:00
|
|
|
|
2015-01-12 05:21:18 +00:00
|
|
|
device_attr = self.device_state_attributes
|
|
|
|
|
|
|
|
if device_attr is not None:
|
|
|
|
data.update(device_attr)
|
2015-01-06 08:10:33 +00:00
|
|
|
|
2015-07-23 20:15:17 +00:00
|
|
|
data[ATTR_MIN_TEMP] = self.min_temp
|
|
|
|
data[ATTR_MAX_TEMP] = self.max_temp
|
2015-07-23 16:13:46 +00:00
|
|
|
|
2015-01-06 08:10:33 +00:00
|
|
|
return data
|
2015-01-12 05:21:18 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def current_temperature(self):
|
|
|
|
""" Returns the current temperature. """
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
@property
|
|
|
|
def target_temperature(self):
|
|
|
|
""" Returns the temperature we try to reach. """
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_away_mode_on(self):
|
|
|
|
"""
|
|
|
|
Returns if away mode is on.
|
|
|
|
Return None if no away mode available.
|
|
|
|
"""
|
|
|
|
return None
|
|
|
|
|
|
|
|
def set_temperate(self, temperature):
|
|
|
|
""" Set new target temperature. """
|
|
|
|
pass
|
|
|
|
|
|
|
|
def turn_away_mode_on(self):
|
|
|
|
""" Turns away mode on. """
|
|
|
|
pass
|
|
|
|
|
|
|
|
def turn_away_mode_off(self):
|
|
|
|
""" Turns away mode off. """
|
|
|
|
pass
|
2015-07-23 20:15:17 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def min_temp(self):
|
|
|
|
""" Return minimum temperature. """
|
|
|
|
return self.hass.config.temperature(7, TEMP_CELCIUS)[0]
|
|
|
|
|
|
|
|
@property
|
|
|
|
def max_temp(self):
|
|
|
|
""" Return maxmum temperature. """
|
|
|
|
return self.hass.config.temperature(35, TEMP_CELCIUS)[0]
|