mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Nest Cam support (#4292)
* start nestcam support * start nestcam support * introduce a access_token_cache_file * Bare minimum to get nest thermostat loading * occaisonally the image works * switch to nest-aware interval for testing * Add Nest Aware awareness * remove duplicate error logging line * Fix nest protect support * address baloobot * fix copy pasta * fix more baloobot * last baloobot thing for now? * Use streaming status to determine online or not. online from nest means its on the network * Fix temperature scale for climate * Add support for eco mode * Fix auto mode for nest climate * update update current_operation and set_operation mode to use constant when possible. try to get setting something working * remove stale comment * unused-argument already disabled globally * Add eco to the end, instead of after off * Simplify conditional when the hass mode is the same as the nest one * away_temperature became eco_temperature, and works with eco mode * Update min/max temp based on locked temperature * Forgot to set locked stuff during construction * Cache image instead of throttling (which returns none), respect NestAware subscription * Fix _time_between_snapshots before the first update * WIP pin authorization * Add some more logging * Working configurator, woo. Fix some hound errors * Updated pin workflow * Deprecate more sensors * Don't update during access of name * Don't update during access of name * Add camera brand * Fix up some syntastic errors * Fix ups ome hound errors * Maybe fix some more? * Move snapshot simulator url checking down into python-nest * Rename _ready_to_update_camera_image to _ready_for_snapshot * More fixes * Set the next time a snapshot can be taken when one is taken to simplify logic * Add a FIXME about update not getting called * Call update during constructor, so values get set at least once * Fix up names * Remove todo about eco, since that's pretty nest * thanks hound * Fix temperature being off for farenheight. * Fix some lint errors, which includes using a git version of python-nest with updated code * generate requirements_all.py * fix pylint * Update nestcam before adding * Fix polling of NestCamera * Lint
This commit is contained in:
parent
601193b1d2
commit
84b12ab007
109
homeassistant/components/camera/nest.py
Normal file
109
homeassistant/components/camera/nest.py
Normal file
@ -0,0 +1,109 @@
|
||||
"""
|
||||
Support for Nest Cameras.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/camera.nest/
|
||||
"""
|
||||
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
import requests
|
||||
from homeassistant.components.camera import (PLATFORM_SCHEMA, Camera)
|
||||
import homeassistant.components.nest as nest
|
||||
from homeassistant.util.dt import utcnow
|
||||
|
||||
|
||||
DEPENDENCIES = ['nest']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({})
|
||||
|
||||
NEST_BRAND = "Nest"
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup a Nest Cam."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
camera_devices = hass.data[nest.DATA_NEST].camera_devices()
|
||||
cameras = [NestCamera(structure, device)
|
||||
for structure, device in camera_devices]
|
||||
add_devices(cameras, True)
|
||||
|
||||
|
||||
class NestCamera(Camera):
|
||||
"""Representation of a Nest Camera."""
|
||||
|
||||
def __init__(self, structure, device):
|
||||
"""Initialize a Nest Camera."""
|
||||
super(NestCamera, self).__init__()
|
||||
self.structure = structure
|
||||
self.device = device
|
||||
|
||||
# data attributes
|
||||
self._location = None
|
||||
self._name = None
|
||||
self._is_online = None
|
||||
self._is_streaming = None
|
||||
self._is_video_history_enabled = False
|
||||
# default to non-NestAware subscribed, but will be fixed during update
|
||||
self._time_between_snapshots = timedelta(seconds=30)
|
||||
self._last_image = None
|
||||
self._next_snapshot_at = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the nest, if any."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""Nest camera should poll periodically."""
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_recording(self):
|
||||
"""Return true if the device is recording."""
|
||||
return self._is_streaming
|
||||
|
||||
@property
|
||||
def brand(self):
|
||||
"""Camera Brand."""
|
||||
return NEST_BRAND
|
||||
|
||||
# this doesn't seem to be getting called regularly, for some reason
|
||||
def update(self):
|
||||
"""Cache value from Python-nest."""
|
||||
self._location = self.device.where
|
||||
self._name = self.device.name
|
||||
self._is_online = self.device.is_online
|
||||
self._is_streaming = self.device.is_streaming
|
||||
self._is_video_history_enabled = self.device.is_video_history_enabled
|
||||
|
||||
if self._is_video_history_enabled:
|
||||
# NestAware allowed 10/min
|
||||
self._time_between_snapshots = timedelta(seconds=6)
|
||||
else:
|
||||
# otherwise, 2/min
|
||||
self._time_between_snapshots = timedelta(seconds=30)
|
||||
|
||||
def _ready_for_snapshot(self, now):
|
||||
return (self._next_snapshot_at is None or
|
||||
now > self._next_snapshot_at)
|
||||
|
||||
def camera_image(self):
|
||||
"""Return a still image response from the camera."""
|
||||
now = utcnow()
|
||||
if self._ready_for_snapshot(now):
|
||||
url = self.device.snapshot_url
|
||||
|
||||
try:
|
||||
response = requests.get(url)
|
||||
except requests.exceptions.RequestException as error:
|
||||
_LOGGER.error('Error getting camera image: %s', error)
|
||||
return None
|
||||
|
||||
self._next_snapshot_at = now + self._time_between_snapshots
|
||||
self._last_image = response.content
|
||||
|
||||
return self._last_image
|
@ -14,7 +14,8 @@ from homeassistant.components.climate import (
|
||||
PLATFORM_SCHEMA, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW,
|
||||
ATTR_TEMPERATURE)
|
||||
from homeassistant.const import (
|
||||
TEMP_CELSIUS, CONF_SCAN_INTERVAL, STATE_ON, STATE_OFF, STATE_UNKNOWN)
|
||||
TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
||||
CONF_SCAN_INTERVAL, STATE_ON, STATE_OFF, STATE_UNKNOWN)
|
||||
|
||||
DEPENDENCIES = ['nest']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -24,10 +25,18 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.All(vol.Coerce(int), vol.Range(min=1)),
|
||||
})
|
||||
|
||||
STATE_ECO = 'eco'
|
||||
STATE_HEAT_COOL = 'heat-cool'
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup the Nest thermostat."""
|
||||
_LOGGER.debug("Setting up nest thermostat")
|
||||
if discovery_info is None:
|
||||
return
|
||||
|
||||
temp_unit = hass.config.units.temperature_unit
|
||||
|
||||
add_devices(
|
||||
[NestThermostat(structure, device, temp_unit)
|
||||
for structure, device in hass.data[DATA_NEST].devices()],
|
||||
@ -58,9 +67,9 @@ class NestThermostat(ClimateDevice):
|
||||
if self.device.can_heat and self.device.can_cool:
|
||||
self._operation_list.append(STATE_AUTO)
|
||||
|
||||
self._operation_list.append(STATE_ECO)
|
||||
|
||||
# feature of device
|
||||
self._has_humidifier = self.device.has_humidifier
|
||||
self._has_dehumidifier = self.device.has_dehumidifier
|
||||
self._has_fan = self.device.has_fan
|
||||
|
||||
# data attributes
|
||||
@ -68,41 +77,24 @@ class NestThermostat(ClimateDevice):
|
||||
self._location = None
|
||||
self._name = None
|
||||
self._humidity = None
|
||||
self._target_humidity = None
|
||||
self._target_temperature = None
|
||||
self._temperature = None
|
||||
self._temperature_scale = None
|
||||
self._mode = None
|
||||
self._fan = None
|
||||
self._away_temperature = None
|
||||
self._eco_temperature = None
|
||||
self._is_locked = None
|
||||
self._locked_temperature = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the nest, if any."""
|
||||
if self._location is None:
|
||||
return self._name
|
||||
else:
|
||||
if self._name == '':
|
||||
return self._location.capitalize()
|
||||
else:
|
||||
return self._location.capitalize() + '(' + self._name + ')'
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
"""Return the unit of measurement."""
|
||||
return TEMP_CELSIUS
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device specific state attributes."""
|
||||
if self._has_humidifier or self._has_dehumidifier:
|
||||
# Move these to Thermostat Device and make them global
|
||||
return {
|
||||
"humidity": self._humidity,
|
||||
"target_humidity": self._target_humidity,
|
||||
}
|
||||
else:
|
||||
# No way to control humidity not show setting
|
||||
return {}
|
||||
return self._temperature_scale
|
||||
|
||||
@property
|
||||
def current_temperature(self):
|
||||
@ -112,21 +104,17 @@ class NestThermostat(ClimateDevice):
|
||||
@property
|
||||
def current_operation(self):
|
||||
"""Return current operation ie. heat, cool, idle."""
|
||||
if self._mode == 'cool':
|
||||
return STATE_COOL
|
||||
elif self._mode == 'heat':
|
||||
return STATE_HEAT
|
||||
elif self._mode == 'range':
|
||||
if self._mode in [STATE_HEAT, STATE_COOL, STATE_OFF, STATE_ECO]:
|
||||
return self._mode
|
||||
elif self._mode == STATE_HEAT_COOL:
|
||||
return STATE_AUTO
|
||||
elif self._mode == 'off':
|
||||
return STATE_OFF
|
||||
else:
|
||||
return STATE_UNKNOWN
|
||||
|
||||
@property
|
||||
def target_temperature(self):
|
||||
"""Return the temperature we try to reach."""
|
||||
if self._mode != 'range' and not self.is_away_mode_on:
|
||||
if self._mode != STATE_HEAT_COOL and not self.is_away_mode_on:
|
||||
return self._target_temperature
|
||||
else:
|
||||
return None
|
||||
@ -134,10 +122,11 @@ class NestThermostat(ClimateDevice):
|
||||
@property
|
||||
def target_temperature_low(self):
|
||||
"""Return the lower bound temperature we try to reach."""
|
||||
if self.is_away_mode_on and self._away_temperature[0]:
|
||||
# away_temperature is always a low, high tuple
|
||||
return self._away_temperature[0]
|
||||
if self._mode == 'range':
|
||||
if (self.is_away_mode_on or self._mode == STATE_ECO) and \
|
||||
self._eco_temperature[0]:
|
||||
# eco_temperature is always a low, high tuple
|
||||
return self._eco_temperature[0]
|
||||
if self._mode == STATE_HEAT_COOL:
|
||||
return self._target_temperature[0]
|
||||
else:
|
||||
return None
|
||||
@ -145,10 +134,11 @@ class NestThermostat(ClimateDevice):
|
||||
@property
|
||||
def target_temperature_high(self):
|
||||
"""Return the upper bound temperature we try to reach."""
|
||||
if self.is_away_mode_on and self._away_temperature[1]:
|
||||
# away_temperature is always a low, high tuple
|
||||
return self._away_temperature[1]
|
||||
if self._mode == 'range':
|
||||
if (self.is_away_mode_on or self._mode == STATE_ECO) and \
|
||||
self._eco_temperature[1]:
|
||||
# eco_temperature is always a low, high tuple
|
||||
return self._eco_temperature[1]
|
||||
if self._mode == STATE_HEAT_COOL:
|
||||
return self._target_temperature[1]
|
||||
else:
|
||||
return None
|
||||
@ -163,8 +153,7 @@ class NestThermostat(ClimateDevice):
|
||||
target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW)
|
||||
target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH)
|
||||
if target_temp_low is not None and target_temp_high is not None:
|
||||
|
||||
if self._mode == 'range':
|
||||
if self._mode == STATE_HEAT_COOL:
|
||||
temp = (target_temp_low, target_temp_high)
|
||||
else:
|
||||
temp = kwargs.get(ATTR_TEMPERATURE)
|
||||
@ -173,14 +162,11 @@ class NestThermostat(ClimateDevice):
|
||||
|
||||
def set_operation_mode(self, operation_mode):
|
||||
"""Set operation mode."""
|
||||
if operation_mode == STATE_HEAT:
|
||||
self.device.mode = 'heat'
|
||||
elif operation_mode == STATE_COOL:
|
||||
self.device.mode = 'cool'
|
||||
if operation_mode in [STATE_HEAT, STATE_COOL, STATE_OFF, STATE_ECO]:
|
||||
device_mode = operation_mode
|
||||
elif operation_mode == STATE_AUTO:
|
||||
self.device.mode = 'range'
|
||||
elif operation_mode == STATE_OFF:
|
||||
self.device.mode = 'off'
|
||||
device_mode = STATE_HEAT_COOL
|
||||
self.device.mode = device_mode
|
||||
|
||||
@property
|
||||
def operation_list(self):
|
||||
@ -217,30 +203,33 @@ class NestThermostat(ClimateDevice):
|
||||
@property
|
||||
def min_temp(self):
|
||||
"""Identify min_temp in Nest API or defaults if not available."""
|
||||
temp = self._away_temperature[0]
|
||||
if temp is None:
|
||||
return super().min_temp
|
||||
if self._is_locked:
|
||||
return self._locked_temperature[0]
|
||||
else:
|
||||
return temp
|
||||
return None
|
||||
|
||||
@property
|
||||
def max_temp(self):
|
||||
"""Identify max_temp in Nest API or defaults if not available."""
|
||||
temp = self._away_temperature[1]
|
||||
if temp is None:
|
||||
return super().max_temp
|
||||
if self._is_locked:
|
||||
return self._locked_temperature[1]
|
||||
else:
|
||||
return temp
|
||||
return None
|
||||
|
||||
def update(self):
|
||||
"""Cache value from Python-nest."""
|
||||
self._location = self.device.where
|
||||
self._name = self.device.name
|
||||
self._humidity = self.device.humidity,
|
||||
self._target_humidity = self.device.target_humidity,
|
||||
self._temperature = self.device.temperature
|
||||
self._mode = self.device.mode
|
||||
self._target_temperature = self.device.target
|
||||
self._fan = self.device.fan
|
||||
self._away = self.structure.away
|
||||
self._away_temperature = self.device.away_temperature
|
||||
self._away = self.structure.away == 'away'
|
||||
self._eco_temperature = self.device.eco_temperature
|
||||
self._locked_temperature = self.device.locked_temperature
|
||||
self._is_locked = self.device.is_locked
|
||||
if self.device.temperature == 'C':
|
||||
self._temperature_scale = TEMP_CELSIUS
|
||||
else:
|
||||
self._temperature_scale = TEMP_FAHRENHEIT
|
||||
|
@ -10,36 +10,109 @@ import socket
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.const import (CONF_PASSWORD, CONF_USERNAME, CONF_STRUCTURE)
|
||||
from homeassistant.helpers import discovery
|
||||
from homeassistant.const import (CONF_STRUCTURE, CONF_FILENAME)
|
||||
from homeassistant.loader import get_component
|
||||
|
||||
_CONFIGURING = {}
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
REQUIREMENTS = ['python-nest==2.11.0']
|
||||
REQUIREMENTS = [
|
||||
'git+https://github.com/technicalpickles/python-nest.git'
|
||||
'@nest-cam'
|
||||
'#python-nest==3.0.0']
|
||||
|
||||
DOMAIN = 'nest'
|
||||
|
||||
DATA_NEST = 'nest'
|
||||
|
||||
NEST_CONFIG_FILE = 'nest.conf'
|
||||
CONF_CLIENT_ID = 'client_id'
|
||||
CONF_CLIENT_SECRET = 'client_secret'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Required(CONF_USERNAME): cv.string,
|
||||
vol.Required(CONF_PASSWORD): cv.string,
|
||||
vol.Required(CONF_CLIENT_ID): cv.string,
|
||||
vol.Required(CONF_CLIENT_SECRET): cv.string,
|
||||
vol.Optional(CONF_STRUCTURE): vol.All(cv.ensure_list, cv.string)
|
||||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
def request_configuration(nest, hass, config):
|
||||
"""Request configuration steps from the user."""
|
||||
configurator = get_component('configurator')
|
||||
if 'nest' in _CONFIGURING:
|
||||
_LOGGER.debug("configurator failed")
|
||||
configurator.notify_errors(
|
||||
_CONFIGURING['nest'], "Failed to configure, please try again.")
|
||||
return
|
||||
|
||||
def nest_configuration_callback(data):
|
||||
"""The actions to do when our configuration callback is called."""
|
||||
_LOGGER.debug("configurator callback")
|
||||
pin = data.get('pin')
|
||||
setup_nest(hass, nest, config, pin=pin)
|
||||
|
||||
_CONFIGURING['nest'] = configurator.request_config(
|
||||
hass, "Nest", nest_configuration_callback,
|
||||
description=('To configure Nest, click Request Authorization below, '
|
||||
'log into your Nest account, '
|
||||
'and then enter the resulting PIN'),
|
||||
link_name='Request Authorization',
|
||||
link_url=nest.authorize_url,
|
||||
submit_caption="Confirm",
|
||||
fields=[{'id': 'pin', 'name': 'Enter the PIN', 'type': ''}]
|
||||
)
|
||||
|
||||
|
||||
def setup_nest(hass, nest, config, pin=None):
|
||||
"""Setup Nest Devices."""
|
||||
if pin is not None:
|
||||
_LOGGER.debug("pin acquired, requesting access token")
|
||||
nest.request_token(pin)
|
||||
|
||||
if nest.access_token is None:
|
||||
_LOGGER.debug("no access_token, requesting configuration")
|
||||
request_configuration(nest, hass, config)
|
||||
return
|
||||
|
||||
if 'nest' in _CONFIGURING:
|
||||
_LOGGER.debug("configuration done")
|
||||
configurator = get_component('configurator')
|
||||
configurator.request_done(_CONFIGURING.pop('nest'))
|
||||
|
||||
_LOGGER.debug("proceeding with setup")
|
||||
conf = config[DOMAIN]
|
||||
hass.data[DATA_NEST] = NestDevice(hass, conf, nest)
|
||||
|
||||
_LOGGER.debug("proceeding with discovery")
|
||||
discovery.load_platform(hass, 'climate', DOMAIN, {}, config)
|
||||
discovery.load_platform(hass, 'sensor', DOMAIN, {}, config)
|
||||
discovery.load_platform(hass, 'camera', DOMAIN, {}, config)
|
||||
_LOGGER.debug("setup done")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Setup the Nest thermostat component."""
|
||||
import nest
|
||||
|
||||
conf = config[DOMAIN]
|
||||
username = conf[CONF_USERNAME]
|
||||
password = conf[CONF_PASSWORD]
|
||||
if 'nest' in _CONFIGURING:
|
||||
return
|
||||
|
||||
nest = nest.Nest(username, password)
|
||||
hass.data[DATA_NEST] = NestDevice(hass, conf, nest)
|
||||
conf = config[DOMAIN]
|
||||
client_id = conf[CONF_CLIENT_ID]
|
||||
client_secret = conf[CONF_CLIENT_SECRET]
|
||||
filename = config.get(CONF_FILENAME, NEST_CONFIG_FILE)
|
||||
|
||||
access_token_cache_file = hass.config.path(filename)
|
||||
|
||||
nest = nest.Nest(
|
||||
access_token_cache_file=access_token_cache_file,
|
||||
client_id=client_id, client_secret=client_secret)
|
||||
setup_nest(hass, nest, config)
|
||||
|
||||
return True
|
||||
|
||||
@ -85,3 +158,17 @@ class NestDevice(object):
|
||||
except socket.error:
|
||||
_LOGGER.error(
|
||||
"Connection error logging into the nest web service.")
|
||||
|
||||
def camera_devices(self):
|
||||
"""Generator returning list of camera devices."""
|
||||
try:
|
||||
for structure in self.nest.structures:
|
||||
if structure.name in self._structure:
|
||||
for device in structure.cameradevices:
|
||||
yield(structure, device)
|
||||
else:
|
||||
_LOGGER.info("Ignoring structure %s, not in %s",
|
||||
structure.name, self._structure)
|
||||
except socket.error:
|
||||
_LOGGER.error(
|
||||
"Connection error logging into the nest web service.")
|
||||
|
@ -11,29 +11,35 @@ import voluptuous as vol
|
||||
from homeassistant.components.nest import DATA_NEST, DOMAIN
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.const import (
|
||||
TEMP_CELSIUS, CONF_PLATFORM, CONF_SCAN_INTERVAL, CONF_MONITORED_CONDITIONS
|
||||
TEMP_CELSIUS, TEMP_FAHRENHEIT, CONF_PLATFORM,
|
||||
CONF_SCAN_INTERVAL, CONF_MONITORED_CONDITIONS
|
||||
)
|
||||
|
||||
DEPENDENCIES = ['nest']
|
||||
SENSOR_TYPES = ['humidity',
|
||||
'operation_mode',
|
||||
'last_ip',
|
||||
'local_ip',
|
||||
'last_connection',
|
||||
'battery_level']
|
||||
'last_connection']
|
||||
|
||||
WEATHER_VARS = {'weather_humidity': 'humidity',
|
||||
'weather_temperature': 'temperature',
|
||||
'weather_condition': 'condition',
|
||||
'wind_speed': 'kph',
|
||||
'wind_direction': 'direction'}
|
||||
SENSOR_TYPES_DEPRECATED = ['battery_health',
|
||||
'last_ip',
|
||||
'local_ip']
|
||||
|
||||
SENSOR_UNITS = {'humidity': '%', 'battery_level': 'V',
|
||||
'kph': 'kph', 'temperature': '°C'}
|
||||
WEATHER_VARS = {}
|
||||
|
||||
DEPRECATED_WEATHER_VARS = {'weather_humidity': 'humidity',
|
||||
'weather_temperature': 'temperature',
|
||||
'weather_condition': 'condition',
|
||||
'wind_speed': 'kph',
|
||||
'wind_direction': 'direction'}
|
||||
|
||||
SENSOR_UNITS = {'humidity': '%',
|
||||
'temperature': '°C'}
|
||||
|
||||
PROTECT_VARS = ['co_status',
|
||||
'smoke_status',
|
||||
'battery_level']
|
||||
'battery_health']
|
||||
|
||||
PROTECT_VARS_DEPRECATED = ['battery_level']
|
||||
|
||||
SENSOR_TEMP_TYPES = ['temperature', 'target']
|
||||
|
||||
@ -51,21 +57,22 @@ PLATFORM_SCHEMA = vol.Schema({
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup the Nest Sensor."""
|
||||
nest = hass.data[DATA_NEST]
|
||||
conf = config.get(CONF_MONITORED_CONDITIONS, _VALID_SENSOR_TYPES)
|
||||
|
||||
all_sensors = []
|
||||
for structure, device in chain(nest.devices(), nest.protect_devices()):
|
||||
sensors = [NestBasicSensor(structure, device, variable)
|
||||
for variable in config[CONF_MONITORED_CONDITIONS]
|
||||
for variable in conf
|
||||
if variable in SENSOR_TYPES and is_thermostat(device)]
|
||||
sensors += [NestTempSensor(structure, device, variable)
|
||||
for variable in config[CONF_MONITORED_CONDITIONS]
|
||||
for variable in conf
|
||||
if variable in SENSOR_TEMP_TYPES and is_thermostat(device)]
|
||||
sensors += [NestWeatherSensor(structure, device,
|
||||
WEATHER_VARS[variable])
|
||||
for variable in config[CONF_MONITORED_CONDITIONS]
|
||||
for variable in conf
|
||||
if variable in WEATHER_VARS and is_thermostat(device)]
|
||||
sensors += [NestProtectSensor(structure, device, variable)
|
||||
for variable in config[CONF_MONITORED_CONDITIONS]
|
||||
for variable in conf
|
||||
if variable in PROTECT_VARS and is_protect(device)]
|
||||
all_sensors.extend(sensors)
|
||||
|
||||
@ -99,16 +106,7 @@ class NestSensor(Entity):
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the nest, if any."""
|
||||
if self._location is None:
|
||||
return "{} {}".format(self._name, self.variable)
|
||||
else:
|
||||
if self._name == '':
|
||||
return "{} {}".format(self._location.capitalize(),
|
||||
self.variable)
|
||||
else:
|
||||
return "{}({}){}".format(self._location.capitalize(),
|
||||
self._name,
|
||||
self.variable)
|
||||
return "{} {}".format(self._name, self.variable)
|
||||
|
||||
|
||||
class NestBasicSensor(NestSensor):
|
||||
@ -138,7 +136,10 @@ class NestTempSensor(NestSensor):
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit the value is expressed in."""
|
||||
return TEMP_CELSIUS
|
||||
if self.device.temperature_scale == 'C':
|
||||
return TEMP_CELSIUS
|
||||
else:
|
||||
return TEMP_FAHRENHEIT
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
@ -191,19 +192,4 @@ class NestProtectSensor(NestSensor):
|
||||
|
||||
def update(self):
|
||||
"""Retrieve latest state."""
|
||||
state = getattr(self.device, self.variable)
|
||||
if self.variable == 'battery_level':
|
||||
self._state = getattr(self.device, self.variable)
|
||||
else:
|
||||
self._state = 'Unknown'
|
||||
if state == 0:
|
||||
self._state = 'Ok'
|
||||
if state == 1 or state == 2:
|
||||
self._state = 'Warning'
|
||||
if state == 3:
|
||||
self._state = 'Emergency'
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the nest, if any."""
|
||||
return "{} {}".format(self._location.capitalize(), self.variable)
|
||||
self._state = getattr(self.device, self.variable).capitalize()
|
||||
|
@ -124,6 +124,9 @@ fuzzywuzzy==0.14.0
|
||||
# homeassistant.components.device_tracker.bluetooth_le_tracker
|
||||
# gattlib==0.20150805
|
||||
|
||||
# homeassistant.components.nest
|
||||
git+https://github.com/technicalpickles/python-nest.git@nest-cam#python-nest==3.0.0
|
||||
|
||||
# homeassistant.components.notify.gntp
|
||||
gntp==1.0.3
|
||||
|
||||
@ -437,9 +440,6 @@ python-mpd2==0.5.5
|
||||
# homeassistant.components.switch.mystrom
|
||||
python-mystrom==0.3.6
|
||||
|
||||
# homeassistant.components.nest
|
||||
python-nest==2.11.0
|
||||
|
||||
# homeassistant.components.device_tracker.nmap_tracker
|
||||
python-nmap==0.6.1
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user