GoogleAppsScriptでSwitchBot温湿度計のデータを取り込みスプレッドシートに記録する

#1. はじめに

2020年の12月にSwitchBotのAPIが公開されていたことを（半年以上経った今更）知った。
APIは1日に1000回までリクエストが可能とのこと。
もともとRaspberry Piを使ったBLE経由で温湿度計のデータの取り込みをしようと考えていたが、APIのリクエストでデータ取得ができるのであればGoogleAppsScriptの定期実行で温湿度の取り込みができるのでは？と思い、試してみた。

https://github.com/OpenWonderLabs/SwitchBotAPI


#2. 利用デバイス・事前準備
##2.1 利用デバイス
* SwitchBot温湿度計
* SwitchBot Hub mini

##2.2 事前の準備
* 温湿度計の設定（アプリとの接続）を終わらせる
* クラウドサービスをオンにしてSwitchBot Hub miniと連携をさせておく
* プロフィール→設定→アプリバージョンを10回タップ（開発者向けオプション有効化）
* 開発者向けオプションからトークンを取得

https://note.com/klayer123/n/nb14086840351

※こちらを参考にさせていただいた


#3. GoogleAppsScriptのコード

* Googleスプレッドシートで新しいスプレッドシートを作成し、スクリプトエディタに以下のコードを記載する
    * header情報には事前の準備で取得したトークンを入力する
    * 今回は練習のためにデバイスリストの取得とデータの読出しを別途で行ったが、通常デバイスのIDは分かっているのでリストの取得はやらなくてもよい。（APIのリクエストに上限があることを考えるとむしろやらないほうがいい）
* 「トリガー」で定期実行の設定を行う
    * イベントのソースを「時間主導型」
    * 時間ベースのトリガーのタイプを「分ごとのタイマー」
    * 時間の間隔を1分、5分、10分、15分、30分から選択


~~~Javascript
function getJSON_SwitchBotHubMini(){

  var headers = {"Authorization" : "token"}; //header情報として取得したトークンを設定

  var url1 = "https://api.switch-bot.com/v1.0/devices"; 
  var options = {
    "headers" : headers,     //header情報を追加
  }

  var response = UrlFetchApp.fetch(url1,options);                 //デバイスリストを取得するためのリクエスト
  var json=JSON.parse(response.getContentText());                 //JSONで受け取る
  var deviceIDlist = [];

  for(i=0;i<json['body']['deviceList'].length;i++){               //SwitchbotMeterのリストを取得
    if (json['body']['deviceList'][i]["deviceType"] == "Meter"){
      deviceIDlist.push(json['body']['deviceList'][i].deviceId); 
    }
  }

//デバイスの数だけデータの取得を繰り返し
  deviceIDlist.forEach ((deviceID) => {
    var url2 = "https://api.switch-bot.com/v1.0/devices/" + deviceID + "/status";
    var data = UrlFetchApp.fetch(url2,options);                 //温湿度計のステータスを取得
    var datajson=JSON.parse(data.getContentText());   
    var temp = datajson['body']['temperature']
    var rhumidity = datajson['body']['humidity']
    var ahumidity    =217*(6.1078*10**(7.5*temp/(temp+237.3)))/(temp+273.15)*rhumidity/100 //絶対湿度（g/m^3)を算出

  // シート取得
    var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = spreadsheet.getSheets()[0];
    var date = new Date();
  // データ入力
    sheet.appendRow([deviceID,date,temp,rhumidity,ahumidity]);
  } );

}
~~~
※普段ほとんどプログラミングをしないのでとんでもない実装をしているかもしれない。


https://qiita.com/iechaiu47/items/5ae954df048e677706a0

※コードについてはPythonベースのこちらを参考にさせていただいた。

https://officeforest.org/wp/2018/05/04/google-apps-script%E3%81%A7webapi%E3%82%84%E5%A4%96%E9%83%A8%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E6%8C%87%E5%8D%97%E6%9B%B8/

※GASでのHeader情報の入れ方などについてはこちらのサイトを参照した。



#4. 結果
1時間ほど5分間隔で測定してみたが、特に問題なく取得できているようだ。データの更新間隔を確かめるためにエアコンの吹き出し口の前と屋外を移動させてみたが、5分間隔であれば大丈夫そう。
![chart.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1637818/faee5208-52ca-5420-b63c-d921f1228aec.png)
1日のリクエストの上限が1000回なので、温湿度計が1個でデバイスリストの取得を行わなければ1.5分間隔程度が最短になる。しかしGoogle Apps Scriptのトリガー側で1.5分間隔は設定できないという制約があるため、5分間隔で取得するのが最短ということになりそう。5分間隔での取得する場合、1日のリクエスト数は温湿度計1つに対して288回なので3つの温湿度計までなら同時に取得していくことができるはず。このあたりは今後、もう少し長期間の取得を継続してみて検証してみたい。

#5. 追記：BLEでの読み込みとAPIでの読み込みの比較
SwitchBot温湿度計とBluetooth Low Energy（BLE）で通信して直接値を読み込んだ場合と、Hub mini経由でAPIをたたいてデータの取り込みをした場合の比較をしたので追記する。

ある日の12時間分のデータを比較すると、APIで読み込んだデータはおよそ30分ごとにしか更新が行われていないような挙動をしている。リアルタイム性を求めるならRaspberry PiなどからBLEで読み込んだ方がよさそうだ。（BLEはおよそ3分毎、APIは5分ごとにデータ取得）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1637818/23e9187f-4be8-9236-97cf-49194ed1707e.png)