Nefry BTからブラウザにWeb Bluetoothでデータを表示する方法

Nefry BTからブラウザにWeb Bluetoothでデータを表示する方法:

IoTLT Advent Calendar 2018の10日目担当の蔵下です。普段はIoTな会社でWeb系の開発を行っています。

のびすけさんの記事「Nefry BT(ESP32)からBLEでNode.jsにデータを送ってみよう」で、Nefry BTもいい感じにBLE使えるやん!:clap: ということで、 Nefry BT ↔ ブラウザ でデータを表示する方法をまとめてみました。



web.gif


▲クリスマスっぽさを少しだけ:christmas_tree:


Nefry BT(BLEデバイス)とブラウザの通信はWeb Bluetoothでできる

Nefry BTとブラウザでのデータ通信は Web Bluetooth で実現できます。普段の仕事でもゴニョゴニョ使っているので、詳細は他記事でまとめていますので良かったら見てみてください。

Web Bluetoothは、現在(2018/12/10)Windows、Mac、AndroidのChromeで使えます(詳細はこちら)。そうです、 スマホでも使えます! IoTなデモ作る幅も広がると思うので、ぜひ触ってみてください。

https://dotstud.io/blog/nefrybt-ble-bluetooth-peripheral/


ソースコード

今回のデモはのびすけさんの記事記事「Nefry BT(ESP32)からBLEでNode.jsにデータを送ってみよう」をベースに一部変更を加えながら進めました(ありがとうございます!)。Nefry BTは初期のR1を使っています。


スケッチ(Nefry BT側のコード)

sketch.ino
#include <Nefry.h> 
#include <BLEDevice.h> 
#include <BLEServer.h> 
#include <BLEUtils.h> 
#include <BLE2902.h> 
 
BLECharacteristic *pCharacteristic; 
bool deviceConnected = false; 
uint8_t value = 0; 
 
// See the following for generating UUIDs: 
// https://www.uuidgenerator.net/ 
 
#define SERVICE_UUID        "d5875408-fa51-4763-a75d-7d33cecebc31" 
#define CHARACTERISTIC_UUID "a4f01d8c-a037-43b6-9050-1876a8c23584" 
 
class MyServerCallbacks: public BLEServerCallbacks { 
    void onConnect(BLEServer* pServer) { 
      deviceConnected = true; 
    }; 
 
    void onDisconnect(BLEServer* pServer) { 
      deviceConnected = false; 
    } 
}; 
 
void setup() { 
  Serial.begin(115200); 
 
  // Create the BLE Device 
  BLEDevice::init("NefryBT"); 
 
  // Create the BLE Server 
  BLEServer *pServer = BLEDevice::createServer(); 
  pServer->setCallbacks(new MyServerCallbacks()); 
 
  // Create the BLE Service 
  BLEService *pService = pServer->createService(SERVICE_UUID); 
 
  // Create a BLE Characteristic 
  pCharacteristic = pService->createCharacteristic( 
                      CHARACTERISTIC_UUID, 
                      BLECharacteristic::PROPERTY_READ   | 
                      BLECharacteristic::PROPERTY_WRITE  | 
                      BLECharacteristic::PROPERTY_NOTIFY | 
                      BLECharacteristic::PROPERTY_INDICATE 
                    ); 
 
  // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml 
  // Create a BLE Descriptor 
  pCharacteristic->addDescriptor(new BLE2902()); 
 
  // Start the service 
  pService->start(); 
 
  // Start advertising 
  pServer->getAdvertising()->start(); 
  Serial.println("Waiting a client connection to notify..."); 
} 
 
void loop() { 
 
  if (deviceConnected) { 
    Serial.printf("*** NOTIFY: %d ***\n", value); 
    char buffer[32]; 
    sprintf(buffer, "{\"val\":%d}", value); 
    Serial.printf(buffer); 
    pCharacteristic->setValue(buffer); 
    pCharacteristic->notify(); 
    //pCharacteristic->indicate(); 
    value++; 
  } 
  delay(2000); 
} 


JavaScript(ブラウザ側のコード)

app.js
const SERVICE_UUID = 'd5875408-fa51-4763-a75d-7d33cecebc31' 
const CHARACTERISTIC_UUID = 'a4f01d8c-a037-43b6-9050-1876a8c23584' 
 
const btn = document.getElementById('btn') 
const text = document.getElementById('text') 
 
// Web Bluetoothはユーザーアクションをトリガーに処理を始める必要がある 
btn.addEventListener('click', (event) => { 
  connect() 
}) 
 
const connect = () => { 
  // Scan 
  navigator.bluetooth.requestDevice({ 
    // 'Nefry'というデバイス名でフィルタリング 
    acceptAllDevices: false, 
    filters: [ 
      {namePrefix: 'Nefry'} 
    ], 
    optionalServices: [ 
      // 使用したいServiceを登録しておく 
      SERVICE_UUID 
    ] 
  }) 
    // 接続 
    .then(device => device.gatt.connect()) 
    // Service取得 
    .then(server => server.getPrimaryService(SERVICE_UUID)) 
    // Characteristic取得 
    .then(service => service.getCharacteristic(CHARACTERISTIC_UUID)) 
    // Notificationsを開始 
    .then(characteristic => setNotifications(characteristic)) 
    // Errorはこちら 
    .catch(error => console.log(error)) 
} 
 
// Notification設定 
const setNotifications = (characteristic) => { 
 
  // Add Event 
  characteristic.addEventListener('characteristicvaluechanged', (event) => { 
    const value = event.target.value 
 
    // データをパース 
    const decoder = new TextDecoder('utf-8') 
    const str = decoder.decode(value) 
    const json = JSON.parse(str) 
    // Nefry BTからのデータを表示 
    if (text) text.innerHTML = json.val 
  }) 
 
  // Notifications開始 
  characteristic.startNotifications() 
} 


HTML(ブラウザ側のコード)

index.html
<!DOCTYPE html> 
<html lang="ja"> 
<head> 
  <meta charset="UTF-8"> 
  <title>Web Bluetooth API</title> 
  <script src="main.js" defer></script> 
  <!-- CSSは省略 --> 
</head> 
<body> 
<button id="btn">Connect</button> 
<div id="text"></div> 
</body> 
</html> 


まとめ

特に面白みのないネタになってしまいました(笑)。ですが、みなさんの面白いIoT作品の新たな選択肢になればいいなと思いまとめてみました。最近IoTLT参加できていなかったので、来年からまたちょこちょこ参加したいと思います! 良いお年を~

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)