What is PowerUp3.0 ?
紙飛行機に装着して,ケータイから操作可能なラジコン化するキット.
プロペラの回転数と垂直尾翼の角度をコントロールして紙飛行機を自在に操縦できるようになる.
↓ 実物はこんなもの,プロペラのついたちっさいUnitを実物の紙飛行機に装着します.
↓ 公式はこちら
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と思われる.
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 = 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 = 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のデバイス制御ができた.
///---