あなたやわたしやあの子のドキドキと気持ち - BLE心拍センサの可視化、配信

# TL;DR

- 市販心拍センサーは、BLE GATT標準プロファイルで、毎分心拍数や、「気持ち」が反映される心拍のゆらぎまで取れる
    - 今回はPolar H7を使用
- Node-REDのカスタムノードで簡単にそれらを扱える(npm: [node-red-contrib-ble-heart-rate](https://www.npmjs.com/package/node-red-contrib-ble-heart-rate))
- 他の機能、ノードと組み合わせて可視化したり、配信したり色々したら楽しかった
- 今回はnode.jsスクリプトからのカスタムノードを作ったが、流れを掴めば想像より簡単だった

# はじめに

<blockquote class="twitter-tweet" data-lang="en"><p lang="in" dir="ltr">Maia Hirasawa - Boom!(2011) <a href="https://t.co/5B43NaoPK1">https://t.co/5B43NaoPK1</a></p>&mdash; Tomo Masuda (@tomo_makes) <a href="https://twitter.com/tomo_makes/status/942018594837225472?ref_src=twsrc%5Etfw">December 16, 2017</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

Boom, Boom, Boom, b-b-boom...My heart beats! 懐かしいなと思ったら再生しながらどうぞ。

トレッドミルの耳たぶクリップセンサや、スマートウォッチでワークアウト時に負荷を測る、など身の回りで自分の鼓動を使う例も多くなってきました。

しかし、それらは主に、予め用途別に用意され、閉じられたアプリケーションの中で使います。 MOTTAINAI.

主なBLE(Bluetooth Low Energy)心拍センサは、標準のプロファイルから主要なデータを読み取ることができ、自分で活用できます。

例えば、

- ゲームやスポーツ配信に自分の心拍をのせるもよし
- ためて自分の感情や眠りの様子を分析するもよし
- 毎分心拍数だけでなく、機種により感情(自律神経の状態)が反映された心拍のゆらぎがとれることも

ということでNode-RED Advent Calendar 2017 12/16のテーマはハートビート、Node-REDを使って心拍からのぞく、あなたやわたしやあの子のドキドキと気持ちです。

# とりあえず試す: 自分のドキドキと気持ちのうつろいを眺める
## 必要なもの

- BLE心拍センサー
- Node-RED導入済み、かつ[noble](https://github.com/sandeepmistry/noble)を使いBLE接続できるPC等

## ステップ

1. 心拍センサーを準備
1. ble heartrateノードを導入
1. 簡単なフローで動作確認
1. リアルタイムでグラフ化
1. その他のアイデア
    2. 配信
    3. キューイング

## 心拍センサーを準備

今回はPolar H7心拍センサーを使います。
胸囲にバンドを巻き、心臓近くの皮膚に密着した電極から心電を取り、それを分析した毎分心拍数、心拍のゆらぎを1秒ごとにBLEとして飛ばしてくれます。

<img width="818" alt="polarH7.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/64608/37cdb420-3b2b-efb8-ccd1-e5e93b453594.jpeg">


ほかにも下記を買う、とか友達に借りるなりすると動く(はず)。

- Polar H10が最新の模様。手元になく検証できていません。人ばしr.. 持っている方試して、教えてください>　[Polar H10心拍センサー | Polar Japan](https://www.polar.com/ja/products/accessories/h10)

- EPSON Pulsense(心拍数のみ)> [PULSENSE | 製品情報 | エプソン](https://www.epson.jp/products/pulsense/)
- その他廉価版センサも、心拍数までは取れると思われます


## ble heartrateノードを導入

一般にBLEセンサーデバイスからデータには、Services/Characteristicsといった「番地」が定められています。ベンダ独自のものと、用途に応じてベンダ共通で定められているものがあります。今回はベンダ共通のものを使います。

> 参考 心拍についてのベンダ共通のとりきめ  
> BLE GATT profile: [heart rate service](https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.heart_rate.xml)
> BLE GATT profile: [heart rate measurement](https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml)

Node-REDを動かしているPC等の近くに、BLE GATTプロファイル準拠した心拍センサがいたら、上の仕様に従い、データを取り出してNode-REDで使えるようにしてくれるカスタムノードを作り、今回公開しました。(それなりの試行錯誤があったので、需要があればまたの機会にまとめます。)

そのノードを、npmからインストールします。

```
$ cd .node-red
$ npm i node-red-contrib-ble-heart-rate
```

ノードの中身、詳細が気になる方は、こちらを参照ください。使うだけなら飛ばして大丈夫です。

> npm: [node-red-contrib-ble-heart-rate](https://www.npmjs.com/package/node-red-contrib-ble-heart-rate)  
> github: [tomo-makes/node-red-contrib-ble-heart-rate: A contributed Node-RED node, that retrieve data from BLE heartrate monitors.](https://github.com/tomo-makes/node-red-contrib-ble-heart-rate)


## 簡単なフローで動作確認

Node-REDを立ち上げ、左のパレットに `ble heartrate` というノードが取り込まれていることを確認します。
まず、下記のようにdebugへ直接流すシンプルなフローを組み、デプロイします。

<img width="597" alt="20171216_advent_simple_debug.png" src="https://qiita-image-store.s3.amazonaws.com/0/64608/98114418-37c2-7064-b2a6-913b51bbafff.png">


`ble-heartrate` ノードは下記インジケータを持ちます。

|ステータス|説明|
|---|---|
|scanning|近くのBLEデバイスを探す|
|discovered|近くにBLEデバイスが見つかった|
|connected|BLEデバイスに接続した|
|disconnected|BLEデバイスから切断した|
|waiting|次のscanまで10秒待つ|

装着した心拍モニタをonにしてしばらくすると `scanning` -> `discovered` -> `connected` とstatusが変わり、debugが出力されはじめます。
( `ble-heart-rate v0.2.0` では、debug、consoleどちらも確認できます)
遷移しない場合、Node-REDの稼働するPC等のBluetooth機能off/onを試してください。

### 余談: 案外ばらついている心拍、ゆらぎとは

- console.log例

```
Flag: 22  HBR:73  RRI1:870  RRI2:NaN
Flag: 22  HBR:72  RRI1:878  RRI2:NaN
Flag: 22  HBR:72  RRI1:895  RRI2:824
Flag: 22  HBR:72  RRI1:878  RRI2:NaN
Flag: 22  HBR:72  RRI1:882  RRI2:NaN
```

- HBR:毎分心拍数[回/分]
- RRI1: 心拍と心拍の間隔[ms]

が毎秒出力されます。心拍と、取得タイミングにより、RRIが２データ(RRI1, RRI2)出力されることがあります。
HBRではさほど変動がないように見えますが、RRIでは変化が見えます。これが心拍のゆらぎです。


## リアルタイムでグラフ化

数値だけではピンとこないので、ダッシュボードを導入します。

> [node-red/node-red-dashboard: A dashboard UI for Node-RED](https://github.com/node-red/node-red-dashboard)

```
$ cd .node-red
$ npm i node-red-dashboard
```

ダッシュボード用のノードが追加されていることを確認し、例えばこのように配置します。

<img width="1440" alt="20171216_advent_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/64608/9efe9ce0-9545-1688-3746-f4b2e5d4e321.png">

ダッシュボード(ゲージや、ラインチャート)は、 `msg.payload` に入った数値をそのまま表示するため、 `ble heartrate` と `chart` ノードなどの間に、payloadから特定の値のみを取り出す `function` ノードをはさみました。

- 例 HBRを取り出す

```js
var newmsg = { "payload": msg.payload.hbr };
return newmsg;
```

見栄えの調整などをすると、このように、リアルタイムでドキドキを表示できました。

<img width="1436" alt="20171216_advent_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/64608/6e075717-7169-a1bd-8dd4-41300d3f1367.png">


上が毎分心拍(ゲージ、ラインチャート)、下が心拍変動=ゆらぎ(ラインチャート)です。上に比べ、下が高精細なデータが取れているのがわかります。

運動したら心拍数が上がる、下がる、は当たり前として、面白いのは:

- 冷たいビールとかを飲むと、心拍一瞬(数秒のオーダで)早くなる
- 横になると、心拍がすっと下がる
- 呼吸に応じた上下が観察される

など、思った以上に自分の心臓が生きている!(当たり前)=環境に対して変動している、ということです。

先に述べた通り、心拍のゆらぎは自律神経の活動を反映しているとされ、周波数解析などを行うと、緊張、リラックスの状態などを推定することもできます。


## その他のアイデア
### 配信する

WebSocketノードを追加すると、離れたクライアントに心拍ストリームを送ることができます。
何の意味があるのでしょうか。

- 遠距離カップルがLINE常時通話に加えて心拍を共有したり
- ゲーム配信に心拍がのったり

UIはボタンからタッチスクリーン、声へ変わりましたし、写真、ビデオを超えて自分のバイタルまでコンテンツ化するのですね。きっと。
言うだけならタダです。

下のようにやります。今回は、WebSocketクライアント側はNode-RED上での簡易確認までです。

- 配信側

<img width="1440" alt="20171216_advent_3.png" src="https://qiita-image-store.s3.amazonaws.com/0/64608/8ca9fb8f-30bd-7b30-fac2-1e4f5a1566ee.png">

- 受信側

<img width="1436" alt="20171216_advent_4.png" src="https://qiita-image-store.s3.amazonaws.com/0/64608/53a09fec-e800-a47f-319f-92b1d4e5d344.png">


### メッセージキューの導入

信頼性ある心拍配信をしたい場合(あるのか?)メッセージキューを入れることもできるでしょう。

> [node-red-contrib-msg-queue](https://www.npmjs.com/package/node-red-contrib-msg-queue)

```
$ npm i node-red-contrib-msg-queue
```



# おまけ: カスタムノードの作り方

ここからは、今回contribノード `ble-heartrate` を作成するにあたって考えたこと、ログです。
カスタムノード作成から公開までの流れは、こちらの記事に非常に詳しくまとまっています。
> [Node-REDのノードをつくる手順 - Qiita](https://qiita.com/zuhito/items/1c65fdbb3743d9f87edd)

## 今回とった流れ

以前にスタンドアロンのnode.jsスクリプトとして、BLE心拍センサからデータを取得し、ごにょごにょするのを書いていました。
今回はその

- 「あんこ(=元スクリプト)」を

カスタムノード化するため

- 「もち(=Node-REDカスタムノードのお作法)」でつつみ
- 「大福もち(=完成したカスタムノード)」を作り
- 「お店に陳列(=githubおよびnpm公開)」

したという感じです。


## もち(=Node-REDカスタムノードのお作法)

- 三点セット: node-red-contrib-{name}.js, node-red-contrib-{name}.html, package.json
- js
    - 自前node.jsスクリプトを包む
        - `module.exports = function(RED) {}`
            - `function xxx(config) {}`
                - `RED.nodes.createNode(this,config);`
                - `var node = this;`
                - (もともとのnode.jsスクリプト)
            - `RED.nodes.registerType("xxx",xxx);`
- html
    - 見た目と、プロパティ変数などの定義
    - 設定画面用のhtml
    - 説明文
- package.json
    - npm initで生成
- その他
    - 設定画面で入れた値をjs側でどう参照するか: [Node-RED日本ユーザ会 : プロパティ](https://nodered.jp/docs/creating-nodes/properties)


## まとめ

- 市販心拍センサーPolar H7で、毎分心拍数や、「気持ち」が反映される心拍のゆらぎまで取れた
- カスタムノード化により、他の機能、ノードと組み合わせ(可視化、配信など)を簡単に行えた
- カスタムノード作成も、流れを掴めば想像より簡単