【祝ヨーロッパ上陸】AWS CloudFormationを使ってAWS IoT Buttonの環境を構築する

Amazonにはお気に入りの商品をワンプッシュで注文するAmazonダッシュボタンというサービスがあります。 これをプログラマブルに制御可能にした AWS IoT Buttonがアメリカで先行発売され、2017年6月からはヨーロッパでも利用可能になりました。

Announcing availability of the AWS IoT Button in Europe | What’s New at AWS

筆者が滞在するドイツのAmazonでも購入可能になったため、早速注文して触ってみました。

AWSマネジメントコンソールの操作で環境を構築する手順は次のブログを参照下さい

【開封の儀 in バンクーバー】AWS IoT Buttonを使って東京リージョンのAWS IoTを動かしてみる

AWS IoT Button を購入する

ヨーロッパでは

  • イギリス
  • ドイツ
  • フランス
  • イタリア
  • スペイン

のAmazon からいつもと同じ手順で購入します。

iot-button

通常は€24.99ですが、筆者が購入した時は€21.99でセールをしていました。

完成形

今回は AWS IoT のクイックスタート「AWS IoT ボタンの AWS CloudFormation クイックスタート」の手順をさらい、ダッシュボタンをクリックすると、Eメール通知されるシステムを構築します。

aws iot button-cfn-architecture

作業の流れ

以下の流れで作業します

  1. AWS IoT ボタンの DSNを控える
  2. AWS IoT 証明書を作成
  3. 証明書以外の AWS のリソースを CloudFormation で作成
  4. AWS IoT ボタンを設定
  5. ボタンを押して疎通確認

AWS IoT ボタンの DSN を控える

購入した AWS IoT ボタンの device serial number (DSN) を確認します。

DSNは16桁の英数字で構成され

  • ケースのバーコード下
  • ボタンの裏側

で確認できます。

IoT 証明書を作成

AWS IoTではX.509のクライアント証明書でAWSと認証します。その証明書をマネジメントコンソールから作成します。

AWS_IoT_01

AWS IoT の「Security→Certificates」に移動し「Create」ボタンをクリックします。

AWS_IoT_02

  • One-click certificate creation (recommended)
  • Create with CSR
  • Use my certificate

の3種類の内、一つ目の「One-click certificate creation」で証明書を作成します。

AWS_IoT_03

Certificate、private keyをダウンロードし、[Activate] を選択します。

作成した証明書の「Details」ページに移動し、証明書の ARN を控えます

AWS_IoT_04

[Registry]->[Things]->[Interact]からHTTPSのエンドポイントを確認します。

AWS_IoT_Things_Endpoint

このエンドポイントを控えます。

証明書以外の AWS のリソースを CloudFormation で作成

以下のCloudFormation用 JSON テンプレートを「AWSIoTButtonQuickStart.template」と言う名前で保存します。

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Creates required AWS resources to allow an AWS IoT button to send information through an Amazon Simple Notification Service (Amazon SNS) topic to an email address.",
  "Parameters": {
    "IoTButtonDSN": {
	  "Type": "String",
	  "AllowedPattern": "G030JF05[0-9][0-5][0-9][1-7][0-9A-HJ-NP-X][0-9A-HJ-NP-X][0-9A-HJ-NP-X][0-9A-HJ-NP-X]",
	  "Description": "The device serial number (DSN) of the AWS IoT Button. This can be found on the back of the button. The DSN must match the pattern of 'G030JF05[0-9][0-5][0-9][1-7][0-9A-HJ-NP-X][0-9A-HJ-NP-X][0-9A-HJ-NP-X][0-9A-HJ-NP-X]'."
	},
	"CertificateARN": {
	  "Type": "String",
	  "Description": "The Amazon Resource Name (ARN) of the existing AWS IoT certificate."
	},
	"SNSTopicName": {
	  "Type": "String",
	  "Default": "aws-iot-button-sns-topic",
	  "Description": "The name of the Amazon SNS topic for AWS CloudFormation to create."
	},
	"SNSTopicRoleName": {
	  "Type": "String",
	  "Default": "aws-iot-button-sns-topic-role",
	  "Description": "The name of the IAM role for AWS CloudFormation to create. This IAM role allows AWS IoT to send notifications to the Amazon SNS topic."
	},
	"EmailAddress": {
	  "Type": "String",
	  "Description": "The email address for the Amazon SNS topic to send information to."
	}
  },
  "Resources": {
    "IoTThing": {
      "Type": "AWS::IoT::Thing",
      "Properties": {
        "ThingName": {
		  "Fn::Join" : [ "",
		    [
		      "iotbutton_",
              { "Ref": "IoTButtonDSN" }
			]
		  ]
		}
      }
    },
	"IoTPolicy": {
      "Type" : "AWS::IoT::Policy",
      "Properties": {
        "PolicyDocument": {
		  "Version": "2012-10-17",
          "Statement": [
            {
              "Action": "iot:Publish",
              "Effect": "Allow",
              "Resource": {
			    "Fn::Join": [ "",
		          [
		            "arn:aws:iot:",
					{ "Ref": "AWS::Region" },
					":",
					{ "Ref": "AWS::AccountId" },
					":topic/iotbutton/",
					{ "Ref": "IoTButtonDSN" }
			      ]
		        ]
			  }
            }
          ]
        }
      }
    },
	"IoTPolicyPrincipalAttachment": {
      "Type": "AWS::IoT::PolicyPrincipalAttachment",
      "Properties": {
        "PolicyName": {
		  "Ref": "IoTPolicy"
		},
		"Principal": {
		  "Ref": "CertificateARN"
		}
      }
    },
	"IoTThingPrincipalAttachment": {
      "Type" : "AWS::IoT::ThingPrincipalAttachment",
      "Properties": {
        "Principal": {
		  "Ref": "CertificateARN"
		},
		"ThingName": {
		  "Ref": "IoTThing"
		}
      }
    },
	"SNSTopic": {
      "Type": "AWS::SNS::Topic",
	  "Properties": {
	    "DisplayName": "AWS IoT Button Press Notification",
	    "Subscription": [
		  {
		    "Endpoint": {
			  "Ref": "EmailAddress"
			},
			"Protocol": "email"
		  }
		],
        "TopicName": {
		  "Ref": "SNSTopicName"
		}
      }
    },
	"SNSTopicRole": {
	  "Type": "AWS::IAM::Role",
	  "Properties": {
	    "AssumeRolePolicyDocument": {
		  "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "Service": "iot.amazonaws.com"
              },
              "Action": "sts:AssumeRole"
            }
          ]
		},
	    "Path": "/",
		"Policies": [
		  {
		    "PolicyDocument": {
			  "Version": "2012-10-17",
              "Statement": [
			    {
                  "Effect": "Allow",
                  "Action": "sns:Publish",
                  "Resource": {
				    "Fn::Join": [ "",
		              [
		                "arn:aws:sns:",
					    { "Ref": "AWS::Region" },
					    ":",
					    { "Ref": "AWS::AccountId" },
					    ":",
					    { "Ref": "SNSTopicName" }
                      ]
			        ]
		          }
				}
              ]
			},
			"PolicyName": {
			  "Ref": "SNSTopicRoleName"
			}
		  }
		]
	  }
	},
	"IoTTopicRule": {
      "Type": "AWS::IoT::TopicRule",
      "Properties": {
        "RuleName": {
		  "Fn::Join": [ "",
		    [
		     "iotbutton_",
		     { "Ref": "IoTButtonDSN" }
			]
		  ]
		},
		"TopicRulePayload": {
		  "Actions": [
		    {
		      "Sns": {
			    "RoleArn": {
			      "Fn::GetAtt": [ "SNSTopicRole", "Arn" ]
			    },
			    "TargetArn": {
			      "Ref": "SNSTopic"
			    }
			  }
			}
		  ],
		  "AwsIotSqlVersion": "2015-10-08",
          "RuleDisabled": false,
          "Sql": {
		    "Fn::Join": [ "",
		      [
		        "SELECT * FROM 'iotbutton/",
				{ "Ref": "IoTButtonDSN" },
				"'"
		      ]
			]
		  }
        }
      }
    }
  }
}

このテンプレートを利用して [Create Stack] から CloudFormation のスタックを作成します。

パラメーターには以下の情報を入力します。

パラメーター 備考
CertificateARN 証明書作成時に控えたARN
EmailAddress ボタン押下時に通知するメールアドレス
IoTButtonDSN IoTボタンのDSN
SNSTopicName CFnで作成するSNSトピック名
SNSTopicRoleName CFnで作成するSNSトピックのロール名

「Review」ページでは、画面下部の「I acknowledge that AWS CloudFormation might create IAM resources」にチェックを入れ「Create」ボタンでスタックを作成します。

  • ボタンに対応する IoT Thingの登録
  • AWS IoTにメッセージを送信するIoTポリシー
  • ボタンがAWS IoTと認証するための証明書の設定
  • 通知用 SNSトピックの作成
  • SNS通知するAWS IoTルールの作成

などが行われます

AWS IoT ボタンを設定

次に AWS IoT ボタンを設定します。

AWS IoT ボタンは Wi-Fi アクセスポイントになるため、この Wi-Fi に接続し、ネットワーク設定や証明書のインストールを行います。

  1. AWS IoTボタンが青く点灯するまで長押しします(5秒程度はかかります)
  2. 「Button ConfigureMe - XXX」という SSID が見つかるため、接続します。パスワードは デバイスシリアルナンバー (DSN) の末尾 8 文字です。
  3. http://192.168.0.1/index.html に接続します。
  4. 設定画面で以下の手順で設定

aws_iot_button_config

Wi-Fi Configuration:

ボタンが利用する Wi-Fi の接続情報を入力します。

AWS IoT Configuration:

「AWS IoT 証明書を作成」で作成した証明書をアップロードします。

また、[Registry]->[Things]->[Interact]で確認した HTTPS エンドポイントに合わせて

  • Endpoint Subdomain
  • Endpoint Region

を設定し、「Final Endpoint」が HTTPS エンドポイントと同一になっていることを確認します。

「By clicking this box, you agree to the AWS IoT Button Terms and Conditions.」をチェックし[configure]で設定完了です。

詳細は次のページを参照下さい

AWS Documentation » AWS IoT » Developer Guide » Getting Started with AWS IoT » Configure Your Device

ボタンを押して疎通確認

最後に疎通確認を行います

ボタンは3種類の押し方があります。

  • 1回押し
  • 2回押し
  • 長押し(1.5秒以上)

例えば「1回押し」をすると「AWS Notification Message」という件名で

{"serialNumber": "G030PT1234567890", "batteryVoltage": "1543mV", "clickType": "SINGLE", "configuration":"true"}

というような本文のメールが届きます。

"clickType": "SINGLE" とボタンの押し方も認識されています。

aws_iot_button_sns_mail

まとめ

AWS IoTドキュメントのクイックスタートを元にAWS CloudFormationを使ってAWS IoT Buttonの環境を構築しました。

今回のCloudFormationのテンプレートはIoT Buttonを疎通確認する上でほぼミニマムな構成となっているため

  • Lambda につなげる
  • DynamoDB に保存する

などの拡張をかんたんにできます。

デモやソリューション提供などで、同じ環境を何度も構築する人はこの CloudFormation をベースにするのがおすすめです。

参照