サマリ
遠隔地のBLEデバイスをnobleで動かせるよ with obniz-noble
背景
最近BLE周りしか触ってないじゃないか!?っていうぐらいBLEのことばっかやってますが、先日、obniz-nobleなるものをリリースしました
どういうものかというと、**nobleでobnizを操作しようよ!**っていうものです。
node.jsでBLEといえばnoble一択、というほど強いんですが、このnoble、なんとnodejsのバージョン8でしか動きません。
正確にはnobleはバージョン依存していないのですが、nobleが使ってるライブラリがバージョン依存で動きません。nobleのgithubも2年以上放置されてますし、メンテナンスする予定ないんですかね・・・
いろいろなかたがこれに対応してnode12でも動くnobleとかを作っていたりシますが、ここはやっぱりobnizでしょ!ということでobnizで動くnobleを作ったのがobniz-nobleです
構成
会社とか、外部においたPC(もしくはクラウド)でnobleを動かし、家においたobnizを通じてBLEデバイスをコントロールします
nobleのリプレイス方法
いろんなプロジェクトやライブラリでnobleが使われているので、それをobniz-nobleにリプレイスしてみます。
通常のリプレイス方法
READMEに書いてありますがこの1行を2行に変えるだけです。
//before
cosnt noble = require("noble");
//after
const obnizNoble = require("obniz-noble")
cosnt noble = obnizNoble("OBNIZ_ID_HERE");
・・・でもちょっとまってください、直接noble使うときは自分のコード内にcosnt noble = require("noble");
があるからいいですが、他人のライブラリの中にあるときはどうしましょう??
そんなときはyarnの選択的な依存関係の解決をつかいます。
yarnの選択的な依存関係の解決
npmを使ってる人が多いと思いますが、その上位互換のyarnというものがあり、
いろんな便利機能が実装されています。
そのうちの1つがyarnの選択的な依存関係の解決なのですが、この機能ちょっとずるくて、npm installで入るパッケージが使用しているライブラリをひっそりと入れ替えることができます。
ちょうどnode-linkingというのがnoble使っていたのですが、こんなふうに入れ替えることができます
node-linkingはnobleを使ってるつもりなのに、いつの間にかobniz-nobleをつかっていた!?ということができるわけです。
単純なnobleのリプレースだとobnizIdを入れるところがないので、obniz-nobleをラップしたnoble-replaceフォルダを作ってreplaceします.
ProjectRoot
├─┬ main@1.0.0
│ └─┬ node-linking@0.4.0
│ └── @abandonware/noble@>=1.9.2-5 // <- ここはnoble-replaceで置換される
│
└─┬ noble-replace@1.0.0
└── obniz-noble@2.0.0
具体的なフォルダ構成はこちらのgithubにおいていますが、特徴的なところはmain/package.jsonです。
{
.
.
.
"dependencies": {
"node-linking": "^0.4.0"
},
"resolutions": {
"node-linking/@abandonware/noble": "file:../noble-replace"
},
}
このように書くことでnode-linking
が使ってる@abandonware/noble
のかわりにnoble-replace
を読み込みます。
noble-replaceの中にはindex.jsで
const obnizNoble = require("obniz-noble");
module.exports = obnizNoble("86014802");
この2行だけのファイルを置いています。
動かしてみた
node-linkingのREADMEに書いてあるプログラムをデバイス名だけ変更して実行してみます。
// node-inking をロードし、`Linking` コンストラクタオブジェクトを取得
const Linking = require('node-linking');
// `Linking` オブジェクトを生成
const linking = new Linking();
// `LinkingDevice` オブジェクト
let device = null;
// `LinkingDevice` オブジェクトを初期化
linking.init().then(() => {
// 名前が `Tukeru` で始まるデバイスを 5 秒間発見を試みる
return linking.discover({
duration: 5000,
nameFilter: 'Sizuku'
});
}).then((device_list) => {
if(device_list.length > 0) {
// 発見したデバイスを表す `LinkingDevice` オブジェクト
device = device_list[0];
// デバイス名
let name = device.advertisement.localName;
console.log('`' + name + '` was found.');
// デバイスに接続
console.log('Connecting to `' + name + '`...');
return device.connect();
} else {
throw new Error('No device was found.');
}
}).then(() => {
console.log('Connected.');
console.log('This device suports:');
for(let service_name in device.services) {
if(device.services[service_name]) {
console.log('- ' + service_name);
}
}
// デバイスを切断
console.log('Disconnecting...');
return device.disconnect();
}).then(() => {
console.log('Disconnected');
}).catch((error) => {
console.log('[ERROR] ' + error.message);
console.error(error);
});
実行したら無事うごきました!
BLEデバイスは手元じゃなくてもobnizの近くにあれば発見できます
`Sizuku_tha0142155` was found.
Connecting to `Sizuku_tha0142155`...
Connected.
This device suports:
- deviceName
- led
- battery
- temperature
- humidity
Disconnecting...
Disconnected
↑これがSizuku_tha0142155です
ライブラリの中で使われてるライブラリをひっそり入れ替える事ができるのはすごいですね!
まとめ
obnizのこと書いてるのかnobleのこと書いてるのかyarnのこと書いてるのかよくわからなくなりますが、obnizでもnobleつかえるよ!って話でした