温湿度計作り(6):Raspberry Pi センサデータのグラフ表示
Webサーバーにデータを送信できるようになったので、あとはGUIをどう作るかですが、前回と同じく、インデペンデンスシステムズ横浜のページを参考にさせて頂きました。
http://independence-sys.net/main/?p=3973
こちらのページで紹介されているCanvasJSが実装も簡単で使いやすく、見た目も折れ線グラフで複数パラメータを同時に表示でき、日・週・月毎の表示も簡単に切り替えられるため、そのまま参考にしました。
まず、データベースにアクセスするためのホスト名やパスワードをまとめたファイルを、以下のように用意します。XXXXXXXやYYYYYYYに入れる文字列は、前回記事と同様です。
【Database.php】
<?php function GetDb(){ // mysql:host=ホスト名;dbname=データベース名;charset=文字エンコード $dsn = 'mysql:host=XXXXXX.php.xdomain.ne.jp;dbname=YYYYYYYY;charset=utf8'; // データベースのユーザー名 $usr = 'ZZZZZZZZZ'; // データベースのパスワード $passwd = 'AAAAAAAAAA'; $db = new PDO($dsn, $usr, $passwd); $db-> exec('SET NAMES utf8'); return $db; } ?>
続いて、MySQLのデータを取得するプログラムを以下のように記述します。
<?php require_once 'Database.php'; $target = isset($_GET['target']) ? $_GET['target'] : 'temp'; $range = isset($_GET['range']) ? $_GET['range'] : 'Day'; switch ($range){ case 'Average': case 'Month': $dayRange = 30; break; case 'Week': $dayRange = 7; break; case 'Day': $dayRange = 1; break; default: break; } $day = date("Y-m-d H:i:s",strtotime("-$dayRange day")); $qryDate = strtotime("-{$dayRange} day"); $db = GetDb(); switch ($range){ case 'Average': for ($day=0; $day <$dayRange ; $day++) { $days = date("Y-m-d", $qryDate); $sth = $db->prepare("SELECT datetime,avg($target) FROM raspi_sensorvalues where datetime like '$days%' ORDER BY id ASC"); $sth->execute(); $row = $sth->fetch(PDO::FETCH_ASSOC); $jsonData[] = [ 'label'=>substr($row['datetime'],5,5), 'y'=>(float)round($row['avg('.$target.')'],2) ]; $qryDate = strtotime("+1 day", $qryDate); } break; case 'Month': case 'Week': case 'Day': $sth = $db->prepare("SELECT datetime,$target FROM raspi_sensorvalues where datetime >= '$day' ORDER BY id ASC"); $sth->execute(); while($row = $sth->fetch(PDO::FETCH_ASSOC)){ $jsonData[]=[ 'label'=>substr($row['datetime'],5,11), 'y'=>(float)$row[$target] ]; } break; } header('Content-type: application/json'); echo json_encode($jsonData); ?>
最後に表示部分を以下のように記述します。
【Graph01.php】
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>センサーデータ</title> <script type="text/javascript" src="https://canvasjs.com/assets/script/canvasjs.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script type="text/javascript"> function drawChart(selectspan) { var temp_data; $.ajax({ url: "MySQL.php", //データ取得のURL type: "GET", //GETメソッドで取得 dataType: 'json', //処理結果はjson形式で受信 async: false, //非同期通信 data: { target: 'temp', range: selectspan }, success: function(json1) { temp_data = json1;} }); var hum_data; $.ajax({ url: "MySQL.php", dataType: 'json', async: false, data: { target: 'hum', range: selectspan }, success: function(json1) { hum_data = json1;} }); var lux_data; $.ajax({ url: "MySQL.php", dataType: 'json', async: false, data: { target: 'lux', range: selectspan }, success: function(json1) { lux_data = json1;} }); var chart = new CanvasJS.Chart(chartContainer01, { title: {text: "温度・湿度・照度データ"}, axisX: { labelAngle: -90, labelFontSize: 14, labelFontColor: '#222'}, axisY:[{ title: "Tempreture", lineColor: "#C24642", tickColor: "#C24642", labelFontColor: "#C24642", titleFontColor: "#C24642", //includeZero: false, suffix: "℃" }, { title: "Humidity", lineColor: "#369EAD", tickColor: "#369EAD", labelFontColor: "#369EAD", titleFontColor: "#369EAD", includeZero: false, suffix: "%" }], axisY2: { title: "Illuminance", lineColor: "#FF8C00", tickColor: "#FF8C00", labelFontColor: "#FF8C00", titleFontColor: "#FF8C00", includeZero: false, suffix: "lx" }, toolTip: {shared: true}, legend: {cursor: "pointer",itemclick: toggleDataSeries}, //axisY: { title: "temperature", suffix: '℃',axisYIndex: 0, labelFontSize: 14, labelFontColor: '#222' }, theme: "light1", //デフォルトテーマに設定 data: [{ type: 'line', //温度グラフの種類 name: "temperature", color: "#C24642", showInLegend: true, axisYIndex: 0, dataPoints: temp_data //表示するデータ }, { type: 'line', //湿度グラフの種類 name: "humidity", color: "#369EAD", axisYIndex: 1, showInLegend: true, dataPoints: hum_data //表示するデータ }, { type: 'line', //照度グラフの種類 name: "illuminance", color: "#FF8C00", axisYType: "secondary", showInLegend: true, dataPoints: lux_data //表示するデータ }] }); chart.render(); //マウスカーソル一つに3つの値を表示する設定 function toggleDataSeries(e) { if (typeof (e.dataSeries.visible) === "undefined" || e.dataSeries.visible) { e.dataSeries.visible = false; } else { e.dataSeries.visible = true; } e.chart.render(); } } </script> </head> <body onload= drawChart('Day')> <form> <select name="selectspan" onchange="drawChart(this.value)"> <option value="Day" selected="">1日</option> <option value="Week">1週間</option> <option value="Month">1ヵ月</option> <option value="Average">1ヵ月平均</option> </select> </form> <div id="chartContainer01" style="height: 450px; width: 100%;"></div><br> </body> </html>
この3つのファイルをWebサーバーにアップロードします。
そして、Graph01.phpのページを開くと、以下のようなページがされました!
見た目も綺麗ですし、カーソルを画面に触れるだけで、上図のように各時間帯の数値も確認できます。
これならスマホのブラウザからアクセスするだけで、いつでも家のセンサ情報を確認できますね。スマホのブラウザから開くと、若干見た目が崩れるので、私はPC版サイトから開くようにして、PCと同じビジュアルになるように設定しています。