diff --git a/.coveragerc b/.coveragerc index adb3c59765e..57c3d89d647 100644 --- a/.coveragerc +++ b/.coveragerc @@ -41,6 +41,9 @@ omit = homeassistant/components/mysensors.py homeassistant/components/*/mysensors.py + homeassistant/components/nest.py + homeassistant/components/*/nest.py + homeassistant/components/rpi_gpio.py homeassistant/components/*/rpi_gpio.py @@ -124,7 +127,6 @@ omit = homeassistant/components/thermostat/heatmiser.py homeassistant/components/thermostat/homematic.py homeassistant/components/thermostat/honeywell.py - homeassistant/components/thermostat/nest.py homeassistant/components/thermostat/proliphix.py homeassistant/components/thermostat/radiotherm.py diff --git a/homeassistant/components/binary_sensor/nest.py b/homeassistant/components/binary_sensor/nest.py new file mode 100644 index 00000000000..e1414de5648 --- /dev/null +++ b/homeassistant/components/binary_sensor/nest.py @@ -0,0 +1,56 @@ +""" +homeassistant.components.binary.nest +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Support for Nest Thermostat Binary Sensors. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.nest/ +""" +import logging +import socket +import homeassistant.components.nest as nest + +from homeassistant.components.sensor.nest import NestSensor +from homeassistant.components.binary_sensor import BinarySensorDevice + + +BINARY_TYPES = ['fan', + 'hvac_ac_state', + 'hvac_aux_heater_state', + 'hvac_heat_x2_state', + 'hvac_heat_x3_state', + 'hvac_alt_heat_state', + 'hvac_alt_heat_x2_state', + 'hvac_emer_heat_state', + 'online'] + + +def setup_platform(hass, config, add_devices, discovery_info=None): + "Setup nest binary sensors from config file" + + logger = logging.getLogger(__name__) + try: + for structure in nest.NEST.structures: + for device in structure.devices: + for variable in config['monitored_conditions']: + if variable in BINARY_TYPES: + add_devices([NestBinarySensor(structure, + device, + variable)]) + else: + logger.error('Nest sensor type: "%s" does not exist', + variable) + except socket.error: + logger.error( + "Connection error logging into the nest web service." + ) + + +class NestBinarySensor(NestSensor, BinarySensorDevice): + """ Represents a Nst Binary sensor. """ + + @property + def is_on(self): + "Returns is the binary sensor is on or off" + + return bool(getattr(self.device, self.variable)) diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py new file mode 100644 index 00000000000..1b1d940595a --- /dev/null +++ b/homeassistant/components/nest.py @@ -0,0 +1,37 @@ +""" +homeassistant.components.thermostat.nest +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Adds support for Nest thermostats. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/thermostat.nest/ +""" +import logging + +from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD) + +REQUIREMENTS = ['python-nest==2.6.0'] +DOMAIN = 'nest' + +NEST = None + + +# pylint: disable=unused-argument +def setup(hass, config): + """ Sets up the nest thermostat. """ + global NEST + + logger = logging.getLogger(__name__) + username = config[DOMAIN].get(CONF_USERNAME) + password = config[DOMAIN].get(CONF_PASSWORD) + + if username is None or password is None: + logger.error("Missing required configuration items %s or %s", + CONF_USERNAME, CONF_PASSWORD) + return + + import nest + + NEST = nest.Nest(username, password) + + return True diff --git a/homeassistant/components/sensor/nest.py b/homeassistant/components/sensor/nest.py new file mode 100644 index 00000000000..040469d2e13 --- /dev/null +++ b/homeassistant/components/sensor/nest.py @@ -0,0 +1,109 @@ +""" +homeassistant.components.sensor.nest +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Support for Nest Thermostat Sensors. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.nest/ +""" +import logging +import socket +import homeassistant.components.nest as nest + +from homeassistant.helpers.entity import Entity +from homeassistant.const import TEMP_CELCIUS + +DEPENDENCIES = ['nest'] +SENSOR_TYPES = ['humidity', + 'mode', + 'last_ip', + 'local_ip', + 'last_connection', + 'battery_level'] + +SENSOR_UNITS = {'humidity': '%', 'battery_level': '%'} + +SENSOR_TEMP_TYPES = ['temperature', + 'target', + 'away_temperature[0]', + 'away_temperature[1]'] + + +def setup_platform(hass, config, add_devices, discovery_info=None): + "Setup Nest Sensor from config file" + + logger = logging.getLogger(__name__) + try: + for structure in nest.NEST.structures: + for device in structure.devices: + for variable in config['monitored_conditions']: + if variable in SENSOR_TYPES: + add_devices([NestBasicSensor(structure, + device, + variable)]) + elif variable in SENSOR_TEMP_TYPES: + add_devices([NestTempSensor(structure, + device, + variable)]) + else: + logger.error('Nest sensor type: "%s" does not exist', + variable) + except socket.error: + logger.error( + "Connection error logging into the nest web service." + ) + + +class NestSensor(Entity): + """ Represents a Nest sensor. """ + + def __init__(self, structure, device, variable): + self.structure = structure + self.device = device + self.variable = variable + + @property + def name(self): + """ Returns the name of the nest, if any. """ + + location = self.device.where + name = self.device.name + if location is None: + return "{} {}".format(name, self.variable) + else: + if name == '': + return "{} {}".format(location.capitalize(), self.variable) + else: + return "{}({}){}".format(location.capitalize(), + name, + self.variable) + + +class NestBasicSensor(NestSensor): + """ Represents a basic Nest sensor with state. """ + + @property + def state(self): + """ Returns the state of the sensor. """ + + return getattr(self.device, self.variable) + + @property + def unit_of_measurement(self): + return SENSOR_UNITS.get(self.variable, None) + + +class NestTempSensor(NestSensor): + """ Represents a Nest Temperature sensor. """ + + @property + def unit_of_measurement(self): + return TEMP_CELCIUS + + @property + def state(self): + temp = getattr(self.device, self.variable) + if temp is None: + return None + + return round(temp, 1) diff --git a/homeassistant/components/thermostat/nest.py b/homeassistant/components/thermostat/nest.py index f38935b726e..423a3195976 100644 --- a/homeassistant/components/thermostat/nest.py +++ b/homeassistant/components/thermostat/nest.py @@ -11,38 +11,21 @@ import logging from homeassistant.components.thermostat import (ThermostatDevice, STATE_COOL, STATE_IDLE, STATE_HEAT) -from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, TEMP_CELCIUS) +from homeassistant.const import (TEMP_CELCIUS) +import homeassistant.components.nest as nest -REQUIREMENTS = ['python-nest==2.6.0'] +DEPENDENCIES = ['nest'] -# pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): - """ Sets up the nest thermostat. """ + "Setup nest thermostat" + logger = logging.getLogger(__name__) - username = config.get(CONF_USERNAME) - password = config.get(CONF_PASSWORD) - - if username is None or password is None: - logger.error("Missing required configuration items %s or %s", - CONF_USERNAME, CONF_PASSWORD) - return - - try: - import nest - except ImportError: - logger.exception( - "Error while importing dependency nest. " - "Did you maybe not install the python-nest dependency?") - - return - - napi = nest.Nest(username, password) try: add_devices([ NestThermostat(structure, device) - for structure in napi.structures + for structure in nest.NEST.structures for device in structure.devices ]) except socket.error: diff --git a/requirements_all.txt b/requirements_all.txt index 205dca38209..b6d0af08ee0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -95,6 +95,9 @@ paho-mqtt==1.1 # homeassistant.components.mysensors https://github.com/theolind/pymysensors/archive/005bff4c5ca7a56acd30e816bc3bcdb5cb2d46fd.zip#pymysensors==0.4 +# homeassistant.components.nest +python-nest==2.6.0 + # homeassistant.components.notify.free_mobile freesms==0.1.0 @@ -192,9 +195,6 @@ heatmiserV3==0.9.1 # homeassistant.components.thermostat.honeywell evohomeclient==0.2.4 -# homeassistant.components.thermostat.nest -python-nest==2.6.0 - # homeassistant.components.thermostat.proliphix proliphix==0.1.0