1

我是 PHP 新手,我正在编写 PHP 代码以使用 PHPModbus 库从 modbus 设备获取数据。我需要能够每秒显示数据,然后每分钟将数据写入 CSV 文件。

  • 我使用 header('Refresh:1') 每秒刷新页面。
  • 我将数据作为原始字节获取,我根据参数将其转换为浮点数或整数。
  • 然后我将数据存储在一个数组'energymeter_param'中并内爆数组的内容以获得一个我想每60秒写入CSV文件log.csv的字符串。
  • 如果您阅读我的代码,您会看到每次秒的值变为 0 时我都在调用 file_put_contents() 函数。[ if(date('s') == 0)]。
  • 但有时在刷新页面时,时间会直接从 HH:MM:59 跳到 HH:MM:01,所以我错过了那一分钟日志文件中的数据。

我该如何克服呢?

<?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 );
}
4

3 回答 3

0

考虑一个 AJAX 解决方案,其中计时器变量由浏览器在 JavaScript 中处理。

在 document.ready() 上,您可以使用 setTimeout 启动对 php 的 Ajax 调用(以获取最新数据)并跟踪最后一次写入的时间。如果自上次写入以来的时间 > 59 秒,则执行写入。

于 2012-12-05T06:27:11.813 回答
0

你有两件事发生(状态和完全匹配)。

首先,apache+PHP(我假设是 apache,但同样适用于 IIS 和其他无状态设置)不会一直运行您的脚本,而是仅在请求时运行。这会导致您看到的不一致,浏览器可能无法准确地在您想要的时候发出请求(太多的因素导致了这种情况的发生)。

这可以通过运行 PHP 守护程序来处理 1 分钟的日志记录来更好地处理。

但是,如果您想继续这条路线,那么您必须处理不一致的查询。

您可以使用涵盖“大于”而不是完全匹配表达式的方法。特别是,您可以通过 stat 函数(mtime 值)检查您的 CSV 文件上次更改的时间:http: //php.net/manual/en/function.stat.php,然后如果超过 59 秒,则附加到文件。

众所周知,浏览器是不可靠的计时方式,所以我仍然推荐一个守护进程。

于 2012-12-05T06:27:51.143 回答
0

使用 ssh

watch -n 1 php /yourphpscript.php

这样你的脚本就会每秒运行一次

于 2014-03-20T03:53:11.077 回答