ESPr Developerで温度を測定してグラフ化(3)

もう、半年以上も前のことになりますが、ESPr Developerを使って、当社のベランダの温度を測定するIoTデバイスを作りました(作成したときの記事は こちら、改良版の記事は こちら)。


5分毎に気温を測定して、Wi-FiでWebサーバに送信、それ以外の時間はdeep sleepする仕組みです。

実は、このデバイスで電池がどのぐらいもつのか確かめたいと考え、作成した後も、ずっと現在まで稼働させています。
作成した半年前には、最高気温が50℃ちかくになることもあったのですが、現在では逆に、最低気温がマイナスになることもあります。

せっかくデータがたまってきたので、これまでの気温の推移を見てみたくなり、PHPで集計プログラムを作ってみることにしました。
以下のような仕様です。

  • データ採取期間(2018年7月〜2019年2月)すべてにわたり、日次の最低気温と最高気温をグラフ化
  • データがおかしい期間やデータがない期間は電池が消耗している期間と考え、グレーの折れ線で表示
  • グラフ表示には「Chart.js」を使用

プログラムは以下のようになりました(やっつけで作ったので結構汚いです)。

<?php
$dbname = 'db_temp';
$db = new SQLite3($dbname);
$sql = "SELECT * FROM temp";
$result = $db->query($sql);

// 測定期間を取得
$bdate = "";
$edate = "";
while($info = $result->fetchArray(SQLITE3_ASSOC)){
  $date = (int)($info['event_time']/86400);
  if($bdate=="" || $bdate>$date) $bdate = $date;
  if($edate=="" || $edate<$date) $edate = $date;
}

// 日次の最低,最高気温を取得
for($i=$bdate ; $i<=$edate ; $i++){
  $min[$i] = "";
  $max[$i] = "";
  $flag[$i] = "";
}
$prev = 0;
while($info = $result->fetchArray(SQLITE3_ASSOC)){
  $event_time = $info['event_time'];
  $date = (int)($event_time/86400);
  $val0 = $info['val0']*100/1024;
  if($min[$date]=="" || $min[$date]>$val0) $min[$date] = $val0;
  if($max[$date]=="" || $max[$date]<$val0) $max[$date] = $val0;
  if($event_time-$prev>480){
    $flag[(int)($prev/86400)] = 1;
    $flag[$date] = 1;
  }
  if($val0>50) $flag[$date] = 1;
  $prev = $event_time;
}
for($i=$bdate ; $i<$edate ; $i++){
  if($max[$i]=="" || $min[$i]=="") $flag[$i] = 1;
}

// グラフ表示用データを生成
$res_max = "";
$res_min = "";
$res_flag = "";
for($i=$bdate ; $i<$edate ; $i++){
  $time = $i*86400*1000;
  if($flag[$i]!=1){
    $res_max .= "{ x: " .$time .", y: " .$max[$i] ." },";
    $res_min .= "{ x: " .$time .", y: " .$min[$i] ." },";
    $res_flag .= "{ x: " .$time .", y: 0 },";
  } else{
    $res_flag .= "{ x: " .$time .", y: 50 },";
  }
}

$db->close();
?>

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>温度計</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"></script>
<style>
  body { font-family: sans-serif; }
</style>
</head>
<body>
<h1>兵庫県川西市の温度</h1>
<canvas id="temp" width="300" height="100"></canvas>
<script>
var ctx = document.getElementById('temp').getContext('2d');
var temp = new Chart(ctx, {
  type: 'line',
  data: {
    datasets: [{
      label: '最高気温',
      fill: false,
      borderColor: 'red',
      backgroundColor: 'red',
      pointRadius: 0,
      data: [ <?php echo $res_max; ?> ]
    },{
      label: '最低気温',
      fill: false,
      borderColor: 'blue',
      backgroundColor: 'blue',
      pointRadius: 0,
      data: [ <?php echo $res_min; ?> ]
    },{
      label: 'データなし',
      fill: true,
      borderColor: 'lightgray',
      backgroundColor: 'lightgray',
      pointRadius: 0,
      data: [ <?php echo $res_flag; ?> ]
    }]
  },
  options: {
    scales: {
      xAxes: [{ type: 'time' }],
      yAxes: [{ ticks: { min: 0, max: 50, stepsize: 10 } }]
    }
  }
});
</script>
</body>
</html>

表示結果は以下のとおりです。

電池は単三を3本使っていますが、おおむね当初の想定どおり、20日〜25日程度もっているようです。

設置場所を時々変えたり、台風が来た時にはデバイスを室内に退避させたり、たまには直射日光もあたったりと、気温の測定環境としては適切ではありませんが、データとしてはなかなかおもしろいものが取れたと思います。