From 6cb02128b4dd646444a66a03019b24e97616e23d Mon Sep 17 00:00:00 2001
From: PhracturedBlue <rc2012@pblue.org>
Date: Thu, 4 Jan 2018 11:10:56 -0800
Subject: [PATCH] Reconnect to alarmdecoder on disconnect (#11383)

* Reconnect to alarmdecoder on disconnect

* Use track_point_in_time instead of call_later

* use alarmdecoder 1.13.2 which has a more robust reconnection fix
---
 homeassistant/components/alarmdecoder.py | 34 +++++++++++++++++++++---
 requirements_all.txt                     |  2 +-
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/homeassistant/components/alarmdecoder.py b/homeassistant/components/alarmdecoder.py
index c5321b918b9..120925dab6e 100644
--- a/homeassistant/components/alarmdecoder.py
+++ b/homeassistant/components/alarmdecoder.py
@@ -6,13 +6,15 @@ https://home-assistant.io/components/alarmdecoder/
 """
 import logging
 
+from datetime import timedelta
 import voluptuous as vol
 
 import homeassistant.helpers.config_validation as cv
 from homeassistant.const import EVENT_HOMEASSISTANT_STOP
 from homeassistant.helpers.discovery import load_platform
+from homeassistant.util import dt as dt_util
 
-REQUIREMENTS = ['alarmdecoder==0.12.3']
+REQUIREMENTS = ['alarmdecoder==1.13.2']
 
 _LOGGER = logging.getLogger(__name__)
 
@@ -88,6 +90,7 @@ def setup(hass, config):
 
     conf = config.get(DOMAIN)
 
+    restart = False
     device = conf.get(CONF_DEVICE)
     display = conf.get(CONF_PANEL_DISPLAY)
     zones = conf.get(CONF_ZONES)
@@ -101,8 +104,33 @@ def setup(hass, config):
     def stop_alarmdecoder(event):
         """Handle the shutdown of AlarmDecoder."""
         _LOGGER.debug("Shutting down alarmdecoder")
+        nonlocal restart
+        restart = False
         controller.close()
 
+    def open_connection(now=None):
+        """Open a connection to AlarmDecoder."""
+        from alarmdecoder.util import NoDeviceError
+        nonlocal restart
+        try:
+            controller.open(baud)
+        except NoDeviceError:
+            _LOGGER.debug("Failed to connect.  Retrying in 5 seconds")
+            hass.helpers.event.track_point_in_time(
+                open_connection, dt_util.utcnow() + timedelta(seconds=5))
+            return
+        _LOGGER.debug("Established a connection with the alarmdecoder")
+        restart = True
+
+    def handle_closed_connection(event):
+        """Restart after unexpected loss of connection."""
+        nonlocal restart
+        if not restart:
+            return
+        restart = False
+        _LOGGER.warning("AlarmDecoder unexpectedly lost connection.")
+        hass.add_job(open_connection)
+
     def handle_message(sender, message):
         """Handle message from AlarmDecoder."""
         hass.helpers.dispatcher.dispatcher_send(
@@ -140,12 +168,12 @@ def setup(hass, config):
     controller.on_rfx_message += handle_rfx_message
     controller.on_zone_fault += zone_fault_callback
     controller.on_zone_restore += zone_restore_callback
+    controller.on_close += handle_closed_connection
 
     hass.data[DATA_AD] = controller
 
-    controller.open(baud)
+    open_connection()
 
-    _LOGGER.debug("Established a connection with the alarmdecoder")
     hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_alarmdecoder)
 
     load_platform(hass, 'alarm_control_panel', DOMAIN, conf, config)
diff --git a/requirements_all.txt b/requirements_all.txt
index c08ac5b703c..7084efae27b 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -81,7 +81,7 @@ aiolifx_effects==0.1.2
 aiopvapi==1.5.4
 
 # homeassistant.components.alarmdecoder
-alarmdecoder==0.12.3
+alarmdecoder==1.13.2
 
 # homeassistant.components.sensor.alpha_vantage
 alpha_vantage==1.6.0
-- 
GitLab