News

試作デバイスとのBLE通信実装:Node.jsむけBLEライブラリnoble実行

  • このエントリーをはてなブックマークに追加
  • Pocket
  • LINEで送る
20190131_試作デバイスとのBLE通信実装(商品開発テックテック日記)

#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デバッグ用のアプリケーション
LightBlue®Explorer

LightBlue®Explorer 

Bluetooth Low Energy のデバイスをスキャン、接続し、提供するサービス/キャラクタリスティックを確認 することができます。
デバイス情報をCloneして、Virtual Peripheralsを作成して擬似BLEデバイスになることもできます。

CySmart

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

次は、複数デバイスへのアクセスと値の取得にチャレンジします!

  • このエントリーをはてなブックマークに追加
  • Pocket
  • LINEで送る

コメントを残す

*

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください