PythonからFitbit APIを使ってデータを取得する(OAuth2)
昨年2016年にFitbitデビューしました。APIを使って遊んでみたかったのですができていませんでした。 以前この記事でもFitbit APIを使ってみたい的なことを言ったのでこの度やってみました。
この手のやってみた系は日本や海外ブログでいくつか見つけたのですが、最初のトークン取得を別の方法でできたのと、OAuth2トークンを更新してから保存する部分について説明しているところが見当たらず試行錯誤したので共有します。
アプリの登録
ここは他の方が書いていることと大して変わらないためさらっといきます。
「Register new app」タブを選択
設定内容はこんな感じにしました。
- Application Name * : my3rdFBapp
- Description * : my3rdFBapp
- Application Website * : このブログのURL
- Organization * : none
- Organization Website * : このブログのURL
- OAuth 2.0 Application Type * : Personal
- Callback URL * :
http://127.0.0.1:8080/
- Default Access Type * : Read & Write
agreeしてRegister
登録が完了するとトークンを発行するための情報が表示される。OAuth 2.0 Client ID
とClient Secret
をメモしておく。
トークンの発行
続いて先ほどの作成したアプリのページ下部にある「OAuth 2.0 tutorial page」を選択します。(https://dev.fitbit.com/apps/oauthinteractivetutorial)
ここからの手順が結構重要&複雑です。
Authorize
- Flow type : Authorization Code Flow
- Fitbit URL : www.fitbit.com(デフォルト)
- OAuth 2.0 Client ID : メモした
OAuth 2.0 Client ID
- Client Secret : メモした
Client Secret
- Redirect URI :
http://127.0.0.1:8080/
Select Scopes
とExpires In(ms)
はデフォルトでOK。(Expires In(ms)
は値を変えても反映されなかったのでよくわからないまま)これらをすべて入力すると、その下に長いURLが生成されている。それをクリックする。 こんな画面が表示されるので許可を選択。
そうするとアクセスできませんの画面が表示されるけど、これでOK。
ブラウザのURLのバーをみると、
http://127.0.0.1:8080/?code=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#_=_
的な感じにリダイレクトされていると思う。 これのcode=
の後から#
の手前までのコードをコピーする。コピーしたコードを先ほどのチュートリアルページの
Code:
の後の入力ボックスにペーストする。 そうするとcurl
コマンドが生成されて表示されるのでそれをコピーしてターミナルで実行する。成功するとこんな感じのトークンとか他の情報が発行されるのでメモしておく。
{"access_token":"xxxx","expires_in":28800,"refresh_token":"xxxx", "scope":"settings location sleep social heartrate activity nutrition weight profile", "token_type":"Bearer","user_id":"XXXXXX"}
エラーが出たらここまでの手順でなにかミスっているのでやり直す。
ここでようやっとPython
以下の環境でやりました。
- OS: CentOS7.2
- Python: 3.5.1
fitbitモジュールを使います。
$ pip install fitbit
$ vi token.txt さっきの項目5でコピーしたトークンをまるごと貼り付ける
$ vi app.py
下のコードを貼る。CLIENT_ID
とCLIENT_SECRET
を入れてください。
# -*- coding: utf-8 -*- import fitbit import datetime from ast import literal_eval CLIENT_ID = "XXXXXX" # 自分のやつを入れる。 CLIENT_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # 自分のやつを入れる。 TOKEN_FILE = "token.txt" tokens = open(TOKEN_FILE).read() token_dict = literal_eval(tokens) access_token = token_dict['access_token'] refresh_token = token_dict['refresh_token'] def updateToken(token): f = open(TOKEN_FILE, 'w') f.write(str(token)) f.close() return def pound_to_kg(pound): kg = pound * 0.454 return kg client = fitbit.Fitbit(CLIENT_ID, CLIENT_SECRET, access_token = access_token, refresh_token = refresh_token, refresh_cb = updateToken) #TODAY = datetime.date.today() TODAY = "2017-02-02" bodyweight = client.get_bodyweight(base_date=TODAY) weight = bodyweight["weight"][0]["weight"] print(pound_to_kg(weight), "kg")
実行する
$ python app.py xx.xx kg
ポイント
コードの下手さは勘弁してください。ポイントになるのは、fitbit.Fitbit()
を呼び出すときのrefresh_cb
引数です。
Fitbit APIが採用しているOAuth2は、一定時間を超えるとアクセストークンが失効してしまいます(デフォルトでは8時間)。リフレッシュトークンを使えばアクセストークンを更新することができます。その際にリフレッシュトークンも更新されます。
python-fitbitモジュールではAPI実行時にトークンが失効していた場合はリフレッシュするところまでやってくれます。
しかし保存するところまではやってくれません。先程token.txt
に書いたトークンを随時更新していく必要があるのでそこは自分で実装する必要があります。
そこで、refresh_cb
に関数を渡しておくと、もしfitbit.Fitbit()
を呼び出したときにトークンが失効していた場合は自動的にリフレッシュした後、指定した関数に新しいトークンを渡してくれます。
なのでupdateToken()
では新しいトークンを受け取ってファイルに上書きするということをしています。
ちなみにトークン更新後にファイルに上書きするのに失敗した場合、再度トークンを使用するためにはトークン新規発行以外に方法はないので注意しましょう。
このコードではupdateToken()
の中でファイルに上書きをしていますが、DBに入れるとかするともっといいと思います。
client
を認証した後は好きにやってあげてください。データの参照も更新もできるはずです。今回コード中でweightを参照していて、Fitbitなのに体重?と思うかもしれませんが、私の場合、体重計はWithingsを使っていてIFTTTを使ってFitbitにも反映されるようにしているので体重が見れます。
ハマったところ
- CLIENT_IDとかCLIENT_SECRETとかcodeとかaccess_tokenとかrefresh_tokenとかもうよくわからない。
- OAuth2が全然わからない。
- トークンが失効するまでに8時間かかるので失効→リフレッシュ→トークンファイル更新を頻繁に試せない。
- 最後までいいテスト方法がわからず。(だれか教えてください…)
まとめ
これで継続的にデータがとれるようになりました。
今回しんどいこと多かったですがPythonとOAuth2と英語のいい勉強になりました。
やっとAPIを使う準備ができたので今度はFitbit APIを使って何か作ってみようと思います。