Android Things Preview 4でBLE通信をしてみた

Android Things Preview 3からBluetooth Low Energyが対応されているらしかったので、
いろいろ試していた間に、Android Things Preview 4がリリースされてしまい、
やり直してみた記事です。

<img width="360" alt="Android Things Preview 4" src="https://qiita-image-store.s3.amazonaws.com/0/1213/bee3eb05-23e4-9e76-c45d-ee6cda387d20.jpeg">

# 初めに

なぜ、Android ThingsでBLEが使いたいかというと、[AndroidアプリでFirebase Realtime DBにセンサーデータを保存、閲覧する](http://qiita.com/kojira/items/48d113013080a4476ceb)、の最後に記載したように、普通のスマホだと長期間充電し続けることになり、バッテリーが餅のように膨らんで危険な状態になってしまったため、長期間電源に繋いでいても問題ない端末で運用したいという思いからです。
<img width="360" alt="哀れなNexus 4" src="https://qiita-image-store.s3.amazonaws.com/0/1213/f2132bc7-8660-8d4f-8d6a-79cbdf57e577.jpeg">
※参考画像(2ヶ月間ケーブルを繋いでいたため、バッテリーが膨らんで裏のガラス面が割れて盛り上がっているNexus 4)

今度こそ長期間、[冷蔵庫の温湿度を計測](http://qiita.com/kojira/items/b78f75651b0be535c097)するゾ！


[Android Things](https://developer.android.com/things/index.html)を焼く端末は[Raspberrypi3](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/)を使用、
BLEのペリフェラルにはいつものように[Linking](https://linkingiot.com/)端末を使用しました。

※Linkingについての過去記事
 「[Linkingの端末をもらったのでデモアプリを試してみた](http://qiita.com/kojira/items/a8cdf4b499efb06887ea)」

# 環境構築

Macでの環境構築手順は「[Android ThingsをRaspberry Pi 3にインストール](http://qiita.com/aoinakanishi/items/fae26dc1ad0f16b58558)」に詳しく書かれているので、そちらを参考にしてもらうと良いです。
気をつける点は初回起動は**LANケーブル**が必須なことくらいです。
後、キーボードがあるとadbコマンドでキーイベントを送らなくても良いので操作が楽です。
もちろん、Preview 4のイメージをダウンロードして下さいね。

# Scanしてみる

Scan開始ボタンをトグルできるように、[公式のBLEサンプル](https://github.com/googlesamples/android-BluetoothLeGatt)を若干改造して、キーボードのイベントを拾うようにします。

```java:DeviceScanActivity.java
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        L.e("keyCode:" + keyCode + " KeyEvent:" + event.getAction());
        switch (keyCode) {
            case 19://上キー
                scanLeDevice(true);
                break;
            case 20://下キー
                scanLeDevice(false);
                break;
        }
        return super.onKeyDown(keyCode, event);
    }
```




![screen1.png](https://qiita-image-store.s3.amazonaws.com/0/1213/6a5194ba-f662-57a5-a686-6e208e211e18.png)

[Sizuku 6x](https://ssl.braveridge.com/store/html/products/detail.php?product_id=33)、[Oshieru](https://ssl.braveridge.com/store/html/products/detail.php?product_id=39)、[Tomoru](https://ssl.braveridge.com/store/html/products/detail.php?product_id=4)、[Pochiru](https://ssl.braveridge.com/store/html/products/detail.php?product_id=28)、[Tukeru](https://ssl.braveridge.com/store/html/products/detail.php?product_id=34)の５つのLinkingデバイスが表示されました。

Sizukuにカーソルを合わせてEnterを押し、Sizukuに接続してみます。

以下のような変更を加えています。

Write押下時にLinkingのシーケンス順にデータを送る処理です。

```java:DeviceControlActivity.java
    if ((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
        byte[][] value = new byte[][]{
                {0x01, 0x00, 0x00, 0x00, 0x00},
                {0x00, 0x03, 0x02, 0x00, 0x05, 0x02, 0x01, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x01, 0x07, 0x04, 0x00, 0x00, 0x00},
                {0x01, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
                {0x01, 0x03, 0x02, 0x00, 0x02, 0x02, 0x01, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00}
        };
        mBluetoothLeService.writeCharacteristic(characteristic, value[index]);
        index = (index + 1) % 4;
    }
```

Linking固有のUUIDの追加。

- Device Information Service
- PeripheralDeviceLink Service
- PeripheralDeviceLink Write
- PeripheralDeviceLink Indicate

```java:SampleGattAttributes.java
public class SampleGattAttributes {
    private static HashMap<String, String> attributes = new HashMap();
    public static String HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb";
    public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
    public static String HEART_RATE_CONTROL_POINT = "00002a39-0000-1000-8000-00805f9b34fb";

    static {
        // Sample Services.
        attributes.put("0000180d-0000-1000-8000-00805f9b34fb", "Heart Rate Service");
        attributes.put("0000180a-0000-1000-8000-00805f9b34fb", "Device Information Service");
        attributes.put("b3b36901-50d3-4044-808d-50835b13a6cd", "PeripheralDeviceLink Service");
        // Sample Characteristics.
        attributes.put(HEART_RATE_MEASUREMENT, "Heart Rate Measurement");
        attributes.put(HEART_RATE_CONTROL_POINT, "Heart Rate Control Point");
        attributes.put("00002a29-0000-1000-8000-00805f9b34fb", "Manufacturer Name String");
        attributes.put("b3b39101-50d3-4044-808d-50835b13a6cd","PeripheralDeviceLink Write");
        attributes.put("b3b39102-50d3-4044-808d-50835b13a6cd","PeripheralDeviceLink Indicate");
    }

    public static String lookup(String uuid, String defaultName) {
        String name = attributes.get(uuid);
        return name == null ? defaultName : name;
    }
}
```




![Connect2Sizuku.png](https://qiita-image-store.s3.amazonaws.com/0/1213/be5323dc-7741-f1e7-6792-7e1c1d4cf67d.png)

Peri0pheralDeviceLink Serviceの項目を開いてみます。
![OpenPeripheralDeviceLinkService.png](https://qiita-image-store.s3.amazonaws.com/0/1213/dedf7c4b-5beb-bb62-0045-6552a7f7208a.png)

1．「PeripheralDeviceLink Indicate」を押下
2．「PeripheralDeviceLink Write」を１回押下
3． 画面上部のdata部分に「83」から始まるバイト列が表示される
4．「PeripheralDeviceLink Write」を２回押下
5．加速度の取得が開始され、data部分に受信データが表示される
6．「PeripheralDeviceLink Write」を１回タップ
7．加速度の取得が停止される 

加速度のデータが取れている所。
![Get6x.png](https://qiita-image-store.s3.amazonaws.com/0/1213/c69b24b1-2d11-a7b4-3aa1-b877932e96e9.png)

たまに落ちることがあります。
アプリではなく、Bluetoothのフレームワークが落ちたようです。
まだまだ不安定ですね・・・。これでは長期稼働は厳しいかも。。。
![crash.png](https://qiita-image-store.s3.amazonaws.com/0/1213/ab0a78f7-a51e-5aa7-8274-f9ef0e61643a.png)

今回使用したソースコードは[ここに](https://github.com/kojira/AndroidThingsBLE)アップしてあります。


Connectすると不安定だけど、ビーコン情報ならなんとかなるはず！
ということで、次回はTukeruのBeacon情報からの温湿度の取得にチャレンジしてみます！

でわまた。