ブログTOPにうちのベランダの気温と湿度を表示
ベランダ太陽光発電で気象観測システムを構築しており、
雨の日も雪の日も猛暑の日も動き続け、
先日でとうとう1000日達成したところですが、、
ブログTOPに気温と湿度を表示させてみました。
* 1000日達成の記事
*ログをChart.jsでグラフ化
目次
ソースコード
jsonを返すphp
ログを取得しているラズパイサーバでjsonを返すphpを作成。
ログファイルは年月ごとのテキストファイル(YYYYMM.txt)になっており、
中身はこのような形で記録されている。
1 2 3 4 5 6 |
2024/06/25 20:26 4.08 0.23 1002.3 18.97 64.2 2024/06/25 20:29 4.07 0.25 1002.3 18.94 64.1 2024/06/25 20:33 4.06 0.23 1002.3 18.92 64.0 2024/06/25 20:36 4.07 0.25 1002.3 18.95 63.8 2024/06/25 20:39 4.08 0.23 1002.4 18.95 63.8 ・・・・・ |
時刻 電圧 ソーラー 気圧 気温 湿度
ここから最新ログデータを抽出しJSON化。
ChatGPTにサクッとコードを書いてもらいました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
<?php // ログフォルダのパスを指定 $logDir = './logs/'; // ディレクトリが存在しない場合は終了 if (!is_dir($logDir)) { die('ログディレクトリが存在しません。'); } // ログディレクトリ内のファイルを取得 $files = scandir($logDir); // 数値が最大のファイル名を保持する変数 $maxFile = null; $maxNumber = -1; // ファイルをループして数値が最大のファイルを探す foreach ($files as $file) { // ファイル名が数値.txt形式の場合に処理 if (preg_match('/^(\d+)\.txt$/', $file, $matches)) { $number = (int)$matches[1]; if ($number > $maxNumber) { $maxNumber = $number; $maxFile = $file; } } } if ($maxFile !== null) { // ファイルの内容を読み込む $filePath = $logDir . $maxFile; $fileContent = file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); // 最後の行を取得 if (!empty($fileContent)) { $lastLine = end($fileContent); // データ行をタブで分割 $data = explode("\t", $lastLine); // データをJSON形式に整形 $jsonData = [ "time" => $data[0], "batteryVoltage" => (float)$data[1], "solarVoltage" => (float)$data[2], "airPressure" => (float)$data[3], "temperature" => (float)$data[4], "humidity" => (float)$data[5] ]; // JSON形式にエンコード $jsonOutput = json_encode($jsonData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); echo $jsonOutput; } else { echo "ファイルが空です。"; } } else { echo "数値.txt形式のファイルが見つかりませんでした。"; } ?> |
WP側でログデータJSONを取得するphp
WPCodeプラグインでphpを追加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
// データを取得するURL $url = 'ラズパイサーバに置いたJSONのURL'; // cURLセッションを初期化 $ch = curl_init(); // cURLのオプションを設定 curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // URLからデータを取得 $response = curl_exec($ch); // cURLセッションを閉じる curl_close($ch); // 取得したデータをデコード(仮にJSONデータと仮定) $data = json_decode($response, true); // 必要なデータを抽出しエスケープ処理を行う $temperature = round($data['temperature'], 1); $humidity = round($data['humidity'], 1); global $time; global $temperature_js; global $humidity_js; $time = esc_js($data['time']); $temperature_js = esc_js($temperature); $humidity_js = esc_js($humidity); |
HTML
json取得のphpで設定したグローバル変数を記述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<div class="flex items-center md:h-full gap-3 md:pb-5"> <div class="relative flex-none max-md:w-1/2"> <span class="inline-block p-1 rounded-md bg-[rgba(240_244_240/85%)] px-4 font-bold mb-3 md:text-lg">うちのベランダ</span> <div class="bg-[rgba(240_244_240/85%)] rounded-md"> <span class="block text-center font-bold p-1">温度 <span class="text-[#0073e6] text-[18px]"><?php echo $temperature_js; ?>℃</span></span> <div class="w-full md:w-1/2 md:w-96 h-20 md:h-40 mb-3"> <canvas id="chart1" data-chart="<?php echo $temperature_js; ?>"></canvas> </div> </div> <span class="inline-block p-2 rounded-md bg-[rgba(240_244_240/85%)] text-xs md:text-sm px-4 font-bold">データ取得日時 <?php echo $time; ?></span> </div> <div> <div class="bg-[rgba(240_244_240/85%)] m-auto !mr-0 rounded-md p-3"> <span class="block text-center font-bold p-1 -mt-1">湿度 <span class="text-[#0073e6] text-[18px]"><?php echo $humidity_js; ?>%</span></span> <div class="w-[150px] h-40 md:w-[250px] md:h-[250px]"> <canvas id="chart2" data-chart="<?php echo $humidity_js; ?>"></canvas> </div> </div> </div> </div> |
JavaScript
Chart.jsの設定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
const ctx = document.getElementById('chart1'); const ctx2 = document.getElementById('chart2'); const dataTemperature = Number(ctx.getAttribute('data-chart')); const dataHumidity = ctx2.getAttribute('data-chart'); setTimeout(function() { new Chart(ctx, { type: 'bar', data: { labels: ['温度'], datasets: [{ label: '温度', data: [dataTemperature], backgroundColor: ['rgba(0,115,230,.9)'], borderWidth: 1 }] }, options: { plugins: { legend: { display: false, }, }, legend: { labels: { fontColor: 'black' } }, maintainAspectRatio: false, indexAxis: 'y', scales: { x: { min: -20, max: 40, }, y: { display: false, beginAtZero: true } } } }); new Chart(ctx2, { type: 'doughnut', data: { labels: ['湿度',''], datasets: [{ label: '湿度', data: [dataHumidity ,100-dataHumidity], backgroundColor: ['rgba(0,115,230,.9)', 'transparent'], borderWidth: 1 }] }, options: { plugins: { legend: { display: false, }, tooltip: { // 'tooltips'ではなく 'tooltip' を使う enabled: true, mode: 'index', intersect: false, filter: function(tooltipItem, context) { return tooltipItem.dataIndex !== 1; // 'index' ではなく 'dataIndex' を使う } }, }, maintainAspectRatio: false, } }); }, 1000); |
完成!
お父ちゃん確認でもろもろ表示調整を行い、
このような形でブログTOPに表示することができました。