ESP32-WROVERでBLE通信(Custom Characteristic編)

前回(ESP32-WROVERでBLE通信)でサンプルコードやテンプレートプロジェクトでPC-ESP間でBLE通信しましたが、私的にはPC-BLEデバイス間で単純なデータR/Wをしたいのでそれをやっていきます。

ESP32のテンプレートプロジェクトでは心拍計サービスでしたが、他の標準サービスでデータR/W的な物はないか調べてもドンピシャというのは無さそうです(Bluetooth.com/ja-jp)。

ですのでCustomサービスを作ってみました。

では、始めましょう!!!

BLEはGATTサービスの内容を変えることで他のサービスやCustomサービスに対応する事ができます。ですので「ESP32-WROVERでBLE通信」を元にしてGATTサービスを対応していきますので、このページから始める方は前回(ESP32-WROVERでBLE通信)を参考にしてプロジェクト作ってから始めて下さい。

プロジェクト名は前回の「GattSecurityServerExample」から「GattSecuriyServerCustom」にしています。

このテンプレートプロジェクトのGATTサーバー定義がどこにあるかというと138行目辺りの”heart_rate_gatt_db”がそうです。

まずこの”heart_rate_gatt_db”の中身を確認してみます。

基本的にGATTサーバーは以下のような構造をしています。

GATTサーバー

これと”esp_gatts_attr_db”を対応させてみます。

UUIDPermission
サービス0x2800(Primary Service)Read0x180D(心拍数サービス)
特性0x2803(Characteristic Declaration)ReadNotify
特性0x2A37(Heart Rate Measurement)ReadNull
ディスクリプター0x2902(Client Characteristic Configuration Descriptor(CCCD))Read/WriteHeart Measurement CCC
特性0x2803(Characteristic Declaration)ReadRead
特性0x2A38(Body Sensor Location)暗号化ReadSensor location Value
特性0x2803(Characteristic Declaration)ReadRead/Write
特性0x2A39(Heart Rate Control Point)暗号化Read/WriteHeart Ctrl Point
1.心拍数サービス

よくわかりませんね。私もそれほどわかっていないので悪しからず。

わかっていないながらも多少解説するとNotify(通知)はサーバー(ESP32)がデータを一方的に送ってきますがCCCDのNotify bitをOnした場合のみNotify(通知)します。ReadやWriteはクライアント(PC)側から要求します。

今回はNotifyやCCCDは使わないのでHeart Rate Control Pointといったところをカスタム化します。

以下が今回のカスタムサービスです。

UUIDPermission
サービス0x2800(Primary Service)Read787767d1-a760-4568-90c8-85525e7add92(ベンダー固有UUID)
特性0x2803(Characteristic Declaration)ReadRead
特性54bde750-f4df-4909-9be0-61083b10b171(ベンダー固有UUID)暗号化ReadRead Data
特性0x2803(Characteristic Declaration)ReadWrite
特性11078b7f-42e5-4e91-abb9-f247e622159a(ベンダー固有UUID)暗号化WriteWrite Data
2.カスタムサービス

サービスのところで元々は規定の心拍数サービスなのでUUIDは16bitの0x180Dでしたが今回はカスタムサービスなので128bitUUIDになっています。

BLEにおいてはBLEの負担低減のため16bitを使用できますがUUIDは本来BLE限らずいろいろと使われるグローバルで一意な事が高い確率で保証される128bitの数字です。

ちなみにBLEではxxxxxxxx-0000-1000-8000-00805f9B34FBのxxxxxxxxのところに0000180dが入り最終的に128bitになります。

カスタムサービスの場合、それは使えないので128bitになります。

UUIDはOnline UUID Generatorなどで生成できます。サイトにはVersion1とVersion4がありますが説明文によるとVersion1がタイムスタンプとそのコンピューターのMACアドレスから生成されて、Version4は安全な乱数ジェネレーターで生成される、とあります。

同様に特性でも2つのUUIDを生成してそれぞれRead Data、Write Dataとしました。

これを具体的にコードに移植します。”heart_rate_gatt_db”を”custom_gatt_db”にして以下のようにしました。

ここで使われるUUID 3個、read_data、write_dataを定義します。GATTプロファイルはリトルエンディアンなので下位のバイトから並べます。

デバイス名を「ESP_BLE_SECURITY_CUSTOM」(任意)にします。

その他、名前を変えたところも合わせて名前を変えます。また使わなくなった変数も削除します。

できたらbuild & flashします。

ESP32側の準備ができたところで前回の(ESP32-WROVERでBLE通信)でやったようにESP32 BLEにペアリング、接続をしていきます。

では、

PC(Windows10)の「Windowsの設定」→「デバイス」→「Bluetoothとその他のデバイス」を選択。

「Bluetoothまたはその他のデバイスを追加する」→「Bluetooth」をクリック。

「ESP-BLE-SECURITY_CUSTOM」が見つかるのでクリック、ペアリングができます。

ペアリングができたので前回も使った「Bluetooth GATT クライアント」GitHubにある完全なサンプルを使用して接続してみます。

「1)Client: Discover servers」を選んで「Start enumerating」をクリックして現れる「ESP_BLE_SECURITY_CUSTOM」を選択します。

「2) Client: Connect to a server」を選んで「Connect」をクリックして「Choose a service」をクリックするとさきほど設定したカスタムサービスが現れます。

「Custom Service: 787767d1-….」を選択して「Choose a characteristic」をクリックすると「Custom Characteristic: 54bde750-…」と「Custom Characteristic:11078b7f-…」が現れます。

「Custom Characteristic: 54bde750-…」の方がReadなのでこちらを選択して「Read Value」をクリックすると初期値”initial value”が読み取れます。

Read特性はできました!!!

しかしWrite特性は何もコードを記述していないので動きません。Writeした値をそのままReadできるようにするコードを足していきます。

GATTのWriteイベントは”gatts_profile_event_handler”の”case ESP_GATTS_WRITE_EVT:”を呼び出すのでここに「write_data」→「read_data」のコードを足します。

しかし再度build & flashして、ライト特性「Custom Characteristic: 11078b7f-…」にデータを入力して「Write Value as UTF-8」をクリックしても「write_data」が「read_data」に反映されません。

“case ESP_GATTS_WRITE_EVT”の”write_data”を”param->write.value”に変えても結果は同じです。”case ESP_GATTS_READ_EVT”に何かコードを足さなければいけなさそうですが、どこにデータをセットすればいいのでしょうか。param->readにvalueメンバーは無いのです。

ESP-IDFのサンプルコードなどをいろいろ見てみるとサンプルコード”gatt_securiy_server”ではなくサンプルコード”gatt_server”の”case ESP_GATTS_READ_EVT”に以下のようなコードがあります。

これを流用してみました。

あと上で設定したGATTプロファイルの内、[CUSTOM_IDX_READ_DATA]のところの{ESP_GATT_AUTO_RSP}を{ESP_GATT_RSP_BY_APP}に変えます。これはその字のままAutoでレスポンスをするのでなくアプリでレスポンスするということです。

再度、build & flashします。

今度は書いたデータが読み出されました。

これで一応、終わりなのですが、ここのRead ResultにあるUnknown formatとは何なのでしょうか。

UWPアプリのサンプルコードを確認してみたりするとこれはディスクリプターの1つの特性提示フォーマットディスクリプター(Characteristic presentation format descriptor)を参照して特性提示フォーマットディスクリプターが無いとUnknown formatとしていました。

特性提示フォーマットディスクリプターは7byteで1byte目に値のフォーマットを示します。

フォーマットは28種類あり例えばunsigned 32bit integer→0x08、UTF8 string→0x19などです。

このディスクリプターをGATTプロファイルに追加してみます。

追加したディスクリプターで使っている変数もソースファイル、ヘッダーファイルに追加します。

今度はUnknown formatとはなりませんし、”1″を書いた値を読むとunsigned 32bitに指定しているので49(0x31)と表示されます。

プロジェクト全てはGitHubにあります。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

ESP32

前の記事

ESP32-WROVERでBLE通信