👋
fitbitに保存された体重をspreadsheetに出力する
はじめに
google pixel watchを購入して、健康情報がfitbitに集まるようになりました。
また、Homdoxという家電ブランドの体重計を買ったんですが、体重の情報はHealthU+というアプリに集まります。
体重計はこちら
HealthU+はfitbitへデータ連携が可能であるため、fitbitには健康情報の大半が集まっていそうです。というわけでfitbitの情報が取れないか(ゆくゆくはNotionなどに格納?)確認してみました。
fitbitのAPIが使えるようになるまで
以下を参考にトークン情報を入手
code
メイン処理。
main.js
function main() {
const fitbitManager = new FitbitManager();
fitbitManager.updateToken();
const weightList = fitbitManager.getTodayWeightList();
if(!weightList.length) return;
addSheetLastRow(
SHEET.weight,
weightList.map(weight => weight.getOutList())
);
}
fitbitとAPI接続を行う処理をクラス化。
トークン更新の処理は以下参考。
FitbitManager.js
class FitbitManager{
constructor(){
const sheet = SpreadsheetApp.getActive().getSheetByName(SHEET.config.name);
this.id = sheet.getRange(SHEET.config.cell.id).getValue();
this.accessToken = sheet.getRange(SHEET.config.cell.accessToken).getValue();
this.refreshToken = sheet.getRange(SHEET.config.cell.refreshToken).getValue();
}
getTodayWeightList(){
const option = {
method: 'get',
headers: {
Authorization: `Bearer ${this.accessToken}`,
},
};
const res = UrlFetchApp.fetch(`https://api.fitbit.com/1/user/${this.id}/body/log/weight/date/today.json`, option);
const json = JSON.parse(res);
return json.weight.map(json => new Weight(json));
}
updateToken(){
const option = {
method: 'post',
headers: {
Authorization: `Bearer ${this.accessToken}`,
},
};
const res = UrlFetchApp.fetch(`https://api.fitbit.com/oauth2/token?grant_type=refresh_token&expires_in=90000&refresh_token=${this.refreshToken}`, option);
const json = JSON.parse(res);
this.accessToken = json.access_token;
this.refreshToken = json.refresh_token;
const sheet = SpreadsheetApp.getActive().getSheetByName(SHEET.config.name);
sheet.getRange(SHEET.config.cell.accessToken).setValue(this.accessToken);
sheet.getRange(SHEET.config.cell.refreshToken).setValue(this.refreshToken);
}
}
体重情報(クラス)。
Weight.js
class Weight{
constructor(json){
this.bmi = json.bmi;
this.fat = json.fat;
this.time = dayjs.dayjs(`${json.date} ${json.time}`);
this.weight = json.weight;
}
getOutList(){
return [
this.time.format('YYYY/MM/DD HH:mm'),
this.weight,
this.fat,
this.bmi
];
}
}
spreadsheet操作の処理。
sheet.js
const SHEET = {
config: {
name: 'config',
cell: {
id: 'b2',
accessToken: 'b3',
refreshToken: 'b4',
},
},
weight: {
name: 'weight',
},
};
function getSheetData(sheetConfig){
let data = getSheetDataFull(sheetConfig);
[...Array(sheetConfig.row.data - 1)].forEach(_ => data.shift());
return data;
}
function getSheetDataFull(sheetConfig){
const sheet = SpreadsheetApp.getActive().getSheetByName(sheetConfig.name);
return sheet.getDataRange().getValues();
}
function addSheetLastRow(sheetConfig, list, column){
const sheet = SpreadsheetApp.getActive().getSheetByName(sheetConfig.name);
sheet.getRange(
sheet.getLastRow() + 1,
column !== undefined ? column : 1,
list.length,
list[0].length
).setValues(list);
}
あとはトリガーで23時頃に実行させる。
Discussion