sakura.ioからAWS IoT経由でDynamoDBに書き込む

概要

sakura.ioとAWSを連携させてセンサーデータをDynamoDBに書き込み、IoT.kyoto VISで可視化します。
AWS IoTルールエンジンを利用して直接DynamoDBに書き込むこともできますが、今回はIoT.kyoto VISの制約によりLambdaでデータを整形してからDynamoDBに書き込むことにします。
スクリーンショット 2017-09-18 10.00.40.png

前提条件

  • モノとさくらの通信モジュールを接続し、計測値が取得できていること
  • sakura.ioコンソールでモジュール登録までが完了していること。モジュール登録までの手順はこちら
  • AWSアカウントの開設が完了していること(要クレジットカード)
    FullSizeRender.png

[1] IAMの設定

IAMキーの作成

下表のアクセス権をもつIAMキーを作成します。

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

  • vis」というUser nameでProgrammatic accessユーザーを作成する
    IAM Management Console 2017-02-05 15-25-26.png

スクリーンショット 2017-09-18 10.52.20.png

  • [Attach existing policies directly]をクリックし、[dynamo]で検索して、[AmazonDynamoDBReadOnlyAccess]にチェックを入れる
  • [Next: Review]をクリックする
    スクリーンショット 2017-09-18 10.56.57.png

  • [AmazonDynamoDBReadOnlyAccess]が表示されていることを確認して[Create user]をクリックする
    スクリーンショット 2017-09-18 10.57.06.png

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

IAM Roleの設定

下表のアクセス権をもつIAMロールを作成します。なお、手順を簡易にするため少し過剰な権限を設定しています。

ロール名 アクセス権 使用箇所
lambda_ dynamodb AmazonDynamoDBFullAccess CloudWatchLogsFullAccess LambdaからDynamoDBへの書き込み
  • 下図の通りLambda用のIAMロールを作成する
    スクリーンショット 2017-09-18 00.04.27.png
    スクリーンショット 2017-09-18 00.18.17.png

  • [Attach existing policies directly]をクリックし、[dynamo]で検索して、[AmazonDynamoDBFullAccess]にチェックを入れる

  • 検索文字列を削除後、同様に[cloudwatch]で検索して、[CloudWatchLogsFullAccess]にチェックを入れる
    スクリーンショット 2017-09-18 00.25.22.png

  • 適用されたポリシー2種(緑の囲み)を確認の上、[Role name]に[lambda_dynamodb]を入力して[Create role]をクリックする
    スクリーンショット 2017-09-18 00.28.57.png

[2] AWS IoTの設定(Thing)

AWS IoTは概念が少々複雑ですが、ある程度把握しておかないとこれ以降の設定内容が理解できないと思います。AWS Black Belt Online Seminar 2016 AWS IoTで学習すると良いでしょう。
おおまかな設定の流れは次の通りです。

  1. 証明書Thingポリシーを紐付ける
  2. 証明書をデバイスにインストールする
  3. 流れてきたトピックに対するアクション(連携先等)をルールで定義する

ポリシーの作成

  • AWS IoTコンソールを開く
    スクリーンショット 2017-09-18 00.46.54.png

  • リージョンが「Asia Pacific (Tokyo)」でない場合は変更する
    4bd6b0f2-3593-3b10-1839-62f3c2f13173.png

  • [Get started]をクリックする(下図は表示されない場合もある)
    スクリーンショット 2017-09-11 17.23.40.png

  • ポリシーを作成する
    スクリーンショット 2017-09-18 01.26.53.png

  • 下表の通り入力して[Create]をクリックする

項目 入力内容
Name AllPubSub
Action iot:*
Resource ARN *
Effect Allow

スクリーンショット 2017-09-18 01.12.18.png

Thingと証明書の作成

  • Thingを作成する
    スクリーンショット 2017-09-18 00.49.51.png

  • sakuraioを入力して[Create thing]をクリックする
    スクリーンショット 2017-09-18 00.51.50.png

  • 作成したThingをクリックする
    スクリーンショット 2017-09-18 00.53.55.png

  • 証明書を作成する
    スクリーンショット 2017-09-18 00.55.14.png

  • クライアント証明書/クライアント秘密鍵/ルート証明書の3種類をダウンロードする(ルート証明書のみ、右クリック ->リンク先を別名で保存)

  • [Activate](押し忘れ注意!) -> [Attach a policy]の順にクリックする
    スクリーンショット 2017-09-18 00.57.16.png

  • [AllPubSub]を選択して[Done]をクリックする
    スクリーンショット 2017-09-18 01.18.49.png

  • 戻る
    スクリーンショット 2017-09-18 01.24.11.png

エンドポイントを確認する

  • 歯車マークをクリックするとエンドポイントが表示されるので控えておく
    スクリーンショット 2017-09-18 01.38.48.png

[3] sakura.ioの設定

  • sakura.ioコンソールを開く
  • [+サービス追加]をクリックする
    スクリーンショット 2017-09-17 19.15.58.png

  • [AWS IoT]をクリックする
    スクリーンショット 2017-09-18 01.44.30.png

  • 下表の通り入力して[作成]をクリックする(証明書は先ほどダウンロードしたものをテキストエディタで開いてコピペする。証明書のファイル名をxxxxx.txtに変更すると開きやすい)

項目 入力内容
名前 temp_humi_awsiot
ホスト名 先ほど控えたAWS IoTエンドポイント
ポート番号 8883
PublishするTopicのプレフィックス sakuraio/pub
SubscribeするTopic sakuraio/sub
ルート証明書 ダウンロードしたものをコピペ(VeriSign-Class 3-Public-Primary-Certification-Authority-G5.pem)
クライアント証明書 ダウンロードしたものをコピペ(xxxx-certificate.pem.crt)
クライアント秘密鍵 ダウンロードしたものをコピペ(xxxx-private.pem.key)

スクリーンショット 2017-09-18 01.50.14.png

  • 設定済の連携サービス[temp_humi_awsiot]を開き、接続ステータスが[success]となっていることを確認する
    接続ステータスが[unknown]と表示される場合は、10秒程度待ってからブラウザをリロードする
    スクリーンショット 2017-09-18 02.17.55.png
    スクリーンショット 2017-09-18 02.18.34.png

[4] AWS IoTの受信テスト

  • AWS IoTコンソールを開く(画面キャプチャ省略)
  • リージョンが「Asia Pacific (Tokyo)」でない場合は変更する(画面キャプチャ省略)
  • [Test]をクリックし[Subscription topic]にsakuraio/#を入力する
  • [Subscribe to topc]をクリックする
    スクリーンショット 2017-09-18 02.23.14.png

  • 下図のようにトピックが5秒毎に更新されればOK
    スクリーンショット 2017-09-18 02.26.53.png

データ構造

AWS IoTにはsakuraio/pub/{deviceID}というトピックで下記のようなメッセージが送られてきます。計測値はvalueに格納されており、HDC1000を接続してsakura.io公式コードを使用した場合は下表のようになります。

{
"module": "xxxxxxxxxx",
"type": "channels",
"datetime": "2017-09-18T07:58:24.776736813Z",
"payload": {
"channels": [
{
"channel": 0,
"type": "f",
"value": 27.575073,
"datetime": "2017-09-18T07:58:24.742738363Z"
},
{
"channel": 1,
"type": "f",
"value": 73.33374,
"datetime": "2017-09-18T07:58:24.754738363Z"
},
{
"channel": 2,
"type": "I",
"value": 14021,
"datetime": "2017-09-18T07:58:24.766738363Z"
}
]
}
}
channel 計測対象
0 温度
1 湿度
2 カウンタ

[5] DynamoDBの設定

  • DynamoDBコンソールを開く(画面キャプチャ省略)
  • リージョンが「Asia Pacific (Tokyo)」でない場合は変更する(画面キャプチャ省略)
  • [Create table]をクリックする
    スクリーンショット 2017-09-18 03.01.18.png

  • [Table name]にsakuraio_temp_humiを入力する

  • [Partition key]にmoduleを入力する
  • [Add sort key]にチェックを入れ、datetimeを入力する
  • [Create]をクリックする
    スクリーンショット 2017-09-18 03.02.53.png

[6] LambdaおよびAWS IoT(ルール)の設定

AWS IoTのルールをトリガーにLambda Functionをキックします。Lambda Functionでは、タイムスタンプのms以下の切り捨てや計測値(value)の取り出しおよび、DynamoDBへの書込を行います。詳細はコードをご覧ください。

  • Lambdaコンソールを開く(画面キャプチャ省略)
  • リージョンが「Asia Pacific (Tokyo)」でない場合は変更する(画面キャプチャ省略)
  • [Create function]をクリックする
    スクリーンショット 2017-09-18 02.37.12.png

  • [Author from scratch]をクリックする
    スクリーンショット 2017-09-18 02.38.27.png

  • トリガーに[AWS IoT]を選択する
    スクリーンショット 2017-09-18 02.38.46.png

  • 下表の通り入力して[Next]をクリックする

項目 入力内容
IoT type Custom IoT Rule
Rule Create a new rule
Rule name sakuraio
Rule query statement SELECT * FROM ‘sakuraio/#’
Enable trigger ON

スクリーンショット 2017-09-18 02.54.45.png

  • [Name]にsakuraio_dynamodbと入力し、下記のコードをコピペする
const AWS = require("aws-sdk");
const dynamoDB = new AWS.DynamoDB.DocumentClient({
region: "ap-northeast-1"
});

exports.handler = (event, context, callback) => {
console.log(`event: ${JSON.stringify(event)}`);

const payload = event["payload"]["channels"];
console.log(`payload: ${JSON.stringify(payload)}`);

// DynamoDBにPUTするItemObjectを生成
const item = {};

// moduleをItemに格納
item["module"] = event["module"];
console.log(`item: ${JSON.stringify(item)}`);

// ミリ秒を切り捨て
const dateTime = event["datetime"];
const splitTime = dateTime.split(".");
console.log(`splitTime: ${JSON.stringify(splitTime[0])}`);
const time = splitTime[0] + "Z";
console.log(`time: ${JSON.stringify(time)}`);

// datetimeをItemに格納
item["datetime"] = time;
console.log(`item: ${JSON.stringify(item)}`);

// 各valueをItemに格納
Object.keys(payload).map((key) => {
const channel = "channel-" + payload[key]["channel"];
const value = payload[key]["value"];
item[channel] = value;
});
console.log(`item: ${JSON.stringify(item)}`);

// Paramsを生成 TableNameは適宜変更
const params = {
TableName: "sakuraio_temp_humi",
Item: item
};
console.log(`params: ${JSON.stringify(params)}`);

// DynamoDBにPUT実行
const dynamoPutPromise = dynamoDB.put(params).promise();
dynamoPutPromise.then((data) => {
console.log("put success!");
callback(null);
}).catch((err) => {
console.log(err);
callback(err);
});
};

スクリーンショット 2017-09-18 03.16.26.png

  • スクロールして、[lambda_dynamoDB]ロールを選択し、[Next]をクリックする
    スクリーンショット 2017-09-18 03.17.33.png

  • [Create function]をクリックする
    スクリーンショット 2017-09-18 03.30.43.png

[7] DynamoDBへの書き込み確認

  • DynamoDBコンソールを開く(画面キャプチャ省略)
  • リージョンが「Asia Pacific (Tokyo)」でない場合は変更する(画面キャプチャ省略)
  • [Tables] -> [sakuraio_temp_humi] -> [Items]の順にクリックする
  • 下図のようにレコードが記録されていることを確かめる
    スクリーンショット 2017-09-18 03.32.46.png

[8] IoT.kyoto VISの設定

vis

サインアップ

https://vis.iot.kyotoにアクセスし、「新規登録」をクリックします。登録にはメールアドレスが必要ですが、登録時にメールが受信できる必要はありません。(パスワードリマインド時のみ受信できる必要があります)

設定

手順はIoT.kyoto VIS公式マニュアルの3~4章を参照してください。
[ユーザー設定]の入力例は下図の通りです。AWSアクセス設定には、先ほど作成したIAMキー(ダウンロードしたCSV参照)を使用します。「AWS IoT連携」はOFFにしてください
スクリーンショット 2017-09-18 04.04.44.png

グラフを表示させる

[パーティションキー]と[表示対象キー]を選択して、リロードします。
スクリーンショット 2017-09-18 09.20.54.png

グラフ設定で更新間隔等を調整します。
スクリーンショット 2017-09-18 10.02.06.png

温度と湿度を同時にグラフ表示することができます。
スクリーンショット 2017-09-18 09.57.24.png