Improve stability of netatmo sensor (#24190)

* Improve stability of netatmo sensor

* Improve stability of netatmo sensor

* Improve stability of netatmo sensor

* netatmo, except timeout

* netatmo, except timeout

* netatmo, except timeout

* netatmo, except timeout

* Always release lock
This commit is contained in:
Daniel Høyer Iversen 2019-06-14 21:26:02 +02:00 committed by GitHub
parent 9aeb75f28d
commit b0e6f34976
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,20 +1,21 @@
"""Support for the Netatmo Weather Service."""
from datetime import timedelta
import logging
from time import time
import threading
from datetime import timedelta
from time import time
import requests
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import (
CONF_NAME, CONF_MODE, CONF_MONITORED_CONDITIONS,
TEMP_CELSIUS, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_BATTERY)
from homeassistant.helpers.entity import Entity
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import call_later
from homeassistant.util import Throttle
from .const import DATA_NETATMO_AUTH
_LOGGER = logging.getLogger(__name__)
@ -101,7 +102,6 @@ MODULE_TYPE_INDOOR = 'NAModule4'
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the available Netatmo weather sensors."""
dev = []
not_handled = {}
auth = hass.data[DATA_NETATMO_AUTH]
if config.get(CONF_AREAS) is not None:
@ -121,45 +121,55 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
area[CONF_MODE]
))
else:
for data_class in all_product_classes():
def _retry(_data):
try:
_dev = find_devices(_data)
except requests.exceptions.Timeout:
return call_later(hass, NETATMO_UPDATE_INTERVAL,
lambda _: _retry(_data))
if _dev:
add_entities(_dev, True)
import pyatmo
for data_class in [pyatmo.WeatherStationData, pyatmo.HomeCoachData]:
data = NetatmoData(auth, data_class, config.get(CONF_STATION))
module_items = []
# Test if manually configured
if CONF_MODULES in config:
module_items = config[CONF_MODULES].items()
else:
# otherwise add all modules and conditions
for module_name in data.get_module_names():
monitored_conditions = \
data.station_data.monitoredConditions(module_name)
module_items.append(
(module_name, monitored_conditions))
for module_name, monitored_conditions in module_items:
# Test if module exists
if module_name not in data.get_module_names():
not_handled[module_name] = \
not_handled[module_name]+1 \
if module_name in not_handled else 1
else:
# Only create sensors for monitored properties
for module_name, monitored_conditions in module_items:
for condition in monitored_conditions:
dev.append(NetatmoSensor(
data, module_name, condition.lower(),
config.get(CONF_STATION)))
continue
for module_name, _ in not_handled.items():
_LOGGER.error('Module name: "%s" not found', module_name)
# otherwise add all modules and conditions
try:
dev.extend(find_devices(data))
except requests.exceptions.Timeout:
call_later(hass, NETATMO_UPDATE_INTERVAL,
lambda _: _retry(data))
if dev:
add_entities(dev, True)
def all_product_classes():
"""Provide all handled Netatmo product classes."""
import pyatmo
def find_devices(data):
"""Find all devices."""
dev = []
not_handled = []
for module_name in data.get_module_names():
if (module_name not in data.get_module_names()
and module_name not in not_handled):
not_handled.append(not_handled)
continue
for condition in data.station_data.monitoredConditions(module_name):
dev.append(NetatmoSensor(
data, module_name, condition.lower(), data.station))
return [pyatmo.WeatherStationData, pyatmo.HomeCoachData]
for module_name in not_handled:
_LOGGER.error('Module name: "%s" not found', module_name)
return dev
class NetatmoSensor(Entity):
@ -515,22 +525,6 @@ class NetatmoData:
self.update()
return self.data.keys()
def _detect_platform_type(self):
"""Return the XXXData object corresponding to the specified platform.
The return can be a WeatherStationData or a HomeCoachData.
"""
from pyatmo import NoDevice
try:
station_data = self.data_class(self.auth)
_LOGGER.debug("%s detected!", str(self.data_class.__name__))
return station_data
except NoDevice:
_LOGGER.warning("No Weather or HomeCoach devices found for %s",
str(self.station)
)
raise
def update(self):
"""Call the Netatmo API to update the data.
@ -541,14 +535,20 @@ class NetatmoData:
if time() < self._next_update or \
not self._update_in_progress.acquire(False):
return
from pyatmo import NoDevice
try:
self.station_data = self._detect_platform_type()
except NoDevice:
return
from pyatmo import NoDevice
try:
self.station_data = self.data_class(self.auth)
_LOGGER.debug("%s detected!", str(self.data_class.__name__))
except NoDevice:
_LOGGER.warning("No Weather or HomeCoach devices found for %s",
str(self.station)
)
return
except requests.exceptions.Timeout:
_LOGGER.warning("Timed out when connecting to Netatmo server.")
return
try:
if self.station is not None:
data = self.station_data.lastData(
station=self.station, exclude=3600)