読者です 読者をやめる 読者になる 読者になる

ちぎっては投げるブログ

Programming, Android, RaspberryPi, Digital Devices, Kinkuma Hamster...

自分が帰宅しているかをRaspberryPiで検知する簡単な方法

I’m home

いつかのブログにも書いたかもしれないが、RaspberryPiで色々センサーをいじれるように遊んでいると、「自分が家にいるときだけ」という処理をしたくなる。

しかし、近接センサーは近くしか見ないし、照度センサーは窓の近くだと結構変わるし、わざわざそのためにBLEを使うのも……。

という場合に、簡単な方法として、自分のスマホのIPへpingを打って返り値を確認するという方法がある。

家に無線LANの環境があり、スマホだけ自宅にあるという状態がないのが前提である。

せっかくRaspberryPiなのにセンサー使わないのかよ!というのはあるが、手段よりも目的重視で……。

f:id:mczh:20170220221353p:plain 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が切れたりした場合である。

そのあたりは反応性の良さとのトレードオフなので、しきい値やチェック間隔を調整していい感じにしよう。