Reading meter using PHP

For more advanced meter data users. Learn from others and ask questions about how to read meters, how to use the EKM Push Data, and how to display the meter data in useful ways.
Post Reply
rcarsey
Posts: 3
Joined: Thu Feb 16, 2012 8:53 am

Reading meter using PHP

Post by rcarsey »

Since I do a lot of PHP programming, it seemed only natural to use PHP to query the meter for data.

Below is a snipit of code which you can use to get the data from the meter... of course your PHP must have the extensions for snmp and tcp -- which i think come standard.

Code: Select all

<?php

function get_meter_data($meter_number, $remote_address, $remote_port) {
	//$meter_number is the meters serial number. leading 0s not required.
	//$remote_address is the IP address of the ethernet-RS485 converter
	//$remote_port is the TCP port number the converter is listening to (50000 in my case)

	//We do not check the checksum - I'm lazy.  Probably should. Running for 8 months, querying
	//once per minute..I've encountered one or two bad results from the meter.


	/*  Connect and get response */
	// fix up the meter number with the correct amount of leading zeros
	$meter_number = str_pad($meter_number, 12, "0", STR_PAD_LEFT);
	//create a new socket and make sure it worked
	$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
	if ($socket === false)
		echo "socket_create() failed: reason: ".socket_strerror(socket_last_error())."\n";
	// connect to the meter and check to make sure we connected
	$res = socket_connect($socket, $remote_address, $remote_port);
	if ($res === false)
        {
                echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
                echo "Aborting";
                exit;
        }

	//send query string to the meter.  e.g.  /?000000000123!  then a CRLF
	socket_write($socket, "/?" . $meter_number . "!\r\n");
	//Receive a response of 255 bytes.  Wait till we have all of them!
	$res = socket_recv($socket, $response, 255, MSG_WAITALL);
	if ($res === false)
        	echo "socket_recv() failed; reason: " . socket_strerror(socket_last_error($socket)) . "\n";

	// no idea what this is about. EKM Meter software sends it, so we will too. Then close the connection.
	$message = "\x0a\x03\x32\x3d";
	socket_write($socket, $message);
	socket_close($socket);

	// Now the fun stuff.  parsing through the 255 byte response
	$meter_number = substr($response,4,12);
	$meter_model = substr($response,1,2); //non-ASCII
	$meter_firmware = substr($response,3,1); //non-ASCII
	$KWh_total = substr($response, 16, 8) / 10;
	$L1_KWh = substr($response, 24, 8) / 10;
	$L2_KWh = substr($response, 32, 8) / 10;
	$L3_KWh = substr($response, 40, 8) / 10;
	$L4_KWh = substr($response, 48, 8) / 10;
	$ReverseKWh_total = substr($response, 56, 8) / 10;
	$L1_ReverseKWh = substr($response, 64, 8) / 10;
	$L2_ReverseKWh = substr($response, 72, 8) / 10;
	$L3_ReverseKWh = substr($response, 80, 8) / 10;
	$L4_ReverseKWh = substr($response, 88, 8) / 10;
	$L1_volt = substr($response,96, 4) / 10 ;
	$L2_volt = substr($response,100, 4) / 10;
	$L3_volt = substr($response,104, 4) / 10 ;
	$L1_amp = substr($response,108, 5) / 10;
	$L2_amp = substr($response,113, 5) / 10;
	$L3_amp = substr($response,118, 5) / 10;
	$L1_watt = substr($response,123, 7) / 1;
	$L2_watt = substr($response,130, 7) / 1;
	$L3_watt = substr($response,137, 7) / 1;
	$watt_total = substr($response,144, 7) / 1;
	$L1_pf = substr($response,151, 4);
	$L2_pf = substr($response,155, 4);
	$L3_pf = substr($response,159, 4);
	$max_demand = substr($response, 163,7) / 1;
	$demand_period = substr($response, 170,1); //not sure of units
	$meter_date = "20" . substr($response, 172,2) . "-" .  substr($response, 174,2) . "-" .  substr($response, 176,2) . " " .  substr($response, 180,2)  . ":" .  substr($response, 182,2) .":" .  substr($response, 184,2);
	$CT_rating = substr($response, 86,4);
	$pulse1_count = substr($response, 163,8) / 1;
	$pulse2_count =  substr($response, 171,8) / 1;
	$pulse3_count =  substr($response, 179,8) / 1;
	$pulse1_ratio =  substr($response, 187,4) / 1;
	$pulse2_ratio =  substr($response, 191,4) / 1;
	$pulse3_ratio =  substr($response, 195,4) / 1;
	$pulse_HL =  substr($response, 202,3) ;

	// do whatever you want with the data.
	print "Meter Number: " . $meter_number . "\r\n";
	print "KWh Total: " . $KWh_total. "\r\n";
	print "Reverse KWh Total: " . $ReverseKWh_total. "\r\n";
	print "L1 V: " .$L1_volt. "\r\n";
	print "L2 V: " . $L2_volt. "\r\n";
	print "L3 V: " . $L3_volt. "\r\n";
	print "L1 A: " . $L1_amp. "\r\n";
	print "L2 A: " . $L2_amp. "\r\n";
	print "L3 A: " . $L3_amp. "\r\n";
	print "L1 W: " . $L1_watt. "\r\n";
	print "L2 W: " . $L2_watt. "\r\n";
	print "L3 W: " . $L3_watt. "\r\n";
	print "Watt Total: " . $watt_total. "\r\n";
	print "L1 Pf: " . $L1_pf. "\r\n";
	print "L2 Pf: " . $L2_pf. "\r\n";
	print "L3 Pf: " . $L3_pf. "\r\n";
	print "Max Demand: " . $max_demand. "\r\n";
	print "Meter Date: " . $meter_date. "\r\n";


} //end of function

/* MAIN  */

get_meter_data(11123,"10.5.2.17",50000);

?>
Jameson
Posts: 862
Joined: Fri Nov 04, 2011 7:42 pm
Location: Santa Cruz, CA
Contact:

Re: Reading meter using PHP

Post by Jameson »

Hey this is VERY cool ;) Thank you so much for sharing! We love this type of collaboration.

Can you give us a hand on how to set it up? We have tried to host the code on our web server: http://documents.ekmmetering.com/EKM-php-reader.php

When you go to this URL you get:
Parse error: syntax error, unexpected T_STRING in /home/dbrouwer/public_html/documents/EKM-php-reader.php on line 4
We took the text of your code (changed the IP address and port to on of ours here) and put it in a .php file. We then posted this to our web server. Obviously we seem to be missing something about how this is supposed to work.

Thanks for any insights you have.

Regards,
Jameson
EKM METERING
http://www.ekmmetering.com
831.425.7371
LBJ
Posts: 4
Joined: Mon Dec 31, 2012 2:35 pm

Re: Reading meter using PHP

Post by LBJ »

Thanks rcarsey, this is great, especially all of that parsing! Jameson, that sounds like it could be a fairly simple error - if you can post the code (or send privately) I can try to help debug.

Note also to anyone using this code, the tcp rcarsey's referring to is the sockets (php_sockets.dll or .so) extension.
Jameson
Posts: 862
Joined: Fri Nov 04, 2011 7:42 pm
Location: Santa Cruz, CA
Contact:

Re: Reading meter using PHP

Post by Jameson »

LBJ,

Yes, you are right, this is great. Very nice of rcarsey to put this together.

To be honest I was not certain what I was doing. I just took the code (word for word) that is posted here by rcarsey and pasted it into a file that I named "ekm-php-reader.php". I changed the IP address, port, and meter number from this section: "get_meter_data(11123,"10.5.2.17",50000)". Then I put it in a web folder and tried to open it.

So in short I have the same code that is pasted here (above).

If you do get this working, it would be great if you could send us a link to see it run.

Thanks!
Jameson
EKM METERING
http://www.ekmmetering.com
831.425.7371
LBJ
Posts: 4
Joined: Mon Dec 31, 2012 2:35 pm

Re: Reading meter using PHP

Post by LBJ »

Hmm... it sounds like maybe there was a text encoding issue involving the text editor you were using? So the copy/paste from the website introduced unwanted characters? I was able to take the code straight from this page with no problems (using Crimson Editor). I'd love to share but unfortunately the code is running on a local server that's not set up for outside access at this time.

I'm still working out a few other issues with the script that are probably server-dependent. We're running the test server on a windows machine, so timeouts need to be accounted for, and parsing of the return string is slightly off (probably due to os-dependent socket handling discrepancies as well). If the OP is still around, I'd be interested to know what their setup is - php version, apache/iis version, etc.
Post Reply