BLE端末からデータを抽出してSORACOMFunnelでS3へ

どうもくろにゃんこたんです！
クリスマスも近いので、Qiitaに遊びに来てみましたよ(・ω・)ノ

# 要約
この記事ではBluetooth LE（Low Energy）のセンサーを利用して、歩数計の値を取得。SORACOMFunnelへ常時飛ばすものです。
SensorTAGなどを利用出来ればBLEも難しくは無いのかもしれませんが、それではつまらないので、
今回はWishで売っていた格安スマートリストバンドをターゲットとします。

##　まえがき
Qiitaにお邪魔したのは初めてなので軽く自己紹介。
もともと学生時代からPCサポートやチラシ制作などに携わっていた結果、バイトと会社員のようなダブルワークで過ごし、その後３つの会社にお世話になり、現在個人事業主5年目として、フリーランスでDTPデザインからWeb、販促グッズデザイン、プロモーションVFX制作、Webコーディング、システム開発（主にPHP）、AWSのサーバ設計などのアドバイス、と自分でみてもかなり幅広めでやっております。
ただもともと上位レイヤーでの仕事が多いので、マイコン系の低いレイヤーでの工作はあまり知りません。
そ・し・てPythonもほとんど触ったことがありません。
（ハードル高すぎ）

今のスキルクラウドはこちら。（やってみたかった）

![wordle.png](https://qiita-image-store.s3.amazonaws.com/0/218533/3ee4b89d-38fc-822a-7df6-280e6528f7d7.png)
*created by wordle.net*


そして2児（２歳と０歳）の娘の父なので、この記事のセンサー調査も０歳を抱っこしながら書いてます。


が
今回の題材は「BLE」＋「SORACOM」
とってもピッタリな題材なので、選んだテーマだったのですが、
これがなかなかの茨の道への始まりとは・・・

# いつでもすぐ会える距離にいるのになかなか会えない
イメージしてみてください。。


離島、もしくは陸の孤島で一人で暮らしている母親。
快活な母はなんでも一人でこなし全く心配をかけないように暮らしています。
もちろん子供たちに会えるなら嬉しいけど、毎日はねぇ。。。

そんな母ももう70過ぎ。いくら一人でなんでも出来るからといっても、
持病もあり定期的に遠い病院へ通うのは大変。
3日に一回の診療がだんだんと億劫になっていき、1週間に一回、2週間に一回と病院も遠のいてしまいます。
お医者さんは往診しますから。と暖かい提案をして頂いているのですが、
まだまだそんなに年寄りじゃないよ。と強気な母。
郵送してもらった孫の写真を見たりすることはあったり、LINEも少し使えるようになった母。
でも自分からそれ以上のことはスマートフォンを手にとってみてもわからないことばかり。

そんななか、娘からちょっと大きめの箱と、ブレスレット型の時計。
「誕生日プレゼントだよ！」と久しぶりにメッセージカードまで。
その時から母はこのブレスレット型の時計を気に入って一日中つけて買い物へ出かけたり。
あの箱は「コンセントに挿しておいてね」としか書いていなくて、一体何の機械なんやら・・・

そしてある時母は風を引いて寝込んでしまいました。
重い風邪で次の日になっても布団から出られません。
ただの風邪くらいで電話しちゃあまずいよね。。。迷惑だろうし。と思って電話もかけませんでした。
3日目も寝込んでしまい流石にしんどいなぁと思っていた矢先。

「こんにちは！◯◯医院の医師です。往診に来ましたー」
約束も無いし、往診は遠いから断っていたはずの医師。その突然の訪問に母はびっくり。

3日間位今までの歩数からぐっと下がったので、何かあったのかなと思って訪ねてきました！
風邪を引かれていたのですね。今年の冬はぐっと寒くなりましたものね。
診察させていただけて良かったです。これでこのお薬と栄養を採ってもう少し休んでいてくださいね。
その間にこのブレスレットも充電しておきましたので、またつけていてくださいね。
薬を飲んで2日も休めばもうスッキリ。快活な母が復活です。

でもどうして風邪で寝込んでるってわかったのかしら・・・
その時医師が行った言葉
「その間にこのブレスレットも充電しておきましたので、またつけていてくださいね。」
を思い出して母はハッとしました。この時計が万歩計になるのは知ってたけどまさか、これで寝込んでるってわかったのかしら。

遠くにいても娘が心配して送ってくれたこのブレスレット。
娘が直ぐ側にいてくれるような気がして、このブレスレットがもっと大事な存在になりました。

イメージここまで

# イメージの解説
読んでいただいた方ありがとうございます。
当然お分かりのことかと思いますが、
ブレスレット→BLE端末
大き目の箱→Raspberry3とSORACOMSIMが入ったドングルが刺さっています。
後はタイトルにもある通りのことが起こって、3日間も少ししか歩数が無い母親が病気かもしれないと思って、病院に相談したということですね。
見守りセンサーなどという仰々しい名前だと引いてしまいますが、オシャレなブレスレット程度であれば良いのかな？

# BLE端末を選ぶ
ここで現実に戻ります。
BLEにも色々ありまして、（そもそもBluetoothの規格をこねくり回して出来た規格がBLE）ですので、なかなか大変です。
BLEは通常のBluetooth端末としてペアリングし続けて使うマウスやキーボード、スピーカーなどとは違い、基本的に誰でもMACアドレスと中の構造を知れば、BLEの中のデータを取得できる可能性が有り得ます。

そして今回（安易に）選んだのがこちら！
![DSC04630.JPG](https://qiita-image-store.s3.amazonaws.com/0/218533/3438bd3d-a440-96ab-a22d-3b4154bcbadc.jpeg)





キレイでしょ！
Wishで安く買えました（1,500円）

通常仕様はスマートフォンアプリと接続を行って歩数やデータ入力（身長、体重など）のデータにもとづいて、ヘルスメーターの様な表示を行ってくれます。基本的にはスマートフォンとの連携が前提としたものなので、他には時計表示、歩数表示、消費カロリーなどが画面で表示されるだけのものです。もちろん生活防水（結構大事です）。

Daydayband(Google play)
https://play.google.com/store/apps/details?id=com.yc.pedometer


# 解析開始
はい。ココからかなり泥臭くなっていきます。。
当然の事ながらBLEの仕様なんて閲覧できないので、ひたすら対象にConnectしてインタラクティブでデータを眺め続けることになります。
GATT系のデバッグアプリなんてものも試してみたのですが、サービス名の表示止まりで、目的の歩数まではたどり着かなかったです。。。

## bluezのインストール
ということでラズパイの環境を整えます。

◯Raspberry PI(Raspbian)でbluezインストール、SensorTagに接続してみる
https://qiita.com/u_one/items/9b6f6bd37c0e221bfa16

こちらに掲載されている情報で

```
sudo hcitool lescan
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/218533/aa76c7b3-03d1-0039-8710-7d0d8525a320.png)


``` 78:02:B7:23:BE:2C M52A ```
というものが見つかりましたね！

## GATTTOOLで解析

このアドレスを使ってGATTTOOLを起動します。
（この名前のTがいくつあるかわからない感じ。製作者の苦しみが伝わってきます(・ω・；)　）

``` gatttool -b 78:02:B7:23:BE:2C -I
```
これよりgattのインタラクティブモードに移ります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/218533/e199422e-57db-b609-75ad-17c33333e244.png)


このように「primary」コマンドでuuidの一覧とハンドルのスタート・エンドが見られます。
基本的にはこのなかの何処かに歩数が隠されているはずです！


## 20時間後・・・(ヽ´ω`)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/218533/fc77374c-d141-f505-887a-e5b772db6109.png)

ｷﾀ━━━━(ﾟ∀ﾟ)━━━━!!
handle:0x0014 のCharacteristic valueには
 b1 07 e1 0c 0a 0b 00 38 00 00 00 38
の16進が！12個あるので3分割してみると

 b1 07 e1 0c　　　0a 0b 00 38　　　00 00 00 38

ここの右ブロックの00 00 00 38という数字ですが、

![a.jpg](https://qiita-image-store.s3.amazonaws.com/0/218533/d4a62ee1-1f23-f867-ecbc-f1ce4a25cfe2.jpeg)

Step=56
16進数なので
(16^1×3)　＋　8　= 48＋8　＝56　
画面表示とピッタリです！！

要はこの値を取得出来ればそのまま飛ばせるようになると。

ここまで到達するのに長かった・・・
だって仕様書なんて無いし。。
達成感はもう半端なくありました。まるでリアル脱出ゲーム(R) で最後の大謎を解くために、最初の方の小謎が、こう関係していたのか！！的な発見です。（わかるかな？）

なんかここで力尽きた感がありますが、それだとSORACOMネタにならないので頑張って続けます。

ここでBLEセンサーのコネクション＋データ取得＋RequestにてPOST送信を行うコードを書いていきます。

```python3

from bluepy import btle
from bluepy.btle import BTLEException
import time
import struct
import requests
import codecs
import urllib.request,json

MAC_ADDR = "78:02:B7:23:BE:2C"

#connect
tPe = btle.Peripheral(deviceAddr="78:02:B7:23:BE:2C")
tch = tPe.getCharacteristics()
buf = tch[6].read()
#buf = b'\xb1\x07\xe1\x0c\t\x10\x00A\x00\x01jj'
print (buf)
#print ("%s" % buf[0])
#print ("%s" % buf[1])
#print ("%s" % buf[2])
#print ("%s" % buf[3])
#print ("%s" % buf[4])
#print ("%s" % buf[5])
#print ("%s" % buf[6])
#print ("%s" % buf[7])
#print ("%s" % buf[8])
#print ("%s" % buf[9])
#print ("%s" % buf[10])



headers={'Content-Type':'application/json'}
datas = {'step01':buf[9],'step02':buf[10],'step03':buf[11],'mes':'hello'}
##datas = '{"message":"hello00000000000000000"}'
json_data = json.dumps(datas).encode("utf-8")
r = requests.post('http://funnel.soracom.io/',headers=headers,data=json_data)
#r = requests.post('http://jectworks.com/t/',data=datas)
print (r.text)
#print (buf.encode('utf-8'))
```

苦労が見え隠れするコードですな。。。(ヽ´ω`)
まずPython3でハマり、BLEのライブラリでハマり、Bytesデータの扱いでハマり、、、、
必要最低限のコードにしたのがこれ。

```python3
from bluepy import btle
from bluepy.btle import BTLEException
import time
import struct
import requests
import codecs
import urllib.request,json

MAC_ADDR = "78:02:B7:23:BE:2C"

#connect
tPe = btle.Peripheral(deviceAddr="78:02:B7:23:BE:2C")
tch = tPe.getCharacteristics()
buf = tch[6].read()
print (buf) #センサーデータ

#センサーデータ送信
headers={'Content-Type':'application/json'}
datas = {'step01':buf[9],'step02':buf[10],'step03':buf[11],'mes':'hello'}

json_data = json.dumps(datas).encode("utf-8")

r = requests.post('http://funnel.soracom.io/',headers=headers,data=json_data)
print (r.text)

```
例外処理を一切考えないコード。ｗ

本当は接続できるまでループで待機するのも考えたのですが、そこはラズパイの方で対応。

下記つぶやきからスクリプト実行→BLEコネクト→データ取得→データをSORACOM Funnelへ送信している様子を動画で見られます。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">激安歩数計からBLEでデータ取得が出来た！ <a href="https://t.co/iJaWPNGYZU">pic.twitter.com/iJaWPNGYZU</a></p>&mdash; くろにゃんこたん (@kuronyankotan) <a href="https://twitter.com/kuronyankotan/status/939697193908183042?ref_src=twsrc%5Etfw">2017年12月10日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

（ちなみに動画では表示画面とBLE端末がものすごく近いですが、遠隔でいじっているだけで、実際の受信ラズパイは5ｍ程後ろにあります。）
いよいよSORACOM Funnelを使ってデータを送信です。

## 受信確認
KinesisFHからのデータはS3にPUTしています。
1分間に数回送ると改行が・・・という問題も解決しています。

◯SORACOM FunnelからAmazon Kinesis Firehoseを使ってS3へ保存。してからのAthenaで集計したい！
https://kuronyankotan.com/?p=286

ここまで来たら後は自分の庭です。

## 考え方
◯基本的に正確に歩数は取れないものという前提を持って設計する。歩数が指定したタイミングで取らないと破綻するような運用にしない。
◯リアルタイム性を求めすぎるとセンサー、環境などの変更のほかコストも掛かることを考えておく。

## 一日に一回Athenaで集計。
ま、一日に一回「昨日の歩数は100歩でした」と分かるだけでも、音沙汰なしよりずっと良い。という考え方で利用。
**あくまで生存を保証しているものでは無く、生存していない前提で考える。**
（じゃないと突き詰めたら医療機器になってしまいます。）

歩数が分かるということは下記3つの安心が得られる
◯生存している。
◯家にいる
◯歩数によって健康もモニタリング出来る。

生活出来ているかの情報源のひとつとして利用が可能。


## 考察
### 何故BLEを採用したか。
無線で、機械を出来るだけ意識しない方向に持って行きたかった。
また、RFIDは無線アンテナの価格帯や顔認証カメラは回線利用量の問題があり、
全て低電力で動作出来るもので実装の必要があったから。

また、ラズパイをBLEのゲートウェイとして置いておくことが出来れば、これ一つで温湿度、Bluetooth体重計などBluetooth機器のデータ取得が一気にまとめられる可能性があります。

### なぜ格安の歩数計を使ったか
それはもう価格ですよ(´ω｀)
価格がそれなりの値段であれば、気軽にハイ・どうぞって出来ないのは明白。
今後のスケーリングにひびくので。
でも辛かった。
本当はCEATEC JAPAN 2017のときに、某センサー会社様の心拍リストバンドと、今回のラズパイを代替出来るという、SIMが入るBLEゲートウェイが登場していたのでそれを使いたかったのですが、（会場では良いですよーどんどん（買って）使ってくださいーって盛り上がったのですが・・・・）
後日購入依頼をメールでしてみたところ、
＿人人人人人人人人人人人人人人人人人人＿
＞　個人にはゲートウェイは売らないよ　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^￣
って後日連絡が来たので、やめました(ヽ´ω`)


## 展望
冒頭のストーリーのように、娘が独立して、一人ぼっちで暮らす人が生きているのか、異常はないか等
心配ない。ちゃんと一人でやって行けている。というちょっとした安心を届けられます。
安心をちょっとだけプラス出来るようなIoTというのでも良いかなぁと(´ω｀)

それでは良い日を(・ω・)ノ