#IoT #試作開発 #Nodejs #npm #BLE #BluetoothLowEnergy #SakeTamu #ヤロテク
日々、IoTを妄想しているOKスタイルです!
2018年11月に試作基板が完成し、そのファーム、筐体製作の前に基板に載せたBLEとの通信実装が目下の課題です。
試作開発:試作デバイス(基板)とのBLE通信をする
◉ 開発環境
・MacBook Air (11-inch, Early 2015) OS X Yosemite バージョン10.10.5
・Homebrew 1.9.3
・Nodebrew v4.7.2 → Node.jsのバージョン管理のために使用
・Node.js v4.7.2 → 最新バージョンではエラーになるため、古いバージョンを使用
・npm 2.15.11
開発環境は最小限(ストレージ不足に悩んでます(^^;;)でなんとかやりくりしています。
◉ 開発でやりたいこと(ゴール)
・Macのターミナル上で、指定したBLEデバイスへのアクセスを確認する
◉ 開発手順
①開発環境構築
結論を先に言ってしまいますが、今回の開発の肝になったのが、開発環境でした。
実は、上記の開発環境はうまく実装できた時の開発環境です。当初は下記の開発環境でした。
・MacBook Air (11-inch, Early 2015) OS X Yosemite バージョン10.10.5
・Homebrew 1.9.3
・Python 3.6.1 | Anaconda 4.4.0
・Node.js v10.15.0
・npm 2.15.11
その中ではエラーが2つありました。
エラー1: ()なしの print で syntax error
Python2でないと動かないのに、Python3で実行した時にでるエラーです。
対策: Anaconda のバージョンを下げて、Python2の実行環境を構築
→結果的にはMacは元からPython2の環境があるので、Anacondaはアンインストールしました。
エラー2に大分、手こずった中で余計なものは消していったからです(^^;;
エラー2: Error: Cannot find module ‘xpc-connection’
Node.jsを実行すると、モジュール「xpc-connection」がない!と数十回は怒られました。
その度に原因を推測して、環境を変えては、実行しての繰り返しをしました。
対策: Node.jsのバージョンを8より古いバーションに下げて、Node.jsファイルを実行
対策に辿りつくきっかけになった情報を参考までに貼り付けます。
(参考)https://github.com/line/line-simple-beacon/issues/7
上の参考URLのところに下記文言がありました。
I have tried it and found out it has the problem with node 10
internal/modules/cjs/loader.js:583
throw err;
^
Error: Cannot find module 'xpc-connection'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
at Function.Module._load (internal/modules/cjs/loader.js:507:25)
at Module.require (internal/modules/cjs/loader.js:637:17)
at require (internal/modules/cjs/helpers.js:20:18)
at Object.<anonymous> (/Users/Evan/src/go/src/github.com/kkdai/line-simple-beacon/tools/line-simplebeacon-nodejs-sample/node_modules/bleno/lib/mac/highsierra.js:10:21)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
So, I try to downgrade to node@8 it works well.
エラーの詳細については、ココ(https://teratail.com/questions/170332#reply-256070)に書いたので見てみてください。
② BLEデバイス情報の確認
開発環境ができたら、BLE通信プログラムを作成するのに必要なBLEデバイス情報を確認します。
<BLE情報確認項目>
⑴ サービスUUID
⑵ キャラクタリスティックUUID
上記2項目があれば、BLEデバイスを探すことができて、デバイス内のキャラクタリスティックにアクセスしてデータをやりとりすることが可能になります。
ちなみに私は下記2つのアプリを使って、BLEデバイスの情報を確認しました。
(参考)BLEデバイス情報を確認するBLEデバッグ用のアプリケーション
Bluetooth Low Energy のデバイスをスキャン、接続し、提供するサービス/キャラクタリスティックを確認 することができます。
デバイス情報をCloneして、Virtual Peripheralsを作成して擬似BLEデバイスになることもできます。
Bluetooth Low Energy のデバイスをスキャン、接続し、提供するサービス/キャラクタリスティックを確認 することができます。
③ Node.jsむけBLEライブラリnobleのインストール
nobleはNode.js向けのBLEライブラリで、MacやWindowsなどのPC、Raspberry PiなどのデバイスをBLEのCentralにすることができます。
//ディレクトリの作成と移動
mkdir ble_central
cd ble_central
//空のファイルの作成
touch app.js
//プロジェクト初期化
npm init -y
//nobleライブラリのパッケージをインストール
npm i --save noble
BLEデバイスにアクセスするための準備はこれで完了です!
④app.jsファイルにコマンドを記述
それではファイルにコマンドを記述していきます。
先ほど②で確認したBLEデバイスにアクセスするためのBLEデバイス情報(サービスUUIDとキャラクタリスティックUUID)を使っていきます。
'use strict';
const noble = require('noble');
const serviceuuid = `a6ad91bd376e465f8c6c460fd3e15038`;
const charauuid = `80d881a61ab347f08c752c31eac31f43`;
//キャラクタリスティックにアクセスしてデータやりとり
const accessChara = (chara) => {
console.log('-----Start GATT Access-----')
chara.notify(true, (err) => {
if (err) {
console.log('listen notif error', err)
} else {
console.log('listen notif')
}
});
chara.on('data', (data, isNotif) => {
const jsonStr = data.toString('utf-8');
const jsonData = JSON.parse(jsonStr);
console.log(jsonData);
});
}
//BLE deviceをさがす。
const discovered = (peripheral) => {
console.log(`BLE Device Found: ${peripheral.advertisement.localName}(${peripheral.uuid}) RSSI${peripheral.rssi}`);
if(peripheral.advertisement.localName === 'SAKETAMU'){
noble.stopScanning();
console.log('device found');
console.log(`service discover...`);
peripheral.connect(error => {
if (error) {
console.log("connection error:", error)
} else {
console.log("device connected");
}
peripheral.discoverServices([],(err, services) => {
if (error) {
console.log("discover service error", error)
}
console.log('discover service');
services.forEach(service => {
if(service.uuid === serviceuuid){
service.discoverCharacteristics([], (error, charas) => {
console.log('discover chara');
charas.forEach(chara => {
if(chara.uuid === charauuid){
console.log("found chara: ", chara.uuid)
accessChara(chara);
}
});
});
}
});
});
});
}
}
//BLEスキャン開始
const scanStart = () => {
noble.startScanning();
noble.on('discover', discovered);
}
if(noble.state === 'poweredOn'){
scanStart();
}else{
noble.on('stateChange', scanStart);
⑤app.jsの実行
最後に「app.js」ファイルを実行してBLEデバイスにアクセスできるか確認していきましょう!
node app.js
実行後、下記のような表示が出たらBLEデバイスへのアクセスは成功です!
BLE Device Found: SAKETAMU(000000aaaa00000a0a00aa0aa000a00a) RSSI-37
device found
service discover...
device connected
discover service
discover chara
found chara: 88a888a88aa888a88a888a88aaa88a88
-----Start GATT Access-----
listen notif
まとめ
エラーの潰しこみで時間がかかってしまいましたが、一歩ずつ進めていきます!
少しでも開発のヒントや参考になれば幸いです。
開発のやり方もいろいろなパターンあると思いますので、こうやってみたらいいのでは!?というご意見もお待ちしています!
それでは最後まで読んでいただき、ありがとうございましたm(_ _)m
次は、複数デバイスへのアクセスと値の取得にチャレンジします!