mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Merge branch 'pr/635' into dev
Conflicts: requirements_all.txt
This commit is contained in:
commit
bbfeba0fe4
@ -17,6 +17,9 @@ omit =
|
||||
homeassistant/components/*/tellstick.py
|
||||
homeassistant/components/*/vera.py
|
||||
|
||||
homeassistant/components/ecobee.py
|
||||
homeassistant/components/*/ecobee.py
|
||||
|
||||
homeassistant/components/verisure.py
|
||||
homeassistant/components/*/verisure.py
|
||||
|
||||
|
154
homeassistant/components/ecobee.py
Normal file
154
homeassistant/components/ecobee.py
Normal file
@ -0,0 +1,154 @@
|
||||
"""
|
||||
homeassistant.components.ecobee
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Ecobee Component
|
||||
|
||||
This component adds support for Ecobee3 Wireless Thermostats.
|
||||
You will need to setup developer access to your thermostat,
|
||||
and create and API key on the ecobee website.
|
||||
|
||||
The first time you run this component you will see a configuration
|
||||
component card in Home Assistant. This card will contain a PIN code
|
||||
that you will need to use to authorize access to your thermostat. You
|
||||
can do this at https://www.ecobee.com/consumerportal/index.html
|
||||
Click My Apps, Add application, Enter Pin and click Authorize.
|
||||
|
||||
After authorizing the application click the button in the configuration
|
||||
card. Now your thermostat and sensors should shown in home-assistant.
|
||||
|
||||
You can use the optional hold_temp parameter to set whether or not holds
|
||||
are set indefintely or until the next scheduled event.
|
||||
|
||||
ecobee:
|
||||
api_key: asdfasdfasdfasdfasdfaasdfasdfasdfasdf
|
||||
hold_temp: True
|
||||
|
||||
"""
|
||||
|
||||
from homeassistant.loader import get_component
|
||||
from homeassistant import bootstrap
|
||||
from homeassistant.util import Throttle
|
||||
from homeassistant.const import (
|
||||
EVENT_PLATFORM_DISCOVERED, ATTR_SERVICE, ATTR_DISCOVERED, CONF_API_KEY)
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
import os
|
||||
|
||||
DOMAIN = "ecobee"
|
||||
DISCOVER_THERMOSTAT = "ecobee.thermostat"
|
||||
DISCOVER_SENSORS = "ecobee.sensor"
|
||||
NETWORK = None
|
||||
HOLD_TEMP = 'hold_temp'
|
||||
|
||||
REQUIREMENTS = [
|
||||
'https://github.com/nkgilley/python-ecobee-api/archive/'
|
||||
'd35596b67c75451fa47001c493a15eebee195e93.zip#python-ecobee==0.0.1']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ECOBEE_CONFIG_FILE = 'ecobee.conf'
|
||||
_CONFIGURING = {}
|
||||
|
||||
# Return cached results if last scan was less then this time ago
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=180)
|
||||
|
||||
|
||||
def request_configuration(network, hass, config):
|
||||
""" Request configuration steps from the user. """
|
||||
configurator = get_component('configurator')
|
||||
if 'ecobee' in _CONFIGURING:
|
||||
configurator.notify_errors(
|
||||
_CONFIGURING['ecobee'], "Failed to register, please try again.")
|
||||
|
||||
return
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def ecobee_configuration_callback(callback_data):
|
||||
""" Actions to do when our configuration callback is called. """
|
||||
network.request_tokens()
|
||||
network.update()
|
||||
setup_ecobee(hass, network, config)
|
||||
|
||||
_CONFIGURING['ecobee'] = configurator.request_config(
|
||||
hass, "Ecobee", ecobee_configuration_callback,
|
||||
description=(
|
||||
'Please authorize this app at https://www.ecobee.com/consumer'
|
||||
'portal/index.html with pin code: ' + network.pin),
|
||||
description_image="/static/images/config_ecobee_thermostat.png",
|
||||
submit_caption="I have authorized the app."
|
||||
)
|
||||
|
||||
|
||||
def setup_ecobee(hass, network, config):
|
||||
""" Setup ecobee thermostat """
|
||||
# If ecobee has a PIN then it needs to be configured.
|
||||
if network.pin is not None:
|
||||
request_configuration(network, hass, config)
|
||||
return
|
||||
|
||||
if 'ecobee' in _CONFIGURING:
|
||||
configurator = get_component('configurator')
|
||||
configurator.request_done(_CONFIGURING.pop('ecobee'))
|
||||
|
||||
# Ensure component is loaded
|
||||
bootstrap.setup_component(hass, 'thermostat', config)
|
||||
bootstrap.setup_component(hass, 'sensor', config)
|
||||
|
||||
hold_temp = config[DOMAIN].get(HOLD_TEMP, False)
|
||||
|
||||
# Fire thermostat discovery event
|
||||
hass.bus.fire(EVENT_PLATFORM_DISCOVERED, {
|
||||
ATTR_SERVICE: DISCOVER_THERMOSTAT,
|
||||
ATTR_DISCOVERED: {'hold_temp': hold_temp}
|
||||
})
|
||||
|
||||
# Fire sensor discovery event
|
||||
hass.bus.fire(EVENT_PLATFORM_DISCOVERED, {
|
||||
ATTR_SERVICE: DISCOVER_SENSORS,
|
||||
ATTR_DISCOVERED: {}
|
||||
})
|
||||
|
||||
|
||||
# pylint: disable=too-few-public-methods
|
||||
class EcobeeData(object):
|
||||
""" Gets the latest data and update the states. """
|
||||
|
||||
def __init__(self, config_file):
|
||||
from pyecobee import Ecobee
|
||||
self.ecobee = Ecobee(config_file)
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self):
|
||||
""" Get the latest data from pyecobee. """
|
||||
self.ecobee.update()
|
||||
_LOGGER.info("ecobee data updated successfully.")
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""
|
||||
Setup Ecobee.
|
||||
Will automatically load thermostat and sensor components to support
|
||||
devices discovered on the network.
|
||||
"""
|
||||
# pylint: disable=global-statement, import-error
|
||||
global NETWORK
|
||||
|
||||
if 'ecobee' in _CONFIGURING:
|
||||
return
|
||||
|
||||
from pyecobee import config_from_file
|
||||
|
||||
# Create ecobee.conf if it doesn't exist
|
||||
if not os.path.isfile(hass.config.path(ECOBEE_CONFIG_FILE)):
|
||||
if config[DOMAIN].get(CONF_API_KEY) is None:
|
||||
_LOGGER.error("No ecobee api_key found in config.")
|
||||
return
|
||||
jsonconfig = {"API_KEY": config[DOMAIN].get(CONF_API_KEY)}
|
||||
config_from_file(hass.config.path(ECOBEE_CONFIG_FILE), jsonconfig)
|
||||
|
||||
NETWORK = EcobeeData(hass.config.path(ECOBEE_CONFIG_FILE))
|
||||
|
||||
setup_ecobee(hass, NETWORK.ecobee, config)
|
||||
|
||||
return True
|
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
@ -9,7 +9,7 @@ https://home-assistant.io/components/sensor/
|
||||
import logging
|
||||
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.components import wink, zwave, isy994, verisure
|
||||
from homeassistant.components import wink, zwave, isy994, verisure, ecobee
|
||||
|
||||
DOMAIN = 'sensor'
|
||||
SCAN_INTERVAL = 30
|
||||
@ -21,7 +21,8 @@ DISCOVERY_PLATFORMS = {
|
||||
wink.DISCOVER_SENSORS: 'wink',
|
||||
zwave.DISCOVER_SENSORS: 'zwave',
|
||||
isy994.DISCOVER_SENSORS: 'isy994',
|
||||
verisure.DISCOVER_SENSORS: 'verisure'
|
||||
verisure.DISCOVER_SENSORS: 'verisure',
|
||||
ecobee.DISCOVER_SENSORS: 'ecobee'
|
||||
}
|
||||
|
||||
|
||||
|
94
homeassistant/components/sensor/ecobee.py
Normal file
94
homeassistant/components/sensor/ecobee.py
Normal file
@ -0,0 +1,94 @@
|
||||
"""
|
||||
homeassistant.components.sensor.ecobee
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Ecobee Thermostat Component
|
||||
|
||||
This component adds support for Ecobee3 Wireless Thermostats.
|
||||
You will need to setup developer access to your thermostat,
|
||||
and create and API key on the ecobee website.
|
||||
|
||||
The first time you run this component you will see a configuration
|
||||
component card in Home Assistant. This card will contain a PIN code
|
||||
that you will need to use to authorize access to your thermostat. You
|
||||
can do this at https://www.ecobee.com/consumerportal/index.html
|
||||
Click My Apps, Add application, Enter Pin and click Authorize.
|
||||
|
||||
After authorizing the application click the button in the configuration
|
||||
card. Now your thermostat and sensors should shown in home-assistant.
|
||||
|
||||
You can use the optional hold_temp parameter to set whether or not holds
|
||||
are set indefintely or until the next scheduled event.
|
||||
|
||||
ecobee:
|
||||
api_key: asdfasdfasdfasdfasdfaasdfasdfasdfasdf
|
||||
hold_temp: True
|
||||
|
||||
"""
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.components import ecobee
|
||||
from homeassistant.const import TEMP_FAHRENHEIT
|
||||
import logging
|
||||
|
||||
DEPENDENCIES = ['ecobee']
|
||||
|
||||
SENSOR_TYPES = {
|
||||
'temperature': ['Temperature', TEMP_FAHRENHEIT],
|
||||
'humidity': ['Humidity', '%'],
|
||||
'occupancy': ['Occupancy', '']
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ECOBEE_CONFIG_FILE = 'ecobee.conf'
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the sensors. """
|
||||
if discovery_info is None:
|
||||
return
|
||||
dev = list()
|
||||
for name, data in ecobee.NETWORK.ecobee.sensors.items():
|
||||
if 'temp' in data:
|
||||
dev.append(EcobeeSensor(name, 'temperature'))
|
||||
if 'humidity' in data:
|
||||
dev.append(EcobeeSensor(name, 'humidity'))
|
||||
if 'occupancy' in data:
|
||||
dev.append(EcobeeSensor(name, 'occupancy'))
|
||||
|
||||
add_devices(dev)
|
||||
|
||||
|
||||
class EcobeeSensor(Entity):
|
||||
""" An ecobee sensor. """
|
||||
|
||||
def __init__(self, sensor_name, sensor_type):
|
||||
self._name = sensor_name + ' ' + SENSOR_TYPES[sensor_type][0]
|
||||
self.sensor_name = sensor_name
|
||||
self.type = sensor_type
|
||||
self._state = None
|
||||
self._unit_of_measurement = SENSOR_TYPES[sensor_type][1]
|
||||
self.update()
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name.rstrip()
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
""" Returns the state of the device. """
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
return self._unit_of_measurement
|
||||
|
||||
def update(self):
|
||||
ecobee.NETWORK.update()
|
||||
data = ecobee.NETWORK.ecobee.sensors[self.sensor_name]
|
||||
if self.type == 'temperature':
|
||||
self._state = data['temp']
|
||||
elif self.type == 'humidity':
|
||||
self._state = data['humidity']
|
||||
elif self.type == 'occupancy':
|
||||
self._state = data['occupancy']
|
@ -15,6 +15,7 @@ from homeassistant.config import load_yaml_config_file
|
||||
import homeassistant.util as util
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.temperature import convert
|
||||
from homeassistant.components import ecobee
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN,
|
||||
TEMP_CELCIUS)
|
||||
@ -41,6 +42,10 @@ ATTR_OPERATION = "current_operation"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DISCOVERY_PLATFORMS = {
|
||||
ecobee.DISCOVER_THERMOSTAT: 'ecobee',
|
||||
}
|
||||
|
||||
|
||||
def set_away_mode(hass, away_mode, entity_id=None):
|
||||
""" Turn all or specified thermostat away mode on. """
|
||||
@ -66,7 +71,8 @@ def set_temperature(hass, temperature, entity_id=None):
|
||||
|
||||
def setup(hass, config):
|
||||
""" Setup thermostats. """
|
||||
component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
|
||||
component = EntityComponent(_LOGGER, DOMAIN, hass,
|
||||
SCAN_INTERVAL, DISCOVERY_PLATFORMS)
|
||||
component.setup(config)
|
||||
|
||||
def thermostat_service(service):
|
||||
|
209
homeassistant/components/thermostat/ecobee.py
Normal file
209
homeassistant/components/thermostat/ecobee.py
Normal file
@ -0,0 +1,209 @@
|
||||
"""
|
||||
homeassistant.components.thermostat.ecobee
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Ecobee Thermostat Component
|
||||
|
||||
This component adds support for Ecobee3 Wireless Thermostats.
|
||||
You will need to setup developer access to your thermostat,
|
||||
and create and API key on the ecobee website.
|
||||
|
||||
The first time you run this component you will see a configuration
|
||||
component card in Home Assistant. This card will contain a PIN code
|
||||
that you will need to use to authorize access to your thermostat. You
|
||||
can do this at https://www.ecobee.com/consumerportal/index.html
|
||||
Click My Apps, Add application, Enter Pin and click Authorize.
|
||||
|
||||
After authorizing the application click the button in the configuration
|
||||
card. Now your thermostat and sensors should shown in home-assistant.
|
||||
|
||||
You can use the optional hold_temp parameter to set whether or not holds
|
||||
are set indefintely or until the next scheduled event.
|
||||
|
||||
ecobee:
|
||||
api_key: asdfasdfasdfasdfasdfaasdfasdfasdfasdf
|
||||
hold_temp: True
|
||||
|
||||
"""
|
||||
from homeassistant.components.thermostat import (ThermostatDevice, STATE_COOL,
|
||||
STATE_IDLE, STATE_HEAT)
|
||||
from homeassistant.const import (TEMP_FAHRENHEIT, STATE_ON, STATE_OFF)
|
||||
from homeassistant.components import ecobee
|
||||
import logging
|
||||
|
||||
DEPENDENCIES = ['ecobee']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ECOBEE_CONFIG_FILE = 'ecobee.conf'
|
||||
_CONFIGURING = {}
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Setup Platform """
|
||||
if discovery_info is None:
|
||||
return
|
||||
data = ecobee.NETWORK
|
||||
hold_temp = discovery_info['hold_temp']
|
||||
_LOGGER.info("Loading ecobee thermostat component with hold_temp set to "
|
||||
+ str(hold_temp))
|
||||
add_devices(Thermostat(data, index, hold_temp)
|
||||
for index in range(len(data.ecobee.thermostats)))
|
||||
|
||||
|
||||
class Thermostat(ThermostatDevice):
|
||||
""" Thermostat class for Ecobee """
|
||||
|
||||
def __init__(self, data, thermostat_index, hold_temp):
|
||||
self.data = data
|
||||
self.thermostat_index = thermostat_index
|
||||
self.thermostat = self.data.ecobee.get_thermostat(
|
||||
self.thermostat_index)
|
||||
self._name = self.thermostat['name']
|
||||
self._away = 'away' in self.thermostat['program']['currentClimateRef']
|
||||
self.hold_temp = hold_temp
|
||||
|
||||
def update(self):
|
||||
self.data.update()
|
||||
self.thermostat = self.data.ecobee.get_thermostat(
|
||||
self.thermostat_index)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Returns the name of the Ecobee Thermostat. """
|
||||
return self.thermostat['name']
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
""" Unit of measurement this thermostat expresses itself in. """
|
||||
return TEMP_FAHRENHEIT
|
||||
|
||||
@property
|
||||
def current_temperature(self):
|
||||
""" Returns the current temperature. """
|
||||
return self.thermostat['runtime']['actualTemperature'] / 10
|
||||
|
||||
@property
|
||||
def target_temperature(self):
|
||||
""" Returns the temperature we try to reach. """
|
||||
return (self.target_temperature_low + self.target_temperature_high) / 2
|
||||
|
||||
@property
|
||||
def target_temperature_low(self):
|
||||
""" Returns the lower bound temperature we try to reach. """
|
||||
return int(self.thermostat['runtime']['desiredHeat'] / 10)
|
||||
|
||||
@property
|
||||
def target_temperature_high(self):
|
||||
""" Returns the upper bound temperature we try to reach. """
|
||||
return int(self.thermostat['runtime']['desiredCool'] / 10)
|
||||
|
||||
@property
|
||||
def humidity(self):
|
||||
""" Returns the current humidity. """
|
||||
return self.thermostat['runtime']['actualHumidity']
|
||||
|
||||
@property
|
||||
def desired_fan_mode(self):
|
||||
""" Returns the desired fan mode of operation. """
|
||||
return self.thermostat['runtime']['desiredFanMode']
|
||||
|
||||
@property
|
||||
def fan(self):
|
||||
""" Returns the current fan state. """
|
||||
if 'fan' in self.thermostat['equipmentStatus']:
|
||||
return STATE_ON
|
||||
else:
|
||||
return STATE_OFF
|
||||
|
||||
@property
|
||||
def operation(self):
|
||||
""" Returns current operation ie. heat, cool, idle """
|
||||
status = self.thermostat['equipmentStatus']
|
||||
if status == '':
|
||||
return STATE_IDLE
|
||||
elif 'Cool' in status:
|
||||
return STATE_COOL
|
||||
elif 'auxHeat' in status:
|
||||
return STATE_HEAT
|
||||
elif 'heatPump' in status:
|
||||
return STATE_HEAT
|
||||
else:
|
||||
return status
|
||||
|
||||
@property
|
||||
def mode(self):
|
||||
""" Returns current mode ie. home, away, sleep """
|
||||
mode = self.thermostat['program']['currentClimateRef']
|
||||
self._away = 'away' in mode
|
||||
return mode
|
||||
|
||||
@property
|
||||
def hvac_mode(self):
|
||||
""" Return current hvac mode ie. auto, auxHeatOnly, cool, heat, off """
|
||||
return self.thermostat['settings']['hvacMode']
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
""" Returns device specific state attributes. """
|
||||
# Move these to Thermostat Device and make them global
|
||||
return {
|
||||
"humidity": self.humidity,
|
||||
"fan": self.fan,
|
||||
"mode": self.mode,
|
||||
"hvac_mode": self.hvac_mode
|
||||
}
|
||||
|
||||
@property
|
||||
def is_away_mode_on(self):
|
||||
""" Returns if away mode is on. """
|
||||
return self._away
|
||||
|
||||
def turn_away_mode_on(self):
|
||||
""" Turns away on. """
|
||||
self._away = True
|
||||
if self.hold_temp:
|
||||
self.data.ecobee.set_climate_hold("away", "indefinite")
|
||||
else:
|
||||
self.data.ecobee.set_climate_hold("away")
|
||||
|
||||
def turn_away_mode_off(self):
|
||||
""" Turns away off. """
|
||||
self._away = False
|
||||
self.data.ecobee.resume_program()
|
||||
|
||||
def set_temperature(self, temperature):
|
||||
""" Set new target temperature """
|
||||
temperature = int(temperature)
|
||||
low_temp = temperature - 1
|
||||
high_temp = temperature + 1
|
||||
if self.hold_temp:
|
||||
self.data.ecobee.set_hold_temp(low_temp, high_temp, "indefinite")
|
||||
else:
|
||||
self.data.ecobee.set_hold_temp(low_temp, high_temp)
|
||||
|
||||
def set_hvac_mode(self, mode):
|
||||
""" Set HVAC mode (auto, auxHeatOnly, cool, heat, off) """
|
||||
self.data.ecobee.set_hvac_mode(mode)
|
||||
|
||||
# Home and Sleep mode aren't used in UI yet:
|
||||
|
||||
# def turn_home_mode_on(self):
|
||||
# """ Turns home mode on. """
|
||||
# self._away = False
|
||||
# self.data.ecobee.set_climate_hold("home")
|
||||
|
||||
# def turn_home_mode_off(self):
|
||||
# """ Turns home mode off. """
|
||||
# self._away = False
|
||||
# self.data.ecobee.resume_program()
|
||||
|
||||
# def turn_sleep_mode_on(self):
|
||||
# """ Turns sleep mode on. """
|
||||
# self._away = False
|
||||
# self.data.ecobee.set_climate_hold("sleep")
|
||||
|
||||
# def turn_sleep_mode_off(self):
|
||||
# """ Turns sleep mode off. """
|
||||
# self._away = False
|
||||
# self.data.ecobee.resume_program()
|
@ -20,6 +20,9 @@ pysnmp==4.2.5
|
||||
# homeassistant.components.discovery
|
||||
netdisco==0.5.1
|
||||
|
||||
# homeassistant.components.ecobee
|
||||
https://github.com/nkgilley/python-ecobee-api/archive/d35596b67c75451fa47001c493a15eebee195e93.zip#python-ecobee==0.0.1
|
||||
|
||||
# homeassistant.components.ifttt
|
||||
pyfttt==0.3
|
||||
|
||||
@ -75,6 +78,8 @@ https://github.com/bashwork/pymodbus/archive/d7fc4f1cc975631e0a9011390e8017f64b6
|
||||
|
||||
# homeassistant.components.mqtt
|
||||
paho-mqtt==1.1
|
||||
|
||||
# homeassistant.components.mqtt
|
||||
jsonpath-rw==1.4.0
|
||||
|
||||
# homeassistant.components.notify.pushbullet
|
||||
|
Loading…
x
Reference in New Issue
Block a user