Tuesday, March 4, 2014

Status of the Home Brew Security System

I decided to upgrade from an Arduino and a large media server to an Udoo quad core (http://shop.udoo.org/usa/product/udoo-quad.html), because I didn't want to have to have the event server on the same network as everyone else.  I'm sort of paranoid.  What I found is :
  • The Udoo uses GPIO inputs that ARE available through the Linux image.
  • The Udoo failed to work with my relays.  This was because the relays were 5v relays (perfect for the Arduino Mega2560 I was using), but the Udoo uses a 3v logic level.  Simply put, the relays would never work.
  • I could put my entire event server package onto the Udoo, and have a self-contained alert system.  This was my goal.
Here's what happened.

I found a great tutorial from Adafruit at http://www.udoo.org/ProjectsAndTutorials/linux-gpio-manipulation/.  I slapped together some listener programs to watch the GPIO states, and I was suddenly in business again.  I no longer needed to upload any code to the Atmel chip on board - I could do it all in native C code, standard-Linux stuff.  Those tools were checked into the event server repository (subversion), and have been thoroughly tested.

Next, I needed to be able to work the garage door.  I toyed with building a separate, stand-alone device, but I'd already done that, and I was starting to get lazy.  I found a device on ebay, http://www.ebay.com/itm/111248757109?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l2649, that was $50, and had two relays and Ethernet.  The downside is this came hard coded to an IP address of  I had to use a crossover cable to connect it up, and reconfigure it to use DHCP.  It has a simple web-based interface.  So, being the nerd I am, I watched network traffic to see what requests were being sent.  When I'd click one of the relay buttons on the web page, it would send a request :
When I turned it back off, it sent an identical request.  There was no "off" or "on" designation in the requests.  Apparently, the device simply took "toggle" commands".

I did find if I left off the ?relay=1, it simply gave me the following page:
    <font size="5"> one                             <span style="color:red">0 </span> </font>
    <br />
    <br />
    <br />
    <font size="5"> two                             <span style="color:red">0 </span> </font>
    <p hidden>
    Status: 0 0 
    Relay1: one                          
    Relay2: two                          
Now I was getting somewhere.  I toggled it, ran the previous, and found that the "Status: 0 0" line went to "Status: 1 0".  It's a two relay board, so now I know how to get the current state.  Next, I needed to identify what had to be done to ensure it was always turning the switch off when it was done acting like a momentary push-button :
  1. Ensure the switch was in the off position.
  2. Toggle the switch to the "on" position.
  3. Wait for 1 second.
  4. Toggle the switch back to the "off" position.
So, I used the request without the "?relay=1" to get the "Status: " line for the relay I needed.  If it had a 1 for that one, I had to turn it off first.  In my case, it should ALWAYS be in the off position already.  Next, I had to toggle it to "on" position, and a simple request to the following would work perfectly :
Then, I slept for a second, and then made that toggle request a second time to turn it off.  I hooked it up, and ran it.  Woohooo!  I'm back online again!  Here's the code I used :


use LWP;
use HTTP::Request;

my $relay_host = '';
my $relay_index = 0;

my $ua = LWP::UserAgent->new('alarmsystem');
$ua->credentials($relay_host.':80',"Protected", 'admin', 'admin');

# FIRST - Ensure this thing is OFF
my $res = $ua->get('http://'.$relay_host.'/relays.cgi');
print $res->content;
if ($res->content =~ /status: ([\d\s]+)/i) {
  my (@rows) = split(/[\s\t]+/,$1);

  if ($rows[$relay_index] == 1) {
    my $res = $ua->get('http://'.$relay_host.'/relays.cgi?relay='.($relay_index+1));

# SECOND - Turn it ON
my $res = $ua->get('http://'.$relay_host.'/relays.cgi?relay='.($relay_index+1));
# sleep for a second
# LAST - Turn it back to OFF
my $res = $ua->get('http://'.$relay_host.'/relays.cgi?relay='.($relay_index+1));