Prevent Nest component setup crash due insufficient permission. (#14966)
* Prevent Nest component setup crash due insufficient permission. * Trigger CI * Better error handle and address code review comments * Lint * Tiny wording adjust * Notify user if async_setup_entry failed * Return False if exception occurred in NestDevice.initialize
This commit is contained in:
parent
15507df407
commit
6e4fb7a937
1 changed files with 48 additions and 37 deletions
|
@ -123,7 +123,8 @@ async def async_setup_entry(hass, entry):
|
||||||
_LOGGER.debug("proceeding with setup")
|
_LOGGER.debug("proceeding with setup")
|
||||||
conf = hass.data.get(DATA_NEST_CONFIG, {})
|
conf = hass.data.get(DATA_NEST_CONFIG, {})
|
||||||
hass.data[DATA_NEST] = NestDevice(hass, conf, nest)
|
hass.data[DATA_NEST] = NestDevice(hass, conf, nest)
|
||||||
await hass.async_add_job(hass.data[DATA_NEST].initialize)
|
if not await hass.async_add_job(hass.data[DATA_NEST].initialize):
|
||||||
|
return False
|
||||||
|
|
||||||
for component in 'climate', 'camera', 'sensor', 'binary_sensor':
|
for component in 'climate', 'camera', 'sensor', 'binary_sensor':
|
||||||
hass.async_add_job(hass.config_entries.async_forward_entry_setup(
|
hass.async_add_job(hass.config_entries.async_forward_entry_setup(
|
||||||
|
@ -193,63 +194,73 @@ class NestDevice(object):
|
||||||
|
|
||||||
def initialize(self):
|
def initialize(self):
|
||||||
"""Initialize Nest."""
|
"""Initialize Nest."""
|
||||||
|
from nest.nest import AuthorizationError, APIError
|
||||||
|
try:
|
||||||
|
# Do not optimize next statement, it is here for initialize
|
||||||
|
# persistence Nest API connection.
|
||||||
|
structure_names = [s.name for s in self.nest.structures]
|
||||||
if self.local_structure is None:
|
if self.local_structure is None:
|
||||||
self.local_structure = [s.name for s in self.nest.structures]
|
self.local_structure = structure_names
|
||||||
|
|
||||||
|
except (AuthorizationError, APIError, socket.error) as err:
|
||||||
|
_LOGGER.error(
|
||||||
|
"Connection error while access Nest web service: %s", err)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def structures(self):
|
def structures(self):
|
||||||
"""Generate a list of structures."""
|
"""Generate a list of structures."""
|
||||||
|
from nest.nest import AuthorizationError, APIError
|
||||||
try:
|
try:
|
||||||
for structure in self.nest.structures:
|
for structure in self.nest.structures:
|
||||||
if structure.name in self.local_structure:
|
if structure.name not in self.local_structure:
|
||||||
yield structure
|
|
||||||
else:
|
|
||||||
_LOGGER.debug("Ignoring structure %s, not in %s",
|
_LOGGER.debug("Ignoring structure %s, not in %s",
|
||||||
structure.name, self.local_structure)
|
structure.name, self.local_structure)
|
||||||
except socket.error:
|
continue
|
||||||
|
yield structure
|
||||||
|
|
||||||
|
except (AuthorizationError, APIError, socket.error) as err:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Connection error logging into the nest web service.")
|
"Connection error while access Nest web service: %s", err)
|
||||||
|
|
||||||
def thermostats(self):
|
def thermostats(self):
|
||||||
"""Generate a list of thermostats and their location."""
|
"""Generate a list of thermostats."""
|
||||||
try:
|
return self._devices('thermostats')
|
||||||
for structure in self.nest.structures:
|
|
||||||
if structure.name in self.local_structure:
|
|
||||||
for device in structure.thermostats:
|
|
||||||
yield (structure, device)
|
|
||||||
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 smoke_co_alarms(self):
|
def smoke_co_alarms(self):
|
||||||
"""Generate a list of smoke co alarms."""
|
"""Generate a list of smoke co alarms."""
|
||||||
try:
|
return self._devices('smoke_co_alarms')
|
||||||
for structure in self.nest.structures:
|
|
||||||
if structure.name in self.local_structure:
|
|
||||||
for device in structure.smoke_co_alarms:
|
|
||||||
yield (structure, device)
|
|
||||||
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 cameras(self):
|
def cameras(self):
|
||||||
"""Generate a list of cameras."""
|
"""Generate a list of cameras."""
|
||||||
|
return self._devices('cameras')
|
||||||
|
|
||||||
|
def _devices(self, device_type):
|
||||||
|
"""Generate a list of Nest devices."""
|
||||||
|
from nest.nest import AuthorizationError, APIError
|
||||||
try:
|
try:
|
||||||
for structure in self.nest.structures:
|
for structure in self.nest.structures:
|
||||||
if structure.name in self.local_structure:
|
if structure.name not in self.local_structure:
|
||||||
for device in structure.cameras:
|
|
||||||
yield (structure, device)
|
|
||||||
else:
|
|
||||||
_LOGGER.debug("Ignoring structure %s, not in %s",
|
_LOGGER.debug("Ignoring structure %s, not in %s",
|
||||||
structure.name, self.local_structure)
|
structure.name, self.local_structure)
|
||||||
except socket.error:
|
continue
|
||||||
|
|
||||||
|
for device in getattr(structure, device_type, []):
|
||||||
|
try:
|
||||||
|
# Do not optimize next statement,
|
||||||
|
# it is here for verify Nest API permission.
|
||||||
|
device.name_long
|
||||||
|
except KeyError:
|
||||||
|
_LOGGER.warning("Cannot retrieve device name for [%s]"
|
||||||
|
", please check your Nest developer "
|
||||||
|
"account permission settings.",
|
||||||
|
device.serial)
|
||||||
|
continue
|
||||||
|
yield (structure, device)
|
||||||
|
|
||||||
|
except (AuthorizationError, APIError, socket.error) as err:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Connection error logging into the nest web service.")
|
"Connection error while access Nest web service: %s", err)
|
||||||
|
|
||||||
|
|
||||||
class NestSensorDevice(Entity):
|
class NestSensorDevice(Entity):
|
||||||
|
|
Loading…
Add table
Reference in a new issue