1

私はPHPが初めてで、PHPModbusライブラリを使用してmodbusデバイスからデータを取得するPHPコードを書いています。毎秒データを表示し、毎分データを CSV ファイルに書き込むことができる必要があります。

  • header('Refresh:1') を使用して毎秒ページを更新しました。
  • パラメータに応じて float または int に変換する raw バイトとしてデータを取得します。
  • 次に、データを配列 '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

タイマー変数が JavaScript のブラウザーによって処理される AJAX ソリューションを考えてみましょう。

document.ready() では、(最新のデータを取得するために) setTimeout を使用して PHP への Ajax 呼び出しを開始し、最後の書き込みの時間を追跡できます。最後の書き込みからの時間が 59 秒を超える場合は、書き込みを行います。

于 2012-12-05T06:27:11.813 に答える
0

2 つのことが進行中です (状態と完全一致)。

まず、apache+PHP (私は apache を想定していますが、IIS やその他のステートレス セットアップにも同じことが当てはまります) は、常にスクリプトを実行するのではなく、要求された場合にのみ実行します。これにより、ブラウザーが必要なときに正確に要求を行わない可能性があるという、あなたが見ている矛盾が発生します (なぜこれが起こるのかについてあまりにも多くの要因があります)。

これは、PHP デーモンを実行して 1 分間のログを処理することで、より適切に処理できます。

ただし、このルートを続行する場合は、一貫性のないクエリに対処する必要があります。

完全一致表現ではなく、「より大きい」をカバーする方法を使用できます。特に、stat 関数 (mtime 値) を介して CSV ファイルが最後に変更された時刻を確認できます: http://php.net/manual/en/function.stat.php 59 秒以上経過している場合は、次のように追加します。ファイル。

ブラウザーは信頼性の低いタイミング方法であることが知られているため、それでもデーモンをお勧めします。

于 2012-12-05T06:27:51.143 に答える