Central: スキャン

スキャン

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

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

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

  obniz.ble.scan.onfind = 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を指定してタイムアウトをなしとすることで繰り返しスキャンが可能です。

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

  obniz.ble.scan.onfind = 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();
}

条件付き検索

検索時にパラメーターを指定することで特定のデバイスだけに絞り込むことができます。複数設定した場合はどれかに一致したもののみ検索結果として検出されます。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を受け取る可能性があります。

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

  obniz.ble.scan.onfind = 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の変化を知ることができます。

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

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

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

  obniz.ble.scan.onfind = 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()も利用可能です。

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

スキャンの中断

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

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

  obniz.ble.scan.onfind = 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();
}