OK Google、FitBitに体重を記録して

# 本記事の目的

Google Home Miniを数か月前に購入したのですが、スマートホーム化をしているわけでもなくただの置物になっていました。また健康が気になるお年頃なのでFitBit Charge2は毎日はめて歩数計や、睡眠時間、心拍などの情報は常にとっているものの家にある体重計はBluetooth対応ではなくめんどくさくて今まで記録はしていませんでした。

最初は体重計の数値をカメラで撮って画像認識で数値読み取ろうかなとも思ったのですが、そんなことよりしゃべったほうが早いのではとスマートスピーカーを使用した仕組み作ってみたら思いのほか簡単に実現できましたよという記録です。

## 概要

### 体重をFitBitに記録

![GoogleHomeMiniToFitbit.png](https://qiita-image-store.s3.amazonaws.com/0/24418/54060ab7-401a-7855-2b8c-5081f9e12751.png)

大体の流れは上記の絵の通りです。
Googleが出しているIFTTTのApplet [Connect Google Assistant to Fitbit](https://ifttt.com/connect/google_assistant/fitbit) があるのでこれ使えば一発で実現できます。

音声認識の精度はさすがGoogleだけにばっちりなのですが、少しだけコツがありました。

Google Homeに話しかけるフレーズの登録なのですが、「体重は xx キロ」としゃべりかけるつもりで 最初 `体重は xx キロ` というフレーズのみ登録していましたが、うまく認識されないことがありました。アクティビティを確認したところ、Googleが `キロ`を `Kg`と変換していることがあり登録フレーズにマッチしなかったようでした。
そこで代替えフレーズとして `体重は xx Kg` を登録することで今のところ100%成功しています。
![phrase.png](https://qiita-image-store.s3.amazonaws.com/0/24418/d72e4a1c-687a-a99f-842e-be51dfdc3790.png)

### 体脂肪率をFitBitに記録する

![bodyFit.png](https://qiita-image-store.s3.amazonaws.com/0/24418/a96fd1c3-61f5-748a-f088-4624f0fffab7.png)


残念ながら、体重計に出てくる体脂肪率については公開されているレシピがないため自分で作成する必要があります。
といってもIFTTTには [Google Assistant](https://ifttt.com/services/google_assistant) と [WebHooks](https://ifttt.com/maker_webhooks)が用意されているためWebHookにFitBitの[Fitbit Web API Basics](https://dev.fitbit.com/build/reference/web-api/basics/)を設定してあげればよさそうと思っていました。

しかしここで問題が...

FitBitに体脂肪率を記録するAPIには記録する日を入れる必要があります。Google Assistantではしゃべったときの日時を {{CreatedAt}} というパラメーターで持っているのですがこれが `September 4, 2018 at 10:04PM` のようなフォーマットになっていて APIで必要なフォーマット`YYYY-MM-DD`に変換できないのです。

残念ながら直接FitBitに記録することはできませんでしたので、いったんGoogleスプレッドシートに記録し、Google Apps Scriptで FitBit APIをたたくことにしました。

まずは、IFTTTで Google Assistantにしゃべった体脂肪率をGoogle スプレッドシートに記録する部分です。

[Google AssistantをIFTTTで連携](https://qiita.com/sesame525/items/fba27b41bec3aebd3de0)　や [IFTTT, Google Assistant, Google Sheetsで赤ちゃんの授乳を記録する](http://takopomm.hatenablog.com/entry/2017/12/09/023000)　という記事を参考にさせてもらいました。

![bodyfat.png](https://qiita-image-store.s3.amazonaws.com/0/24418/ad3a1a7c-04d2-16c7-8482-6b259804f11b.png)

結局のところ日時のフォーマットの変換は難しく、 Google Assistantの {{CreatedAt}}を使用することはあきらめて、スプレッドシートに追加された日時を Google Apps Scriptで取得することにしました。

![GoogleSpreadSheet.png](https://qiita-image-store.s3.amazonaws.com/0/24418/4f3acecc-8527-c199-cc4d-badbb519b7c9.png)

この記事 [IFTTTでGoogleスプレッドシートに日時が書きだしできない時の対処法](https://qiita.com/sitopp/items/66c432da6e33494d1db1) が参考になりました。

あとは、FitBitのAPIを呼ぶ箇所です。
セキュリティ上必要なトークンは直接コードに書かずに プロパティとして保管し参照するのがよさそうです。
UserPropertiesは画面からの入力ができませんでしたので、一度コードで記入する必要があるみたいです。

また、体脂肪率を登録するFitBit APIでは パラメーターとして 時刻(time)もあるのですが、これを使用するとFut Bitのダッシュボードに反映できないという現象がありましたので、日にちのみ登録することにしました。

``` js
function addDate(e) {
    var lr = SpreadsheetApp.getActiveSheet().getLastRow();
    var now = new Date();
    var createDate = Utilities.formatDate( now, 'Asia/Tokyo', 'yyyy-MM-dd');
  
    SpreadsheetApp.getActiveSheet().getRange(lr, 2).setValue(createDate);
    SpreadsheetApp.getActiveSheet().getRange(lr, 3).setValue(createTime);
    var fat = SpreadsheetApp.getActiveSheet().getRange(lr, 4).getValue();
    
    pushFat(createDate, fat);
}

// FitBit に体脂肪率を登録する
function pushFat(date, fat) {
  var url = "https://api.fitbit.com/1/user/[ユーザーID]/body/log/fat.json";
  var userProperties = PropertiesService.getUserProperties();
  var token = userProperties.getProperty('FITBIT_TOKEN');

  var payload =
  {
    "date" : date,
    "fat" : fat
  };
  // オプション指定
  var options =
  {
    "method"  : "post",
    "payload" : payload,
    "headers" : {"Authorization" : "Bearer "+ token},
    "contentType" : "application/x-www-form-urlencoded",
  };
  //通知を送る
  var response = UrlFetchApp.fetch(url,options);
  Logger.log(response);
}
```

こんな感じで無事FitBitのダッシュボードに体重と体脂肪率を記録していくことができそうです。