あとは論理的なところか。
2.2 Generic Attribute profile(GATT)
どうでもいいことだが、これを普通に略すと「GAP」になってしまうのよね・・・。GATTと同じルールで略すと、Generic Access ProfileはGACCだし。
GATTは「ガット」でよいけど、GACCは「ガック」になって、なんとなくがっくりしそうだからダメなのかな。
GATTはデータ値を実際に転送するレイヤー。
2.2.1 Roles
GATT ServerとGATT Client。値を持っている方がServerで、アクセスしに行く方がClient。
LED Buttonアプリでは、PeripheralがServerで、CentralがClientになる。
2.2.2 GATT hierarchy
GATT Serverはattributeテーブルと呼ばれるデータ構造を持っている。データ構造というか、attributeがデータそのものなのかな。
2.2.2.1 Attribute
attributeは、ハンドル、UUID、値で構成されている。- ハンドル
GATTテーブルのインデックスで、デバイス内でユニーク。 - UUID
attributeが持つデータのタイプ情報や値を解読するためのキー情報。
多くのattributeが同じUUIDを使うことになる。
2.2.2.2 Characteristic
characteristicは最低でも2つのattribute(declarationとvalue)を持つことになる。GATT Serverが転送する値は、必ずcharacteristicに割り当てられる。
Core_v4.1のp.2181あたりに書いてある。
characteristic定義は、以下を含む。
- characteristic declaration(p.2182)
- Characteristic Value declaration(p.2184)
- characteristic descriptor declaration(p.2184)
2.2.2.3 Descriptors
characteristicのattributeに、descriptorというものがある。Characteristic Valueに関連した情報みたいだ。
ただ、CCCD(Client Characteristic Configuration Descriptor)は別みたい。
S110では、NotifyかIndicateプロパティに自動的に付加されるとのこと。
2.2.2.4 Service
serviceは1つ以上のcharacteristicから構成される。普通は、特定のセンサーの読み書きや設定のような感じでまとめたserviceにするのだけど、LED Buttonアプリはあまり気にせず、LEDとボタンをまとめたserviceにしておく。
2.2.2.5 Profile
profileは1つ以上のserviceから構成される。profileはattributeがない。
2.2.3 Standard versus custom services and characteristics
省略2.2.4 UUIDs
UUIDは128bitの値。2.2.4.1 Bluetooth SIG UUIDs
Bluetooth Core Specificationでは、base UUIDと16bit UUIDで分けている。0x0000xxxx-0000-1000-8000-00805F9B34FB
これは、Bluetooth SIGが使っているcommon base UUID(p.1864)。
例えばHeart Rate Measurement Characteristicは0x2A37なので、こうなる。
0x00002A37-0000-1000-8000-00805F9B34FB
2.2.4.2 Vendor specific UUIDs
SoftDeviceも、Bluetooth SIGと同じようなUUIDの決め方にしている。base UUIDはnRFgo Studioで生成するらしい。
LED Buttonアプリでは「0x0000xxxx-1212-EFDE-1523-785FEABCD123」にしているとのこと。
serviceは0x1523、LED characteristicは0x1524、ボタン状態characteristicは0x1525。
2.2.5 On-air operations and properties
だいたいの操作は、attributeのハンドルとUUIDで行う。characteristicを扱うのは、propertyに依存する。
- Write
- Write without response
- Read
- Notify
- Indicate
2.2.5.1 Write and Write without response
GATT ClientがServerに書き込むことができる。without responseの場合は、アプリレベルの承認や応答が無しになる。
2.2.5.2 Read
GATT ClientがServerの値を読むことができる。2.2.5.3 Notify and Indicate
GATT Serverが変化をClientに通知することができる。NotifyとIndicateの違いは、Indicateはアプリレベルの承認が必要で、Notifyにはそれがない。
LED Buttonアプリでは、こうする。
- LED characteristicは、アプリレベルの承認が不要なので、Write without responseとRead property。
- ボタン状態characteristicは、アプリレベルの承認は不要なので、Notify propertyのみ。
これで2章は終わりだ。
ようやく、4章の続きに戻ることができる。
もともとは、なんでService構造体にハンドルとかUUIDがいるの?という疑問だったのだけど、attributeの構造がそうなっているからなんですな。
4.4.3 Service Initialization
サービスが1つ、characteristicが2つ。typedef struct ble_lbs_s {uint16_t service_handle;ble_gatts_char_handles_t led_char_handles;ble_gatts_char_handles_t button_char_handles;uint8_t uuid_type;uint16_t conn_handle;ble_lbs_led_write_handler_t led_write_handler;} ble_lbs_t;
UUIDタイプは、sd_ble_uuid_vs_add()で設定するようだ。管理用かな?
この書き方はスニペットだ、と書いてあるので、従っておけばよいか。
なお、Base UUIDはnRFgo Studioで作るようになってるんだけど、これは単にUUIDの生成のためだけで、別にボードに書き込んだりするものではないようだ。
また、Base UUIDエンディアンはこの段階でリトルにしておくようだ。
でも、16bit UUIDは直値で書いている。これはnRF51822がリトルエンディアンで動いているからそれでよいってことかいな。
#define LBS_UUID_BASE {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00}
あとは実装の細かいところになるから、もういいかな。
と思ったんだけど、p.24が気になった。
訳し方が間違ってるような気がする・・・。4.4.4 Handling stack events
stackイベントは、なにかしらアプリケーションに通知する必要がある場合に発生する。
このアプリでは、LED characteristicに書き込んだとき(必要とするならば)。
4.4.4.2 Removing handling of CCCD writes
既存のイベントハンドラ(Battery Serviceのね)はCCCDへの書き込み操作をlistenするようにしてあるが、このアプリでは不要。
sd_ble_gatts_hvx()のドキュメントでは「CCCDが有効でないなら通知は許可しない」といっているので、このアプリではチェックしなくてよい。
「if the CCCD is not enabled」って書いてあるけど、S110は自動でCCCDを付加するんじゃないっけ?
そうじゃなくて、そもそもCCCDへの書き込みを行わないから関係ない?
BASのCharacteristicを見ると、Client Characteristic Configurationへの読み書きが必須になっているな。今回作るサービスではCCCDがないから、書き込みを通知する必要は無いから、ハンドラは削除してよいだろう。
それはわかるのだが、sd_ble_gatts_hvx()がなんでCCCDの有無と関係するのかと、今回のサービスはCCCDが無いけどsd_ble_gatts_hvx()でエラーになるんじゃないのか、というのがわかってない。
NotifyかIndicateをサポートするcharacteristicでは自動的にCCCDを付加する、というのがあった、あれのおかげなのか?
じゃあ、sd_ble_gatts_hvx()がCCCDのチェックをすること自体、意味が無いだろうし。。。
とりあえず、この節で「ハンドラを外しましょう」といってるのは、on_write()に書かれているCCCDへの書き込みかどうかを判定する処理を指している、ということはわかった。
あとは、やっぱり自分で書きながら試した方がよさそうだ。
よさそうなのはいいんだけど、どちらかといえば問題になるのはCentral。
Nordicの評価ボードはUARTがついてるみたいで、それをCOMポートと接続してPCから制御できるようなのだ。
それがMaster Control Panelというアプリだと思う。
じゃあ使えんか、と思うのだが、Android 4.3用にnRF Master Control Panelというアプリがある。
これなら使えそうやん!と思ったのだが・・・Android Lのプレビュー版をインストールしたためか、インストールに失敗するようになったのよね・・・。
iOSにはMaster Control Panelに相当するものが無い。
うーむ。
まあ、LightBlueで十分な気もするんだけどね。
とにかく、Peripheralの開発にはCentralも必要になるので、手軽な使える環境を用意しておかないと。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。