Seeed K.K.の中井です。
最近の展示会やイベントなどでSenseCAP Watcherを展示してきましたが、皆さんの反応は良く、AIを手軽に使えるデバイスということに興味を持っていただけているのかなぁと感じています。
そんなSenseCAP Watcherですが、様々な状況を判断し登録したタスクにマッチした状況となればスマホに通知が出来るのですが、専用のアプリ(SenseCraft APP)だけではなく任意のSNSやサービスにもイベントを通知することもできるようです。
私も実際に他のSNSやサービスに通知したことがなかったので、試してみましたよという記事になります。(デバイスを直接制御することができたりするようですがそれはまた別の機会に試したいと思っています)
SenseCAP Watcherは、世界初(?)のフィジカルAIエージェントという製品です。Watcherの"目"(=カメラOV5647)が状況を監視し 特定の状況 を確認した場合に アクション することができるデバイスとなっています。製品の特長と言いますか概要を簡単に説明すると、"特定の状況"や"アクション"(これらをまとめて タスク と表現します)を自然言語やプッシュトーク(※英語のみ対応)で登録することができ、タスク実行に必要となるAIモデルやフローが自動的にデプロイされ、基本的な使用方法であればノーコードでAIを体験・業務利用することができる、というものです。
自然言語でAI??、、そうです。簡単に言うと「チャット感覚でやらせたいことを登録してアプリに知らせることができる」という感じでしょうか。これだけだとまさに万能のデバイスと思われるかもしれませんが、苦手なことも色々あります。詳しくは、公式Wikiにまとめられていますのでそちらをお読みください。
さて、前置きが長くなってしまいましたが、SenseCAP WatcherのHTTP Push Notificationを試していきたいと思います。公式WikiではHTTP Push Notificationを使って他のSNSやサービスと連携する場合にはNode-REDを用いたインテグレーションを推奨しています。
Node-REDサーバーを構築して、、サーバー管理したくない人がほとんどだと思いますので、 今回はNode-REDが統合されているenebularを利用してみます。Webhookが使える実行環境が無償で利用できる点もenebularを選んだ理由の1つです。
enebularをセットアップする前に、まずはWatcherのHTTP Push Notificationがどのような振る舞いをするのか確認してみました。
HTTP Push Notification
Watcherがどのような通知を行うのか、実際に受信してみて確認してみました。検証には下記のAPIサーバを簡易的に用意しました。
# # main.py # from fastapi import FastAPI, Request import logging logger = logging.getLogger('uvicorn') app = FastAPI() @app.post("/v1/notification/{path}") async def get_event(req: Request): logger.info("### POST:/vi/notification/{path}") logger.info(f" Path: {req.path_params}") logger.info(f" Query Params: {req.query_params}") logger.info(f" HEADER: {req.headers}") logger.info(f" BODY: {await req.body()}") return {"Result": "OK"}
PS C:\Users\nakai\Documents\my_api_server> uvicorn main:app --host 192.168.1.114 --port 8000 INFO: Started server process [18996] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://192.168.1.114:8000 (Press CTRL+C to quit)
APIサーバを用意した後、SenseCAP側を設定。タスクにはSenseCraft APPでWatcherをタップし、Assign Task画面に標準(?)で表示されるif there is a person, device plays sound 'Hi, I'm watcher, an AI bot'
。
Detail Configsに入ってHTTP Push Notification
にチェックを入れ、Go Setup
で通知先(HTTP URL
)を指定します。もちろん先ほど用意したAPIサーバを指定。HTTP Token
にはとりあえずダミーの文字列をいれておきました。
Run Task
してWatcherが人物を検出すると次のように通知されました。
INFO: ### POST:/vi/notification/{path} INFO: Path: {'path': 'event'} INFO: Query Params: INFO: HEADER: Headers({'user-agent': 'ESP32 HTTP Client/1.0', 'host': '192.168.1.114:8000', 'content-type': 'application/json', 'authorization': 'Asdfghk', 'api-obiter-device-eui': '2CF7F1C96270009D', 'content-length': '10523'}) INFO: BODY: b'{"requestId":"5b5ea8ae-36c3-4974-845f-40e56a6ebe2c","deviceEui":"2CF7F1C96270009D","events":{"timestamp":1734488354199,"text":"Hi, I\'m watcher, an AI bot","img":"~base64でエンコードされた画像データ~","data":{"inference":{"boxes":[[172,253,340,308,71,0]],"classes_name":["person"]}}}}' INFO: 192.168.1.127:63124 - "POST /v1/notification/event HTTP/1.1" 200 OK
Header
{ "user-agent": "ESP32 HTTP Client/1.0", "host": "192.168.1.114:8000", "content-type": "application/json", "authorization": "Asdfghk", "api-obiter-device-eui": "2CF7F1C96270009D", "content-length": "10523" }
Body
{ "requestId":"5b5ea8ae-36c3-4974-845f-40e56a6ebe2c", "deviceEui":"2CF7F1C96270009D", "events":{ "timestamp":1734488354199, "text":"Hi, I\'m watcher, an AI bot", "img":"~base64でエンコードされた画像データ~", "data":{ "inference":{ "boxes":[ [172,253,340,308,71,0] ], "classes_name":[ "person" ] } } } }
HeaderにはHTTP Token
で指定したキーが”authorization”として渡されています。Bodyに"deviceEui"があるので複数のWatcherを利用したとしても識別ができるようになっていますね。events.data.inference.boxesには対象検出時の画像内のボックス座標とAccuracy、Classification IDが確認できます。
ただ、JSONのフォーマットが決まっているので直接外部サービスに送信して使える、というようにはいかなそうです。
インテグレーション
今回はお試しなのでアカウント設定やインテグレーション確認用に設定済みのslackを用いてSenseCAP Watcherのイベントを通知するようにしました。
slackにメッセージを送るためにはslack appを用意する必要があります。この記事では「slack appの作成」、「ワークスペースへのインストール」、「チャンネルへslack appを追加」などの設定方法については割愛しますので、下記などを参考にしてください。
必要なのは、特定のワークスペース/チャンネルにファイルをアップロードできるappと そのappが組み込まれたチャンネルがあれば試すことができます。
enebular
enebularではWatcherのイベントを受け取りslackに転送するフローの作成とその実行環境を作成します。
まずはフローの作成から。プロジェクトを選択してアセットを作成。
デバッグ方法の確認
編集画面に移動して、とりあえずWatcherのイベントの受け口としてhttp in
ノード、レスポンスを返すためのhttp response
ノード、レスポンスを設定するためのfunction
ノードを配置して繋ぎます。
事前に確認した通知の内容から、http in
はPOSTメソッドを、URLに/vi/notification/event
を設定します。http response
は"200"を返しておくようにします。function
は必要ないかもしれませんがとりあえず"OK"でも返しておきます。debug
ノードをつけておくとWatcherの通知時のペイロードを確認することができるようになります。
http in | http response | function |
---|---|---|
とりあえずここまでのフローはこんな感じです。
一旦、フローをデバッグする方法の確認。フローエディタの右上にある"i"のアイコンにカーソルを合わせるとインスタントURLを確認することができるので、SenseCraft APPでHTTP URL
に設定。Watcherで自分を検出させると通知が行われ、enebularが通知を受け取り、デバッグメッセージに通知時のペイロードが表示されます。
画像をデコード
Watcherの通知時のペイロード(Notification Payload)には画像データが含まれていることは確認済みです。それをSlackに添付したいのですが、slackはBase64エンコードされたデータを受け取ったとしても自動的にデコードして画像表示することができないので、slackに送る前にデコードします。
Node-REDでBase64を扱うには追加のライブラリが必要のようです。メニューからパレットの管理を選択して、ノードを追加でnode-red-node-base64
ライブラリを追加します。base64で検索すると最上位に出てきました。
とりあえずbase64
ノードを配置しておき、バッファ<->Base64の変換
、プロパティにはpayload.events.img
を設定しておきます。
因みにnode-red-contrib-image-output
ライブラリのimage
ノードを使うとフローエディタ上に画像を表示することができます。Base64でエンコードされたデータでもデコードした後でもどちらでもプレビュー表示することができます。
note. 画像データはJPEGフォーマット
Base64でエンコードされた画像データをデコード後に確認してみると、
FF D8 FF E0
で始まっているのでJPEG画像ということがわかりました。
slack
Node-REDにはslack用のライブラリnode-red-contrib-slack
も用意されているのでパレットに追加します。
追加するとパレットのソーシャルグループにいくつかのノードが追加されます。今回はslackにメッセージを送信したいのでslack-web-out
ノードを選択して配置します。このノードのSlack Clientには、メッセージを送るワークスペースにインストールしたslack appのOAuth Tokenを指定して追加します。
note. slack appのOAuth Tokenの取得
OAuth Tokenは、slack apiでYour Appsに移動して、対象のAppを選択して表示されるメニューのOAuth & Permissions(または、Install App)から取得することができます。
続いて上記で設定したslack appに対して実行するAPIの設定をfunction
ノードで行います。今回は画像とテキストを送信したいので、files.uploadメソッドを利用します。msg.topic
にメソッドを設定し、msg.payload.channels
には送信対象のチャンネル名またはチャンネルIDを設定します。function
ノードはslack-web-out
の前に接続します。
msg.topic = "files.upload"; msg.payload = { "channels": "**channel names or IDs**", "initial_comment": msg.payload.events.text, "filename": "image", "file": msg.payload.events.img, "filetype": "auto" }; return msg;
フローの動作確認
ここまでに作成したフローでは、
- WatcherからPOSTリクエストを受ける:
http in
- Base64エンコードされた画像データをデコード:
base64
- files.uploadメソッドのパラメータを設定:
function
- slackに送信:
slack-web-out
という流れで処理が行われるように設定してきました。ここで一旦動作確認しておきます。 先ほどと同様にインスタントURLをSenseCraft APPで設定して自分に向けると、、
無事slackにメッセージが飛んできました!
最後にクラウド実行環境の設定
インスタントURLですと短期的に利用はできるのですが、(4時間ほど)時間が経つと使えなくなってしまいます。恒久的にフローが動作するように実行環境を作成してそこにデプロイしてあげます。
enebularにはLow-Code Development Platform(LCDP)というのが用意されていて、定期実行が可能なスケジュールトリガーやHTTPトリガーなどを設定してフローを実行することができるクラウド環境です。
フリープランでも2つの実行環境を作成でき、月当たり24時間稼働させることができます。今回のフローは1回あたり1分程度の稼働なので、24時間も稼働できれば十分かなと思います。
早速、クラウド実行環境の設定をしていきます。 作成方法などは公式のドキュメントを参照してください。
名称を入力すると1~2分待てば実行環境が出来上がります。(簡単w)
続いてSenseCAP WatcherのNotificationの受け口、HTTPトリガーを設定します。
クラウド実行環境の準備はこれだけなので、フローをクラウド実行環境上で利用できるように修正します。公式のドキュメントに記載があるようにLCDP in
とLCDP out
ノードで挟み込んであげればよいだけなので、http in
ノードをLCDP in
ノードに置き換え、slack-web-out
ノードの後ろにLCDP out
ノードを付け加えてあげます。また、http response
などは不要になるので削除、デバッグ
もできなさそう(?)なので削除しています。
このフローをクラウド実行環境にデプロイして完成です。
まとめ
- SenseCAP WatcherのHTTP Push Notificationで外部サービスと連携する場合に指定できるのは、URLとTokenのみ
- Notificationに含まれる画像データはBase64でエンコードされている
- enebular(Node-RED)を使うとインテグレーションが容易になる
- enebularはクラウド実行環境が用意されていてフリーで利用が可能 (素晴らしい)
今回作成したフローは公開しましたので、テンプレートとしてお使いください。使用される場合には送信対象のslackチャンネルとTokenの設定が必要となります。
参考リンク
- Watcher to Node-RED | Seeed Studio Wiki
- 新リリースのenebularクラウド実行環境の使い方 | enebular blog
- 花粉のピークは過ぎたかもしれないけど、enebularで花粉bot作ってみた #linebot - Qiita
- files.upload method | Slack
- Node-REDでSlackへメッセージを投稿する
- Node-REDでSlackへ画像を投稿する
変更履歴
日付 | 変更者 | 変更内容 |
---|---|---|
2024/12/25 | mnakai | 作成 |