Webサイト発注虎の巻ダウンロード
Webサイト発注虎の巻ダウンロード

ラズパイでNode-REDにSwitchBotの人感センサーの検知情報を送れるか検証してみた

キー坊

こんにちは! テクニカルディレクターのキー坊です。

お家にいる時間が長くなってくると、「あー、これ自動でやってくれないかなぁ」とか思うことありませんか? そこで今回はタイトルの通り、SwitchBotを使って遊んでみようと思います。

Switch Botとは?
SwitchBot(スイッチボット)は、すべてのスイッチとボタンを機械的に制御するスマートなIoTロボットです。 家庭やオフィス内のデバイスのオン/オフを切り替える、小型で自動化されたデバイス(AndroidまたはiPhoneのアプリケーション経由で制御される)です。
文章引用元:Switch Botオンラインサイト

我が家でもSwitchBotを活用して集合玄関の開錠ボタンを自動化しています。

SwitchBotの製品は、大別すると以下の3つに種類が分かれます。

  • 実際にアクションをしてくれる「ボット」
  • 指定された情報を検知してくれる「センサー」
  • 上2つを束ねる「ハブ」

先ほどお話した、集合玄関の開錠ボタンは「ボット」のお話になりますね。そして今回は「センサー」を使った実験をしようと思います。使用するのは「人感センサー」です。

実験の目的は「Node-REDにSwitchBotの人感センサーの検知情報を送れるのか?」です。自分で組み込んだセンサーじゃなくてもNode-REDで扱えると結構できることが増えるのでは、と考えてこちらの実験を行うことにしました。

ただし、それだけの記事だとつまらないので、今回はドラクエ3の地球のへそを再現しようかと思います。

このオッサンは何を言ってるんだ? と思ってる方もいると思いますので、少しだけ説明させてください。

「地球のへそ」はドラゴンクエスト3に出てくるダンジョンの一つで、主人公である勇者一行がダンジョンを進んでいくと「引き返せ!」とどこからともなく言われるというダンジョンです。

これはつまり、センサーで人が来たことを感知して、引き返せとボットにアクションさせてるわけです。実はものすごくハイテクなダンジョンだったんですね。

ということで、前振りが長くなりましたが、こちらを作ってみようと思います!

準備

Raspberry PiにOSとNode-REDをインストールする必要がありますが、以前行っているので今回は手順を割愛します。以下の記事などを参考に準備してください。

SwitchBot人感センサーは、お手持ちのスマートフォンを使ってSwitchBotアプリに認識させるところまでセットアップを進めてください。この辺りは買ったときについてくる説明書を読めばなんとかなると思います。

実装

実はいくつか調べてみましたが、センサーが検知したときにNode-RED側に知らせる方法は見つかりませんでした(僕の調査が甘い可能性は十分ありますが)。

しょうがないので、精度は落ちるだろうけど毎回センサーを呼び出して無理やり実現したらどの程度検知できるのか? を確認してみようと思います。

SwitchBotにはAPIが提供されているので今回はそちらを活用していきます。SwitchBotAPIのドキュメントは以下のURLから確認できます。

まずはSwitchBotAPIを実行するためのトークン(鍵)ゲットしましょう。手順は下記の通りです。

  1. スマートフォンのSwitchBotアプリを起動してプロフィール > 設定とタップする
  2. 「アプリバージョン」を10回タップする
  3. 「開発者向けオプション」が表示されるので、メニューを開いて「トークンを取得」を押すとトークンが表示されます

これを何らかの方法でラズパイに渡しておいてください。

 

curl -H 'Authorization:{トークン}' https://api.switch-bot.com/v1.0/devices

ターミナルを開いて上記のようにコマンドを打ってください。

 

{
  "statusCode":100,
  "body":{
    "deviceList":[
      {
        "deviceId":"C133xxxxxxxx",
        "deviceName":"人感センサー ",
        "deviceType":"Motion Sensor",
        "enableCloudService":true,
        "hubDeviceId":"FCABxxxxxxxx"
      },
      {
        "deviceId":"FCABxxxxxxxx",
        "deviceName":"hubmini",
        "deviceType":"Hub Mini",
        "enableCloudService":false,
        "hubDeviceId":"000000000000"
      }
    ],
    "infraredRemoteList":[]
  },
  "message":"success"
}

上記のようにJSONで結果が取得できると思います。ここで取得できるdeviceIdを使うので人感センサーのdeviceIdを控えておいてください。

 

curl -H 'Authorization:{トークン}' https://api.switch-bot.com/v1.0/devices/{deviceId}/status

次に先程取得したdeviceIdを使って上記のようにAPIを叩いてみましょう。

 

{
  "statusCode":100,
  "body":{
    "deviceId":"C133xxxxxxxx",
    "deviceType":"Motion Sensor",
    "hubDeviceId":"FCABxxxxxxxx",
    "moveDetected":false,
    "brightness":"bright"
  },
  "message":"success"
}

上記のように現在のセンサーの情報が取得できるようになったと思います。moveDetectedに検知情報が入っているのが確認できますね。

さて、Node-REDでこれを使ってセンサー情報の取得をすれば良さそうですね。ただし、APIを叩ける回数が1日に1万回と制限されています。1日が86400秒ですので、APIの限界として約9秒に1度しか検知できない計算になります。

さらに、人感センサーは一度検知すると30秒間は「検知した」という情報が維持されます(きっと数秒などのあまりに短い間隔で連続して検知すると、頻度が高すぎるという判断からでしょう)。

なので、精度としては「うーん、これじゃない!」という感じになりそうですね。とはいえ、最大10秒(平均5秒)程度の誤差で検知できるなら、まあまあ面白そうですしこの形で一度Node-REDと連携してみましょう。

まずは、さきほどの結果をNode-REDから取得できるようにしましょう。各ノードには上記のような設定をしてください。インジェクションノードは何も設定してないので省略。

 

msg.headers = {};
msg.headers['Authorization'] = '{トークン}';
return msg;

set tokenと名付けたファンクションノードは上記のようにコードを設定。

 

https://api.switch-bot.com/v1.0/devices/{deviceId}/status

http requestノードにはURLを設定します。

 

const data = JSON.parse(msg.payload);
msg.payload = data.body;
return msg;

次のJSON parseと名付けたファンクションは上記のようにコードを設定。デバッグノードも結果を確認するためなので、設定などは特にしてません。デプロイボタンを押してデプロイ後、インジェクションノードのボタンを押すと実行されます。

 

実行後、右サイドバーの虫のようなアイコンからデバッグノードに出力された結果を確認すると、ターミナルから実施したのと同じような結果が取得できていると思います。

後はこれを「10秒に1回実行する」と「検知したらGoogle Homeに喋らせる」ということをやっていけば良さそうですね。「10秒に1回実行」は実はすぐにできるので方法を紹介します。

 

インジェクションノードを開いてみると下のほうに繰り返しの設定があります。ここに上記の画像のように設定すればよいのです。本当は、一度検出したら30秒は結果が維持されるので、その間は問い合わせるだけ無駄なのですが、実験なのでとりあえず良しとしましょう。

 

さて、動体検知情報を受取ることはできたので、次にその判断をします。判断にはswitchノードを使い画像のように設定します。

プロパティの下向き矢印を押して「JSONata式」を選択し、「payload.moveDetected」を入力します。後は条件に「is true」と「is false」を設定します。

これはmoveDetectedに検知情報が格納されていて、検知した場合true、検知できない場合はfalseが入っているので、そのどちらになるか? を確認している感じです。

 

msg.message = 'moving!'
return msg;

後は、その先のfunctionノードで、1番目は上記のようにしました。

2番目はメッセージを「stopping!」にしただけです。地球のへそを再現するなら停止状態のメッセージはいらないですが、現状ではテストをするときに都合がいいので動体が検知できない場合もメッセージを出してます。完全再現するなら、一番目のメッセージを「引き返せ」にすると良さそうですね(笑)

この後にdebugノードを繋げてmsg.messageを表示してあげればOKです。

 

完成すると画像のようにノードが配置されているはずです。

後はGoogle Homeに喋らせるだけですが、ここは前にもやったので今回は割愛します。方法はこちらに詳しく書いてあります。

喋らせることも割と簡単にできるので、実際にやってみてください。

まとめ

これで、あなたの家の中に地球のへそダンジョンを再現できます。廊下に仕掛けて友達を家に招いたときにびっくりさせられるのでは、と思います(笑)

本来の目的である、「Node-REDにSwitchBotの人感センサーの検知情報を送れるのか?」については、頻繁に問い合わせると電池の保ちなど気になる点はあるものの、動作に問題はなさそうです。

何に使えるかはまだ考えているところですが、人感センサーを机の下などに仕込んでおいて、着席すると部屋の明かりとモニターがついてGoogle Homeが「おはようございます。ニュースを読み上げます」とニュースを流してくれるとか、中二病とSFの混じったようなデスクでも作ってみようかなーと画策してます(笑)