Raspberry PiとAWSを繋いでみる ~AWS IoT Device Clientの導入~

ラズパイにAWS IoT Device Clientを導入してみました。
2023.03.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。CX事業本部のKyoです。前回に続いてラズパイとAWS IoT Coreを触っていきます。

前回はこちら。

概要

前回セットアップしたラズパイにAWS IoT Device Clientを導入して、MQTTでIoT Coreとの疎通確認をします。具体的には以下の手順を行います。

AWS IoT Device Client のインストールと設定

ステップ 1: AWS IoT Device Client をダウンロードして保存する

まずはAWS IoT Device Client のダウンロード、コンパイル、ラズパイへのインストールを行います。

そもそもAWS IoT Device Clientとは?という情報はダウンロード元リポジトリのREADMEにあるので待ち時間に覗いてみるといいと思います(ダウンロード、ビルドを合わせると20分くらいでした)。

ここでもざっくり概要をまとめてみます。

  • IoTデバイスとAWS IoTサービスと連携するためのリファレンス実装 (C++製)
    • 運用のベストプラクティスが組み込まれている
    • OSSなのでPoCに使ったり、改修してもよい
    • デフォルトで以下のAWSサービスにアクセスできる
      • AWS IoT Core
      • AWS IoT Device Management
      • AWS IoT Device Defender

ビルドが終わったら以下のコマンドで確認します。

$ ./aws-iot-device-client --help

	AWS IoT Device Client BINARY

For more documentation, see https://github.com/awslabs/aws-iot-device-client

Available sub-commands:

--help:									Get more help on commands
--version:								Output current version
--export-default-settings <JSON-File-Location>:				Export default settings for the AWS IoT Device Client binary to the specified file and exit program
...

この後に使用するディレクトリを作成し、パーミッションを変更してこのステップは完了です。

ステップ 2: AWS IoT で Raspberry Pi をプロビジョニングする

このステップは「デバイス証明書ファイルを作成およびダウンロードする」と「AWS IoTリソースの作成」の2つから成ります。

デバイス証明書ファイルを作成およびダウンロードする

ラズパイにSSHして、作業を行います。

create-keys-and-certificateでAWS IoTに証明書を作り、出力された情報をラズパイ側にファイルとして保存します。

aws iot create-keys-and-certificate \
--set-as-active \
--certificate-pem-outfile "~/certs/testconn/device.pem.crt" \
--public-key-outfile "~/certs/testconn/public.pem.key" \
--private-key-outfile "~/certs/testconn/private.pem.key"

…こんなエラーが出ました。

An error occurred (AccessDeniedException) when calling the CreateKeysAndCertificate operation: User:  is not authorized to perform: iot:CreateKeysAndCertificate on resource: * because no identity-based policy allows the iot:CreateKeysAndCertificate action

ポリシーが足りないと言われているので、ラズパイのAWS CLIに設定しているIAMユーザーのポリシーを以下の形に変更しました。具体的には前回作成したポリシーにiot:CreateKeysAndCertificateを追加しています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "iot:DescribeEndpoint",
                "iot:CreateKeysAndCertificate"
            ],
            "Resource": "*"
        }
    ]
}

改めてコマンドを実行すると、証明書ファイルを作成できました。レスポンスに含まれるcertificateArnは後で必要になるのでメモしておきます。また、証明書ディレクトリとそのファイルに対するアクセス許可を設定しておきます。

以上でデバイス証明書ファイルがラズパイにインストールできました。

AWS IoT リソースの作成

ローカルPCのAWS CLIから作業を行います。今回はAdmin権限を持つユーザーを利用しました。

  • デバイスデータエンドポイントのアドレスを取得 (後で使うのでメモしておきます)
aws iot describe-endpoint --endpoint-type IoT:Data-ATS
  • AWS IoT のモノを作成
aws iot create-thing --thing-name "DevCliTestThing"
  • AWS IoT ポリシーを作成
aws iot create-policy \
--policy-name "DevCliTestThingPolicy" \
--policy-document "file://~/policies/dev_cli_test_thing_policy.json"

ポリシーの定義ファイルであるdev_cli_test_thing_policy.jsonの中身は以下のようになっています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iot:Publish",
                "iot:Subscribe",
                "iot:Receive",
                "iot:Connect"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
  • ポリシーをデバイス証明書にアタッチ
aws iot attach-policy \
--policy-name "DevCliTestThingPolicy" \
--target ""
  • デバイス証明書を AWS IoT のモノのリソースにアタッチ
aws iot attach-thing-principal \
--thing-name "DevCliTestThing" \
--principal ""

特にハマりどころはなかったですが、モノ、ポリシー、デバイス証明書の関係性を把握できると理解が深まりそうです。

ステップ 3: AWS IoT Device Client を設定して接続をテストする

ラズパイ側で、AWS IoT Device Clientの設定ファイルを作成します。デバイスデータエンドポイントを前のステップで取得したものに置き換えるのを忘れないようにします。

設定を理解する上では以下が参考になりそうです。

AWSマネジメントコンソールからMQTT テストクライアントを開き、MQTTメッセージをサブスクライブする準備をします。

※ トピックフィルターに設定した#ワイルドカードです。

ラズパイ側からAWS IoT Device Clientを実行します。

./aws-iot-device-client --config-file ~/dc-configs/dc-testconn-config.json

しかし、以下のようなエラーが発生しました。

2023-03-24T10:57:55.197Z [INFO]  {Main.cpp}: Now running AWS IoT Device Client version v1.8.18-6633b39
2023-03-24T10:57:55.214Z [ERROR] {FileUtils.cpp}: Failed to create directory /var/log/aws-iot-device-client/
2023-03-24T10:57:55.215Z [ERROR] {Main.cpp}: *** AWS IOT DEVICE CLIENT FATAL ERROR: Failed to initialize AWS CRT SDK.
AWS IoT Device Client must abort execution, reason: Failed to initialize AWS CRT SDK
Please check the AWS IoT Device Client logs for more information
Segmentation fault

ディレクトリの作成に失敗しているようです。エラーメッセージを元に対策を見つけました。

上記に従ってディレクトリの作成とパーミッションの変更を行い、改めてコマンドを実行します。

無事にエラーが消え、

2023-03-24T11:18:05.299Z [INFO]  {Main.cpp}: Now running AWS IoT Device Client version v1.8.18-6633b39
2023-03-24T11:18:05.311Z [INFO]  {SharedCrtResourceManager.cpp}: SDK logging is enabled. Check /var/log/aws-iot-device-client/sdk.log for SDK logs.
2023-03-24T11:18:05.313Z [DEBUG] {LockFile.cpp}: creating lockfile
2023-03-24T11:18:05.314Z [DEBUG] {Retry.cpp}: Retryable function starting, it will retry until success
2023-03-24T11:18:05.391Z [INFO]  {SharedCrtResourceManager.cpp}: Establishing MQTT connection with client id DevCliTestThing...
2023-03-24T11:18:05.641Z [INFO]  {SharedCrtResourceManager.cpp}: MQTT connection established with return code: 0
2023-03-24T11:18:05.641Z [INFO]  {SharedCrtResourceManager.cpp}: Shared MQTT connection is ready!
2023-03-24T11:18:05.642Z [INFO]  {Main.cpp}: Provisioning with Secure Elements is disabled
2023-03-24T11:18:05.642Z [INFO]  {Main.cpp}: Config shadow is disabled
2023-03-24T11:18:05.642Z [INFO]  {Main.cpp}: Jobs is disabled
2023-03-24T11:18:05.642Z [INFO]  {Main.cpp}: Secure Tunneling is disabled
2023-03-24T11:18:05.642Z [INFO]  {Main.cpp}: Device Defender is disabled
2023-03-24T11:18:05.642Z [INFO]  {Main.cpp}: Sample shadow is disabled
2023-03-24T11:18:05.642Z [INFO]  {Main.cpp}: PubSub is enabled
2023-03-24T11:18:05.642Z [INFO]  {samples/PubSubFeature.cpp}: Creating Pub/Sub file: /home/pi/.aws-iot-device-client/pubsub/publish-file.txt
2023-03-24T11:18:05.642Z [INFO]  {FileUtils.cpp}: Successfully create directory /home/pi/.aws-iot-device-client/pubsub/ with required permissions 745
2023-03-24T11:18:05.642Z [INFO]  {samples/PubSubFeature.cpp}: Creating Pub/Sub file: /home/pi/.aws-iot-device-client/pubsub/subscribe-file.txt
2023-03-24T11:18:05.643Z [INFO]  {Main.cpp}: Sensor Publish is disabled
2023-03-24T11:18:05.643Z [INFO]  {SharedCrtResourceManager.cpp}: Starting Device Client features.
2023-03-24T11:18:05.643Z [DEBUG] {FeatureRegistry.cpp}: Attempting to start Pub Sub Sample
2023-03-24T11:18:05.643Z [INFO]  {samples/PubSubFeature.cpp}: Starting Pub Sub Sample
2023-03-24T11:18:05.643Z [INFO]  {Main.cpp}: Client base has been notified that Pub Sub Sample has started
2023-03-24T11:18:05.697Z [DEBUG] {samples/PubSubFeature.cpp}: PublishCompAck: PacketId:(Pub Sub Sample), ErrorCode:0
2023-03-24T11:18:05.705Z [DEBUG] {samples/PubSubFeature.cpp}: SubAck: PacketId:(Pub Sub Sample), ErrorCode:0

テストクライアントにも通知が届いていました!

おわりに

今回はAWS IoT Device Clientの導入とAWS IoT Coreへの疎通確認を行いました。

前回がAWS CLIを使った疎通だったのに対して、今回はAWS IoT Device ClientからのMQTTによる疎通です。デバイス証明書の設定など、ぐっとIoTっぽくなりましたね。

また今回はほぼ全工程をAWS CLIから設定を行いました。CLIから行うことでどのAWS APIを叩いているのか、必要な権限は何かが、理解しやすくてよかったです。