PowerUp3.0のBLEをHackして自作Appから操作してみた

More than 1 year has passed since last update.


What is PowerUp3.0 ?

紙飛行機に装着して,ケータイから操作可能なラジコン化するキット.

プロペラの回転数と垂直尾翼の角度をコントロールして紙飛行機を自在に操縦できるようになる.

↓ 実物はこんなもの,プロペラのついたちっさいUnitを実物の紙飛行機に装着します.

2017-04-21_010546.JPG

↓ 公式はこちら

https://www.poweruptoys.com/products/powerup-v3


何をしたか?

Android/iOSから操作するためのAppは公式から公開されているが,

ケータイとPowerUp3.0とはBluetoothを使って通信する,とのことだったので,

通信ProtocolをHackすれば自作Appからも操作可能になるはず.

Bluetooth/BLEの勉強も兼ねて,PowerUp3.0を自作Appから操作するまでをまとめてみた.


Step1 : 通信Protocolの特定

Bluetooth通信,と一言でいわれても,ケータイとPowerUp3.0間でどういう通信をしているか,が全く不明なので,解析のとっかかりをつかむためにも,公式App動作中のBluetooth通信をPacket Dumpしてみる.

Androidの開発者設定にHCI Snoop Log有効化のOptionがあるらしく,これを使えば簡単にPacket Logが取れるらしい.

↓ こちらのページが分かりやすかったのでこれを参考に公式AppでPowerUp3.0を操作中のLogを取ってみる.

http://fromnorth.blogspot.jp/2015/02/bluetooth-hci.html

AndroidのADBを有効化 + HCI Snoop Log有効化


PowerUp3.0 公式Appを起動して操作

HCI Snoop Log無効化
(この時点でHCI Logファイルが書き出される)

$adb shell pull /sdcard/btsnoop_hci.log .
でLogファイルを回収(Productによってファイルパスが変わるらしい)

取ったLogをWiresharkで見ると,↓ のようなPacketが大量に取れている.

プロペラ回転数のみを変更していたため,このPacketはプロペラ回転数制御Packetと思われる.

ble_log.png

Bluetooth HCI ACL Packet

HCI (Host Controller Interface)のPacket.

Frameの種類が4種類(HCI Command/Event, ACL Data, SCO Data)あり,そのうちの1つ(ACL)らしい.

非同期通信用のL2CAP Packet用に使われるとのこと.

http://www.wdic.org/w/WDIC/HCI%20(Bluetooth)

Bluetooth L2CAP Protocol

ACLの説明どおり,L2CAP Protocolが使われている.

CID(Channel ID) = 0x0004 → Attribute Protocol

はBluetooth 4.0(= BLE)以降サポートされているものの模様.

http://www.wdic.org/w/WDIC/L2CAP

Bluetooth Attribute Protocol

Opcode: Write Command

によって,

Service UUID = 86c3810ef17140d9a11726b300768cd6

Characteristic UUID = 86c3810e001040d9a11726b300768cd6

に対して,

Value=0a

の書込をしている模様.


Step2 : Android BT/BLE APIでPowerUp3.0のBLE情報をDumpする

使われているProtocolがBLEのAttribute Protocolなことがわかったので,AndroidのPublic APIでPowerUp3.0デバイスのBLEを情報をDumpしてみる.

Bluetooth GATT(Generic Attributes)

https://www.bluetooth.com/ja-jp/specifications/generic-attributes-overview

公式仕様によると,BLEデバイスは↓のような構造で情報を持っている.

GATT                         // BLEデバイスは1つのGATT(GATT Server)をもつ

- Service // GATTは復数(1つ以上)のServiceをもつ
- Characteristic // 1つのServiceは復数(1つ以上)のCharacteristicをもつ
- Value // 1つのCharacteristicは1つのValueをもつ
- Descriptor // 1つのCharacteristicは復数(1つ以上)のDescriptorをもつ
- Descriptor
- Characteristic
- Value
- Descriptor
- Service
- Service // 1つのServiceが復数(1つ以上)のServiceを含むことがある
- Service

これをAndroidのBluetooth APIを使ってすべてDumpすればいい.

Android Developer - Bluetooth Low Energy

https://developer.android.com/guide/topics/connectivity/bluetooth-le.html

↓のBluetoothGattからService取得→Characteristic/DescriptionのReadリクエスト,でOK.

https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html

GATTがもつ全Service/CharacteristicをDumpすると↓のような感じになるはず.


Service/Characteristic=UUID

service = 00001800-0000-1000-8000-00805f9b34fb

chara = 00002a00-0000-1000-8000-00805f9b34fb
chara = 00002a01-0000-1000-8000-00805f9b34fb
chara = 00002a02-0000-1000-8000-00805f9b34fb
chara = 00002a03-0000-1000-8000-00805f9b34fb
chara = 00002a04-0000-1000-8000-00805f9b34fb

service = 00001801-0000-1000-8000-00805f9b34fb
chara = 00002a05-0000-1000-8000-00805f9b34fb

service = 0000180a-0000-1000-8000-00805f9b34fb
chara = 00002a23-0000-1000-8000-00805f9b34fb
chara = 00002a24-0000-1000-8000-00805f9b34fb
chara = 00002a25-0000-1000-8000-00805f9b34fb
chara = 00002a26-0000-1000-8000-00805f9b34fb
chara = 00002a27-0000-1000-8000-00805f9b34fb
chara = 00002a29-0000-1000-8000-00805f9b34fb

service = 0000180f-0000-1000-8000-00805f9b34fb
chara = 00002a19-0000-1000-8000-00805f9b34fb

service = 86c3810e-f171-40d9-a117-26b300768cd6
chara = 86c3810e-0010-40d9-a117-26b300768cd6
chara = 86c3810e-0020-40d9-a117-26b300768cd6
chara = 86c3810e-0021-40d9-a117-26b300768cd6
chara = 86c3810e-0040-40d9-a117-26b300768cd6

service = f000ffc0-0451-4000-b000-000000000000
chara = f000ffc1-0451-4000-b000-000000000000
chara = f000ffc2-0451-4000-b000-000000000000


PowerUp3.0のFirmwareのVersionによってはズレているものもあるかも.


Step3 : 各Characteristicの内容を調べる

[UUID=0000xxxx-0000-1000-8000-00805F9B34FB]

のパターンになっているUUIDが多いが,これはBluetooth Service Discovery Protocolで定められているBase UUIDというもので,特定の機能のために標準で予約されている.

https://www.bluetooth.com/specifications/assigned-numbers/service-discovery

GATT Services

https://www.bluetooth.com/specifications/gatt/services

GATT Characteristics

https://www.bluetooth.com/specifications/gatt/characteristics

[UUID=0451-4000-b000-000000000000]

のパターンが何者なのか不明だったが,TI社製ChipのOAD Service(Over the Air Download)に使うUUIDらしい.

https://e2e.ti.com/support/wireless_connectivity/bluetooth_low_energy/f/538/t/380928

公式App起動時にPowerUp3.0のFirmware Updateが走るときがあり,これに使っているのかな.

各Service/Characteristicをまとめると↓のような感じ


Service/Characteristic=UUID

service = 00001800-0000-1000-8000-00805f9b34fb → 0x1800 Generic Access

chara = 00002a00-0000-1000-8000-00805f9b34fb → 0x2A00 Device Name
chara = 00002a01-0000-1000-8000-00805f9b34fb → 0x2A01 Appearance
chara = 00002a02-0000-1000-8000-00805f9b34fb → 0x2A02 Peripheral Privacy Flag
chara = 00002a03-0000-1000-8000-00805f9b34fb → 0x2A03 Reconnection Address
chara = 00002a04-0000-1000-8000-00805f9b34fb → 0x2A04 Peripheral Preferred Connection Parameters

service = 00001801-0000-1000-8000-00805f9b34fb → 0x1801 Generic Attribute
chara = 00002a05-0000-1000-8000-00805f9b34fb → 0x2A05 Service Changed

service = 0000180a-0000-1000-8000-00805f9b34fb → 0x180A Device Information
chara = 00002a23-0000-1000-8000-00805f9b34fb → 0x2A23 System ID
chara = 00002a24-0000-1000-8000-00805f9b34fb → 0x2A24 Model Number String
chara = 00002a25-0000-1000-8000-00805f9b34fb → 0x2A25 Serial Number String
chara = 00002a26-0000-1000-8000-00805f9b34fb → 0x2A26 Firmware Revision String
chara = 00002a27-0000-1000-8000-00805f9b34fb → 0x2A27 Hardware Revision String
chara = 00002a29-0000-1000-8000-00805f9b34fb → 0x2A29 Manufacturer Name String

service = 0000180f-0000-1000-8000-00805f9b34fb → 0x180F Battery Service
chara = 00002a19-0000-1000-8000-00805f9b34fb → 0x2A19 Battery Level

service = 86c3810e-f171-40d9-a117-26b300768cd6 → PowerUp3.0独自のUUID
chara = 86c3810e-0010-40d9-a117-26b300768cd6
chara = 86c3810e-0020-40d9-a117-26b300768cd6
chara = 86c3810e-0021-40d9-a117-26b300768cd6
chara = 86c3810e-0040-40d9-a117-26b300768cd6

service = f000ffc0-0451-4000-b000-000000000000 → TI ChipのOAD機能
chara = f000ffc1-0451-4000-b000-000000000000
chara = f000ffc2-0451-4000-b000-000000000000


となり,消去法的に

[UUID=86c3810e-xxxx-40d9-a117-26b300768cd6]

がPowerUp3.0の制御用Service/Characteristicになっている模様.


Step4 : PowerUp3.0制御用Characteristic UUIDを調べる

[UUID=86c3810e-xxxx-40d9-a117-26b300768cd6]

の xxxx を 0010,0020,0021,0040,の4パターンそれぞれに適当に値を書き込んでみて,

PowerUp3.0の実機の挙動がどうなるか,を見ればどのUUIDがプロペラ回転数か尾翼角度かが分かる.

プロペラ回転数

[UUID=86c3810e-0010-40d9-a117-26b300768cd6]

1 byte 範囲で制御

垂直尾翼角度

[UUID=86c3810e-0021-40d9-a117-26b300768cd6]

Signed Integerで,

0 = Center

+/- = Right/Left

各CharacteristicのDescriptorを読み出せばHintが書かれているかもしれない.

PowerUp3.0の場合は,

86c3810e-0010-40d9-a117-26b300768cd6 → Engine Speed

86c3810e-0020-40d9-a117-26b300768cd6 → Rudder Angle
86c3810e-0021-40d9-a117-26b300768cd6 → Rudder 2 Angle
86c3810e-0040-40d9-a117-26b300768cd6 → Temperature

というDescriptorが入っている.

(Rudder AngleじゃなくRudder 2 Angleが制御用に使われているのはなぜだろう..)

これで後は適当にAndroid AppでSlider UIとか作ればPowerUp3.0を自作Appから制御できる.


まとめ

WireSharkのBluetooth Packet DumpとAndroidのBT/BLE APIを使って

PowerUp3.0のデータ構造を解析,公式App以外の自作AppからPowerUp3.0のデバイス制御ができた.

///---