Home Automation 2.0 – Pt 3

In my first post, in this three-part series, I wrote about how I physically interfaced my Ademco Alarm Panel to my Home Automation computer.  In this article, I will show you how to capture the data stream that comes through that interface, how to parse it and then how to make use of it in our Indigo Home Automation system.

Review & Some Cautions

As outlined in the first article, we’re using an AD2USB Adapter from NuTech which is wired into the Ademco panel and then connected to my Mac via USB.  Let me just state here that I had a lot of issues getting this to work reliably! My first attempt to interface to my Mac, located about 30 ft away, was just too unreliable.  I ended up moving my HA server to my wiring closet so I could use a standard USB cable.  This too proved to be unreliable until I used a shielded USB cable as covered in article two. Since implementing these changes, my system has been up and running without incident.

Getting Our Data

In article two I mentioned that I was using a software product called Serial Bridge and thought that it might have been the source of my data feed reliability problems.  While I eventually ruled Serial Bridge out as the source of my problems, I’m not convinced that it was not, at least, a contributing factor. The software is produced by Perceptive Automation and was written for the Mac PowerPC platform. Since my HA system runs on Mac OS/x on the intel platform, that means Serial Bridge had to run using Apple’s Rosetta translator.  This added overhead and I just simply didn’t like the solution and decided to look for other options. Seeking “other options” quickly led to the need to write my own solution. I considered Python and Perl but ultimately settled on my faithful standby, PHP.

One of the beauties of Unix-like operating systems (The core of OS/x is based on BSD) is how easy it is to interface with devices.  When the AD2USB is plugged into one of the Mac’s USB ports the FTDI software creates a Serial Port for us that shows up in /dev. Since the AD2USB is producing a text feed for us we can easily view that feed by opening a connection to our serial device and outputting its contents to STDOUT.

cat /dev/cu.usbserial-A2001wKL

Note: Your device name will differ.

At this point you should see a stream of cryptic data coming from your AD2USB Adapter.

Working with Indigo

Now that we know we have the ability to easily get our data feed from the AD2USB by simply “opening” a connection to our device, let’s now turn our attention to how we interface with Indigo.

Indigo 4 ships with an excellent API that allows us to do just about anything we want programatically.  My setup tracks the status of my alarm panel via a variable.  I can then write triggers within Indigo to take certain actions based on the status of my panel.  An example of this is to turn on all the lights in the house when the garage door is opened after dark ONLY if the Alarm is engaged.  In this scenario, I know the house is empty so we can turn on all the lights without disturbing anyone and we get to walk into a fully lit house.  Scenarios for how you can use this data are endless.

Bringing it all together

Now that we know how to get the data and how we’ll interface with Indigo, we need to write our script. As I mentioned previously, my choice is PHP which I will be running in CLI mode.  Fortunately, PHP CLI ships standard on the Mac platform so there is no setup required.

#!/usr/bin/php -q
<?php
 /**
 *  Author: Geek-Tips.com
 *    Date: 26 November 2010
 * Updated: 27 November 2010
 *    File: ad2usb-parser.php
 * Version: 0.4
 * Purpose: The scripts purpose is to capture the data stream that comes from the ad2usb device and
 *                    feed state change information into Indigo.
 *
 *   Notes: V0.4: Removed getdata function to external file.
 *                    V0.3: Purchased Serial Bridge from Perceptive Automation to perform this function but
 *                    I seemed to have regular problems with that solution.  I also noticed that Serial Bridge
 *                    seemed to tax the CPU on my Home Automation server in a range from 20% - 85% which didn't
 *                    seem like a good overall solution.  I think the cpu issues may have been related to
 *                    to the fact that the solution was written for PowerPC which requires me to run Rosetta
 *                    and I wanted to get rid of that any way.  I sent a note to Jay over at Perceptive
 *                    Automation.
 *
 *                    Usage: ./ad2usb-parser.php
 *
 *   Legal: AD2USB Parser by Geek-Tips.com is licensed under a Creative Commons
 *                    Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 *                    http://creativecommons.org/licenses/by-nc-sa/3.0/
 **/

 require_once("../functions/getdata.php");

 $alarm_state = "";
 $alarm_state_compare = "";
 $alarm_display = "";
 $alarm_display_compare = "";
 $indigourl = "http://127.0.0.1:8176/variables/";

 do{
 $handle = fopen("/dev/cu.usbserial-A2001wKL","r");
       $mintime = time();
       do{
 $str_ad2usb = fgets($handle);

 $alarm_state_compare = substr($str_ad2usb,1,3);
 $alarm_display_compare = urlencode(trim(substr($str_ad2usb,61,-3)));
 echo $str_ad2usb;

 if ($alarm_state_compare != $alarm_state) {
       if ($alarm_state_compare == '100') {
             $updateurl = $indigourl . "alarmstate?_method=put&value=100+Disarmed";
             $result = get_data($updateurl);
       } elseif ($alarm_state_compare == '010') {
             $updateurl = $indigourl . "alarmstate?_method=put&value=010+Armed+Away";
             $result = get_data($updateurl);
       } elseif ($alarm_state_compare == '001') {
             $updateurl = $indigourl . "alarmstate?_method=put&value=001+Armed+Stay";
             $result = get_data($updateurl);
       }
             $alarm_state = $alarm_state_compare;
 }

 if ($alarm_display_compare != $alarm_display) {
       if ($alarm_display_compare != urlencode("DISARMED CHIME Hit * for faults")) {
             $updateurl = $indigourl . "alarmdisplay?_method=put&value=" . $alarm_display_compare;
             $result = get_data($updateurl);
             $alarm_display = $alarm_display_compare;
       }
 }

 $str_ad2usb = '';
 sleep(1);
       }while( time()< $mintime+60);
       fclose($handle);
 }while(1);

 fclose($handle);
 ?>
<?php
 function get_data($url)
 {
 $ch = curl_init();

 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_HEADER, 0);
 curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4);
 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
 curl_setopt($ch, CURLOPT_URL, $url);

 $data = curl_exec($ch);

 curl_close($ch);
 return $data;
 }
 ?>

You will need to modify the code to match your setup. Assuming you are running the script on your Indigo server then all you should be required to change is the variable names. If not, you’ll need to change the URL for the Indigo webserver as well.

That’s really all there is to it! For more information on the data records produced by the AD2USB, check out this link and adjust the script to meet your needs.

You will notice that I close the connection to the port with each loop.  This may not be necessary but was implemented while trying to sort out the reliability issues mentioned above.  Future versions of the script will likely leave the connection open indefinitely, but this will need to be thoroughly tested.

Until next time, GEEK OUT!

If you use this script or publish modifications, please give credit and let me know by leaving a comment.

~GT~

Leave a Comment

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