こんにちは。
Raspberry PiとAWSをつなげて何かできないかと思い、今回はRaspberry Piに気温/気圧/湿度センサーを接続して、取得した情報をAWS IoT Coreに送り、S3バケットに情報を保存するところまでやってみようと思います。
構成イメージ
今回AWS上で構築するリソースとデータの流れは以下のイメージです。
センサー ⇒ Raspberry Pi ⇒ AWS IoT Core ⇒ S3バケットの順でデータが流れる想定です。
Raspberry Pi上でPythonスクリプトを動かして取得データをMQTTでAWS IoT Coreに送り、AWS IoT CoreでメッセージをS3バケットに保存するようにルール設定をしてみようと思います。

用意するもの
今回使うものは以下の通りです。
・Raspberry Pi 5
・温湿度・気圧センサーモジュールキット (BME280使用)
・ジャンパーケーブル×5
・ブレッドボード×1
(・AWSコンソール接続用PC)
Raspberry Pi 事前設定
今回やりたいことを実施するために、いくつかRaspberry Pi上で設定しておく必要があります。
・I2C通信の有効化
・必要なライブラリのインストール
・温湿度・気圧センサーモジュールキットとRasberry Piの接続
以上の設定方法を順を追って説明します。
※今回は取得したデータをRaspberry Piから送り、AWS上へ保存することがメインのため簡単に説明します。
Raspberry Pi設定:I2C有効化
Raspberry Piとセンサーの通信を行うために、Raspberry Pi側でI2C通信を有効化します。
コンソールで以下のコマンドを実行します。
②「I5 I2C」を選択し、[ENTER]キーを押下
③ 確認画面が表示されたら<はい>を選択し、[ENTER]キーを押下
④ I2Cが有効化されたメッセージが表示されたら[ENTER]キーを押下
⑤ Raspberry Piを再起動する
Raspberry Pi設定:ライブラリのインストール
BME280センサーからデータを取得するために、以下のコマンドを実行して必要なライブラリを追加します。
sudo pip3 install bme280 –break-system-packages
sudo pip3 install paho-mqtt –break-system-packages
※インストールオプションに「–break-system-packages」をつけないと、インストール時にエラーになります。
温湿度・気圧センサーモジュールキットとRasberry Piの接続
センサーをRaspbarry Piにつなぐため、まずはブレッドボードに温湿度・気圧センサーモジュールキットを接続します。
次に回路とRaspbarry Piを接続します。
| センサー側 | Raspberry Pi側 | 
| BME280 VDD | 3.3V:1ピン | 
| BME280 GND | GND:9ピン | 
| BME280 SDI | GPIO2(SDA):3ピン | 
| BME280 SDO | GND:6ピン | 
| BME280 SCK | GPIO3(SDL):5ピン | 
接続が終わったら、以下のコマンドを実行します。
実行結果に「76」という表記があれば、正常に接続できています。
AWS設定
さて、Rasberry Piの下準備が完了したところで、次にAWSの設定を実施していきます。
今回AWS上で設定が必要なのは以下の通りです。
・S3バケットの作成
・AWS IoT Coreのポリシー作成
・Raspberry Piの登録と接続用証明書発行
・AWS IoT Coreのエンドポイント作成
・AWS IoT Coreのルール設定
こちらも順を追って説明していきます。
S3バケットの作成
まずは、最終的にデータが保存されるS3バケットを作成します。
※下図の赤枠部分

AWSコンソールにログインして、Amazon S3を開きます。
[汎用バケット]>[バケットを作成]からバケットを作成します。
※今回は特別な設定は実施せず、すべてデフォルトのまま作成します。

AWS IoT Core:ポリシー設定
ここからはAWS IoT Coreの設定を実施します。
※下図の赤枠部分

まずは、Raspberry PiがIoT Core向けに実施できる操作を制御する「ポリシー」を設定していきます。
※このあと発行する証明書にポリシーをアタッチすることで、実施できる操作が制御されます。
AWSコンソールでIoT Coreを開いて、[管理]>[セキュリティ]>[ポリシー]を開いてください。
ポリシーが表示されたら、画面右上の[ポリシーを作成]からポリシーを作成していきます。

作成画面が表示されたら、ポリシー名と許可するアクションを設定します。
今回は一通りのMQTTアクションを許可するため、以下の許可設定とします。
すべて設定し終えたら、画面右下の[作成]でポリシーを作成します。
| ポリシー効果 | ポリシーアクション | ポリシーリソース | 
| Allow | iot:Connect | * | 
| Allow | iot:Publish | * | 
| Allow | iot:Receive | * | 
| Allow | iot:Subscribe | * | 
以上でポリシーの作成は完了です。
AWS IoT Core:Raspberry Piの登録と接続用証明書発行
ポリシーの作成が完了したら、Raspberry PiをIoT Coreへ接続するための証明書を発行します。
[管理]>[すべてのデバイス]>[モノ]を開き、画面右上の[モノを作成]からデバイスを登録していきます。
モノのプロパティはデフォルト設定のまま、次へ進みます。
今回は、デバイスシャドウも「シャドウがありません」のままで問題ないです。

デバイス証明書の設定は「新しい証明書を自動生成 (推奨)」を選択したまま、次へ進みます。

ポリシーの選択では、先ほど作成したポリシーにチェックを入れ、「モノの作成」を押下してください。

「モノの作成」を押下すると、証明書ファイルのダウンロード画面が表示されますので、必要な証明書をダウンロードします。
今回利用するのは、以下の3ファイルです。
・デバイス証明書ファイル (.crt)
・プライベートキーファイル (*****-private.pem.key)
・「Amazon ルートCA 1」のルートCA証明書ファイル

以上で証明書の発行は完了です。
AWS IoT Core:エンドポイント作成
続いて、Raspberry PiがMQTT接続する際の接続先になるエンドポイントを作成していきます。
IoT Coreコンソールの[接続]>[ドメイン設定]を開き、[ドメイン設定を作成]からエンドポイントを作成します。
作成画面が開いたら、以下の通り設定します。
※記述の無い箇所はデフォルトのままで結構です。
・ドメイン設定名:任意の名前
・ドメインタイプ:AWSマネージドドメイン (カスタムドメインも利用できるようですが、今回はマネージドを利用します。)

・アプリケーションプロトコル:セキュアな Websocket 経由の MQTT

設定し終えたら、[ドメイン設定を作成]を押下します。
ドメイン設定が作成出来たら、作成したドメイン設定の「ドメイン名」を控えておいてください。
(後ほど作成するPythonスクリプトの中に記述します。)

以上でエンドポイントの作成は完了です。
AWS IoT Core:ルール設定
最後に、Raspberry Piから送信されてきたときのルール設定をします。
ルール設定では、ルールの対象とするメッセージをSQL形式で指定出来たり、
そのメッセージに対するアクションを設定することができます。
IoT Coreコンソールの[管理]>[メッセージのルーティング]>[ルール]を開き、[ルールを作成]からルールを作成します。
ルールのプロパティ設定画面が表示されたら、任意のルール名を入力して次へ進みます。

次に、SQLステートメントを設定します。ここで設定したSQLに従って、対象とするメッセージを抽出します。
今回は、「topic/」から始まるすべてのメッセージを対象としたいため、以下の通りSQLステートメントを入力し、次へ進みます。
ルールアクションでは、SQLに従って抽出したメッセージに対して、どのようなアクションを実行するかを設定できます。
・アクション:S3 bucket
・S3 URI:先ほど作成したS3バケット
・キー:iot/${topic()}/${timestamp()}.json
・IAMロール:アクションに必要なアクセス許可が付与されたロール
今回は「iot/トピック名」の下に、「タイムスタンプ.json」というファイル名で、メッセージが保存されるように指定しています。
また、IAMロールについては、今回は「AmazonS3FullAccess」を付与したロールを指定しています。
※作成されていない場合は、このタイミングで作成してください。

以上で、すべてのAWS設定が完了しました。
Pythonスクリプトの作成
Pythonスクリプトのコードを以下に記述します。
こちらのスクリプトでは、AWS IoT CoreのエンドポイントへMQTTクライアント接続し、
センサーで取得した情報を5秒おきにエンドポイント向けにパブリッシュします。
トピック名は「topic/raspi1」としているため、パブリッシュされたメッセージは先ほどのルール設定に引っかかって、
S3バケットに保存されるという算段です。
※事前にRaspbarry Piにダウンロードした証明書ファイルを保存しておいてください。
※以下はご自身の設定に合わせて置き換えてください。
・IoT Coreのエンドポイントドメイン名
・各種証明書ファイルのパス/ファイル名
import time
import json
import socket
from datetime import datetime
import ssl
import paho.mqtt.client as mqtt
from smbus2 import SMBus
import bme280
#AWSエンドポイント情報
aws_endpoint = "********.amazonaws.com" #作成したエンドポイントのドメイン名
aws_port = 8883
#MQTTトピック設定
mqtt_topic = "topic/raspi1"
#AWS証明書
ca_path   = "*************.pem"             #「Amazon ルートCA 1」のルートCA証明書ファイル
crt_path  = "*************.pem.crt"         #デバイス証明書ファイル (.crt)
key_path  = "*************-private.pem.key" #プライベートキーファイル (*****-private.pem.key)
# BME280のI2C定義(I2Cポート1、アドレスはSDOをGNDなら0x76)
i2c_port = 1
i2c_address = 0x76
# I2Cバス・BME280初期化
bus = SMBus(i2c_port)
bme280.load_calibration_params(bus, i2c_address)  # キャリブレーション
#MQTTクライアント接続
client = mqtt.Client()
client.tls_set(ca_certs=ca_path,
               certfile=crt_path,
               keyfile=key_path,
               tls_version=ssl.PROTOCOL_TLSv1_2)
client.connect(aws_endpoint, aws_port, keepalive=60)
client.loop_start()
time.sleep(1) 
hostname = socket.gethostname()
try:
    while True:
        # BME280データ取得
        data = bme280.sample(bus, i2c_address)
        temperature = data.temperature
        humidity    = data.humidity
        pressure    = data.pressure
        now = datetime.utcnow().isoformat() + "Z"
        payload = {
            "datetime": now,
            "hostname": hostname,
            "temperature": round(temperature, 2),
            "humidity": round(humidity, 2),
            "pressure": round(pressure, 2)
        }
        client.publish(mqtt_topic, json.dumps(payload), qos=1)
        print("published:", payload)
        time.sleep(5)
except KeyboardInterrupt:
    print("終了します。")
finally:
    client.disconnect()
    bus.close()
Pythonスクリプトの実行/動作確認
ここまでですべての準備が整いましたので、実際にRaspberry Pi上でPythonスクリプトを動かして動作を確認してみましょう。
Raspbarry Piでコンソールを開いて、以下のコマンドを実行してください。
今回はPythonスクリプトのファイル名を「sensor.py」としています。
パブリッシュされたメッセージはIoT Coreで設定したルールの通り、指定のS3バケットへjson形式で保存されます。

最後に
今回はRaspberry Piに気温/気圧/湿度センサーを接続して、取得した情報をAWS IoT Coreに送り、S3バケットに情報を保存するところまでやってみました。
個人的にはRaspbarry PiもAWS IoT Coreも初めて触る代物だったため、構成はかなり簡単めかな?と思っております。
皆様もぜひとも触ってみてはいかがでしょうか。
また、続きとして、今回S3バケットに保存したデータをQuickSightで可視化してみる記事もございますので、
ぜひともご覧ください。
https://blog.usize-tech.com/visualize-iot-data-raspberrypi-aws/
もっと詳しく調べたら色々できそうだと思ったので、まだまだたくさん触ってみたいと思います。
最後まで読んでいただきありがとうございました。

 
  
  
  
  





