こんにちは。CX事業本部のKyoです。引き続きラズパイとAWS IoT Coreを触っていきます。
前回はこちら。
概要
前回AWS IoT Device Clientをセットアップしたラズパイにより詳細な設定を行い、MQTTでIoT Coreと双方向で通信します。
具体的には以下の手順を行います。
AWS IoT Device Client との MQTT メッセージ通信をデモンストレーションする
ステップ 1: Raspberry Pi を準備して MQTT メッセージ通信のデモンストレーションをする
このステップは前回とほぼ同じ内容でした。ラズパイへの証明書セットアップ、AWS IoTへのプロビジョニング、MQTT テストクライアントでのサブスクライブの準備、を行いました。
違いがあるとすれば、1つのデバイスに対して複数の証明書をセットアップした点です。本文にも以下のような表現がありました。
AWS IoT のモノのリソースはクラウド内のデバイスの仮想表現なので、AWS IoT に複数のモノのリソースを作成して、さまざまな目的で使用できます。これらすべてを同じ物理 IoT デバイスで使用して、デバイスのさまざまな側面を表すことができます。
また、AWS IoTポリシーの書き方もより限定的になっていました。
前回
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:Publish",
"iot:Subscribe",
"iot:Receive",
"iot:Connect"
],
"Resource": [
"*"
]
}
]
}
今回
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:Connect"
],
"Resource": [
"arn:aws:iot:<リージョン>:<アカウントID>:client/PubSubTestThing"
]
},
{
"Effect": "Allow",
"Action": [
"iot:Publish"
],
"Resource": [
"arn:aws:iot:<リージョン>:<アカウントID>:topic/test/dc/pubtopic"
]
},
{
"Effect": "Allow",
"Action": [
"iot:Subscribe"
],
"Resource": [
"arn:aws:iot:<リージョン>:<アカウントID>:topicfilter/test/dc/subtopic"
]
},
{
"Effect": "Allow",
"Action": [
"iot:Receive"
],
"Resource": [
"arn:aws:iot:<リージョン>:<アカウントID>:topic/test/dc/subtopic"
]
}
]
}
ステップ 2: AWS IoT Device Client でのメッセージの発行をデモンストレーションする
AWS IoT Device Client を使用してデフォルトメッセージを発行する
まず、AWS IoT Device Client を使用してデフォルトメッセージを発行します。無事にHello Worldできています。ここまでが前回と同じ部分です。
AWS IoT Device Client を使用してカスタムメッセージを発行する
カスタムメッセージを発行していきます。まずはラズパイ側で以下のJSONファイルを作成します。これがカスタムメッセージのペイロードになります。
{
"temperature": 28,
"humidity": 80,
"barometer": 1013,
"wind": {
"velocity": 22,
"bearing": 255
}
}
その後、デフォルトメッセージの設定ファイルを元に以下のような設定ファイルを作成します。作成したペイロードJSONのパスが含まれている点がポイントです。
{
"endpoint": "<デバイスデータエンドポイント>",
"cert": "~/certs/pubsub/device.pem.crt",
"key": "~/certs/pubsub/private.pem.key",
"root-ca": "~/certs/AmazonRootCA1.pem",
"thing-name": "PubSubTestThing",
"logging": {
"enable-sdk-logging": true,
"level": "DEBUG",
"type": "STDOUT",
"file": ""
},
"jobs": {
"enabled": false,
"handler-directory": ""
},
"tunneling": {
"enabled": false
},
"device-defender": {
"enabled": false,
"interval": 300
},
"fleet-provisioning": {
"enabled": false,
"template-name": "",
"template-parameters": "",
"csr-file": "",
"device-key": ""
},
"samples": {
"pub-sub": {
"enabled": true,
"publish-topic": "test/dc/pubtopic",
"publish-file": "<ペイロードファイルのパス>",
"subscribe-topic": "test/dc/subtopic",
"subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
}
},
"config-shadow": {
"enabled": false
},
"sample-shadow": {
"enabled": false,
"shadow-name": "",
"shadow-input-file": "",
"shadow-output-file": ""
}
}
両ファイルに適切なパーミッションが設定されていることを確認したら、以下のコマンドでカスタムメッセージを発行します。
./aws-iot-device-client --config-file ~/dc-configs/dc-pubsub-custom-config.json
テストクライアントでは以下のように受信できました。
ステップ 3: AWS IoT Device Client でメッセージのサブスクリプションをデモンストレーションする
単一の MQTT メッセージトピックをサブスクライブする
改めて先ほどの設定JSONを確認します。
subscribe-topic
が test/dc/subtopic
に設定されていますね。これはtest/dc/subtopic
というトピックを(ラズパイ側で)サブスクライブできることを示しています。
また、このサブスクリプションから受信したペイロードはsubscribe-file
で指定されている~/.aws-iot-device-client/log/pubsub_rx_msgs.log
に書き込まれることになります。
"samples": {
"pub-sub": {
"enabled": true,
"publish-topic": "test/dc/pubtopic",
"publish-file": "",
"subscribe-topic": "test/dc/subtopic",
"subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
}
},
...
AWS IoT Device Clientを実行し、テストクライアントからtest/dc/subtopic
というトピック名のメッセージを発行します。
ラズパイのターミナルには以下のように表示されました。
2023-03-29T14:42:44.059Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 57 bytes
また、書き込み先にはペイロードが書き込まれていることが確認できました。
$ tail ~/.aws-iot-device-client/log/pubsub_rx_msgs.log
{
"message": "AWS IoT コンソールからの挨拶"
}
なお、トピック名をtest/dc/subtopic2
に変えるとメッセージの受信・ログへの書き込み共に行われないことも確認できました。
ワイルドカード文字を使用して複数の MQTT メッセージトピックをサブスクライブする
これまでの設定JSONを元に新しい設定JSONを作成します。subscribe-topic
がtest/dc/#
になっています。この#
がワイルドカードを意味します。
{
"endpoint": "",
"cert": "~/certs/pubsub/device.pem.crt",
"key": "~/certs/pubsub/private.pem.key",
"root-ca": "~/certs/AmazonRootCA1.pem",
"thing-name": "PubSubTestThing",
"logging": {
"enable-sdk-logging": true,
"level": "DEBUG",
"type": "STDOUT",
"file": ""
},
"jobs": {
"enabled": false,
"handler-directory": ""
},
"tunneling": {
"enabled": false
},
"device-defender": {
"enabled": false,
"interval": 300
},
"fleet-provisioning": {
"enabled": false,
"template-name": "",
"template-parameters": "",
"csr-file": "",
"device-key": ""
},
"samples": {
"pub-sub": {
"enabled": true,
"publish-topic": "test/dc/pubtopic",
"publish-file": "",
"subscribe-topic": "test/dc/#",
"subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log"
}
},
"config-shadow": {
"enabled": false
},
"sample-shadow": {
"enabled": false,
"shadow-name": "",
"shadow-input-file": "",
"shadow-output-file": ""
}
}
AWS IoT ポリシーの変更も必要です。iot::Subscribe
とiot::Receive
のResource
をワイルドカードを含む形に書き換えます。ポリシーでのワイルドカードは#
でないことに気をつけます。
{
"Effect": "Allow",
"Action": [
"iot:Subscribe"
],
"Resource": [
"arn:aws:iot:<リージョン>:<アカウントID>:topicfilter/test/dc/*"
]
},
{
"Effect": "Allow",
"Action": [
"iot:Receive"
],
"Resource": [
"arn:aws:iot:<リージョン>:<アカウントID>:topicfilter/test/dc/*"
]
}
更新後のポリシーです。バージョンが2
になってます。
テストクライアントで#
をサブスクライブします。また、ラズパイ側でもAWS IoT Device Clientを起動しておきます。
テストクライアントから二種類トピックを発行します。はじめにtest/dc/subtopic
、次に(先ほどの設定ではサブスクライブできなかった)test/dc/subtopic2
を発行します。
ラズパイ側では以下のようなログが表示されていました。
2023-03-29T15:03:35.493Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 119 bytes
2023-03-29T15:04:06.148Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 58 bytes
ログファイルも同様です。
tail -n 20 ~/.aws-iot-device-client/log/pubsub_rx_msgs.log
{
"message": "AWS IoT コンソールからの挨拶"
}{
"temperature": 28,
"humidity": 80,
"barometer": 1013,
"wind": {
"velocity": 22,
"bearing": 255
}
}
{
"message": "AWS IoT コンソールからの挨拶2"
…よく見ると3件入っていますね。これについては以下の説明がありました。
受信したログには AWS IoT Device Client によって発行されたメッセージが表示されることもあります。これは、ワイルドカードトピックフィルターにそのメッセージトピックが含まれており、発行されたメッセージがサブスクライバーに送信される前にメッセージブローカーがサブスクリプションリクエストを処理することがあるためです。
おわりに
今回は前回の復習をしつつ、より詳しくMQTTの扱いを体験しました。 サブスクライブできるトピックはAWS IoT Device Clientの設定による制御とAWS IoT ポリシーによる制御が行われており、それぞれでワイルドカードも利用できる、というのがポイントでしょうか。