先日のラズパイ温度計、延々と温度計測を続けています。
一日の温度変化は、測定データを全て取得すればよいですでが、週間とか月間といった長いスパンになると、データをはしょったほうがよいです。
ということで、測定データの移動平均を取ってみようと思い立ちました。
色んなサイトを参考にさせて頂いて、なんとか実装することができました。
CakePHP3でのコードはこんな感じです。
$hm_data = $this->ondo_data->find( )
->join( [ .....(3)
'table' => 'temperature_histories',
'alias' => 'subtbl',
'type' => 'LEFT',
'conditions' => [
'TIMESTAMPDIFF(MINUTE, TemperatureHistories.measuring_datetime, subtbl.measuring_datetime) BETWEEN -35 AND 35',
'TemperatureHistories.sensor_id = subtbl.sensor_id',
],
] )
->select([
'dayhhmm' => "DATE_FORMAT(TemperatureHistories.measuring_datetime, '%d %H:%i')",
'hourAvg' => 'AVG(CAST(subtbl.temperature AS SIGNED))', .....(5)
'measuring_datetime' => 'TemperatureHistories.measuring_datetime',
])
->where(function ($exp, $q) use ( $sdate, $edate ) { .....(1)
return $exp->between( 'TemperatureHistories.measuring_datetime', $sdate, $edate );
})
->where( ['MINUTE(TemperatureHistories.measuring_datetime)' => '00', 'TemperatureHistories.sensor_id' => $sensor_id ] ) .....(2)
->group([ 'TemperatureHistories.measuring_datetime' ]) .....(4)
->order([ 'TemperatureHistories.measuring_datetime' => 'ASC' ]) .....(6)
->all();
temperature_histories はテーブル名。
temperature へ計測結果が入ります。
measuring_datetime は計測日時。
sensor_id は、温度センサーのIDです。
大ざっぱな解説は…
(1)集計期間は、$sdate と $edate の間です。
(2)データを取得するのは、$sensor_id 指定されるセンサー、時間は正時(00分)毎とします。
(3)subtblという別名で自分自身をjoinしますが、その際に、測定時間の前後35分間の測定値も取得します。
(4)joinしたテーブルからは複数のデータがくるので、TemperatureHistories.measuring_datetime でグループ化します。
(5)上記(3)でjoinしたsubtblから取得したデータの平均値を計算します。
(6)当たり前ですが、測定時間でソートします。
temperature を CAST しているのは、temperatureが数値型ではなく文字列型のためです。
最初に、あまり深く考えずに、文字列型にしてしまったので、こんなことになっています。
dayhhmm はグラフ化する時に横軸で使用するためです。
で、得られたデータをグラフ化したら、こんな感じになりました。