まえおき
ちょっとアプリの対抗として BLE Peripheral を実装(エミュレーション)する必要があったのだが、iOS/AndroidだとMACアドレス周りのセキュリティ考慮や、Android同士だと相性が出るという不治の病などがあって、スマートフォンでやるのは無理があるなぁと思っていた。
また、現場で実際にアプリのテストをやろうとしたりすると、Macのエミュレーションとかも、パラでやるのに向いていないのでなんだかなぁという状態だった。
「Raspberry Pi 3 Model B」発表のお知らせ
https://raspberry-pi.ksyic.com/news/page/nwp.id/24
そんな折、Raspberry Pi 3先生にBluetooth 4.0/Wifiが内蔵されたということで、node.js/blenoあたりで実装すればハードの仕様差も少ないし調達も楽だしで現実的じゃん?と思った。
ただ、恥ずかしながらbleno自体初めてだし、Raspberry Pi 3でPeripheralキメたって話もあまり見つからなかったので、とりあえずミニマムで試してみた。
前提
- Raspberry Pi 3 Model B がある
- raspbianはインストール済み
- Linux raspberrypi 4.1.19-v7+ #858 SMP Tue Mar 15 15:56:00 GMT 2016 armv7l GNU/Linux
- /etc/debian_version : 8.0
- sudo apt-get update とかはあらかた終了
下ごしらえ
nodebrewでnode.jsをインストール
Macで慣れているという理由で、深く考えずにnodebrewをインストール
ここらへんを参照
Raspberry PiにnodebrewでNode.jsをインストールする
http://qiita.com/yuyakato/items/a1225154445520dc2db3
参照がうまく切り替わらなかったので一旦リブートしてからnodebrewでnode.jsをセットアップ
$ nodebrew install-binary v4.4.3
$ nodebrew use v4.4.3
bleno向けモジュール群
https://github.com/sandeepmistry/bleno の言う通りにセットアップ
$ sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
BLE Peripheralサンプル
blenoのサンプルをそのままコピペしてドーンでもいいのだけれど、何を実装しなきゃいけないかを把握したかったので、ミニマムな内容であえて一気通貫で書いてみた。
{
"name": "bleno-sample",
"version": "1.0.0",
"description": "bleno sample for rspi3",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"bleno": "^0.4.0"
}
}
var bleno = require('bleno');
var name = 'raspberrypi';
var serviceUuids = ['180F'];
var primaryService = new bleno.PrimaryService({
uuid: '180F',
characteristics: [
new bleno.Characteristic({
uuid: '2A19',
properties: ['read'],
value: new Buffer([100])
})
]
});
bleno.on('stateChange', function(state) {
console.log('stateChange: '+state);
if (state === 'poweredOn') {
bleno.startAdvertising(name, serviceUuids, function(error){
if (error) console.error(error);
});
} else {
bleno.stopAdvertising();
}
});
bleno.on('advertisingStart', function(error){
if (!error) {
console.log('start advertising...');
bleno.setServices([primaryService]);
} else {
console.error(error);
}
});
内容は、BatteryService/BatteryLevelのみの佗しい感じで。
サンプルの実行
デバイスいじるのでsudoで実行
$ sudo node index.js
stateChange: poweredOn
start advertising...
概ね良好そう。
結果
- node.jsのバージョンで最初ハマったけど、それ以外は概ね何もしなくても動いた。
- アドバタイズの停止やリブートなども試したが、iOS/Androidに通知されるPeripheralのMACアドレス(or UDID)はちゃんと固定になっている(当たり前だが)
- NEXUS9やNEXUS Playerで実装した時はAndroid -> Androidの接続が異常に遅かったが、そういうのは無く、iOSと同程度の速さでConnectできた。
- Androidで実装した時と違ってとにかく全体的に早い。