アイドルの生体情報をNokia Sleep&Body+で計測し毎日ツイートする

# 概要
アイドルグループ・・・・・・・・・は、**アイドルの生体情報を計測し、毎日ツイートする**企画「今日の生体情報」を実施した。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">第13回定期公演「Tokyo in Bio」<br><br>今日の生体情報です！<br><br>Tokyo in Bioの概要と楽しみ方のヒント👇<a href="https://t.co/iV0Du2WdHT">https://t.co/iV0Du2WdHT</a><a href="https://twitter.com/hashtag/Tokyo_in_Bio?src=hash&amp;ref_src=twsrc%5Etfw">#Tokyo_in_Bio</a><a href="https://twitter.com/hashtag/%E4%BB%8A%E6%97%A5%E3%81%AE%E7%94%9F%E4%BD%93%E6%83%85%E5%A0%B1?src=hash&amp;ref_src=twsrc%5Etfw">#今日の生体情報</a><a href="https://twitter.com/hashtag/NokiaSleep?src=hash&amp;ref_src=twsrc%5Etfw">#NokiaSleep</a> <a href="https://t.co/LcVAYrHCZS">pic.twitter.com/LcVAYrHCZS</a></p>&mdash; ・・・・・・・・・ (@dotstokyo) <a href="https://twitter.com/dotstokyo/status/1022093017312907265?ref_src=twsrc%5Etfw">2018年7月25日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

*実際のツイートは以下から確認できる*
[from:dotstokyo #今日の生体情報 - Twitter検索](https://twitter.com/search?https://twitter.com/search?l=&q=%23今日の生体情報%20from%3Adotstokyo&src=typd)

本記事では、企画内容と、企画の実施主体である・・・・・・・・・を紹介したあと、

- 計測に使用した機材、Nokia Sleep, Nokia Body+の概要
- Nokia Sleep, Nokia Body+が計測したデータのうち、「APIでアクセスできるデータ」「APIでアクセスできないデータ」のリスト
- Nokia Sleep, Nokia Body+が計測したデータに、Nokia Health APIを使ってアクセスする方法

を示す。

## 企画内容
- Nokia Sleepで、アイドルの「眠りの長さと深さ」を毎日計測する
- 計測した睡眠データをチャートに起こす

![sleep_series_sample.jpeg](https://qiita-image-store.s3.amazonaws.com/0/133133/1d8bc1cb-82f2-2207-c546-d4da2fa2a500.jpeg)

- Nokia Body+で、アイドルの「筋肉量・水分量・骨量」を毎日計測する
- 計測した体組成データを表に起こす

![body_measure_sample.jpeg](https://qiita-image-store.s3.amazonaws.com/0/133133/37d0c9b6-d488-f25b-8761-3b70f8075821.jpeg)

- 以上二点の画像を、毎日ツイートする

# コンセプト
- **普段どおりの生活を送っているだけでコンテンツが生成される**仕組みづくり
- 「他者への介入と、介入を受けての振る舞いの変化、そのフィードバックループによって進化していく生態系」であるTwitterで、あえて、**人の意思では操作困難な身体のシグナル**を発信する
- **身体によるツイート**
- 人格を有したヒトによるツイート、人格を有さない機械によるツイート、人格を有した機械によるツイートが入り乱れるTwitter空間に、「ヒト」×「非人格」という新たな切り口を提供する

|        |       人格 | 非人格       |
|:----------------:|:-----------------:|:------------------:|
| ヒト            |  きゃりーぱみゅぱみゅ([@pamyurin](https://twitter.com/pamyurin)) |        今日の生体情報([@dotstokyo](https://twitter.com/dotstokyo))        |
| 機械          |    りんな([@ms_rinna](https://twitter.com/ms_rinna)) |   気温bot(関東)([@__BQ](https://twitter.com/__BQ))          |


# ・・・・・・・・・
- ・・・・・・・・・はおもに東京で活動をしているアイドルグループ
- グループの正式な呼び名はなく、人それぞれ「ドッツトーキョー」「てんきゅー」など思い思いの呼び方をしている
- メンバーの名前は全員「・」。ファンからは「・ちゃん」と呼ばれている
- メンバーはサングラスのようなもので顔が隠れている
- さまざまな[テクノロジー企画](https://dots.tokyo/about/#technology)を実施している

![dotstokyo.jpg](https://qiita-image-store.s3.amazonaws.com/0/133133/605d0017-f01d-ba78-960f-78033f7c2f51.jpeg)

・・・・・・・・・は過去にも、プロダクトや企画で生体情報を用いている。

- [アイドルの睡眠データを3Dプリンタでオブジェ化して日本武道館で展示する](https://qiita.com/a-r-i/items/908fbe2ced42734335f3)
 - 睡眠データを計測するのにFitbitを使用
- [アイドルのリアルタイム心拍を転送、心拍数に合わせてファンのスマホが震えるアプリ](https://dots.tokyo/about/#heartsync)
 - 心拍数の計測にはmioFuseを使用

・・・・・・・・・についてのさらなる情報は、以下のページを参照。
[・・・・・・・・・について](https://dots.tokyo/about)

# Nokia Sleep
- Nokiaが販売している、敷きパッド型の睡眠トラッカー
 - Fitbitなどの腕時計型トラッカーと異なり、**わざわざ寝る前に装着する必要がない**
 - **普通に生活してるだけで睡眠情報を計測できる**

![sleep-front_lg_2x.png](https://qiita-image-store.s3.amazonaws.com/0/133133/670c76ee-bc98-d511-cf1b-edd21e9ca7ca.png)

![sleep-bed-poster-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/133133/f1d96334-ca33-dfbe-1a29-e096b9cec5d4.jpeg)

- [スリープセンシング＆ホームオートメーションパッド | Nokia Sleep](https://health.nokia.com/jp/ja/sleep)

## Nokia Health APIでアクセスできるデータ
### Sleep - v2 Get
眠りの深さ

| value       |       state |    状態    |
|:----------------:|:-----------------:|:------------------:|
| 0            |              awake |        目覚めている状態        |
| 1           |            light sleep |       浅い睡眠       |
| 2            |              deep sleep |        深い睡眠        |
| 3               |     REM sleep |         とても浅い睡眠(レム睡眠)         |

[Sleep - v2 Get](http://developer.withings.com/oauth2/#tag/sleep%2Fpaths%2Fhttps%3A~1~1api.health.nokia.com~1v2~1sleep%3Faction%3Dget%2Fget)

### Sleep - v2 Getsummary
睡眠の概要

| 　　　　　　　　|       　　　　　　　 |
|:----------------:|:-----------------:|
|wakeupduration   | (ベッドの中で)起きていた時間(秒) |
|lightsleepduration  |浅い睡眠の時間(秒) |
|deepsleepduration |深い睡眠の時間(秒) |
|remsleepduration |とても浅い睡眠(レム睡眠)の時間(秒) | 
|durationtosleep | ベッドに入ってから、眠るまでの時間(秒) | 
|durationtowakeup|目覚めた後、ベッドから出るまでの時間(秒) |
|wakeupcount    |  睡眠が中断された回数 |

[Sleep - v2 Getsummary](http://developer.withings.com/oauth2/#tag/sleep%2Fpaths%2Fhttps%3A~1~1api.health.nokia.com~1v2~1sleep%3Faction%3Dgetsummary%2Fget)

## Nokia Health APIでアクセスできないデータ
計測しているが、Nokia Health APIからはアクセスできないデータ

- 睡眠スコア
- 規則性
- 睡眠時心拍数
- いびきの長さ
- 呼吸数

このうち、睡眠時心拍数・いびきの長さ・呼吸数は、Nokia HealthダッシュボードからCSV形式でダウンロードできる。

ダッシュボード
[https://dashboard.health.nokia.com/](https://dashboard.health.nokia.com/)

# Nokia Body+
- Nokiaが販売している体組成計

![bodyplus-black-fatmass-m_lg_2x.png](https://qiita-image-store.s3.amazonaws.com/0/133133/be034fea-6177-3312-5d8e-4355ac8234c0.png)

[Wi-Fi対応 体組成計 | Nokia Body+](https://health.nokia.com/jp/ja/body-plus)

## Nokia Health APIでアクセスできるデータ
### Measure - Getmeas

| value       |       meastype |    種類    |
|:----------------:|:-----------------:|:------------------:|
| 1             |  Weight(kg) |    体重        |
| 5            |  Fat Free Mass (kg)|  除脂肪体重      |
| 6             | Fat Ratio (%)  | 体脂肪率      |
| 8               | Fat Mass Weight (kg)|  体脂肪量      |
| 76             | Muscle Mass|   筋肉率    |
| 77         | Hydration |   水分量   |
| 88         |Bone Mass  |骨量 |

[Measure - Getmeas](http://developer.withings.com/oauth2/#tag/measure%2Fpaths%2Fhttps%3A~1~1api.health.nokia.com~1measure%3Faction%3Dgetmeas%2Fget)

## Nokia Health APIでアクセスできないデータ
なし

# Nokia Health API
Nokia製品で計測したデータにアクセスできるAPI

>このAPIをご使用いただくことで、開発者の方々は、体重、体脂肪、アクティビティ、睡眠、血圧、心拍数など、Nokia製品で測定された健康データにアクセスし、それらを開発者様のサービスに統合したり、全く新しい革新的なユーザー体験を作成したりできます。
>[https://health.nokia.com/jp/ja/developers](https://health.nokia.com/jp/ja/developers)

ドキュメント
[Nokia Health API developer documentation](http://developer.withings.com/oauth2/)

以下、Nokia Health APIを使って、Nokia Sleep, Nokia Body+が計測したデータにアクセスする手順を示す。

## 下準備
1. Nokia Healthアカウントを取得
  - https://account.withings.com/connectionwou/account_create
1. 以下のページを参考にNokia Sleep, Nokia Body+とスマートフォンをペアリング

- [Nokia Sleepのセットアップ – Nokia](https://support.health.nokia.com/hc/ja/articles/360000123667-Nokia-Sleepのセットアップ)
- [Nokia Body+ - 体重計をインストールする - iOS手順 – Nokia](https://support.health.nokia.com/hc/ja/articles/219051817-Nokia-Body-体重計をインストールする-iOS手順)
- [Nokia Body+ - 体重計をインストールする - Android手順 – Nokia](https://support.health.nokia.com/hc/ja/articles/218553558-Nokia-Body-体重計をインストールする-Android手順)

## アプリ登録(client id, consumer secretの取得)
1. アプリを登録
 - [https://account.withings.com/partner/add_oauth2](https://account.withings.com/partner/add_oauth2)

1. 登録するとclient idとconsumer secretが表示されるので、控えておく

## access tokenの取得
### access tokenとは
- 有効期限は4時間
- access tokenを使うことで、Nokia Health APIにアクセスできる
- refresh tokenを使ってリフレッシュできる

### refresh tokenとは
- 有効期限は1年間
- access tokenをリフレッシュするために使われる
 - リフレッシュすると、新しいrefresh tokenが返される。古いものは4時間後に失効する

### authentication codeの取得
[OAuth 2.0 - Get your authentication code](http://developer.withings.com/oauth2/#tag/OAuth-2.0%2Fpaths%2Fhttps%3A~1~1account.health.nokia.com~1oauth2_user~1authorize2%3Fresponse_type%3Dcode%5B...%5D%2Fget)

ベースURLにパラメーターを付与して、ブラウザからアクセスする。

```:ベースURL
https://account.withings.com/oauth2_user/authorize2
```

パラメーター

- response_type
 - "code"
- client_id
- state
 - サイトやアプリにリダイレクトされたものが偽装されていないことを確認するために使用
 - 必須ではないが、なぜか付け足さないとユーザー同意画面に飛べなかった
- scope
 - アクセスできるデータの範囲
 - 詳細→ [Scopes](http://developer.withings.com/oauth2/#tag/scopes) 
- redirect_uri
 - アプリ登録で記入したコールバックURL

本企画の場合、最終的なURLはこのようになった

```:最終的なURL
https://account.withings.com/oauth2_user/authorize2?response_type=code&client_id=クライアントID&state=hoge&scope=user.metrics,user.activity&redirect_uri=http://localhost:4567/oauth/callback
```

このURLにアクセスすると、ユーザー同意画面が表示される。

<img width="567" alt="68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3133333133332f37353539316362392d633930372d626234342d393631302d3362383736333761353764612e706e67.png" src="https://qiita-image-store.s3.amazonaws.com/0/133133/067e3481-d958-aa2e-c939-d04a59f50275.png">

「このアプリを許可する」を選ぶと、authentication codeが付与されたコールバックURLにリダイレクトされる。

```
http://localhost:4567/oauth/callback?code=オーセンティケーションコード&state=hoge
```

### access tokenの取得
[OAuth 2.0 - Get your access token](http://developer.health.nokia.com/oauth2/#tag/OAuth-2.0%2Fpaths%2Fhttps%3A~1~1account.health.nokia.com~1oauth2~1token%20%5Bgrant_type%3Dauthorization_code%5D%2Fpost)

authentication codeを使って、access tokenを取得する。
以下は、Python3.6.1での例。

```python:get_accesstoken
def get_accesstoken(client_id, client_secret, code, redirect_uri):
    url = "https://account.withings.com/oauth2/token"

    payload = {
                "grant_type": "authorization_code",
                "client_id": client_id,
                "client_secret": client_secret, # consumer secretのこと
                "code": code, # authentication codeのこと
                "redirect_uri": redirect_uri
              }

    r = requests.post(url, data=payload)

    return r.json()
```

レスポンスにaccess tokenとrefresh tokenが含まれている。

```
{'access_token': ‘アクセストークン’, 'expires_in': '10800', 'token_type': 'Bearer', 'scope': 'user.metrics,user.activity', 'refresh_token': ‘リフレッシュトークン’, 'userid': ‘ユーザーID’}
```

### access tokenのリフレッシュ
[OAuth 2.0 - Refresh your access token](http://developer.withings.com/oauth2/#tag/OAuth-2.0%2Fpaths%2Fhttps%3A~1~1account.health.nokia.como~1auth2~1token%20%5Bgrant_type%3Drefresh_token%5D%2Fpost)

```python:refresh_accesstoken
def refresh_accesstoken(client_id, client_secret, refresh_token):
    url = "https://account.withings.com/oauth2/token"

    payload = {
                "grant_type": "refresh_token",
                "client_id": client_id,
                "client_secret": client_secret,
                "refresh_token": refresh_token
              }

    r = requests.post(url, data=payload)

    return r.json()

```

## データへのアクセス
### Sleep - v2 Get
[Sleep - v2 Get](http://developer.health.nokia.com/oauth2/#tag/sleep%2Fpaths%2Fhttps%3A~1~1api.health.nokia.com~1v2~1sleep%3Faction%3Dget%2Fget)

```python:get_sleep
def get_sleep(access_token, startdate, enddate):
    url = "https://wbsapi.withings.net/v2/sleep?action=get"

    payload = {
               "access_token": access_token,
               "startdate": startdate, # UNIXタイムスタンプで指定
               "enddate": enddate # UNIXタイムスタンプで指定
              }

    r = requests.get(url, params=payload)

    return r.json()
```
### Sleep - v2 Getsummary
[Sleep - v2 Getsummary](http://developer.health.nokia.com/oauth2/#tag/sleep%2Fpaths%2Fhttps%3A~1~1api.health.nokia.com~1v2~1sleep%3Faction%3Dgetsummary%2Fget)

```python:get_summary
def get_summary(access_token, startdateymd, enddateymd):
    url = "https://wbsapi.withings.net/v2/sleep?action=getsummary"

    payload = {
               "access_token": access_token,
               "startdateymd": startdateymd, # YYYY-MM-DD形式で指定
               "enddateymd": enddateymd # YYYY-MM-DD形式で指定
              }

    r = requests.get(url, params=payload)

    return r.json()
```
### Measure - Getmeas
[Measure - Getmeas](http://developer.health.nokia.com/oauth2/#tag/measure%2Fpaths%2Fhttps%3A~1~1api.health.nokia.com~1measure%3Faction%3Dgetmeas%2Fget)

```python:get_meas
def get_meas(access_token, startdate, enddate):
    url = "https://wbsapi.withings.net/measure?action=getmeas"

    payload = {
                "access_token": access_token,
                "startdate": startdate, # UNIXタイムスタンプで指定
                "enddate": enddate # UNIXタイムスタンプで指定
              }

    r = requests.get(url, params=payload)

    return r.json()
```

# ソースコード
- [https://github.com/a-r-i/nokiahealth_py](https://github.com/a-r-i/nokiahealth_py)
- [https://github.com/a-r-i/tweet_nokiahealth_bioinfomation](https://github.com/a-r-i/tweet_nokiahealth_bioinfomation)