3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ブラウザで Amplify の PubSub を使ってサーバからの push を受ける

Posted at

動機

MQTTを使用して、Lambdaからブラウザを更新する方法〜aws-iot-device-sdk(aws-iot-sdk-browser-bundle.js)を使用する場合〜 の例を自分でも試してみようと…の続き。

今見ると、純粋 JS 実装の aws-iot-device-sdk とネイティブライブラリで一部書き直された aws-iot-device-sdk-v2 とがあるが、ブラウザで使うのにネイティブは却下。 aws-iot-device-sdk だけかと思って npm trends 調べたら、人気なのは Amplify らしい…。ドキュメントがいまいち不親切で、やりたいことをどうやれば実現できるかよくわからなくて敬遠していたが、人間、長いものに巻かれるのも大事だ。

経過

  • Cognito の Identity Pool (IDプール) を用意して Enable access to unauthenticated identities (認証されていない ID に対してアクセスを有効にする) のチェックを on にする
  • 未認証ユーザに割り当てる IAM Role は iot:Connect, iot:Receive, iot:Subscribe の最低限のポリシーだけを付与する

この辺は くだんの記事 と同じ。で、未認証ユーザに subscribe させるのって、 amplify でどうやって書くんだ?ドキュメントの例は signin して認証済みユーザとして subscribe するものばかりで、案の定わけわからん。

こういうときは、ソースを見るしかない。 GitHub から clone してきてローカルでいろいろ探索してみる。どうやら、

  • Auth の config に region と identityPoolId だけ与えて放置すれば、 PubSub で必要になったときに暗黙に @aws-amplify/core の Credentials._setCredentialsForGuest() が呼ばれて、 guest 用の credentials ( accessKeyId, secretAccessKey, sessionToken を持つ未認証ユーザ向けの一時 credentials ) が勝手に用意されるらしい
  • Amplify をまるごと import しなくても、 PubSub にも addPluggable() があるので、 AWSIoTProvider はそこで設定すればよい
  • subscribe したときの next イベントには、 publish されてきた payload だけではなく provider の情報も一緒に入ってくるので、選り分けないといけない

ということが見えてきた。 いや、そりゃ OSS だから自分でソース見りゃいいってのはそうなんですが、もう少しどこかに書いておいてくれても…。

結果

import Auth from '@aws-amplify/auth';
import PubSub from '@aws-amplify/pubsub';
import { AWSIoTProvider } from '@aws-amplify/pubsub/lib/Providers';

const AWS_REGION = 'ap-northeast-1';
const IDENTITY_POOL_ID = 'ap-northeast-1:XXXXXXXXXXXXXXXXXXXXXX';
const ENDPOINT = 'yyyyyyyyyyy.iot.ap-northeast-1.amazonaws.com';
const TOPIC = 'hoge';

const subscribeJob = async () => {
  Auth.configure({
    region: AWS_REGION,
    identityPoolId: IDENTITY_POOL_ID,
  });

  PubSub.configure();
  PubSub.addPluggable(new AWSIoTProvider({
    aws_pubsub_region: AWS_REGION,
    aws_pubsub_endpoint: `wss://${ENDPOINT}/mqtt`,
  }));

  const onMessage = ({ provider, value }) => {
    console.log('> ' + JSON.stringify(value));
  };
  const onError = (err) => {
    console.error(err);
  };
  const onClose = () => {
    console.log('Closed');
  }

  PubSub.subscribe(TOPIC).subscribe({
    next: onMessage,
    error: onError,
    close: onClose,
  });

  console.log('subscribe success');
};

export default subscribeJob;

あとはこの関数をどこか初期化にふさわしい場所で呼び出す ( React なら App.js で useEffect() するとか) だけ。 AWS IoT のコンソールでテスト publish すると、ブラウザのコンソールに publish したメッセージが表示される。めでたしめでたし。

確かに、 aws-iot-device-sdk よりも amplify のほうがコードは簡単になっている。が、このとっつきにくさは何なんだろう…。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?