y.takky てくめも

web技術について勉強会の参加メモだったり、本を読んだメモだったりを載せる予定

【なつやすみのしゅくだい】go言語でfitbitAPIを叩いて睡眠情報を取得する。

【なつやすみのしゅくだい】

前々からgo言語触りたかったってことと、FitbitAPIを叩いて情報を取得したかったので、夏季休暇期間の暇な時間にgo言語でfitbitAPIを叩いて睡眠情報を取得してみた。

ソースはこちら

github.com

作業のお供

zenpad7で dアニメストアでアニメ見ながら作業するのが捗った。
タブレットスタンドがかなり役立った。 CLANNAD Afterの後半とハナヤマタ前半見終わった。

anime.dmkt-sp.jp

fitbitAPIを使うために諸々登録する

dev.fitbit.com

dev.fitbit.comにユーザ登録をした後アプリケーションの登録を行う。
f:id:ytacky:20160818201858p:plain

画像の通りに必要なところを埋めていく。
Applicatinon NameやDescription, Application Website, Organization, Organization Websiteまでは適当でOK
自分で使うだけだし。
OAuth 2.0 Application Type はClientを選択した。
Using Implicit Grant Flowを使うためにはClientを選択する必要がある。

Using OAuth 2.0 — Fitbit Web API Docs

Callback URLは重要で、ここで登録したアドレス以外がcallbackのURLとして指定されても使うことができない。
今回はgoのビルドインサーバを使うのでlocalhost:8080とした。
Default Access Typeは読み取りだけでいいのでReadとした。

これでSaveすると、OAuth 2.0 Client ID / Client Secretが発行される。
また、 OAuth 2.0: Authorization URI と OAuth 2.0: Access/Refresh Token Request URIも取得できる。 (このURLは共通なので発行される。というより表示される。という書き方が正しいかもしれない)

どんな感じに叩くか確かめたい

Fitbit API Debug Tool

Debug toolが用意されている。
これに自分のClient IDやsecretを入力し指示に従って行くと、一通り認証から必要な情報の取得までできる。
プログラムを組み終わった後この機能に気づいた...

認証ページのURLを生成する

generateOauthURL.goとして作成した。

今回はAuthorization Code Flowで認証するための認証ページのURLを作成した。 examplsにあるように、

https://www.fitbit.com/oauth2/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope={scopes}

となる。 client_id/redirect_urlは上で生成したものになる。

scopeは

Using OAuth 2.0 — Fitbit Web API Docs

から見たい情報のscopeを選択する。今回は睡眠情報なのでsleepを指定。複数の場合空白で繋げて%エンコードする必要がある。 (%20で複数scopeをつなぐ)

コード上では、HttpParam構造体とAuthUrl構造体を作り、必要な情報はこれを使うようにしている。
また、環境変数は.envとしてアプリケーションのルートディレクトリに作成して、それをgithub.com/joho/godotenvライブラリを使用して読み込んで使用している。

アクセストークンの取得

上記で生成したURLにアクセスすると認証画面が表示され、認証するとredirect_urlに設定したページに飛ばされる。
このリダイレクト先をfitbit.goとして作成している。
今回は簡単に使いたかったのでgoのbuild inサーバを使用している。

リダイレクトされるとクエリパラメータに?code=とaccess token取得用のcodeが付与される。
まずはこのcodeを使用してaccess tokenを取得する。

https://dev.fitbit.com/docs/oauth2/#accessT

endpointのURLはhttps://api.fitbit.com/oauth2/token これに対してPOSTを行う。必要なBody部分としては、
リダイレクトのときについてきたcodeとgrant_type=authorization_code,client_id,redirect_uriが必要。 また、Headerには {client_id}:{client_secret}をBase64 Encodingしたものが必要となる。:をつけた状態の文字列をBase64 Encoding忘れるのがありがちなミスなので注意したいところ。

これでPOSTするとjson形式でaccess_tokenやscope,user_idが返却される。
この値をdecodeしたいので、FitbitJsonという構造体を作り、json.Unmarshalでdecodeした。

これで睡眠情報を取得するためのユーザIDとaccess_tokenが取得できた。

睡眠情報を取得する。

Sleep Logs — Fitbit Web API Docs

睡眠情報に関してAPIは多種あるが、今回は単純に睡眠時のログを取得するAPIを叩く。
APIのエンドポイントは、https://api.fitbit.com/1/user/[user-id]/sleep/date/[date].json となる。user-idはアクセストークンの取得で取得できたものを使用する。
dateはyyyy-MM-dd形式で指定する。
このAPIを叩くときには認証が必要なのでHeaderに Authorization: Bearer [access_token]
を与えてあげる必要がある。
これで睡眠情報が取得できる。

睡眠情報の形式

以下のようにjson形式で返却される。 (ここでは見やすいようにjson_decodeしたものを記載している)
起きた回数や睡眠効率。何時に寝てその時間帯はどんなステータス(寝返りを打っていたのか、目覚めていたのか)
何時間寝ていたのか。など取得できる。

{
    "sleep": [
        {
            "awakeCount": 0, 
            "awakeDuration": 0, 
            "awakeningsCount": 13, 
            "dateOfSleep": "2016-08-xx", 
            "duration": 25260000, 
            "efficiency": 94, 
            "isMainSleep": true, 
            "logId": 12226936629, 
            "minuteData": [
                {
                    "dateTime": "00:49:30", 
                    "value": "1"
                }, 
                {
                    "dateTime": "00:50:30", 
                    "value": "1"
                }, 
               ~~~~~
                {
                    "dateTime": "07:49:30", 
                    "value": "1"
                }
            ], 
            "minutesAfterWakeup": 0, 
            "minutesAsleep": 396, 
            "minutesAwake": 25, 
            "minutesToFallAsleep": 0, 
            "restlessCount": 13, 
            "restlessDuration": 25, 
            "startTime": "2016-08-xxT00:49:30.000", 
            "timeInBed": 421
        }
    ], 
    "summary": {
        "totalMinutesAsleep": 396, 
        "totalSleepRecords": 1, 
        "totalTimeInBed": 421
    }
}

今後

REFRESH TOKENをつかって認証したり、何か別なシステムと連携して捗るようにしたい。