Raspberry Pi + AWS IoT Core + Grafana で室内環境を可視化してみた
はじめに
こんにちは、最近すっかり暖かくなってきましたね。
部屋で仕事をしていると「暑い!」とさえ感じるようになってきました。
今回は Raspberry Pi と SCD40 センサを使って室内環境データを取得 し、
AWS IoT Core 経由でクラウドに送信して、Grafana で可視化 してみました。
最終的には、このセンサデータを AI Agent に活用 することを考えていて、
可視化だけでなく、後続の AI システムで扱いやすいデータ基盤 を作ることを目的としています。
作ったもの
この記事で紹介する構成は以下となります。
SCD40 センサーで CO2 / 温度 / 湿度 を測定
Raspberry Pi から AWS IoT Core に MQTT publish
IoT Core トピックルールによる Lambda 起動
Lambda で DynamoDB に時系列データを保存
Athena 経由の Grafana ダッシュボード
最終的に、Grafana ダッシュボード上で、室内環境データをリアルタイムに可視化できるようになりました。

全体構成
室内環境データ可視化のアーキテクチャは以下となります。

AWS IoT Core を使う理由
今回の目的ですと、センサー値を API Gateway に直接 POST する構成も考えられましたが、
ここでは AWS IoT Core を使うことにしました。
理由は以下となります。
デバイス証明書ベースで安全に接続できる
MQTT publish / subscribe と相性が良い
小さなセンサーデータを軽量に送信できる
IoT Core トピックルールにより後続処理へ柔軟にルーティングできる
将来的にデバイス制御にも拡張しやすい (AWS 側からデバイス操作ができる!)
特にトピックルールを使うことで、
受信した MQTT メッセージを Lambda や DynamoDB などの AWS サービスに流しやすくなる点 が魅力でした。
センサーから AWS にデータを送る
SCD40 と Raspberry Pi の接続
SCD40 は CO2、温度、湿度を取得できるセンサーモジュールで、
Raspberry Pi とは I2C で接続しています。

ピンを刺すだけで簡単に接続できました。もう少し電子工作したかった…

センサーデータ取得のポイント
配線は楽でしたが、SCD40 から返ってくる値はそのまま使える形式ではなく、生データを変換する 必要があります。
実装上で注意したポイントは以下となります。
I2C 経由で SCD40 から測定値を取得する
CRC チェックで通信データの破損を検知する
CO2 / 温度 / 湿度を扱いやすい形式に変換する
MQTT payload として JSON 形式で送信する
最終的に payload は以下のような形式で、Raspberry Pi から IoT Core に送信しています。
{
"device_id": "raspi-home-1",
"timestamp_ms": 1711958400000,
"temperature": 25.0,
"humidity": 40.0,
"co2_ppm": 500
}MQTT publish 処理
以下は、Raspberry Pi からセンサデータを MQTT で送信するスクリプトの一部となります。
※ MQTT は軽量な publish/subscribe 型の通信プロトコルで、IoTデバイスとの連携に適しています
ENDPOINT = "<IoT Core Endpoint>.iot.ap-northeast-1.amazonaws.com"
PORT = 8883
TOPIC = "wellness/device/raspi-home-1/telemetry"
# センサデータの読み取り、変換、CRC チェック、etc...
def read_measurement():
...
return co2, temp, hum
client.connect(ENDPOINT, PORT, keepalive=60)
client.loop_start()
start_periodic_measurement()
while True:
co2, temp, hum = read_measurement()
payload = {
"device_id": "raspi-home-1",
"timestamp_ms": int(time.time() * 1000),
"temperature": round(temp, 2),
"humidity": round(hum, 2),
"co2_ppm": int(co2),
}
# MQTT publish
result = client.publish(
TOPIC,
json.dumps(payload),
qos=1
)
time.sleep(5)スクリプトを Raspberry Pi 上で実行すると、センサデータのログが流れてきます。
センサに息を吹きかけると、CO2 が上昇していることが分かりますね!

AWS 側で受信する
先ほどのスクリプトで、Raspberry Pi から送信した MQTT メッセージは、
IoT Core の以下のトピックに publish しています。
wellness/device/raspi-home-1/telemetryAWS 側では、IoT Core のトピックルールにより、上記トピックに publish された場合は、
Lambda を起動し、受信した payload を DynamoDB に保存する ような仕組みになっています。

ここまでで確認するポイントは以下となります。
CloudWatch Logs に Lambda の受信ログが出ること
DynamoDB の room_metrics テーブルにデータが保存されること
device_id と timestamp_ms を使って時系列データとして扱えること
まず、CloudWatch Logs から、AWS 側でセンサデータを受信できていることが確認できます。

DynamoDB にもセンサデータが登録されていますね!

ここまでで、SCD40 → Raspberry Pi → IoT Core → DynamoDB までの、
センサデータを AWS 上に送信・保存 することができました。
Grafana でデータを可視化する
ここからは AWS 上のデータを可視化する 領域になりますが、
いくつかポイントを説明しながら進めていきます。
なぜ Athena を挟むのか?
DynamoDB に保存したデータを Grafana で時系列グラフとして扱うため、
今回は Athena DynamoDB Connector を利用しました。
Athena を挟むことで、DynamoDB のデータを SQL で扱える ようになる点がポイントです。
SELECT *
FROM "dynamodb_datasource"."room_metrics"
LIMIT 10;クエリを Athena で実行すると、DynamoDB からデータを取得できました。

Grafana ダッシュボード作成
Grafana 側では、Athena をデータソースとして追加して、
CO2 / 温度 / 湿度 を時系列グラフとして表示 できるようにします。
実際には以下のような流れで設定しています。
Amazon Managed Grafana Workspace 作成
Athena データソース追加
Time series グラフ作成
Athena SQL を使ったデータ可視化
例えば、CO2 の時系列グラフでは、以下のようなクエリを利用しています。
SELECT
from_unixtime(timestamp_ms / 1000) as time,
CAST(co2_ppm AS DOUBLE) as co2_ppm
FROM "dynamodb_datasource"."room_metrics"
WHERE
device_id = 'raspi-home-1'
ORDER BY timeGrafana では Data source に Athena を選択して、
上記クエリを入力し、Visualizations に Time series を設定しています。

クエリ結果から CO2 グラフを表示することができました!

CO2 / 温度 / 湿度 でダッシュボードを作成すると以下のようになります。
測定中にセンサに息を吹きかけた後、手で握ったので、
最初に CO2 が上昇した後、温度 / 湿度が上昇している ことがわかります。

苦労した点
実は、Grafana 側の権限設定にはかなりハマりました。
Athena Connector の Lambda Invoke 権限や、
Grafana Workspace IAM Role の S3 権限不足など、
複数サービスを跨ぐため原因の切り分けが難しかったです。
今回の構成では「動かない原因が IAM にある」ケースがかなり多く、
AWS の権限設計の重要さを実感しました。
可視化して分かったこと
実際にデータを可視化してみると、室内の状況をかなり把握することができました。
換気しなかった夜間に CO2 の濃度が上昇している
換気すると CO2 は一気に下がる
日中は PC 作業や外気温の影響で室温が上がる
湿度も温度や換気に連動して変化する

AI Agent へつなげるための設計
今回データを可視化してみて、Agent に渡すべき情報は「最新値」だけでは足りないということも分かりました。
例えば CO2 が高い場合でも、以下のパターンが考えられます。
瞬間的に高いのか / 1時間ずっと高いのか
上昇傾向なのか / ピークから下降傾向なのか
そのため、後続の AI Agent では情報を正しく判断できるように、
以下の情報を使うような設計にしました。
最新値
1時間平均
最大値 / 最小値
トレンド
今回はセンサデータを AWS 上に集計・可視化までのお話ですが、
次の記事では、センサーデータ基盤を活用した AI Agent システム を紹介したいと思います。
まとめ
この記事では、SCD40 + Raspberry Pi + AWS IoT Core + Grafana を使って、室内環境を可視化するデータ基盤を構築しました。
できたことは以下となります。
Raspberry Pi から CO2 / 温度 / 湿度 を測定
AWS IoT Core に MQTT publish
Lambda で DynamoDB に保存
Athena 経由で Grafana 可視化
グラフから AI Agent に必要なデータ設計を検討
次の記事では、このデータを活用した、
室内環境・天気・スケジュールを統合的に判断する AI Wellness Agent を
テーマにする予定です。
参考リンク
AWS IoT Core
Amazon Managed Grafana
Athena DynamoDB Connector
使用センサ: SCD40(光音響NDIR方式 CO2センサーモジュール)
