I’m home
いつかのブログにも書いたかもしれないが、RaspberryPiで色々センサーをいじれるように遊んでいると、「自分が家にいるときだけ」という処理をしたくなる。
しかし、近接センサーは近くしか見ないし、照度センサーは窓の近くだと結構変わるし、わざわざそのためにBLEを使うのも……。
という場合に、簡単な方法として、自分のスマホのIPへpingを打って返り値を確認するという方法がある。
家に無線LANの環境があり、スマホだけ自宅にあるという状態がないのが前提である。
せっかくRaspberryPiなのにセンサー使わないのかよ!というのはあるが、手段よりも目的重視で……。
Photo by geralt | Pixabay / CC BY 0
スマホの準備
まず、自分のスマホを固定IPにしておく。DHCPで他のマシンに取られないように、ちょっと外れた番号にしておくと良い。たとえば192.168.1.20など。
Linuxのpingは止めるまで打ち続ける仕様
Windowsのコマンドプロンプトから打つと数回で勝手に止まるが、Linuxから打つと無限に打ち続けるようだ。いつも無意識に止めていたから気が付かなかった。
しかし、無限に打ち続けられてしまうと返り値が取得できない。
どうせなら失敗したら返ってくるとか、成功するまでは打ち続けるとか、そのようなオプションがあれば楽だったが、見当たらない。
しかたがないので、指定した回数だけpingを打って、一旦その結果を取得して、その結果によって更にループさせたりbreakさせたりする必要がある。
指定した回数だけpingを飛ばす
指定した回数だけ実行させるには、-cのオプションをつける。
ping -c 回数 192.168.1.20
今回の目的では、1回pingを実行してスリープさせて、またpingを実行して、のループがいいだろう。
サンプルコード
#!/bin/sh PING_TARGET="192.168.1.20" MAX_SECOND=108000 SLEEP_SEC=5 #loop until ping success count=$MAX_SECOND success_count=0 THRESHOLD=5 while [ $count -ge 0 ] ; do ping ${PING_TARGET} -c 1 >> /dev/null rc=$? if [ $rc -eq 0 ] ; then if [ $success_count -eq $THRESHOLD ] ; then break fi success_count=`expr $success_count + 1` else success_count=0 #reset fi sleep $SLEEP_SEC count=`expr $count - $SLEEP_SEC` done if [ $rc -eq 0 ] ; then # 処理 fi
変数は適当に変える。 このサンプルは、5秒に一度pingを打ち、5回連続で成功すればbreakして、処理を実行する。 最大待ち時間は、約108000秒(6時間)にしてある。
このコードは、自宅に帰ったら勝手に照明をつけるためにRaspberryPiに仕込んでいるコードの抜粋である。
このスクリプトを、仕事の定時にcrontabで自動実行するようにしている。 すると、定時~6時間以内に家に着けば、勝手に電気がついてくれる。
ちなみに、シェルスクリプトのデバッグで困ったときは、
#!/bin/sh
の部分を、
#!/bin/sh -x
に変更すると、行ごとの処理をすべて表示してくれるのでわかりやすい。
問題点
問題点は、自宅にいながらスマホの電源が切れたりwifiが切れたりした場合である。
そのあたりは反応性の良さとのトレードオフなので、しきい値やチェック間隔を調整していい感じにしよう。