mackerelで室温を監視して、お部屋をいい感じの温度にキープする

前回の記事ではSiri + Raspberry Pi + IRKitで
お部屋の家電を操作するところまで作りました。

takanamito.hateblo.jp

今回は、その続編として
室温を計測し、規定の温度を外れた場合に自動でエアコンを操作して
お部屋の温度を快適に保つ方法を実践していきます。

先日、会社の勉強会で発表した際に使った資料がこちら

この発表で「エアコンの自動設定に任せられないのか」「そもそも目指す温度に設定しておけばいいんじゃないのか」という意見がありましたが

  • うちのエアコンに温度の「自動」設定がなかった
  • そもそも実家でも学校でも「自動」で快適な温度になったことがない
  • 温度上げる時はさっさと上げたい
  • なんかたまに謎判定でエアコンサボるからめっちゃ寒かったりする

みたいな理由から今回の自作温度調節機能の開発がスタートしました。

お金がある人は最新モデルの霧ヶ峰とかを買うといいかもしれません。

霧ヶ峰 MSZ-GV2216(W) ピュアホワイト(2.2kW)

霧ヶ峰 MSZ-GV2216(W) ピュアホワイト(2.2kW)

システム構成

前回までに登場した

  • Raspberry Pi
    • homebridge
    • homebridge-irkit
  • IRKit (API付き学習リモコン)
  • エアコン

に加えて、ラズパイにUSB温度計のTemperを接続します。
接続する際は、本体に直接挿すと熱伝導でUSBスティック自体が熱くなるため
延長ケーブルなどで本体の熱が伝わらないように接続するのがコツです。

USB温度計! USB thermometer-528018

USB温度計! USB thermometer-528018

また、設置する位置が高かったり低かったり、当たり前ですが熱を放つ機械のそばにあるだけで計測結果が変わります。
自分の体感値と照らし合わせながら最適な設置場所を探してみてください。

我が家ではこれを「百葉箱ポジション」と呼んでいます。

室温自動調節の仕組み

  • Temperで温度を取得
  • ラズパイで稼働中のmackerel-agent経由で温度をメトリクス化
  • Alert設定で10分継続してしきい値を上回る/下回る温度が続いた場合Alert発火
  • ラズパイから定期的にmackerelのAlert APIを叩いてCRITICAL状態の場合はエアコンの設定温度を操作

f:id:takanamito:20170212002428p:plain:w300

こんな流れです。
発表スライドにも載っているのですが、開発中はmackerelを使わずに
毎分温度を取得して、低ければ設定温度を上げるようにしていたのですが
室温はすぐに上がらないため、ラズパイが温度を上げようとして
毎分エアコンの「ピッ」という音を聞かされることになりました。

また部屋がちょうどいい温度にもかかわらず
トイレに行くために一瞬だけ廊下へのドアを開けただけで冷気が入り込み
その冷気を拾ってラズパイが過剰に反応してしまうこともありました。

そこでmackerelを使って「○○分継続して温度が規定値を外れたら」という
webの外形監視っぽい仕組みを導入することで回避しています。

温度を取得

ラズパイにTemperを接続して温度を取得します。
商品にwindows用のインストーラーがついていますが、ラズパイ用にコマンドをビルドします。

【Raspberry Pi】USB温度計を付けてみる – Happy Life Hacking

mackerelに投げる

mackerel-agentもgithubにarm版が公開されています。

Releases · mackerelio/mackerel-agent · GitHub

この中から mackerel-agent_linux_arm.tar.gzをDLし、展開して利用します。

mackerel-agentのARM版バイナリーはRaspberry PI 2でもさくっと動く - Qiita

temperから取得できる温度を整形してmackerelに渡すためのスクリプトを用意

#!/bin/bash

name="temper"
monitor_time=`date +%s`
temperature=`/opt/temper/temper | sed -e 's/.*,\(.*\)/\1/'`
echo -e "${name}\t${temperature}\t${monitor_time}"

mackerelの設定ファイルに上のスクリプトを叩くように追記してagentを再起動

[plugin.metrics.process]
command="sudo /home/pi/temper.sh"
type="metric"

Monitorを設定

ここまでの手順でmackerelにメトリクスが表示されるようになったと思います。 f:id:takanamito:20170211232917p:plain

Monitorの設定画面から

  • 温度上限
  • 温度下限

の設定をしたMonitorを作成しましょう。
我が家では 上限 23℃, 下限 21℃で、10分間既定値を外れた場合にAlertを発火するようにしています。

f:id:takanamito:20170211233807p:plain

Alertを監視するスクリプトを用意

mackerelのmonitorがalert状態になったのを取得する必要があります。
今回は手軽にやりたかったので「cronで15分おきにAlert APIを叩く」という方法で確認を行っています。

アラート - Mackerel API ドキュメント (v0)

雑スクリプトで取得して、IRKitにリクエストを送ります。

#!/bin/bash

cd `dirname $0`

check_alerts () {
  curl https://mackerel.io/api/v0/alerts -H 'X-Api-Key:xxxxx' -H 'Content-Type: application/json' | jq '.alerts[]'
}

# 自動調節モードのOn/Offを確認
if [ ! -e /tmp/check.txt ]; then
  echo 'Auto control is off'
  exit 0
fi

JSON=`check_alerts`

ID=`echo $JSON | jq '.monitorId'`
STATUS=`echo $JSON | jq '.status'`
echo $ID
echo $STATUS

if [ $STATUS = '"CRITICAL"' ]; then
  echo `date`
  echo 'Status is CRITICAL'

  if [ $ID = '"xxxxx"' ]; then # 上限アラート
    sh ./22.sh
    sleep 1
    sh ./21.sh
  elif [ $ID = '"xxxxx"' ]; then # 下限アラート
    sh ./22.sh
    sleep 1
    sh ./23.sh
  else
    echo 'Unknown Alerts'
  fi
else
  echo `date`
  echo 'Status is not CRITICAL'
fi

やっていることは単純で

  • Alert APIを叩いてjqでjsonをみる
  • ステータスがCRITICALかつ
    • 上限Monitorのidと一致すれば
    • 下限Monitorのidと一致すれば
    • ※各MonitorのidはmackerelのMonitor画面URLに付与されています
  • IRKitにHTTPリクエストを送るスクリプトを実行
    • ※今回はそれぞれ2℃ずつ変更すべくスクリプトを実行しています

また序盤で「自動調節モードのOn/Offを確認」とコメントがありますが
ファイルの有無を自動調節モードの起動フラグとして利用しているだけです。

このファイルの作成/削除はhomebridge-cmdで管理しているため
「Hey Siri エアコン調節オン」みたいに声で自動調節モードを起動できるところがちょっとかっこよくて気に入ってます。

結果

f:id:takanamito:20170211235420p:plain

ある日のグラフです

  • 20:00ごろ 帰宅
    • エアコンを起動
    • 自動調節モードもON
    • 既に21℃を下回っているためalert状態
  • 数分後
    • alert状態がわかりラズパイが自動的に設定温度をアップ
  • 20:30すぎ
    • 20℃を突破
  • 22:00前
    • 今度は上限のAlertに引っかかる
    • ラズパイが設定温度を下げる

という挙動で、その後いい感じに温度がキープできているのがわかるかと思います。
この日、ぼくは普通に暮らしており、温度に関することを一切意識していません。

このように、考えないといけないことが1つ減らせたのがとてもうれしいです。
今後はスマートコンセントを使って、加湿器も制御して湿度をコントロールできればと思っています。

今度からは、霧ヶ峰を買って解決できるようになりたいです。