LoginSignup
22

More than 5 years have passed since last update.

RaspberryPi + Athena + Quicksightで可視化する<前編>

Last updated at Posted at 2017-02-06

概要

本コンテンツは、JAWS DAYS 2017IoTハンズオン向けに作成したものです。
下記のようなデータフローを構築して、温度センサーデータをQuicksightで可視化します。
温度センサー -> RaspberryPi -> Kinesis Firehose -> S3 -> Athena -> Quicksight
本格的な分析や可視化にも耐えうる構成となっており、プロダクションへの応用も可能です。また、温度センサーの組み立てでは簡単な電子工作を体験できます。
スクリーンショット 2017-02-06 21.28.43.png

<前編>の範囲

<前編>では、温度センサー -> RaspberryPi -> Kinesis Firehose -> S3 の部分を説明します。成功すれば下記のようなJSONメッセージがS3バケットに格納されます。汎用的なJSONメッセージですので、後工程で様々に活用することが可能(ココ重要!)です。

{"time":"2017-02-04 19:14:33", "temperature":25.562}
{"time":"2017-02-04 19:14:43", "temperature":25.562}
{"time":"2017-02-04 19:14:53", "temperature":25.5}
{"time":"2017-02-04 19:15:03", "temperature":19.5}
{"time":"2017-02-04 19:15:13", "temperature":15.375}
{"time":"2017-02-04 19:15:23", "temperature":14.5}

<後編>はこちら

必要な機材

  • PC
  • RaspberryPi 2または3
  • micro USB電源
  • micro SDカード (8GB以上)
  • 温度センサーセット
    • DS18B20
    • 2.2kΩカーボン抵抗
    • ブレッドボード
    • ジャンパワイヤ オスーメス 3本

前提条件

  • AWSアカウントをもっていること。アカウント開設手順はこちら
  • RaspberryPiにRaspbianがインストール済みで、PCからSSHでログインまたはHDMI接続のモニタでターミナル操作ができること。手順はこちら。Raspbianは[Release date:2017-01-11]で動作確認しています
  • RaspberryPiがインターネットに接続できていること

<前編>で利用するAWSサービス

Amazon Kinesis Firehose

多数のノードからデータを集約する場合、古くはFTPサーバを利用しました。現在であればHTTPベースのAPIサーバといったところでしょうか。数千~数万といった多数のIoTエッジデバイスノードを集約する場合、サーバのスケールや分散処理が大きな課題となります。Kinesisファミリーはストリーミングデータの集約に特化したフルマネージドサービスで、単一のエンドポイントで大量のストリーミングデータを処理することができます。

  • データはクレデンシャルをつけてエンドポイントにHTTPSでPOSTする。CLIやSDKも利用可能
  • 受信したデータはAmazon Kinesis Analytics、Amazon S3、Amazon Redshift、および Amazon Elasticsearch Serviceのどれかに配送される
  • 配送先には設定したインターバル毎にデータが届く。最小のインターバルは60秒
  • データ転送量による課金
  • オートスケールで、1 秒あたり数ギガバイトを超える入力データレートにも対応
  • さらなるリアルタイム性(遅延数秒以内)が求められる場合は、Kinesis Streamsを使う

Amazon S3

一見ただのオブジェクトストレージ(ファイルサーバ)ですが、AWSの根幹をなすサービスと言え、非常に多くの機能をもっているので一言で説明することはできません。今回の利用用途に絞って説明します。

  • API/CLI/SDKでHTTPSによるアクセス
  • ストレージ容量とリクエスト数とデータ転送量(アウトバウンド)による課金。ストレージ容量1GBあたり3円/月程度と非常に低料金
  • バケット毎にリージョンを指定でき、リージョン内で3箇所にコピーが作成される
  • IoTにおけるユースケースとしては、データのハブとしての使い方が有効。S3にデータを集めておけばAWSのさまざまなサービスから利用可能となる。JSON形式のデータが望ましい

[ToDo 0] RaspberryPiの準備

インターネット接続確認

RaspberryPiをインターネットに接続し、PCから有線LANまたはWi-Fi経由でSSH接続します。
RaspberryPiのIPアドレスが分からない場合は、こちらを参考にGUIやifconfigコマンド等で調べてください。下記の場合、192.168.0.209がRaspberryPiのIPアドレス(Wi-Fi)であることが分かります。
Wi-Fiで接続するのにwlan0にIPアドレスが割り当てられていない場合は、こちらを参考にWi-Fiアクセスポイントへの接続設定を行って下さい。

$ ifconfig
wlan0     Link encap:Ethernet  HWaddr cc:e1:d5:4d:59:5e
          inet addr:192.168.0.209  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: 2001:268:d006:d652::2/128 Scope:Global

wgetコマンドで適当なURLを打ってみればインターネットに接続できているか確認ができます。

 $ wget https://google.co.jp

--2016-03-23 17:53:19--  https://google.co.jp/
Resolving google.co.jp (google.co.jp)... 2404:6800:4003:809::2003, 106.162.198.104, 106.162.198.123, ...
Connecting to google.co.jp (google.co.jp)|2404:6800:4003:809::2003|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://www.google.co.jp/ [following]
--2016-03-23 17:53:30--  https://www.google.co.jp/
Resolving www.google.co.jp (www.google.co.jp)... 2404:6800:4007:805::2003, 106.162.192.173, 106.162.192.167, ...
Connecting to www.google.co.jp (www.google.co.jp)|2404:6800:4007:805::2003|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘index.html’

index.html              [ <=>                  ]  18.90K  --.-KB/s   in 0.1s

2016-03-23 17:53:32 (130 KB/s) - ‘index.html’ saved [19358]

アップデートとvimのインストール

インターネット接続が確認できたら、下記を実行します。

$ sudo apt-get update
$ sudo apt-get install -y vim

[ToDo 1] APIアクセス用のKeyを作成する(AWS)

Kinesis FirehoseにAPIでアクセスするために、AWSのIAM Access Keyを作成します。
今回作成するのは下記のユーザーおよびそれにひも付くKeyです。

ユーザー名 アクセス権 使用箇所
firehose-full AmazonKinesisFirehoseFullAccess RaspberryPiからKinesisへの書き込み
  • AWSにサインインする
  • Identity and Access Management(IAM)コンソールを開く
    ※ 英語画面で説明するので日本語表示になっている場合は、画面左下の言語選択を「English」に変更する
    AWS Management Console 2017-02-05 15-21-17.png

  • 「firehose-full」という名前でProgrammatic accessユーザーを作成する
    IAM Management Console 2017-02-05 15-25-26.png

    IAM Management Console 2017-02-05 15-27-19.png

  • [Attach existing policies directly]をクリックし、[firehose]で検索して、[AmazonKinesisFirehoseFullAccess]にチェックを入れる
  • [Next: Review]をクリックする
    IAM Management Console 2017-02-05 15-36-54.png

  • [Create user]をクリックする
    IAM Management Console 2017-02-05 15-38-24.png

  • 認証情報の書かれたCSVをダウンロードし、[Close]をクリックする
    IAM Management Console 2017-02-05 15-41-43.png

[ToDo 2] Kinesis Firehoseの設定(AWS)

  • Kinesisコンソールを開く
    AWS Management Console 2017-02-05 15-13-43.png

  • Kinesis Firehoseは2017年2月現在、東京リージョンでは提供されていないので、利用可能な北バージニア(N.Virginia)リージョンを選択する
    2017年8月25日に東京リージョンで利用可能になりました!
    k-1.png

  • [Go to Firehose]をクリックする
    スクリーンショット 2016-10-19 13.42.20.png

  • [Create Delivery Stream]をクリックする
    Amazon Kinesis Firehose 2016-10-19 13-43-18.png

  • 配送先に[Amazon S3]を選択する
    スクリーンショット 2016-10-19 13.44.22.png

  • 任意のStream Nameを入力し、ログを格納するS3バケットを選択(ここではともに「iotan-f」としている)する。バケットはここで作成することもできる(S3バケットのリージョンはお好みで)
  • ログのファイル名はデフォルトでStream名+タイムスタンプとなるが、必要であればプレフィックスを指定する
  • [Next]をクリックする
    Amazon Kinesis Firehose 2016-10-19 13-46-27.png

  • Buffer interval(S3への送信間隔)を指定する。最小値は60秒。ハンズオンでは早く結果が分かるように60秒に設定する
  • IAM roleで[Firehose Delivery IAM role]を選択する
  • 他はデフォルトでOK
    スクリーンショット 2017-03-04 14.50.48.png

  • そのまま[Allow]をクリックする
    IAM Management Console 2016-10-19 13-49-20.png

  • そのまま[Next]をクリックする
    Amazon Kinesis Firehose 2016-10-19 13-50-05.png

  • [Create Delivery Stream]をクリックする
    Amazon Kinesis Firehose 2016-10-19 13-51-10.png

  • S3配送ストリームが作成された。[ACTIVE]になったら利用可能
    Amazon Kinesis Firehose 2016-10-19 14-24-14.png

[ToDo 3] AWS CLIをインストールする(RaspberryPi)

AWS CLIのインストール

pipコマンドでAWS CLIをインストールします。

$ sudo pip install awscli
(途中省略)
Successfully installed awscli botocore PyYAML docutils rsa s3transfer jmespath python-dateutil futures
Cleaning up...

AWS CLIの設定

CLIを実行する際のリージョンや認証情報を設定します。認証情報は[ToDo 1]でダウンロードしたCSVを参照します。

項目 入力内容
AWS Access Key ID (CSV参照)
AWS Secret Access Key (CSV参照)
Default region name 北バージニアリージョンの場合は「us-east-1」
東京リージョンの場合は「ap-northeast-1」
Default output format json
$ aws configure
AWS Access Key ID [None]: ************                    
AWS Secret Access Key [None]: ************
Default region name [None]: us-east-1
Default output format [None]: json

[ToDo 4] AWS CLIでKinesis Firehoseにput-recordしてみる(RaspberryPi / AWS)

テストデータのput-record

AWS CLIでKinesis Firehoseにテストデータをput-recordしてみます。--delivery-stream-nameのあとの*****には、[ToDo 2]で設定したストリーム名を入力します。
下記のような"RecordId"のレスポンスが表示されたら成功です。データがS3に書き込まれるまで、最大で[ToDo 2]で設定したBuffer intervalの秒数だけかかります。

$ aws firehose put-record --delivery-stream-name ***** --record Data=blob
{
    "RecordId": "PEMfHNCtnMGQ5+bCvkm7TgynKepLxf2awvfD5He1atikTPY3zg8Eo2o3LnGhEqYzlVFUEnbv4xT7z8t/AUOVMI8Fy4EcznypTh1xDLP1RnoBtB7MzXOa1094BJ3WhvSV9vWC0sxaHeTAMcDoe1hkSrDQ1BsVZje3iMGkxOuMpnCKw/wEAhPtFn3V3/safpY7sTm7dr8oGYWbPNGzxN7wc6K6VgTYzV6Z"
}

S3バケットの確認

Quicksightでの分析時にエラーの原因となるので、テストデータを確認したら必ず削除するようにして下さい。

  • S3コンソールを開く(新UIで説明)
  • [ToDo 2]で設定したバケット -> 年 -> 月 -> 日 -> 時(UTC) の順に開く
  • 1つだけファイルがあるはずなので、ダウンロードする
    S3 Management Console 2017-02-05 18-28-22.png

  • テキストエディタで開くと送信内容が確認できる
  • 確認後はバケットからファイルを削除しておく
    iotan-f-2-2017-02-05-09-07-49-8c4cf761-2815-4bda-8f76-be03d3525ee6 (1) 2017-02-05 18-30-49.png

S3バケットにファイルが書き込まれない場合は・・・

Kinesis Firehoseのコンソール画面からデモデータが送信できるので、S3バケットに書き込まれるか確認することで原因の切り分けができます。
Amazon Kinesis Firehose 2017-02-05 18-21-24.png
iotan-f-2-2017-02-05-09-39-46-02201148-4ccd-4c57-81eb-81f5d7fc8c4e 2017-02-05 18-43-29.png

[ToDo 5] 温度センサー回路を組み立てて温度を計測する(RaspberryPi)

1-wireデジタル温度センサーとは

RaspberryPiのGPIOはデジタル信号しか受け付けませんが、多くのセンサー類はアナログ信号を出力しますので、ADコンバーターを使って信号を変換する必要があります。今回使うデジタル温度センサーDS18B20は、1-wire規格に準拠しており、1本の信号線だけで低速なデジタルデータ転送を行うことができるので、回路が非常にシンプルになります。

温度センサー回路の組み立て

念のため、RaspberryPiをシャットダウンして回路を接続して下さい。
下記のパーツを図の通り配線し、RaspberryPiの電源をONにします。ジャンパワイヤの色は図の通りでなくてかまいません。

  • DS18B20
  • 2.2kΩカーボン抵抗
  • ブレッドボード
  • ジャンパワイヤ オスーメス 3本

DS18B20.png

RaspberryPiの設定

  • 1-wireデバイス用のモジュールを起動時に読み込むようにする
$ sudo vim /etc/modules

(最後尾に下記2行を追記する)
w1-gpio
w1-therm
  • 1-wireデバイスのGPIOに関する設定を記述する
$ sudo vim /boot/config.txt

(最後尾に下記1行を追記する)
dtoverlay=w1-gpio-pullup,gpiopin=4
  • リブート後、再度ログインする
$ sudo reboot

温度を読み出す

DS18B20は温度をファイルに書き込む仕様となっています。再起動すると/sys/bus/w1/devices/28-************/ (28-************は個体により異なるデバイスID)というディレクトリが作成されており、その中にw1_slaveというファイルが見つかるはずです。t=に続く5桁の整数を1000で割った数が温度(摂氏)です。
デバイスID 28-************[ToDo 6]で使うので控えておいてください

$ cd /sys/bus/w1/devices/
$ ls -l
total 0
lrwxrwxrwx 1 root root 0 Feb  6 01:28 28-************ -> ../../../devices/w1_bus_master1/28-************
lrwxrwxrwx 1 root root 0 Feb  6 01:28 w1_bus_master1 -> ../../../devices/w1_bus_master1
$ cd 28-************
$ cat w1_slave 
a7 01 55 00 7f ff 0c 10 22 : crc=22 YES
a7 01 55 00 7f ff 0c 10 22 t=26437

pi@raspberrypi: :sys:bus:w1:devices:28-0214642802ff — ssh pi@192.168.0.3 — 90×11 2017-02-06 01-32-30.png

[ToDo 6] シェルスクリプトで温度データをKinesis Firehoseにput-recordする(RaspberryPi)

シェルスクリプトで一定時間ごとに温度を読み出し、AWS CLIを叩いてKinesis Firehoseにput-recordします。JSONは["]をバックスラッシュでエスケープしなければならないことに注意が必要です。
本スクリプトはエラー処理を考慮していません。プロダクションの場合は、当然エラー処理を考慮する必要がありますので、fluentdなどのミドルウェアを使うとよいでしょう。

$ cd ~
$ vim temp-firehose.sh
  • deviceid=のあとの28-************には、[ToDo 5]で控えた28-から始まるDS18B20のデバイスIDを入力する
  • streamname=のあとの*********には、[ToDo 2]で設定したストリーム名を入力する
temp-firehose.sh
#!/bin/bash

# 第1引数がデータの送信間隔となる(デフォルトは15秒)
if [ "$1" = "" ]
then
        interval=15
else
        interval=$1
fi

# DS18B20のデバイスIDをdeviceidにセット
deviceid=28-************
# Kinesis Firehoseストリーム名をstreamnameにセット
streamname=*********

while [ 1 ]
do
        (
                # 日時をtimeにセット
                time=`date '+%F %T'`
                # 温度を読み取り、tempにセット
                temp=$(awk -F= 'END {print $2/1000}' < /sys/bus/w1/devices/$deviceid/w1_slave)
                # センサーデータが取得できたときのみデータを送信する
                if [ -n "$temp" ] ; then
                        # 送信するJSON文字列を作る
                        payload='{\"time\":\"'$time'\", \"temperature\":'$temp'}'
                        # JSONを画面に表示
                        echo $payload
                        # AWS CLIでput-recordする
                        aws firehose put-record --delivery-stream-name $streamname --record="{\"Data\":\"$payload\n\"}"
                fi
        ) &
        sleep $interval
done

シェルスクリプトを実行します。停止する場合はctrl + C。第1引数(下記では20)が送信間隔で、省略した場合は15秒間隔で送信されます。下記のようにJSONと"RecordId"のレスポンスが交互に表示されたら成功です。送信間隔によってはレスポンスは遅れて表示されることもあります。

$ sh temp-firehose.sh 20
{\"time\":\"2017-02-06 01:00:10\", \"temperature\":26.187}
{
    "RecordId": "sqyX8BaKpoWgWlYjJcPdxlp/sIxOIisujyk/cjbgnUO+CbigLVEhNk9UBL9VmmQL7QXtWu5c0Gi0yZF9hYi8rY5YBXoM9anaKsEowTHSfpjQSpx9/zink5b8WQvJYZtAazYolN7GfwQkWzCQHmTbGrUztmLwiZfECorKU4SCiHF0xbDkz5b+1W9F/ylabNHNbV8Fx4gEIJs45pX+LpWz7+zjsMHmZSun"
}
{\"time\":\"2017-02-06 01:00:30\", \"temperature\":26.062}
{
    "RecordId": "sHadXs3jJTUnu9FLwPfwZzVDautdy7Vdy7k7u9dt1tYLlgF5MA4aVTYiNTh6yOtKn8H+OwWOIS3WmJTIO70kA+3snWWWG+a0fHFwQEXkIZTlu1ybXbPfXPS9566mMRkA1nLAxiBQSsXr8Wpv9XO9S6e3tf5CJYwOMaKbVVCKpr+u+uKqueyZVioLAKQz1TrF11jMBxNUdApdyVK8LQFvWu9c3V+WDcPl"
}

[ToDo 7] S3バケットに温度データログファイルが書き込まれていることを確認する(AWS)

[ToDo 4]の手順でS3バケットにファイルが書き込まれていることを確認します。初回は書き込まれるまで少し時間がかかる場合があります。

S3 Management Console 2017-02-06 01-21-10.png
ファイルを開くとJSONが書き込まれているはずです。センサーを保冷剤で冷やすとこんな感じで温度が下がります。

iotan-f-2-2017-02-05-16-04-50-9ee9d802-867e-41bc-b222-6162ec3c2f18 2017-02-06 01-23-02.png

正常に書き込まれている事を確認したら、データを蓄積するためにシェルスクリプトは実行したままの状態にしてください。コマンドラインで他の操作をする場合は、別ウインドウでSSH接続しましょう。

<後編>はこちら

[おまけ] シェルスクリプトで温度データをDynamoDBにput-itemする(RaspberryPi)

NoSQL DBであるAmazon DynamoDBにもほぼ同じ方法で書き込むことができます。
IoT.kyoto VISで可視化すると良いかもです。(宣伝スミマセン)
スクリーンショット 2017-02-12 14.29.41.png

DynamoDBのテーブルを作成する

  • aws configureコマンドで登録したIAMにDynamoDBの書き込み権限(AmazonDynamoDBFullAccess等)を付与する
  • 以下の条件でDynamoDBのテーブルを作成する
項目 設定値
リージョン 北バージニア(us-east-1)
Table Name (任意のテーブル名)
Partition key id
Sort key time

スクリプトを実行する

$ vim temp-dynamodb.sh
  • deviceid=のあとの28-************には、[ToDo 5]で控えた28-から始まるDS18B20のデバイスIDを入力する
  • tablename=のあとの*********には、DynamoDBのテーブル名を入力する
temp-dynamodb.sh
#!/bin/bash

# 第1引数がデータの送信間隔となる(デフォルトは15秒)
if [ "$1" = "" ]
then
        interval=15
else
        interval=$1
fi

# DS18B20のデバイスIDをdeviceidにセット
deviceid=28-************
# DynamoDBのテーブル名をtablemnameにセット
tablename=*********
# ノードのデバイスIDをidにセット
id=id001

while [ 1 ]
do
        (
                # 日時をtimeにセット
                time=`date '+%F %T'`
                # 温度を読み取り、tempにセット
                temp=$(awk -F= 'END {print $2/1000}' < /sys/bus/w1/devices/$deviceid/w1_slave)
                # センサーデータが取得できたときのみデータを送信する
                if [ -n "$temp" ] ; then
                        # 送信するJSON文字列を作る
                        payload='{"id": {"S":"'$id'"},"time": {"S":"'$time'"},"temperature": {"N":"'$temp'"}}'
                        # JSONを画面に表示
                        echo $payload
                        # AWS CLIでput-itemする(消費キャパシティのレスポンスなし)
                        aws dynamodb put-item --table-name $tablename --item="$payload"
                        # AWS CLIでput-itemする(消費キャパシティのレスポンスあり)
                        #aws dynamodb put-item --table-name $tablename --item="$payload" --return-consumed-capacity TOTAL
                fi
        ) &
        sleep $interval
done

シェルスクリプトを実行します。停止する場合はctrl + C。第1引数(下記では1)が送信間隔で、省略した場合は15秒間隔で送信されます。下記のようにエラーメッセージが表示されず、JSONが連続して表示されていたら成功です。

$ sh temp-dynamodb.sh 1
{"id": {"S":"id001"},"time": {"S":"2017-02-12 14:09:48"},"temperature": {"N":"30.437"}}
{"id": {"S":"id001"},"time": {"S":"2017-02-12 14:09:49"},"temperature": {"N":"29.937"}}
{"id": {"S":"id001"},"time": {"S":"2017-02-12 14:09:50"},"temperature": {"N":"29.562"}}
{"id": {"S":"id001"},"time": {"S":"2017-02-12 14:09:51"},"temperature": {"N":"29.312"}}

DynamoDBのテーブルに書き込まれていることを確認する

スクリーンショット 2017-02-12 14.14.51.png

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22