[fitbit] 3. PythonでFitbit APIを使って心拍数データを取得してmatplotlibで表示

fitbit

はじめに

fitbitとは、心拍数、歩数や睡眠をトラッキングするために腕に着用するタイプのスマートウォッチです。日々の健康状態を把握するのに役立っています。ここでは、Fitbit APIを使って心拍数データを取得してmatplotlibで表示するまでを解説します。

手順

APIの登録など

その1を参照してください。

[fitbit] 1. PythonでFitbit APIを使ってデータ取得 その1 アプリの登録とtokenの取得
fitbitとは、心拍数、歩数や睡眠をトラッキングするために腕に着用するタイプのスマートウォッチです。日々の健康状態を把握するのにとても役立っています。ここでは、Fitbit APIを使ってデータを取得するために、アプリの登録からtokenの取得まで解説します。

fitbit-pythonのインストールなど

その2を参照してください。

[fitbit] 2. PythonでFitbit APIを使ってデータ取得 その2 fitbit-pythonによる睡眠データの取得とmatplotlibによる表示
fitbitとは、心拍数、歩数や睡眠をトラッキングするために腕に着用するタイプのスマートウォッチです。日々の健康状態を把握するのにとても役立っています。ここでは、アプリの登録からtokenの取得までを解説したその1の続きとして、Fitbit APIを使って睡眠データを取得してmatplotlibで表示するところまで解説します。

モジュールのインポート

バージョン

CLIENT_ID, tokenなどを定義

その1で取得したCLIENT_IDとCLIENT_SECRETとtoken.txtをここで使います。token.txtは実行ファイルと同じ場所に置いておきます。

認証

fitbit.Fitbit()により、認証を行います。updateToken関数はtokenの更新用の関数でrefresh_cbupdateTokenとすることでtokenの期限切れの際に随時更新してくれるようになります。

1秒単位で心拍数データを取得

DATEを設定し、client.intraday_time_series('activities/heart')とすることで心拍数データが得られます。detail_level=’1sec’で1秒単位のデータが得られます。しかし、実際に得られるデータはだいたい5,10,15秒間隔のデータとなっています。

日付つき時刻データの作成

データ数と同じサイズの日付データを作成して、時刻データと合体することで日付付き時刻データを作成します。

心拍数データの経時的な変化を表示

to_datetimeで時刻データをdatetime形式に変換し、横軸の時刻データをConciseDateFormatterでシンプルに表示しています。

1分間隔の心拍数データの経時的な変化を表示

intraday_time_seriesでdetail_level=’1min’とすることで1分間隔でデータを取得できます。
1sec間隔のデータと同様の方法で表示すると以下のようになります。

15分間隔の心拍数データの経時的な変化を表示

intraday_time_seriesでdetail_level=’15min’とすることで15分間隔でデータを取得できます。
1sec間隔のデータと同様の方法で表示すると以下のようになります。

まとめて表示

上で得られたプロットをまとめて表示すると以下のようになります。

コードをダウンロード(.pyファイル)

参考

Overview — Python-Fitbit 0.3.0 documentation
Python×fitbit APIを使って心拍数をリアルタイム(?)にSpreadSheetsへ保存する! - Qiita
はじめにfitbitを使い始めて1年近くになりますが、時計盤やアプリ開発ばかりでAPI周りをあまり触っていなかったことや、自身の研究のためもあり、今回はアクティビティデータのリアルタイム取得をやっ…

コメント

  1. […] 486;ンパイソン「[fitbit] 3. PythonでFitbit APIを使って心拍数データを取得してmatplotlibで表示」 […]

  2. 内山優希 より:

    先日はありがとうございました。
    再度質問をしてしまいすみません。バージョンのところなのですが、3.4.2のように . が2つ使ってしまうとエラーになってしまいます。
    また、fitbit初心者であり申し訳ないのですが、fitbit versionのところは、どのように変更するのでしょうか。またはこちらの記事に書いてあるバージョンをそのまま使ってよいのでしょうか。
    初心者の質問で申し訳ございませんが、ご回答いただけますと幸いです。

    • sabopy より:

      これらのコードはjupyter notebookまたはjupyter labでの実行を想定して書いていますので、エラーになる部分は#でコメントアウトすれば動くと思います。
      バージョンのところはバージョンの確認のために表示しているだけなので、こちらも#でコメントアウトでOKです。

  3. iwai より:

    手順通りに進めたとは思うのですが、下記のようなエラーが出てしまいました。

    ValueError Traceback (most recent call last)
    in
    15
    16 tokens = open(TOKEN_FILE).read()
    —> 17 token_dict = literal_eval(tokens)
    18 access_token = token_dict[‘access_token’]
    19 refresh_token = token_dict[‘refresh_token’]

    ~\anaconda3\lib\ast.py in literal_eval(node_or_string)
    89 return left – right
    90 return _convert_signed_num(node)
    —> 91 return _convert(node_or_string)
    92
    93

    ~\anaconda3\lib\ast.py in _convert(node)
    77 elif isinstance(node, Dict):
    78 return dict(zip(map(_convert, node.keys),
    —> 79 map(_convert, node.values)))
    80 elif isinstance(node, NameConstant):
    81 return node.value

    ~\anaconda3\lib\ast.py in _convert(node)
    72 return tuple(map(_convert, node.elts))
    73 elif isinstance(node, List):
    —> 74 return list(map(_convert, node.elts))
    75 elif isinstance(node, Set):
    76 return set(map(_convert, node.elts))

    ~\anaconda3\lib\ast.py in _convert(node)
    77 elif isinstance(node, Dict):
    78 return dict(zip(map(_convert, node.keys),
    —> 79 map(_convert, node.values)))
    80 elif isinstance(node, NameConstant):
    81 return node.value

    ~\anaconda3\lib\ast.py in _convert(node)
    88 else:
    89 return left – right
    —> 90 return _convert_signed_num(node)
    91 return _convert(node_or_string)
    92

    ~\anaconda3\lib\ast.py in _convert_signed_num(node)
    61 else:
    62 return – operand
    —> 63 return _convert_num(node)
    64 def _convert(node):
    65 if isinstance(node, Constant):

    ~\anaconda3\lib\ast.py in _convert_num(node)
    53 elif isinstance(node, Num):
    54 return node.n
    —> 55 raise ValueError(‘malformed node or string: ‘ + repr(node))
    56 def _convert_signed_num(node):
    57 if isinstance(node, UnaryOp) and isinstance(node.op, (UAdd, USub)):

    ValueError: malformed node or string:

    ご助言いただければ幸いです。

    • sabopy より:

      iwai様
      文字列をリストや辞書へ変換するast.literal_eval( )でエラーが起こっているので、tokenファイルのaccess_tokenを辞書形式に変換するのがうまくいっていないのだと思います。
      tokenファイルの意図しないところに改行が入っていることがあるので、それが原因かもしれません。改行のないtokenファイルで再度試行願います。

      • iwai より:

        ありがとうございます。上記のエラーは教えていただいた方法で解決できたのですが、今度は以下のようなエラーが出てしまいました。

        Traceback (most recent call last):
        File “heartbeat_fitbit.py”, line 17, in
        token_dict = literal_eval(tokens)
        File “C:\Users\atusi\anaconda3\lib\ast.py”, line 46, in literal_eval
        node_or_string = parse(node_or_string, mode=’eval’)
        File “C:\Users\atusi\anaconda3\lib\ast.py”, line 35, in parse
        return compile(source, filename, mode, PyCF_ONLY_AST)
        File “”, line 1
        {“access_token”:”eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyMzhCWTUiLCJzdWIiOiI5WUc5S1giLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJzY29wZXMiOiJ3aHIgd251dCB3cHJvIHdzbGUgd3dlaSB3c29jIHdhY3Qgd3NldCB3bG9jIiwiZXhwIjoxNjUxNjIxMTI4LCJpYXQiOjE2NTE1OTIzMjh9.36A7Ppk_tBHz5K2K7X8_121dW-qQfH7A7lpJiYm0fd0″,”expires_in”:28800,”refresh_token”:”1cecc2af59a000add15d8cd0be9426b25f3967e588e8b228dcfd6b5668839f78″,”scope”:”sleep nutrition activity heartrate social profile location weight settings”,”token_type”:”Bearer”,”user_id”:”9YG9KX”}
        ^
        SyntaxError: invalid character in identifier

        • sabopy より:

          expires_in 28800がとなっているので、tokenの有効期限は8時間となります。tokenの期限切れかもしれないので、再度tokenを発行して再挑戦してみてください。

          • iwai より:

            ご返信ありがとうございます。助言いただいた内容で試してみたところ、残念ながらエラーを解消することができず、同じエラーが出てしまいました。

          • sabopy より:

            SyntaxError: invalid character in identifierでFile “”, line 1と出ているので、
            ダブルクォーテーションをシングルクォーテーションにすれば良いのかもしれません。tokenファイルの「”」を「’」にしてみてください。