「Pythonを使ってアルプスのセンサネットワークモジュールでモーションデータの取得」で、python言語と使ってアルプスIoT Smart Moduleをアクセスしましたが、今回は、Raspberry Pi 3にNode.jsをインストールし、Node.jsのBLEモジュール「noble」を用いてアルプスIoT Smart Moduleの地磁気センサと加速度センサからモーションデータを取得します。
nobleモジュールは、Node.jsで動作するBLEモジュールで、次のようなBLEモジュールが提供されています。
- noble … Node.jsのBLEセントラル実装です。BLE機器を利用するもので、周辺のBLE機器をスキャンし、任意のGATTあるいはサービスに接続を行います
- bleno … Node.jsのBLEペリフェラル実装です。BLE機器そのもので定期的にアドバタイズを行う。BLEのペリフェラルデバイスを持っていなくてもNode.jsのモジュールblenoを利用することでアドバタイズを発信することができます。
nobleモジュールの詳細な仕様については、「sandeepmistry/noble」を参照してください。
アルプスIoT Smart Moduleへアクセスするための実行環境の作成
node.jsは、「Raspberry Pi 3にNode.jsのインストール」を参考にインストールしてください。
blenoが利用するBluetoothのプロトコルスタックのBlueZのインストールは次のコマンドで行ってください。
$ sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
blenoはnpmを利用してを次のようにインストールしてください。
$ npm install bleno
確認用のプログラム「nobletest.js」を次に示します。stateがpoweredOnのときにstartScanning()を呼んでいます。 アドバタイズを受信するとnoble.on()のdiscoverに来ますので、受信したペリフェラルの内容、 ここではlocalNameとサービスのUUIDを表示しています。
var noble = require('noble');
noble.on('stateChange', function(state) {
if (state === 'poweredOn') {
noble.startScanning();
} else {
noble.stopScanning();
}
});
noble.on('discover', function(peripheral) {
console.log('Found device with local name: ' + peripheral.advertisement.localName);
peripheral.connect(function(error) {
console.log('connected to peripheral: ' + peripheral.uuid);
});
});
次のコマンドで実行すると、アルプスIoT Smart Moduleのローカル名「SNM00」、UUID「28a183e15896」が取得できます。
$ sudo node nobletest.js Found device with local name: SNM00 connected to peripheral: 28a183e15896
エラーメッセージ「Error: Module version mismatch. Expected 48, got 57」の処置方法
次のように作成したプログラムを実行すると、モジュールのバーションが不一致であるというエラーメッセージが表示される場合があります。
$ sudo node nobletest.js
module.js:597
return process.dlopen(module, path._makeLong(filename));
^
Error: Module version mismatch. Expected 48, got 57.
at Error (native)
at Object.Module._extensions..node (module.js:597:18)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Object. (/home/pi/node_modules/bluetooth-hci-socket/lib/native.js:3:15)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10
この場合、npmが原因のようで、次のようにすでに作成されているディレクトリ「node_modules」を削除して、npmを再インストールします。
$ sudo rm -r node_modules $ npm install
nodeとnpmのバージョンを次に示します。
$ node -v v8.4.0 $ npm –version 5.4.2
アルプスIoT Smart Moduleからモーションデータの取得
モーションデータ取得プログラム「writenoble.js」を次に示します。アルプスIoT Smart Moduleのサービスやcharacteristicsを確認するためにダンプルーチンも追加しています。65行目から67行目で取得したcharacteristicsをそれぞれCustom1、Custom2、Custom3に登録しています。69行目から76行目まででアルプスIoT Smart Moduleの設定を行っています。モーションデータはnotifyにより通視されるので、79行目でモーションデータを受け取っています。Custom1、Custom2、Custom3については、「Sensor Network Module評価キットApplication Note Command Guide」のAppendix1 Service1 Databaseを参照してください。
var noble = require('noble');
console.log('noble');
function bytes2str(data){
var str = "";
for (var i = 0; i < data.length; i++){
str += ('00' + (data[i].toString(16))).slice( -2 );
}
return str ;
}
noble.on('stateChange', function(state) {
console.log('on -> stateChange: ' + state);
if (state === 'poweredOn') {
noble.startScanning();
} else {
noble.stopScanning();
}
});
noble.on('scanStart', function() {
console.log('on -> scanStart');
});
noble.on('scanStop', function() {
console.log('on -> scanStop');
});
noble.on('discover', function(peripheral) {
console.log('on -> discover: ' + peripheral);
noble.stopScanning();
peripheral.on('connect', function() {
console.log('on -> connect');
this.discoverServices();
});
peripheral.on('disconnect', function() {
console.log('on -> disconnect');
});
peripheral.on('servicesDiscover', function(services) {
console.log('on -> Service: ' + services);
//各サービスを登録
var GenericAccess = services[0];
var GenericAttribute = services[1];
var PRIMARY_SERVICE = services[2];
GenericAccess.on('characteristicsDiscover', function(characteristics) {
console.log('on -> GenericAccess:characteristicsDiscover: ' + characteristics);
});
GenericAttribute.on('characteristicsDiscover', function(characteristics) {
console.log('on -> GenericAttribute:characteristicsDiscover: ' + characteristics);
});
PRIMARY_SERVICE.on('characteristicsDiscover', function(characteristics) {
console.log('on -> PRIMARY_SERVICE:characteristicsDiscover: ' + characteristics);
//各characteristicsを登録
var Custom1 = characteristics[0];
var Custom2 = characteristics[1];
var Custom3 = characteristics[2];
Custom1.write(new Buffer([0x01, 0x00]), true);
Custom2.write(new Buffer([0x01, 0x00]), true);
Custom3.write(new Buffer([0x2F, 0x03, 0x03]), true);
Custom3.write(new Buffer([0x01, 0x03, 0x03]), true);
Custom3.write(new Buffer([0x04, 0x03, 0x01]), true);
Custom3.write(new Buffer([0x06, 0x04, 0x64, 0x00]), true);
Custom3.write(new Buffer([0x2F, 0x03, 0x01]), true);
Custom3.write(new Buffer([0x20, 0x03, 0x01]), true);
Custom1.notify(true);
Custom1.on('data', function(data, isNotification) {
console.log('Custom1 = ' + bytes2str(data));
});
Custom2.notify(true);
Custom2.on('data', function(data, isNotification) {
console.log('Custom2 = ' + data[0].toString(16));
});
});
//各サービスのcharacteristicをdiscover実施
GenericAccess.discoverCharacteristics();
GenericAttribute.discoverCharacteristics();
PRIMARY_SERVICE.discoverCharacteristics();
});
peripheral.connect();
});
実行した結果を次に示します。
$ sudo node writenoble.js
noble
on -> stateChange: poweredOn
on -> scanStart
on -> discover: {"id":"28a183e15896","address":"28:a1:83:e1:58:96","addressType":"public","connectable":true,"advertisement":{"localName":"SNM00","serviceData":[],"serviceUuids":[],"solicitationServiceUuids":[],"serviceSolicitationUuids":[]},"rssi":-72,"state":"disconnected"}
on -> scanStop
on -> connect
on -> Service: {"uuid":"1800","name":"Generic Access","type":"org.bluetooth.service.generic_access","includedServiceUuids":null},{"uuid":"1801","name":"Generic Attribute","type":"org.bluetooth.service.generic_attribute","includedServiceUuids":null},{"uuid":"47fe55d8447f43ef9ad9fe6325e17c47","name":null,"type":null,"includedServiceUuids":null}
on -> GenericAccess:characteristicsDiscover: {"uuid":"2a00","name":"Device Name","type":"org.bluetooth.characteristic.gap.device_name","properties":["read"]},{"uuid":"2a01","name":"Appearance","type":"org.bluetooth.characteristic.gap.appearance","properties":["read"]},{"uuid":"2a02","name":"Peripheral Privacy Flag","type":"org.bluetooth.characteristic.gap.peripheral_privacy_flag","properties":["read","write"]},{"uuid":"2a04","name":"Peripheral Preferred Connection Parameters","type":"org.bluetooth.characteristic.gap.peripheral_preferred_connection_parameters","properties":["read"]}
on -> GenericAttribute:characteristicsDiscover: {"uuid":"2a05","name":"Service Changed","type":"org.bluetooth.characteristic.gatt.service_changed","properties":["read","indicate"]}
on -> PRIMARY_SERVICE:characteristicsDiscover: {"uuid":"686a9a3b4c2c4231b8719cfe92cc6b1e","name":null,"type":null,"properties":["read","notify"]},{"uuid":"078ff5d63c9347f5a30c05563b8d831e","name":null,"type":null,"properties":["read","notify"]},{"uuid":"b962bdd15a77479793a1ede8d0ff74bd","name":null,"type":null,"properties":["writeWithoutResponse","write"]}
Custom1 = e01400000000c6830a0101000000000000000000
Custom1 = e01400000000c6830a0101000000000000000000
Custom1 = f214a60052ff7c0049f0e5ff6bfe6400310d0000
Custom1 = f214a9004dff7b004cf0e5ff11fec800310d0001
Custom1 = f214a6004cff7b0049f0f1ff20fe2c01310d0002
Custom1 = f214a90051ff800055f0e8ff1afe9001310d0003
Custom1 = f214aa004fff7c0049f0e2ff38fef401310d0004
Custom1 = f214a7004bff7b004ff0e5ff20fe5802310d0005
Custom1 = f214a70050ff7f004cf0e2ff38febc02310d0006
Custom1 = f214a9004fff7d004ff0e5ff23fe2003310d0007
Custom1 = f214a40052ff7c004cf0e5ff23fe8403310d0008
| uuid | name | uuid | name | properties |
|---|---|---|---|---|
| 1800 | Generic Access | 2a00 | Device Name | read |
| 2a01 | Appearance | read | ||
| 2a02 | Peripheral Privacy Flag | read write | ||
| 2a04 | Peripheral Preferred Connection Parameters | read | ||
| 1801 | Generic Attribute | 2a05 | Service Changed | read indicate |
| 47fe55d8447f43ef9ad9fe6325e17c47 | 686a9a3b4c2c4231b8719cfe92cc6b1e | read notify | ||
| 078ff5d63c9347f5a30c05563b8d831e | read notify | |||
| b962bdd15a77479793a1ede8d0ff74bd | writeWithoutResponse write |