ブロックを積みながら(18) BLE、ハンドル、UUID、CHARACTERISTICS

Joseph Halfmoon

前回は、micro:bitとRaspberry Pi 3 model B+をペアリングし、ラズパイ上のPython3からbluepyモジュールを使ってコネクトしました。そしてその様子をラズパイ上のWiresharkで観察してみました。そこで痛感したことは、Handle / UUID / Characteristic などというものを理解しないと何が何だかサッパリということであります。今回は、micro:bitの「それら」をダンプして何があるのか調べてみます。

※「ブロックを積みながら」投稿順 index はこちら

汎用アトリビュート・プロファイル(GATT)こそは、BLE通信を通じて何かデータをやり取りしたい、というときに避けて通れぬものであるようです。そこにはクライアントとサーバと「呼ばれる」役割があります。

  • サーバ:実際にデータを保持する。クライアントの要求を受信し、応答を返す
  • クライアント:要求をサーバに送信し、応答を得る

前回のコネクションでは、micro:bitがペリフェラル、ラズパイがセントラルという固定の役割でしたが、GATTではデータを実際に持っている側がサーバということになります。データの方向だけで決まるので役割固定ではありませぬ。あるときはサーバ、あるときはクライアント。

ここで登場した「アトリビュート」という概念は階層構造をもったデータであるようです。データを保持するGATTサーバの中には

  1. サービス
  2. 特性(characteristics)
  3. ディスクリプタ

という3レベルの階層構造が含まれると理解できます。micro:bitで具体例に調べると、加速度センサの「サービス」の中に、実際に加速度の値を保持する「特性」とか、測定インターバルを指定する「特性」などが含まれています。そしてディスクリプタは各特性に引っ付いていて、それぞれの特性を補完するような情報を付加する存在であるようです。アプリレベルの具体的な通信は、所望の特性からデータを読み出したり、書き込んだりすることとなります。

そこでどんな特性があるのかリストできれば、BLEを通じて行える操作の一覧が得られることになります。今回は、

  • micro:bit V1.5 上に 「BLE Uartサービス」を走らせておく(アイキャッチ画像参照。1個のブロックを置くだけ)
  • ラズパイ Pythonで、micro:bitをPheripheral()としてコネクトし、特性一覧を出力

してみました。ラズパイ側のPython操作については以下に bluepy モジュールのドキュメントがあるのでそこをご参照ください。

bluepy – a Bluetooth LE interface for Python

単純化すると以下のような3ステップにつきます。xxのところはBLEアドレスが入ります。

pobj = bluepy.btle.Peripheral()
pobj.connect("xx:xx:xx:xx:xx:xx", bluepy.btle.ADDR_TYPE_RANDOM)
clis = pobj.getCharacteristics()

得たリストの各要素(オブジェクト)の中に、uuidやhandleというものが含まれております。

UUID

UUIDはBluetoothの概念ではなく、ITU規定の「ユニバーサル固有識別子」だそうです。グローバルにユニークな16バイト(128ビット)の値。よってこれが分かれば「それがどんなデータであるのか一意に決まる」タイプ(型)として扱って良いのだと思います。ただ、パケットの小さいBLEで128ビットはあんまりな長さなので標準Bluetooth UUIDというものをBluetooth SIGが決めているようです。以下のxxxxxxxxのところに16ビットもしくは32ビットの短い「標準」UUIDをはめ込んで実際の128ビットIDをつくる場合もあるそうです(実例がすぐに登場します。)

xxxxxxxx-0000-1000-8000-00805f9b34fb

先ほどでたmicro:bitの加速度センサ・サービスで具体的な3次元加速度を保持している「特性」のUUIDはBluetooth標準ではなく、フル128ビット値で以下の値でした。

E95DCA4B-251D-470A-A062-FA1922DFA9A8

このようなmicro:bitのBluetooth情報を調べるときに出発点となりそうなのは、例によって英国ランカスター大のmicro:bitのサイトです。

BBC micro:bit Bluetooth Profile

上記のドキュメントの中にリンクがありますが、micro:bit上のGATTサービスに存在する筈のUUIDについてまとめてくれているのが以下のページです。上の加速度センサのUUIDも以下のURLのページから引用させていただいたものです。

Bluetooth Developer Studio Level 3 Profile Report

Handle

さて、UUIDが分かれば実際に読み書きできるかといえばさにあらず。実際に読み書き操作をする場合にはハンドルという16ビットの値を使用します。これはユニークな識別子でトランザクションに渡って変化しない、ボンディングされたデバイスについては複数トランザクションに渡って変化しない、逆に言えば変化する場合もあり、という値です。よって、まず特性を検索し、所望のUUIDに1対1にひっついたハンドルを見つけ、それを使ってデータにアクセスするという手順を踏むのが安全そうです。

BLE Uartサービスのみを走らせてあるmicro:bit V1.5上で実際にリストできた特性のUUID、ハンドルと、ランカスター大の資料から読み取った特性を1行にまとめたものを、以下に「サービス毎」の表形式にしてみました。なお上記資料にUUIDが見当たらない特性には”—“と記しました。

Generic Access
UUID Handle Properties CHARACTERISTICS
00002a00-0000-1000-8000-00805f9b34fb 0003 READ WRITE Device Name
00002a01-0000-1000-8000-00805f9b34fb 0005 READ Appearance
00002a04-0000-1000-8000-00805f9b34fb 0007 READ Peripheral Preferred Connection Parameters
00002a05-0000-1000-8000-00805f9b34fb 000a INDICATE

上記はUUIDからして標準Bluetooth UUIDです。—のところも標準Bluetoothのドキュメントをあされば書いてあるのではないかと思われます。

DFU CONTROL SERVICE
UUID Handle Properties CHARACTERISTICS
e95d93b1-251d-470a-a062-fa1922dfa9a8 000e READ WRITE DFU Control
e97d3b10-251d-470a-a062-fa1922dfa9a8 0011 WRITE NO RESPONSE NOTIFY

DFU=Device Firmware Updateだと思います。ノルディック社のチップのFirmwareを書き換えるためのものでしょう。無暗に触るところではないかも。

Device Information
UUID Handle Properties CHARACTERISTICS
00002a24-0000-1000-8000-00805f9b34fb 0015 READ Model Number String
00002a25-0000-1000-8000-00805f9b34fb 0017 READ Serial Number String
00002a26-0000-1000-8000-00805f9b34fb 0019 READ Firmware Revision String

ここは、読み出し専用のデバイス情報ばかり、まずはこのあたりからアクセスしてみますか。

EVENT SERVICE
UUID Handle Properties CHARACTERISTICS
e95d9775-251d-470a-a062-fa1922dfa9a8 001c READ NOTIFY MicroBit Event
e95d5404-251d-470a-a062-fa1922dfa9a8 001f WRITE NO RESPONSE WRITE Client Event
e95d23c4-251d-470a-a062-fa1922dfa9a8 0021 WRITE Client Requirements
e95db84c-251d-470a-a062-fa1922dfa9a8 0023 READ NOTIFY MicroBit Requirements

ここは「通知」をともなうイベント関係か。また後で。

UART SERVICE
UUID Handle Properties CHARACTERISTICS
6e400002-b5a3-f393-e0a9-e50e24dcca9e 0027 INDICATE TX Characteristic
6e400003-b5a3-f393-e0a9-e50e24dcca9e 002a WRITE NO RESPONSE WRITE RX Characteristic

最後に登場したのが、BLE Uartサービスの特性二つ。シリアル通信はこの2つの特性を読み書きすることで行えるっと。

ようやく呪文のようだったBLE通信の中身が少しわかってきたので、次回は、簡単なところから実際に読み書きしてみたいと思います。

ブロックを積みながら(17) micro:bitとラズパイ、ペアリング+Wireshark に戻る

ブロックを積みながら(19) micro:bit BLE、Pythonで「特性」読み出し へ進む