データをAWS IoT経由でDynamoDBへ保存する


はじめに

仕事上、まるっと引き継いであんまり理解できていない技術である、AWS Iotを自分で一から作成してみる。
やりたいことはタイトルの通り。まずはローカルマシン(PC)から簡単なデータをAWS Iotを使ってDynamoDBへデータを投げる部分を実装してみる。

準備

・AWSアカウント
・ローカルマシン(mac)
・python 3.X ※pipコマンドが使えるようにしておくこと。
・DynamoDBのテーブルは以下の通り作成しておく
 ーテーブル名:iot_test
 ーハッシュキー:time (文字列)

システム構成図

AWS IoT側の設定

AWSにログイン後、「IOT Core」をクリックし、AWS IOTの画面を表示し、
左のメニューの「管理」をクリックし、「モノ」をクリック。

モノを作成する。「単一のモノを作成する」をクリック。

「名前」に任意の名前を入力し、「次へ」をクリック。

「モノに証明書を追加」画面で「1-Click 証明書作成 (推奨)」の「証明書作成」ボタンをクリック。

証明書が作成されるので、以下をすべてダウンロード。  ※1
・このモノの証明書
・パブリックキー
・プライベートキー
・AWS IoTのルートCA
※このファイルは以降ダウンロード出来なくなるので注意

ダウンロードが完了したら、「ポリシーをアタッチ」をクリック。

ポリシーの作成を行います。
「アクション」は「iot:*」
「リソースは「*」
※今回なんでも通す設定にしていますが、設計に応じて必要な制限をかけます。

「モノの登録」をクリックして。モノの登録が完了します。

登録されたモノをクリックすると、
HTTPS、MQTTのエンドポイントを確認することができます。
※管理→モノ→セキュリティ→アクションで作成したポリシーを設定しておきます。

データ送信時は「操作」からRest API エンドポイントを確認して入力します。 ★1

次に、AWS IOTのホームから「ACT」をクリックし、ルールの作成を行います。

「名前」は任意の名前を入力し、「ルールクエリステートメント」には
「SELECT * FROM 'testRule/time' 」を入力します。
※ここで指定したクエリにより、送信データをフィルタリングすることもできる。

続いてアクションを設定します。

今回はDynamoDBに直接送信データを追加ます。

「アクションの追加」を選択し、「DYNAMODBV2」を選択後、
画面下部にある「アクションの設定」ボタンをクリック。

作成済みのDynamoDBを選択します。「リソースの選択」にてテーブルを選択すれば自動で入力されます。
ロールは「ロールの作成」をクリックし、新規作成し、「アクションの追加」をクリック。
以下は作成後の画面。

ローカルマシン側の設定

任意のディレクトリを作成し、※1のファイルをすべて配置する。

ディレクトリには以下の様になる。
・XXX.crt
・XXX-private.pem.key
・XXX-public.pem.key
・AmazonRootCA1.pem
・test.py ← 実行ファイル

pipコマンドを実行
pip install AWSIoTPythonSDK

test.pyのソース

test.py
'''
Send Time Sample
'''

from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import time
import json
import datetime
import logging

# select Debug mode
_DEBUG_ = 'PC'
#_DEBUG_ = 'Raspberry'

# Setup Param
host = "XXXXXX-ats.iot.us-west-2.amazonaws.com" ★1を入力

if _DEBUG_ == 'PC':
    #for PC
    rootCAPath = "XXXXX/AmazonRootCA1.pem"  ※ダウンロードしたKeyを入力
    certificatePath = "XXXXXX/XXXX-certificate.pem.crt"  ※任意のディレクトリに保管する。
    privateKeyPath = "XXXX/XXXX-private.pem.key"
else:
    #for Raspberry Pi
    rootCAPath = "/cert/AmazonRootCA1.pem"
    certificatePath = "/cert/xxxxxxxxx-certificate.pem.crt"
    privateKeyPath = "/cert/xxxxxxxxx-private.pem.key"

useWebsocket = False
clientId = "testRule"
topic = "testRule/time"
deviceNo = "10001"

# Configure logging
logger = logging.getLogger("AWSIoTPythonSDK.core")
logger.setLevel(logging.DEBUG)
streamHandler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
streamHandler.setFormatter(formatter)
logger.addHandler(streamHandler)

# Init AWSIoTMQTTClient
myAWSIoTMQTTClient = None
if useWebsocket:
    myAWSIoTMQTTClient = AWSIoTMQTTClient(clientId, useWebsocket=True)
    myAWSIoTMQTTClient.configureEndpoint(host, 443)
    myAWSIoTMQTTClient.configureCredentials(rootCAPath)
else:
    myAWSIoTMQTTClient = AWSIoTMQTTClient(clientId)
    myAWSIoTMQTTClient.configureEndpoint(host, 8883)
    myAWSIoTMQTTClient.configureCredentials(rootCAPath, privateKeyPath, certificatePath)

# AWSIoTMQTTClient connection configuration
myAWSIoTMQTTClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTClient.configureOfflinePublishQueueing(-1)      # Infinite offline Publish queueing
myAWSIoTMQTTClient.configureDrainingFrequency(2)            # Draining: 2 Hz
myAWSIoTMQTTClient.configureConnectDisconnectTimeout(10)    # 10 sec
myAWSIoTMQTTClient.configureMQTTOperationTimeout(5)         # 5 sec

# Connect and subscribe to AWS IoT
myAWSIoTMQTTClient.connect()
time.sleep(2)
# Initial

try:
    while True:
        nowtime = datetime.datetime.now()
        nowsettime = int(time.mktime(nowtime.timetuple()))  # UNIX Time
        #send Command
        message = {}
        message['time'] = nowtime.strftime('%Y/%m/%d %H:%M:%S')
        message['deviceNo'] = deviceNo
        message['ttl']  = nowsettime + 2592000
        messageJson = json.dumps(message)
        print (messageJson)
        myAWSIoTMQTTClient.publish(topic, messageJson, 1)
        time.sleep(10)
except:
    import traceback
    traceback.print_exc()

print ("Terminated")

動きとしては、数秒おきにサンプルで作成したデータをDynamoDBへ送信し続けます。

実行ログ

DynamoDB(テーブル名はiot_test)

まとめ

ひとまず、データをデバイス → AWS IoT → DBへ保存 という流れを一通り再現することができたのと、データを送信するまでのAWS IoTの必要な設定項目、必要なファイルも確認できたので、理解が深まった。

次はデバイスをPCではなく、raspberry piなどで実際の生データを送る部分や、
送ったデータを可視化(クラフ表示)できるようなところを触ってみたいと思います。