みーのぺーじ

みーが趣味でやっているPCやソフトウェアについて.Python, Javascript, Processing, Unityなど.

Fitbit API を Pythonで使ってみた

先日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と同様,手動で記録したデータと,測定器から直接同期したデータの扱いは異なるようである.

とりあえず現時点では以上です.