Atom's tech blog

Raspberry Pi からAWS IoT通信データをEmail通知してみた!

f:id:iAtom:20201202142441j:plain


本記事ではコアデバイスRaspberry Pi)から送信したメッセージをAWS IoT Core経由でEmail通知(AWS SNS)してみます。

Raspberry Piのインストールや証明書、ルートCA、キー情報は、「 Raspberry PiAWS IoT Greengrassを動かしてみた!(Part1)〜(Part5)」をご確認ください。

AWS SNSとは

Amazon Simple Notification Service(Amazon SNS) は、発行者からサブスクライバー (プロデューサーおよびコンシューマーとも呼ばれます) へのメッセージ配信を提供するマネージド型サービスです。発行者は、論理アクセスポイントおよび通信チャネルであるトピックにメッセージを送信することによって、受信者と非同期的に通信します。クライアントは、SNS トピックにサブスクライブし、サポートされているプロトコル ( Amazon SQS 、 AWS Lambda 、HTTP、E メール、モバイルプッシュ通知、モバイルテキストメッセージ (SMS) など) を使用して、発行されたメッセージを受信できます。

AWS構成図


f:id:iAtom:20201203135040j:plain


構成図間違っていたらすみません。

AWS IoTルール追加


AWS IoTコンソールからルールを追加します。 左メニューの「 ACT 」-> 「ルール」を選択し、「作成」ボタンをクリックします。


f:id:iAtom:20201201201643j:plain


ルール名前を「SnsSendEmail」とします。


f:id:iAtom:20201201201726j:plain


ルールクエリステートメントを「topic/test」に変更し、「アクション」ボタンをクリックします。


f:id:iAtom:20201201201928j:plain


今回はSNSを使用するので、「 SNSプッシュ通知としてメッセージを送信する」を選択し、「アクション設定」ボタンをクリックします。


f:id:iAtom:20201201202410j:plain f:id:iAtom:20201201202425j:plain


アクション設定画面で「SNSターゲット」の「作成」ボタンをクリックします。


f:id:iAtom:20201201202556j:plain


作成画面でSNSターゲット名前を「mqttSnsTest」と入力し、「作成」ボタンをクリックします。


f:id:iAtom:20201201202745j:plain


ロールの作成」ボタンをクリックします。


f:id:iAtom:20201201203024j:plain


ロール名を「mqttSnsTestRole」と入力し、「ロールの作成」ボタンをクリックします。


f:id:iAtom:20201201203205j:plain


アクション設定画面に戻るので、「アクションの追加」ボタンをクリックします。


f:id:iAtom:20201201203333j:plain


ルール作成画面に戻るので、最後に「ルールの作成」ボタンをクリックします。


f:id:iAtom:20201201203507p:plain f:id:iAtom:20201201203557j:plain


これでルール「SnsSendEmail」ができました。


f:id:iAtom:20201201203659j:plain

AWS SNSにEmail登録

AWS SNSコンソールを開きます。


f:id:iAtom:20201201204641j:plain


トピックにSNSターゲット名「mqttSnsTest」が追加されています。


f:id:iAtom:20201201205055j:plain


SNSコンソールの左メニューからサブスクリプションを起動後、「サブスクリプションの作成」ボタンをクリックします。


f:id:iAtom:20201201205150j:plain


トピックAPNのプルダウンから「............................mqttSnsTest」のAPN番号を選択します。


f:id:iAtom:20201201210111j:plain


プロトコルのプルダウンから「Eメール」を選択します。


f:id:iAtom:20201201210240j:plain


送付先のEmailアドレスを入力します。


f:id:iAtom:20201201210741j:plain


サブスクリプションの作成」ボタンをクリックします。


f:id:iAtom:20201201210907j:plain


送付先のEmailアドレスにEmailが送信されます。


f:id:iAtom:20201201211204j:plain


Emailを受信しただけでは、ステータスは「保留中の確認」状態のままです。


f:id:iAtom:20201201211657j:plain


受信後Emailの「Confirm subscription」をクリックし有効状態にします。 クリックすると下記画面が表示されます。


f:id:iAtom:20201201212111j:plain


ステータス状態は「確認済み」に遷移します。 この状態でSNS登録ができたことになります。


f:id:iAtom:20201201212317j:plain

Raspberry Piからメッセージ送信

フォルダ/ファイル構成

         |--- mqttSnsTest.py
         |
         |---cert
                   |--- root.ca.pem                      #  ルートファイル
                   |--- xxxxxxxxxxx.cert.pem"      #証明書ファイル
                   |--- xxxxxxxxxxx.private.key"   #privateキーファイル

メッセージ送信ソースコード

あまり考えず、、「Raspberry PiAWS IoT通信データをデータベース(DynamoDB)へ挿入してみた!」のソースコードでMQTT送信できたので、一部を変更して活用します。

変更は「 clientId = "mqttSnsTest" 」、「 topic = "topic/test" 」、「 time.sleep(30) 」の3つ。

下記ソースのhost(endpoint)は、AWS IoT Coreコンソールから確認できます。


f:id:iAtom:20201204093432j:plain


それでは、ソースコードです。


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

# Setup Param
host = "xxxxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com"  ## -> 自分の環境に合わせて修正

rootCAPath = "./cert/root.ca.pem"          ## -> 自分の環境に合わせて修正
certificatePath = "./cert/xxxxxxxxxx.cert.pem"    ## -> 自分の環境に合わせて修正
privateKeyPath = "./cert/xxxxxxxxxx.private.key"    ## -> 自分の環境に合わせて修正

useWebsocket = False
clientId = "mqttSnsTest"
topic = "topic/test"
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(30)
except:
    import traceback
    traceback.print_exc()

print ("Terminated")

Pythonスクリプト実行

ソースコードは「mqttSnsTest.py」にしたので、下記コマンドで実行します。

    $ python3  mqttSnsTest.py

Pythonスクリプト実行表示ログ

    $ python3 mqtt_dynamo_test.py 
    2020-12-01 16:41:56,095 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Initializing MQTT layer...
    2020-12-01 16:41:56,097 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Registering internal event callbacks to MQTT layer...
    2020-12-01 16:41:56,097 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - MqttCore initialized
    2020-12-01 16:41:56,097 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Client id: mqttSnsTest
    2020-12-01 16:41:56,097 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Protocol version: MQTTv3.1.1
    2020-12-01 16:41:56,098 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Authentication type: TLSv1.2 certificate based Mutual Auth.
    2020-12-01 16:41:56,098 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring endpoint...
    2020-12-01 16:41:56,098 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring certificates...
    2020-12-01 16:41:56,099 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring reconnect back off timing...
    2020-12-01 16:41:56,099 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Base quiet time: 1.000000 sec
    2020-12-01 16:41:56,099 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Max quiet time: 32.000000 sec
    2020-12-01 16:41:56,100 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Stable connection time: 20.000000 sec
    2020-12-01 16:41:56,100 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring offline requests queueing: max queue size: -1
    2020-12-01 16:41:56,100 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring offline requests queue draining interval: 0.500000 sec
    2020-12-01 16:41:56,101 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring connect/disconnect time out: 10.000000 sec
    2020-12-01 16:41:56,101 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Configuring MQTT operation time out: 5.000000 sec
    2020-12-01 16:41:56,101 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync connect...
    2020-12-01 16:41:56,102 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing async connect...
    2020-12-01 16:41:56,102 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Keep-alive: 600.000000 sec
    2020-12-01 16:41:56,104 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Event consuming thread started
    2020-12-01 16:41:56,104 - AWSIoTPythonSDK.core.protocol.mqtt_core - DEBUG - Passing in general notification callbacks to internal client...
    2020-12-01 16:41:56,105 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in fixed event callbacks: CONNACK, DISCONNECT, MESSAGE
    2020-12-01 16:41:56,242 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Starting network I/O thread...
    2020-12-01 16:41:56,321 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [connack] event
    2020-12-01 16:41:56,322 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [connack] event
    2020-12-01 16:41:56,323 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - No need for recovery
    2020-12-01 16:41:56,323 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
    {"time": "2020/12/01 16:41:58", "deviceNo": "10001", "ttl": 1609400518}
    2020-12-01 16:41:58,327 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync publish...
    2020-12-01 16:41:58,329 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in custom puback (QoS>0) event callback...
    2020-12-01 16:41:58,363 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [puback] event
    2020-12-01 16:41:58,364 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [puback] event
    2020-12-01 16:41:58,365 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
    2020-12-01 16:41:58,366 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - This custom event callback is for pub/sub/unsub, removing it after invocation...
    2020-12-01 16:42:16,324 - AWSIoTPythonSDK.core.protocol.connection.cores - DEBUG - stableConnection: Resetting the backoff time to: 1 sec.
    {"time": "2020/12/01 16:42:28", "deviceNo": "10001", "ttl": 1609400548}
    2020-12-01 16:42:28,397 - AWSIoTPythonSDK.core.protocol.mqtt_core - INFO - Performing sync publish...
    2020-12-01 16:42:28,398 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Filling in custom puback (QoS>0) event callback...
    2020-12-01 16:42:28,433 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Produced [puback] event
    2020-12-01 16:42:28,435 - AWSIoTPythonSDK.core.protocol.internal.workers - DEBUG - Dispatching [puback] event
    2020-12-01 16:42:28,436 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - Invoking custom event callback...
    2020-12-01 16:42:28,437 - AWSIoTPythonSDK.core.protocol.internal.clients - DEBUG - This custom event callback is for pub/sub/unsub, removing it after invocation...

Email受信

Pythonスクリプトを実行中、Emai受信が確認できました。 「Raspberry PiAWS IoT通信データをデータベース(DynamoDB)へ挿入してみた!」のソースコードとほぼ同じであるため、送信したメッセージは下記の情報です。

  • 年月日時分秒
  • Device番号:ここでは10001
  • TTL

Emailの本文の「 "time":"2020/12/01 16:42:28", "deviceNo":"10001,"ttl": 1609400548 」確認もできました。 AWS素晴らしいです。


f:id:iAtom:20201201212647j:plain