GoからBLE制御でPLAYBULB Candleの操作をしてみる


　昨日のGo Conference 2015 winterお疲れ様でした。 #gocon
昨日のGoConでBLE話をした@n0bisukeです。 

昨日のスライドはこちらです。

> [GoでIoT ~BLE入門してみた話~ ](https://speakerdeck.com/n0bisuke/godeiot-bleru-men-sitemitahua-go-conference-2015-winter-lt-number-gocon-5fen)


今日は昨日の話を応用して衝動買いしたPlayBulbを使ってみたいと思います。

## PlayBulb Candleとは

スマホから制御可能な光るキャンドルスタンドです。 BLEで制御できます。

![](https://i.gyazo.com/16ba8b9e79484bd3762d69951cd68e4e.png)

上野のヨドバシカメラで衝動買いしてみました。
**2700円くらい**で買えましたよ。 

> [Amazon PlayBulb Candle](http://amzn.to/1NEMXJy)


プログラム可能な照明といえばPhilips Hueが有名ですが[一個あたり7000円](http://amzn.to/1Izk3if)くらいで、電球一個にしては高いなぁという印象です。

**Hueの代替になるか検証したいなとヨドバシカメラ内で思ったので買ってみました。**

##ServiceとCharacteristicのUUIDを調べる

GATTについて分からない人は色々調べてみましょう。または昨日の#gocon時の[スライド](https://speakerdeck.com/n0bisuke/godeiot-bleru-men-sitemitahua-go-conference-2015-winter-lt-number-gocon-5fen)を見て下さい。

> http://yegang.hatenablog.com/entry/2014/08/09/195246

### APIっぽいリポジトリがあるけど...

https://github.com/Phhere/Playbulb

ここがあまり参考にならず。

こっちの方が参考になりました。 
> Web Bluetoothすごい https://www.code-labs.io/codelabs/candle-bluetooth/#0

> Node.js実装 (試してはない) https://github.com/danielsmith-eu/playbulb-live

### 1. サービスUUID 

**Service UUID: 0x`FF02`**

この値がPlayBulb Candle制御用のサービスUUIDみたいです。

#### 1.1 Local Name(ガジェット名)の変更/読み込み 

**Characteristic UUID: 0x`FFFF`**

デフォルトは`PlayBulb`

#### 1.2 色の変更

**Characteristic UUID: 0x`FFFC`**

#### 1.3 エフェクトの変更

**Characteristic UUID: 0x`FFFB`**


※他の`Characteristic UUID`が分かったら追記したいと思います。

## Goからの制御

PayPalが公開しているgatt用のパッケージを使うのがいい感じです。
https://github.com/paypal/gatt
https://godoc.org/github.com/paypal/gatt

### PeripheralのUUIDを調べる

`discoverer.go`を動かしてみます。
https://github.com/paypal/gatt/blob/master/examples/discoverer.go

```
$ go run discover.go
・
・
・
Peripheral ID:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, NAME:()
  Local Name        = PlayBulb
  TX Power Level    = -2
  Manufacturer Data = [77 73 80 79 87]
  Service Data      = []
  
・
・
・
```

近くのデバイスの数だけ出てきます。 `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`としている部分がperipheralのuuidです。Local Nameで名前がそれっぽいものを探しましょう。

### 接続してみる

またサンプルを動かしてみましょう。 `explorer.go`です。
https://github.com/paypal/gatt/blob/master/examples/explorer.go

<Peripheral ID>には先ほど調べたものを入れます。

```
$ go run explorer.go <Peripheral ID>

・
・
・

Service: ff02
  Characteristic  2a37 (Heart Rate Measurement)
    properties    notify
  Descriptor      2902 (Client Characteristic Configuration)
    value         0000b2b3dd0c8f01000000b516000cfc6500ea09 | "\x00\x00\xb2\xb3\xdd\f\x8f\x01\x00\x00\x00\xb5\x16\x00\f\xfce\x00\xea\t"
  Characteristic  fff8
    properties    read
2015/12/07 20:17:03 Unhandled event: xpc.Dict{"kCBMsgId":81, "kCBMsgArgs":xpc.Dict{"kCBMsgArgConnectionInterval":37, "kCBMsgArgConnectionLatency":0, "kCBMsgArgSupervisionTimeout":500, "kCBMsgArgDeviceUUID":xpc.UUID{0xe6, 0x57, 0xb9, 0x78, 0x7d, 0x53, 0x47, 0xc1, 0x87, 0x30, 0xa4, 0xd0, 0xb8, 0xa0, 0x59, 0x5f}}}
    value         0000000000000000000000000000000000000000 | "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
  Characteristic  fff9
    properties    read write
    value         000000ffffffff000000000000 | "\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00"
  Characteristic  fffa
    properties    read writeWithoutResponse
    value         00 | "\x00"
  Characteristic  fffb
    properties    read writeWithoutResponse
    value         00000000ff002300 | "\x00\x00\x00\x00\xff\x00#\x00"
  Characteristic  fffc
    properties    read writeWithoutResponse
    value         00ff0000 | "\x00\xff\x00\x00"
    
 ・
 ・
 ・
```

こんな感じで、`peripheral`内の`Service`や`Characteristic`の情報が取れます。

### 書き込んでみましょう。
`WriteCharacteristic`というメソッドがあります。
ここに値を書き込めばOKです。
[explorer.goの79-80行目](https://github.com/paypal/gatt/blob/master/examples/explorer.go#L79-L80)のところに以下のコードを入れ込んでみました。


```explorer.go
・
・
・
      if c.UUID().String() == "fffc" {
        err := p.WriteCharacteristic(c, []byte("\x00\xff\x00\x00"), true)
        if err != nil {
  				fmt.Printf("Failed to discover descriptors, err: %s\n", err)
  				continue
  			}
      }
・
・
・
```

gistにあげてます。
https://gist.github.com/n0bisuke/8eddfa29176d9c41c2ea#file-gatt-write-test-go-L80-L86

`\x00\xff\x00\x00`を書き込んでますが、最初の00は固定です。その後が色(RGB)になります。

* 赤: `\x00\xff\x00\x00`
* 緑: `\x00\x00\xff\x00`
* 青: `\x00\x00\x00\xff`

みたいな感じです。

実行するとキャンドルの色が赤になります :+1: 

## まとめ

　PlayBulbがプログラム制御出来ました。
早くDroneの記事を書かないとなと思いつつも。 
デバッグがしやすい(ドローンはオフィスで飛ばすとウルサイ...w)方で進めてみました。

色々とBLE周りの情報で詰まる人がいると思うので、もう少し後で加筆したいと思います。