[How-To] Control an Elk M1 via External Perl Scripting

CentOS 5.2, ELK-M1G

Code:
cd /opt
wget http://voxel.dl.sourceforge.net/sourceforge/elkm1control/ElkM1-Control-0.02.tar.gz
tar xzvf ElkM1-Control-0.02.tar.gz
cd ElkM1-Control-0.02
less README
perl Makefile.PL
make
make test
make install
cpan
> install Net::SSLeay
> install IO::Socket::SSL
quit

Code:
#!/usr/bin/perl

use ElkM1::Control;

   my $elkhost = '192.168.1.5';
   my $elkport = '2601'; #2101
   my $elkssl = 1;		  #0
   my $elkdebug = 0;

   my $units = "F";
   my @zonelist = ('one','two','three','four');

   my $elk = ElkM1::Control->new('host' => $elkhost, 'port' => $elkport, 'use_ssl' => $elkssl, 'debug' => $elkdebug);

   my $msg;

   while(1) {
	  $msg = $elk->readMessage();

	  if(!defined($msg)) {
		 sleep .5;
	  } else {
		 switch(ref($msg)) {
			case 'ElkM1::Control::Message::ZoneChangeUpdateReport' {
			   $zonenumber = $msg->getZone;
			   $zoneloc = $zonelist[$zonenumber+1];
			   $zonestate = $msg->getState;
			   print $zoneloc." zone (".$zonenumber.") is now ".$zonestate."\n";
			}
			case 'ElkM1::Control::Message::TemperatureReply' {
			   $groupname = $msg->getGroupName;
			   $groupnumber = $msg->getGroup;
			   $groupdevice = $msg->getDevice;
			   $temperature = $msg->getTemperature;
			   print $groupname." ".$groupnumber." ".$groupdevice.": ".$temperature.$units."\n";
			}
			else {
			   print "Message not known.  ".$msg->toString."  ".ref($msg)."\n";
			}
		 }
	  }

   }

   @zonelist;

   $elk->disconnect;

Sources
  • http://www.cocoontech.com/index.php?showtopic=8920
  • http://search.cpan.org/dist/IO-Socket-SSL/SSL.pm
  • http://www.charmedquark.com/vb_forum/showthread.php?t=6516
  • http://forum.homesecuritystore.com/index.php?topic=7014.msg34304
  • http://www.linuxha.com/ElkM1/index.html
 
Hi, I just try to turn on my Z-wave wall switch with the perl module.

I have problem using the turnOnPLCDevice function, I receive a error message as the following
"Can't use string ("index") as a HASH ref while "strict refs" in use at E:/Perl/site/lib/ElkM1/Control.pm line 140."

However I am able to turn it off with the turnOffPLCDevice function.

Here's my code.

Code:
	use ElkM1::Control;
		my $elk = ElkM1::Control->new(host => '192.168.1.190', port => 2101);
		$elk->turnOnPLCDevice(index => 98);
		$elk->disconnect();

any ideas? Ok. I got it.

It seems like a bug in the Control.pm file. I replace the checkParam() code from the turnOffPLCDevice, and it's working perfectly now. I don't know how to upload the new Control.pm file. Hopefully OP can update it.
 
... It seems like a bug in the Control.pm file. I replace the checkParam() code from the turnOffPLCDevice, and it's working perfectly now. ...

In "turnOnPLCDevice", the "index" parameter is passed to checkParam with an explicit restriction (see "allow"). However, the other parameters refer to restrictions set in variables called $HOUSE_PARAM (defined on line 101 in control.pm) and $UNIT_PARAM (on line 105) and passed in via "Rules" to checkParam.
Code:
sub turnOnPLCDevice {
...
	$self->_checkParam(
		{
			'house' => { rules => $HOUSE_PARAM, var => \$house },
			'unit'  => { rules => $UNIT_PARAM,  var => \$unit },
		},
		'index' => {
			allow => sub { ( $_[0] >= 1 and $_[0] <= 256 ) },
			var		 => \$index,
			description => 'an device index from 1..256'
		},
		\%args
	);

...}

In "turnOffPLCDevice", all parameters are passed with explicit restrictions via "allow".
Code:
sub turnOffPLCDevice {
...
	$self->_checkParam(
		{
			'house' => {
				allow => sub { ( ord( $_[0] ) >= 65 and ord( $_[0] ) <= 77 ) },
				var		 => \$house,
				description => 'an valid house code A..P'
			},
			'unit' => {
				allow => sub { ( $_[0] >= 1 and $_[0] <= 16 ) },
				var		 => \$unit,
				description => 'an unit code from 1..16'
			},
			'index' => {
				allow => sub { ( $_[0] >= 1 and $_[0] <= 256 ) },
				var		 => \$index,
				description => 'an device index from 1..256'
			}
		},
		\%args
	);

I don't know why the author chose to write them differently .. perhaps it was simply an oversight.
 
Thanks for the explanation. 123

I also have problem using requestPLCStatus(). I am getting the return type as ElkM1::Control::Message, but it is supposed to be ElkM1::Control::Message::pLCStatusReply.
 
Thanks for the explanation. 123

I also have problem using requestPLCStatus(). I am getting the return type as ElkM1::Control::Message, but it is supposed to be ElkM1::Control::Message::pLCStatusReply.

Im working on a perl daemon to sit between my ELK M1 and a Philips Pronto 9400 remote so I can control the lights from my main remote. Im currently stuck on getting current status as well. If you have any insight into requestPCLStatus() let me know.

some simple code
----------
my $msg = $elk->requestPLCStatus(bank=>0);
print $msg;
----------

prints "ElkM1::Control::Message=HASH(0x180ca30)"

I havent figured out how to decode that into something I can use yet.
 
I may be wrong but I believe the author overlooked to include a line of code in MessageFactory.pm.

If you look in control.pm, somewhere around line 1115 is where requestPLCStatus is defined. There's not much to it; the last line is what's important because it calls readMessage('PS'). "PS" is an abbreviation for PLC Status.

Go to line 1539 to find where readMessage is defined. I don't understand all of the Perl code here but line 1558 is the one does some heavy-lifting because it uses MessageFactory to instantiate a new object. It passes along the data it received, namely 'PS'.

So our exploration takes us to MessageFactory.pm. If we look at lines 20-35 we notice it is nothing more than a selector. If it receives an 'AS' it will call the ArmingStatusReport and if we check in the Message folder we find a corresponding ArmingStatusReport.pm file. If it gets 'PC' it will call PLCChangeUpdate and there is a PLCChangeUpdate.pm. The problem is that there is no entry for 'PS' to support PLCStatusReply. Fortunately, there is a PLCStatusReply.pm file so all we need to do is add the following line to MessageFactory.pm:
'PS' => 'ElkM1::Control::Message::pLCStatusReply',

You can put it anywhere between lines 20-35.

I haven't tested it but you'll let me know if this does/doesn't solve the problem. :p
 
After adding the PS line to MessageFactory.pm, I started getting errors at line 63 of MessageFactory. in sub instantiate it works out the path to the correct message type and includes it, but im getting "Compilation failed in require at /Library/Perl/5.8.6/ElkM1/Control/MessageFactory.pm line 63, <GEN0> line 1."

Im probably wrong here, but i figured it meant that Perl couldnt find the file to include it. To make sure it was pointing in the right place I added "print $module_file" and commented out anything that was making the script fail and recieved "ElkM1/Control/Message/PLCStatusReply.pm" which is indeed where the file resides. I double and tripple checked the spelling to make sure that I didnt have a typo, but it all looks good. Im afraid Im stumped again.

I may be wrong but I believe the author overlooked to include a line of code in MessageFactory.pm.

If you look in control.pm, somewhere around line 1115 is where requestPLCStatus is defined. There's not much to it; the last line is what's important because it calls readMessage('PS'). "PS" is an abbreviation for PLC Status.

Go to line 1539 to find where readMessage is defined. I don't understand all of the Perl code here but line 1558 is the one does some heavy-lifting because it uses MessageFactory to instantiate a new object. It passes along the data it received, namely 'PS'.

So our exploration takes us to MessageFactory.pm. If we look at lines 20-35 we notice it is nothing more than a selector. If it receives an 'AS' it will call the ArmingStatusReport and if we check in the Message folder we find a corresponding ArmingStatusReport.pm file. If it gets 'PC' it will call PLCChangeUpdate and there is a PLCChangeUpdate.pm. The problem is that there is no entry for 'PS' to support PLCStatusReply. Fortunately, there is a PLCStatusReply.pm file so all we need to do is add the following line to MessageFactory.pm:
'PS' => 'ElkM1::Control::Message::pLCStatusReply',

You can put it anywhere between lines 20-35.

I haven't tested it but you'll let me know if this does/doesn't solve the problem. :blink:
 
I wish I could be of more help but, unfortunately, I no longer have access to a suitable test environment (Perl/ELK M1) so I'm unable to experiment with possible solutions. Perhaps someone else can step in and resolve this problem.

May I suggest you try contacting the author, James Russo (email address is at the bottom of each code file). If he no longer supports ELKM1::Control, let me know, and I'll recreate the required test environment (however, I can't promise a time frame).

If you are not operating in a Linux environment, there are several free solutions to control an M1 from a Windows PC. Here on Cocoontech you'll find BKLLC's M1sender.exe, Dan's my.ELK (available in VBScript and VB.NET), Grayson Peddie's I-Elk (C#.NET), and my ELKM1 driver for Premise.
 
I sent an email to James about "reviving" development of ElkM1::Control and he gave me permission to proceed. If there is an interest in maintaining and advancing this module, I volunteer to take over responsibility. One caveat, I'm not a perl expert so I will need help from the more perl-enabled.

The first step would be to setup a new repository, probably on GitHub (sorry, I dumped cvs ans svn a year ago). GitHub makes it easy for anyone to branch the project, make changes and submit them back for inclusion.

I have my elk m1g connected to my ubuntu desktop, so I can test on a live system fairly easily. Have XP/2K (activestate perl installed on both) and OS X as well.

Anyone interested?
 
Well, looks like no one else is interested, but I am. So I'm marching forward with a bug fix and new feature.

First, I have moved the ElkM1--Control repository to GitHub. The main reason is that I chucked svn about a year ago plus I really like the 'social' aspects of github. For those of you who would like to contribute, it makes forking and merging so simple. And you don't have to have git installed to just download it.

So, here it is: ElkM1--Control Repository. If you have git-core installed, I recommend cloning. If you don't, click the download button to get a zipped copy.

To start things off, there is a new version, 0.03 which has the following changes:
  1. fixed BypassedZoneState -> BypassedZoneStateReply inconsistencies
  2. added EthernetModuleTest message class (just creates a class to hold the messages, doesn't decode the date/time info)

I will probably change the version numbers to the more common major.minor.revision system.

Currently, I have the module running with a script that logs pretty much everything that comes out of of the M1 into a MySQL db. In addition, I wrote a ruby on rails application that presents graphs and stats on the system. Now, I know how many times the kids go in/out the garage door, and if they left it open and for how long. They don't like M1. I'll post the scripts in a separate message.

Anyone have anything else they would like to see?
 
...added EthernetModuleTest message class (just creates a class to hold the messages, doesn't decode the date/time info)

Threadhead,

That's great news! Thank you for taking the time to breathe new life back into ElkM1::Control.

I had written a complete EthernetModuleTest.pm module in the fall of 2007 and shared it with a CT member who planned to release a MisterHouse version of ELKM1:Control. It parses and displays the date/time data. I'd appreciate it if you could incorporate it (attached file) into the latest build. There's a minor bug fix posted on this thread that should also make its way into the latest build (concerns the lack of a message association for "PS" commands).

Once again, thanks for taking up the torch and best of luck!
 

Attachments

  • EthernetModuleTest.zip
    1.6 KB · Views: 88
I had written a complete EthernetModuleTest.pm module in the fall of 2007 and shared it with a CT member who planned to release a MisterHouse version of ELKM1:Control. It parses and displays the date/time data. I'd appreciate it if you could incorporate it (attached file) into the latest build. There's a minor bug fix posted on this thread that should also make its way into the latest build (concerns the lack of a message association for "PS" commands).

Got it. Will do. Thanks!

I also found the "PS" bug and have it fixed on my local copy.

Anything else you remember?
 
Yippie, another update and bug fixes. Check out the latest at the GitHub repository.

I changed the version numbering system to the more common major.minor.release notation. So that puts us at version 0.1.0.

Does anyone mind if I copy some of the example code into the wiki on GitHub?

Bugs? Features? Anyone?
 
Yippie, another update and bug fixes. Check out the latest at the GitHub repository.

I changed the version numbering system to the more common major.minor.release notation. So that puts us at version 0.1.0.

Does anyone mind if I copy some of the example code into the wiki on GitHub?

Bugs? Features? Anyone?


Honored to see my work used! Hopefully the design proves robust. :)

Thanks!

-jr
 
Back
Top