この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
CX事業本部の平内(SIN)です。
以前、下記のような記事を書きました。 こちらは、ブラウザ上で、aws-iot-device-sdkを使用して、AWS IoT Coreのメッセージブローカーをsubscribeし、特定のTopicが到着した時点で、ブラウザを更新するものでした。
やってることは、全く同じなのですが、今回は、これをAWS Amplify(以下、Amplify)で作成してみました。使用したウェブフレームワークは、Veu.jsです。
Amplifyでは、ライブラリAWSIoTProviderを使用することで、簡単にPub/Subが可能です。
Amplify Libraries AWSIoTProvider
また、権限については、AmplifyにAuthカテゴリを追加することで、CognitoのFederated Identitiesが利用可能なので、未認証IDを許可して、特定のトピックをSubscribeするだけのポリシーを追加しています。
「データ更新等に伴い表示を書き換える」というような要件だと、Amplify+AppSyncでGraphQLのSubscriptionで書くと、綺麗に仕上がりそうですが、今回は、あくまでMQTTと飛ばすことを目的として作業していることを、ご了承ください。
2 Vue.js
使用したVue CLIは、Ver 4.5.12 でした。
% vue --version
@vue/cli 4.5.12
プリセットにデフォルトの Default ([Vue 2] babel, eslint) を指定してプロジェクト()を生成しています。
% vue create browser_refresh_sample
? Please pick a preset: (Use arrow keys)
❯ Default ([Vue 2] babel, eslint)
Default (Vue 3 Preview) ([Vue 3] babel, eslint)
Manually select features
・・・略・・・
? Successfully created project browser_refresh_sample.
? Get started with the following commands:
$ cd browser_refresh_sample
$ yarn serve
この後、プロジェクトのフォルダ内で作業進めます。
% cd browser_refresh_sample
3 Amplify
amplifyの方は、4.50.0となっています。
% amplify --version
4.50.0
amplifyの初期化の方も、全てデフォルト設定です。
% amplify init
? Enter a name for the project browserrefreshsample
? Initialize the project with the above configuration? Yes
Using default provider awscloudformation
? Please choose the profile you want to use developer
・・・略・・・
Your project has been successfully initialized and connected to the cloud!
・・・略・・・
続いて、authカテゴリを追加してpushしました。
% amplify add auth
❯ Default configuration
❯ Username
❯ No, I am done.
% amplify push
・・・略・・・
✔ All resources are updated in the cloud
% amplify status
Current Environment: dev
| Category | Resource name | Operation | Provider plugin |
| -------- | ---------------------------- | --------- | ----------------- |
| Auth | browserrefreshsample0ec00635 | No Change | awscloudformation |
Cloud Formationのコンソールを確認するとベースのスタックと、Authカテゴリのスタックが作成されていることを確認できます。
4 ポリシー
Authカテゴリで追加されたスタックのリソース情報からIdentittyPoolのリンクを辿り、CognitoのIDプールの画面を開きます。
「認証されていないIDに対してアクセスを有効にする」にチェックを入れます。
未認証時に適用されるロールに、必要最小限の権限付与ということで、クライアントID、browser_refresh_sample_idからの接続と、トピックbrowser_refresh_sample_topicのサブスクライブと受信だけを許可しています。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iot:Connect"
],
"Resource": [
"arn:aws:iot:ap-northeast-1:*:client/browser_refresh_sample_id"
]
},
{
"Effect": "Allow",
"Action": [
"iot:Subscribe"
],
"Resource": [
"arn:aws:iot:ap-northeast-1:*:topicfilter/browser_refresh_sample_topic"
]
},
{
"Effect": "Allow",
"Action": [
"iot:Receive"
],
"Resource": [
"arn:aws:iot:ap-northeast-1:*:topic/browser_refresh_sample_topic"
]
}
]
}
5 コード
最初に、ライブラリAWSIoTProviderを使用できるように、モジュールをインストールしています。
npm i aws-amplify @aws-amplify/pubsub
npm i core-js@latest
Vue.jsのApp.vueは、下記のように書き換えました。mounted: でMQTTをサブスクライブしています。
<template>
<div id="app">
{{ time }}
</div>
</template>
<script>
import awsconfig from './aws-exports'
Amplify.configure(awsconfig)
import Amplify, { PubSub } from 'aws-amplify';
import { AWSIoTProvider } from '@aws-amplify/pubsub/lib/Providers';
Amplify.addPluggable(new AWSIoTProvider({
aws_pubsub_region: 'ap-northeast-1',
aws_pubsub_endpoint: 'wss://xxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com/mqtt',
clientId: 'browser_refresh_sample_id'
}));
export default {
name: 'App',
data: () => {
return {
time: ""
}
},
mounted: async function () {
PubSub.subscribe('browser_refresh_sample_topic').subscribe({
next: data => {
console.log('Message received', data)
//location.reload()
},
error: error => console.error(error),
close: () => console.log('Done'),
});
},
created : function(){
let currentdate = new Date()
this.time = currentdate.getHours() + ':' + currentdate.getMinutes() + ':' + currentdate.getSeconds() + ' update.'
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Topicにメッセージを送ってみると、ブラウザ側で反応していることが確認できます。
Topicが受信できていることを確認できたら、location.reload()を有効にして、トピック到着で、ブラウザをリロードします。
mounted: async function () {
PubSub.subscribe('browser_refresh_sample_topic').subscribe({
next: data => {
console.log('Message received', data)
// ↓この行を有効にする
location.reload()
},
error: error => console.error(error),
close: () => console.log('Done'),
});
},
6 Lambda
Topicを送信するために作成したLambdaは、以下の通りです。Lambdaの権限に、IoT CoreへのPublishの権限追加が必要です。
exports.handler = async (event) => {
// TODO implement
const endpoint = 'xxxxxxxxxxxx-ats.iot.ap-northeast-1.amazonaws.com';
const topic = "browser_refresh_sample_topic"
const aws = require('aws-sdk');
const region = 'ap-northeast-1';
var iotdata = new aws.IotData({
endpoint: endpoint,
region: region
});
var params = {
topic: topic,
payload: '{"action":"refresh"}',
qos: 0
};
let result = await iotdata.publish(params).promise();
console.log(result);
};
7 最後に
今回は、MQTTのPub/SubでLambdaとブラウザの連携を確認してみました。最初に、話した通り、情報の更新に伴う、画面の更新であれば、MQTTをわざわざ利用する必要なありませんが、MQTTでも、色々連携できれば、応用範囲が広がるように感じています。