M5Stackで取得したセンサーデータをAWS IoT Core と AWS IoT SiteWiseで簡単に見える化する


普段は主にIoTプラットフォームの設計・開発、AWSインフラの構築を担当しています。
IoTプラットフォームの開発では、RaspberryPi等のエッジデバイスで動作するアプリケーションの設計・開発も担当しています。

AWS IoT Core(以下、IoT Core) のMQTTエンドポイントで受信したデータをAWS IoT SiteWise(以下、IoT SiteWise) に取り込んで、見える化した時のメモとして記事を書きます。

できたもの

M5Stack Fire と envⅢ ユニット


M5Stack Fire と env センサー

機能としては以下のような簡易なモノです

  • Wifi接続
  • IoT CoreのMQTTエンドポイントと接続
  • envユニットから取得したデータを画面表示
  • 30秒間隔でIoT Coreに送信
  • ボタンを押すと送信開始/中止

IoT SiteWise のポータル


IoT SiteWiseのポータル

取得したセンサーデータ(気温・湿度・気圧)をリアルタイムで表示できます。

構成図

  • IoT CoreのMQTTエンドポイントで受信したデータを IoT Core ルールによりIoT SiteWiseに連携

なんでやろうと思ったの?

  • M5Stack面白い
  • UIFlow面白い
  • 画面ポチポチしてるだけで、IoT Coreに簡単にメッセージが送れた(受信も簡単!!)
  • センサーで取得したデータを見える化したい!できればリアルタイムで
  • LambdaとDynamoでバックエンド作るか?フロントエンドどうする?面倒。でもやるか。。
=> IoT SiteWiseで作れるじゃん!

前提知識と自分の理解(偏見)

IoT SiteWiseとは?

AWS IoT SiteWise は、産業機器データの収集、整理、分析を簡素化するマネージドサービスです。

https://aws.amazon.com/jp/iot-sitewise/

  • IoT機器で取得したデータを貯めて、加工して、見える化できる!(さらに分析までできる?)

IoT SiteWiseへのデータ取り込みは、IoT Core ルールを使用した方法以外に、IoT SiteWiseゲートウェイ、IoT Event アクション、GreenGrass を使用する方法があるようです。

GreenGrassを利用することで、IoTデバイスの管理やIoTデバイスで動作させるアプリケーションのCICDが容易となるため、商用利用時はGreenGrassを使用することが多くなると思われますが、

  • 手間をかけずに簡単にIoTデータを収集したい
  • とりあえず見える化して何に使えるかを考えたい
  • 個人開発だから運用なんてしない

といった場合では、IoT Core ルールを使用する方法が簡単でアリだと思います。

IoT Coreとは?

簡単で安全なクラウドへのデバイス接続

https://aws.amazon.com/jp/iot-core/

  • IoT機器で取得したデータとAWSの各インフラをつなぐサービス
  • IoT機器、及びIoT機器で動作させるアプリケーション(コンポーネント)の管理が容易になる
  • MQTTのエンドポイントを使用可能

M5Stackとは?

M5Stack is the innovator of modular IoT development platform.

https://m5stack.com/

  • 可愛いマイコン

手持ちのM5Stack Fire とM5Stack用温湿度気圧センサユニット Ver.3(ENV Ⅲ)を使用しました。

やったこと

IoT Core でモノの登録

使用するモノの登録、証明書の発行、IoT Policyを作成を行います。
より詳しい方法:公式のハンズオン

センサーデータをIoT CoreにMQTTメッセージとして送る機能の実装

UIFlowを使用して実装しました。

UI

  • AWSIoT Coreに接続するため、keyファイルとcertファイルを設定
  • 送信先のトピックはIoT SiteWiseに設定するモノを設定( aws/モノ/{デバイス名}/data としておく)

UIFlowは初めて触ったので、公式のドキュメントやサンプルを見ながらポチポチしてみました。
独特な操作に慣れるのに時間がかかりました。

ロジック

  • センサーデータをIoT CoreへMQTTメッセージとして送信する
  • センサーデータを画面に表示する
    だけ

【参考】
Wifi接続

https://docs.m5stack.com/en/uiflow/advanced/wifi
IoT Coreへのメッセージ送信
https://docs.m5stack.com/en/uiflow/IoT Cloud/aws

IoT Core に送信されるMQTTメッセージ

気温・湿度・気圧のパラメータを含むjson形式

{
  "temperature": 20,
  "pressure": 1014,
  "humidity": 40
}

IoT SiteWiseの設定

アセットモデルとデバイスアセットの2つを定義します。

アセットモデルの作成

アセットモデルでは「何のデータを集めるか?集めたデータをどう加工するか?」を定義します。
envⅢ センサーで取得できる気温・湿度・気圧を測定したいので、各パラメータを測定対象のデータとして定義します
気温と気圧、湿度を測定対象として定義し、単位、データ型を指定します。


作成したアセットモデル

また、取得したデータのある期間の平均値や最大値を計算し、グラフ化・アラートの判定対象とするためのメトリクスも作成できます

デバイスアセットの作成

デバイスアセットでは、「作成したアセットモデルと取得したデータをどのように紐付けるか?」を定義します。

紐付けるアセットモデルと名前を定義して作成後、測定値の編集画面から各パラメータとエイリアスを設定します。


作成したデバイスアセットの測定値

(デバイス名に自分の名前を入れなければよかった...)

プロパティにAWS IoT のモノに登録した名称をつけることで、デバイスごとにデータを収集できるようです。
今回は1台のデバイスからしかデータ収集しませんが、とりあえず。

IoT Coreのルールの作成

IoT Core ルールを作成することで、IoT CoreでのMQTTメッセージ受信を契機に他のAWSサービスを呼び出せます。
IoT SiteWise MQTTのデータを連携するルールを作成します。

ルールクエリステイトメントに処理するSQLライクな構文でメッセージの条件を書きます。今回は以下のようにして特定のトピックで受信したことを契機にIoT SiteWiseへデータを連携するようにします。

ルールクエリステイトメント

SELECT * FROM '$aws/モノ/{デバイス名}/data'

1台のIoTデバイスで取得するデータを扱いたい場合、トピックは固定値で良いと思います。例えば、'$aws/モノ/+/data'とすることで、デバイスが増えても各デバイス用のルールを作ら必要はありません。

アクションに IoT SiteWise を指定します。
「プロパティエイリアス別」を選択、プロパティエイリアスにデバイスアセットで設定した各パラメータのエイリアスを書きます。
時刻のデータがIoT機器から送られるMQTTメッセージに含まれない場合でも、IoT Coreルールの中で時刻を設定可能です。

パラメータの個数分、エントリを追加して設定します。


MQTTメッセージから値を取得してSiteWiseに連携する設定

取得する値の定義では、例えば、以下のようなjson を受信する場合

{
  temperature: 36
}

値に ${temperature} と設定することで、temperature: 36 を取得できます。

${reports.temperature} とすれば、以下のように階層を持つjsonでも取得できます。

{
  reports: {
    temperature: 36
  }
}

また、複数のデバイスを管理する場合等、トピックにデバイスごとに可変となる値(例えばデバイス名)を含めたときは、${topic(3)}の形でトピックから値を取得できます。
デバイスごとにトピックと対応するアセットを分ける時に使用できそうです。

IoT SiteWiseでポータルを作成する

再度 IoT SiteWise に戻り、ポータルを作成します。

参考:https://docs.aws.amazon.com/ja_jp/iot-sitewise/latest/userguide/monitor-getting-started.html

ポータルの管理者(もしくは閲覧可能なユーザ)に、IAMユーザもしくはロールを追加刷る必要があります。

ポータルが作成されると、最初は何のデータも表示されていないので、ダッシュボードを作成します。
ダッシュボードでは、グラフの種類を選べたり、グラフの配置・サイズを変更したり、表示するデータを変更したりポチポチするだけで、センサーから取得したデータのグラフを作ることができました。

ダッシュボードは 5 秒ごとに自動的に更新され、データをほぼリアルタイムで視覚化することができます。

料金

1台のデバイスで1回/30秒、数kBのメッセージングであれば少額で済みそうですが、ポータルの利用に関しては1アクティブユーザ毎に10ドル/月 かかるようです。

モニタリングの料金: 10.00USD(毎月の固別アクティブユーザー数ごと)
IoT SiteWise からデータを取得して、SiteWise Monitor のウェブアプリケーションにデータを公開するための料金が発生します。

https://aws.amazon.com/jp/iot-sitewise/pricing/

個人利用用途では安くはない気がします。。

ハマったところ

IoT Core ルールを作成した時のIAMロールの設定(暫定対処実施・未解決)

IoT Core ルールを設定後、指定したトピックへメッセージを送信してもデータが連携されず。
IoT Core ルールのエラーアクションにIoT CoreのMQTT トピックを設定してデバッグすると、以下のメッセージが表示されました。(抜粋)

"failures": [
  {
    "failedAction": "IotSiteWiseAction",
    "failedResource": "",
    "errorMessage": "Failed to send message data to IoT SiteWise asset properties. [Code: AccessDeniedException, Message: User: arn:aws:sts::xxxxxxxxxxx:assumed-role/for-iot-sitewise/xxxxxxxx is not authorized to perform: iotsitewise:BatchPutAssetPropertyValue on resource: /iot/device/{デバイス名}/temperature because no identity-based policy allows the iotsitewise:BatchPutAssetPropertyValue action, 
    ...
  }
]

IAMロールの信頼関係周りでエラーとなっているようでしたが、解決方法がわからず。
公式のトラブルシューティングここらへんを参考としながら、IAMロールのCondition部分を削除することで、データを連携することができました。

IoT Core ルールで作成されるデフォルトのIAMロール

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iotsitewise:BatchPutAssetPropertyValue",
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "iotsitewise:assetHierarchyPath": [
            "/root node asset ID",
            "/root node asset ID/*"
          ]
        }
      }
    }
  ]
}

↑のロールからCondition を削除することでデータを連携することができました。

なぜ、Condition の削除が必要か、信頼関係 の記述をどう修正すればよいのか、、、IAMに詳しい方、教えて下さい。。

感想・まとめ

フロントエンドが苦手(自分)でもIoT SiteWiseを使用することで、非常に簡単にセンサーデータを見える化することができました。
手の混んだUIを作る前に、まずはIoT SiteWiseで見える化するといいかもしれません。簡単なので。
(Lambda + DynamoDB + CloudEdge とかで簡易にIoT基盤を作れる位の腕は欲しい...とは思いました。。)

今回は単一のデバイスを扱いましたが、本来のIoT SiteWiseの使い方としては、複数のデバイス、複数の種類のデータ収集、見える化、及び分析することかと思うので、この点は今後の業務で触っていきたいなと思います。

以上です。