1. 利用機器
1.1. Raspberry Pi 3
- Raspberry Pi 3 Model B - Raspberry Pi
- OS: Raspbian
- Language: Node.js v8.8.1
1.2. MAMORIO
MAMORIO | あなたの大切なものを守る世界最小クラスの紛失防止デバイス
2. 利用ライブラリ
2.1. noble
- noble
- Version: 1.8.1
- node で ble 使う時のデファクトスタンダード?
3. mamorio (ibeacon) のアドバタイジングパケットの中身
3.1. ibeacon
ibeacon のアドバタイジングパケットについては、クラスメソッドさんのブログが分かりやすかったので、引用させていただく。
下記は、iBeaconのアドバタイズパケットです。XX以外の部分は、固定です。
値 | 内容 |
---|---|
1A | AD Structureの長さ |
FF | ADのタイプ |
4C 00 | 企業識別子 0x004C(Apple) |
02 | iBeacon 識別子 |
15 | iBeacon 識別子 |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | UUID |
XXXX | major |
XXXX | minor |
XX | Power |
引用元: iBeaconのスキャナーを作ってみた | Developers.IO
3.2. mamorio
mamorio のアドバタイジングパケットについては、もみあげあしめさんのブログが分かりやすかったので、引用させていただく。
Advertising Packet は Length, Type, Data の形式になっている。
MAMORIOから取得できたAdvertising Packetは下記とおり。※0xは省略
Length | Type | Data |
---|---|---|
02 | 01 | 04 |
1A | FF | 4C 00 02 15 B9 40 7F 30 F5 F8 46 6E AF F9 25 55 6B 57 FE 6E BE 49 F7 47 B5 |
Type の割り当ては Generic Access Profile | Bluetooth Technology Website によると下記とおり。
Typeの値 | 割り当て内容 |
---|---|
0x01 | «Flags» |
0xFF | «Manufacturer Specific Data» |
«Manufacturer Specific Data»の中身
値 | 割り当て内容 | 備考 |
---|---|---|
0x4C00 | Company | Apple, Inc. Company Identifiers |
0x02 | Beacon | -- |
0x15 | Length | 21Byte |
iBeacon本体のデータ構造
値 | 割り当て内容 | 備考 |
---|---|---|
b9407f30-f5f8-466e-aff9-25556b57fe6e | UUID | 企業・組織の識別 |
0xBE49 | Major | iBeaconのグループ |
0xF747 | Minor | グループ内のID |
0xB5 | RSSI | 1m 地点で -75dB |
引用元: MAMORIOが届いたので解析したかった - もみあげあしめ
4. 実装
4.1. ソースコード
'use strict';
const noble = require('noble');
noble.on('stateChange', function (state) {
if (state === 'poweredOn') {
console.log("noble.startScanning()");
//noble.startScanning(); // any service UUID, no duplicates
noble.startScanning([], true); // any service UUID, allow duplicates
} else {
console.log("noble.stopScanning()");
noble.stopScanning();
}
});
noble.on('discover', function (peripheral) {
var rssi = peripheral.rssi;
var buf = peripheral.advertisement.manufacturerData;
if (typeof buf !== "undefined") {
// mamorio (ibeacon) かどうかを判定するための値をセット。
// 16進数の方がイメージしやすかったので下記実装にしている。
var checkbuff = new Buffer([parseInt("4c", 16), parseInt("00", 16), parseInt("02", 16)]);
if (0 == buf.compare(checkbuff, 0, 3, 0, 3)) {
console.log(buf.toString('hex') + " " + rssi);
}
}
});
4.2. 説明
4.2.1. スキャン
noble のサンプルコードそのままだけど、前者だと、UUID は重複しないでスキャン、とのことなので、今回の期待動作ではない。実際に、はじめは理解せずに、前者にしていて、アドバタイズがバンバンされているはずなのになー、なんでだろう?と考え込む時間を浪費。。
後者の実装にしたら、バンバン、スキャンされだした!これだよ、これ、やりたかったのは。
noble.startScanning(); // any service UUID, no duplicates
noble.startScanning([], true); // any service UUID, allow duplicates
4.2.2. mamorio の判定
Manufacturer Data が、 4c00 02
かどうかしか見ていないので、 mamorio かどうかというより、ibeacon かどうかの実装か。
// mamorio (ibeacon) かどうかを判定するための値をセット。
// 16進数の方がイメージしやすかったので下記実装にしている。
var checkbuff = new Buffer([parseInt("4c", 16), parseInt("00", 16), parseInt("02", 16)]);
if (0 == buf.compare(checkbuff, 0, 3, 0, 3)) {
console.log(buf.toString('hex') + " " + rssi);
}
以上。