I am new to PHP and I am writing a PHP code to get data from a modbus device using the PHPModbus library. I need to be able to display the data every second and then write the data to a CSV file every minute.
How do I overcome this?
<?php
// for automatically refreshing the page every one second
header('Refresh: 1');
//setting the time zone and getting the date and time
$timezone = "Asia/Calcutta";
if(function_exists('date_default_timezone_set')){
date_default_timezone_set($timezone);
}
echo date('d-m-Y'). "</br>";
echo date('H:i:s'). "</br>";
//reference to ModbusMaster.php file where the modbus php protocol is defined
require_once dirname(__FILE__) . '/phpmodbus/Phpmodbus/ModbusMaster.php';
// Create Modbus object
$modbus = new ModbusMaster("192.168.1.105", "TCP");
//Energy Meter
// FC3 = Function Code 3 to read holding registers
/*Setting device ID = 5, Starting address as 100 and
number of registers to be read as 120
*/
try {
// FC 3
$recData = $modbus->readMultipleRegisters(5, 100, 120);
}
catch (Exception $e) {
// Print error information if any
echo $modbus;
echo $e;
exit;
}
// Print status information
echo "</br>Status:</br>" . $modbus;
// Conversion
echo "<h2>EN8400</h2>\n";
// Chunk the data array to set of 4 bytes
$values = array_chunk($recData, 4);
//Create an array and set first two values as date and time
$energymeter_param = array();
$energymeter_param[0] = date('Y-m-d H:i:s');
//$energymeter_param[1] = date('H:i:s');
$count = 1;
// Get float from REAL interpretation
//echo "<h3>Energy meter</h3>\n";
//get each parmeter from energy meter and store in the array
foreach($values as $bytes){
/*Since load hours is unsigned long we are converting it
to unsigned long type and scaling to get correct value */
if($count == 59) {
$temp = PhpType::bytes2unsignedint($bytes);
$temp = $temp/3932160;
}
else {
$temp = PhpType::bytes2float($bytes);
//Converting Wh to Kwh
if($count == 31) {
$temp = $temp/1000;
}
}
//store the values in an array
$energymeter_param[$count] = $temp;
$count++;
}
//Store the number of energy meter parameters in a variable
$num_energymeter_param = $count;
echo "<h3>Energy meter array</h3>\n";
//print array
print_r ($energymeter_param)." </br>";
//write the values to a csv file every time seconds becomes 00
if((date('s')) == 00) {
$temprow = implode(',',$energymeter_param);
$temprow.="\n";
$file = 'H:\Appserv\www\Log.csv';
file_put_contents($file, $temprow, FILE_APPEND );
}
You have two things going on (state and exact match).
First, apache+PHP (I'm assuming apache, but same thing applies to IIS and other stateless setups) don't run your script all the time, but only when requested. This causes the inconsistency that you are seeing, where the browser may not make the request exactly when you want it (too many factors as to why this will happen).
This can be better handled by running a PHP daemon to handle the 1 minute logging.
However, if you want to continue with this route, then you have to deal with inconsistent queries.
You can use a way that covers a "greater than" rather than exact match expression. In particular you can check when your CSV file was last changed via the stat function (mtime value): http://php.net/manual/en/function.stat.php and then if it has been longer than 59 seconds append to the file.
Browsers are known to be unreliable ways of timing, so I still recommend a daemon.