My Heart Beats for U:心拍数をGrafanaで可視化する

My Heart Beats for U:心拍数をGrafanaで可視化する

Appleヘルスケアの心拍数を定期的にサーバーへ同期し、Grafanaで可視化して直感的に確認できるようにしました。Health Auto ExportのREST API機能でHTTPエンドポイントへデータを送り、InfluxDBに保存します。Grafanaのダッシュボードから、自分の心拍数の変化を追ったり分析したりできます。

ちょっとしたものを作りました。Appleヘルスケアの心拍数を定期的にサーバーへ同期して、Grafanaでグラフにします。こんな感じです。

ブログ右上の♥️から見られます。Cloudflare Tunnel経由なので中国国内からは遅く、できれば検閲回避用プロキシ🪜を使ってください。現在は公開を終了しています。OPPOのスマートフォンへ替えたため、心拍数を同期・アップロードできなくなりました。

仕組みは、Health Auto Export - JSON+CSVのREST API機能で心拍数を定期的に自前のHTTPエンドポイントへ送り、InfluxDBに書き込むというものです。GrafanaをInfluxDBにつないでダッシュボードを描画します。

Health Auto Export - JSON+CSVで定期同期するにはPremiumが必要です。米国ストアのLifetimeは24.99 USDと少し高めですが、安い代替手段は見当たりませんでした。

購入したらAutomationを新規作成します。

  • Automation TypeはREST API
  • URLはこのあとデプロイするサービスのアドレスで、APIパスは/push/heart_rateです。
  • Data TypeはHealth Metrics
  • Select Health MetricsでHeart Rateにチェック。
  • Export FormatはJSON。
  • Sync Cadenceは1分でも5分でもかまいません。Apple Watchは常時心拍数を測定しているわけではありません。

Enableにチェックを入れればOKです。アプリを終了しても同期が続くよう、ホーム画面にウィジェットを置いておくとよいです。

次はREST APIを公開するサービスをデプロイし、受け取ったデータをInfluxDBに書き込みます。InfluxDBの導入方法は検索してください。ここでは省略しますが、このサービスはInfluxDB 2を使う点に注意してください。

ソースはreekystive/healthkit-collectorにあります。Nodeのプロジェクトで、pnpmから直接起動すると3000番ポートで待ち受けます。私はDockerfileを書いてDockerイメージにまとめ、自宅サーバーへデプロイしました。

起動時には、InfluxDB接続用の環境変数を4つ設定します。

text
INFLUXDB_TOKEN='your_influxdb_token'
INFLUXDB_URL='your_influxdb_url'
INFLUXDB_ORG='your_influxdb_org'
INFLUXDB_BUCKET='your_influxdb_bucket'

デプロイ後に同期を試すと、DBへの書き込みに成功したログが出ます。

最後にGrafanaを立て、Data Sourceを追加してダッシュボードを作ります。クエリは次のとおりです。

text
from(bucket: "bpm")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "heart_rate")
  |> filter(fn: (r) => r["_field"] == "avg" or r["_field"] == "max" or r["_field"] == "min")

Enjoy!

上海と杭州の自宅ネットワークをつなぐ
構文解析で型名と変数名の曖昧さを解消する