LoginSignup
3
1

More than 3 years have passed since last update.

最近のNode.jsでBLEのアドバタイジングパケットを補足してみる

Last updated at Posted at 2021-04-03

はじめに

nobleが虫の息というか、もう息の根を止めてあげていい状態なので他に移行しなければならない。さて次は何がいいだろうかと調べてみてラズパイ用途で行き当たるのは以下の2つくらいじゃないだろうか。

node-ble
node-bluez

node-bleが開発が活発に見えるが、node-bluezもシンプルでよさげ。両方やってみることにする。試した環境はこちら

uname -a
Linux raspberrypi.local 5.8.0-1016-raspi #19-Ubuntu SMP PREEMPT Tue Feb 9 20:12:43 UTC 2021 aarch64 aarch64 aarch64 GNU/Linux

前準備

node-bluzが依存するライブラリとnode.jsをインストールする

sudo apt install -y libglib2.0-dev libdbus-1-dev
sudo apt install -y nodejs npm

ここで入るnodeのバージョンは12.xで古い。nで最新を入れる

sudo npm i -g n
sudo n latest
sudo apt remove --purge nodejs
sudo apt autoremove

/usr/local/bin にlatest versionが入るのでパスを通しておく

~/.profile
export "$HOME/usr/local/bin:$PATH"
source ~/.profile
node -v
v15.13.0

TypeScriptの準備

mkdir -p work && cd $_
npm init -f
npm i -S typescript ts-node bluez node-ble sleep-promise
npx tsc --init

Promiseまわりのエラー回避で tsconfig.jsonのlibを以下にする

tsconfig.json
lib: ["ES2015", "dom"],

node-bleでやってみた

node-ble.ts
import { createBluetooth } from 'node-ble';
import sleep from 'sleep-promise';

const main = async () => {
  const { bluetooth, destroy }: any = createBluetooth();
  const adapter: any = await bluetooth.defaultAdapter();
  if (! await adapter.isDiscovering()) {
    console.log('Discovering:');
    await adapter.startDiscovery();
    while (true) {
      const devices: any = await adapter.devices();
      console.log(devices);
      await sleep(3000);
    }
  }
};

main();

実行する

npx ts-node node-ble.ts 
Discovering:
[ '4E:2E:8E:F1:63:91', 'E1:A6:93:4A:ED:C3' ]
[ '4E:2E:8E:F1:63:91', '5B:A0:F3:EB:BB:0D', 'E1:A6:93:4A:ED:C3' ]
[ '4E:2E:8E:F1:63:91', '5B:A0:F3:EB:BB:0D' ]
[ '4E:2E:8E:F1:63:91', '5B:A0:F3:EB:BB:0D' ]
[ '4E:2E:8E:F1:63:91', '5B:A0:F3:EB:BB:0D', 'E1:A6:93:4A:ED:C3' ]
[ '4E:2E:8E:F1:63:91', '5B:A0:F3:EB:BB:0D', 'E1:A6:93:4A:ED:C3' ]

とれた。Adapterにイベントハンドラがないので Adapter.device()を一定時間ループで回してとる手法。nobleでイベントドリブンな取得に慣れていたのでこれ思いつかなくてしばらくハマった。一回device()しただけじゃ絶対とれないし。これはこれでコールバックじゃない分制御の汎用性は高いと思うけど。好みの問題だろうか。

node-bluezでやってみた

node-bluez.ts
import Bluez from 'bluez';

const bluetooth = new Bluez();

const handleOn = async (address: string, props: any) => {
  console.log(`[NEW] Device: ${address}, ${JSON.stringify(props.Name)}`);
  const dev = await bluetooth.getDevice(address);
  dev.on("PropertiesChanged", (props) => {
    console.log(`[CHG] Device: ${address}, ${props}`);
  });
};

const main = async () => {
  try {
    bluetooth.on('device', handleOn);
    await bluetooth.init();
    const adapter = await bluetooth.getAdapter();
    await adapter.StartDiscovery();
    console.log("Discovering");
  } catch (e) {
   throw new Error(e);
  }
}

main();

実行する

npx ts-node node-bluez.ts 
Discovering
[NEW] Device: 54:AB:0C:6F:15:E6, undefined
[NEW] Device: E1:A6:93:4A:ED:C3, "tkr"
[NEW] Device: D1:1C:63:61:E0:01, undefined
[NEW] Device: E1:A6:93:4A:ED:C3, "tkr"
[NEW] Device: FB:33:A1:32:7F:75, "tkr"
[NEW] Device: E1:A6:93:4A:ED:C3, "tkr"

とれた。こちらはAdaptorにイベントハンドラがあって受信したタイミングでパケットが降ってくる。tkrは財布とかに入れてある忘れ物防止タグのTrackRだ。

おわりに

どちらもざっくりコードをみるかぎりDbus APIのラッパーな感じ。アドバタイジングとるだけならイベントドリブンなnode-bluezのほうが好み。ケースバイケースで使っていこうと思う。やっとnobleの葬式ができそう。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1