M5Stack + UiFlow + AWS でグラフ化 & 異常通知


M5Stack + UiFlow + AWS でグラフ化 & 異常通知

2020-01-25
JAWS-UG金沢 #49 × Marutsu Maker Starter #70 AWS×M5StackでIoTをはじめよう
JAWS-UG金沢 PhalanXware ふぁらお加藤

AWS とは

クラウド業界トップシェア。IoTとの連携方法もたくさんあるのでぜひ使いましょう。

全体的な設計

やりたいこと

温度を測定して送信。グラフで確認できる。しきい値を超えたら自動でメール通知くるようにする。

AWS IoTを使いたいんだけれど

 AWS IoTへはMQTTやHTTPでデータをやりとりするんですが、今日のUiFlowを使うと、メモリが足りないのか?認証をM5Stackに組み込む難易度が高い。(UiFlowを使わない方法ならできる)
 今日はせっかくUIFlowを使うので、そこから呼び出せるものを作る。

流れ

センサー > M5Stack > AWS > メール > 俺たち

M5Stackでまず温度を毎秒とるようにしてみる

Aに環境センサーをとりつけて温度を表示できることを確認します。

  1. まず、温度センサーをAポートにとりつける
  2. flow.m5stack.com をブラウザで表示、m5stackを接続
  3. 「Units」から「+」を選択して「ENV」を追加
  4. labelを4つ配置(1つは後から使います
  5. 図のようにブロックを組んで実行

ここまでできたら、この温度をAWSに送信し、一定値を超えたらメールがくるようにする

流れ
センサー > M5Stack > AWS > メール > 俺たち

AWS部分の流れさらに詳細
CloudFront > AWS API Gateway > Lambda > CloudWatch > SNS > スマホへ

CloudWatchにデータを送るLambdaの作成

Lambda

  1. 関数の作成
  2. イチから作成
  3. 関数名に m5stack-temp
  4. ランタイムは Python 3.8
  5. 「基本的なLambdaアクセス権限で新しいロールを作成」
  6. 「関数の作成」を実行 ## コード
    import boto3
    import json
    import datetime

    print('Loading function')
    cloudwatch = boto3.client('cloudwatch')

    def lambda_handler(event, context):
        PutMetricData = cloudwatch.put_metric_data(
            Namespace='M5STACK',
            MetricData=[
                {
                    'MetricName': 'fromM5Stack-temp',
                    'Timestamp': datetime.datetime.utcnow(),
                    'Value': float(event['body']),
                    'Unit': "None"
                },
            ]
        )
        PutMetricData

ロールの設定

  1. コードから下にスクロールすると「実行ロール」があり、ここから「IAMコンソールでxxxxロールを表示します」リンクをクリックして移動。
  2. ポリシー名のリンクをクリック
    1. 「ポリシーの編集」をクリックし、「JSON」タブをクリック。
      1. 最後のEffectを追加して、cloudwatch:PutMetricData権限を設定する。
    2. 「ポリシーの確認」をクリックして「CloudWatch 制限:書き込み」「CloudWatch Logs 制限: 書き込み」を確認して「変更の保存」実行。
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": "logs:CreateLogGroup",
                "Resource": "arn:aws:logs:ap-northeast-1:999999999999:*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                ],
                "Resource": [
                    "arn:aws:logs:ap-northeast-1:999999999999:log-group:/aws/lambda/m5stackTest:*"
                ]
            },
            {
                "Effect": "Allow",
                "Action": [
                    "cloudwatch:PutMetricData"
                ],
                "Resource": "*",
                "Condition": {
                    "Bool": {
                        "aws:SecureTransport": "true"
                    }
                }
            }
        ]
    }

Lambdaを呼び出すAPI Gatewayの作成

  1. 「APIを作成」
  2. 「REST API」を選んで「構築」
    1. REST
    2. 新しいAPI
    3. 「API名」に m5stack-api
    4. 「エンドポイントタイプ」は 「エッジ最適化」
    5. 「APIの作成」を実行
  3. 「リソース」右の「アクション」からドロップダウンして「メソッドの作成」
    1. 表示されたドロップダウンから「POST」を選択して、✓をクリック
    2. 「統合タイプ」を「Lambda関数」選択
    3. Lambda関数に m5stack-temp を指定
    4. 関数名クリックで関数ページに飛ぶことを確認
  4. テストしてみる。
    1. テスト⚡をクリック
    2. リクエスト本文を {"body": 30.0} と指定。最後がこんな感じのログがでてれば成功。
    Fri Jan 24 14:54:41 UTC 2020 : Successfully completed execution
    Fri Jan 24 14:54:41 UTC 2020 : Method completed with status: 200

Lambdaで保存されたデータをCloudWatchをみてみる

  1. 左から「メトリクス」を選ぶ
  2. 「すべてのメトリクス」タブ、「カスタム名前空間」から「M5STACK」を選択
  3. 「ディメンションなしのメトリクス」
  4. fromM5Stack-temp のチェックを入れるとグラフが表示され、30℃があれば成功。

API Gatewayをhttpで呼び出せるようにCloudFrontを準備する

https://〜をUIFlowから呼び出すと、メモリが足りない?エラーになってしまうので避ける。(超上級編ではC++を使って接続できている)

API Gateway デプロイする

  1. 「リソース」右の「アクション」ドロップダウンから「APIのデプロイ」を選択
  2. 「デプロイされるステージ」に「[新しいステージ]」を選択
    1. ステージ名を「v1」に
    2. 説明は空欄で「デプロイ」を実行
  3. v1 ステージエディター画面にて「URLの呼び出し https://〜/v1」とあるので、これをメモしておく

CloudFrontを経由するように設定する

  1. 「Create Distribution」をクリック
  2. Web の 「Get Started」をクリック
    1. 「Origin Domain Name」にメモした 〜 の部分 (例: 4g65v9xnXX.execute-api.ap-northeast-1.amazonaws.com )を入力
    2. 「Origin Path」に「v1」
    3. 「Origin Protocol Policy」を「HTTPS Only」を選択
    4. 「Default Cache Behavior Settings」の「Allowed HTTP Methods」を「GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE」を選択
    5. 「Query String Forwarding and Caching」を「Forward all, cache based on all」を選択
    6. 「Create Distribution」を実行
    7. Status が Deployed になることを待つ
    8. IDをクリックして「Domain Name」の欄をメモする
    9. (curl が使えるのならば curl -v -d "{\"body\":1024}" http://メモしたURL.cloudfront.net/ を試す。(CloudWatchで↑と同じ方法で確認できる。今回は値1024がきてる。

定期的に温度を送るようにUiFlowを書く

URLには↑でメモした 〜cloudfront.net のURLを指定すること。

CloudWatchでグラフを確認する

 success!!とラベルがで出続けていれば、送信するのに成功しているので、CloudWatchのグラフ画面を再描画させるなどしたらグラフが確認できる。

Amazon SNSを設定する

  1. SNSを開く
  2. 「m5stack-notif」と入力して「次のステップ」を実行
  3. 「トピックの作成」を実行
  4. 「サブスクリプションの作成」を実行
    1. 「プロトコル」をEメール
    2. 「エンドポイント」を自分のメールアドレスにする
    3. 「サブスクリプションの作成」を実行
  5. 確認のための電子メールがくるのを確認
    1. メールを開いて「Confirm subscription」リンクを開く
    2. 「Subscription confirmed!」と表示されればOK
    3. SNSを開き、左から「トピック」を選び「m5stack-notif」を選択
    4. サブスクリプションのところに「確認済み」となっていればOK # アラームを設定する
  6. CloudWatchを開く
  7. 左のメニューからアラームを選択
  8. 「アラームの作成」を実行
  9. 「メトリクスの選択」を実行
  10. 「カスタム名前空間」の「M5STACK」を選択する
  11. 「ディメンションなしのメトリクス」
  12. 「fromM5Stack-temp」にチェックして「メトリクスの選択」
  13. 「統計」を「最大」にし、「期間」を「1分」に
    1. 「しきい値の種類」を「静的」にし、「より大きい」を選択、「... よりも」に30を設定して「次へ」
    2. 「SNSトピックの選択」で「既存のSNSトピックを選択」し、「通知の送信先」で先程作成した「m5stack-notif」を選択して「次へ」
    3. 一意の名前を定義で「m5stack-alerm」として「次へ」
    4. 「アラームの作成」を実行

通知をださせてみる!

  1. M5Stackのセンサーをホッカイロで包んで温度を上げてみる!
  2. しきい値を超えたら「ALARM: "m5stack-alerm" in Asia Pacific (Tokyo)」っていうタイトルのメールが送られてくることを確認

リソースを削除しよう

削除に時間がかかるので注意!

  • CloudFront を開いて対象のDistributionsを選択して > Disable > In Progress
    • 削除に時間がかかるんで他のを並行してやってください
  • API Gateway を開いて「m5stack-api」を選択して > 右上のActions > Delete
  • Lambda を開いて「m5stack-temp」を選択して > 右上のアクション > 削除
  • CloudWatch を開いて「アラーム」を選択して > 「m5stack-alerm」にチェック > 右上のアクション > 削除
  • SNSを開いて 「トピック」を選択して > 「m5stack-nofif」にチェック > 上段の「削除」
  • CloudFront を開いて対象のDistributionsを選択して > Delete

おつかれさまでした