문제

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.

  • I have used the header('Refresh:1') to refresh the page every second.
  • I get the data as raw bytes which I convert to float or int depending on the parameter.
  • Then i store the data in an array 'energymeter_param' and implode the contents of the array to get a string which I want to write to the CSV file log.csv every 60 seconds.
  • If you read my code you would see that I am calling the file_put_contents() function every time the value of seconds becomes 0. [ if(date('s') == 0)].
  • But sometimes while refreshing the page the time skips from HH:MM:59 to HH:MM:01 directly and so i miss the data in the log file for that 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.

다른 팁

Consider an AJAX solution where the timer variables are handled by the browser in JavaScript.

On document.ready() you could start the Ajax calls back to the php with setTimeout (to get he latest data) and track the time of the last write. If time since last write > 59 sec, then do a write.

Use ssh

watch -n 1 php /yourphpscript.php

That way your script gets run every second

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top