NodeJSでBLE通信ができるnobleライブラリでkonashiとつなげたメモ
先日の記事で、NodeJSでBLE通信ができるnobleライブラリでkonashiとつなげたメモです。
今回やりたいこと
今回やりたいことは以下のとおりです。
- Raspberry PiでBlueTooth関連のライブラリが入っていてBlueToothが使える状態が前提で進める。
- NodeJSでnobleライブラリを使って、konashiにアクセス。
- 1秒毎にLED ON/OFFしつつ、アナログ入力を計測する動きにする。
NodeJSでnobleライブラリを使う
早速使っていきます。Raspberry PiでBlueTooth関連のライブラリが入っていてBlueToothが使える状態が前提です。
NodeJSでは特に込み入ったことはなく、
npm install noble
でインストールします。
konashiを操作するためのUUID
konashiを操作するためのUUIDは本家のサイトを参考にします。
NodeJSに変数として保持しておきます。
var noble = require('noble');
// KONASHI自体のサービスID
var KONASHI_SERVICE_UUID = '229bff0003fb40da98a7b0def65c2d4b';
// 操作したいpinのID
var KONASHI_ANALOG_INPUT_PINID = '229b300803fb40da98a7b0def65c2d4b';
var KONASHI_PIO_SETTING_PINID = '229b300003fb40da98a7b0def65c2d4b';
var KONASHI_PIO_OUTPUT_PINID = '229b300203fb40da98a7b0def65c2d4b';
実際のコード
実際のコードは以下のとおりです。
オリジナルlittleBits Bluetooth(konashi)モジュールは、アナログ入力ピン AIO0、デジタル出力ピン PIO2で入出力をやり取りしています。
※このpinルールは開発中のものなので変更される可能性があります。そのときは読み替えましょう。
var noble = require('noble');
// KONASHI自体のサービスID
var KONASHI_SERVICE_UUID = '229bff0003fb40da98a7b0def65c2d4b';
// 操作したいpinのID
var KONASHI_ANALOG_INPUT_PINID = '229b300803fb40da98a7b0def65c2d4b';
var KONASHI_PIO_SETTING_PINID = '229b300003fb40da98a7b0def65c2d4b';
var KONASHI_PIO_OUTPUT_PINID = '229b300203fb40da98a7b0def65c2d4b';
// 各CHARACTERISTICSをUUIDから判断してcharacteristic格納する変数
var KONASHI_CHARACTERISTICS_ANALOG_READ;
var KONASHI_CHARACTERISTICS_PIO_SETTINGS;
var KONASHI_CHARACTERISTICS_PIO_OUTPUT;
// LED ON/OFF
var led_toggle = false;
// 状態がパワーONだったらスキャンに移行
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');
});
// discover 機器が発見されたら
noble.on('discover', function(peripheral) {
console.log('on -> discover: ' + peripheral);
// まずスキャンをとめる
noble.stopScanning();
// KONASHI接続時のイベント
peripheral.on('connect', function() {
console.log('on -> connect');
this.discoverServices();
});
// KONASHI切断時のイベント
peripheral.on('disconnect', function() {
console.log('on -> disconnect');
});
// 見つけたサービス(機器)へのアクセス
peripheral.on('servicesDiscover', function(services) {
for(i = 0; i < services.length; i++) {
// サービスがKONASHI_SERVICE_UUIDと一致した時だけ処理
if(services[i]['uuid'] == KONASHI_SERVICE_UUID){
// サービスのcharacteristic捜索
services[i].on('includedServicesDiscover', function(includedServiceUuids) {
console.log('on -> service included services discovered [' + includedServiceUuids + ']');
this.discoverCharacteristics();
});
// characteristic取得イベント
services[i].on('characteristicsDiscover', function(characteristics) {
// characteristics配列から必要なCHARACTERISTICSをUUIDから判断してcharacteristic格納
for(j = 0; j < characteristics.length; j++) {
// アナログ入力 characteristic
if( KONASHI_ANALOG_INPUT_PINID == characteristics[j].uuid ){
console.log("KONASHI_CHARACTERISTICS_ANALOG_READ exist!!");
KONASHI_CHARACTERISTICS_ANALOG_READ = characteristics[j];
}
// PIO設定 characteristic
// デジタル入出力を担当するPIO全部に出力するようにお願いする
if( KONASHI_PIO_SETTING_PINID == characteristics[j].uuid ){
console.log("KONASHI_PIO_SETTING_PINID exist!!");
KONASHI_CHARACTERISTICS_PIO_SETTINGS = characteristics[j];
// PIOを全部出力に空けとく 11111111(255) ex) 11111110(254)
KONASHI_CHARACTERISTICS_PIO_SETTINGS.write(new Buffer([255]), true);
}
// デジタル出力 characteristic
if( KONASHI_PIO_OUTPUT_PINID == characteristics[j].uuid ){
console.log("KONASHI_PIO_OUTPUT_PINID exist!!");
KONASHI_CHARACTERISTICS_PIO_OUTPUT = characteristics[j];
}
}
// 実際の点滅させるところ
setInterval(function(){
// ANALOG_READ
/*
入力を監視 0~1.3でくる(0V~1.3Vという意味)
・ボタンモジュールを押す場合
ON = 0.000 / OFF = 1.3 みたいにくる 1.0あたりをしきい値にするといい
・DIMMERつまみモジュールの場合
ツマミひねると、0~0.23~0.56~0.89~1.12~1.3 みたいにくる
*/
KONASHI_CHARACTERISTICS_ANALOG_READ.read(function(error, data) {
if (data) {
console.log( 'value:' + (data[1] + data[0]*256)/1000 );
}
});
// 実際の点滅
// DEGITAL OUTPUT PIO2
if(led_toggle){
// LED ON
console.log("LED ON");
KONASHI_CHARACTERISTICS_PIO_OUTPUT.write(new Buffer([255]), true);
} else {
// LED OFF
console.log("LED OFF");
KONASHI_CHARACTERISTICS_PIO_OUTPUT.write(new Buffer([0]), true);
}
// LED ON/OFFの反転
led_toggle = !led_toggle;
}, 1000);
});
services[i].discoverIncludedServices();
}
}
});
// 機器との接続開始
peripheral.connect();
});
こちらで、アナログ入力が計測でき、デジタル出力でLEDなどOUTPUTモジュールをくっつけると繰り返しON/OFFされます。
Raspberry Piで起動した時の様子です。
1秒毎にLED ON/OFFしつつ、アナログ入力を計測してますね。
アナログ入力についてはスライドレバー(SLIDE DIMMER)モジュールでどうなるか図で起こしてみました。
つまり、1.3Vを0%~100%で値が来るようになっています。中間50%が0.65あたりになります。
やるとしてチェックタイミングも今の1秒ですと滑らかではないでしょう。0.2秒程度でやれば、きっとスムーズに度合いを伝えることも可能そうです。
また、ボタンモジュールの場合は0.0と1.3になるので、自分が判定する場合は、50%である0.65あたりをしきい値にON/OFFを判断しています。
かなり泥臭いことをやっている+参考記事
本コードかなり泥臭いことをやっているいます。BLEもkonashiもよくわからないまま進めていたので、まず確実性を高めるためにBLE上の全機器を捜索。しかも、konashiをみつけても油断せず、characteristicsについても全部捜索。該当するものを変数に保持して使う挙句に、PIOについても、とりあえず255を与えて全PINを出力に向けてます。
このあたり、もう少し扱いに慣れてくれば、シンプルにしていきたいところです。
そして、nobleの文献は私としては以下の記事がとても参考になりました。
- 新ファーム機能!EdisonでBLE機器を制御してみた | TONGARISM.COM
- 基礎的にはとてもいいコードだけど、Edisonでやる話なのでkonashiに読み替えないとややハマる
- BLEのアドバタイズを受信する - wonder gadget
- すごくシンプルでありがたい
- nobleでkonashi(koshian)のanalog readの値を読む
- アナログ入力のヒントに
- akita - PukiWiki「
/diary/index.php?akita#cdb50a84」- 「14/11/12: Node.js+nobleでkonashiをつつく」のあたりに、Bufferに255(11111111)を出してPIO SETTINGとPIO OUTPUTする方法が書かれている
ありがたやありがたや。
余談:いろいろBLE接続くり返していると、デジタル出力だけうまくいかないことがある(原因はまだわからず)
これ結構ハマりました。
konashi自体なのかBLE規格のクセかもしれませんが、konashi littleBitsに対していろいろBLE接続くり返していると、デジタル出力だけうまくいかないことがあります。
BLEの専有と解放がうまくいってない予感。 まあ、いろんな機器で取得してみてればそういうこともありますね。
アナログ入力はだいたい取れてるだけに、LEDがつかないわけで、あれー!?コードが悪い???ってなります。
その時は、おちつきましょう。konashiを一旦電源外してOFFにしてリセットしましょう。そうすれば大丈夫でした。
konashi littleBitsの場合はモジュールを一度パチっとはずして付け直します。
littleBitsモジュールにすると、こうやってプラスマイナスを気にせず、気軽に接続を外せて試せるところが素敵なところですね。
また、まれにkonashi littleBitsモジュールの先のOUTPUTモジュールの接触不良ってこともあるので、そのあたりはやっぱり付け直しつつトライアンドエラーで行きましょう。
基本はkonashiを一旦電源外してOFFにしてリセットで、だいたいなんとかなります。
実戦的には、OFFリセット後なるべく単一の機器(この場合Raspberry Piなど)でkonashiとの確保しくというのも大切そうです。
余談:noble以外にもblenoっていうのがあるけど?
npmライブラリ群で似た名前があったりするのはよくあるのですが、よい記事を見つけました。
しかもnodeのモジュールがある。作者もbleaconと同じ人。
※nobleもblenoも作者が一緒!
一緒の方らしいです。すげー。
(他にも気になるライブラリあるなー)
おわりに
いかがでしたでしょうか。
これができると、Raspberry PiがBLEの接続基地として使いつつ、SocketIOサーバーを立てればリアルタイムに色々なことが出来そうです。
それでは、よきRaspberry Pi+NodeJS+BlueTooth Low Energy+littleBits Lifeを!





