ラベル PHP の投稿を表示しています。 すべての投稿を表示
ラベル PHP の投稿を表示しています。 すべての投稿を表示

2025年11月22日土曜日

有効積算温度のグラフ表示

 元々、自分の庭の温湿度をDBに蓄えたかったのは、それを利用して庭の花の開花時期などを予想したりする事をしたかったからですが、安定的に(バッテリ切れ等なく)温湿度を計測できる環境の制作に時間が係り、手を付けられていませんでしたが、Xiao S3のdeep sleep 時14μAは、流石に効果があり、1か月以上安定に動作しています。

 で、本題の有効積算温度グラフ表示を実装してみることにしました。

 まづ、有効積算温度(Effective Accumulated Temperature)とは;

 農業技術辞典 によれば「温度の日平均値をそのまま合計したもの。基準温度以下の温度は生育に寄与しないという考え方に基づき、生育に必要な最低温度(基準温度、発育ゼロ点ともいう)以上の日の日平均温度を合計した値を有効積算温度と呼ぶ。....」(コピペ出来なかったので転記)とあります。 


従って、DBから日平均温度を計算し、基準温度を超えた分だけを足してゆくようなSQLを書いてやればよいことになり、これをグラフ表示するようにすればよいわけです。 

 

 

SQLを含むphpのソースは;

<?php
//  include('funcs.php');
//$threshold = 3;  
//  $location='GardenEast';
//  $startDate = 20250401;
//  $endDate = 20251030;

$averagedataPoints = array();
  $temp;
  $dbh = db_connect();
  $handle = $dbh->prepare('select yyyymmdd, location, case when avg_temp - :threshold > 0 then (avg_temp - :threshold) else 0 end as datapoint from dailydataview where location = :location and yyyymmdd between :start and :end');
  $handle->execute(['threshold' => $threshold, 'location' => $location,'start'=> $startDate,'end'=>$endDate]);
  $result = $handle->fetchAll(PDO::FETCH_OBJ);
  $temp1 = 0;
  $count = 0;
  foreach ($result as $row) {
    $temp1 = $temp1 + $row->datapoint;
    $a = substr($row->yyyymmdd,4,2)."月".substr($row->yyyymmdd,6)."日";
    $label = $a . "(".$count."日)";
    array_push($averagedataPoints, array("y"=> number_format($temp1, 2, '.', '' ), "label"=>$label));
    $count = $count+1;
 }
 $handle=null;
 $result=null;
// print json_encode($averagedataPoints,JSON_NUMERIC_CHECK).'
'; ?>

これを表示するcanvasjs/php/htmlのコードは以下のようにしましたが、formへの指定入力内容が消えてブランクのままグラフの上に残るので見てくれが悪く、「何とかならないのか?」苦慮中です。 指定内容はグラフの方に表示されるので、間違いはありませんが、、、。

また、積算温度の予測機能は持っていませんので、過去の積算温度推移を併記させるようにと考えましたが、DBの過去のデータに欠落があって、開始時期とかが指定通りにならないことがあるので、現時点では、単年の表示のみ。 

作業中、1000以上の数字がグラフ表示されなくて、1~2日悩みましたが、phpのnumber_formatが引数を3つ取り、2番目が小数点以下、3番目が千の単位の区切りを指定できるようになっているため、省略すると千の単位にコンマが入り、これがCanvasJsで問題を起こすのでした。要注意!! 

<thtml>
  <head>
   <script>
    <?php
      include "/usr/local/www/data/DBAccess/funcs.php";
      include "/usr/local/www/data/utilities.php";
      $threshold = $_POST['threshold'];
      $location = $_POST['location'];
      $startDate=$_POST['startDate'];
      $endDate = $_POST['endDate'];
      include "/usr/local/www/data/DBAccess/AccumulatedTemperature2.php";
    ?>
    window.onload = function () {
	var chart = new CanvasJS.Chart("chartContainer", {
	    animationEnabled: true,
	    theme: "light2",
	    title:{
		text:  ,
	    },
	    subtitles: [
		{
		    text: ,
		    fontColor: "blue",
		    fontSize:20
		},
		{
		    text: ,
		    fontColor: "blue",
		    fontSize:15
		}
	    ],
            axisY: {
		title: "積算温度(°C)",
 		lineColor: "#C24642",
		tickColor: "#C24642",
		labelFontColor: "#C24642",
		titleFontColor: "#C24642",
		interlacedColor: "#F0F8FF" ,
		includeZero: true,
		suffix: "°C",
	    },
 	    data: [
		{
		    name: "積算温度",
		    type: "line",
		    indexLabelFontSize: 16,
		    color: "rgba(255,0,0,0.3)", // red
		    lineThickness: 3,
		    showInLegend: true,
		    yValueFormatString: "#0.## °C",
		    dataPoints: <?php echo json_encode($averagedataPoints, JSON_NUMERIC_CHECK); ?>
 		},
	    ]
	});
	chart.render();
    }
    </script>
  </head>
  <body>
    <form action="" method="post">
      閾値(温度°C):<input name="threshold" type="text" value="10" />
      開始日時(YYYYMMDD):<input name="startDate" type="text" />
      終了日時(YYYYMMDD):<input name="endDate" type="text" />
      場所:<select name="location">
	<option value="GardenEast"></option>
	<option value="GardenCenter"></option>
	<option value="GardenNorth"></option>
	<option value="MyRoom"></option>
      </select>
      <input type="submit" value="submit" />
    </form>
    <div id="chartContainer" style="height: 600px; width: 90%;"></div>
    <script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
  </body>
</html>

 

 

 

2024年4月13日土曜日

php のインストールの確認

phpって最初のfacebook書くときに使われたみたいで、それなりに歴史のある言語で、私も2006年位から使っていますが、CLIで使う事はあまり無いので、apacheとの連携のトラブル(mod_phpのバージョンの齟齬)などは気になりますが、拡張モジュールのインストールの問題については気にしたことがありませんでした(今まで問題が無かった)。

今回拡張モジュールのインストールがうまく行っていなくてphp83でトラブりましたが、この拡張モジュールのインストール確認方法として php -v が有効なので記録しておきます。 -vは通常バージョン表示するだけですが、拡張モジュールの読み込みがうまく行っていないと、色々 warning を出してきて、その原因(大概は指定の場所にファイルが無い)も表示してくれるので、簡単に原因を把握することが出来ました。

-vはバージョンを表示する為の物!って固い頭の思い込みをちょっと反省。

2022年5月28日土曜日

サーバーの復帰(続き)

立ち上がりそうなことは確認できたので、システムディスクをM.2 のSSDに替え、最新のFreeBSDを(uname -r: 13.0-RELEASE)M.2 SSDにインストールして、今まで使っていた zfs が立ち上がり、今までのファイルが読めることを確認したので、Xをインストールして、Windowマシンからremoteで幾つでも窓開けて作業できるようにして、まづ第一段階の復帰は終了。 

ここまでは、あまり問題なくすんなり進んで一安心。 特にZFSが完全に読めるので、snapshotなり、以前作っておいてzfsに保存していたusr/local等のバックアップが利用できたので大変に助かった。

で、postgresql, apache24,samba4等いつも使っていたものについても、それぞれ復帰を試みる。

apache24: portから最新のものをインストール(時に大きく変わることは無いはずなので問題は無いはず)。 しかし、http.confで引っ掛かる! バックアップから/usr/local/www/等関係のありそうなものをコピーしてきて、立ち上げ直すと無事にデータロガーも含めて動作した。

samba4: portから最新のものをインストール。これもsmb4.confが必要なので、/usr/local/etc/のバックアップからsmb4.confをコピーしてきて立ち上げ直すと無事動作。 Windowsマシンから、サーバー上のディレクトリが読めるようになって、よかったよかった。

postgresql: これもversion 12を使っていたので、取り敢えずversion 12をインストールしてDBのバックアップをとり、それから最新の、、と思ったけれど一つ手前のversion 14をインストールし直し、先に取ったバックアップファイルからDBを復元。

ここまでで、すべてOK! とはゆかず、、、。

自宅環境の温湿度などを表示させていたWEBサーバーのアプリが、JpGraphを使ってグラフを表示させていたが、php 7.2までしかサポートしていなかった。  

phpも8.0.19にバージョンアップしてしまったので、グラフ表示に別のプログラムを使用することにしました。 Canvas.JSが良さそうなので、一週間ほどいじくりまわして何とか、らしきものが表示できるように出来ました。 そのうち、もう少し機能を理解して改善してゆきたい。 Javascriptを使ったサーバーサイドプログラム?なので、まだ十分には理解できていないかも、、、。

 

停電は川崎市の水道局が工事中に、東電の設備を壊してしまったことによるらしいのですが、お陰で久しぶりにUnix環境のプログラム作成をすることになりました。 Emacsも久しぶりで、使えるようになるのに少々時間が掛かりましたが、今はWindows上でやたらctrl-Cして困ってます。

 

教訓

  • オープンソースのプログラムは定期的にアップデートしていないと、古いシステムのままで動かし続けるのは 複数の自作アプリが組み合わさったりしているので、難しい(個々のプログラムのサポート体制が異なる)
  • ZFSは安定していて、最近open zfsに変更になった様に理解していたが、問題なく使用できて大変助かった(十分信頼に足るシステムのように思う) 。 zfstoolsを利用して、15分毎にsnapshotを取っているので、急な停電でもZFSが壊れていなければ、停電15分前には戻れる。
  • /etc/ 、/usr/local/etc/ 下の自分の設定ファイル、DBのデータ ファイル www下のファイルなどは必ずバックアップを取っておく事。 これで、昨日の状態が復元できる!
  • 年齢も年齢なので、老いの予防に時々システムのアップグレードなどで頭の体操をした方が、良いのでしょうね。 運動などして筋肉強化には務めていますが、頭の体操は、あんまりしていないので、、、。
  •  ZFSを起動システムにしていないので、システムの入れ替えとは独立してファイルを移行できるのですが、設定ファイルのバックアップが自動では取れないことになるので/usr/local/etcはzfs上にマウントし、/etcは別途定期的にzfs上にbackup fileを作るようにしておくことにします。

 

後から継接ぎでzfs のmountpointを追加したので綺麗くないですが、今のdf




2020年3月27日金曜日

JpGraphを久しぶりに弄って 一部問題解決。

室内と庭の温度、湿度のpostgreSQL DBが動くようになったので、今まで使っていた、HPをちょっと弄って化粧をしてみました。

JpGraphを使ってグラフを描かせていましたが、何故かグラフの各点の値表示が出来な
かったり、TrueTypeのフォントが使えていなかったりしたのを、一日がかりで修正。
  • 値の表示が出来なかった原因 ;  $graph->clearTheme()を設定していないと、表示をしてくれなかった。下のphpのソースコード参照
  • TrueTypeフォントのインストール ;  FreeBSDで動いているので、packageからwebfont(MSのTTF同等?)をインストール。 /usr/local/lib/php/jpgraph/jpg-config.inc.phpのTTF, MBTTFを実際にインストールされているディレクトリに指定する。
//
// UNIX:
//   CACHE_DIR /tmp/jpgraph_cache/
//   TTF_DIR   /usr/share/fonts/truetype/
//   MBTTF_DIR /usr/share/fonts/truetype/
//
// WINDOWS:
//   CACHE_DIR $SERVER_TEMP/jpgraph_cache/
//   TTF_DIR   $SERVER_SYSTEMROOT/fonts/
//   MBTTF_DIR $SERVER_SYSTEMROOT/fonts/
//
//------------------------------------------------------------------------
// define('CACHE_DIR','/tmp/jpgraph_cache/');
define('TTF_DIR','/usr/local/share/fonts/webfonts/');
define('MBTTF_DIR','/usr/local/share/fonts/webfonts/');
ついでにDBの欠落データを正しくグラフに反映させる為に、pg_fetch_rows()から、pg_fetch_result()に変更して、array()の該当する日時にデータが挿入されるように変更

require_once ('jpgraph/jpgraph.php');
require_once ('jpgraph/jpgraph_bar.php');
require_once ('jpgraph/jpgraph_stock.php');
require_once ('jpgraph/jpgraph_line.php');

  $ydata = array();
  $y1data = array();
  $ymax = array();
  $ymin = array();
  $yhumid = array();
  $ymaxhumid = array();
  $yminhumid = array();
  $ypressure = array();
  $ymaxpressure = array();
  $yminpressure = array();
  $sdata = array();

$conn = "hostaddr=192.168.?.?? dbname=XXXXX user=Who password=Are_you?";  //fake user/password
$link = pg_connect($conn);
if (!$link) {
   die ('Connection failed '.pg_last_error());
   }

  $result = pg_query("SELECT day, avg_temperature, max_temperature, min_temperature,avg_humidity, max_humidity, min_humidity, avg_pressure,max_pressure,min_pressure from dailydatacurrentmonth where location='MyRoom'" );
if (!$result){
   die('Query failed'.pg_last_error());
  }
$tempE=pg_fetch_result($result, pg_num_rows($result)-1, 0);  // chech when day ends
for ($i = 0, $j = 0, $k = 0; $i < $tempE; $i++){
   $temp =pg_fetch_result($result, $k, 0);  //  day
   if ($i == $temp-1) {
     $x_axis[$i] = $temp;
     $ydata[$i] = pg_fetch_result($result, $k, 'avg_temperature');
     $yhumid[$i] = pg_fetch_result($result, $k, 'avg_humidity');
     $ymaxhumid[$i] = pg_fetch_result($result, $k, 'max_humidity');
     $yminhumid[$i] = pg_fetch_result($result, $k, 'min_humidity');
     $ypressure[$i] = pg_fetch_result($result, $k, 'avg_pressure');
     $ymaxpressure[$i] = pg_fetch_result($result, $k, 'max_pressure');
     $yminpressure[$i] = pg_fetch_result($result, $k, 'min_pressure');
     $sdata[$j++] = pg_fetch_result($result, $k, 'min_temperature');
     $sdata[$j++] = pg_fetch_result($result, $k, 'min_temperature');
     $sdata[$j++] = pg_fetch_result($result, $k, 'max_temperature');
     $sdata[$j++] = pg_fetch_result($result, $k, 'max_temperature');
     $k++;
   } else {
     $x_axis[$i] = $i+1;
     $ydata[$i] = '';
     $yhumid[$i] = '';
     $ymaxhumid[$i] = '';
     $yminhumid[$i] = '';
     $ypressure[$i] = '';
     $ymaxpressure[$i] = '';
     $yminpressure[$i] = '';
     $sdata[$j++] = '';
     $sdata[$j++] = '';
     $sdata[$j++] = '';
     $sdata[$j++] = '';
   } 
}

  $result = '';
  $result = pg_query("SELECT day, avg_temperature from dailydatacurrentmonth_prevyear where location='MyRoom'" );
  if (!$result){
     die('Query failed'.pg_last_error());
  }
for ($i = 0; $i < pg_num_rows($result); $i++){
    $rows = pg_fetch_array($result, NULL, PGSQL_ASSOC);
    $y1data[$i] = $rows['avg_temperature'];
}

$close_flag = pg_close($link);

$graph = new Graph(750, 450);
$graph->clearTheme();
$graph->SetFrame(true);
$graph->SetScale("textlin",10, 40);
$graph->SetY2Scale("lin",10, 90);
$graph->img->SetMargin(50,30,20,90);
$graph->SetShadow();

$graph->title->SetFont(FF_ARIAL,FS_BOLD,14);
$graph->title->Set("Daily Max/Min/Avg Temperature & Avg Humidity of the Month");

//$graph->yaxis->title->SetFont(FF_ARIAL.FS_ITALIC, 10);
$graph->yaxis->title->Set("Temperature");
$graph->ygrid->Show(true,false);
$graph->y2axis->title->Set("Humidity");

$graph->xaxis->title->Set("Month-Day");
//$graph->xaxis->title->SetFont(FF_ARIAL.FSBOLD, 10);
$graph->xgrid->Show(true,true);

// Specify the tick lables
$graph->xaxis->SetTickLabels($x_axis);
$graph->xaxis->SetTextLabelInterval(1);

// Create the linear plot
$lineplot = new LinePlot($ydata);
$lineplot->SetColor("blue");
$lineplot->mark->SetType(MARK_UTRIANGLE);
$lineplot->value->show();
$lineplot->value->SetFont( FF_ARIAL, FS_ITALIC, 7 );
$lineplot->value->SetColor('darkred');
$lineplot->value->SetFormat('%0.1f');

$p1 = new StockPlot($sdata);
$p1->SetWidth(9);

$line2plot = new LinePlot($y1data);
$line2plot->SetColor("red");
$line2plot->mark->SetType(MARK_UTRIANGLE);
//$line2plot->value->show();
$line2plot->value->SetColor('darkred');
$line2plot->value->SetFont( FF_ARIAL, FS_BOLD, 10 );
$line2plot->value->SetFormat('%0.1f');


$barplot = new BarPlot($yhumid);
$barplot->SetColor("black");
$barplot->value->Show();
$barplot->value->SetFont( FF_ARIAL, FS_BOLD, 10 );
$barplot->value->SetFormat('%0.1f');

// Add the plot to the graph
$graph->Add($lineplot);
$graph->Add($line2plot);
$graph->AddY2($barplot);
$graph->Add($p1);

$graph->Stroke();

?>



2017年4月6日木曜日

PostgreSQL/PHP/JpGraph で小物つくり(続)

取り敢えず動くようになれば、化粧はtry & errorで何とでもなります。
 (PHPも慣れてくれば、それなりに動くものは作れますー見通しの良くない言語なので長くなるとバグ取りが大変)。

ということで、現在は左の様な画面が出てくるようになっています。 何故か、JpGraphのデータの値を表示する所が動いてくれません。 サンプルを動かしてみても、表示されないので、使用しているJpGraph(4.0.2) か PHP(7.1.3、ZEND v3.1.0)の問題なのでしょうが、ちょっと残念。
左下のコードで各プロット点にデータの値が表示されるはずなのですが、、、。

 :     :            :
$lineplot->value->show();
$lineplot->value->SetColor('darkred');
$lineplot->value->SetFont(FF_FONT1,FS_BOLD);
$lineplot->value->SetFormat('%0.1f');
 :      :               :
部屋の中の気温、湿度、気圧なので内容はどうでもよい話ですが、システムの枠組みがあればLPWAとセンサーの組み合わせにより、かなり広範囲の気象条件の変化などを把握することが出来ますので、農業等の分野では面白いことが出来ると思います。  


2017年4月4日火曜日

Postgres/PHP/JpGraphで小物作り

以前ESP8266を使って一定時間ごとに室内の気温、湿度、気圧を送信する小物を作りましたが、そのデータを四六時中動いているFreeBSDのサーバに送信するようにしてありました。 そして、サーバではデータを受け取るとPostgreSQLのDBにため込むようにしていました。 
実際にはESPのSleepの仕様(?)の関係から一時間おきくらい(不正確)のデータアップロードになっていますで、計測時間はサーバがデータを受け取った時にしています。
このデータをWEBブラウザでグラフで見れるようにと、久しぶりにPHPでプログラムを組んでみました。 昔一度使ったことがあって、デバッグが面倒で好きになれませんでしたが、今回も自分のケアレスミスでまる一日悩まされることになりました。 グラフの描画プログラムの中にデバッグ用のprint文を埋め込むと”データが壊れているよ”ってエラーが出るんですよね、当たり前の話ですが、、。 このデバッグ用のスタブが見つけられずに苦しんでいましたが、今朝やっと見つけて何とか動くようになりました。 

取り敢えず、未完成ですが、備忘録のつもり。 デバッグスタブと$マークで苦しみました。
まだ、スッピンのブスなので、色々メイクして綺麗にしてあげないと、、、、。 慣れちゃえばそんなにムズイ事は無いのですが、使わないと直ぐに忘れちゃいますからね~。

取り敢えず、シャックのモニターで色々な所の温度とか、土壌水分とか見ながら必要な仕事をモニター画面からボタン一つで指示する、というズボラ・システムの基礎実験の初めの始め。

require_once ('jpgraph/jpgraph.php');
require_once ('jpgraph/jpgraph_line.php');

  $ydata = array();
  $ymax = array();
  $ymin = array();
  $yhumid = array();
  $ymaxhumid = array();
  $yminhumid = array();
  $ypressure = array();
  $ymaxpressure = array();
  $yminpressure = array();
 
$conn = "hostaddr=192.168.1.3 dbname=data_logger user=ken password=love4u";
$link = pg_connect($conn);
if (!$link) {
   die ('Connection failed '.pg_last_error());
   }

  $result = pg_query('SELECT yyyymmdd, avg_temp, max_temp, min_temp,avg_humid, max_humid, min_humid, avg_pressure,max_pressure,min_pressure from dailydata1month' );
if (!$result){
   die('Query failed'.pg_last_error());
  }

for ($i = 0; $i < pg_num_rows($result); $i++){
    $rows = pg_fetch_array($result, NULL, PGSQL_ASSOC);
    $x_axis[$i] = $rows['yyyymmdd'];
    $ydata[$i] = $rows['avg_temp'];
    $ymax[$i] = $rows['max_temp'];
    $ymin[$i] = $rows['min_temp'];
    $yhumid[$i] = $rows['avg_humid'];
    $ymaxhumid[$i] = $rows['max_humid'];
    $yminhumid[$i] = $rows['min_humid'];
    $ypressure[$i] = $rows['avg_pressure'];
    $ymaxpressure[$i] = $rows['max_pressure'];
    $yminpressure[$i] = $rows['min_pressure'];
}

$close_flag = pg_close($link);


$graph = new Graph(750, 350,"auto");
$graph->SetFrame(true);
$graph->SetScale("textlin",0, 40);
$graph->SetY2Scale("lin",0, 1500);

$lineplot = new LinePlot($ydata);
$lineplot->SetColor("blue");
$lineplot1 = new LinePlot($ymax);
$lineplot1->SetColor("red");
$lineplot2 = new LinePlot($ymin);
$lineplot2->SetColor("orange");

$graph->Add($lineplot);
$graph->Add($lineplot1);
$graph->Add($lineplot2);

$graph1 = new Graph(750, 350,"auto");
$graph1->SetFrame(true);
$graph1->SetScale("textlin",0, 100);

$lineploth = new LinePlot($yhumid);
$lineploth->SetColor("blue");
$lineploth1 = new LinePlot($ymaxhumid);
$lineploth1->SetColor("red");
$lineploth2 = new LinePlot($yminhumid);
$lineploth2->SetColor("orange");

$graph1->Add($lineploth);
$graph1->Add($lineploth1);
$graph1->Add($lineploth2);

$lineplotp = new LinePlot($ypressure);
$lineplotp->SetColor("blue");
$lineplotp1 = new LinePlot($ymaxpressure);
$lineplotp1->SetColor("red");
$lineplotp2 = new LinePlot($yminpressure);
$lineplotp2->SetColor("orange");

$graph->Add($lineplotp);
$graph->Add($lineplotp1);
$graph->Add($lineplotp2);

//$graph->Stroke();
$graph1->Stroke();

?>
 

WSJT-x Super F/H

 WSJT-x使い始めてから随分経ちます(JT65しかなかった頃から)が、FT8のF/Hの使いがっ手の悪さ、MSHVの方が利用されている実態、F/HでFoxがマルチで返答すると信号が弱くなる、などからSuperF/Hが実装されましたね。  そこまでは、問題なく理解していたのですが...