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.
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!