AWSチュートリアル「スマートサーモスタット」に従って、M5Stack Core2 for AWSで「m5stack/Core2-for-AWS-IoT-EduKit」のproject「Smart-Thermostat」を実行します。前提条件として、「 M5Stack Core2 for AWSのATECC608Aを使ってAWS IoT Coreへアクセス」を参考にして、AWS IoT Coreにアクセス可能になっていることとします。
以下に記述されている「<CLIENT_ID>」 は、AWS IoT Coreで左側のメニューで「管理」→「モノ」を選択すると表示される「名前」を指します。
AWS IoT Coreのトピックルールの作成
トピックルールは、M5Stack Core2 for AWSがAWS IoT Coreパブリッシュしたメッセージを受信し、サンプリングされた音声レベルを調査し、変化に応じて Device Shadow の部屋の在室状況ステータスを更新します。
- AWS IoT Core マネジメントコンソールに移動し、「Act」、「ルール」、「作成」の順に選択します。
- ルールに名前「thermostatRule」を付けます。
- 以下のクエリを設定して、「アクションの追加」 を選択します。
- 「AWS IoTのトピックにメッセージを再パブリッシュする」、「アクションの設定」の順に選択します。
- 「トピック」 には、「$$aws/things/<CLIENT_ID>/shadow/update 」を使用します。
- 「このアクションの実行のために AWS IoT アクセスを付与するロールを選択または作成」 で、「ロールの作成」 を選択すると、ポップアップが開き新しい IAM ロール名「Core2IotRole」を付けます。その後、「ロールの作成」 をクリックします。
- 「アクションの追加」 を選択して、アクションの設定を終了し、ルール作成フォームに戻ります。
- 作成したトピックルールを次に示します。
SELECT CASE state.reported.sound > 10 WHEN true THEN true ELSE false END AS state.desired.roomOccupancy FROM '$aws/things/<CLIENT_ID>/shadow/update/accepted' WHERE state.reported.sound <> Null
AWS IoT Eventsの入力の作成
AWS IoT Eventsの入力はインバウンドメッセージを探知器モデルにマッピングするための事前定義済みスキーマです。
- IoT Events マネジメントコンソール に移動します。左側のメニューを展開し、「入力」、「入力を作成」の順に選択します。
- 入力に 名前「thermostat」を付け、次のJSON ファイル「input.json」を作成します。
- 「ファイルをアップロード」を選択し、作成したJSON ファイル「input.json」を選びます。
- 「作成」 を選択し、入力の作成を終了します。
- 作成した入力を次に示します。
input.json
{ "current": { "state": { "reported": { "sound": 10, "temperature": 35, "roomOccupancy": false, "hvacStatus": "HEATING" } }, "version": 13 }, "timestamp": 1606282489 }
AWS IoT Coreの Device Shadow の更新ルールの作成
HVAC コントロールアプリケーションの作成に使用するこのリソースに、Device Shadow の更新を転送する新しいルールを作成します。
- AWS IoT Core マネジメントコンソールに戻り、「Act」、「ルール」、「作成」の順に選択します。
- ルールに名前「Core2IotRule」を付けます。
- 以下のクエリを設定して、「アクションの追加」 を選択します。
- 「IoT Events 入力にメッセージを送信」、「アクションの設定」 の順に選択します。
- 「入力名」で、IoT Events コンソールであらかじめ作成した入力リソース名「thermostat 」を見つけます。
- 「ロール」で 「ロールの作成」 を選択し、IAM ロール名「Core2IoTRole2」を付けます。その後「ロールの作成」を選択し、IoT Core が IoT Events にメッセージを送信する許可を与える新しい IAM ロールを確定します。
- 「アクションの追加」 を選択し、新しいルールアクションを確定し、ルール作成フォームに戻ります。
- 「ルールの作成」を選択し、ルールの作成を終了します。
- 作成したDevice Shadow の更新ルールを次に示します。
SELECT current.state as current.state, current.version as current.version, timestamp FROM '$aws/things/<CLIENT_ID>/shadow/update/documents
AWS IoT Events の探知器モデルの作成
AWS IoT Events の探知器モデルは有限ステートマシンで、1 つ以上の入力からのメッセージを処理し、モデルの状態を変更すべきかを判断します。
次のJSON ファイル「Detectormodels.json」を作成します。
Detectormodels.json
{ "detectorModelDefinition": { "states": [ { "stateName": "standby", "onInput": { "events": [], "transitionEvents": [ { "eventName": "startHeating", "condition": "($input.thermostat.current.state.reported.temperature <= $variable.heatingThresholdUnoccupied) || ($input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature <= $variable.heatingThresholdOccupied) ", "actions": [], "nextState": "heating" }, { "eventName": "startCooling", "condition": "($input.thermostat.current.state.reported.temperature >= $variable.coolingThresholdUnoccupied) || ($input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature >= $variable.coolingThresholdOccupied) ", "actions": [], "nextState": "cooling" } ] }, "onEnter": { "events": [ { "eventName": "setThresholds", "condition": "true", "actions": [ { "setVariable": { "variableName": "heatingThresholdUnoccupied", "value": "60" } }, { "setVariable": { "variableName": "heatingThresholdOccupied", "value": "68" } }, { "setVariable": { "variableName": "coolingThresholdOccupied", "value": "72" } }, { "setVariable": { "variableName": "coolingThresholdUnoccupied", "value": "80" } } ] }, { "eventName": "setStandbyInShadow", "condition": "true", "actions": [ { "iotTopicPublish": { "mqttTopic": "'$aws/things/<CLIENT_ID>/shadow/update'", "payload": { "contentExpression": "'{\"state\":{\"desired\":{\"hvacStatus\":\"STANDBY\"}}}'", "type": "JSON" } } } ] } ] }, "onExit": { "events": [] } }, { "stateName": "cooling", "onInput": { "events": [], "transitionEvents": [ { "eventName": "stopCooling", "condition": "(!$input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature < $variable.coolingThresholdUnoccupied) || ($input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature < $variable.coolingThresholdOccupied) ", "actions": [], "nextState": "standby" } ] }, "onEnter": { "events": [ { "eventName": "setCoolingInShadow", "condition": "true", "actions": [ { "iotTopicPublish": { "mqttTopic": "'$aws/things/<CLIENT_ID>/shadow/update'", "payload": { "contentExpression": "'{\"state\":{\"desired\":{\"hvacStatus\":\"COOLING\"}}}'", "type": "JSON" } } } ] } ] }, "onExit": { "events": [] } }, { "stateName": "heating", "onInput": { "events": [], "transitionEvents": [ { "eventName": "stopHeating", "condition": "(!$input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature > $variable.heatingThresholdUnoccupied) || ($input.thermostat.current.state.reported.roomOccupancy && $input.thermostat.current.state.reported.temperature > $variable.heatingThresholdOccupied) ", "actions": [], "nextState": "standby" } ] }, "onEnter": { "events": [ { "eventName": "setHeatingInShadow", "condition": "true", "actions": [ { "iotTopicPublish": { "mqttTopic": "'$aws/things/<CLIENT_ID>/shadow/update'", "payload": { "contentExpression": "'{\"state\":{\"desired\":{\"hvacStatus\":\"HEATING\"}}}'", "type": "JSON" } } } ] } ] }, "onExit": { "events": [] } } ], "initialStateName": "standby" }, "detectorModelName": "hvacApplication", "detectorModelDescription": "cloud application to manage HVAC state", "evaluationMethod": "BATCH" }
- IoT Events マネジメントコンソール に移動します。
- 「探知器モデル」を選択します。
- 「アクション」を選択し、「探知器モデルのインポート」を選択します。
- 「インポート」を選択します。
- 「開く」を選択し、作成したJSON ファイル「Detectormodels.json」を選択して、「発行」を選択します。
- 「ロール」で、新しい IAM ロール名「edukit-iotevents」を入力します。
- 「保存して発行」を選択します。
- 作成した探知器モデル設定とモデル図を次に示します。
M5Stack Core2 for AWSでSmart-Thermostatの実行
取得したproject「Smart-Thermostat」をコンパイルして実行します。M5Stack Core2 for AWSの表示画面を次に示します。
Serial Monitorの出力を次に示します。「roomOccupancy true」となり、状態が「hvacStatus STANDBY」から「hvacStatus COOLING」に遷移していることが確認できます。
・・・ ?[0;32mI (99653) MAIN: Delta - roomOccupancy state changed to 1?[0m ?[0;32mI (99813) MAIN: *****************************************************************************************?[0m ?[0;32mI (99813) MAIN: On Device: roomOccupancy true?[0m ?[0;32mI (99813) MAIN: On Device: hvacStatus STANDBY?[0m ?[0;32mI (99823) MAIN: On Device: temperature 69.884949?[0m ?[0;32mI (99823) MAIN: On Device: sound 123?[0m ?[0;32mI (99833) MAIN: Update Shadow: {"state":{"reported":{"temperature":69.884949,"sound":123,"roomOccupancy":true,"hvacStatus":"STANDBY"}}, "clientToken":"0123779b0168220201-69"}?[0m ?[0;32mI (99863) MAIN: *****************************************************************************************?[0m ?[0;32mI (99863) MAIN: Stack remaining for task 'aws_iot_task' is 2036 bytes?[0m ?[0;32mI (100883) MAIN: Update accepted?[0m ?[0;32mI (101063) MAIN: *****************************************************************************************?[0m ?[0;32mI (101063) MAIN: On Device: roomOccupancy true?[0m ?[0;32mI (101063) MAIN: On Device: hvacStatus STANDBY?[0m ?[0;32mI (101073) MAIN: On Device: temperature 74.825577?[0m ?[0;32mI (101073) MAIN: On Device: sound 84?[0m ?[0;32mI (101083) MAIN: Update Shadow: {"state":{"reported":{"temperature":74.825577,"sound":84,"roomOccupancy":true,"hvacStatus":"STANDBY"}}, "clientToken":"0123779b0168220201-70"}?[0m ?[0;32mI (101113) MAIN: *****************************************************************************************?[0m ?[0;32mI (101113) MAIN: Stack remaining for task 'aws_iot_task' is 2036 bytes?[0m ?[0;32mI (102133) MAIN: Update accepted?[0m ?[0;32mI (102183) MAIN: Delta - hvacStatus state changed to COOLING?[0m ?[0;32mI (102183) MAIN: setting side LEDs to blue?[0m ?[0;32mI (102313) MAIN: *****************************************************************************************?[0m ?[0;32mI (102313) MAIN: On Device: roomOccupancy true?[0m ?[0;32mI (102313) MAIN: On Device: hvacStatus COOLING?[0m ?[0;32mI (102323) MAIN: On Device: temperature 69.031212?[0m ?[0;32mI (102323) MAIN: On Device: sound 38?[0m ?[0;32mI (102333) MAIN: Update Shadow: {"state":{"reported":{"temperature":69.031212,"sound":38,"roomOccupancy":true,"hvacStatus":"COOLING"}}, "clientToken":"0123779b0168220201-71"}?[0m ?[0;32mI (102363) MAIN: *****************************************************************************************?[0m ?[0;32mI (102363) MAIN: Stack remaining for task 'aws_iot_task' is 2036 bytes?[0m ?[0;32mI (103393) MAIN: Update accepted?[0m ?[0;32mI (103463) MAIN: Delta - hvacStatus state changed to STANDBY?[0m ?[0;32mI (103463) MAIN: clearing side LEDs?[0m ?[0;32mI (103573) MAIN: *****************************************************************************************?[0m ?[0;32mI (103573) MAIN: On Device: roomOccupancy true?[0m ?[0;32mI (103573) MAIN: On Device: hvacStatus STANDBY?[0m ?[0;32mI (103583) MAIN: On Device: temperature 80.096695?[0m ・・・