ソラカメのモーション通知を Flux で便利に使う
※ これは SORACOM Advent Calendar 2024の 12/9 の記事です。
はじめに
自宅の車庫にソラカメを設置しているのですが、カメラがあるにも関わらず置いてあったもの(捨てる予定だったものですが)を持って行かれる事件がありました。
クラウド録画はしていたのですが、通知を設定していなかったのですぐに気付けませんでした。
そこで、ソラカメのモーション検知を設定したのですが、例えば夜間家の前を車が通るといちいちヘッドライトの光に反応したりして False Alarm が多すぎるので、人間を感知した時にだけ通知をしたいなと思いました。
構成
全体の構成としてはこんな感じです。
┌───────┐ ┌────────┐ ┌────────┐
│ │ │ │ │ │
│SoraCam│ ──────────► │SORACOM │ ──────────► │ iPhone │
│ │ Webhook │ Flux │ Notify │ (LINE) │
└───────┘ └────────┘ └────────┘
Person detected?
ソラカメの通知先として、Flux App の API イベントソースに設定した Webhook URL を指定します。
Flux App 初期バージョン
Flux app の中はこんなイメージです。
Recording
Stop?
┌─────────┐ ┌─────────┐ ┌────────┐
│ API │ │ SORACOM │ Yes │ │
│(Webhook)│──────►│ API ├──┬────►│ LINE │
│ Source │ │ (*1) │ │ │ │
└────▲────┘ └─────────┘ │No └────────┘
│ │
│ ┌────▼────┐
│ │ │
└────────────────────┤Republish│
│ │
└─────────┘
*1: listSoraCamDeviceEventsForDevice API
イベントとしてソラカメのデバイス ID が入ってくるので、そちらを元に listSoraCamDeviceEventsForDevice API をコールし、最新のイベントの録画が完了しているかチェックします。
完了していたら、LINE へ通知を送ります。
こんな感じでよさそうな感じなんですが、実際にテストをしてみると録画が長い場合には Republish〜SORACOM API アクションの流れがループ限度まですぐに繰り返し実行されてしまい、そこで処理が止まってしまいました。
そこで、Flux のアプリ中に wait を入れる方法を考えてみました。
Flux Wait endpoint
webhook action として 使える endpoint を作りました。
URL: https://flux.j3tm0t0.dev/wait
から呼び出せます。
実際に curl で試してもらうとわかりますが、一定時間後に input で渡されたものをそのまま返すようになってます。
curl -d '{"foo":"bar"}' 'https://flux.j3tm0t0.dev/wait?duration=5'
(5秒の間)
{"foo":"bar"}
これを Flux App の Republish の代わりに入れると、お好みの秒数(ただし webhook action の仕様により8秒くらいまで)の遅延を入れることが出来ます。
※ 特にログなどは取ってはいませんが、予告なく停止することもあると思うので、自己責任でお試しください
Flux App 最終形
さきほどの Flux App を以下のように変更します。
Recording
Stop?
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌────────┐
│ API │ │ Webhook │ │ SORACOM │ Yes │ │
│(Webhook)├─────►│ Wait ├─────►│ API ├──┬────►│ LINE │
│ Source │ │ │ │ (*1) │ │ │ │
└────▲────┘ └─────────┘ └─────────┘ │No └────────┘
│ │
│ ┌────▼────┐
│ │ Webhook │
└────────────────────────────────────┤ Wait │
│ │
└─────────┘
*1: listSoraCamDeviceEventsForDevice API
イベント発火時に即録画が終了していることはまずないので、最初に wait webhook を実行します。
その後、同様に対象デバイスの一番最近のイベントを確認し、まだ録画が進行中の場合は wait webhook を再び実行し、最初のチャンネルにイベント paylaod である ${event.payload}
を戻します。
これにより、よほど長い録画イベントでない限り、ループ上限に達して終了してしまうことがなくなりました。
あとは通知設定で「アクションの実行条件」を
payload[0].eventInfo.atomEventV1.recordingStatus == "completed" &&
payload[0].eventInfo.atomEventV1.labels != null &&
payload[0].eventInfo.atomEventV1.labels[0] == "person"
のように設定し、「メッセージ」を以下のようにしておくと、
カメラ: ${event.payload.deviceName} に人間が映りました
${payload[0].eventInfo.atomEventV1.picture}
以下のように人間が写ったときにだけ通知が来るようになりました!
(通知イメージ)
カメラ: AtomCam Swing moto に人間が映りました
※こちらの写真は、自宅ではなく先日ワーケーションで滞在した建物の前の道です
最後に
これで、人間が写った時にだけ通知が来るようになりましたし、すぐにサムネも確認できるようになりました!
また、さらに便利にするネタを考えているので、この続きはいずれ!
Discussion