switchbot温湿度計のAPIをNode-REDで作る

# TL;DR
- Switchbot温湿度計データをRaspberryPiで取得
- 取得データをNode-REDでAPIとして公開

# はじめに
まったく仕事と関係ないです。

おうちハックに向けて、改めて温湿度の記録をはじめようと思いました。
昔はRapberryPiに[BME280](http://akizukidenshi.com/catalog/g/gK-09421/)をつけて、温湿度を測っていましたが、
やはり、自作だと見た目が悪く、RaspberryPiの給電の都合上設置したい場所に設置できないという課題がありました。

そこでBluetooth, Wifi等なんらかの通信できる「安くて」「見た目の良い」「電池駆動の」温湿度計を探して今回見つけて購入したのがSwitchBotの温湿度計です。

<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8190/ce3a0a8f-854a-ccc2-c8fd-c0ef42784192.png">

https://www.switchbot.jp/meter
>SwitchBot温湿度計はご家庭の温度や湿度を気軽にチェックすることができます。アプリでアラーム通知や履歴確認できる便利なスマート温湿度計です。(引用：https://www.switchbot.jp/meter)




本家のページを見てもらえればわかると思いますが、見た目はただの液晶タイプの温湿度計です。
お値段約2000円という価格にもかかわらず、Bluetoothに対応しており、iOS, Androidアプリを使った温湿度情報を可視化することができます。

しかし...**完全に自分の調査不足**でしたが、
クラウドサービスに連携してと書いていたのですが、別途Hubの購入が必要であるということ...
連携しても温湿度情報取得のAPIが無いようなのでそこで、自分でAPIを作ることにします。

# 温湿度情報の取得
兎にも角にも温湿度情報を取得する必要があります。
今回はどこのご家庭にも一台以上使わなくなって放置されているRaspberry Piを利用しました。

### 利用環境
- 筐体：[Raspberry Pi 3 Model B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/)
- OS:Raspbian
- Python3
- 家の中のLANのみ利用（インターネット公開はしない）

### Raspberry PiでBluetoothのデバイスが見えるか確認する。
pythonとbluepyを利用して、デバイスの一覧を取得する。


```python

import bluepy

scanner = bluepy.btle.Scanner(0)
devices = scanner.scan(5)

for device in devices:
  print('address : %s' % device.addr)
```

実行結果

```
address : 6d:a3:xx:0a:f5:ae
address : e1:bb:xx:2a:fb:e0
address : 2c:26:xx:16:24:38
address : b8:78:xx:3d:3d:e5
address : 5e:93:xx:39:80:39
address : c8:84:xx:53:9a:52
address : 5d:e3:xx:2a:cc:76
address : d3:f2:xx:ac:97:42
address : 52:75:xx:4c:38:b5
address : 72:5f:xx:cd:b0:8d
address : 47:db:xx:64:cd:78
address : c8:84:xx:4f:71:3e
address : 4f:a5:xx:85:3a:97
address : 42:e0:xx:b9:61:5d
address : 5f:53:xx:ed:71:4b
address : 53:c6:xx:62:e5:ce
address : 68:ea:xx:4e:14:1d
address : 6b:22:xx:12:24:d1
address : 60:09:xx:37:11:f3
```

今回SwitchBotのiOSアプリから、確認したところ、e1:bb:xx:2a:fb:e0がSwitchbot温湿度計のMACアドレスです。
RaspberryPiでの取得結果にも当該MACアドレスが存在していることから、RaspberryPiでも当該デバイスを認識できることがわかりました。

## 温湿度データの取得

SwitchBotのBLEから温湿度データを取り出します。
パケット解析をしようと意気込んでいましたが、BLEのパケットの分析と出力は既に実装されている方がいらっしゃったので参考にさせていただきました。
[SwitchBot 温湿度計の測定値を BLE Advertisement パケットから直接読み取る](https://qiita.com/warpzone/items/11ec9bef21f5b965bce3)

今回はSwitchBot温湿度計のAPIを作るために、下記の変更を加えました。

- 引数でMACアドレスを受け取る
- 出力形式をjsonにする

実行結果

```bash
# python3 switchbot-meter.py e1:bb:xx:2a:fb:e0
{
    "isHumidityLowAlert": "False",
    "isTemperatureUnitF": "False",
    "isDualStateMode": "False",
    "isHumidityHighAlert": "False",
    "isTemperatureLowAlert": "False",
    "isEncrypted": "False",
    "isStatusOff": "False",
    "temperature": "26.0", 
    "isTemperatureHighAlert": "False",
    "humidity": "29",
    "battery": "100"
}
```




# API部分の作成
API部分の作成は、Node-REDを使います。
[Node-RED](https://nodered.jp/)はGUIを用いでデータの入出力、加工のフローを表現し、プログラムすることができるツールです。
> Node-REDはフローベースドプログラミング(flow-based programming)ツールであり、元はIBM Emerging Technology Servicesチームによって開発され、 現在ではJS Foundationのひとつになっています。

API部分の作成では、Flask等を使って実装もできますが、Node-REDで実現します。

## Node-REDのフロー作成
今回利用したノードは下記となります。

- http in
- function
- exec
- http response
- debug

<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8190/75270c70-b33e-2514-189a-0471d5903166.png">

#### http in
http://ip/sensors/macaddressをGETする方法
http://ip/sensors/ にjsonで{"mac":"mac address"}をPOSTする方法

前者でも動いくのですが、MACアドレスにはコロン：が入るため、正確にはRFCの確認が必要です。
その他は以下のとおり

- function:    http inで受け取ったオブジェクトをmsg.payloadに格納する。
- exec: ローカルにあるpythonスクリプトの実行
- http response: クライアントにスクリプト実行結果のjsonを返す
- debug: エラーが出たとき用

### 作成したAPIを利用する
Node-REDで作成したAPIを手元のクライアントマシンから叩いてみます。

```bash
~ » curl -X POST -H 'Content-Type:application/json' -d '{"mac":"e1:bb:xx:2a:fb:e0"}' http://192.168.11.41:1880/sensors/             onodes@Casper3
{
    "isTemperatureLowAlert": "False",
    "isHumidityHighAlert": "False",
    "isDualStateMode": "False",
    "isTemperatureHighAlert": "False",
    "isEncrypted": "False",
    "battery": "100",
    "isTemperatureUnitF": "False",
    "humidity": "26",
    "isHumidityLowAlert": "False",
    "isStatusOff": "False",
    "temperature": "29.1"
}
```

どうやら無事に動いたようです。

# おわりに
今回はNode-REDを活用して、Switchbot温湿度計のAPIを作成しました。
WebAPIが無いものに対して、Node-RED等のツールを挟むことで気軽にWebAPIを持たせることができます。
しかし、スクリプトを直接叩いていることもあり、セキュリティは十分に注意する必要があります。