AWS IoT エンタープライズボタンでファミレスのチャイムっぽいのを作る 

# はじめに
AWS IoT Enterprise Buttonと言うものがあると知り、買ってみたので何かしらサンプル的なものを作ってみたいと思いました。
ボタンを押してアクションするもので実用性がありそうなものと一番最初に思い付いたのがこれでした。

# 仕組みについて
ボタンを押すとlambda関数が実行できるので、lambdaからモバイル端末へのプッシュを送り
プッシュ通知を受けたときに音とボタンに設定された番号を表示するようなものを作ります。

# AWS IoT Enterprise Buttonの登録
まずはボタンの登録ですが、これに関しては先人の方たちが丁寧にご解説いただいているのでそちらをご参考に頂ければと思います。
[AWS IoT 1-Click と IoT エンタープライズボタンのセットアップ&動作確認 - Qiita](https://qiita.com/hayao_k/items/d36d4b2579d0bbbe21a9)

# プッシュ通知について
今回はFCM(Firebase Cloud Messaging)を使って実装しました。
プロジェクトの作成や実際のプッシュに関しては色々と詳しい記事などがあると思いますので割愛します。

# モバイル端末側の実装
今回はAndrodで実装しましたが単純なプッシュなので
端末側はiOSでもやることは特に変わらないかと思います。
こちらの記事などが参考になるかと思います。
[AndroidアプリにFirebase Cloud Messagingを実装する(1) - アプリとFirebaseを接続する - Qiita](https://qiita.com/outerlet/items/e3fe96a3d1e15ed42573)

汎用的に使えるようにするには色々と考える必要はあると思うが、とりあえず`FirebaseInstanceId.getInstance().getToken()`した値をメモっておいてサーバ側実装に直打ちする。
プッシュに関しては`onMessageReceived`の`remoteMessage.getData()`で
プッシュを受けたときに設定されたパラメータを拾って、
画面に表示して音を鳴らすだけの実装となっています。

# lambda関数の実装
aws lambdaで使える言語はいくつかありますが、今回はNode.jsで実装しました。
今回、席ごとにチャイムを置くような想定なので、ボタンごとに席番号を持たせて
どの席のボタンなのかを通知する必要があります。
AWS IoT1-Clickによって設定できる、プレイスメントに属性値を設定することによって
lambda側でattributesとしてパラメータを受けることができるのでそれをパラメータとして送ります。仮に属性の名前「num」として設定しています。

```js
// firebase admin sdk
var admin = require('firebase-admin');

var serviceAccount = require('path/to/serviceAccountKey.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
});

var registrationToken = 'hogehoge';

// ボタンからのイベント受け取り
exports.handler = function(event, context) {

  // 設定したプレイスメントのパラメータ値を受け取る
  var num = event['placementInfo']['attributes']['num'];

  // プッシュ通知メッセージの設定
  var message = {
    data: {
      num: num
    },
    token: registrationToken
  };

  admin.messaging().send(message)
  .then((response) => {
    console.log('Successfully sent message:', response);
    context.done();
  })
  .catch((error) => {
    console.log('Error sending message:', error);
    context.done();
  });
}
```

serviceAccountKey.jsonについてはFirebaseからダウンロードしてきたものです。
lambdaでfirebase-adminを使用する際ですが、lambdaモジュールを使用するにはおそらくzipファイルでアップロードするのが楽だと思われます。
コードエントリタイプで.zipファイルをアップロードするとzipの中身が展開されて反映されます。
なので、
ローカルで動くようなものを作ってnode_modulesごと圧縮してアップロードするような形にしました。
丸ごと送っても良いかと思いますが、容量が多いとS3経由の方が良いよと書いてあって面倒だったので必要モジュールのみ送ることにしました。
firebase-adminに必要なモジュールを一応メモしておきます。
buffer-equal-constant-time、ecdsa-sig-formatter、firebase-admin、jsonwebtoken、jwa、jws、lodash.includes、lodash.isboolean、lodash.isinteger、lodash.isnumber、lodash.isplainobject、lodash.isstring、lodash.once、ms、node-forge、safe-buffer、xtend

# 今回作ったもの
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">AWS IoT Enterprise Buttonでファミレスのチャイムっぽいののサンプル作りました。 <a href="https://t.co/SXB9n4Z4YS">pic.twitter.com/SXB9n4Z4YS</a></p>&mdash; razuma (@razuma4) <a href="https://twitter.com/razuma4/status/1018917872427417600?ref_src=twsrc%5Etfw">2018年7月16日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 作ってみて思ったこと
lambdaでの実装は面倒なので、機能に関しては別サーバで実装させてlambdaからはそこのAPI叩くだけにすればあまり面倒なことを考えなくて良いのかな？と思いました。汎用的に使えるし、API変えるだけなのでaws iot EnterpriseButtonとしての使い方は楽になる。サーバレスのlambda本来の使い方としてどうなのってところはあるがそんな感じでも作ってみたい。
ものに関しては機能やUIをしっかりとしたものにすれば、もしかしたら需要があるのかな？とかもちょっと思ってみたりするので製品っぽくしてみたい気持ちもあり。

# おわりに
サンプルを作成してみて、AWS IoT Enterprise Buttonの基本的な仕組みや実装の仕方が
わかったので、今後また何か新たに面白いものが作れたら良いかなと思っています。
あと1個の値段が高いのでもうちょっと安くなって欲しい・・・。
初めてのQiitaへの投稿だったので文章や説明で至らない点もあるかと思いますが、今後も何かしらアウトプットしていければと思っています。ありがとうございました。