From 40e6919fac45dddcd336ea6a85cf060f58f7b0c8 Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Fri, 11 May 2018 20:34:30 -0700 Subject: [PATCH 1/5] Add away sensor to nest binary sensors, eta to nest sensors Comment out one line of code for security_state which need future version of python-nest --- .../components/binary_sensor/nest.py | 23 +++++++++++++-- homeassistant/components/nest.py | 21 +++++++++++--- homeassistant/components/sensor/nest.py | 28 +++++++++++++++---- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/binary_sensor/nest.py b/homeassistant/components/binary_sensor/nest.py index 4089f3a2eaf60f..c120b46af749b2 100644 --- a/homeassistant/components/binary_sensor/nest.py +++ b/homeassistant/components/binary_sensor/nest.py @@ -29,6 +29,16 @@ 'person_detected', ] +STRUCTURE_BINARY_TYPES = [ + 'away', + # 'security_state', # wait python-nest update +] + +STRUCTURE_BINARY_STATE_MAP = { + 'away': {'away': True, 'home': False}, + 'security_state': {'deter': True, 'ok': False}, +} + _BINARY_TYPES_DEPRECATED = [ 'hvac_ac_state', 'hvac_aux_heater_state', @@ -41,7 +51,7 @@ ] _VALID_BINARY_SENSOR_TYPES = BINARY_TYPES + CLIMATE_BINARY_TYPES \ - + CAMERA_BINARY_TYPES + + CAMERA_BINARY_TYPES + STRUCTURE_BINARY_TYPES _LOGGER = logging.getLogger(__name__) @@ -68,6 +78,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error(wstr) sensors = [] + for structure in nest.structures(): + sensors += [NestBinarySensor(structure, None, variable) + for variable in conditions + if variable in STRUCTURE_BINARY_TYPES] device_chain = chain(nest.thermostats(), nest.smoke_co_alarms(), nest.cameras()) @@ -88,7 +102,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): sensors += [NestActivityZoneSensor(structure, device, activity_zone)] - add_devices(sensors, True) @@ -102,7 +115,11 @@ def is_on(self): def update(self): """Retrieve latest state.""" - self._state = bool(getattr(self.device, self.variable)) + value = getattr(self.device, self.variable) + if self.variable in STRUCTURE_BINARY_TYPES: + self._state = bool(STRUCTURE_BINARY_STATE_MAP[self.variable][value]) + else: + self._state = bool(value) class NestActivityZoneSensor(NestBinarySensor): diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py index e7d2ba9043896f..874ddf2114a219 100644 --- a/homeassistant/components/nest.py +++ b/homeassistant/components/nest.py @@ -168,6 +168,19 @@ def __init__(self, hass, conf, nest): self.local_structure = conf[CONF_STRUCTURE] _LOGGER.debug("Structures to include: %s", self.local_structure) + def structures(self): + """Generate a list of structures.""" + try: + for structure in self.nest.structures: + if structure.name in self.local_structure: + yield structure + else: + _LOGGER.debug("Ignoring structure %s, not in %s", + structure.name, self.local_structure) + except socket.error: + _LOGGER.error( + "Connection error logging into the nest web service.") + def thermostats(self): """Generate a list of thermostats and their location.""" try: @@ -190,8 +203,8 @@ def smoke_co_alarms(self): for device in structure.smoke_co_alarms: yield(structure, device) else: - _LOGGER.info("Ignoring structure %s, not in %s", - structure.name, self.local_structure) + _LOGGER.debug("Ignoring structure %s, not in %s", + structure.name, self.local_structure) except socket.error: _LOGGER.error( "Connection error logging into the nest web service.") @@ -204,8 +217,8 @@ def cameras(self): for device in structure.cameras: yield(structure, device) else: - _LOGGER.info("Ignoring structure %s, not in %s", - structure.name, self.local_structure) + _LOGGER.debug("Ignoring structure %s, not in %s", + structure.name, self.local_structure) except socket.error: _LOGGER.error( "Connection error logging into the nest web service.") diff --git a/homeassistant/components/sensor/nest.py b/homeassistant/components/sensor/nest.py index 9ce50dc61e5bd3..66aa10b6c62dc5 100644 --- a/homeassistant/components/sensor/nest.py +++ b/homeassistant/components/sensor/nest.py @@ -36,10 +36,13 @@ SENSOR_TEMP_TYPES = ['temperature', 'target'] +STRUCTURE_SENSOR_TYPES = ['eta'] + _SENSOR_TYPES_DEPRECATED = SENSOR_TYPES_DEPRECATED \ + list(DEPRECATED_WEATHER_VARS.keys()) + PROTECT_VARS_DEPRECATED -_VALID_SENSOR_TYPES = SENSOR_TYPES + SENSOR_TEMP_TYPES + PROTECT_VARS +_VALID_SENSOR_TYPES = SENSOR_TYPES + SENSOR_TEMP_TYPES + PROTECT_VARS \ + + STRUCTURE_SENSOR_TYPES _LOGGER = logging.getLogger(__name__) @@ -73,6 +76,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error(wstr) all_sensors = [] + for structure in nest.structures(): + all_sensors += [NestBasicSensor(structure, None, variable) + for variable in conditions + if variable in STRUCTURE_SENSOR_TYPES] for structure, device in chain(nest.thermostats(), nest.smoke_co_alarms()): sensors = [NestBasicSensor(structure, device, variable) for variable in conditions @@ -94,13 +101,20 @@ class NestSensor(Entity): def __init__(self, structure, device, variable): """Initialize the sensor.""" self.structure = structure - self.device = device self.variable = variable - # device specific - self._location = self.device.where - self._name = "{} {}".format(self.device.name_long, - self.variable.replace("_", " ")) + if device is not None: + # device specific + self.device = device + self._location = self.device.where + self._name = "{} {}".format(self.device.name_long, + self.variable.replace("_", " ")) + else: + # structure only + self.device = structure + self._name = "{} {}".format(self.structure.name, + self.variable.replace("_", " ")) + self._state = None self._unit = None @@ -129,6 +143,8 @@ def update(self): if self.variable == 'operation_mode': self._state = getattr(self.device, "mode") + elif self.variable == 'eta': + self._state = getattr(self.device, 'eta_begin') else: self._state = getattr(self.device, self.variable) From dc0f8860f7cb5a0e84b7ea39d652404c4507cc89 Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Fri, 11 May 2018 20:34:30 -0700 Subject: [PATCH 2/5] Add away sensor to nest binary sensors, eta to nest sensors Comment out one line of code for security_state which need future version of python-nest --- .../components/binary_sensor/nest.py | 23 +++++++++++++-- homeassistant/components/nest.py | 21 +++++++++++--- homeassistant/components/sensor/nest.py | 28 +++++++++++++++---- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/binary_sensor/nest.py b/homeassistant/components/binary_sensor/nest.py index 4089f3a2eaf60f..c120b46af749b2 100644 --- a/homeassistant/components/binary_sensor/nest.py +++ b/homeassistant/components/binary_sensor/nest.py @@ -29,6 +29,16 @@ 'person_detected', ] +STRUCTURE_BINARY_TYPES = [ + 'away', + # 'security_state', # wait python-nest update +] + +STRUCTURE_BINARY_STATE_MAP = { + 'away': {'away': True, 'home': False}, + 'security_state': {'deter': True, 'ok': False}, +} + _BINARY_TYPES_DEPRECATED = [ 'hvac_ac_state', 'hvac_aux_heater_state', @@ -41,7 +51,7 @@ ] _VALID_BINARY_SENSOR_TYPES = BINARY_TYPES + CLIMATE_BINARY_TYPES \ - + CAMERA_BINARY_TYPES + + CAMERA_BINARY_TYPES + STRUCTURE_BINARY_TYPES _LOGGER = logging.getLogger(__name__) @@ -68,6 +78,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error(wstr) sensors = [] + for structure in nest.structures(): + sensors += [NestBinarySensor(structure, None, variable) + for variable in conditions + if variable in STRUCTURE_BINARY_TYPES] device_chain = chain(nest.thermostats(), nest.smoke_co_alarms(), nest.cameras()) @@ -88,7 +102,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): sensors += [NestActivityZoneSensor(structure, device, activity_zone)] - add_devices(sensors, True) @@ -102,7 +115,11 @@ def is_on(self): def update(self): """Retrieve latest state.""" - self._state = bool(getattr(self.device, self.variable)) + value = getattr(self.device, self.variable) + if self.variable in STRUCTURE_BINARY_TYPES: + self._state = bool(STRUCTURE_BINARY_STATE_MAP[self.variable][value]) + else: + self._state = bool(value) class NestActivityZoneSensor(NestBinarySensor): diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py index e7d2ba9043896f..874ddf2114a219 100644 --- a/homeassistant/components/nest.py +++ b/homeassistant/components/nest.py @@ -168,6 +168,19 @@ def __init__(self, hass, conf, nest): self.local_structure = conf[CONF_STRUCTURE] _LOGGER.debug("Structures to include: %s", self.local_structure) + def structures(self): + """Generate a list of structures.""" + try: + for structure in self.nest.structures: + if structure.name in self.local_structure: + yield structure + else: + _LOGGER.debug("Ignoring structure %s, not in %s", + structure.name, self.local_structure) + except socket.error: + _LOGGER.error( + "Connection error logging into the nest web service.") + def thermostats(self): """Generate a list of thermostats and their location.""" try: @@ -190,8 +203,8 @@ def smoke_co_alarms(self): for device in structure.smoke_co_alarms: yield(structure, device) else: - _LOGGER.info("Ignoring structure %s, not in %s", - structure.name, self.local_structure) + _LOGGER.debug("Ignoring structure %s, not in %s", + structure.name, self.local_structure) except socket.error: _LOGGER.error( "Connection error logging into the nest web service.") @@ -204,8 +217,8 @@ def cameras(self): for device in structure.cameras: yield(structure, device) else: - _LOGGER.info("Ignoring structure %s, not in %s", - structure.name, self.local_structure) + _LOGGER.debug("Ignoring structure %s, not in %s", + structure.name, self.local_structure) except socket.error: _LOGGER.error( "Connection error logging into the nest web service.") diff --git a/homeassistant/components/sensor/nest.py b/homeassistant/components/sensor/nest.py index 9ce50dc61e5bd3..66aa10b6c62dc5 100644 --- a/homeassistant/components/sensor/nest.py +++ b/homeassistant/components/sensor/nest.py @@ -36,10 +36,13 @@ SENSOR_TEMP_TYPES = ['temperature', 'target'] +STRUCTURE_SENSOR_TYPES = ['eta'] + _SENSOR_TYPES_DEPRECATED = SENSOR_TYPES_DEPRECATED \ + list(DEPRECATED_WEATHER_VARS.keys()) + PROTECT_VARS_DEPRECATED -_VALID_SENSOR_TYPES = SENSOR_TYPES + SENSOR_TEMP_TYPES + PROTECT_VARS +_VALID_SENSOR_TYPES = SENSOR_TYPES + SENSOR_TEMP_TYPES + PROTECT_VARS \ + + STRUCTURE_SENSOR_TYPES _LOGGER = logging.getLogger(__name__) @@ -73,6 +76,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error(wstr) all_sensors = [] + for structure in nest.structures(): + all_sensors += [NestBasicSensor(structure, None, variable) + for variable in conditions + if variable in STRUCTURE_SENSOR_TYPES] for structure, device in chain(nest.thermostats(), nest.smoke_co_alarms()): sensors = [NestBasicSensor(structure, device, variable) for variable in conditions @@ -94,13 +101,20 @@ class NestSensor(Entity): def __init__(self, structure, device, variable): """Initialize the sensor.""" self.structure = structure - self.device = device self.variable = variable - # device specific - self._location = self.device.where - self._name = "{} {}".format(self.device.name_long, - self.variable.replace("_", " ")) + if device is not None: + # device specific + self.device = device + self._location = self.device.where + self._name = "{} {}".format(self.device.name_long, + self.variable.replace("_", " ")) + else: + # structure only + self.device = structure + self._name = "{} {}".format(self.structure.name, + self.variable.replace("_", " ")) + self._state = None self._unit = None @@ -129,6 +143,8 @@ def update(self): if self.variable == 'operation_mode': self._state = getattr(self.device, "mode") + elif self.variable == 'eta': + self._state = getattr(self.device, 'eta_begin') else: self._state = getattr(self.device, self.variable) From 99ac2806c2bd7866e33c93c609ac01f69daaab0d Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Fri, 11 May 2018 20:44:09 -0700 Subject: [PATCH 3/5] Fix lint --- homeassistant/components/binary_sensor/nest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/binary_sensor/nest.py b/homeassistant/components/binary_sensor/nest.py index c120b46af749b2..2864a4943fc47d 100644 --- a/homeassistant/components/binary_sensor/nest.py +++ b/homeassistant/components/binary_sensor/nest.py @@ -117,7 +117,8 @@ def update(self): """Retrieve latest state.""" value = getattr(self.device, self.variable) if self.variable in STRUCTURE_BINARY_TYPES: - self._state = bool(STRUCTURE_BINARY_STATE_MAP[self.variable][value]) + self._state = bool(STRUCTURE_BINARY_STATE_MAP + [self.variable][value]) else: self._state = bool(value) From 484cf7b6bb712776a95d0c2ce79860de2eb16e8c Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Sat, 12 May 2018 07:57:15 -0700 Subject: [PATCH 4/5] Try to re-trigger the cla-bot --- homeassistant/components/binary_sensor/nest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/binary_sensor/nest.py b/homeassistant/components/binary_sensor/nest.py index 2864a4943fc47d..2a1732cd9f0483 100644 --- a/homeassistant/components/binary_sensor/nest.py +++ b/homeassistant/components/binary_sensor/nest.py @@ -31,7 +31,7 @@ STRUCTURE_BINARY_TYPES = [ 'away', - # 'security_state', # wait python-nest update + # 'security_state', # wait for pending python-nest update ] STRUCTURE_BINARY_STATE_MAP = { From 64bf54e3df490ea67b351f78ec056fdc18ec83b0 Mon Sep 17 00:00:00 2001 From: Jason Hu Date: Wed, 23 May 2018 10:02:19 -0700 Subject: [PATCH 5/5] Follow code review comment --- homeassistant/components/nest.py | 4 ++-- homeassistant/components/sensor/nest.py | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py index 874ddf2114a219..2500755d495f8b 100644 --- a/homeassistant/components/nest.py +++ b/homeassistant/components/nest.py @@ -201,7 +201,7 @@ def smoke_co_alarms(self): for structure in self.nest.structures: if structure.name in self.local_structure: for device in structure.smoke_co_alarms: - yield(structure, device) + yield (structure, device) else: _LOGGER.debug("Ignoring structure %s, not in %s", structure.name, self.local_structure) @@ -215,7 +215,7 @@ def cameras(self): for structure in self.nest.structures: if structure.name in self.local_structure: for device in structure.cameras: - yield(structure, device) + yield (structure, device) else: _LOGGER.debug("Ignoring structure %s, not in %s", structure.name, self.local_structure) diff --git a/homeassistant/components/sensor/nest.py b/homeassistant/components/sensor/nest.py index 66aa10b6c62dc5..0de2e2e0cdbfdb 100644 --- a/homeassistant/components/sensor/nest.py +++ b/homeassistant/components/sensor/nest.py @@ -38,6 +38,8 @@ STRUCTURE_SENSOR_TYPES = ['eta'] +VARIABLE_NAME_MAPPING = {'eta': 'eta_begin', 'operation_mode': 'mode'} + _SENSOR_TYPES_DEPRECATED = SENSOR_TYPES_DEPRECATED \ + list(DEPRECATED_WEATHER_VARS.keys()) + PROTECT_VARS_DEPRECATED @@ -108,12 +110,12 @@ def __init__(self, structure, device, variable): self.device = device self._location = self.device.where self._name = "{} {}".format(self.device.name_long, - self.variable.replace("_", " ")) + self.variable.replace('_', ' ')) else: # structure only self.device = structure self._name = "{} {}".format(self.structure.name, - self.variable.replace("_", " ")) + self.variable.replace('_', ' ')) self._state = None self._unit = None @@ -141,10 +143,9 @@ def update(self): """Retrieve latest state.""" self._unit = SENSOR_UNITS.get(self.variable, None) - if self.variable == 'operation_mode': - self._state = getattr(self.device, "mode") - elif self.variable == 'eta': - self._state = getattr(self.device, 'eta_begin') + if self.variable in VARIABLE_NAME_MAPPING: + self._state = getattr(self.device, + VARIABLE_NAME_MAPPING[self.variable]) else: self._state = getattr(self.device, self.variable)