アルプスのセンサネットワークモジュールをラズパイ3と3GPIで使ってみる（其の1 BLEパケット構造解析）

[メカトラックス株式会社様](http://www.mechatrax.com/)より、[アルプスのセンサネットワークモジュール](http://www.alps.com/j/iotsmart-network/index.html)をお借りすることができました。アルプスのセンサネットワークモジュールは、Bluetooth Low Energy(BLE)を用いて、モーションデータと共に、気圧、温度・湿度などの環境データを取得できます。今回は、センサネットワークモジュールを、BLEを用いて、次のようにRaspberry Pi 3と接続しました。<br>
<div align="center" ><img src="https://qiita-image-store.s3.amazonaws.com/0/124811/2d8f1281-9335-3bfc-82b6-971d7cb9afc6.jpeg"></div>

>写真ではRaspberry Pi 3の上に、メカトラックス株式会社様の[3GPI(Raspberry Pi向け3G通信モジュール)](http://www.mechatrax.com/products/3gpi)を載せています。最終的には、センサネットワークモジュールで取得した環境データを3GPI経由でネットワーク上にアップロードします。なお、今回提供された3GPIに同梱されている接続設定済Raspbian入microSDカードは、現状(2016/08/17現在)のままだと、Bluetoothのデバイスを認識しませんでした。Raspbianのアップデート方法をこのブログの最後に記述しておきます。


Bluezのコマンド「gatttool」を使って、アルプスのセンサネットワークモジュールとRaspberry Pi 3とBLE接続し、温度データ、湿度データ、気圧データを取得します。同時に、BLE接続に使用しているBLEパケットをパケットキャプチャソフト「tshark」を使ってキャプチャし、BLEパケットの構造解析を行います。なお、Raspberry Pi 3にtsharkのインストールする方法およびその使用方法については、「[tsharkによるBLEパケットのキャプチャ ](http://tomosoft.jp/design/?p=7362)」を参照ください。

# センサネットワークモジュールから環境データの取得
Bluezのコマンド「gatttool」を使って、最初にセンサネットワークモジュールのアドレスの取得し、次に、取得したセンサネットワークモジュールのアドレスを使用して、対話的にセンサネットワークモジュールのセンサー情報を読み出します。

## センサネットワークモジュールのアドレスの取得
センサネットワークモジュールを接続するには、BD(Bluetooth Device)アドレスを必要とするため、センサネットワークモジュールの下部のスイッチをONにして、次のhcitoolコマンドを実行します。Bluetoothのネットワークスキャンにより、センサネットワークモジュールが検出されると、その結果が表示されます。センサネットワークモジュールのアドレスが「28:A1:83:E1:58:96」、名称が「SNM00」になっていることがわかります。

```
$  sudo hcitool lescan
LE Scan ...
28:A1:83:E1:58:96 SNM00
28:A1:83:E1:58:96 (unknown)
(ctrl c) 
```

## 対話的なセンサー情報の読み込み
Raspberry Pi 3で、Bluezのコマンド「gatttool」を使って、対話的にセンサネットワークモジュールのセンサー情報を読み込みます。センサネットワークモジュールのコマンドガイド「[Sensor Network Module評価キットApplication Note Command Guide](http://www.alps.com/j/iotsmart-network/pdf/msm_command_manual.pdf)」の「2.2 コマンドによる設定例」を参考にして、次のような設定にしました。

|　　設定　|　 機能|
|:--|:--|
|計測モード|Slowモード|
|計測間隔|1分|
|Acceleration|－|
|Geo-Magnetic|－|
|Pressure|〇|
|Humidity|〇|
|Temperature|〇|
|UV|－|
|Ambient Light|－|

センサネットワークモジュールのコマンドガイドの「Appendix1 Service1 Database」に記述されているService1のパケットデータは、gatttoolコマンドの「char-write-req」を使用すると出力できます。char-write-reqで与える二つのパラメータのうち、最初のパラメータは「Attribute Handle」、二番目のパラメータは、センサネットワークモジュールのコマンドガイドの「4. コマンド構造 (Custom3)」に従ってコマンドを設定します。gatttoolコマンドの実行時のパラメータ、および対話的に入力するchar-write-reqのデータを次に示します。

```
gatttool -i hci0 -b 28:A1:83:E1:58:96 -I 
connect
char-write-req 0x0018 200300
char-write-req 0x0018 230301

char-write-req 0x0013 0100
char-write-req 0x0016 0100

char-write-req 0x0018 2F0303
char-write-req 0x0018 01031C
char-write-req 0x0018 040300
char-write-req 0x0018 05043C00

char-write-req 0x0018 200301
char-write-req 0x0018 230300
```

gatttoolコマンドのchar-write-reqを使用し、センサネットワークモジュールにパケットデータを出力した結果を、次に示します。最後に表示されている「```Notification handle = 0x0012 value: f3 14 c8 e2 76 16 4f 0d 00 80 00 80 00 00 00 00 01 0a 0f 02」と「Notification handle = 0x0012 value: f3 14 c8 e2 76 16 4f 0d 00 80 00 80 00 00 00 00 01 0a 0f 02```」がセンサネットワークモジュールからのデータパケットとなります。

```
$ gatttool -i hci0 -b 28:A1:83:E1:58:96 -I
[28:A1:83:E1:58:96][LE]> connect
Attempting to connect to 28:A1:83:E1:58:96
Connection successful
[28:A1:83:E1:58:96][LE]> char-write-req 0x0018 200300
Characteristic value was written successfully
[28:A1:83:E1:58:96][LE]> char-write-req 0x0018 230301
Characteristic value was written successfully
[28:A1:83:E1:58:96][LE]> char-write-req 0x0013 0100
Characteristic value was written successfully
Notification handle = 0x0012 value: e0 14 00 00 00 00 00 9b 0b 00 01 00 00 00 00 00 00 00 00 00
[28:A1:83:E1:58:96][LE]> char-write-req 0x0016 0100
Characteristic value was written successfully
[28:A1:83:E1:58:96][LE]> char-write-req 0x0018 2F0303
Characteristic value was written successfully
Notification handle = 0x0012 value: e0 14 00 00 00 00 d3 9f 0b 00 01 00 00 00 00 00 00 00 00 00
[28:A1:83:E1:58:96][LE]> char-write-req 0x0018 01031C
Characteristic value was written successfully
Notification handle = 0x0012 value: e0 14 00 00 00 00 d3 9f 0b 00 01 00 00 00 00 00 00 00 00 00
[28:A1:83:E1:58:96][LE]> char-write-req 0x0018 040300
Characteristic value was written successfully
Notification handle = 0x0012 value: e0 14 00 00 00 00 d3 9f 0b 00 01 00 00 00 00 00 00 00 00 00
[28:A1:83:E1:58:96][LE]> char-write-req 0x0018 05043C00
Characteristic value was written successfully
Notification handle = 0x0012 value: e0 14 00 00 00 00 d3 9f 0b 00 01 00 00 00 00 00 00 00 00 00
[28:A1:83:E1:58:96][LE]> char-write-req 0x0018 200301
Characteristic value was written succe
ssfully
Notification handle = 0x0012 value: e0 14 00 00 00 00 d3 9f 0b 00 01 00 00 00 00 00 00 00 00 00
Notification handle = 0x0012 value: f2 14 00 80 00 80 00 80 00 80 00 80 00 80 00 00 24 09 00 00
Notification handle = 0x0012 value: f3 14 ce e2 75 16 52 0d 00 80 00 80 00 00 00 00 01 0a 0f 00
[28:A1:83:E1:58:96][LE]> char-write-req 0x0018 230300
Characteristic value was written successfully
Notification handle = 0x0012 value: e0 14 00 00 00 00 d3 9f 0b 00 01 00 00 00 00 00 00 00 00 00
Notification handle = 0x0012 value: f2 14 00 80 00 80 00 80 00 80 00 80 00 80 00 00 24 0a 00 01
Notification handle = 0x0012 value: f3 14 ce e2 71 16 50 0d 00 80 00 80 00 00 00 00 01 0a 0f 01
Notification handle = 0x0012 value: f2 14 00 80 00 80 00 80 00 80 00 80 00 80 00 00 24 0b 00 02
Notification handle = 0x0012 value: f3 14 c8 e2 76 16 4f 0d 00 80 00 80 00 00 00 00 01 0a 0f 02
Notification handle = 0x0012 value: f2 14 00 80 00 80 00 80 00 80 00 80 00 80 00 00 24 0c 00 03
[28:A1:83:E1:58:96][LE]> exit

(gatttool:837): GLib-WARNING **: Invalid file descriptor.
```

# tsharkによるBLEパケットの解析
Raspberry Pi 3によりgatttoolコマンドで、センサネットワークモジュールから、温度データ、湿度データ、気圧データを取得しましたが、この時同時に、パケットキャプチャソフト「tshark」でBLEパケットをキャプチャします。このキャプチャしたBLEパケットとBluetooth仕様書「[Specification of the Bluetooth system　Core_v4.2](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439)」を対応させてパケット構造を解析します。また、センサネットワークモジュールのコマンドガイド「[Sensor Network Module評価キットApplication Note Command Guide](http://www.alps.com/j/iotsmart-network/pdf/msm_command_manual.pdf)」とキャプチャしたBLEパケットを対応させて構造解析します。

## BLEプロトコルスタックアーキテクチャ
BLE通信を実現するプロトコルスタックは、次のような階層構造を持っています。左側には、ATTとL2CAOのパケット構造を示します。
<div align="center" "><img src="https://qiita-image-store.s3.amazonaws.com/0/124811/bdf803c7-66a3-b5b5-77a8-c4ff030da935.jpeg"></div>

パケットキャプチャソフト「tshark」では、次のレイヤのBLEパケットがキャプチャできます。

<dt>ATT (Attribute Protocol)</dt>
<dd>上位レイヤのGATT通信を実現する通信手順の仕様を規定しています。センサネットワークモジュールのコマンドガイドは、このレイヤのBLEパケットフォーマットを規定しています。
・データ構造の形式
・データの読み書き
・データの更新通知
・データの分割と復元
</dd>

<dt>L2CAP (Logical Link Control and Adaptation Protocol)</dt>
<dd>ホスト部とコントローラ部の橋渡しとなる通信制御を規定しています。
・セッションの制御/管理
・パケットの分割と復元
</dd>
<dt>HCI (Host Controller Interface)</dt>
<dd>ホスト部とコントローラ部を接続するデータ通信の仕様を規定しています。このレイヤーのフォーマットについては、「[Rasberry Pi 3でのBLEのパケット構造解析] (http://tomosoft.jp/design/?p=7385)」を参照してください。
</dd>
</dl>

## L2CAPでのBLEバケット構造解析
Raspberry Pi 3とセンサネットワークモジュール間でBLE接続が完了すると、センサネットワークモジュールから「Connection Parameter Update Request (0x12)」のBLEパケットが転送され、Raspberry Pi 3は、その応答を返します。次にtsharkでキャプチャしたRaspberry Pi 3とセンサネットワークモジュール間のBLEパケットのシーケンスを示します。<br>
<div align="center" "><img src="https://qiita-image-store.s3.amazonaws.com/0/124811/01ca04c4-dfb4-2180-a55a-5d5ee87b78c2.jpeg"></div>


センサネットワークモジュールから送られてきた「Connection Parameter Update Request (0x12)」のパケットフォーマットを示します。このBLEパケットフォーマットは上記のFrame 15を示します。詳細なフォーマットは、Bluetooth仕様書「[Vol 3, Part A] 4.20 CONNECTION PARAMETER UPDATE REQUEST (CODE 0x12)」を参照してください。

```
Frame 15: 21 bytes on wire (168 bits), 21 bytes captured (168 bits) on interface 0
Bluetooth L2CAP Protocol
    Length: 12
    CID: Low Energy L2CAP Signaling Channel (0x0005)
    Command: Connection Parameter Update Request
        Command Code: Connection Parameter Update Request (0x12)
        Command Identifier: 0xd1
        Command Length: 8
        Min. Interval: 144 (180 msec)
        Max. Interval: 160 (200 msec)
        Slave Latency: 4 LL Connection Events
        Timeout Multiplier: 600 (6 sec)
```


## ATTでのBLEバケット構造解析
ATTレイヤーを使用して、Raspberry Pi 3とセンサネットワークモジュール間で、Raspberry Pi 3からセンシング設定、Bluetooth® Smart設定、動作指示、システムのコマンド（センサネットワークモジュールのコマンドガイド「3. コマンド表」）をセンサネットワークモジュールにパケット送信し、センサネットワークモジュールからデータパケット1と2、および、ステータス通知（センサネットワークモジュールのコマンドガイド「5. 通知データ構造 (Custom1)」）をRaspberry Pi 3が受け取ります。次にtsharkでキャプチャしたRaspberry Pi 3とセンサネットワークモジュール間のBLEパケットのシーケンスを示します。<BR>
<div align="center" "><img src="https://qiita-image-store.s3.amazonaws.com/0/124811/9c15b118-a921-435b-b869-14a9bef53869.jpeg"></div>

ATTレイヤーでの「Write Request」パケットフォーマットを次に示します。Write Requestパケットフォーマットに示されている「```Handle: 0x0018```」は、センサネットワークモジュールのAttribute Handleを示します。「```Value: 200300```」はセンサネットワークモジュールの動作指示コマンドを示します。詳細なフォーマットについては、Bluetooth仕様書「[Vol 3, Part F]　3.4.5 Writing Attributes」とセンサネットワークモジュールのコマンドガイド「4.3動作指示コマンド」を参照してください。

```
Frame 22: 15 bytes on wire (120 bits), 15 bytes captured (120 bits) on interface 0
Bluetooth L2CAP Protocol
    Length: 6
    CID: Attribute Protocol (0x0004)
Bluetooth Attribute Protocol
    Opcode: Write Request (0x12)
        0... .... = Authentication Signature: False
        .0.. .... = Command: False
        ..01 0010 = Method: Write Request (0x12)
    Handle: 0x0018
    Value: 200300
```

ATTレイヤーでの「Handle Value Notification」パケットフォーマットを次に示します。Handle Value Notificationパケットフォーマットに示されている「```Handle: 0x0012```」はセンサネットワークモジュールのAttribute Handleを示します。「```Value: f314cee27516520d0080008000000000010a0f00```」はセンサネットワークモジュールのデータパケット2を示します。詳細なフォーマットについては、Bluetooth仕様書「[Vol 3, Part F]　3.4.7.1 Handle Value Notification」とセンサネットワークモジュールのコマンドガイド「5.2 データパケット2」に示します。

```
Frame 56: 32 bytes on wire (256 bits), 32 bytes captured (256 bits) on interface 0
Bluetooth L2CAP Protocol
    Length: 23
    CID: Attribute Protocol (0x0004)
Bluetooth Attribute Protocol
    Opcode: Handle Value Notification (0x1b)
        0... .... = Authentication Signature: False
        .0.. .... = Command: False
        ..01 1011 = Method: Handle Value Notification (0x1b)
    Handle: 0x0012
    Value: f314cee27516520d0080008000000000010a0f00
```

# 3GPI用Raspbianのアップデート方法
今回提供された3GPIに同梱されているRaspbianでは、次に示すようにRaspberry Pi 3でhciconfigコマンドを入力してBluetoothデバイスを確認しても、Bluetoothデバイスが認識されませんでした。

```
$ sudo hciconfig
```

[メカトラックス株式会社様](http://www.mechatrax.com/)に問い合わせて、確認したところ、次の手順でRaspbianをアップデートすれば、Bluetoothデバイスが認識できるようになりました。なお、最終的には、Raspberry Pi 3でもBluetoothデバイスが認識できるRaspbianが、近日中にリリースされるそうです。


1. 次のコマンドでインストールされているパッケージを更新します。
<pre>
$  sudo apt-get update
$  sudo apt-get upgrade
</pre>

2. 次のコマンドでBluetoothパッケージをインストールします。
<pre>
$  sudo apt-get install pi-bluetooth
$  sudo systemctl enable bluetooth.service
$  sudo systemctl enable hciuart.service
</pre>

3. 次のコマンドで「99-com.rules.dpkg-dist」 を 「99-com.rules」 にリネームします（使用していたファイルは保存します）。
<pre>
$  sudo cp /etc/udev/rules.d/99-com.rules /etc/udev/rules.d/99-com.rules.old
$  sudo cp /etc/udev/rules.d/99-com.rules.dpkg-dist　/etc/udev/rules.d/99-com.rules
</pre>

4. 再起動します。
<pre>
$  sudo reboot</pre>

5. 再起動後、次のコマンドでBluetoothデバイスを確認します。「hci0」が表示されれば Bluetoothデバイスが認識されています。
<pre>
$  sudo hciconfig
hci0:   Type: BR/EDR  Bus: UART
        BD Address: B8:27:EB:2E:E0:10  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING
        RX bytes:717 acl:0 sco:0 events:42 errors:0
        TX bytes:1532 acl:0 sco:0 commands:42 errors:0
</pre>


#　関連URL

1. [アルプスのセンサネットワークモジュールをラズパイ3と3GPIで使ってみる（其の2 C言語によるBLEソフト）](http://qiita.com/TomoSoft/items/8e211f29002c38fd2488) 
2. [アルプスのセンサネットワークモジュールをラズパイ3と3GPIで使ってみる（其の3 Googleスプレッドシートへのセンサ情報の保存）](http://qiita.com/TomoSoft/items/4ac6c411f1cfdd128a4c)