RaspberryPi3でMAMORIOの信号を受信する

RaspberryPi3でMAMORIOの信号を受信する

秋にいろいろハッカソンに参加したので、来年また使うかもしれないので、その時のメモをまとめていきます。といっても2-3件ですけどね。

先日あった【Nagoya Hackathon】で自分のチームでは位置情報を取得する必要があったので、技術協力でお越しになっていたMAMORIOさんが出している【MAMORIO】を使用しました。

mamorio.jp

「なくすを、なくす」というコンセプトはシンプルで素敵です。

MAMORIOが手元から離れると、いつどこで失くしたかをお知らせ。あなたのスマートフォンで、大切なものを見守れます。

Android版、iOS版のSDKも準備されていますのでスマートフォンでの開発も可能になっています。 ただ、自分はAndroidの開発をしたことがないので、ハッカソンという早期のプロトタイプ開発の場面では全くダメ人間となってしまいます。 なんとかせねばということで、AndroidStudioのインストールをしたりSDKをダウンロードしていたのですが、隣のチームでも同じような開発をしていたので 聞いてみたところ「iBeaconでいけるっすよ」という天の言葉が。

ということで、2日間あるハッカソンの1日目が終了した深夜。ネットをググりながらコーディングをしました。ただ、この作業中にRaspberryPi3の環境のBluetoothの環境の壊してしまったので、 深夜にもかかわらずRaspbianの新規インストール~Bluetooth設定の確認~Node.jsのインストール~MAMORIOを使ったLチカまで数時間でかたずけなければならず正直泣きたかったです。2日目はかなりポンコツになっていたと思います。

基本スペックはこんな感じです。

スペック
サイズ 縦35.5mm×横19mm×厚さ3.4mm
重さ 3g
電池 リチウム電池 / 最大で1年間ご利用が可能(ご利用環境によって短くなる場合がございます。)電池交換プログラムあり(有償)
保証期間 3ヶ月
通信方法 Bluetooth4.0(Bluetooth Low Energy)
有効距離 約30m
価格 3,780円(税込)
カラー BLACK / RED / BLUE / YELLOW / GRAY

Node.jsでiBeaconの信号をキャッチする

こちらのページを参考にしました。 qiita.com

npmbleaconというパッケージをインストールすれば信号のキャッチが可能になるようです。

RaspberryPi3ではBluetoothは標準で対応しているので、ハードの設定に関してはあまり気にしなくて良いようです。RaspberryPi Zero Wも調べてみたいです。

RaspberryPi3のBLEの設定

設定するRaspberryPiのリビジョンとしては以下を使用しています。(イメージファイルは2017-09-07-raspbian-stretch.imgを使用)

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.1 (stretch)
Release:        9.1
Codename:       stretch

npmを使用して``bleacon```をインストールする

bleaconはNode.jsのモジュールなのでNode.jsの比較的新しいバージョンを使用できるように設定をします。

Node.jsの設定に関しては過去記事とかを参考にしてください。

uepon.hatenadiary.com

$ sudo apt-get update
$ sudo apt-get install libbluetooth-dev
$ npm install bleacon

これでインストールできました。(beeaconはリビルドが行われるのですこし時間かかります)

bleaconを使用してみる

先程の参考サイトをみてコードを書いてみます。

var Bleacon = require("bleacon");
Bleacon.startScanning();
Bleacon.on("discover", function(bleacon) {
        console.dir(bleacon);
        if(bleacon.rssi > -75){
                console.log("近いです")
        }
        console.log(bleacon.proximity)
});

RaspberryPiで取得したiBeaconのrssiの値が-75 より大きい場合には近いですという表示をします。 その後にはproximityの状態も表示しています。

では実行してみましょう。実行するにはsudoが必要で付けないと以下のような警告が出ます。

【sudoのないエラー】

$ node beacon_discover.js
noble warning: adapter state unauthorized, please run as root or with sudo
               or see README for information on running without root/sudo:
               https://github.com/sandeepmistry/noble#running-on-linux
bleno warning: adapter state unauthorized, please run as root or with sudo
               or see README for information on running without root/sudo:
               https://github.com/sandeepmistry/bleno#running-on-linux

【成功例】

$ sudo node  beacon_discover.js
{ uuid: 'b9407f30f5f8466eaff925556b57fe6e',
  major: XXXX,
  minor: YYYYY,
  measuredPower: -75,
  rssi: -77,
  accuracy: 1.104503890181195,
  proximity: 'near' }
near
{ uuid: 'b9407f30f5f8466eaff925556b57fe6e',
  major: XXXX,
  minor: YYYYY,
  measuredPower: -75,
  rssi: -58,
  accuracy: 0.4296139514262019,
  proximity: 'immediate' }
近いです
immediate

取得したrssiの値でも良いのですが、proximityの値でみたほうが処理は楽に記述できるかもしれません。proximityにはimmediate(近接)、near(近い)、far(遠い)の値があるようです。 また、取得した値にはmajorminorがありますが、この値が各タグごとに異なる値になりますので、複数タグがある場合にはこの値をつかって個体の判別をします。(ハッカソンでは複数になることが多いので事前にわかっていると楽です)

MAMORIOが近接したらLEDを光らせる

先程のソースを改良してGPIOを使ったLチカを行います。簡単のためにgpioファイルに値を書き込んでGPIOの制御を行っています。

var fs = require('fs');

var dir = '/sys/class/gpio';
var gpio2 = dir + '/gpio2';
var count = 0;

fs.writeFileSync(dir + '/export', 2); // 2ピン
fs.writeFileSync(gpio2 + '/direction', 'out'); // 出力に設定

function flashLED() {
        count++;
        fs.writeFileSync(gpio2 + '/value', count % 2);
        if (count < 14) {
                setTimeout(flashLED, 500);
        }
}

process.on('SIGINT', () => {
        console.log('Got SIGINT. ');
        fs.writeFileSync(gpio2 + '/value', 0);
        fs.writeFileSync(dir + '/unexport', 2); // 処理の終了
        process.exit(1);
});

var Bleacon = require("bleacon");
Bleacon.startScanning();
Bleacon.on("discover", function(bleacon) {
        console.dir(bleacon);
        if((bleacon.major == "XXXX") && (bleacon.minor == "YYYYY")){
                if(bleacon.proximity == "immediate"){
                        console.log("my_tag_near");
                        count=0;
                        flashLED();
                }
        }
        console.log(bleacon.proximity)
});

今回は特定のタグが近接(proximityの値がimmediateになったら)したらLチカ(点滅)を行うようにしています。また、途中でCtrl+Cを押してしまうとgpioの状態が不定になり、次回の起動が失敗してしまうので、SIGINTシグナルをキャッチして終了処理を入れています。

$ sudo node  beacon_discover_led.js
{ uuid: 'b9407f30f5f8466eaff925556b57fe6e',
  major: XXXX,
  minor: YYYYY,
  measuredPower: -75,
  rssi: -70,
  accuracy: 0.7799771419043033,
  proximity: 'near' }
near
{ uuid: 'b9407f30f5f8466eaff925556b57fe6e',
  major: XXXX,
  minor: YYYYY,
  measuredPower: -75,
  rssi: -59,
  accuracy: 0.45150441487569565,
  proximity: 'immediate' }
my_tag_near
immediate
{ uuid: 'b9407f30f5f8466eaff925556b57fe6e',
  major: XXXX,
  minor: YYYYY,
  measuredPower: -75,
  rssi: -72,
  accuracy: 0.8614877874857131,
  proximity: 'near' }
near
^CGot SIGINT.

おわりに

無事にMAMORIOを検知して制御を行うことができました。タグの検出周期は約5秒ぐらいなので、即応性はそれほどという感じですが、この小ささであればとてもいいかなと思います。個人的にはもう少しお安い感じだといいんですが…2年程度持つとか、スイッチのオンオフがあるとかなら即買いかなと思います。ただ、これくらい削ぎ落としても「いいなあ、ほしいなあ」と思える商品だなとは思います。