HoustonFirefox
Active Member
Hi all,
I'm in the process of installing some solar panels to power my Elk M1 Gold as well as powering attic fans, mobile device charging stations, etc. With that in mind I thought it would be a good idea to install two additional temperature sensors to see if the attic fans were doing their job. I installed one of the sensors in an inconspicuous place under an eave to measure the outside temp as well as another at a high point in my attic.
remember that the whole point of this is to cut down on my sumer A/C bills.
My question was... how to log the data that the Elk has access to?
I have a spare Linux server that I run my web server on so I figured that would work fine since it's on 24/7 and only consumes 14 watts of power. In addition, it has a 1TB hard drive in it that sits idle most of the time. It is a TS-109 Pro server and I HIGHLY recommend it (check it out at www.qnap.com).
Anyhoo, I'm learning PHP and thought this would be a good exercise so I wrote a small PHP script that opens a connection with the Elk M1 Gold over it's non-secure port, grabs the Elk date and time as well as all of the temperatures on the box. Again, I only have three (so far). These are the Keypad (house) temp, the Outside Temp and the Attic Temp.
So, without further ado, here is the script:
[codebox]<?php // Begin TLOG.PHP
// This script logs onto your Elk M1, Grabs the date/time/temp and writes it to a file specified in $logfilename
FUNCTION fnStripCRLF($data)
{
while ((substr($data,-1) == "\n") or (substr($data,-1) == "\r"))
{
$data = substr($data,0,strlen($data)-1); // strip offending character
}
return $data;
}
$ElkIP = "192.168.1.61"; // CHANGE THIS TO POINT TO YOUR ELK ETHERNET EXPANDER
$ElkNSPort = 2163; // CHANGE THIS TO POINT TO YOUR ELK ETHERNET EXPANDER NON-SECURE PORT
$logfilename = "tlog.log"; // CHANGE THIS IF NEEDED
$fp = fsockopen($ElkIP, $ElkNSPort, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$fmtstr = "";
$out = "06rr0056\r\n"; // get real time clock data
fwrite($fp, $out); // send request for clock
$elkclkdata = fgets($fp, 255); // get the response
// echo "Clock Data: " . $elkclkdata . "<br>";
$elkclkdata = fnStripCRLF($elkclkdata); // strip CR/LF
$fmtstr = substr($elkclkdata, 15,2) . "-" . // Year
substr($elkclkdata, 13,2) . "-" . // Month
substr($elkclkdata, 11,2) . " " . // Day
substr($elkclkdata, 10,1) . " " . // DOW (1=Sunday)
substr($elkclkdata, 8,2) . ":" . // Hour
substr($elkclkdata, 6,2) . ":" . // Minute
substr($elkclkdata, 4,2) . " " . // Second
substr($elkclkdata, 18,1); // DST? (0/1)
// echo "fClock Data: " . $fmtstr . "<br>"; // Uncomment to debug
$elkclkdata = $fmtstr;
$out = "06lw0057\r\n"; // get all temperatures
fwrite($fp, $out); // send request for temps
$elkdata = fgets($fp, 255); // get the response
// echo "Temp Data : " . $elkdata . "<br>"; // Uncomment to debug
$elkdata = substr($elkdata, 4, strlen($elkdata)); // strip header information
$elkdata = substr($elkdata, 0, strlen($elkdata)-4) . "\r\n"; // strip checksum
// echo "Temp Data : " . $elkdata . "<br>"; // Uncomment to debug
fclose($fp); // close the file
$fh = fopen($logfilename, "a+"); // open the log file
fwrite($fh, $elkclkdata . " " . $elkdata); // write the data
fclose($fh); // close the log file
echo $elkdata; // display the data if in interactive mode
}
?>[/codebox]
Once you run it, then it will write data to the file specified in the $logfilename variable. Make sure you change the IP and the port number to point to whatever you are using. I set up a cron (scheduled job) to fire off this script once every 5 minutes and the data can then be analyzed any way you want it.
Here is a sample of the output:
[codebox]08-06-12 5 18:09:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015814500000000
08-06-12 5 18:14:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015814600000000
08-06-12 5 18:19:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015814600000000
08-06-12 5 18:29:52 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015814500000000
08-06-12 5 18:34:52 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015714500000000
08-06-12 5 18:39:52 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015714400000000
08-06-12 5 18:44:52 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015614400000000
08-06-12 5 18:49:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015614400000000
08-06-12 5 18:54:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015514400000000
08-06-12 5 18:59:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015514400000000
08-06-12 5 19:14:52 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015414400000000[/codebox]
Note that the software I wrote to analyze the data automatically down-converts the temperatures from what the Elk provides. All Elk keypad temperatures need to have 40 subtracted from them while external temperature probes need to have 60 subtracted from them to arrive at the final temp. I think Elk did this since the M1 cannot store negative numbers and they wanted to be able to log below-zero temperatures.
Regardless, taking the last line as an example, you'll see that the temps are three digits long. The first temp (117) is the front door keypad temp. If you subtract 40, you'll get the temp (77 degrees F). This is followed by a bunch of zeros (in groups of 3) that correspond to missing temperature probes and then we finally arrive at the value 154 (attic temp, subtract 60 = 94 degrees) and then the outside temp shown by 144 (outside temp, subtract 60= 84 degrees).
* * * * *
Note that the code does not check the Checksum values to see if the data is valid, but I've yet to get a bad packet.
Spanky, check the code in the Elk M1 RS-232 Protocol Document for computing the checksum, I've spent days trying but I think it's wrong since I can never come up with a correct checksum by strictly following the directions in the document.
Again, I'm just learning PHP so the script isn't the prettiest in the world. I know a lot of people here don't/can't/won't buy HomeSeer or CQC for home automation and want to write their own so I figured this would be a nice thing to write about since I know there is a lot of interest.
I plan on writing an entire PHP class library to encapsulate all of the Elk functionality so you can roll your own website that talks with the Elk.
I'd be interested to see any examples that others may have.
Enjoy the code!
I'm in the process of installing some solar panels to power my Elk M1 Gold as well as powering attic fans, mobile device charging stations, etc. With that in mind I thought it would be a good idea to install two additional temperature sensors to see if the attic fans were doing their job. I installed one of the sensors in an inconspicuous place under an eave to measure the outside temp as well as another at a high point in my attic.
remember that the whole point of this is to cut down on my sumer A/C bills.
My question was... how to log the data that the Elk has access to?
I have a spare Linux server that I run my web server on so I figured that would work fine since it's on 24/7 and only consumes 14 watts of power. In addition, it has a 1TB hard drive in it that sits idle most of the time. It is a TS-109 Pro server and I HIGHLY recommend it (check it out at www.qnap.com).
Anyhoo, I'm learning PHP and thought this would be a good exercise so I wrote a small PHP script that opens a connection with the Elk M1 Gold over it's non-secure port, grabs the Elk date and time as well as all of the temperatures on the box. Again, I only have three (so far). These are the Keypad (house) temp, the Outside Temp and the Attic Temp.
So, without further ado, here is the script:
[codebox]<?php // Begin TLOG.PHP
// This script logs onto your Elk M1, Grabs the date/time/temp and writes it to a file specified in $logfilename
FUNCTION fnStripCRLF($data)
{
while ((substr($data,-1) == "\n") or (substr($data,-1) == "\r"))
{
$data = substr($data,0,strlen($data)-1); // strip offending character
}
return $data;
}
$ElkIP = "192.168.1.61"; // CHANGE THIS TO POINT TO YOUR ELK ETHERNET EXPANDER
$ElkNSPort = 2163; // CHANGE THIS TO POINT TO YOUR ELK ETHERNET EXPANDER NON-SECURE PORT
$logfilename = "tlog.log"; // CHANGE THIS IF NEEDED
$fp = fsockopen($ElkIP, $ElkNSPort, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$fmtstr = "";
$out = "06rr0056\r\n"; // get real time clock data
fwrite($fp, $out); // send request for clock
$elkclkdata = fgets($fp, 255); // get the response
// echo "Clock Data: " . $elkclkdata . "<br>";
$elkclkdata = fnStripCRLF($elkclkdata); // strip CR/LF
$fmtstr = substr($elkclkdata, 15,2) . "-" . // Year
substr($elkclkdata, 13,2) . "-" . // Month
substr($elkclkdata, 11,2) . " " . // Day
substr($elkclkdata, 10,1) . " " . // DOW (1=Sunday)
substr($elkclkdata, 8,2) . ":" . // Hour
substr($elkclkdata, 6,2) . ":" . // Minute
substr($elkclkdata, 4,2) . " " . // Second
substr($elkclkdata, 18,1); // DST? (0/1)
// echo "fClock Data: " . $fmtstr . "<br>"; // Uncomment to debug
$elkclkdata = $fmtstr;
$out = "06lw0057\r\n"; // get all temperatures
fwrite($fp, $out); // send request for temps
$elkdata = fgets($fp, 255); // get the response
// echo "Temp Data : " . $elkdata . "<br>"; // Uncomment to debug
$elkdata = substr($elkdata, 4, strlen($elkdata)); // strip header information
$elkdata = substr($elkdata, 0, strlen($elkdata)-4) . "\r\n"; // strip checksum
// echo "Temp Data : " . $elkdata . "<br>"; // Uncomment to debug
fclose($fp); // close the file
$fh = fopen($logfilename, "a+"); // open the log file
fwrite($fh, $elkclkdata . " " . $elkdata); // write the data
fclose($fh); // close the log file
echo $elkdata; // display the data if in interactive mode
}
?>[/codebox]
Once you run it, then it will write data to the file specified in the $logfilename variable. Make sure you change the IP and the port number to point to whatever you are using. I set up a cron (scheduled job) to fire off this script once every 5 minutes and the data can then be analyzed any way you want it.
Here is a sample of the output:
[codebox]08-06-12 5 18:09:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015814500000000
08-06-12 5 18:14:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015814600000000
08-06-12 5 18:19:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015814600000000
08-06-12 5 18:29:52 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015814500000000
08-06-12 5 18:34:52 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015714500000000
08-06-12 5 18:39:52 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015714400000000
08-06-12 5 18:44:52 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015614400000000
08-06-12 5 18:49:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015614400000000
08-06-12 5 18:54:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015514400000000
08-06-12 5 18:59:53 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015514400000000
08-06-12 5 19:14:52 0 11700000000000000000000000000000000000000000000000000000000000000000000000000000
000015414400000000[/codebox]
Note that the software I wrote to analyze the data automatically down-converts the temperatures from what the Elk provides. All Elk keypad temperatures need to have 40 subtracted from them while external temperature probes need to have 60 subtracted from them to arrive at the final temp. I think Elk did this since the M1 cannot store negative numbers and they wanted to be able to log below-zero temperatures.
Regardless, taking the last line as an example, you'll see that the temps are three digits long. The first temp (117) is the front door keypad temp. If you subtract 40, you'll get the temp (77 degrees F). This is followed by a bunch of zeros (in groups of 3) that correspond to missing temperature probes and then we finally arrive at the value 154 (attic temp, subtract 60 = 94 degrees) and then the outside temp shown by 144 (outside temp, subtract 60= 84 degrees).
* * * * *
Note that the code does not check the Checksum values to see if the data is valid, but I've yet to get a bad packet.
Spanky, check the code in the Elk M1 RS-232 Protocol Document for computing the checksum, I've spent days trying but I think it's wrong since I can never come up with a correct checksum by strictly following the directions in the document.
Again, I'm just learning PHP so the script isn't the prettiest in the world. I know a lot of people here don't/can't/won't buy HomeSeer or CQC for home automation and want to write their own so I figured this would be a nice thing to write about since I know there is a lot of interest.
I plan on writing an entire PHP class library to encapsulate all of the Elk functionality so you can roll your own website that talks with the Elk.
I'd be interested to see any examples that others may have.
Enjoy the code!