IoT センサーデータを SiteWise Monitor でノンコーディングで可視化してみた

IoT データ可視化の決定版!? SiteWise Monitor の基本をマスターしよう!
2022.04.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

前回、SiteWise ゲートウェイを使って設備機器のデータを SiteWise に取り込んでみました。

今回は SiteWise に取り込んだデータを 「AWS IoT SiteWise Monitor」を使って可視化してみたいと思います。

構成

今回の構成は非常にシンプルです。今回は API を使って直接 SiteWise にデータ書込みを行います。
(SiteWise ゲートウェイの作成はそれなりに手間のかかる作業である為)
そして SiteWise に書き込まれたデータを付属の SiteWise Monitor を使って可視化します。

00-sitewise-monitor-api

作業の流れ

今回の作業の流れは下記のとおりです。

  • 疑似デバイス用のプログラム作成
  • IAM 権限の設定
  • SIteWise の設定
    • アセットモデル、アセットの作成
    • アセットプロパティとデータストリームの関連付け
    • ポータルの作成
  • SiteWise Monitor の設定
    • プロジェクトの作成
    • ダッシュボードの作成

疑似デバイス用のプログラム作成

前回は Greengrass による SiteWise ゲートウェイを使って 疑似 OPC UA サーバからデータを送信しましたが、今回は「SiteWise API」を使って直接 SiteWise にデータを書き込んでみたいと思います。

この疑似デバイスが送るデータの内容は下記のとおりです。

  • CPU クロック数
    • プロパティエイリアス:/test/device/1/clock
  • 温度
    • プロパティエイリアス:/test/device/1/temperature
  • デバイスの高負荷状態と低負荷状態を模した状態を定期的に繰り返す
    • 高負荷状態ならクロック数と温度が高い値を送信

なお、今回はデータソースが OPC UA サーバではないので、プロパティエイリアスは OPC UA のデータモデルに則っていなくても構いません。
/ 区切りで管理しやすい形で設定するとよいかと思います。今回は次のような意味を込めて設定しました。

  • /[用途]/[デバイス種別]/[デバイス番号]/[データ種別]

このように、SiteWise は 産業用途での利用の他、一般的な各種センサーデータも簡単に取り込んで可視化できる点が特徴の一つです。

コードは下記になります。( sitewise-send-data-api.py というファイル名で保存)

sitewise-send-data-api.py

import boto3
import uuid
import random
import time
import logging
import sys
import json
import math

logger = logging.getLogger()
logger.setLevel(logging.INFO)
streamHandler = logging.StreamHandler(stream=sys.stdout)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
streamHandler.setFormatter(formatter)
logger.addHandler(streamHandler)

client = boto3.client('iotsitewise')

def batch_put_asset():
    start = time.time()
    mode = 'low' # 最初はLOWモードでスタート
    logger.info("starting low mode... ")

    while True:
        timer = int(time.time() - start)
        # 現在時刻の取得 (小数部, 整数部)
        timestamp_float, timestamp_int = math.modf(time.time())

        if mode == 'low':
            if timer < 120:
                MeasureValueTemp = random.uniform(1, 30)
                MeasureValueClock = random.randint(600000000,800000000)
                logger.info("temperature: {}".format(MeasureValueTemp))
                logger.info("clock: {}".format(MeasureValueClock))
            else:
                mode = 'high'
                logger.info("starting high mode... ")
                start = time.time() + 1  # reset timer
                continue
        else: #if mode == 'high':
            if timer < 120: # Mode: High load
                MeasureValueTemp = random.uniform(50, 90)
                MeasureValueClock = random.randint(1200000000,1500000000)
                logger.info("temperature: {}".format(MeasureValueTemp))
                logger.info("clock: {}".format(MeasureValueClock))
            else:
                mode = 'low'
                logger.info("starting low mode... ")
                start = time.time() + 1 # reset timer
                continue

        try:
            response = client.batch_put_asset_property_value(
                entries=[
                    {
                        'entryId': '{}'.format(uuid.uuid4()),
                        'propertyAlias': '/test/device/1/temperature',
                        'propertyValues': [
                            {
                                'value': {
                                    'doubleValue': MeasureValueTemp
                                },
                                'timestamp': {
                                    'timeInSeconds': int(timestamp_int),
                                    'offsetInNanos': int(round((timestamp_float * 1000000000), 0))
                                },
                                'quality': 'GOOD'
                            },
                        ]
                    },
                    {
                        'entryId': '{}'.format(uuid.uuid4()),
                        'propertyAlias': '/test/device/1/clock',
                        'propertyValues': [
                            {
                                'value': {
                                    'doubleValue': MeasureValueClock
                                },
                                'timestamp': {
                                    'timeInSeconds': int(timestamp_int),
                                    'offsetInNanos': int(round((timestamp_float * 1000000000), 0))
                                },
                                'quality': 'GOOD'
                            },
                        ]
                    },
                ]
            )
            logger.info("response: {}\n".format(json.dumps(response, indent=2)))

            if response['errorEntries']:
                    logger.error("temperature: {} clock: {}".format(MeasureValueTemp, MeasureValueClock))
        except Exception as e:
            logger.error("{}".format(e))
            logger.error("temperature: {} clock: {}".format(MeasureValueTemp, MeasureValueClock))

        time.sleep(5)

try:
    batch_put_asset()
except KeyboardInterrupt:
    print('\nstopped putting value.')

IAM 権限の付与

上記スクリプトを実行する環境(パソコンや EC2 など)に必要な権限を付与します。付与する IAM 権限は下記のとおりですが、緩い内容になっているので本番用途で利用する際はさらに権限を絞って設定して下さい。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "iotsitewise:BatchPutAssetPropertyValue",
            "Resource": "*"
        }
    ]
}

SIteWise の設定

次に SiteWise 側の設定を行っていきます。
前回のものとは別に新たにアセットモデルとアセットを定義します。

アセットモデルとアセットの作成

SiteWise の画面でアセットモデルを作成します。

11-make-asset-model

適当なモデル名を付けます。今回は test-device としました。

12-named-model

「測定の定義」では、clocktemperature の 2 つを定義します。

13-define-measure

最後に「モデルの作成」をクリックして終了です。

14-submit-model

アセットの作成

次にアセットを作成します。

15-make-asset

先程作成したモデル test-device を指定して作成します。
名前は適当なものを付けて下さい。今回は test-device-1 としました。

16-make-asset

アセットプロパティとデータストリームの関連付け

ここまでできたら先程のスクリプトを実行して、SiteWise へのデータ書き込みを開始します。

$ python sitewise-send-data-api.py

特にエラーが発生せずに書込みできていれば、下記のように SiteWise のデータストリームにエイリアスが出現しているはずなので、データストリームエイリアスとアセットプロパティの関連付けを行います。

対象のエイリアスを選択して「データストリームを管理」をクリックします。

30-select-stream-alias

(どちらが先でもいいですが)最初に /test/device/1/temparature「測定値を選択」をクリックします。次に先程作成したアセットを展開して、関連付けたい「測定値」である temparature を選択します。
最後に、画面右上の「選択」をクリックして関連付けは完了です。

/test/device/1/clock についても同じ作業を行い関連付けを完了させて下さい。

31-assign-stream-alias-propaty-alias

関連付けができれば下記のような画面になります。

32-assined-stream

関連付けが正常にできていれば、アセット(test-device-1)の画面でデータが取り込まれている様子が見えると思います。

33-asset-data

ポータルの作成

ここでは可視化するダッシュボードを利用するユーザーや認証方式の各種設定を行います。
SiteWise のコンソールより「ポータルの作成」をクリックします。

01-1-make-portal

適当なポータル名を付けて下さい。「ユーザー認証」は今回は AWS SSO が利用できない環境だったので IAM を選択しました。IAM User や IAM Role を SiteWise Monitor のユーザーとして使う事ができます。

01-2-config-portal

「サポート連絡先のEメール」は適当なメールアドレスを設定してください。

02-mail-and-next

次のオプション設定画面では「アラーム」と「エッジ設定」を無効にしておきます。
AWS SSO が使えない場合、アラーム機能を有効化してもメールなどで通知ができないので一旦無効のままとします。

また、今回は SiteWise ゲートウェイを使っていないので「エッジ設定」も無効のままとします。もし SiteWise ゲートウェイで「データ処理パック」を有効にしている場合は、このチェックを有効にすることでゲートウェイデバイス上でポータルが利用できるようになります。

03-option

次の画面ではポータルの管理者を設定します。今回はこの AWS 環境を利用している IAM Role を使いたかったので、その Role を指定しています。

04-select-iam-role-and-admin

今回はユーザーは「登録無し」として利用します。管理者のみでもポータルは利用可能です。
なお、SiteWise Monitor では「アクティブユーザー毎に月額 USD 10」の課金が固定で発生する点に注意して下さい。ここで別のユーザーを追加すると管理者と合わせて 「USD 20」の料金が発生します。

05-assign-user

ポータルが作成できると、下記のようにポータル専用の URL が発行されます。

06-success-make-portal

SiteWise Monitor の設定

次はダッシュボードを設定していきます。

プロジェクトの作成

まずはダッシュボードの管理単位となるプロジェクトを作成します。先程の SiteWise のコンソールにある「ポータルを開く」をクリックしてダッシュボードにアクセスします。

07-open-portal

ダッシュボード画面から「プロジェクト」の画面を開き「プロジェクトを作成」をクリックします。

08-make-project

適当なプロジェクト名を付けます。

09-make-new-project

プロジェクトが作成できれば下記の様な画面が開きます。

10-detail-my-project

作成したプロジェクトにはどのデータを表示するか何も設定されていないので、プロジェクトにアセットを追加していきます。
下記のように「アセット」画面を開きます。追加したいアセット(今回は test-device-1)を選択して「プロジェクトにアセットを追加」をクリックします。

20-add-asset-to-project

次の画面で追加したいプロジェクトを選択して「プロジェクトにアセットを追加」をクリックします。

21-add-asset-next

ダッシュボードの作成

最後にダッシュボードを作成します。「ダッシュボード」から「ダッシュボードを作成」をクリックします。

40-make-dashboard

画面上側にダッシュボード名を入力できるので適当な名前を付けておきます。
また、画面左側に先程追加したアセットが見えるようになっているので、各アセットを左側へドラッグ&ドロップして適当な配置に並べます。

41-drag-drop-data

上下に並べてみました。これでよければ「ダッシュボードを保存」をクリックして保存します。

42-save-dashboard

これでダッシュボードができました。下記の動画のようにリアルタイムにグラフを更新したり、画面上から範囲指定も簡単に行うことが可能です。

しきい値の設定

単にグラフ表示するだけでは面白くないので、もう少しダッシュボードを作り込んでみます。

ダッシュボードではグラフ上に「しきい値」を設定して、超過時に警告表示に変えることで簡易的なモニタリング機能を実現することができます。
(しきい値の超過時に通知を行いたいような場合はアラーム機能を使いますが、本記事では扱いません)

「稼働率」項目の追加

モニタリングの指標として、このデバイスの「稼働率」を監視したいと思います。
稼働率は「CPU クロック数の最大値を 100%」 として 1分間計測したもの、とここでは定義します。

この稼働率はすでに取得しているアセットデータである clock より算出可能なので、作成済みのアセットモデル test-device に次のようなメトリクスを定義します。

  • 名前:utilization (適当なもの)
  • 計算式:(clock/1500000000)*100
  • データ型:ダブル
  • 時間間隔:1分
    • すぐに動作確認したかったので短めの時間にしています。

なお、計算式はコピペで入力できません。私の環境では次の手順で入力しました。

  • 計算式の空欄をクリックした状態で「十字キーの↓」を入力してプルダウンから (x)clockを選択
  • 十字キーでカーソルを一番左に移動して ( を入力
  • 十字キーでカーソルを一番右に移動して /1500000000)*100を入力
    • この時カーソルは画面から消えて位置が見えませんが問題ありません。

計算式によってはコンソールからの入力が難しい場合があるので、計算式の設定は AWS CLI などから行う方がいいかと思います。

64-define-metrics

アセットの「測定項目」や「メトリクス」はダッシュボードにプロパティとして追加することができます。先程のダッシュボードで「編集」をクリックしてみましょう。

65-edit-dashboard

先程追加したメトリクス utilization が新たに表示されているのでダッシュボードに追加します。

66-utilization

utilization を追加したら適当なビジュアライゼーションのタイプをセットします。今回は KPI にしました。

67-select-visualization-type

次に しきい値 を「60 より大きい」でセットします。これにより utilization が 60 未満であれば赤色で数値が表示されるようになります。(画像では既にしきい値未満なので赤色です)

68-set-threshold

正常時は下記のように黒文字の表示になります。

69-status-ok

しきい値を下回ると赤色の文字に変わります。

70-state-warning

注意点

既に記載したとおりですが、SiteWise Monitor は「アクティブユーザー毎に USD 10 / 月」の課金が発生します。
これはユーザーの追加タイミングに限らず当月に作成したユーザー数の分だけ課金になります。利用日数で按分されることはなく「固定 10 USD / ユーザー / 月」である点に注意してください。

その他の料金については料金ページをご参照下さい。このページから Excel の料金カリキュレーターをダウンロードできるので、合わせて活用いただければと思います。
(本記事の執筆時点では、SiteWise は AWS Pricing Calculator 未対応です)

最後に

SiteWise Monitor を使うことで簡単に IoT データを可視化することが分かりました。手順も慣れてしまえば難しくありません。

今回は単純なダッシュボードを作りましたが、もっと工夫すればより使い勝手の良い画面が作成できると思います。引き続き検証を行いご紹介していきたいと思います。