Slide 1

Slide 1 text

つらくない(?) Bluetooth Low Energy Masayuki IZUMI @izumin5210 Masayuki IZUMI @izumin5210

Slide 2

Slide 2 text

 Rekimoto Lab. at the University of Tokyo (2008-2015: Akashi-NCT)  Enginner at Wantedly, Inc. (2014.9-2015.2: Dmetlabel, Inc.)

Slide 3

Slide 3 text

Ruby JavaScript Android Design pry(main) > izumin.skill_ratio

Slide 4

Slide 4 text

Bluetooth Low Energy

Slide 5

Slide 5 text

Android 4.3 (API Level 18) introduces built-in platform support for Bluetooth Low Energy in the central role and provides APIs that apps can use to discover devices, query for services, and read/write characteristics. - Bluetooth Low Energy | Android Developers

Slide 6

Slide 6 text

Q. BLE つらくないですか

Slide 7

Slide 7 text

Q. BLE つらくないですか A. つらいです

Slide 8

Slide 8 text

BluetoothGatt Bluetooth LE の周辺機器は、サーバとして、センサの値、動作設定 値、内部状態などを公開しています。Bluetooth LE は、ある機能を サービスという単位にまとめます。1 つのサービスは複数のキャラ クタリスティクスを持ちます。例えばエアコンであれば、室内温度 というサービスを作り、そのなかに気温センサの値というキャラク タリスティクスをもたせる設計をしたりします。 - BLE の通信仕様 - Reinforce-Lab.'s Blog* * http://reinforce-lab.github.io/blog/2013/08/13/blebook-ch2-ble-spec/

Slide 9

Slide 9 text

BluetootGatt  GATT (Generic Attribute Profile)

Slide 10

Slide 10 text

BluetootGatt  GATT (Generic Attribute Profile)  あらゆる BLE 端末は GATT に基いて データの送受信を行う

Slide 11

Slide 11 text

BluetootGatt  GATT (Generic Attribute Profile)  あらゆる BLE 端末は GATT に基いて データの送受信を行う  Android では BluetoothGatt クラスを利用する

Slide 12

Slide 12 text

BluetootGatt  GATT (Generic Attribute Profile)  あらゆる BLE 端末は GATT に基いて データの送受信を行う  Android では BluetoothGatt クラスを利用する ↑ こいつが闇

Slide 13

Slide 13 text

BLE つらい問題 ちょっと触ってみた結果、どうにも悲しいことに 「1. 安定性がイケてない」 「2. SDK サンプルがイケてない」 「3. API 仕様がイケてない」 という三重苦です。 - Android の BLE で Characteristics の Read/Write サンプルを作ってみた - ReDo** ** http://greety.sakura.ne.jp/redo/2013/11/androidblecharacteristicsreadwrite.html

Slide 14

Slide 14 text

ここから,このつらい BLE まわりを なんとかマシに出来ないか試行錯誤していきます 

Slide 15

Slide 15 text

BLE つらい問題 ちょっと触ってみた結果、どうにも悲しいことに 「1. 安定性がイケてない」 「2. SDK サンプルがイケてない」 「3. API 仕様がイケてない」 という三重苦です。 - Android の BLE で Characteristics の Read/Write サンプルを作ってみた - ReDo** ** http://greety.sakura.ne.jp/redo/2013/11/androidblecharacteristicsreadwrite.html

Slide 16

Slide 16 text

どうしようもねえ!!!

Slide 17

Slide 17 text

イケてない API  すべての操作は非同期・コールバックベース

Slide 18

Slide 18 text

BluetoothGattCallback onConnectionStateChange(BluetoothGatt gatt, int status, int newState) onServicesDiscovered(BluetoothGatt gatt, int status) onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)

Slide 19

Slide 19 text

BluetoothGattCallback onConnectionStateChange(BluetoothGatt gatt, int status, int newState) onServicesDiscovered(BluetoothGatt gatt, int status) onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)

Slide 20

Slide 20 text

BluetoothGattCallback  接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange()

Slide 21

Slide 21 text

BluetoothGattCallback  接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange()  Service 探し BluetoothGatt#discoverService() → onServiceDiscovered()

Slide 22

Slide 22 text

BluetoothGattCallback  接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange()  Service 探し BluetoothGatt#discoverService() → onServiceDiscovered()  書き込み BluetoothGatt#writeCharacteristic() → onCharacteristicWrite()

Slide 23

Slide 23 text

BluetoothGattCallback  接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange()  Service 探し BluetoothGatt#discoverService() → onServiceDiscovered()  書き込み BluetoothGatt#writeCharacteristic() → onCharacteristicWrite()  切断処理 BluetoothGatt#disconnect() → onConnectionStateChange()

Slide 24

Slide 24 text

BluetoothGattCallback  接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange()  Service 探し BluetoothGatt#discoverService() → onServiceDiscovered()  書き込み BluetoothGatt#writeCharacteristic() → onCharacteristicWrite()  切断処理 BluetoothGatt#disconnect() → onConnectionStateChange()

Slide 25

Slide 25 text

BluetoothGattCallback  接続処理 BluetoothDevice#connectGatt() → onConnectionStateChange()  Service 探し BluetoothGatt#discoverService() → onServiceDiscovered()  書き込み BluetoothGatt#writeCharacteristic() → onCharacteristicWrite()  切断処理 BluetoothGatt#disconnect() → onConnectionStateChange() ↓ 切断は disconnect() して, callback を待ってから close()

Slide 26

Slide 26 text

イケてない API  すべての操作は非同期・コールバックベース  登録できる Callback インスタンスは 1 つ

Slide 27

Slide 27 text

イケてない API  すべての操作は非同期・コールバックベース  登録できる Callback インスタンスは 1 つ  ドキュメントにない仕様(disconnect → close とか)

Slide 28

Slide 28 text

対策①: 状態を意識する private static final int STATE_DISCONNECTED = 0; private static final int STATE_CONNECTING = 1; private static final int STATE_CONNECTED = 2; 公式サンプル

Slide 29

Slide 29 text

対策①: 状態を意識する private static final int STATE_DISCONNECTED = 0; private static final int STATE_CONNECTING = 1; private static final int STATE_CONNECTED = 2; 公式サンプル たりない

Slide 30

Slide 30 text

対策①: 状態を意識する enum State { DISCONNECTED, CONNECTING, CONNECTED, SERVICE_DISCOVERING, SERVICE_DISCOVERED, DISCONNECTING }

Slide 31

Slide 31 text

対策①: 状態を意識する enum State { DISCONNECTED, CONNECTING, CONNECTED, SERVICE_DISCOVERING, SERVICE_DISCOVERED, DISCONNECTING } ※ READING / WRITING 等も必要かもしれない

Slide 32

Slide 32 text

対策②: Callback のハンドリング  どの操作のコールバックかを判断するには, 引数に入ってるインスタンス見るしかない  普通にやると Callback Hell 不可避

Slide 33

Slide 33 text

対策②: e.g. Enum でハンドリング @Override public onCharacteristicWrite() { CharacteristicHandler.valueOf(characteristic.getUuid()) .handle(characteristic); } enum CharacteristicHandler { DIGITAL_WRITE(/* ... */), DIGITAL_READ(/* ... */) UNKNOWN(null); public static CharacteristicHandler valueOf(UUID uuid) { /* ... */ } public UUID getUUID() { /* ... */ } public void handle() { /* ... */ } }

Slide 34

Slide 34 text

対策②: e.g. Enum でハンドリング @Override public onCharacteristicWrite() { CharacteristicHandler.valueOf(characteristic.getUuid()) .handle(characteristic); } enum CharacteristicHandler { DIGITAL_WRITE(/* ... */), DIGITAL_READ(/* ... */) UNKNOWN(null); public static CharacteristicHandler valueOf(UUID uuid) { /* ... */ } public UUID getUUID() { /* ... */ } public void handle() { /* ... */ } }

Slide 35

Slide 35 text

対策②: e.g. Enum でハンドリング @Override public onCharacteristicWrite(/* ... */) { CharacteristicHandler.valueOf(characteristic.getUuid()) .handle(characteristic); } enum CharacteristicHandler { DIGITAL_WRITE(/* ... */), DIGITAL_READ(/* ... */) UNKNOWN(null); public static CharacteristicHandler valueOf(UUID uuid) { /* ... */ } public UUID getUUID() { /* ... */ } public void handle() { /* ... */ } }

Slide 36

Slide 36 text

対策②: e.g. Enum でハンドリング @Override public onCharacteristicWrite(/* ... */) { CharacteristicHandler.valueOf(characteristic.getUuid()) .handle(characteristic); } enum CharacteristicHandler { DIGITAL_WRITE(/* ... */), DIGITAL_READ(/* ... */) UNKNOWN(null); public static CharacteristicHandler valueOf(UUID uuid) { /* ... */ } public UUID getUUID() { /* ... */ } public void handle() { /* ... */ } }

Slide 37

Slide 37 text

対策②: Callback のハンドリング  どの操作のコールバックかを判断するには, 引数に入ってるインスタンス見るしかない  普通にやると Callback Hell 不可避  上手く処理を移譲させないとヤバい (数千行のなんちゃら Manager クラスとかと対峙するはめに…)

Slide 38

Slide 38 text

余談  イイ感じのパターンでラップしちゃうのもある e.g. Rx, Promise, Observer, flux

Slide 39

Slide 39 text

 イイ感じのパターンでラップしちゃうのもある e.g. Rx, Promise, Observer, flux  出回ってる BLE デバイスの SDK はつらい (ハッカソンとかではそのことを念頭に置いた方がいい) 余談

Slide 40

Slide 40 text

 イイ感じのパターンでラップしちゃうのもある e.g. Rx, Promise, Observer, flux  出回ってる BLE デバイスの SDK はつらい (ハッカソンとかではそのことを念頭に置いた方がいい)  BLE まわり,ユニットテストどうするの? (BluetoothGatt は final なので… ラッパー書くしかない?) 余談

Slide 41

Slide 41 text

 BLE,基本的にはつらいです Conclusion

Slide 42

Slide 42 text

 BLE,基本的にはつらいです  公式はあまり信用出来ない(過激派) Conclusion

Slide 43

Slide 43 text

 BLE,基本的にはつらいです  公式はあまり信用出来ない(過激派)  状態遷移を意識しよう Conclusion

Slide 44

Slide 44 text

 BLE,基本的にはつらいです  公式はあまり信用出来ない(過激派)  状態遷移を意識しよう  ガバガバ Callback からどうやって処理を ハンドリングしていくかが重要 Conclusion

Slide 45

Slide 45 text

http://konashi.ux-xu.com/ https://github.com/YUKAI/konashi-android-sdk/ https://www.flickr.com/photos/36571434@N03/8524872002