叶鋼は午前1時に計算をする

電子工作と計算の記録

【BLEを使う】mbed HRM1017サンプルプログラムのプロトコル解析 その3

鼻行類という名前がまさに示すとおり、その共通の特徴は鼻が特殊な構造をしていることである。

鼻は1個のこともあり、多数存在することもある。

ムカシハナアルキ属(Archirrhinos)を除く鼻行類では、鼻器が移動のための器官となっているから、四肢は移動器官としての機能を失っている。

鼻行類」より引用

いままでの記事はこちらをご覧ください。

 

前回からだいぶ間が空いてしまいましたが、データパケットの送受信について解析します。

前回のadvertisingパケット、スキャンパケット、接続要求パケットのやり取りを通して接続状態になると、マスターとスレーブでのデータパケットの送受信が開始されます。

 

・Pull型とPush型のデータアクセス

データパケットの通信には2種類あります。Pull型のデータアクセスとPush型のデータアクセスです。

Pull型のデータアクセスは、マスターからの読み込み要求を受けて、スレーブがデータを返します。

 

通信中、マスターからの読み込み要求がないときは、connIntervalの時間間隔(ここでは約30msec)でマスターからスレーブへData Type : Empty PDUのパケット送信します。

スレーブからマスターにも同じくData Type : Empty PDUのパケットを送信しています。

 

実際に、何もないときはひたすらにEmpty PDUの応酬を繰り返しているだけなのが確認できます。

(スレーブレーテンシーを設定していれば、設定した回数だけスレーブからマスターへのEmpty PDUは省略されることになります。)

f:id:yegang:20140913143020j:plain

マスターからの読み込み要求があるときはマスターからスレーブにData Type : Control やData Type : L2CAP-Sのパケットを送信します。

それに対して、スレーブは必ずData Type : Empty PDUもしくは一つ前の要求に対する応答を返します。

これは、マスターからの要求に対して、スレーブがすぐにデータを用意できないためです。そのためスレーブの応答は、マスターの要求に対して必ずコネクション・イベント1回分遅れます。

 

実際に以下の図で示すように、①のマスターからスレーブへの要求に対する応答は次のコネクション・イベント時のスレーブからマスターへの応答①において行われ、②のマスターからスレーブへの要求に対する応答は次のコネクション・イベント時のスレーブからマスターへの応答②において行われています。

f:id:yegang:20140913143104j:plain

Push型アクセスは、スレーブがマスターからの要求を必要とせずに、スレーブからマスターへデータを送ることができます。

つまり、NotifyやIndicateによるアクセスのことです。

スレーブでNotifyやIndicateの発生要因となるデータ変化があると、その直後のコネクション・イベントにおいてNotifyやIndicateによるスレーブからマスターへのデータ送信を行います。

 

実際のNotifyによるデータ送信を以下に示します。

P.nbr.287の後にスレーブにおいてNotify発生要因となるデータ変化があったようで、P.nbr.288とP.nbe.289のコネクション・イベントでデータを送信しています。

f:id:yegang:20140913143240j:plain

Pull型アクセスと異なり、Notifyが発生する1つ前のP.nbr.286のコネクション・イベントにおいてマスターからスレーブへの要求はなくEmpty PDUになっています。

Push型アクセスはマスターからの要求を必要としていないことが分かります。

Push型アクセスはデータ変化があるとすぐにそれをマスターに報せることができます。

接続の回数が少なくて済み、データ容量の軽いEmpty PDUの割合が多くなるので、低消費電力にもなります。

 

ここでついでにIndicateの場合も紹介します。

f:id:yegang:20140913143307j:plain

マスターからの要求がなくともP.nbr.291でスレーブからマスターへのデータ送信をしているのは、Notifyと同じです。

異なるのは次のコネクション・イベントのP.nbr.292でマスターからスレーブへの応答があることです。

 

・データチャンネルパケット

次は実際のデータパケットの構造について調べてみます。

ちなみに、以下のブログの「通信」以降の解説が分かりやすくまとまっています。

そちらを読むほうが、私のいいかげんな記事を見るよりは(以下略)

http://reinforce-lab.github.io/blog/2013/08/13/blebook-ch2-ble-spec/

データチャンネルパケットは以下の構造を持ちます。

f:id:yegang:20140913143505j:plain

BLUETOOTH SPECIFICATION Version 4.0 [Vol 6] 45ページ 2.4 DATA CHANNEL PDUより引用)

パケットの中身を見る前に、ヘッダーの各設定の意味を簡単に解説します。

 

・LLID(Logical Link ID)

LLIDはそのパケットがデータ用か制御用かを示しています。

LLIDの値内容
01b LL Data PDU :続きのあることを示すFragment
もしくはEmpty PDU
10b LL Data PDU :最初か最後であることを示すFragment
11b LL Control PDU(制御用)

 

NESN

次のシーケンス番号の期待値を示します。

 

・SN

シーケンス番号を示します。

 

NESNとSNは通信が正常に行われているかを確認するために使われます。

f:id:yegang:20140913143715j:plain

上の図に示したように、接続直後はNESN=0とSN=0から開始します。

マスターからスレーブへのパケット送信に成功すると、次回のスレーブからマスターへ送信するパケットではNESNを1にします。

するとマスターはNESNが1であるのを確認して、マスターからスレーブへSNを1にしたパケットを送信します。

もしここでスレーブからマスターのパケットでNESNが0だった場合、転送は失敗したことを意味し、マスターはNESNが0であるのを確認して、前に転送したSN=0のパケットをもう1度再送します。

 

スレーブがマスターからSN=1のパケット受信に成功したときは、マスターへNESN=0を送信します。

そしてマスターはNESN=0を確認して、SN=0を送信します。

ここでマスターがNESN=1を受信すれば、前に転送したSN=1のパケットをもう1度再送します。

このようにSNとNESNが1と0の組み合わせを繰り返しながら、フロー制御を行います。

 

・MD(More Data)

装置に他の転送データが有るか無いかを示します。

MD=0で続きのデータはなく、MD=1ならば次のコネクション・イベントにおいてパケットの送信を継続します。

 

・Length

payloadとMICを足したbyte長さを示します。Empty PDUならば0になります。

 

 

以上がヘッダーの意味になります。次はpayloadについて調べてみます。

・LL Control PDU

制御用のパケットについて確認します。

制御用のパケットのpayloadは以下の構造を持ちます。

f:id:yegang:20140913143856j:plain

BLUETOOTH SPECIFICATION Version 4.0 [Vol 6] 46ページ 2.4.2 LL Control PDUより引用)

 

接続直後、最初にマスターとスレーブ間で送受信されるデータパケットが以下の制御用パケットでした。

f:id:yegang:20140913144424j:plain

LLID=0x03なのでData TypeがControlになっています。

マスターからスレーブの送信はNESN=0とSN=0で開始し、次のコネクション・イベントのスレーブからマスターの送信ではNESN=0とSN=1になっており、正常に送受信が進んでいることが分かります。

MD=0なので他の転送データはないようです。

payloadの長さは6bytesです。

 

・Opcode (1byte)

Opcode=0x0Cはバージョン通知を意味します。

 

・CtrData

バージョン通知のデータは以下の構造を持ちます。

f:id:yegang:20140913144109j:plain

BLUETOOTH SPECIFICATION Version 4.0 [Vol 6] 51ページ 2.4.2.13 LL_VERSION_INDより引用)

 

VerNrはBluetoothコントローラ規格のバージョンを示します。

番号については以下を参照ください。

https://www.bluetooth.org/en-us/specification/assigned-numbers/link-manager

マスター側もスレーブ側も0x06で、Bluetooth Core Specification 4.0であることを示しています。

 

CompidはBluetoothコントローラ製造者識別番号を示します。

番号については以下を参照ください。

https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers

マスター側は0x0FなのでBroadcom Corporation、スレーブ側は0x59なのでNordic Semiconductor ASA(つまりNORDIC製のnRF51822)になります。

SubVerNrは実装しているBluetoothコントローラの一意的な値もしくは改訂番号を示します。

 

通信中に確認できた他の制御用パケットにはOpcode=0x00のLL_CONNECTION_UPDATE_REQ やOpcode=0x01のLL_CHANNEL_MAP_REQがありました。

ここでは詳細を調べませんが、これらは接続パラメータの更新を行うためのパケットで、マスターからスレーブへの送信のみになります。

f:id:yegang:20140913144639j:plain

f:id:yegang:20140913144646j:plain

 

・LL Data PDU

データ用のパケットについて確認します。

 

実際にサンプルプログラムが利用しているのは温度計サービスとバッテリーサービスです。

これらのデータがどのように送信されているかに注目して調べます。

 

マスター(クライアント)とスレーブ(サーバ)間でのやり取りは、Read、Write、Notify、Indicateなどの種類があります。

バッテリーサービスは、スレーブ側のバッテリーにおいてデータ変化があると、それをマスターに報せるNotifyを使います。

温度計サービスは、スレーブ側の温度計のデータ状態をマスターに報せて、マスターからの応答を受け取るIndicateを使います。

 

実際に、接続開始後、以下のようにNotifyとIndicateによるスレーブからマスターへのデータ送信が繰り返されています。

f:id:yegang:20140913144926j:plain

1回分の温度計データとバッテリーデータの送信を抜き出すと以下になります。

f:id:yegang:20140913144950j:plain

まず、マスターからスレーブへEmpty PDUが送信されています。

LLID=0x01でPDU-Lengthが0なのがEmpty PDUの特徴です。

そして、スレーブからマスターへデータ変化検知によるNotifyが送信されています。

LLID=0x02なので、このパケットが最初のデータ(そして、最後のデータ)であることが分かります。

ですが、MD=1なので、送信すべきデータはまだ残っており、次のコネクション・イベントで送信することが示されています。

 

サービスはATTプロトコルによって、やり取りされます。

ATT_Handle_Value_NotifyのOpcode=0x1Bは、Handle Value Notification、Attribute値の変化通知を意味します。

AttValue=0x62=98はバッテリー残量の値です。

 

次のコネクション・イベントでも、例によってマスターからスレーブへEmpty PDUが送信された後、スレーブからマスターへデータ状態を通知するIndicateが送信されています。

今度はMD=0なので、送信すべきデータは全て送信されたことが分かります。

ATT_Handle_Value_IndのOpcode=0x1Dは、Handle Value Indication、Attribute値の状態通知を意味します。

ATT Valueは00 84 00 00 FFです。

HTSを入手して調べると、これはTempature Measurementだと推測できます。

f:id:yegang:20140913145108j:plain

AttValue=0x84=132が温度13.2℃を表しています。

他の値にも意味があると思いますが、まだ調べきれていません。

 

次のマスターからスレーブでは、このIndicate の応答が送信されています。

ATT_Handle_Value_ConfirmのOpcode=0x1Eは、Handle Value Confirmation、状態通知の確認を意味しています。