擬似センサーからのデータを AWS IoT Core 経由でS3へ保存する

2023.10.02

こんにちは、データアナリティクス事業本部コンサルティングチームshunです。

工場にあるようなセンサーデータを、データ分析するためS3に流したい、、、でもどうやって良いかわからないから、ちょっとだけサンプルを作ってお試ししてみたい、、、そう思ったことはありませんか?・・・私はあります! というわけで、今回はAWSの公式ハンズオンを参考に、擬似センサーを用意してそのデータをS3に送信・保存するまでの流れをやってみました。

参考にしたAWSハンズオンは以下のものになります。

今回のシステム構成

今回は以下のような構成を準備します。

  • Cloud9上で擬似センサーを作成、そこから時系列データをMQTTで AWS IoT Coreに送信
  • AWS IoT Coreから Amazon Kinesis Data Firehose を用いて Amazon S3 にデータをプッシュ
  • リージョンは任意の1つのみ使用する

AWS IoT Coreについて、より理解を深めたい方は以下のブログを参照いただけたらと思います。

以下に環境のセットアップ手順を記載します。

セットアップ手順

擬似センサーの準備

今回は、Cloud9 上で仮想的なデバイスとして動作するプログラムを擬似センサーと見立ててデータソースといたします。

まずは Cloud9で環境を作成します。環境の名前は任意のもので大丈夫ですが、本テストの最後に環境を削除する際にラクなので、日付などを混ぜておくと良いと思います({お名前}-yyyymmdd など)。 Cloud9のターミナルが立ち上がったら以下のコマンドを実行し、 AWS IoT Device SDK Python v2 をインストールします。

pip3 install --user awsiotsdk

フォルダの作成と移動をし、

mkdir -p ~/environment/dummy_client/certs/
cd ~/environment/dummy_client/

AWS側が提供しているダミーデバイスコードをダウンロードします。

wget https://awsj-iot-handson.s3-ap-northeast-1.amazonaws.com/aws-iot-core-workshop/dummy_client/device_main.py -O device_main.py

この後の手順を進める際に Cloud9 を利用しているブラウザのタブは開いたままにしてください。タブを閉じると、Cloud9のインスタンスは30分(デフォルト設定の場合)で自動的に終了します。

AWS IoT Coreのセットアップ

次に、AWS IoT Core を利用するために必要な設定や、デバイスから通信を行うために必要なリソースを作成していきます。

IoTポリシーの作成

まず、AWS IoT Coreのコンソール画面 を開き、左のサイドメニューから セキュリティ -> ポリシー をクリックし、画面中央の ポリシーの作成 を押します。

今回は以下の手順でポリシーを設定していきます。

  • ポリシー名に{お名前}-yyyymmdd-policy を入力する
    • {お名前} の部分をご自身の名前に置き換えて日付を入力する
    • 例:shun-20230928-policy など
  • ポリシードキュメントの ビルダー が選択されていることを確認する
  • 「ポリシー効果」で 「許可」 を選択 する
  • 「ポリシーアクション」に すべての AWS IoT アクション 「*」 を選択する
  • 「ポリシーリソース」に 「*」 を入力する
  • 画面下部の 作成 を押下

なお、今回参考にしているハンズオンでは手順を簡略化するため、上記で設定したような権限の広いポリシーを作成しておりますが、セキュリティのベストプラクティスでは最小限の権限を設定することが推奨されております。 最小権限のポリシーを設定する場合は、以下の例のようになります。 なお、このポリシーでは AWS IoT Core への接続、data/ トピックへの Publish、およびClassic Shadow に関連するトピックへの Publish, Subscribe, Receive を許可しています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:ap-northeast-1:123456789012:client/${iot:Connection.Thing.ThingName}"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": [
        "arn:aws:iot:ap-northeast-1:123456789012:topic/data/${iot:Connection.Thing.ThingName}",
        "arn:aws:iot:ap-northeast-1:123456789012:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update",
        "arn:aws:iot:ap-northeast-1:123456789012:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/get"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:Receive",
      "Resource": [
        "arn:aws:iot:ap-northeast-1:123456789012:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update/delta",
        "arn:aws:iot:ap-northeast-1:123456789012:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update/accepted",
        "arn:aws:iot:ap-northeast-1:123456789012:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update/rejected",
        "arn:aws:iot:ap-northeast-1:123456789012:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/get/accepted",
        "arn:aws:iot:ap-northeast-1:123456789012:topic/$aws/things/${iot:Connection.Thing.ThingName}/shadow/get/rejected"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Subscribe"
      ],
      "Resource": [
        "arn:aws:iot:ap-northeast-1:123456789012:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update/delta",
        "arn:aws:iot:ap-northeast-1:123456789012:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update/accepted",
        "arn:aws:iot:ap-northeast-1:123456789012:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/update/rejected",
        "arn:aws:iot:ap-northeast-1:123456789012:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/get/accepted",
        "arn:aws:iot:ap-northeast-1:123456789012:topicfilter/$aws/things/${iot:Connection.Thing.ThingName}/shadow/get/rejected"
      ]
    }
  ]
}

モノの作成

続いて モノの作成 をしていきます。左のサイドメニューより すべてのデバイス -> モノ をクリックし、「モノを作成」 を押します。

  • 既に選択されている「1つのモノを作成」を選択します
  • モノのプロパティ画面で、モノの名前を入力します(ここでも {お名前}-yyyymmdd といったものでOKです)
  • Device Shadow設定画面で、「名前のないシャドウ(クラシック)」を選択します
  • デバイス証明書設定画面で「新しい証明書を自動生成(推奨)」を選択します
  • 証明書にポリシーをアタッチ画面で、先程作成したポリシー({お名前}-yyyymmdd-policy)にチェックを入れて、モノを作成します
  • ポップされた画面で、
    • デバイス証明書
    • プライベートキーファイル

をそれぞれダウンロードします。これは擬似センサーのセットアップ時に使用します。

擬似センサーのセットアップ

Cloud9 環境内に、仮想デバイスが AWS IoT Core と通信するために必要なファイルを配置していきます。

  • 左側のファイルツリーから dummy_client -> certs のフォルダを選択
  • 上のメニューから File -> Upload Local Files... をクリック
  • 表示されたダイアログに、先程ダウンロードした、「証明書:○○-certificate.pem.crt」と「秘密鍵:○○-private.pem.key」の2つをドラッグ&ドロップ(○○はダウンロードした証明書の名前)。

アップロードが完了したらダイアログを閉じます。 また、Cloud9 のターミナルで以下のコマンドを実行しルートCA証明書のダウンロードをします。

cd ~/environment/dummy_client
wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -O certs/AmazonRootCA1.pem

ここで、今までに準備したプログラムやファイルを用いて仮想デバイスを起動し、AWS IoT Core と通信していきます。 ターミナルで以下のコマンドを実行し、デバイスを起動します。コマンド内の{ご自分の作ったモノ名}と {AWS IoTのendpoint_url}は各々の値に置き換えてください。

cd ~/environment/dummy_client/
python3 device_main.py --device_name {ご自分の作ったモノ名} --endpoint {AWS IoTのendpoint_url}

{AWS IoTのendpoint_url} については、以下の手順で確認できます。

  • AWS IoT Coreのコンソール画面 を開く
  • 左のサイドメニューの下の方にある 設定 を選択
  • 表示された デバイスデータエンドポイント の エンドポイント の値が該当値

上記コマンドを実行すると、ダミーデバイスは AWS IoT Core へ MQTT で接続し、5秒おき(デフォルト設定の場合)にメッセージを送信します。 コマンド実行後、以下のような結果が返ってきます。 この一番下の topic をメモしておいてください。 以下の例では data/shun-20230928 です。

device_name: shun-20230928
endpoint: random-ats.iot.ap-northeast-1.amazonaws.com
rootca cert: ./certs/AmazonRootCA1.pem
private key: ./certs/random-private.pem.key
certificate: ./certs/random-certificate.pem.crt
Check latest Shadow status
Subscribing to Shadow Delta events...
Subscribing to Shadow Update responses...
Finished getting initial shadow state.
un subscribe from get shadow events
topic: data/shun-20230928

S3バケットの作成

擬似センサーからのデータを保管する先となるS3バケットを作成します。S3の画面を開き、「バケットを作成」を選択します。

  • バケット名に {お名前}-yyyymmdd を入力
  • AWS リージョン が最初に選択したリージョンであることを確認

上記確認して、「バケットを作成」を選択してください。 続いて、Kinesis Data Firehose の作成を進めていきます。

Kinesis Data Firehose ストリームの作成

ここでは擬似センサーからのデータをS3に送るために用いる、Amazon Kinesis Data Firehose を設定していきます。以下の画面のように、Kinesisのトップ画面 を開き、「Kinesis Data Firehose」 を選択、「配信ストリームを作成」 を押します。

配信ストリームの設定画面において、

  • ソース として、「Direct PUT」 を選択
  • 送信先 として 「Amazon S3」 を選択
  • 配信ストリーム名 に {お名前}-yyyymmdd を入力

と設定します。そのまま、画面を下の方にスクロールしていくと「送信先の設定」項があるので、ここで先ほど作成したS3バケットを指定します。 また、「バッファのヒント、圧縮、暗号化」をクリックし、展開されたシート内にある設定項目で

  • バッファサイズ は 「5MiB」 を入力
  • バッファ間隔 に 「60 秒」 を入力
  • データレコードの圧縮 は 「GZIP」 を選択
  • データレコードの暗号化 は 「有効ではありません」 を選択

と設定してください。

最後に画面下部の「配信ストリームを作成」を押します。 作成されたストリームの画面に移動するので、Status が Active になるのを待ちます(数分程度かかります)。

IoT ルールの作成

作成した Firehose ストリームへ IoT Core からデータ転送するため、IoT ルールを作成します。

  • AWS IoT Core のコンソール画面 を開く
  • 画面左のメニューから メッセージのルーティング を展開し、「ルール」を選択
  • 「ルールを作成」 を選択
  • ルール名 に {お名前}_yyyymmdd_s3 のように入力
  • 「次へ」 を選択
  • SQL ステートメント に以下を入力
    • 「自分のトピック名」は、擬似センサーのセットアップ時にメモした Topic の値を用います。
select * from '自分のトピック名'

以下のような入力イメージになります。

次に、ルールアクションの設定を以下の通りに入力します。

  • Kinesis Firehose ストリーム で先程作成した {お名前}-yyyymmdd を選択
  • 区切り文字 で 「\n」 を選択
  • 「新しいロールを作成」 を選択
  • ダイヤログで ロール名 に {お名前}-yyyymmdd-kfh を入力し、作成 をクリック

必要項目を入力後、「次へ」をクリックし、表示される入力内容を確認して「作成」を選択します。

最後に、S3の画面を開き、作成したバケット内を確認してください。 ${year}/${month}/${day}/${hour} のようなプレフィックス配下に、.gz ファイルのオブジェクトが作成されていることを確認できれば、目的としていたシステム作成が完了です。

テスト環境の削除

当初のシステムを確認できたら、不要な課金を防ぐため構築した環境の削除を推奨いたします。 テスト環境の削除については、ハンズオン内のこちらのページをご参照ください。

終わりに

いかがでしたでしょうか?今回の構成で、お手軽にセンサーデータをデータレイクに貯めるイメージが掴めるのではないかと思います。 もし、このブログの内容がどなたかのお役に立てれば幸いです。以上、shun でした!