Texus Instruments の SensorTag (CC2541) を触る機会があったので、またもラズパイから操作してみました。
技術情報がオープンになっているので非常にわかりやすいです。
- SensorTag User's Guide
http://processors.wiki.ti.com/index.php/SensorTag_User_Guide
- SensorTag attribute table
(ググるとPDFの表が出てきます)
外形はこんな感じ。赤い筐体がかっこいいです。
それでは SensorTag のプライマリサービスを見てみましょう。
$ sudo ./gatttool -i hci0 -b 78:A5:04:19:6D:DB -I [78:A5:04:19:6D:DB][LE]> connect Attempting to connect to 78:A5:04:19:6D:DB Connection successful [78:A5:04:19:6D:DB][LE]> primary attr handle: 0x0001, end grp handle: 0x000b uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle: 0x000c, end grp handle: 0x000f uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle: 0x0010, end grp handle: 0x0022 uuid: 0000180a-0000-1000-8000-00805f9b34fb attr handle: 0x0023, end grp handle: 0x002a uuid: f000aa00-0451-4000-b000-000000000000 attr handle: 0x002b, end grp handle: 0x0035 uuid: f000aa10-0451-4000-b000-000000000000 attr handle: 0x0036, end grp handle: 0x003d uuid: f000aa20-0451-4000-b000-000000000000 attr handle: 0x003e, end grp handle: 0x0048 uuid: f000aa30-0451-4000-b000-000000000000 attr handle: 0x0049, end grp handle: 0x0054 uuid: f000aa40-0451-4000-b000-000000000000 attr handle: 0x0055, end grp handle: 0x005c uuid: f000aa50-0451-4000-b000-000000000000 attr handle: 0x005d, end grp handle: 0x0061 uuid: 0000ffe0-0000-1000-8000-00805f9b34fb attr handle: 0x0062, end grp handle: 0x0068 uuid: f000aa60-0451-4000-b000-000000000000 attr handle: 0x0069, end grp handle: 0x0073 uuid: f000ccc0-0451-4000-b000-000000000000 attr handle: 0x0074, end grp handle: 0xffff uuid: f000ffc0-0451-4000-b000-000000000000
この中で加速度データに関するサービスの uuid は f000aa10-0451-4000-b000-000000000000 で、 関連する characteristic のハンドル番号は 0x2b 〜 0x35 が割り当てられていることがわかります。
それぞれの characteristic のタイプをみてみましょう。
[78:A5:04:19:6D:DB][LE]> char-desc 0x002b 0x0035 handle: 0x002b, uuid: 00002800-0000-1000-8000-00805f9b34fb handle: 0x002c, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x002d, uuid: f000aa11-0451-4000-b000-000000000000 handle: 0x002e, uuid: 00002902-0000-1000-8000-00805f9b34fb handle: 0x002f, uuid: 00002901-0000-1000-8000-00805f9b34fb handle: 0x0030, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0031, uuid: f000aa12-0451-4000-b000-000000000000 handle: 0x0032, uuid: 00002901-0000-1000-8000-00805f9b34fb handle: 0x0033, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x0034, uuid: f000aa13-0451-4000-b000-000000000000 handle: 0x0035, uuid: 00002901-0000-1000-8000-00805f9b34fb
"SensorTag attribute table" と見比べていくと、SensorTag で加速度サービスを 使うのに必要そうなハンドル番号は以下のようです。
- ハンドル番号=0x2d 加速度の読み出し
- ハンドル番号=0x2e 通知モードの設定
- ハンドル番号=0x31 レンジの設定
- ハンドル番号=0x34 計測間隔時間の設定
それでは、gatttool のインタラクティブモードを使って SensorTag を操作するコマンドを以下に記述していきます。
(1) SensorTagとの接続開始
コマンド:connect
(2) 計測値のレンジの設定(ハンドル番号=0x31)
使用するレンジに応じて設定値が異なる。 またデフォルトでは加速度の計測が無効になっていることに注意。 無効 → 0x00(デフォルト) ±2G→ 0x00 ±4G→ 0x02 ±8G→ 0x03
コマンド:char-write-cmd 0x31 01
(3) 計測間隔時間の設定(ハンドル番号=0x34)
計測間隔は最小100ms/最大1000ms(デフォルト)で、設定値は10分の1の値を指定する。 最小とする場合:100ms → 100x0.1=10 → 0x0A
コマンド:char-write-cmd 0x34 0a
(4) 通知モードの設定(ハンドル番号=0x2e)
SensorTag から加速度データの通知の有無を設定する。 通知なし→ 0x0000 (デフォルト) 通知あり→ 0x0100
コマンド:char-write-cmd 0x2e 0100 (通知ありに変更)
コマンド:char-write-cmd 0x2e 0000 (通知なしに変更)
(5) SensorTag との接続終了
コマンド:disconnect
実行例は以下のようになりました。
$ sudo gatttool -i hci0 -b 78:A5:04:19:6D:DB -I [78:A5:04:19:6D:DB][LE]> connect (1) Attempting to connect to 78:A5:04:19:6D:DB Connection successful [78:A5:04:19:6D:DB][LE]> char-write-cmd 0x31 01 (2) [78:A5:04:19:6D:DB][LE]> char-write-cmd 0x34 0a (3) [78:A5:04:19:6D:DB][LE]> char-write-cmd 0x2e 0100 (4) Notification handle = 0x002d value: 3e 07 f3 Notification handle = 0x002d value: 3e 07 f3 Notification handle = 0x002d value: 3d 06 f3 Notification handle = 0x002d value: 3e 06 f3 Notification handle = 0x002d value: 3c 06 f3 Notification handle = 0x002d value: 3d 06 f2 Notification handle = 0x002d value: 3d 06 f2 Notification handle = 0x002d value: 3c 05 f4 ...(snipped)... [78:A5:04:19:6D:DB][LE]> char-write-cmd 0x2e 0000 [78:A5:04:19:6D:DB][LE]> disconnect (5) [78:A5:04:19:6D:DB][LE]> exit $
(4)のコマンドを入力すると、加速度データが SensorTag から順次通知されてきます。
gatttool では通知がきた時刻がわからないため、(3)のコマンドで設定した計測間隔100ms なのか確認できません。
そこで、gatttool のソースを修正してリコンパイルしてみました。
$ tar xfJ bluez-5.23.tar.xz $ cd bluez-5.23 $ cp attrib/interactive.c{,.ORG} $ vi attrib/interactive.c $ make
bluez-5.23.tar.xz を bluez.org からダウンロードし、 展開してできる attrib/interactive.c を次のように修正。
修正前
static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data) { uint8_t *opdu; uint16_t handle, i, olen; size_t plen; GString *s; handle = get_le16(&pdu[1]); switch (pdu[0]) { case ATT_OP_HANDLE_NOTIFY: s = g_string_new(NULL); g_string_printf(s, "Notification handle = 0x%04x value: ", handle); break;
修正後
static void my_g_string_printf_with_time(GString *s, uint16_t handle) { struct timeval myTime; struct tm *time_st; gettimeofday(&myTime, NULL); time_st = localtime(&myTime.tv_sec); g_string_printf(s, "%d/%02d/%02d %02d:%02d:%02d.%06d Notification handle = 0x%04x value: ", time_st->tm_year+1900, time_st->tm_mon+1, time_st->tm_mday, time_st->tm_hour, time_st->tm_min, time_st->tm_sec, myTime.tv_usec, handle); } static void events_handler(const uint8_t *pdu, uint16_t len, gpointer user_data) { uint8_t *opdu; uint16_t handle, i, olen; size_t plen; GString *s; handle = get_le16(&pdu[1]); switch (pdu[0]) { case ATT_OP_HANDLE_NOTIFY: s = g_string_new(NULL); /* g_string_printf(s, "Notification handle = 0x%04x value: ", handle); */ my_g_string_printf_with_time(s, handle); break;
この改造版 attrib/gatttool で実行するとマイクロ秒単位での時刻付きで表示されます。
$ sudo attrib/gatttool -i hci0 -b 78:A5:04:19:6D:DB -I [78:A5:04:19:6D:DB][LE]> connect Attempting to connect to 78:A5:04:19:6D:DB Connection successful [78:A5:04:19:6D:DB][LE]> char-write-cmd 0x31 01 [78:A5:04:19:6D:DB][LE]> char-write-cmd 0x34 0a [78:A5:04:19:6D:DB][LE]> char-write-cmd 0x2e 0100 2016/11/12 19:23:26.818633 Notification handle = 0x002d value: fb 02 42 2016/11/12 19:23:26.886093 Notification handle = 0x002d value: ff 04 42 2016/11/12 19:23:27.021098 Notification handle = 0x002d value: 00 06 41 2016/11/12 19:23:27.088594 Notification handle = 0x002d value: 00 06 41 2016/11/12 19:23:27.223609 Notification handle = 0x002d value: fe 04 41 2016/11/12 19:23:27.291091 Notification handle = 0x002d value: ff 06 41 2016/11/12 19:23:27.358580 Notification handle = 0x002d value: ff 03 42 2016/11/12 19:23:27.493601 Notification handle = 0x002d value: fe 06 40 2016/11/12 19:23:27.561082 Notification handle = 0x002d value: fe 04 3f 2016/11/12 19:23:27.696095 Notification handle = 0x002d value: 00 06 41 ...(snipped)... [78:A5:04:19:6D:DB][LE]> char-write-cmd 0x2e 0000 [78:A5:04:19:6D:DB][LE]> disconnect [78:A5:04:19:6D:DB][LE]> exit $
目測ではありますが、設定通りに 0.1 秒くらいの間隔で計測データが通知されていることを確認できました。