Update waterfurnace library to 0.7, add reconnect logic (#15657)

One of the features of the waterfurnace 0.7 is timingout out stuck
connections on the websocket (which tends to happen after 48 - 96
hours of operation). This requires the homeassistant component to
catch and reconnect under these circumstances. This has turned out to
be pretty robust in preventing stuck sockets over the last month.
This commit is contained in:
Sean Dague 2018-08-14 07:49:04 -04:00 committed by GitHub
parent 91e1ae035e
commit 051903d30c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 16 deletions

View File

@ -18,7 +18,8 @@ from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import discovery
REQUIREMENTS = ["waterfurnace==0.4.0"]
REQUIREMENTS = ["waterfurnace==0.7.0"]
_LOGGER = logging.getLogger(__name__)
@ -26,6 +27,11 @@ DOMAIN = "waterfurnace"
UPDATE_TOPIC = DOMAIN + "_update"
CONF_UNIT = "unit"
SCAN_INTERVAL = timedelta(seconds=10)
ERROR_INTERVAL = timedelta(seconds=300)
MAX_FAILS = 10
NOTIFICATION_ID = 'waterfurnace_website_notification'
NOTIFICATION_TITLE = 'WaterFurnace website status'
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
@ -80,6 +86,36 @@ class WaterFurnaceData(threading.Thread):
self.unit = client.unit
self.data = None
self._shutdown = False
self._fails = 0
def _reconnect(self):
"""Reconnect on a failure."""
import waterfurnace.waterfurnace as wf
self._fails += 1
if self._fails > MAX_FAILS:
_LOGGER.error(
"Failed to refresh login credentials. Thread stopped.")
self.hass.components.persistent_notification.create(
"Error:<br/>Connection to waterfurnace website failed "
"the maximum number of times. Thread has stopped.",
title=NOTIFICATION_TITLE,
notification_id=NOTIFICATION_ID)
self._shutdown = True
return
# sleep first before the reconnect attempt
_LOGGER.debug("Sleeping for fail # %s", self._fails)
time.sleep(self._fails * ERROR_INTERVAL.seconds)
try:
self.client.login()
self.data = self.client.read()
except wf.WFException:
_LOGGER.exception("Failed to reconnect attempt %s", self._fails)
else:
_LOGGER.debug("Reconnected to furnace")
self._fails = 0
def run(self):
"""Thread run loop."""
@ -117,20 +153,7 @@ class WaterFurnaceData(threading.Thread):
# that pretty much can all be solved by logging in and
# back out again.
_LOGGER.exception("Failed to read data, attempting to recover")
try:
self.client.login()
except Exception: # pylint: disable=broad-except
# nested exception handling, something really bad
# happened during the login, which means we're not
# in a recoverable state. Stop the thread so we
# don't do just keep poking at the service.
_LOGGER.error(
"Failed to refresh login credentials. Thread stopped.")
return
else:
_LOGGER.error(
"Lost our connection to websocket, trying again")
time.sleep(SCAN_INTERVAL.seconds)
self._reconnect()
else:
self.hass.helpers.dispatcher.dispatcher_send(UPDATE_TOPIC)

View File

@ -1444,7 +1444,7 @@ warrant==0.6.1
watchdog==0.8.3
# homeassistant.components.waterfurnace
waterfurnace==0.4.0
waterfurnace==0.7.0
# homeassistant.components.media_player.gpmdp
websocket-client==0.37.0