先日Fitbit Oneを購入した,という記事を書いたが,今までOmronのWellnessLinkを愛用していたみーがこっちに乗り換えた理由の1つに,サービスのデータにアクセスするためのAPIが充実している,という点がある.WellnessLinkもデータをエクスポートできるのだが,その逆がとても難しい.FitbitならAPIを叩くだけで簡単にデータをインポートし,エクスポートできる.
ということで,Pythonを用いたFitbit.comの開発方法をメモしておく.
用意したもの
最後の3つはpython-fitbitを使うのに必要なモジュールで,pipしたりeasy_installしたりすれば頭を使わずにインストールできるのだけど,cx_freezeするときに何かと問題になることを考慮して,site-packagesフォルダにGitHubからダウンロードしたスクリプトを放り込んでおいた.
とりあえずpythonをインタラクティブモードで起動して,import fitbit ができるかを確認し,エラーがでなければ準備完了である.
fitbit.comへの認証 (OAuth)
これはpython-fitbitがほとんどやってくれるので簡単である.python-fitbitに含まれているgather_keys_cli.pyというファイルを参考にすればよい.
client = FitbitOauthClient(CLIENT_KEY,CLIENT_SECRET)
client key, client secretという2つの値は,ここからアプリ情報を登録することで取得できる.アプリ固有の値であるため,適当にソースコードに書いておく.
token = client.fetch_request_token()
これでリクエストトークンという値を取得できる.今から認証しますがいいですか?という感じ.
webbrowser.open(client.authorize_token_url()) verifier=raw_input("Verifier: ")
初回の認証ではverifierという値を取得する必要があり,これはブラウザーを立ち上げてユーザーにfitbit.comにログインしてもらった上で表示されるverifierを入力してもらう.そのため入力画面を設ける.コンソール画面ならinputを使えばいいし,Qtを使っているのなら,QInputDialogなんかを表示しておけばよい.
token = client.fetch_access_token(verifier)
verifierを送ると,アクセストークンという値が返ってくる.これを使えばは次回からのユーザー認証を省略できるので,この値はファイルに保存しておくと便利である.ちなみに2回目の認証は,
fitbit.Fitbit(CLIENT_KEY, CLIENT_SECRET, resource_owner_key=token["oauth_token"], resource_owner_secret=token["oauth_token_secret"], user_id=token["encoded_user_id"], system="ja-JP" )
とすれば認証済みのclass FitbitOauthClient が class Fitbit に格納されている.
単位
fitbit-pythonはデフォルトだと体重がポンドになっており,日本人には向かない.fitbit.Fitbit(... system="ja-JP") と値を指定しておくとkg単位になる.
関数
ここにリファレンスがある.引っかかったところをいくつかメモしておく.
_COLLECTION_RESOURCE(resource, date=None, user_id=None, data=None)
fitbit.comにデータをアップロードするにはこのメソッドを使用するが,このメソッドはcurryを使うことで以下のメソッドが実装されていることになる.
body(date=None, user_id=None, data=None)\ activities(date=None, user_id=None, data=None)\ foods(date=None, user_id=None, data=None)\ water(date=None, user_id=None, data=None)\ sleep(date=None, user_id=None, data=None)\ heart(date=None, user_id=None, data=None)\ bp(date=None, user_id=None, data=None)
例えば2014-5-5のbody情報を,体重65.2kg,体脂肪率14.2%にアップロードしたい場合は,
self.client = fitbit.Fitbit(....) self.client.body(date="2014-5-5", data={"weight": "65.2", "fat": "14.2"})
とすればサーバーの値が更新される.詳細は,https://wiki.fitbit.com/display/API/API-Log-Body-Measurements に書いてある.
time_series(resource, user_id=None, base_date="today", period=None, end_date=None)
時系列のグラフを書きたいときなどは,この関数を使って,指定した期間のデータをまとめてダウンロードする必要がある.例えば,base_dateからperiodの期間の体重を取得したい場合は.
self.client.time_series(”body/weight", base_date=base_date, period=period)
とすればよい.パラメータの詳細は https://wiki.fitbit.com/display/API/API-Get-Time-Series に書いてある.
取得した値の処理だが,基本的にはpythonのdictionary型で返ってくるので,適宜扱えばよい.
サーバー側のデータの扱い
先月の体重をまとめてアップロードした場合,fitbitはどのような処理をするのかを実験してみたところ,先月の体重がグラフに追加され,目標値に対する評価は行ってくれたが,バッチはもらえなかった.やはりwellnesslinkと同様,手動で記録したデータと,測定器から直接同期したデータの扱いは異なるようである.
とりあえず現時点では以上です.