[小ネタ]AWS IoT EventsからLambdaへJSON形式のペイロードを渡す際の記述方法

AWS IoT EventsからLambdaへペイロードをJSON形式で渡す時困ったので紹介します。
2021.03.31

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

はじめに

CX事業本部の佐藤智樹です。

今回はタイトル通り AWS IoT EventsからLambdaへペイロードをJSON形式で渡す際の記述方法を紹介します。

以下の記事を確認するとわかりますが、IoT Events宛に送信されたペイロードをLambdaへ渡す際は、IoT Eventsの変数に格納するかカスタムペイロード機能を使わないと渡すことができません。具体的には以下の記事の「6.遷移後のイベント」と「9.アラート発生」を見てください。

変数の場合は1つずつアクションに設定することになるので、量が多い場合はかなり面倒になります。カスタムペイロードであれば複数データをまとめて渡すことができます。

Black Beltにカスタムペイロードの書き方は書いてあるのですが実例はあまりなく、特にAWS CDKに組み込む場合どうエスケープして良いのか書き方に悩んだので備忘録として記載します。

実際の記載方法

以下の記述で文字列(StringValueName)、数字(NumberValueName)、ブール値(FlagName)をLambdaに渡せます。iotEventsInputがインプット名になります。JSON全体を文字にしなければならないところが若干曲者です。

カスタムペイロード:

'{
  "StringValueName": "${$input.iotEventsInput.StringValue}",
  "NumberValueName": ${$input.iotEventsInput.NumberValueName},
  "FlagName": ${$input.iotEventsInput.FlagName}
}'

AWS CDKで検知器モデルのインプットも管理する場合は、以下のようにインプット名が「IotEventsInput」とするとIotEventsInput.inputNameの部分を${IotEventsInput.inputName}に変更してます。

export class IotEventsStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);
…
    const iotEventsInput = new iotEvents.CfnInput(this, "IotEventsInput", {
      inputName: "IotEventsInput",
      inputDefinition: {
        attributes: [
          { jsonPath: "StringValueName" },
          { jsonPath: "NumberValueName" },
          { jsonPath: "FlagName" },
        ],
      },
    });
…
      states:[
        {
          stateName: "any-state"
          onEnter: {
            events: [
              {
                eventName: "any-event",
                actions: [
                  {
                    lambda: {
                      functionArn:
                        "arn:aws:lambda:ap-northeast-1:<account-id>:function:function-name",
                      payload: {
                        contentExpression: `\'{
                                              \"StringValueName\": \"\${$input.${iotEventsInput.inputName}.StringValue}\",
                                              \"NumberValueName\": \${$input.${iotEventsInput.inputName}.NumberValueName},
                                              \"FlagName\": \${$input.${iotEventsInput.inputName}.FlagName}
                                            }\'`,
                        type: "JSON",
                      },
                    },
                  },
                ],
              },
            ];
          }
        }
…

所感

項目のエスケープがうまくいっている確認するために、検知器モデルの検証(CUIのstart-detector-model-analysisかAWSコンソールの「分析を実行」)だと分からなく何度も動作確認しました。大したことない内容に見えますが、同じようなことをする人が少しでも減るようにと思ったので共有します。ハートビート監視だけでなくアプリケーションの細かい状態管理で使用したい場合などに参考になれば幸いです。