Texus Instruments の SensorTag (CC2541) を触る機会があったので、またもラズパイから操作してみました。
技術情報がオープンになっているので非常にわかりやすいです。
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 秒くらいの間隔で計測データが通知されていることを確認できました。