2021年07月29日 更新

Notifyでデータ読み込み

どうも、クラゲです。
Web Bluetooth APIを超簡単に扱えるBlueJellyを使って今回はNotifyを行います
セントラル(PCやスマホ)側からのタイミングではなく、ペリフェラル(BLEデバイス)側からのタイミングで読み込みます。
前半では温度センサ値の読み込み、後半では様々なデータ受信が汎用的に扱えるBluetooth UARTを活用したデータ読み込みを行います。

温度サービスの例

温度変化が分かりやすいようにドライヤーで温めました。27℃~41℃まで変化しています。

【 必要なもの 】

Scan と同様

【 micro:bitの準備 】

Scan と同様

micro:bitが手元にない人は、HTML側のUUIDと受信データフォーマットを変更すれば、他のBLEデバイスでも対応可能です

【 デモページとソースコード 】

micro:bitに内蔵されている温度センサの値を1秒毎に取得して表示します。

WEB上で試せるデモページはこちら
BlueJelly Sample : Notify

ローカル環境で試したい方はこちらのGitHubからダウンロードし、notify.htmlを開いて実行してください。

Start Notifyボタンを押して成功すると、数値が表示されます。1秒毎にリアルタイムに値が更新されます。
Stop Notifyボタンを押すと読み込みを停止します。
notifyもread同様、scanやconnectを行っていない場合は、先にscanやconnectを行った後にnotifyする仕様となっています。
それではプログラムの解説に入ります。

【 プログラム解説(HTML) 】

前回のReadサンプルプログラムから変更は1か所のみ。

HTMLのreadボタンを消して、Start NotifyボタンとStop Notifyボタンを追加しました。

<button id="startNotifications" class="button">Start Notify</button>
<button id="stopNotifications" class="button">Stop Notify</button>

【 プログラム解説(JavaScript) 】

notifyはstartとstopの2種類ありますが、フローは似たような感じです。

startNotify中にデータを受け取るとonReadイベントが呼ばれます。 データを受け取るタイミングはBLEデバイス側で決まっています。 onReadの中身は Readサンプルプログムと全く同じです。

ble.onRead = function (data, uuid){
  //フォーマットに従って値を取得
  value = data.getInt8(0);//8bitの場合のフォーマット

  //コンソールに値を表示
  console.log(value);

  //HTMLにデータを表示
  document.getElementById('data_text').innerHTML = value;
  document.getElementById('uuid_name').innerHTML = uuid;
  document.getElementById('status').innerHTML = "read data"
}

startNotify処理が終わるとonStartNotifyイベントが呼ばれます。 ここではStart Notifyが始まったことを伝えているだけです。 実際にデータを取得するタイミングはonRead時です。

ble.onStartNotify = function(uuid){
  console.log('> Start Notify!');

  document.getElementById('uuid_name').innerHTML = uuid;
  document.getElementById('status').innerHTML = "started Notify";
}

同様にstopNotify処理が終わると、onStopNotifyイベントが呼ばれます。

ble.onStopNotify = function(uuid){
  console.log('> Stop Notify!');

  document.getElementById('uuid_name').innerHTML = uuid;
  document.getElementById('status').innerHTML = "stopped Notify";
}

ボタンが押されたときの関数呼び出しを指定します 今回はnotifyなので、ble.startNotify及びble.stopNotifyで呼び出しています。

document.getElementById('startNotifications').addEventListener('click', function() {
      ble.startNotify('UUID1');
});

document.getElementById('stopNotifications').addEventListener('click', function() {
      ble.stopNotify('UUID1');
});

うまくいかない場合

特にmicro:bit以外を使っていてうまくいかない人は、以下の3点を確かめてください

  • BLEデバイスのUUIDとJavaScriptのUUIDが正しく合っているか確認
  • BLEデバイスの対象Service/CharacteristicのプロパティにNotifyがあるか確認
  • 受信データフォーマットに従っているか確認(例えばフォーマットをdata.getInt16(0)などに変えてみる)

UARTサービスの例

後半はUARTを活用したNotifyを実行します。

生の加速度センサ値ではなく、micro:bit内で傾き角度を計算した値を取得して表示しています。

【 必要なもの 】

前半と同様

【 micro:bitの準備 】

前半と同様

【 デモページとソースコード 】

micro:bit内で加速度センサ値から傾きを計算した結果を100ミリ秒毎に取得して表示します。

WEB上で試せるデモページはこちら BlueJelly Sample : Notify UART

ローカル環境で試したい方はこちらのGitHubからダウンロードし、notify_uart.htmlを開いて実行してください。

micro:bitを下の写真のオレンジ矢印のように回転すると-179〜180まで変化します。数値は角度(単位:度)を表しています。

【 プログラム解説(HTML) 】

前半と同様

【 プログラム解説(JavaScript) 】

JavaScriptは前半から2つの変化点があります
1つ目はUUIDです。UARTサービスのTXキャラクタリスティックに変更しています

window.onload = function () {
  //UUIDの設定
  ble.setUUID("UUID1", BlueJelly.MICROBIT_UART_SERVICE, BlueJelly.MICROBIT_TX_CHARACTERISTIC);
}

2つ目はonReadの中身です。
UARTの場合は、固定のByte数ではなく、文字列として受け取る点が先程と異なります。for文を使って1つずつデータを連結し、数値化してから変数valueへ代入しています。

ble.onRead = function (data, uuid){
  //フォーマットに従って値を取得
  let value = "";
  for(let i = 0; i < data.byteLength; i++){
    value = value + String.fromCharCode(data.getInt8(i));
  }

  //数値化
  value = Number(value);

  //コンソールに値を表示
  console.log(value);

  //HTMLにデータを表示
  document.getElementById('data_text').innerHTML = value;
  document.getElementById('uuid_name').innerHTML = uuid;
  document.getElementById('status').innerHTML = "read data"
}

UARTについてはこちらで説明している通りです。
前半の温度センサの場合であれば、UARTを活用することで、ずっと1秒毎に温度データをもらうのではなく、micro:bit側でコードを変更して温度変化があったときだけ送信するなど、色々とカスタマイズが可能です。

うまくいかない場合

前半と同様


これでBLEデバイスからデータを読み込むReadとNotifyについては学んだので、次回はBLEデバイスへの書き込みに挑戦しましょう

以上、Notifyでデータ読み込みでした!