昨今テレワークに代表される多様な働き方が導入されて、メンバーの居場所がわからなくて困っていると小耳に挟みました。
ちょうど(?)使ってなかったBLEタグが手元にあったので、お手軽に解決する方法を考えてみたいと思います。
構成
とりあえずはこんなイメージでしょうか。
それぞれの役割を列挙すると、
タグ: 個人を特定するIDを周囲にアドバタイジングする
ノード: 周囲に存在するタグを検出し、自らが設置された位置を特定するIDを添えてセントラルへ情報を通知する
セントラル: ノードから通知された最新のタグ位置を保持する
となります。シンプルですね。
今回はそれぞれ下記の構成で実装してみたいと思います。
タグ | MAMORIO RE https://mamorio.jp/re |
ノード | M5ATOM LITE |
セントラル | M5Stack |
実装
ESP-NOW
先程のイメージ図を素直に実装すると、各ノードからセントラルへの通知はWiFi経由で行えば簡単そうです。 ですが、WiFi環境がなかったり未登録の機器による接続に制限がある場合での運用を考慮したいと思います。
M5StackおよびM5Atomに載っているESP32ではESP-NOWというコネクションレスの無線通信が可能です。MACアドレスを指定するだけで送信できてとても便利なのでそちらを使ってみることにしましょう。
ESP-NOWはArduino core for the ESP32のスケッチ例を見ればなんとなくわかっちゃうのですが、一応説明すると
- 初期化
- 送信先のピアを登録(送信する場合)
- コールバックの登録
- (必要ならば)送信
の流れで実装すれば送受信できちゃいます。簡単ですね。
#include <esp_now.h> #include <WiFi.h> const uint8_t CHANNEL = 0; const uint8_t target[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // 送信先のMACアドレス }; void OnDataRecv(const uint8_t * mac, const uint8_t *recvData, int len) { // 受信した } void setup() { WiFi.mode(WIFI_STA); if (::esp_now_init() != ESP_OK) { return; } esp_now_peer_info_t peerInfo; ::memcpy(peerInfo.peer_addr, target, 6); peerInfo.channel = CHANNEL; peerInfo.encrypt = false; if (::esp_now_add_peer(&peerInfo) != ESP_OK) { return; } ::esp_now_register_recv_cb(OnDataRecv); } void loop() { static uint8_t i = 0; ::esp_now_send(target, &i, 1); i++; ::delay(5000); }
MAMORIOのスキャン
MAMORIOはiBeaconデバイスらしいので、iBeaconをスキャンする実装をしていきます。
BLEのライブラリはNimBLE-Arduinoを使います。
スケッチ例のBLE_Beacon_Scanner.inoがドンピシャで今回やりたいことなのでほぼそのまま参考にできそうですね。
#include <NimBLEDevice.h> #include <NimBLEBeacon.h> const int scanDuration = 5; NimBLEScan* bleScan; void setup() { NimBLEDevice::init(""); bleScan = NimBLEDevice::getScan(); bleScan->setActiveScan(true); bleScan->setInterval(100); bleScan->setWindow(99); } void loop() { const auto begin = ::millis(); auto foundDevices = bleScan->start(scanDuration, false); for (int i = 0; i < foundDevices.getCount(); ++i) { auto device = foundDevices.getDevice(i); // 見つかったデバイスであれこれする } bleScan->clearResults(); }
loop()
内のコメントが挿入されている部分で見つかったiBeaconが対象のMAMORIOだった場合にセントラルへ送信すればいいわけです。
なお、MAMORIOは
こちらのブログによるとUUID "b9407f30-f5f8-466e-aff9-25556b57fe6e"
とのこと。
無印MAMORIOの情報ですが、MAMORIO REでもUUIDは同じでした。
どの個体かを特定するのはMajorとMinorでするんだと思うんですが、手元には一つしかないのでよくわかりません。値段もお高いので今の所追加する予定もないので迷宮入りですね。ご存知の方はお教えいただけると助かります。
完成
iBeaconのスキャンとノード・セントラル間の通信ができるようになったので、あとは組み合わせて実装すれば完成です。
完成したコードはこちらになります。 github.com
今回セントラルはデータを集約するだけではなく表示も兼ねているのでちょっとごちゃっとしていますが、基本的には受け取ったデータを覚えて順次表示しているだけなので難しいところはないんじゃないかなと思います。
ノードを3つ用意して机上で動作確認してみました。なんとなくタグの移動を捉えていますね。
忘れ物タグ(mamorio)とM5Stackでプレゼンス管理のテスト。机上の距離だと検出がブレブレだけど、ちゃんと別の部屋に置けばそこそこ使い物になるかな?
— イナバ (@hollyhockberry) 2021年7月25日
人数が増えたらトラフィック増えて挙動が変わるかもだから実験したいけど予算が‥ #M5Stack #m5atom pic.twitter.com/gllznSBTaL
課題
なんとなく期待したような動作ができましたが、動作させてみると課題が見えてきちゃいました。
- BLEタグを全員に配るとお金が(ry
- ESP-NOWが届く範囲でM5ATOMを配置しなくてはならない
1.はこのシステムにどれだけの価値を見出すかにかかってくるので場合によっては問題にならなそうですが、2.は少し厄介です。 なんとか力技で解決できそうな気がしますが、別の方法を考えてみたいところです。
というわけでもうちょっと考えてみます(続く)