Central: スキャン

スキャン

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

advertisementを取得し周りにあるデバイスを全部探してみましょう。ble.scanにあるble.scan.startWait()によりスキャンを開始できます。発見されたデバイスはble.scan.onfindに設定した関数でbleRemotePeripheralオブジェクトとして受け取ることができます。

// Javascript Full Example

var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();

  obniz.ble.scan.onfind = async function(peripheral){
    console.log(peripheral.localName)
  };

  obniz.ble.scan.onfinish = async function(peripherals, error){
    console.log("scan timeout!")
  };

  await obniz.ble.scan.startWait();
}

スキャンは一定時間(デフォルト 30 秒)で完了し、完了時にはble.scan.onfinishに設定した関数が呼ばれます。
一定時間経過後、繰り返しスキャンさせたい場合は onfinish 内で ble.scan.startWait() を呼ぶことで繰り返しスキャンが可能です。
スキャン時間に duration: null を指定すると一定時間で停止せずに常時スキャンする状態になります。

ただし、スキャン時間の指定に関わらず期待した時間より早くスキャンが停止されることがあります。
その場合は onfinish 内で ble.scan.startWait() を再度呼んでスキャンを再開させる必要があります。

// Javascript Full Example

var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();

  obniz.ble.scan.onfind = async function(peripheral){
    console.log(peripheral.localName)
  };

  obniz.ble.scan.onfinish = async function(peripherals, error){
    console.log("scan again")
    await obniz.ble.scan.startWait();
  };

  await obniz.ble.scan.startWait();
}

条件付き検索

検索時にパラメーターを指定することで特定のデバイスだけに絞り込むことができます。
複数設定した場合はOR検索となり、どれかに一致したもののみ検索結果として検出されます。
binaryを用いることで特殊なビーコンなどの絞り込みも可能です。

ScanTarget

  • uuids: UUIDを指定して絞り込み
  • localName: デバイスの名前を指定して絞り込み(完全一致)
  • localNamePrefix: デバイス名を指定して絞り込み(前方一致)(obniz.js 3.4.0以降)
  • deviceAddress: デバイスアドレスを指定して絞り込み(obniz.js 3.4.0以降)
  • binary: advertisementに含まれるバイナリ列の部分一致で絞り込み(obniz.js 3.4.0以降)

また、スキャンの設定を変更することができます。時間の長さやActive/Passiveの切り替えなどです。特に通信費を抑える場合はデバイス側でのfilterを行うfilterOnDeviceプロパティ(obnizOS 3.2.0以上)もあります。

ScanSetting

  • duration: スキャンの時間を変更(標準30秒)
  • duplicate: 同一のデバイスでも新しいadvertisementを受け取ったら通知。以下は名前を指定する例です。
  • activeScan: アクティブスキャンかどうかを指定します(標準アクティブ)
  • filterOnDevice: フィルター処理をデバイス上で行うかどうかを指定します。(obnizOS 3.2.0以上・obniz.js 3.4.0以上)

filterOnDeviceについて
デバイス側で指定された条件に合わせたfilterが実施されるため通信費の削減を行うことができます。
また、filterOnDevice実行時には受け取るadvertisementのscanResponseが足りないまたはその逆のadvertisementを受け取る可能性があります。

// Javascript Full Example

var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();
  var target = {
    localName: "Blank"
  };

  obniz.ble.scan.onfind = async function(peripheral){
    console.log(peripheral.localName)
  };

  obniz.ble.scan.onfinish = async function(peripherals, error){
    console.log("scan timeout!")
  };

  await obniz.ble.scan.startWait(target);
}

検索時間を長くし、かつ同じデバイスでもadvertisementを再度受け取ったら通知するようにします。これによりadvertisement内に含まれるデータが変わった場合や、RSSIの変化を知ることができます。

// Javascript Example

var target = {
  localName: "Blank"
};
var setting = {
  duration: 60, // 60 sec
  duplicate: true // allow duplicate
}
await obniz.ble.scan.startWait(target, setting);

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

// Javascript Full Example

var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();
  var target = {
    uuids: ["1111"]
  };

  obniz.ble.scan.onfind = async function(peripheral){
   console.log(peripheral.localName)
  };

  obniz.ble.scan.onfinish = function(){
   console.log("scan timeout!")
  };

  await obniz.ble.scan.startWait(target);
}

より複雑な検索方法については、より高度な条件付きスキャンを参照ください

1つのみ検索

検索はcallback形式でなく待機することも可能です。特にstartOneWait()を利用すれば、ある1つのデバイスだけ探すことも可能です。また、条件を指定せずすべてのデバイスのスキャンが終わるまで待機するstartAllWait()も利用可能です。

// Javascript Example

await obniz.ble.initWait();
var target = {
  localName: "Blank"
};
var peripheral = await obniz.ble.scan.startOneWait(target);

スキャンの中断

開始中のスキャンを中断するにはble.scan.endWait()を利用します。

// Javascript Full Example

var obniz = new Obniz("OBNIZ_ID_HERE");
obniz.onconnect = async function () {
  await obniz.ble.initWait();
  var target = {
    uuids: ["1111"]
  };

  obniz.ble.scan.onfind = async function(peripheral){
    console.log(peripheral.localName)
  };

  obniz.ble.scan.onfinish = async function(peripherals, error){
    console.log("scan timeout!")
  };

  await obniz.ble.scan.startWait(target);
  await obniz.wait(1000);
  await obniz.ble.scan.endWait();
}