diff --git a/.coveragerc b/.coveragerc index dc44541c0c3..08b93aa4b7e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -149,6 +149,7 @@ omit = homeassistant/components/climate/heatmiser.py homeassistant/components/climate/homematic.py homeassistant/components/climate/knx.py + homeassistant/components/climate/oem.py homeassistant/components/climate/proliphix.py homeassistant/components/climate/radiotherm.py homeassistant/components/cover/garadget.py diff --git a/homeassistant/components/climate/oem.py b/homeassistant/components/climate/oem.py new file mode 100644 index 00000000000..0280f116f1e --- /dev/null +++ b/homeassistant/components/climate/oem.py @@ -0,0 +1,148 @@ +""" +OpenEnergyMonitor Thermostat Support. + +This provides a climate component for the ESP8266 based thermostat sold by +OpenEnergyMonitor. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/climate.oem/ +""" +import logging + +import requests +import voluptuous as vol + +# Import the device class from the component that you want to support +from homeassistant.components.climate import ( + ClimateDevice, PLATFORM_SCHEMA, STATE_HEAT, STATE_IDLE, ATTR_TEMPERATURE) +from homeassistant.const import (CONF_HOST, CONF_USERNAME, CONF_PASSWORD, + CONF_PORT, TEMP_CELSIUS, CONF_NAME) +import homeassistant.helpers.config_validation as cv + +# Home Assistant depends on 3rd party packages for API specific code. +REQUIREMENTS = ['oemthermostat==1.1'] + +_LOGGER = logging.getLogger(__name__) + +# Local configs +CONF_AWAY_TEMP = 'away_temp' + +# Validation of the user's configuration +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_NAME, default="Thermostat"): cv.string, + vol.Optional(CONF_PORT, default=80): cv.port, + vol.Inclusive(CONF_USERNAME, 'authentication'): cv.string, + vol.Inclusive(CONF_PASSWORD, 'authentication'): cv.string, + vol.Optional(CONF_AWAY_TEMP, default=14): vol.Coerce(float) +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup oemthermostat.""" + from oemthermostat import Thermostat + + # Assign configuration variables. The configuration check takes care they + # are present. + name = config.get(CONF_NAME) + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + away_temp = config.get(CONF_AWAY_TEMP) + + # If creating the class raises an exception, it failed to connect or + # something else went wrong. + try: + therm = Thermostat(host, port=port, + username=username, password=password) + except (ValueError, AssertionError, requests.RequestException): + return False + + # Add devices + add_devices((ThermostatDevice(hass, therm, name, away_temp), ), True) + + +class ThermostatDevice(ClimateDevice): + """Interface class for the oemthermostat module and HA.""" + + def __init__(self, hass, thermostat, name, away_temp): + """Initialize the device.""" + self._name = name + self.hass = hass + + # Away mode stuff + self._away = False + self._away_temp = away_temp + self._prev_temp = thermostat.setpoint + + self.thermostat = thermostat + # Set the thermostat mode to manual + self.thermostat.mode = 2 + + # set up internal state varS + self._state = None + self._temperature = None + self._setpoint = None + + @property + def name(self): + """Name of this Thermostat.""" + return self._name + + @property + def temperature_unit(self): + """The unit of measurement used by the platform.""" + return TEMP_CELSIUS + + @property + def current_operation(self): + """Return current operation i.e. heat, cool, idle.""" + if self._state: + return STATE_HEAT + else: + return STATE_IDLE + + @property + def current_temperature(self): + """Return the current temperature.""" + return self._temperature + + @property + def target_temperature(self): + """Return the temperature we try to reach.""" + return self._setpoint + + def set_temperature(self, **kwargs): + """Change the setpoint of the thermostat.""" + # If we are setting the temp, then we don't want away mode anymore. + self.turn_away_mode_off() + + temp = kwargs.get(ATTR_TEMPERATURE) + self.thermostat.setpoint = temp + + @property + def is_away_mode_on(self): + """Return true if away mode is on.""" + return self._away + + def turn_away_mode_on(self): + """Turn away mode on.""" + if not self._away: + self._prev_temp = self._setpoint + + self.thermostat.setpoint = self._away_temp + self._away = True + + def turn_away_mode_off(self): + """Turn away mode off.""" + if self._away: + self.thermostat.setpoint = self._prev_temp + + self._away = False + + def update(self): + """Update local state.""" + self._setpoint = self.thermostat.setpoint + self._temperature = self.thermostat.temperature + self._state = self.thermostat.state diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 62aa6353908..5159326a7b3 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 62aa6353908851a8fd648a981e9bf06f2a14a6dc +Subproject commit 5159326a7b3d1ba29ae17a7861fa2eaa8c2c95f6 diff --git a/requirements_all.txt b/requirements_all.txt index 733c6c4e513..b83c94a2276 100755 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -352,6 +352,9 @@ neurio==0.3.1 # homeassistant.components.google oauth2client==4.0.0 +# homeassistant.components.climate.oem +oemthermostat==1.1 + # homeassistant.components.sensor.openevse openevsewifi==0.4