💭

AWS IoTとReactで温湿度環境見える化(温湿度+絶対湿度)IoTミニアプリを構築しました。

2022/02/12に公開

先日、「ノーコードツール(AppSheet)で温湿度環境見える化(温湿度+絶対湿度)IoTアプリを構築しました」と題し、GoogleのAppSheetをつかって、IoTミニアプリを構築した解説記事をアップしました。今回は、AWS IoT等AWSのサーバレス開発環境とReactのAPI通信用の新しいライブラリであるReactQueryを組み合わせてIoTミニアプリを構築した経緯を紹介したいと思います。最後に、ノーコード開発との比較についても書きましたので、ご覧いただければ幸いです。

技術構成

センサー (温度、湿度)から取得したデータをSoracomのモバイル回線およびサービスを経由して、AWSに接続。AWSの中では、AWS IoTでソラコムからのデータをうけとり、Lambda経由でDynamoDBにいったん格納後、APIGateway,Lambda,ReactQuery等に連携し、データの加工や、リアルタイム画面表示を実現しています。
また、セキュリティの為、データ表示画面とAPIエンドポイントとの接続は、ログイン認証を必須としています。これを実現する為にAWSCognito,APIGatewayの機能を使用しています。

システム構成全体図
システム構成全体図

アプリ機能概要

ログイン画面からメイン画面への遷移
ログイン画面からメイン画面への遷移

1)基本機能
センサーからのデータ(温度、湿度)をリアルタイムにグラフおよびテーブルに表示します。データは自動的に更新されます。
また、絶対湿度については、AWSLambdaで計算処理されたものを表示しています。
センサーが複数ある場合は、ドロップダウンメニューで切り替えます。

2)ログイン機能
センサーデータ表示画面へのアクセスおよび、APIエンドポイントへのアクセスはログイン認証を必要とします。

3)アラート機能
センサーデータが閾値を超えた場合、アラートを送信します。

それぞれの機能について、実装手法と実現機能を解説

1)センサーデータ取得(SORACOM)からAWS連携設定

SORACOMが販売している温湿度センサー(https://soracom.jp/store/5235/)を使用 していますので、デバイス側のコーディングは不要です、さらにクラウド接続サービスのSORACOM Funnelを使用することでAWS IoTへの連携は、設定のみで簡単に行えます。

参考)
https://blog.soracom.com/ja-jp/2017/04/14/lets-soracom-funnel-with-aws-iot/

センサーからは、温度、湿度に加え、位置情報等をクラウドに送信します。

2)AWSの設定(データ連携と絶対湿度の計算)

ソラコムからAWSに連携されたデータは、AWS IoTCoreのルールエンジン経由で、定義済みのLambda関数と連携、Lambda関数の中で、絶対湿度の計算後、DynamoDBへのデータ書き込みが行われます。

AWS IoTからLambdaへの連携
AWS IoTからLambdaへの連携

Lambda関数から、DynamoDBに書き込む為のIAM(Identity and Access Management)権限を付与しておきます。

sensordata-dynamodb-policyの設定画面
sensordata-dynamodb-policyの設定画面

今回のアプリでは、センサーで取得した、温度、湿度のデータから絶対湿度を算出しています。そもそも絶対湿度とはなにか、なぜ重要なのかについては、以下のちきりんさんの記事をご参照ください。健康管理、住環境維持にとても重要な指標であることがわかります。

“絶対湿度”計の勧め(冬編)

そこで、絶対湿度の計算をする必要がありますが、エクセルで計算する場合は以下の計算式となります(tは温度、RHは相対湿度)

=217(6.107810^(7.5t/(t+237.3)))/(t+273.15)RH/100

今回のアプリでは、sensorDataPut関数の中で以下の通り記述しています。

Lambda関数:絶対湿度計算のコード
Lambda関数:絶対湿度計算のコード

このようなプロセスを経て、DynamoDBに自動的にデータが蓄積されていきます。(事前にDynamoDBテーブルを定義しておきます)

DynamoDBテーブル画面
DynamoDBテーブル画面

Lamda関数は、DynamoDBへデータを登録する関数”sensorDataPut”関数に加え、DynamoDBからデータを取り出す関数"sensorDataGetById”関数を用意しておきます。この関数の肝は、16行目から29行目に記述している、DynamoDBクエリのパラメータ設定となります。この部分で、センサーID(画面のドロップダウンメニューで指定)、データ取得期間(ここでは、24時間前以降の測定データ)、データ取得件数(ここでは10件)、データ並び順(降順)を指定しています。

Lamda関数:getSensorDataById
Lamda関数:getSensorDataById



セキュリティ設定(ログイン認証、APエンドポイントセキュリティ設定について)

3-1)セキュリティ設定(ログイン認証)

DynamoDBに蓄積されたデータを参照する際には、ログイン認証を通過したユーザーのみが行えるように、認証機能の設定を行いました。

認証機能の設定はAWS Amplify という開発環境を使いました。これを使うことで、数行のコマンドを発行するだけで、認証機能の基本設定が完了します。

上記の設定で実装されるログイン画面は、標準では英語のUIとなっていますが、さらに今回は、ログイン画面、サインアップ画面の日本語化も行いました。

ログイン画面
ログイン画面

Amplifyの認証機能の設定、日本語化については、Udemyの以下の講座が大変参考になりましたので、皆様にも紹介させていただきます。(無料です!)

最短・最速で学ぶ AWS Amplify + React - Authentication編 (2022年7月追記:講座は閉鎖されたようです。)

3-2)APIエンドポイントセキュリティ設定について。

上記の設定で、グラフ表示画面へのセキュリティ設定は行えましたが、実はこれだけでは十分とは言えません。

以下に示すセキュリティ設定を行わない場合は、上記の画面にデータを供給している、APIエンドポイントにアクセスすると誰でもデータを見ることができてしまいます。

APIエンドポイントにセキュリティ設定を行っていない場合。(データが見れてしまう)
APIエンドポイントにセキュリティ設定を行っていない場合。(データが見れてしまう)

そこで、AWS CognitoとAPIGatewayで、APIセキュリティ設定を行います。詳細は割愛しますが、ざっくりイメージを持っていただくために、AWS CognitoとAPIGatewayにおける、設定画面の一部を掲載しておきます

Cognitoの設定フロー
Cognitoの設定フロー

API Gatewayの設定フロー
API Gatewayの設定フロー

これで、サーバー側の認証機能の設定は完了です。これにより、ログイン認証していないクライアントから、APIへアクセスされても、認証エラーとなり、データが表示されることはありません。

APIエンドポイントにセキュリティ設定を行った場合。(認証エラーとなります)
APIエンドポイントにセキュリティ設定を行った場合。(認証エラーとなります)


最後に、クライアント側からのアクセスの際に認証許可を得るための仕組みを追加しておきます。

ログインに成功すれば、10行目のtoken変数にtoken情報が格納されているので、APIリクエストの際には、このtoken情報をヘッダーに付与すると、API経由でセンサーデータが正しく取得できます。

ReactクライアントのfetchData関数
ReactクライアントのfetchData関数

4)画面表示(フロントエンド)ReactQuery

ここまでで、認証関係はクリアしたので、あとはデータを画面表示する為のコーディングとなります。今回は、ReactとAPI通信用のライブラリである、ReactQueryを使用します。

このReactQueryをつかうことで、APIとの通信に関するコーディング量が大幅に削減され、簡潔でわかりやすく記述することができました。

それではReactQueryを活用した、コードの解説をします。第二引数で上記に図示した、fetchDataを引数として呼び出します。第三引数として、キャッシュの利用や、データの再取得インターバルやバックグランドでのデータ取得の自動化設定等を行います。(以下コードの赤枠部分。)

グラフ表示の部分には、Chart.js(react-chartjs-2)ライブラリを使用しました。ここで、APIから取得した、連想配列データを処理して、表示要素ごとのChart.js用の配列データを用意します。DynamoDBから取得したデータは、最新のデータから10件、降順で取得する設定になっている為、sort関数をつかって、データの並び順を逆にします、そのあと、温度、湿度、絶対湿度、ラベル(時刻データ)に分解して配列データにしています。(以下コードのオレンジ色の部分)

/components/ChartSection.jsの一部
/components/ChartSection.jsの一部

Chart.jsは、棒グラフ、円グラフ等様々な表示オプションがありますが、今回は折れ線グラフを採用しました。

データが複数系統ありますので、Y座標軸として左側に温度、右側に湿度を表示するように設定しました。オプションを細かく設定することで、様々な表示ニーズに対応することができます。

react-chartjs-2 Y軸設定
react-chartjs-2 Y軸設定

Chart.jsオプションの詳細設定コードの詳細はGitHubをご参照ください。Y軸の複数設定表示について、react-chartjs-2特有のChartOptionの書き方がありますので、ご参考にしていただければと思います。

ソースコード:Github
https://github.com/IoT-Arduino/awsiot-react-app/blob/main/sensor-data-client/src/components/ChartSection.js

5)アラート機能

AWS IoTRulesには、データが特定の条件を満たした場合に、何らかのアクションを起動させる設定を、コードを書かずに実装する機能があります。Amazon SNS(SimpleNotificationService)と連携すれば、例えば、湿度が20%を下回った場合、emailでお知らせするなどの機能を簡単に構築できます。

ただし、この場合は、送信メッセージの内容は、センサーから送信された生データとなります。メッセージの加工を行う為、AWS IoTRulesから、メッセージ送信用のLambda関数を経由して、SNSからメッセージを送信する構成にします。

以下の図は、メッセージ送信用のLambda関数のコードになります。センサーデータとテキストメッセージを自由に組み合わせて、メッセージタイトルやメッセージ内容を組み立てることができます。

Lambda関数:sensorDataAlert
Lambda関数:sensorDataAlert

こちらのLambda関数にも、SNSメッセージを発行する為の、IAM(Identity and Access Management)権限を付与します。

lambda-to-sns-sensorポリシー設定画面
lambda-to-sns-sensorポリシー設定画面

Amazon SNSの設定は非常に簡単です、メッセージ送信データの保存箱的な位置づけの“トピック”と、メッセージ読み取り側の設定(送信先や送信手段)である、サブスクリプションを設定します。

詳細設定手順は割愛しますが、設定画面イメージは以下の通りです。

Amazon SNSの設定画面
Amazon SNSの設定画面

これらの設定を行うことで、以下のようなメールが送信されます。

アラートメールサンプル
アラートメールサンプル

ノーコードと比較したメリットデメリット。

今回のミニアプリは、センサーから送られてきたデータをグラフ表示、テーブル表示する画面に認証機能を付与したとてもシンプルなものですが、データの流れの基盤的な部分を構築してしまえば、画面上の細かいカスタマイズ等はかなり自由度高く行えます。

一方、前回の記事で、ノーコードツール(AppSheet)を使用しましたが、これと比較した場合、確かに、コードを書く工数がかかることはデメリットとなります。

最終的にはケースバイケースで技術選択を行っていくかと思いますが、AWSサーバレスの開発環境の充実、ReactQuery等新しいライブラリの充実等のおかげもあって、コードを書く負担も以前よりは軽減されていると思います。

個人的には、コードを書いて構築するほうが自由度があってよいと思いました。

その他AWS学習参考情報等

AWS Serverless tutorial Part1- Part5 (英語)
Hexalという架空のグリーンエナジー会社向けのアプリ構築を通じて、AWSサーバレス開発(Cognito,APIGateway,Lambda,DynamoDB)について学ぶことができます。フロントエンドはReactで構築します、CSSデータ等デザイン部分はサンプルコードがあらかじめ用意されていますので、AWSの設定やコーディング部分に集中して学習できるとても良い教材だと思います。(無料です!)

AWS公式チュートリアル
AWS Amplify を使用してシンプルなウェブアプリケーションを作成する

Discussion