Tabe/gのデータ解析部分に関して

# 説明内容
* [Maker Faire Tokyo 2017](http://makezine.jp/event/mft2017/)の中で出展した「[Tabe/g](http://www.tabegram.com/)」で利用したものの説明
* ここに記載するのは、データをクラウドに吸い上げて可視化するまでのところになります

# システム概要
* データの流れは下記の通りで、今回は太字のところを試す

RaspberryPi3 -> Soracom Air -> Soracom Beam -> AWS IoT -> **Amazon Elasticsearch Service -> kibana**

* それ以外のところは、[Raspberry Pi3×SORACOM×AWS IoT×myThingsで勤怠連絡ボタンを作ってみる](http://qiita.com/yumatsud/items/3b766b2997b411633ff5)の部分を引用する

# やった見たこと
* Amazon Elasticsearch Serviceの立ち上げ
* AWS IoTの作成
* SORACOM Beamの設定

## Amazon Elasticsearch Service
立ち上がりが遅いらしいので、Elasticsearchを先に立ち上げておきます

1.ドメインの定義：ドメイン名を「tabegram-sensor」にし、バージョンが5.3を指定
<img width="1389" alt="スクリーンショット 2017-08-01 0.39.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/1d4be253-0852-ea2d-ccaf-c6f95283f692.png">


2.クラスタの設定：インスタンス数1、インスタンスタイプt2.small.erasticsearchを指定(お試しなので、専用マスター、ゾーン対応は無効のままにしておきます)し、その他の設定はデフォルトのものを指定
<img width="1376" alt="スクリーンショット 2017-08-01 0.45.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/b2127f8b-9fbf-cf15-3262-62168b1baa76.png">

<img width="1372" alt="スクリーンショット 2017-08-01 0.46.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/545a8e80-e8b7-8ad7-8808-0ebfc81562c4.png">


3.アクセスの設定:テンプレートで「1つ以上のAWSアカウントまたはIAMユーザを許可」を選択し、自分のアカウント入れておく
<img width="1379" alt="スクリーンショット 2017-08-01 0.51.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/9a6b913b-bd2a-8b9f-e47d-6d8f4f2fc3c9.png">

<img width="1384" alt="スクリーンショット 2017-08-01 0.51.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/94ab6a20-0048-66d9-c00c-c4c695ce3c98.png">


4.確認：再度設定内容を確認して問題ないければ確認ボタンを押す
5.作成されると下記のような画面になり、設定が完了するとドメインのステータスがアクティブになるので、それまでは待ち
<img width="1398" alt="スクリーンショット 2017-08-01 0.55.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/e7f6a998-761b-f70d-b441-5f260d67bacc.png">


## AWS IoT
基本的には「[Raspberry Pi3×SORACOM×AWS IoT×myThingsで勤怠連絡ボタンを作ってみる](http://qiita.com/yumatsud/items/3b766b2997b411633ff5)」の証明書にアタッチまでは同様。

1.ルールを作成時に、アクションでElasticsearch Serviceを選択
<img width="1288" alt="スクリーンショット 2017-08-01 1.23.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/c0be7bc7-ff93-26b6-cb69-7e2eeba8be21.png">


2.必要項目を入れる(IAMも必要であれば適当に作成)
<img width="1268" alt="スクリーンショット 2017-08-01 1.24.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/15f37ae6-ab9c-978c-022e-49e6218b3b44.png">


3.下記のようにアクションを設定できたらルールを作成ボタンを押す
<img width="1298" alt="スクリーンショット 2017-08-01 1.28.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/028aa39f-0104-1b03-fdef-3135bdec6138.png">

## 疎通確認
* mosquitto_pub(PC)から下記のコマンド確認

```
$ mosquitto_pub --cafile rootCA.pem \
  --cert xxxxxxxxxx-certificate.pem.crt \
  --key xxxxxxxxxx-private.pem.key \
  -h xxxxxx.iot.us-west-2.amazonaws.com \
  -p 8883 -d -t topic/tabegram \
  -m '{"timestamp":"2017-08-01T15:20:53.420Z","temperature":20}'
Client mosqpub/821-YukinoMacBo sending CONNECT
Client mosqpub/821-YukinoMacBo received CONNACK
Client mosqpub/821-YukinoMacBo sending PUBLISH (d0, q0, r0, m1, 'topic/tabegram', ... (57 bytes))
Client mosqpub/821-YukinoMacBo sending DISCONNECT
```

* Node.jsで確認

```meature.js
'use strict'

var awsIot = require( 'aws-iot-device-sdk');
var device = awsIot.device({
    keyPath: 'xxxxxxxxxx-private.pem.key',
    certPath: 'xxxxxxxxxx-certificate.pem.crt',
    caPath: 'rootCA.pem',
    clientId: 'tabegram',
    host: 'xxxxxxxxxx.iot.us-west-2.amazonaws.com'
});

var getRandomData = function(value){
    return Math.floor(value + Math.random()*value/10 - value/10/2);
}

var sendSensorData = function(){
    var data = JSON.stringify({
        timestamp: new Date(),
        temperature: getRandomData(20),
    }); 
    console.log(data);
    device.publish('topic/tabegram', data);
}

console.log('before connect');
device.on('connect', function(){
    console.log('connect');
    setInterval(function(){
        sendSensorData();
    }, 1000);
});
```
下記は実行結果

```
$ npm init
$ npm install --save aws-iot-device-sdk
$ node weight.js 
before connect
connect
{"timestamp":"2017-08-01T14:55:15.827Z","temperature":19}
・・・・・
```

## Kibana
* Elastictsearch ServiceからKibanaのリンクをクリック
<img width="1398" alt="スクリーンショット 2017-08-02 0.25.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/b09846f6-696e-fe13-042d-9bb1e48889a4.png">

* 最初は下記の画面になるので、「Index name or pattern」「Time-field name※」に**timestamp**を指定し、Createボタンをクリック
<img width="1430" alt="スクリーンショット 2017-08-01 23.22.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/cd393907-2cca-485e-67d7-372374d98eb1.png">
※上記で試しにデータをストアしていないと「Time-field name」にtimestampの選択肢がでない

* Discoverタブを開いて下記のようになって入ればデータが取れている
<img width="1433" alt="スクリーンショット 2017-08-02 0.31.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/e40a1432-3646-4197-efeb-7ee300a2fe9c.png">

* Visualizeタブでグラフを作成
<img width="1431" alt="スクリーンショット 2017-08-02 0.41.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/dd9b0cff-669d-2a4f-a35a-0085b0ed9629.png">

* DashBoardタブで必要なグラフを置いておけば表示しておきたいデータを可視化できます
<img width="1434" alt="スクリーンショット 2017-08-02 0.45.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/664798b2-1dae-8416-8fd2-2563bd88c1be.png">


## SORACOM Beam
* 「[Raspberry Pi3×SORACOM×AWS IoT×myThingsで勤怠連絡ボタンを作ってみる](http://qiita.com/yumatsud/items/3b766b2997b411633ff5)」の同様にMQTTを設定する
* mosquitto_pub(ラズパイ)から下記のコマンド確認

```
$ mosquitto_pub -d -h beam.soracom.io -t topic/tabegram \
  -m '{"timestamp":"2017-08-01T15:19:53.420Z","temperature":20}' -p 1883
Client mosqpub/1426-darmaso-ra sending CONNECT
Client mosqpub/1426-darmaso-ra received CONNACK
Client mosqpub/1426-darmaso-ra sending PUBLISH (d0, q0, r0, m1, 'topic/tabegram', ... (57 bytes))
Client mosqpub/1426-darmaso-ra sending DISCONNECT
```

# 他部分と接続
全体絵としては下記
![OgTHH5993daf6cc64f7027a36127f.jpg](https://qiita-image-store.s3.amazonaws.com/0/71637/5aa614d3-1680-d3be-0edd-09bbf69a229a.jpeg)

①計測器(Arduino) -> ②通信&ハブ(RaspberryPi) -> ③鏡(Arduino)

1.計測器からは、000〜999のシリアルデータを受け取る
2.受け取ったデータをキャストして、timestamp付きでSORACOM BeamへMQTTで流す(pythonコードは下記)

```tabegram.py
import serial
import time
import json
import paho.mqtt.client as mqtt
from datetime import datetime
from pytz import timezone

def on_connect(client, userdata, rc):
  print("Connected with result code " + str(rc))

def on_disconnect(client, userdata, rc):
  if rc != 0:
    print("Unexpected disconnection.")

def on_publish(client, userdata, mid):
  print("publish: {0}".format(mid))

def main():
  con = serial.Serial('/dev/ttyACM0', 9600)
  print con.portstr
  # Setting MQTT
  client = mqtt.Client()
  client.on_connect = on_connect
  client.on_disconnect = on_disconnect
  client.on_publish = on_publish
  client.connect("beam.soracom.io", 1883, 60) 

  while 1:
    str=con.read(3)
    if str != "": 
      print int(str)
      now = datetime.now()
      utc_now = datetime.now(timezone('UTC'))
      iso_now = utc_now.isoformat()
      now_s = "%s" % iso_now
      message = json.dumps({"timestamp":now_s, "weight":int(str)})
      client.publish("topic/tabegram", message)

if __name__ == '__main__':
    main()
```
3.鏡には特定のデータ範囲によって文字列をシリアルデータで送信
4.Kibanaの方には下記のようにデータが可視化される
<img width="1432" alt="スクリーンショット 2017-08-03 23.50.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/71637/0dfb7e5c-3673-40eb-39f7-2c821fbfb0a3.png">

# 感想
* AWS IoTからElasticksearchへ直結できるのはありがたい
* あとはKibanaをどこまでカスマイズできるか、例えば単純なブラウズ自動更新機能とかが入っていないのは残念
    * リアルタイムはある程度担保できたので、あとは見せ方のみ
* とはいえあサーバレスでここまでできるのはとても楽チンでよかったですmm

# 参考
* [MTF 抽象的電子工作](http://makezine.jp/event/makers2017/m0213/)
* AWS関連
    * [AWS IoT が Elasticsearch Service と CloudWatch に連携できるようになりました](https://aws.amazon.com/jp/blogs/news/aws-iot-update/)
    * [Amazon Kinesis](https://aws.amazon.com/jp/kinesis/)
    * [Amazon Kinesis Firehose](https://aws.amazon.com/jp/kinesis/firehose/)
* SORACOM関連
    * [Raspberry Pi と SORACOM Harvest を使用してデバイスのデータをクラウドで収集・可視化する](https://dev.soracom.io/jp/start/harvest_raspberrypi/)
    * [Raspberry Pi3×SORACOM×AWS IoT×myThingsで勤怠連絡ボタンを作ってみる](http://qiita.com/yumatsud/items/3b766b2997b411633ff5)
* [github.com/tabegram](https://github.com/tabegram)
* Qiita記事
    * [「AWS IoTのデータをKibanaに表示する」をやってみた。2017/3版](http://qiita.com/moritalous/items/8907685d57ec8d3b5dbb#_reference-178fcc5fce7763d4ba0d)