obnizのBLEでペリフェラルを探す

# obnizのBLEでペリフェラルを探す

BLEとはBluetooth Low Engeryの略で、Bluetoothの一種です。
こんな特徴を持っています

- 省電力
- ペアリングなしの接続モードがある
- GATTというプロファイルが基本で、データベースのように相手を扱う
- １つの親に対して複数の子を接続できる
- スマートフォンなどでかなり普及していて、多くのスマートフォンから利用できる。

obnizにもBLEの機能があります。
これを利用することで同じようにBLEを利用する照明とかスマートウォッチにつないで値を取り出したり、逆にスマホから繋がれるなんてことが可能です。

## セントラルとペリフェラル

BLEでは1対多の通信となっていて、親が1存在します。その親をセントラル、子をペリフェラルと呼びます。


## 初期化

BLEを使用するときは最初に初期化をする必要があります。
初期化はこちらのようにやります。

```javascript
  await obniz.ble.initWait();
```

## スキャン

BLEのペリフェラルはadvertisement(直訳で広告)という信号を送り続けます。
これは「私はXXXっていうデバイスです！つなぐことができますよ！」という信号で、これを使ってセントラルは近くにいるBLEペリフェラルを探すことができます。

## ペリフェラルの用意。

「BLEペリフェラルを用意して下さい」といっても難しいですよね。
スマホがあれば、アプリから用意できます。
無料アプリでもたくさんありますが、「LightBlue」がおすすめです。

LightBlueをインストールし、動かすと下に「バーチャルデバイスを作る」とういのがでてきます。それを選択します。
どんなタイプか聞かれたら「Blank」を選びましょう。
![lessons_obnizjs_ble_scan2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258216/cddace09-cce8-acfd-7dab-ec21f0ca0dc2.png)

すると作成されて、Blankというのがでてきます。

左側にチェックが入っていれば有効になっています。

![lessons_obnizjs_ble_scan1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258216/50e8ea90-f158-c9bd-3c69-babd7049a716.png)


この状態でスキャンしてみましょう。

## スキャン

スキャンはこのようにして開始します。

```javascript
obniz.ble.scan.start();
```

これによりobnizは決められた時間だけまわりにいるbleのadvertisementを集めて、どんなデバイスが近くにいるのかを調べます。
もし、見つかれば見つかったときにonfind関数を呼んで教えてくれます。

```javascript
obniz.ble.scan.onfind = function(peripheral){
}
```

onfindの引数に入っているperipheralというのはobniz.jsのペリフェラルクラスです。他のドキュメントで詳しく説明していますが、とにかく見つけたデバイスが入っています。

スキャンはある一定時間だけ行われて終わったらonfinishが呼ばれます。

```javascript
obniz.ble.scan.onfinish = function(){
}
```

まずは何も設定せずに周りにあるデバイスを全部探してみましょう。

```javascript
var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();
  obniz.ble.scan.start();
  
  obniz.ble.scan.onfind = function(peripheral){
   console.log(peripheral.localName)
  };
  
  obniz.ble.scan.onfinish = function(peripheral){
   console.log("scan timeout!")
  };
}
```

デバイスが見つかったらデバイスの名前を表示するようにしています。名前がないものも多いのでnullとなることがあります。

## 条件付き検索

次に条件をつけて検索してみましょう。
例えば先ほどアプリで作ったペリフェラルは"Blank"という名前がついています。
実際にスマホからBlankという名前でadvertisementが出ているので、その名前で検索してみます。
ちなみに先ほどのアプリはそのアプリをスマホで開いていないとうまく動かないことがあるので、開いたまま置いておきましょう。

```javascript
var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();
  var target = {
    localName: "Blank"
  };
  obniz.ble.scan.start(target);
  
  obniz.ble.scan.onfind = function(peripheral){
   console.log(peripheral.localName)
  };
  
  obniz.ble.scan.onfinish = function(peripheral){
   console.log("scan timeout!")
  };
}
```

どうでしょうか。Blankは見つかったでしょうか。
ちなみに検索時間は標準で30秒ですが変更するにはこのようにします。

```javascript
var target = {
  localName: "Blank"
};
var setting = {
  duration : 10 // 10 sec
}
obniz.ble.scan.start(target, setting);
```

検索時の条件としてlocalNameの他にadvetisementに入っているUUIDを指定することもできます。

例えば、先ほどのアプリでBlankのところをタップするとこのようなものが見えます。

![](./images/lessons_obnizjs_ble_scan.png)

UUID: 1111

というのがあります。
このUUID1111はadvertisementに入るようにLightBlueではないっています。
このUUIDをadvertisementしているデバイスだけ検索するということも可能です。

```javascript
var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();
  var target = {
    uuids: ["1111"]
  };
  obniz.ble.scan.start(target);
  
  obniz.ble.scan.onfind = function(peripheral){
   console.log(peripheral.localName)
  };
  
  obniz.ble.scan.onfinish = function(peripheral){
   console.log("scan timeout!")
  };
}
```

ちゃんとBlankというのが見つかるかと思います。

## スキャンの中断。

始めたスキャンを中断するにはend()を利用します。

```javascript
var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();
  var target = {
    uuids: ["1111"]
  };
  obniz.ble.scan.start(target);
  
  obniz.ble.scan.onfind = function(peripheral){
   console.log(peripheral.localName)
  };
  
  obniz.ble.scan.onfinish = function(peripheral){
   console.log("scan timeout!")
  };
  
  await obniz.wait(1000);
  obniz.ble.scan.end();
}
```


## awaitな検索

start()とonfind()を使った方法ではなく、awaitを使って検索することもできます。
方法は２つあります。

```javascript
await obniz.ble.scan.startOneWait();
await obniz.ble.scan.scan.startAllWait();
```

`startOneWait()`は条件に合うペリフェラルが1つでも見つかったら終わりにする関数。
`startAllWait()`がその条件に合うペリフェラルを時間のかぎり全部探す関数です。
これらを使えばcallbackなくペリフェラルを探せます。

```javascript
var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();
  var target = {
    localName: "Blank"
  };
  var peripheral = await obniz.ble.scan.startOneWait(target);
  if (peripheral) {
    console.log("Found!")
  }
}
```

```javascript
var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();
  var target = {
    localName: "Blank"
  };
  var peripherals = await obniz.ble.scan.startAllWait(target);
  for (peripheral in peripherals) {
    console.log("Found!")
  }
}
```