ここまででできたこと
- 環境モニタを作ろう with ESP32 DEV Module 〜 No1. まずは動かして見よう
- 環境モニタを作ろう with ESP32 DEV Module 〜 No2. 温度湿度センサーをつけよう
- 環境モニタを作ろう with ESP32 DEV Module 〜 No3. wifiに接続して、https通信を試してみよう
- 環境モニタを作ろう with ESP32 DEV Module 〜 No4. 温度と湿度データをクラウドに入れたい!AWS-IoTを使ってみよう #aws-iot
- 環境モニタを作ろう with ESP32 DEV Module 〜 No5. ESP32からAWS-IoTへデータをPublish #aws-iot
さて、今回は、AWS-IoTにPublishされたデータをDynamoDBに保存できるようにしましょう!
AWS IoTのルール設定
IoTルールは、Publishされたトピックやメッセージの内容を基に、他のAWSサービスに連携できる機能です。メッセージを保存したり、Lambdaを起動したりするといったことができるようになります。
- Amazon DynamoDB
- Amazon S3
- Amazon SNS
- Amazon SQS
- AWS Lambda
- Amazon Kinesis Streams
- Amazon Kinesis Firehose
- AWS IoTの別Topicへのメッセージ転送
今回は、PublishされたデータをDynamoDBに保存するルールを作成しましょう
DynamoDBへ保存
DynamoDBのテーブルを作成する
センサーのデータを格納するテーブルを作成しましょう。
- テーブル名:ueda_sensor_table
id (文字列) | |
timestamp (文字列) |
「TableArn」が出力されるので、控えておきましょう。
aws dynamodb create-table --table-name ueda_sensor_table \ --attribute-definitions AttributeName=id,AttributeType=S AttributeName=timestamp,AttributeType=S \ --key-schema AttributeName=id,KeyType=HASH AttributeName=timestamp,KeyType=RANGE \ --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1 { "TableDescription": { "AttributeDefinitions": [ { "AttributeName": "id", "AttributeType": "S" }, { "AttributeName": "timestamp", "AttributeType": "S" } ], "TableName": "ueda_sensor_table", "KeySchema": [ { "AttributeName": "id", "KeyType": "HASH" }, { "AttributeName": "timestamp", "KeyType": "RANGE" } ], "TableStatus": "CREATING", "CreationDateTime": 1511494873.387, "ProvisionedThroughput": { "NumberOfDecreasesToday": 0, "ReadCapacityUnits": 1, "WriteCapacityUnits": 1 }, "TableSizeBytes": 0, "ItemCount": 0, "TableArn": "arn:aws:dynamodb:ap-northeast-1:xxxxxxx:table/ueda_sensor_table" } }
AWS-IOTからDynamoDBにPutできるIAMロールを作成する
DynamoDBにデータをPutできるポリシーを作成します
- 「aws_iot_dynamoDB」という名前で、ロールを作成します。
vi assume.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal":{
"Service":"iot.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
aws iam create-role --role-name aws_iot_dynamoDB --assume-role-policy-document file://assume.json
- 作成したロール「aws_iot_dynamoDB」に対して、ポリシーを適用します。
vi dynamo-policy.json
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:ap-northeast-1:xxxxxxxxxxx:table/ueda_sensor_table"
}
}
aws iam put-role-policy --role-name aws_iot_dynamoDB --policy-name dynamodb_put_policy --policy-document file://dynamo-policy.json
AWS-IOTからDynamoDBにPutするルールを作成
ルールの作成サンプルは、以下の公式サイトにあリマス。それを自分用にアレンジしてください。
ルールを記述したjsonファイルを作成します
- “sql”はどのトピックから取得するか
- “dynamoDB”の部分は、対象となるテーブル名、AWS-IoTからDynamoにPUTするためのroleArnを記述し、それぞれのキーに何の値を格納するかを書きます
vi dynamo-rule.json { "ruleName": "SensorRuleDynamo", "topicRulePayload": { "sql": "SELECT * FROM 'topic/sensor'", "description": "", "actions": [ { "dynamoDB": { "tableName": "ueda_sensor_table", "roleArn" : "arn:aws:iam::749789197689:role/aws_iot_dynamoDB", "hashKeyField": "id", "hashKeyValue": "${topic(2)}", "rangeKeyField": "timestamp", "rangeKeyValue": "${timestamp()}" } } ], "ruleDisabled": false } }
ルールを作成します
aws iot create-topic-rule --cli-input-json file://dynamo-rule.json
作成したルールを確認します
$ aws iot list-topic-rules --region ap-northeast-1 { "rules": [ { "ruleArn": "arn:aws:iot:ap-northeast-1:749789197689:rule/SensorRuleDynamo", "ruleName": "SensorRuleDynamo", "topicPattern": "topic/sensor", "createdAt": 1511495449.0, "ruleDisabled": false } ] }
ESP32からPublish
コード抜粋
元となるコードは、こちらのサイトにあります!
ESP32でAWS IoTに繋いでThing Shadowを弄る – コーヒーサーバは香炉である
トピックの名前だけ変更して実行。
char *pubTopic = "topic/sensor"; void mqttLoop() { if (!mqttClient.connected()) { connectAWSIoT(); } mqttClient.loop(); long now = millis(); if (now - messageSentAt > 5000) { messageSentAt = now; sprintf(pubMessage, "{\"state\": {\"desired\":{\"foo\":\"%d\"}}}", dummyValue++); mqttClient.publish(pubTopic, pubMessage); } } void loop() { mqttLoop(); }
AWS-IoTからDynamoDBへ
「topic/sensor」でサブスクライブして、データが届いていることを確認します。
DynamoDBにデータが入っています!
ルール作成のSQLの演算子の話
ルールを作成する際のSQL 式の SELECT 句または WHERE 句では、組み込み関数を使うことができます。
また、先ほどのRule作成の時に、「timestamp()」を使いましたが、「clientid()」で、クライアントIDを取得することもできます
- clientid
- メッセージを送信している MQTT クライアントの ID を返すか、または、メッセージが MQTT クライアント経由で送られていない場合は、
n/a
を返します。SQL バージョン 2015-10-8 以降でサポートされています。
- メッセージを送信している MQTT クライアントの ID を返すか、または、メッセージが MQTT クライアント経由で送られていない場合は、
以下のように、ハッシュキーにclientidを指定すると、DynamoDBにはクライアントIDがキーで入るようになります
"dynamoDB": { "tableName": "ueda_sensor_table", "roleArn" : "arn:aws:iam::749789197689:role/aws_iot_dynamoDB", "hashKeyField": "id", "hashKeyValue": "${clientid()}", "rangeKeyField": "timestamp", "rangeKeyValue": "${timestamp()}" }
DynamoDBの状態
さて、これでESP32>AWS-IoT>AWSの各種サービス連携までできましたね!
リアルなセンサーのデータを全て格納していきましょう!