「M5Stack Core2 for AWSでSmart-Thermostatの実行」で、AWS IoT Eventsの探知器モデルを使ってモデルの状態を判断しましたが、Device Shadowに保存されたM5Stack Core2 for AWSからのデータを、Lambda関数を使って判断してその結果をDevice Shadowに保存し、M5Stack Core2 for AWSにcallback通知します。
AWSチュートリアル「スマートサーモスタット」に対する変更方針
- AWSチュートリアル「スマートサーモスタット」をベースに、AWS IoTのトピックルールで使用するアクション「AWS IoTのトピックにメッセージを再パブリッシュする」と「IoT Events 入力にメッセージを送信」を、「メッセージデータを渡す Lambda 関数を呼び出す」に変更する。
- Lambda 関数では「sound」の値を使用して「hvacStatus」を判断し、この結果をLambda 関数からDevice Shadowにパブリッシュします。
- M5Stack Core2 for AWSのファームウェアはスマートサーモスタットのコードと同じとし、AWS IoT Device SDK for Embedded C を使用してDevice Shadowによりデータ転送を行います。
AWS IoT のトピックルールにLambda関数の登録
M5Stack Core2 for AWSでパブリッシュしたメッセージをAWS IoT Coreで受信して、Lambda関数で処理するために次のように設定します。
- AWS IoT Core マネジメントコンソールに移動し、「Act」、「ルール」、「作成」の順に選択します。
- ルールに名前「Core2IotLambdaRule」を付けます。
- 以下のクエリを設定して、「アクションの追加」 を選択します。
- 「メッセージデータを渡す Lambda 関数を呼び出す」、「アクションの設定」の順に選択します。
- 「新しい Lambda 関数を作成」をクリックし、「関数名」 に「thermostatlambda1 」、「ランタイム」に「Node.js」、「アクセス権限」に「基本的な Lambda アクセス権限で新しいロールを作成」を選択して「関数の作成」ボタンをクリックします。次のLambda 関数の作成画面が表示されます。
- 「設定」タブ、左側メニュ「アクセス権限」をそれぞれ選択し、実行ロールに管理ポリシー「 AWSIoTDataAccess」を追加します。これにより「GetThingShadow」「UpdateThingShadow」の実行を許可します。
- 「アクションの追加」 を選択して、アクションの設定を終了し、ルール作成フォームに戻ります。
- 作成したトピックルールを次に示します。
SELECT current.state as current.state, current.version as current.version, timestamp FROM '$aws/things/<CLIENT_ID>/shadow/update/documents'
実行ロールに管理ポリシー「 AWSIoTDataAccess」を追加しないでLambda 関数「thermostatlambda1 」を実行すると、例外「ForbiddenException」が発生します。
Device Shadowを処理するLambda 関数の作成
作成したLambda 関数「thermostatlambda1」を次に示します。
- 13行目で、「getThingShadow」メソッドによりDevice Shadow の内容を読み込みます。
- 23行目で、「sound」の値が「50」以上の場合、「hvacStatus」を「COOLING」、それ以外は「hvacStatus」を「STANDBY」にします。
- 44行目で、「updateThingShadow」メソッドによりDevice Shadow にパブリッシュします。
thermostatlambda1/index.js
var aws = require('aws-sdk'); var endpoint = 'xxxxxxx.amazonaws.com'; var thingName = 'yyyyyyyy'; exports.handler = async (event) => { // TODO implement console.log('exports.handler 01'); var iotdata = new aws.IotData( { endpoint: endpoint } ); console.log("event JSON:", JSON.stringify(event, null, 2)); var params = { thingName: thingName }; iotdata.getThingShadow(params, function (err, data) { if (!err) { // シャドウドキュメントから現在の設定を取得 var payload = JSON.parse(data.payload); console.log("payload : " + JSON.stringify(payload, null, 2)); var sound = payload.state.reported.sound; console.log("sound : " + sound); //var currentBlinkPattern = payload.state.desired.blinkPattern; var status ; if(sound > 50){ status = "COOLING"; } else{ status = "STANDBY"; } var desiredState = { state: { desired: { hvacStatus: status } } }; // デバイスシャドウを書き込む var params = { thingName: thingName, payload: JSON.stringify(desiredState) }; iotdata.updateThingShadow(params, function (err, data) { if (!err) { context.succeed(); } else { context.fail(err); } }); } else{ console.log("getThingShadow error "+err); } }); console.log('exports.handler end'); };
M5Stack Core2 for AWSでSmart-Thermostatの実行
M5Stack Core2 for AWSをリセットして実行します。Serial Monitorの出力を次に示します。ログ「Delta – hvacStatus state changed to COOLING」により、「hvacStatus」の値が「STANDBY」から「COOLING」に変化したcallbackが発生したことが確認できます。
・・・ ?[0;32mI (10762) I2S: PLL_D2: Req RATE: 44100, real rate: 90909.000, BITS: 16, CLKM: 11, BCK: 5, MCLK: 11.338, SCLK: 2909088.000000, diva: 64, divb: 21?[0m ?[0;32mI (11072) MAIN: *****************************************************************************************?[0m ?[0;32mI (11072) MAIN: On Device: roomOccupancy false?[0m ?[0;32mI (11072) MAIN: On Device: hvacStatus STANDBY?[0m ?[0;32mI (11082) MAIN: On Device: temperature 70.634026?[0m ?[0;32mI (11082) MAIN: On Device: sound 22?[0m ?[0;32mI (11092) MAIN: Update Shadow: {"state":{"reported":{"temperature":70.634026,"sound":22,"roomOccupancy":false,"hvacStatus":"STANDBY"}}, "clientToken":"xxxxxx-0"}?[0m ?[0;32mI (13402) MAIN: *****************************************************************************************?[0m ?[0;32mI (13402) MAIN: Stack remaining for task 'aws_iot_task' is 2036 bytes?[0m ?[0;32mI (14422) MAIN: ************* hvac_Callback?[0m ?[0;32mI (14422) MAIN: Delta - hvacStatus state changed to COOLING?[0m ?[0;32mI (14422) MAIN: setting side LEDs to blue?[0m ?[0;32mI (14452) MAIN: Update accepted?[0m ?[0;32mI (14602) MAIN: *****************************************************************************************?[0m ?[0;32mI (14602) MAIN: On Device: roomOccupancy false?[0m ?[0;32mI (14602) MAIN: On Device: hvacStatus COOLING?[0m ?[0;32mI (14612) MAIN: On Device: temperature 76.786415?[0m ?[0;32mI (14612) MAIN: On Device: sound 19?[0m ?[0;32mI (14622) MAIN: Update Shadow: {"state":{"reported":{"temperature":76.786415,"sound":19,"roomOccupancy":false,"hvacStatus":"COOLING"}}, "clientToken":"xxxxxxx-1"}?[0m ?[0;32mI (14652) MAIN: *****************************************************************************************?[0m ?[0;32mI (14652) MAIN: Stack remaining for task 'aws_iot_task' is 2036 bytes?[0m ?[0;32mI (15672) MAIN: Update accepted?[0m ?[0;32mI (15852) MAIN: *****************************************************************************************?[0m ?[0;32mI (15852) MAIN: On Device: roomOccupancy false?[0m ?[0;32mI (15852) MAIN: On Device: hvacStatus COOLING?[0m ?[0;32mI (15862) MAIN: On Device: temperature 67.747856?[0m ?[0;32mI (15862) MAIN: On Device: sound 6?[0m ?[0;32mI (15872) MAIN: Update Shadow: {"state":{"reported":{"temperature":67.747856,"sound":6,"roomOccupancy":false,"hvacStatus":"COOLING"}}, "clientToken":"xxxxxxx-2"}?[0m ?[0;32mI (15902) MAIN: *****************************************************************************************?[0m ・・・
AWS IoT Core マネジメントコンソールに移動し、「管理」「モノ」から対応するモノ「xxxxx」を選択し、表示された「Device Shadow」タブを選択し、「Classic Shadow」を選択すると次のように表示されます。
CloudWatchマネジメントコンソールに移動し、「ログ」「ロググループ」から対応する「/aws/lambda/thermostatlambda1」を選択し、表示されたログを確認します。Lambda 関数「thermostatlambda1」により読み出されたDevice Shadowの内容が表示されます。Lambda 関数「thermostatlambda1」からDevice Shadowの内容が更新されていることが確認できます。