michimani.net

AWS IoT エンタープライズボタンで Lambda 関数を実行して Slack にメッセージを送信してみた

2019-07-09

先日お邪魔した 目黒JavaScriptもくもく会 で AWS IoT エンタープライズボタン というデバイスの話が出ていました。どうやら AWS Lambda をはじめとした AWS の各サービス (SNS とか DynamoDB とか) と非常に簡単に連携できる IoT デバイスらしいということなので、とりあえず買って試してみました。

目次

AWS IoT エンタープライズボタン とは

AWS IoT エンタープライズボタン

AWS IoT ボタンは、Amazon Dash Button ハードウェアをベースにしたプログラミング可能なボタンです。このシンプルな Wi-Fi デバイスは設定が簡単で、特定のデバイス向けのコードを記述することなく、AWS IoT Core、AWS Lambda、Amazon DynamoDB、Amazon SNS、およびその他多くのアマゾン ウェブ サービスの使用を開始する開発者向けに設計されています。

Amazon Dash Button は既にに販売が終了していますが、ベースは Amazon Dash Button で、ボタンを押した時のアクションをハックできるのが AWS IoT エンタープライズボタン です。公式の説明文にもあるように、 Wi-Fi でインターネットに接続し、AWS の各種サービスと連携することができます。連携できるサービスには AWS Lambda も含まれています。Lambda で関数を実行できるということは、ほぼ何でもできるということなので、アイデア次第では色んなことに使えそうです。

AWS IoT エンタープライズボタン は普通に Amazon で売っているので、誰でも購入できます。

今回やること

AWS IoT エンタープライズボタンをトリガーにして、 Slack にメッセージを送信する Lambda 関数を実行してみます。

手順としては下記の通りですが、 Slack の Webhook URL の取得については割愛します。

  1. Slack の Webhook URL を取得
  2. Slack にメッセージを送信する Lambda 関数を作成
  3. AWS IoT エンタープライズボタン を AWS IoT 1-Click に登録
  4. AWS IoT 1-Click で Lambda 関数の呼び出しを設定
  5. AWS IoT エンタープライズボタン を押す

実際の手順

では、手順をひとつずつみていきます。
ちなみに今回は 東京リージョン を使います。

1. Slack の Webhook URL を取得

割愛します。

2. Slack にメッセージを送信する Lambda 関数を作成

まずは Slack にメッセージを送信する Lambda 関数を作成します。
Python 3.7 で実装します。

import json
import logging

from base64 import b64decode
from urllib.request import Request, urlopen
from urllib.error import URLError, HTTPError

SLACK_CHANNEL = 'iot-test'
HOOK_URL = 'https://hooks.slack.com/services/ABCDEFGHI/JKLMNOPQR/stuvwxyz1234567890abcdef'

logger = logging.getLogger()
logger.setLevel(logging.INFO)


def lambda_handler(event, context):
    logger.info("Event: " + str(event))
    message = str(json.dumps(event, indent=2))
    
    slack_message = {
        'channel': SLACK_CHANNEL,
        'icon_emoji': ':robot_face:',
        'attachments': [
            {
                'color': '#6293ca',
                'fields': [
                    {
                        'value': "```\n%s\n```" % (message)
                    }
                ]
            }
        ]
    }

    req = Request(HOOK_URL, json.dumps(slack_message).encode('utf-8'))
    try:
        response = urlopen(req)
        response.read()
        logger.info("Message posted to %s", slack_message['channel'])
    except HTTPError as e:
        logger.error("Request failed: %d %s", e.code, e.reason)
    except URLError as e:
        logger.error("Server connection failed: %s", e.reason)

event で渡される辞書データを成形された json 文字列をメッセージとして送信するだけの関数です。

3. AWS IoT エンタープライズボタン を AWS IoT 1-Click に登録

次に AWS IoT エンタープライズボタン を IoT デバイスとして登録します。
登録には AWS の IoT 1-CLick というサービスと、 iOS/Android 向けに提供されている AWS IoT 1-Click アプリ (以下、アプリ) を使います。
AWS IoT 1-Click アプリは、 App Store および Google Store からダウロードします。今回は iOS 版を使いますが、 Android 版でもほぼ同じだと思います。

大まかな手順としては次の通りです。

  1. IoT 1-CLick でデバイス ID を入力する
  2. アプリを使ってデバイスを登録する

ではこれもひとつずつ見ていきます。

1. IoT 1-CLick でデバイス ID を入力する

AWS のマネジメントコンソールから IoT 1-Click を探して IoT 1-Click のオンボードボードを表示します。

IoT 1-Click

表示したら、 デバイスの登録 ボタンを押して デバイスID を入力します。

IoT 1-Click オンボード
IoT 1-Click デバイス ID 入力

登録ボタンを押すとデバイスの反応待ちになるので、一旦そのままにしておきます。

2. アプリを使ってデバイスを登録する

アプリ起動後は、上で操作したものと同じ AWS アカウント (IAM IAM ユーザ) でログインします。また、リージョンは アジアパシフィック (東京) を選択しておきます。
そして、セットアップ画面の Wi-Fi を設定 ボタンから AWS IoT エンタープライズボタンの Wi-Fi設定をします。

IoT 1-Click アプリ セットアップ

デバイス ID は手入力、または、 AWS IoT エンタープライズボタン が入っていた箱の側面に貼ってあるバーコードを読み取ることで入力可能です。私は何の躊躇もなしに外箱を捨ててしまったので、手入力しました。外箱はしっかり残しておきましょう。
ちなみにデバイス ID は AWS IoT エンタープライズボタン本体の裏側に記載されているので、万が一箱を捨ててしまっても大丈夫です。ただし、めちゃくちゃ字が小さいです。

IoT 1-Click アプリ ボタン待ち

デバイス ID を入力するとペアリングが始まるので、AWS IoT エンタープライズボタン を 6 秒間 (青い光が点滅するまで) 押します。アプリ側で認識されると、続いて Wi-Fi の設定に移ります。(キャプチャがありません、ご了承ください)
接続したい SSID をセレクトボックスから選択して、パスワードを入力します。すると「Wi-Fi 設定中です」みたいなメッセージが表示されてローディングアニメーションが表示されます。
ここでそのまま放置すると接続エラーになってしまう ので、ローディングアニメーションが表示されたら AWS IoT エンタープライズボタン を 1 回押します。

Wi-Fi 設定が完了すると、マネジメントコンソール上でも認識されるので、デバイスの登録は完了です。
ちなみにアプリ側での Wi-Fi 設定は途中でキャンセルするとデバイス ID の入力からやり直しになります。なので、箱を捨ててしまっているとかなり面倒なことになります。(なりました)

4. AWS IoT 1-Click で Lambda 関数の呼び出しを設定

デバイスが登録できたら、あとはマネジメントコンソール上でプロジェクトの設定をします。
ここで出てくるキーワードがいくつかあるので、それぞれの説明を書いておきます。

プロジェクト

IoT デバイスで何かをするためのプロジェクトです。これが大元です。

プレイスメント

IoT デバイスを配置する場所 (概念) です。
プロジェクト内に複数作成できます。
ひとつのプレイスメントには複数のデバイスを登録できますが、その最大数は後述するテンプレートに依存します。
また、複数のプレイスメントで同じデバイスを共有することはできません。例えば A と B のプレイスメントがある場合に、デバイス1 を A と B の両方に配置することはできません。

プレイスメントにはデバイスと合わせて、属性 の形で任意の情報を持たせることができます。

テンプレート

デバイステンプレート、プレイスメント という項目で構成されています。
一つのプロジェクトに対して一つ存在します。

デバイステンプレートは、そのプロジェクトで使うデバイスのテンプレートを 1 個以上作成します。
例えば、 SMS を送信するデバイス、 Email を送信するデバイス、 Lambda 関数を実行するデバイス という 3 つのデバイステンプレートを作成することができます。

プレイスメントは前述したとおり 属性 と 値 で任意の情報を持たせることができるので、そのテンプレートを作成します。個別のプレイスメントでそれらを上書きすることができます。


…と書きましたが、文字だけでは伝わりにくいので実際に作ったプロジェクトのテンプレートとプレイスメントの内容を見ながら説明を加えてみます。

まずはテンプレートです。

IoT 1-Click プロジェクト テンプレート

デバイスは 3 つ登録しています。それぞれ名前の通りですが、 SMS を送信するデバイス、 Email を送信するデバイス、 Lambda 関数を実行するデバイス です。テンプレートではあくまでも何かをするデバイスの枠を用意しているというイメージです。
テンプレート内のプレイスメントですが、ここで設定しているものは全て必須属性となっています。プレイスメントは基本的に任意の属性・値を設定できますが、今回のように SMS 送信、 Email 送信 を行うデバイスを登録する場合は、それぞれ SMS 送信先電話番号とメッセージ内容、 Email 送信先メールアドレスと件名と本文 が必須の属性となります。もちろん、これら以外に任意の属性を追加することも可能です。

続いて、プレイスメントです。

IoT 1-Click プロジェクト プレイスメント

テンプレートで設定したデバイス 3 つの枠はありますが、デバイス ID が空欄になっています。つまり、どの枠にもデバイスが登録されていません。このように、必ずしもデバイスを登録する必要はなく、例えばこのプレイスメントでは SMS 送信のデバイスだけを登録する、といったことが可能です。
また、プレイスメントごとに属性を変えることで、このプレイスメントに登録されたデバイスが押された場合には この電話番号へ SMS を送るといった形で、プレイスメントごとに詳細な設定をすることができます。(SMS 送信だと phoneNumber の値を変更する)

ただし、実行する Lambda 関数はデバイステンプレートで指定したものから変更することができません。なので、もしプレイスメントごとに実行する Lambda 関数を変更したい場合は、 A という関数を実行するデバイス、 B という関数を実行するデバイス…といった形でデバイステンプレートを設定して、各プレイスメントで実行したいデバイステンプレートにデバイスを登録するのが良いと思います。


前置きが長くなりましたが、実際にプロジェクトを作成していきます。基本的に上で説明した設定を埋めていく感じです。
サイドメニューの 管理 から プロジェクト を選択して 作成 ボタンからプロジェクトを作成します。

まずはプロジェクトの名前と説明を入力します。

IoT 1-Click プロジェクト作成 プロジェクト名

続いてテンプレートの設定です。
今回は Lambda 関数を実行するだけなので、デバイステンプレートには Lambda 関数実行用のデバイスを設定します。

IoT 1-Click プロジェクト作成 デバイステンプレート

Lambda 関数実行の場合は必須のプレイスメント属性は無いので、適当に属性と値を設定しておきます。

IoT 1-Click プロジェクト作成 テンプレート プレイスメント

これでプロジェクトは完成です。
引き続いてプレイスメントを作成します。

プレイスメントの作成では、プレイスメント名と、デバイステンプレートで用意したデバイスの枠にデバイスを設定、あとはプレイスメントの属性を設定します。

IoT 1-Click プレイスメント作成

で、今回の目的を達成するためのプロジェクトの設定が次のようになります。(上のキャプチャと名前が異なる部分があります)

IoT 1-Click プロジェクト サンプル テンプレート
IoT 1-Click プロジェクト サンプル プレイスメント

これでプロジェクトの作成とプレイスメントの設定が完了したので、あとは AWS IoT エンタープライズボタン を押すだけです…!

5. AWS IoT エンタープライズボタン を押す

ということで、とりあえず 1 回押してみます。すると数秒後に Slack にメッセージが飛んできます。

IoT 1-Click Slack message

これが IoT …。

上のキャプチャのとおりですが、 IoT 1-Click から Lambda に渡される event の内容はこんな json になっています。

{
  "deviceInfo": {
    "deviceId": "G030AB12345678CD",
    "type": "button",
    "remainingLife": 99.35,
    "attributes": {
      "projectRegion": "ap-northeast-1",
      "projectName": "MyProject",
      "placementName": "MyPlacement",
      "deviceTemplateName": "runLambda"
    }
  },
  "deviceEvent": {
    "buttonClicked": {
      "clickType": "SINGLE",
      "reportedTime": "2019-07-08T12:38:25.312Z"
    }
  },
  "placementInfo": {
    "projectName": "MyProject",
    "placementName": "MyPlacement",
    "attributes": {
      "floor": "99",
      "room": "999",
      "building": "9"
    },
    "devices": {
      "runLambda": "G030AB12345678CD"
    }
  }
}

とりあえず 1 回 と書いたのには訳があって、 AWS IoT エンタープライズボタン では次の 3 パターンの押し方を認識します。

そして、それぞれの押し方によって渡される event 内の deviceEvent.buttonClicked.clickTypeSINGLEDOUBLELONG になります。
Lambda 側で何か処理を分岐させる場合は、プレイスメントの属性と、このクリックタイプ を条件にすると良さそうです。

ちなみに deviceInfo.remainingLife は AWS IoT エンタープライズボタン の寿命になっています。ボタン自体は約 2,000 回押すことができると書かれていますが、プログラム上で扱うにはこの値を使って「あと○回押せます」とかもできそうです。

まとめ

AWS IoT エンタープライズボタン を使って Lambda を実行して Slack にメッセージを送ってみたという話でした。
いままで IoT 関係にはとっつきにくかったんですが、びっくりするくらい簡単に IoT っぽいことができました。Lambda が実行できるということはほぼなんでもできるということなので、発想次第では本当にいろんなことができそうです。

IoT 関係に踏み込みたいけど何から始めていいのかよくわかわんっていう人には、 AWS IoT エンタープライズボタン おすすめです。


comments powered by Disqus