![]() ![]() |
Nov 21 2007, 04:50 PM
Post
#1
|
|
|
Cocoonut ![]() ![]() ![]() ![]() Group: Registered Posts: 1439 Joined: 01.09.06 From: Montreal, QC Member No.: 1259 |
Overview
This document describes how to use ElkM1::Control, and custom scripts, to control and monitor an ElkM1 without the use of a Home Automation (HA) program. Introduction Many commercial HA applications (i.e. CQC, HomeSeer, HouseBot, PowerHome, etc) provide a means to monitor and control an Elk M1 via a driver. The driver can be an integral, optional, or a user-contributed component of the HA application. An effective M1 driver must create an Application Programming Interface (API) between the HA application and the M1. The API is considered complete if it encompasses all capabilities described in Elk's "ASCII Protocol RS-232 Interface Specification" document. Normally, an M1 driver is used exclusively with its native HA application. In most cases, the driver is an extension of the HA program and cannot function without it. However, thanks to Neil Cherry's posting in the MisterHouse mailing list, I learned of an M1 API that is not tied to a specific HA program. Early in 2006, James A. Russo created a new project on Sourceforge, called ElkM1::Control, providing a standalone API to the M1. Developed in Perl, an interpreted language, ElkM1::Control provides most of the capabilities described in Elk's "ASCII Protocol" document. Its source code is freely available to everyone and, by virtue of Perl, can be used on Windows or Linux PCs. Unfortunately, only one version (0.02) was ever posted but it was amply documented, well-designed, and included commented code. What can ElkM1::Control do for me? ElkM1::Control is a Perl-based API to the ELK M1 and is a natural complement to MisterHouse (also written in Perl). However, it can be used to create useful applications without MisterHouse or any other HA program. For example, you can write standalone Perl scripts to:
CODE use ElkM1::Control; my $elk = ElkM1::Control->new(host => '192.168.0.251', port => 2101); $elk->armAway(code => 1234); $elk->disconnect(); It is easy to see what this command does: $elk->disarm(code => 1234); Here are the commands to turn off output 9, pause for ten seconds, and then turn on output 10 for ten minutes (600 seconds): $elk->controlOutputOff(output => 9); sleep 10; $elk->controlOutputOn(output => 10, timeout => 600); Here's how to get, and print, the temperature recorded by the second keypad: $elk->requestTemperature(group => 1, device => 2); my $msg = $elk->readMessage; print "Temperature is ".$msg->getTemperature" if (ref($msg) eq 'ElkM1::Control::Message::TemperatureReply'); Here are the commands to activate a task and turn on device C5: $elk->activateTask(task => 1); $elk->turnOnPLCDevice(house => 'C', unit => 5); What do I need to use it? You will need the following hardware:
You will need the following software:
In order to simplify your life, my installation instructions have cut a few corners. James Russo designed ElkM1::Control to support encrypted communications, using Secure Socket Layers (SSL), via port 2601. However, this capability is lost if you follow my installation instructions. Some Perl modules, such as ElkM1::Control, can be installed by simply copying them to the \perl\site\lib folder. However, other modules must first be "built" using tools that are not commonly found on a typical Windows PC (i.e. C compiler, C libraries, nmake utility, etc). Proper installation of the IO::Socket::SSL module is a complicated affair because it depends on other modules that must be compiled. To avoid this headache, I cheated by creating a version of IO::Socket::SSL that is simply a copy of an existing module: IO::Socket::INET. This trick serves to satisfy the Perl interpreter, lets us talk to the M1 on an unencrypted port (2101), but eliminates the ability to successfully communicate via an encrypted port. If you absolutely require encrypted communications, see the following article: "How to Add Support for Encrypted Communications" (posted below). How do I use it? Copy example #1 into your favourite text editor. CODE # Example 1: Say the current time use ElkM1::Control; my $elk = ElkM1::Control->new(host => '192.168.0.251', port => 2101); $elk->speakPhrase(phrase => 238); $elk->disconnect();
cd desktop The M1 should say the current time. If you see "unable to connect", the M1's port 2101 may be closed or perhaps there's a network connectivity problem. If Windows does not know how to execute the file it means the ".pl" extension is not associated with ActiveState's Perl interpreter. A quick solution to this problem is to execute the file like so: perl saytime.pl Copy example #2 into a text editor, revise the IP address, and save it as readmsg.pl. CODE # Example 2: Display all M1 messages use ElkM1::Control; my $elk = ElkM1::Control->new(host => '192.168.0.251', port => 2101); while (1) { # Loop forever while (my $msg = $elk->readMessage) { # Read the M1's messages print $msg->toString; # Print the messages } } Run readmsg.pl at the command prompt. Nothing may be displayed for awhile unless you create some activity (i.e. violate a zone) or simply wait for the next Ethernet Module Test message (sent every 30 seconds). Have fun! This post has been edited by BraveSirRobbin: Dec 13 2007, 09:58 AM
Attached File(s)
|
|
|
|
Nov 23 2007, 12:32 PM
Post
#2
|
|
|
Cocoonut ![]() ![]() ![]() ![]() Group: Registered Posts: 1439 Joined: 01.09.06 From: Montreal, QC Member No.: 1259 |
How to add support for encrypted communications
ElkM1::Control is a useful addition to anyone's Home Automation bag-of-tricks. In order to expose ElkM1::Control to a wider audience, my installation instructions maintained simplicity by sacrificing functionality. I eliminated support for encrypted communciations because it takes some effort to install the proper Perl modules and OpenSSL on a Windows PC. However, I recognize that some people won't use the "dumbed-down" version of ElkM1::Control because they must have encrypted communications. Background ElkM1::Control relies on a set of Perl modules, and OpenSSL, in order to communicate via an encrypted port. The following instructions explain how to install the required modules, and OpenSSL, on a Windows PC. ActiveState's Perl interpreter (V5.8.8) includes a utility called "ppm-shell" and it will be used to install two Perl modules and OpenSSL. The University of Winnipeg maintains a repository of Perl modules and a Windows-specific version of OpenSSL. Use of their repository simplifies the installation process. Prerequisites
NOTE: In informal testing, encrypted communications take more time to execute than when they are sent "in the clear" (i.e. unencrypted). If the operating environment is reasonably secure, you may want to use unencrypted communications for better performance. However, if you plan to send commands to the M1 via the Internet, and you're not using a Virtual Private Network (VPN) or stunnel, then you ought to encrypt the communications. This post has been edited by 123: Nov 29 2007, 01:17 PM
Attached File(s)
|
|
|
|
Dec 12 2007, 03:38 AM
Post
#3
|
|
|
Cocooner ![]() ![]() Group: Registered Posts: 18 Joined: 12.06.07 From: Australia Member No.: 3782 |
This would be great to read as I just got my m1 up and running with an ethernet connection, I'm using a slug to serve up pages to control my m1g.
Unfortunately I am unable to download your attachments and have sent a pm to the admin but am yet to receive a reply. I am in the process of writing a perl script to detect when a bluetooth device (phone) comes into range to automatically disable the alarm and will post if once it is working and I am able to download your attachments. |
|
|
|
Dec 12 2007, 08:26 AM
Post
#4
|
|
|
Cocoonut ![]() ![]() ![]() ![]() Group: Manufacturers Posts: 2253 Joined: 05.04.05 From: Lenoir, NC USA Member No.: 672 |
123,
Great write up! Good information. Edited: oops, can't read! This post has been edited by Spanky: Dec 13 2007, 11:31 PM |
|
|
|
Dec 12 2007, 09:17 AM
Post
#5
|
|
|
Cocoonut ![]() ![]() ![]() ![]() Group: Registered Posts: 1439 Joined: 01.09.06 From: Montreal, QC Member No.: 1259 |
... Unfortunately I am unable to download your attachments and have sent a pm to the admin but am yet to receive a reply. ... Hmm, I was wondering why my article received over 250 views but only 1 attachment-download! BSR, I get a "permission-denied" when attempting to download the attachments. Maybe something broke when the article was transferred from the Home Security forum to the How-To forum. Let me know if you need me to re-post the attachments. This post has been edited by 123: Dec 12 2007, 09:24 AM |
|
|
|
Dec 13 2007, 07:47 AM
Post
#6
|
|
|
Cocooner ![]() ![]() Group: Registered Posts: 18 Joined: 12.06.07 From: Australia Member No.: 3782 |
|
|
|
|
Dec 13 2007, 09:15 AM
Post
#7
|
|
|
Cocoonut ![]() ![]() ![]() ![]() Group: Registered Posts: 1439 Joined: 01.09.06 From: Montreal, QC Member No.: 1259 |
cheekymonkey, Great write up! Good information. not me mate, it was 123. Your alias is highly apropos! Your first post on Cocoontech gets you credit for this How To. Well done, you cheeky monkey! Welcome to Cocoontech! BTW, your plan w/bluetooth is intriguing and I look forward to hearing more about it. This post has been edited by 123: Dec 13 2007, 09:18 AM |
|
|
|
Dec 15 2007, 10:31 AM
Post
#8
|
|
|
Cocooner ![]() ![]() Group: Registered Posts: 41 Joined: 12.16.04 From: NJ, USA Member No.: 373 |
BTW, I've managed to get the serial port and Linux working with this module (using open and stty to setup the port). I wrote a class to override some of the Ethernet module's functions. I'm still having trouble getting the Device::SerialPort module working (so it's portable between most OSs that run perl). For some reason I can't read from the tied FH (using the examples from Device::SerialPort).
|
|
|
|
Dec 16 2007, 09:15 AM
Post
#9
|
|
|
Advanced Cocooner ![]() Group: -= Silver Supporter =- Posts: 344 Joined: 12.29.06 From: Washington, DC Metro Member No.: 2555 |
BTW, I've managed to get the serial port and Linux working with this module (using open and stty to setup the port). I wrote a class to override some of the Ethernet module's functions. I'm still having trouble getting the Device::SerialPort module working (so it's portable between most OSs that run perl). For some reason I can't read from the tied FH (using the examples from Device::SerialPort). Interesting... when you get this working, can you post a how-to and some code? |
|
|
|
Dec 16 2007, 01:56 PM
Post
#10
|
|
|
Cocooner ![]() ![]() Group: Registered Posts: 41 Joined: 12.16.04 From: NJ, USA Member No.: 373 |
BTW, I've managed to get the serial port and Linux working with this module (using open and stty to setup the port). I wrote a class to override some of the Ethernet module's functions. I'm still having trouble getting the Device::SerialPort module working (so it's portable between most OSs that run perl). For some reason I can't read from the tied FH (using the examples from Device::SerialPort). Interesting... when you get this working, can you post a how-to and some code? Sure no problem, I'm going to build another module for use with Misterhouse (MH). MH doesn't need to open a serial port via the new method (MH opens it another way) so I'll need to inherit the already opened Device::SerialPort IO handle from MH(Device::SerialPort works with MH just fine). Being able to override and inherit has made the coding much easier. I hope to have the web page integrated into Misterhouse by the end of the month (working module, user code and web page). I'll then post the information to Misterhouse Elk M1 Wiki page and my Elk M1 page along with how to use the module without MH. Nothing is there yet but I hope to have something posted there very soon. I'll announce on this thread first. I'd like to thank Spanky who made the eval kit available to me and . |
|
|
|
Dec 19 2007, 11:26 AM
Post
#11
|
|
|
Cocoonut ![]() ![]() ![]() ![]() Group: Registered Posts: 1439 Joined: 01.09.06 From: Montreal, QC Member No.: 1259 |
FYI
For whatever reason, the documents I posted in my original message cannot be downloaded. In addition, I cannot re-post the documents in a reply. I've informed the forum's administrator and hopefully this will be resolved shortly. |
|
|
|
Dec 23 2007, 09:49 AM
Post
#12
|
|
|
CocoonTech Admin ![]() ![]() ![]() ![]() Group: Admin Posts: 8045 Joined: 12.22.03 From: New York Member No.: 1 |
Try now guys, looks like a new security feature was added, but not activated.
ps: very nice work! |
|
|
|
Dec 23 2007, 05:26 PM
Post
#13
|
|
|
Cocooner ![]() ![]() Group: Registered Posts: 18 Joined: 12.06.07 From: Australia Member No.: 3782 |
|
|
|
|
Dec 24 2007, 02:44 AM
Post
#14
|
|
|
Cocooner ![]() ![]() Group: Registered Posts: 18 Joined: 12.06.07 From: Australia Member No.: 3782 |
Here is my XMAS present to you guys, feel free to enhance, correct my coding practices, hopefully someone finds it usefull.
My code was tested on a Linksys NSLU2 running debian slug OS and using an ASUS WL-BTD201M dongle One important thing to note is this script doesn't connect(pair) with your device, so the required information could be sniffed and smart people could impersonate your device. I do have a shell script that does pairing, has a threshold (rough distance) checking but I haven't yet been able to successfully port that part into perl, I'm hoping next year will bring success. As I cant quite work out how to add an attachment I'll post my code. To find your device/phone's mac address and name follow this link . Note you must have your phone set to discoverable during these steps otherwise you will get errors and no information. Once you gathered all the required info change your device to hidden, my script still works fine with hidden devices. The script is designed to be fired off as an init script and will then run continuously, though as I don't have a housekeeping script checking if it is running I have enabled chiming on the elk so I will get a reminder if the script has failed and I need to punch in the code. If you have multiple devices a separate script will need to be written for each device. I have tested 2 running at once and they didnt encounter any problems, the only one I did have was if the status window was up on the RP software. Strangely I was unable to get my elk to speak so I didn't include a greeting CODE #!/usr/bin/perl -w
$stateDir = "/tmp" ; $devicename = "phone_name" ; $deviceMAC = "xx:xx:xx:xx:xx:xx" ; $phoneLeftHome = "$stateDir/$devicename.home" ; $hcitool = "/usr/bin/hcitool" ; $elkHost = "xxx.xxx.xxx.xxx" ; # elk $elkPort = "2101" ; $useSSL = "0" ; $date = `date` ; $sleep = "10" ; $exitSleep = "600" ; # set to 30 for testing $disarmCode = "xxxxxx" ; $DEBUG = 0 ; use ElkM1::Control; while ( 1 ) { print "checking phone $devicename\n" if $DEBUG ; $phone_in_range = &inRange ; if ($phone_in_range) { print "phone in range\n" if $DEBUG ; print "now time to check if alarmed\n" if $DEBUG ; my @status = &checkELK ; my $alarm_armed = $status[0] ; my $ExitDelay = $status[1] ; if ($ExitDelay ) { print "waiting for phone to get out of range\n" if $DEBUG ; # wait for the phone to get out of range sleep($exitSleep) ; $phone_in_range = &inRange ; if ($phone_in_range) { print "2nd waiting for phone to get out of range\n" if $DEBUG ; sleep($exitSleep) ; # set to 600 $phone_in_range = &inRange ; if ($phone_in_range) { print "phone left home\n" ; # must be left home better set a flag so we wont disarm alarm open phoneHOME, ">$phoneLeftHome" ; print phoneHOME "$date" ; close phoneHOME ; } else { print "phone now out of range\n" if $DEBUG ; } sleep($sleep) ; # next ; } } else { if ($alarm_armed) { print "alarm ARMED\n" if $DEBUG ; if ( -e $phoneLeftHome ) { print "phone is left home so ignoring it\n" if $DEBUG ; sleep($sleep) ; next ; } # panel is armed and phone hasn't been left home so lets disable it &disarm ; } else { print "alarm not armed\n" if $DEBUG ; if (-e $phoneLeftHome ) { # people are home so lets delete the flag unlink "$phoneLeftHome" ; } } } # sleep here as a successfull connect doesnt take that long # but an unsucessfull attempt has already taken long enough sleep($sleep) ; } } sub disarm { print "disable alarm, using code $disarmCode\n"; my $elk = ElkM1::Control->new( 'host' => $elkHost, 'port' => $elkPort, 'use_ssl' => $useSSL, 'debug' => 0 ); $elk->disarm( code => $disarmCode ) ; $elk->disconnect() ; # check alarm has been disabled as we dont want to set it off while ( &checkELK(1) ) { print " message still trying to disable alarm\n"; my $elk = ElkM1::Control->new( 'host' => $elkHost, 'port' => $elkPort, 'use_ssl' => $useSSL, 'debug' => 0 ); $elk->disarm( code => $disarmCode ) ; $elk->disconnect() ; sleep (2) ; } } sub checkELK { my $alarmArmed = "0" ; my $ExitDelay = "0" ; my $alarmCheckOnly = 0 ; if ( $_[0] ) { $alarmCheckOnly = 1 ; print "alarmCheckOnly\n" if $DEBUG ; } my $elk = ElkM1::Control->new( 'host' => $elkHost, 'port' => $elkPort, 'use_ssl' => $useSSL, 'debug' => 0 ) or die ; my $msg = $elk->requestArmingStatus() ; my @keys = keys %$msg ; my ($AreaArmingStatus,$AreaReady2Arm,$AreaAlarm) = $$msg{'message'} =~ /^1EAS(\w{8})(\w{8})(\w{8})\d{2}\w {2}$/ ; print "AreaArmingStatus $AreaArmingStatus\n" if $DEBUG ; print "AreaReady2Arm $AreaReady2Arm\n" if $DEBUG ; print "AreaAlarm $AreaAlarm\n" if $DEBUG ; if ( $AreaArmingStatus =~ /1/) { $alarmArmed = "1" ; } if ( $AreaReady2Arm =~ /3/) { $ExitDelay = "1" ; print "ExitDelay Active\n" if $DEBUG ; } $elk->disconnect() ; if ( $alarmCheckOnly ) { print "returning alarmArmed $alarmArmed\n" if $DEBUG ; return($alarmArmed) ; } else { return($alarmArmed , $ExitDelay) ; print "returning alarmArmed:$alarmArmed ExitDelay:$ExitDelay \n" if $DEBUG ; } } sub inRange { # on the nslu2 this takes about 20 sec to fail # and about 3-5 sec to pass if the device is in range print "checking if phone in range\n" if $DEBUG ; `$hcitool name $deviceMAC > /tmp/$devicename` ; if ( -e "/tmp/$devicename" ) { open NAME, "/tmp/$devicename" ; for (<NAME>) { if ($_ = $devicename) { # a simple check that the mac address # returns the correct name, this test may be # not actually achieve any increase in security # but what the heck print "$devicename IN RANGE\n" if $DEBUG ; unlink "/tmp/$devicename" ; return(1) ; } } unlink "/tmp/$devicename" ; return(0) ; } else { print "$devicename OUT OF RANGE\n" if $DEBUG ; return(0) ; } } |
|
|
|
Dec 24 2007, 09:37 AM
Post
#15
|
|
|
Cocoonut ![]() ![]() ![]() ![]() Group: Registered Posts: 1439 Joined: 01.09.06 From: Montreal, QC Member No.: 1259 |
A very interesting application of the M1 with a bluetooth-equipped phone!
I don't have the requisite phone to test this but I noticed something in the code you may want to alter. You are instantiating an ElkM1::Control object within "while" loops (i.e. $elk = ElkM1::Control->new) . This means you are opening a new connection to the M1 each time the loop executes and that's unnecessary. Open a single connection at the beginning of the program (i.e. before all of the loops) and close it at the end of the program. While the connection is open, you can send commands and listen for messages. This post has been edited by 123: Dec 24 2007, 09:51 AM |
|
|
|
![]() ![]() |
|
Lo-Fi Version | Time is now: 20th November 2009 - 05:23 PM |
|
|