AWS IoT thing shadowの取得と更新


Thing shadowの読み書きを行う方法はいくつかある。それらのまとめ。

イメージ

アプリケーション側 (Eg. Lambda)

準備

Lambda関数を作成しAWS IoT Dataへのアクセス権限を割り当てる。

基本動作

// 初期化
const iotdata = new aws.IotData( { endpoint: <エンドポイント> } );

const params = {
    thingName: <thing名>,
    payload: <更新内容>
};
// データ更新
/// 非同期で更新する。
const res = iotdata.updateThingShadow(params, (err, data) => {
    // 実行後のコールバック関数
});
/// 同期的に更新したい。
const res = await iotdata.updateThingShadow(params).promise();

// データ取得
const params = {
    thingName: <thing名>
};
let res = await iotdata.getThingShadow(params).promise();
console.log(res)

同期的な更新ではAWS.Response()オブジェクトのpromise()を利用。
イベントハンドラの第三引数callbackを用いる方法もあるが面倒。
公式ドキュメント:AWS.Response
公式ドキュメント:promise

イベント駆動な呼び出し

shadowの特定の変化をトリガしてLambdaを実行するようにRuleActionを設定する。
デバイス側からのreportedの値が変化したことや一定の閾値を超えたことを検出して特定のActionを実行する。
ActionはLambdaに限らず種々のAWSサービスを利用できる。

設定方法などはここでは省略、以下参照。

デバイス側

同じくaws-sdkを用いることもできるが、デバイスに入れるモジュールサイズに制限がある環境等ではaws-sdkは70MBほどと大きすぎるためAWS IoT特化のsdkを利用。

準備

shadowと通信するための準備。
thingを作成済みであり、作成時に生成した或いは登録した証明書はローカルに落としている前提とする。

var awsIot = require('aws-iot-device-sdk');

var thingShadows = awsIot.thingShadow({
    keyPath: "./xxxxxxxxxx-private.pem.key",
    certPath: "./xxxxxxxxxx-certificate.pem.crt",
    caPath: "./rootCA.pem",
    clientId: "<thing名>",
    host: "xxxxxxxxxxxxx-xxx.iot.ap-northeast-1.amazonaws.com"
});

keyPathおよびcertPathには証明書のパスを指定する。
caPathはルート証明書。公式から落としてきて保存したファイル名とパスを指定する。clientIdはthing名、hostはエンドポイント名である。エンドポイントはAWS IoTコンソールのサイドバーにある設定から参照できる。もしくは、各thingの相互作用の項目からも確認可能。

基本動作

thingShadows.on('connect', function () {
    // AWS IoTのthingとの接続時の処理をこの中で書く。
    thingShadows.register(<thing名>, {}, function () {
        // 登録作業。
    });
}

thingShadows.on('status',
    function (<thing名>, stat, clientToken, stateObject) {
        // shadowの取得や変更はstatus変化として扱われこのイベントを受け取る。(パラメータのstatはstateが来る。)
        // stateObjectにshadowの値が含まれる。
    }
);

thingShadows.on('delta',
    function (<thing名>, stat, clientToken, stateObject) {
        // "desired"と"reported"に差異が生じた場合にはこのイベントを受け取る。
        // なお、stateObjectにはdelta部分のみ含まれる。
    }
);

// shadow全取得 → なお、取得する値は上記の'state'イベントとして受け取る。
thingShadows.get(<thing名>);

イベント駆動な呼び出し

上記のdeltaを利用。

ほか

thingを作成した初期のshadowにはwelcomeの様な適当な値が入っていてコンソールの編集から削除するも消えなくて地味に苦労する。shadowは直接消して削除するのではなく値にnullを指定して更新してあげることで削除できるのでその様に更新すると初期のwelcomeを消すことができる。
なお、中の要素が全てなくなるとdesiredreportedのキー自体がなくなる。 また、これはdeltaでトリガすることができないので注意。

公式sdk資料