Detecting Failed AD2USB to Raspberry Pi Connections

One of my ongoing home automation frustrations is the interface between my Ademco Alarm Panel and the Raspberry Pi I use to monitor the panel’s bus traffic. The problem that I have is a termination of the USB connection between the AD2USB (AlarmDecoder) that taps into the Ademco panel and the Pi itself. This always happens during a lightning storm and seems to be the USB port on the Raspberry Pi shutting down in response to voltage fluctuations coming from the AD2USB. Rebooting the Raspberry fixes the issue, but it usually takes a couple of days before I realize I’m not getting notifications from my HA system at which point I take steps to reset the Raspberry Pi.

I think I can resolve this issue once and for all by putting a USB Isolator between the AD2USB and the Raspberry Pi. To test this theory, I’ve ordered a unit from Circuits@Home which I hope to have in place within a few days.

USB Isolator
USB Isolator

I expect the isolator will greatly improve the reliability of the communications between the AD2USB and my HA system, but I also wanted to implement a monitoring system to notify me if messages stop coming from the AD2USB. Following is a simple python script that runs on the Raspberry Pi. If no messages are received within a five minute timeframe then a variable is set on my Indigo server which I then use to notify me of the failure.

import time
from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import SocketDevice
import urllib2
import logging

# Configuration values
logging.basicConfig(filename='ad2socket.log',format='%(asctime)s %(message)s',level=logging.DEBUG)
HOSTNAME = '127.0.0.1'
PORT = 10000
FAIL_URL = "http://indigo:8176/variables/ser2sockMon?_method=put&value=FAIL"
PASS_URL = "http://indigo:8176/variables/ser2sockMon?_method=put&value=PASS"
ALARM_COUNTER = 0

def main():
    """
    monitor socket communications if they stop sending data send an alert.
    """
    try:
        # Retrieve an AD2 device that has been exposed with ser2sock on localhost:10000.
        device = AlarmDecoder(SocketDevice(interface=(HOSTNAME, PORT)))

        # Set up an event handler and open the device
        device.on_message += handle_message
        with device.open():
            global ALARM_COUNTER
            while True:
                time.sleep(1)
                ALARM_COUNTER+=1;
                if ALARM_COUNTER > 300:
                    logging.info('FAIL')
                    ALARM_COUNTER=0
                    try:
                        response = urllib2.urlopen(FAIL_URL)
                    except Exception, ex:
                        logging.warning('Exception opening url ', ex)

    except Exception, ex:
        logging.warning('Exception: ', ex)

def handle_message(sender, message):
    """
    reset our alarm counter on every message
    """
    global ALARM_COUNTER

    try:
        response = urllib2.urlopen(PASS_URL)
    except Exception, ex:
        logging.warning('Exception opening url ', ex)
    ALARM_COUNTER=0

if __name__ == '__main__':
    main()

One helpful note to anyone wanting to mimic what I’ve done here is that there can be extended periods of time with little to no traffic on the alarm panel bus. In order to force traffic, I’ve set up a job on my Indigo server to send a panel message consisting of a single pound symbol (#) every five minutes. This always results in an updated alarm-state message being sent across the bus.

Until next time – GEEK OUT!

~GT~

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload the CAPTCHA.