Raspberry Pi Zero WでFitbitからリアルタイムにデータを取る

これは[IoTLT Advent Calendar 2017（その1）](https://qiita.com/advent-calendar/2017/iotlt)の21日目の記事です。

----
Fitbitネタを書きたいなぁと思っていましたが、Fitbit Advent Calendarがなかったので、ラズパイを絡めてIoT感を出してみます。
\# [Ionic Advent Calendar](https://qiita.com/advent-calendar/2017/ionic)というのがありますが、Fitbit Ionicとはまるで別物の話でした。

# Fitbit
言わずと知れた活動量計で、WebAPIからある程度まとまった形で歩数・カロリー・心拍数などのデータを取得することができますが、実はリアルタイムにデータをとる方法は公式には提供されていません。一方、公式のスマホアプリは、ユーザが身に着けたFitbitからリアルタイムにデータを取得できています。

今回、Fitbitから公式スマホアプリに送られるデータ（内部的にはlivedataと呼ばれる、心拍数や歩数などのデータのこと）を取得できるモジュールを作成し、それをラズパイ上で動作させてみました。細かい処理の流れは[こちら](https://qiita.com/horihiro/items/03c4bef3e71539eddaad)にまとめています（随時更新）。


# 動作の様子
下の動画のような感じ取得できます。

![fitbit-livedata.gif](https://qiita-image-store.s3.amazonaws.com/0/90361/a1ff168c-a9d8-8d0d-c3d2-db7b9faa68dd.gif)

ラズパイからBLEを通してFitbitに接続し、受信したlivedataをコンソールに出力しています。心拍数`heartRate`と歩数`steps`の変化が取れているのがわかるかと思います。

# fitbit-livedata
上の動画で使っている`fitbit-livedata`というコマンドが今回作成したnode.js製のモジュールで、[noble](https://github.com/sandeepmistry/noble)と[bleno](https://github.com/sandeepmistry/bleno)と言う BLEでは定番ライブラリを使って[こちらのシーケンス](https://qiita.com/horihiro/items/03c4bef3e71539eddaad#%E3%83%9B%E3%82%B9%E3%83%88%E3%81%A8tracker%E3%81%AE%E3%82%84%E3%82%8A%E5%8F%96%E3%82%8A)を実装しています。

https://www.npmjs.com/package/fitbit-livedata

動作確認が取れているFitbitは[Charge HR](https://www.fitbit.com/jp/chargehr)のみです。[Ionic](https://www.fitbit.com/ionic)は一時期繋がってましたが、いつの間にかつながらなくなりました。他の機種は持っていないので、試せていません。

\# 一応、自分以外でも、Charge HRとmacOS(Sierra)の組み合わせでの動作確認が[取れています](https://github.com/horihiro/node-fitbit-livedata/issues/1#issuecomment-350544205)


## インストール＆使い方
### ライブラリとして使うには
ライブラリとして使う（他のjsファイルからimport/requireして使う）場合は、

```shell-session:install-as-library
$ npm i fitbit-livedata
```
でインストールしてください。サンプルコードは[githubのREADME.md](https://github.com/horihiro/node-fitbit-livedata#usage-as-library)をご覧ください。

### コマンドとして使うには
上の動画のようにコマンドとして使う場合は、

```shell-session:install-as-command
$ npm i -g fitbit-livedata
```
でインストールするとPATHが通るのでお勧めです。使い方は[githubのREADME.md](https://github.com/horihiro/node-fitbit-livedata#usage-as-cli-tool)をご覧(ry

ライブラリとして入れた場合でも、

```shell-session:execute-as-command
node ./node_modules/fitbit-livedata/dist/bin/cli.js
```

でコマンドと同様の動作をさせることもできますが、面倒なのでお勧めしません。

## 使用上の注意
### その１
上記シーケンス自体はFitbit社が公開しているものではなく、AndroidアプリのBluetoothログとソースコードから再現したシーケンスの一部なので、Fitbit社がその気になれば（ファームウェアアップデートなど）いつでも動かなくなりますのでご注意ください。

\# 実際、[Fitbit Ionic](https://www.fitbit.com/ionic)は一時期動いていたのですが、今はシーケンスが変わってしまったのか、繋がらなくなりました:innocent:

### その２
このモジュールを使ってFitbitと接続した後、公式スマホアプリからの強制ログアウトが頻発します。
アカウントをBANされたわけではないので、慌てず再ログインしてください。

# Raspberry PI Zero Wで動かす
一通り宣伝が終わったので、やっとIoT感だします。と言っても上のモジュールをラズパイ上で動かすだけです。
## ラズパイの準備
### 無線LAN＆ssh
Raspberry PI Zero Wは無線LANとBluetoothが最初から載っていてお得です。無線とsshd設定は@masciiさんの[記事](https://qiita.com/mascii/items/0d1a280ac58ed8f6f999)を参考にしました。

### node.js
当然、node.jsが必要なのでv9.3.0を入れました。私はnodebrewから。

```shell-session:install-nodebrew
$ curl -L git.io/nodebrew | perl - setup
$ echo export PATH=\$HOME/.nodebrew/current/bin:\$PATH >> ~/.bashrc
$ source ~/.bashrc
$ nodebrew install-binary v9.3.0
$ nodebrew use v9.3.0
```

### Javaランタイム
あとAndroidのjavaの一部をjavascriptに移植しきれておらず、苦肉の策でjarを同梱して実行いるので、javaも必要です。aptから入れればいいと思います。

```shell-session:install-java
$ sudo apt-get install openjdk-8-jre-headless -y
```

### Bluetooth用パッケージ
[noble](https://github.com/sandeepmistry/noble)と[bleno](https://github.com/sandeepmistry/bleno)を使ってBluetoothにアクセスするので、[ここ](https://github.com/sandeepmistry/noble#ubuntudebianraspbian)に従って下記コマンドで必要なパッケージを入れます。

```shell-session:install-packages
$ sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
```

ついでにsudoなしでbluetoothデバイスにアクセスできるよう、下記コマンドも実行しておきます。

```shell-session:change-permission
$ sudo setcap cap_net_raw+eip $(eval readlink -f `which node`)
```
参考：https://github.com/sandeepmistry/noble#running-on-linux

最後に`fitbit-livedata`を入れます。

```shell-session:install-fitbit-livedata
$ npm i -g fitbit-livedata
```

## 実行
最初の動画はラズパイのシェルから下記コマンドを実行し、Fitbit Charge HRのlivedataを取得している様子で、この時は、Fitbitアカウントとパスワードはそれぞれ`FITBIT_USERNAME`と`FITBIT_PASSWORD`という環境変数に予め設定しておきました。

```shell-session:execute-as-cli
$ fitbit-livedata -u ${FITBIT_USERNAME} -p ${FITBIT_PASSWORD}
```

で、これをどう使ってどういうものを作るのかは、まだまだ[思案中](https://speakerdeck.com/horihiro/fitbithatukusitajie-guo-can-nian-ninatutahua)です。
アイデアください。

* * *
以下、余談

上の動画はCharge HRからのlivedata取得の様子なんですが、本当はIonicから取得した動画にするつもりでした。しかし、上記の通り、以前は接続できていたIonic、この記事を書き始めて確認しようと動作させてみたら、livedataが取れなくなっていました。

しかもそれをTwitterでつぶやいたら、うっかり公式アカウントの目に留まってしまいリプライが。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ご連絡ありがとうございます！一度、Ionicの再起動：<a href="https://t.co/ekcM1AVt8s">https://t.co/ekcM1AVt8s</a> により、不具合が改善されるかどうかのお試しをお願いいたします。もし、再起動をお試し頂いても不具合が改善されない場合には、再度お知らせください。どうぞよろしくお願いします！</p>&mdash; Fitbit Japan (@fitbit_jp) <a href="https://twitter.com/fitbit_jp/status/942561666104942592?ref_src=twsrc%5Etfw">2017年12月18日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

公式アカウント様、Fitbit自体の不具合じゃないんです。大変お騒がせしました:bow:
何度かIonicのファームウェアアップデートが降ってきて更新をしているので、接続手順が変わったのかもしれません。年が明けて時間ができたら解析しようと思います。