読者です 読者をやめる 読者になる 読者になる

それからのBLE (2)

BGAPIのサンプルコードの解析と GATT の勉強で見通しができてきたので、メモしておきます。

iBuffaro の BSHSBTPT01BK は SIG が規定する Proximity プロファイルに対応しています。

そこで、Proximity プロファイルの Imediate Alert Service (IAS) のクライアントを BLED112 を使って実装してみます。

IAS とは、キータグのようなサーバに対してアラートレベルの値を送信すると、サーバはその値に応じた動作をするサービスです。BSHSBTPT01BK では次のような動作をします。

Alert Level の値 BSHSBTPT01BKの動作
0x00 (No Alert) 動作なし(あるいは動作停止)
0x01 (Mild Alert) バイブレーション
0x02 (High Alert) ブザー鳴動

サーバが保持する上記のような値は「特性値」と呼ばれます。

アラートレベルの送信手続きは "WriteWithoutResponse" を使うことが規定されています。
これはクライアントがサーバに値を書き込む際にサーバからの応答がないことを表しています。

IAS サービスと、アラートレベルの特性値の UUID は以下の値が規定されています。

Imediate Alert Service 0x1802
Alert Level 0x2a06

通常の UUID は 128ビット(16バイト)で与えられますが、上記は SIG が定める 16ビットの特殊な UUID になっています。

さて、BLED112 を制御する BGAPI では、次のような流れで行うようです。
以下、すでにサーバ(BSHSBTPT01BK)と クライアント(BLED112) の間でコネクションが成立しているものとし、いずれもクライアントがサーバに対して行う処理を想定します。

(1) サーバのプライマリサービスを検索し、目的のサービス(今回は IAS)の UUID を持つものを調べ、その際のハンドルの領域(目的のサービスのはじめのハンドルから終わりのハンドル)を取得する。
(2) ハンドルの領域内で目的の特性値の UUID を持つものを調べ、そのハンドルを決定する。
(3) ハンドルを使って特性値の処理 (今回は WiteWithoutResponse) を行う。

結論を言ってしまうと、BSHSBTPT01BK では Alert Level のハンドルは 0x0d (13) となっていました。
BSHSBTPT01BK 限定ならばハンドル 0x0d を使っていきなり (3) でも問題ありません。
(もちろん、他のキータグではハンドルは別の値になっていることが予想されるので、これはなりたちません)

BGAPI で WiteWithoutResponse を行う関数は次の通り:

ble_cmd_attclient_write_command(connection,atthandle,data_len,data_data)

従って、次のような実装となりました。
(主要部分のみ抜粋)

uint16 handle_alert_level = 0x0d; // アラーとレベルのハンドル
uint8 alert_level = 0x02; // 0x00:No Alert, 0x01:Mild Alert, 0x02:High Alert

// コネクション状態が変化したときに呼ばれるコールバック関数
void ble_evt_connection_status(
  const struct ble_msg_connection_status_evt_t *msg
){

  if (msg->flags & 1) { // 新規コネクション

    ble_cmd_attclient_write_command(
      msg->connection,                // コネクションのハンドラ
      handle_alert_level,             // アラートレベルのハンドル
      1,                              // 書き込むバイト列のサイズ(バイト数)
      &alert_level                    // 書き込むバイト列(のポインタ)
    );

  }
}

ソースコードの全体は後日公開します。

GATT の規定等は以下を参照
Bluetooth GATT | Specifications | Bluetooth Development Portal