Fitbit API から睡眠データを取得してみた
Fitbit Charge2 を装着したまま洗顔をしたら、水がかかりお亡くなりになりました。。。
ちょうど、Fitbit Charge3 が出たので購入。 今度は防水なので大丈夫でしょう!!
せっかくなので、睡眠データを取得して何かをしたいと思います。
睡眠レベル
一言に睡眠と言っても、状態によっていくつかレベルがあります。
- 覚醒状態 (wake)
- 毎晩10-30回ほど発生
- 期間が非常に短い
- レム睡眠 (rem)
- 浅い眠り、体の眠り
- 夢を見ることがある
- 心拍数が上がったり、呼吸が早くなったり
- ノンレム睡眠
- 深い眠り、脳の眠り
- 第1段階〜第4段階に分かれる
眠りの深さは
覚醒状態 -> レム睡眠 -> ノンレム睡眠 第1段階 -> ノンレム睡眠 第4段階
の順に深くなります。
Fitbitでは、ノンレム睡眠を浅い睡眠と深い睡眠の2つに分け、4つの睡眠レベルに分けています。
- 目覚めた状態 (wake)
- レム睡眠 (rem)
- 浅い睡眠 (light)
- ノンレム睡眠 第1段階
- ノンレム睡眠 第2段階
- 深い睡眠 (deep)
- ノンレム睡眠 第3段階
- ノンレム睡眠 第4段階
俺の睡眠データ
基本、早寝早起きです。たまに小学生の子供達より早く寝ます。
手っ取り早く、curlで叩いて睡眠データを取得します。
Fitbit APIをcurlで叩く方法は、下記のエントリを参照してください。
《2018-11-16》
ver1.1以前(classic) と 1.2(stages) ではフォーマットが異なるので注意です。
ver1.1の場合
curl -H "Authorization: Bearer **********.**********" https://api.fitbit.com/1.1/user/-/sleep/date/2018-11-16.json | jq . > 2018-11-16-v1.1.json
2018-11-16-v1.1.json
{ "sleep": [ { "awakeCount": 0, "awakeDuration": 0, "awakeningsCount": 17, "dateOfSleep": "2018-11-16", "duration": 30000000, "efficiency": 95, "endTime": "2018-11-16T05:39:00.000", "isMainSleep": true, "logId": 20170274799, "minuteData": [ { "dateTime": "21:18:30", "value": "1" }, { "dateTime": "21:19:30", "value": "1" }, 略 { "dateTime": "05:36:30", "value": "1" }, { "dateTime": "05:37:30", "value": "1" } ], "minutesAfterWakeup": 0, "minutesAsleep": 473, "minutesAwake": 27, "minutesToFallAsleep": 0, "restlessCount": 17, "restlessDuration": 27, "startTime": "2018-11-15T21:18:30.000", "timeInBed": 500 } ], "summary": { "stages": { "deep": 71, "light": 215, "rem": 85, "wake": 41 }, "totalMinutesAsleep": 473, "totalSleepRecords": 1, "totalTimeInBed": 500 } }
v1.2の場合
curl -H "Authorization: Bearer **********.**********" https://api.fitbit.com/1.2/user/-/sleep/date/2018-11-16.json | jq . > 2018-11-16-v1.2.json
2018-11-16-v1.2.json
{ "sleep": [ { "dateOfSleep": "2018-11-16", "duration": 30000000, "efficiency": 95, "endTime": "2018-11-16T05:39:00.000", "infoCode": 0, "isMainSleep": true, "levels": { "data": [ { "dateTime": "2018-11-15T21:18:30.000", "level": "wake", "seconds": 30 }, { "dateTime": "2018-11-15T21:19:00.000", "level": "light", "seconds": 300 }, 略 { "dateTime": "2018-11-16T05:23:00.000", "level": "wake", "seconds": 510 }, { "dateTime": "2018-11-16T05:31:30.000", "level": "light", "seconds": 450 } ], "shortData": [ { "dateTime": "2018-11-15T21:18:30.000", "level": "wake", "seconds": 150 }, { "dateTime": "2018-11-15T21:59:00.000", "level": "wake", "seconds": 60 }, 略 { "dateTime": "2018-11-16T05:10:30.000", "level": "wake", "seconds": 30 }, { "dateTime": "2018-11-16T05:33:30.000", "level": "wake", "seconds": 30 } ], "summary": { "deep": { "count": 6, "minutes": 79, "thirtyDayAvgMinutes": 72 }, "light": { "count": 35, "minutes": 264, "thirtyDayAvgMinutes": 196 }, "rem": { "count": 10, "minutes": 92, "thirtyDayAvgMinutes": 64 }, "wake": { "count": 38, "minutes": 65, "thirtyDayAvgMinutes": 43 } } }, "logId": 20170274799, "minutesAfterWakeup": 0, "minutesAsleep": 435, "minutesAwake": 65, "minutesToFallAsleep": 0, "startTime": "2018-11-15T21:18:30.000", "timeInBed": 500, "type": "stages" } ], "summary": { "stages": { "deep": 71, "light": 215, "rem": 85, "wake": 41 }, "totalMinutesAsleep": 435, "totalSleepRecords": 1, "totalTimeInBed": 500 } }
ver1.2の方が睡眠レベル単位でまとめているため、データ容量が少なくなる傾向になります。
以後、ver1.2形式で取得します。
《2018-11-17》
Fitbitを外したまま寝てしまった。。。
しかし、エラーにならず結果が取得できることがわかりました。
curl -H "Authorization: Bearer **********.**********" https://api.fitbit.com/1.2/user/-/sleep/date/2018-11-17.json | jq . > 2018-11-17-v1.2.json
2018-11-17-v1.2.json
{ "sleep": [], "summary": { "totalMinutesAsleep": 0, "totalSleepRecords": 0, "totalTimeInBed": 0 } }
《2018-11-18》
curl -H "Authorization: Bearer **********.**********" https://api.fitbit.com/1.2/user/-/sleep/date/2018-11-18.json | jq . > 2018-11-18-v1.2.json
2018-11-18-v1.2.json
{ "sleep": [ { "dateOfSleep": "2018-11-18", "duration": 24840000, "efficiency": 89, "endTime": "2018-11-18T05:30:00.000", "infoCode": 0, "isMainSleep": true, "levels": { "data": [ { "dateTime": "2018-11-17T22:36:00.000", "level": "wake", "seconds": 30 }, { "dateTime": "2018-11-17T22:36:30.000", "level": "light", "seconds": 1020 }, 略 { "dateTime": "2018-11-18T05:18:00.000", "level": "light", "seconds": 510 }, { "dateTime": "2018-11-18T05:26:30.000", "level": "wake", "seconds": 210 } ], "shortData": [ { "dateTime": "2018-11-17T22:36:00.000", "level": "wake", "seconds": 120 }, { "dateTime": "2018-11-17T22:45:00.000", "level": "wake", "seconds": 30 }, 略 { "dateTime": "2018-11-18T04:32:00.000", "level": "wake", "seconds": 30 }, { "dateTime": "2018-11-18T04:35:00.000", "level": "wake", "seconds": 120 } ], "summary": { "deep": { "count": 4, "minutes": 77, "thirtyDayAvgMinutes": 73 }, "light": { "count": 23, "minutes": 203, "thirtyDayAvgMinutes": 209 }, "rem": { "count": 8, "minutes": 75, "thirtyDayAvgMinutes": 70 }, "wake": { "count": 26, "minutes": 59, "thirtyDayAvgMinutes": 47 } } }, "logId": 20192347613, "minutesAfterWakeup": 0, "minutesAsleep": 355, "minutesAwake": 59, "minutesToFallAsleep": 0, "startTime": "2018-11-17T22:36:00.000", "timeInBed": 414, "type": "stages" } ], "summary": { "stages": { "deep": 71, "light": 215, "rem": 85, "wake": 41 }, "totalMinutesAsleep": 355, "totalSleepRecords": 1, "totalTimeInBed": 414 } }
睡眠データの項目
公式ドキュメントを見ても項目についての詳細な説明がなく、項目名と実データから推測。間違っていたらコメントください。
睡眠データ
睡眠データ(sleep)は配列形式です。
昼寝をして夜寝た場合は2件登録されます。複数件ある場合は、Fitbit側が判定して1件だけisMainSleepフラグをtrueにします。
項目 | サンプル | 説明 | |
---|---|---|---|
dateOfSleep | '2018-09-18' | 睡眠日 | |
duration | 21960000 | ベッド(布団)にいた合計時間(ミリ秒) | |
efficiency | 97 | 睡眠効率(%)。のび太は100。計算方法はここを参考 | |
endTime | '2018-09-18T05:06:00.000' | 起床時間 | |
infoCode | 0 | ||
isMainSleep | true | メインの睡眠かどうか | |
levels | 明細データのレベル | ||
data | {"dateTime": "2018-09-18T02:27:00.000", "level": "rem", "seconds": 840} | 睡眠レベル単位のデータ配列。wake, rem, light, deepの4種類。睡眠レベル、開始時間、持続時間(秒) | |
shortData | {"dateTime": "2018-09-17T23:04:00.000", "level": "wake", "seconds": 150} | 覚醒データ配列。目覚めた状態が3分以内のデータ | |
summary | "deep": {"count": 4, "minutes": 78, "thirtyDayAvgMinutes": 57} | 睡眠レベル単位の要約データ。合計回数、合計時間(分)、30日間の平均時間(分) | |
logId | 19548152255 | ログID | |
minutesAfterWakeup | 5 | 起床した後の時間(分) | |
minutesAsleep | 334 | 睡眠時間(分) | |
minutesAwake | 32 | 起きていた時間(分) | |
minutesToFallAsleep | 0 | 最初の眠るまでの時間(分) | |
startTime | '2018-09-17T23:00:00.000' | 就寝時間 | |
timeInBed | 366 | ベッド(布団)にいた時間(分)。minutesAsleep + minutesAwake | |
type | 'stages' | 睡眠データの種類 |
timeInBed = minutesToFallAsleep + minutesAsleep + minutesAwake
要約データ
項目 | サンプル | 説明 | |
---|---|---|---|
stages | 睡眠レベル | ||
deep | 38 | 深い睡眠(分) | |
light | 163 | 浅い睡眠(分) | |
rem | 82 | レム睡眠(分) | |
wake | 31 | 目覚めた状態(分) | |
totalMinutesAsleep | 334 | 睡眠時間の合(分) | |
totalSleepRecords | 1 | 合計睡眠回数(sleep配列の件数) | |
totalTimeInBed | 366 | ベッド(布団)にいた合計時間(分)。totalTimeInBed - totalMinutesAsleep が起きている時間 |
Python3の場合
Fitbit用のモジュールを利用すると簡単に取得できます。
クライアントID (OAuth 2.0 Client ID)、クライアントシークレット、アクセストークン、リフレッシュトークンは https://dev.fitbit.com/apps で登録したアプリから取得した値を設定します。
API_VERSIONに1.2
を指定しています。(デフォルト1.0)
import datetime import fitbit def main(): client = fitbit.Fitbit(CLIENT_ID, CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) client.API_VERSION = 1.2 dt = datetime.date(2018, 11, 18) sleep = client.get_sleep(dt) print(sleep) if __name__ == "__main__": main()