ろきメモ【ROKI MEMO】- ろきsanの備忘録 -

ろきさんの備忘録。プログラミング学習記録や開発記録、および学んだ知識等のアウトプットとシェアを目的に書いています。たまに普通のことも書きます。

【AWS IoTボタンでメッセージ送信 2 】AWS IoT 1-Clickで自動作成されたLambdaを修正してみる

スポンサーリンク

先日、AWS IoTボタンを購入し、AWSに登録、SMS送信までを行った。
blog.rokisan.com

ここでは「AWS IoT 1-Click」というサービスに予め用意されている「SMSに送信する」というアクションを利用した。
実際には、ここでLambda関数が自動で作成され、それが紐付いて動作している。なので今回はそのLambda関数を少し編集して、ボタンのクリックタイプ(シングル、ダブル、長押し)によってメッセージを変えてみる。


[前提]

  • 上記の記事でAWS IoTボタンによってSMS送信ができていること
  • AWSコンソールにサインイン済み

さて目次

スポンサーリンク



1. 紐付いているLambda関数名を確認する

「AWS IoT 1-Click」で作成したプロジェクト(のプレイスメント)に紐付いているLambda関数を確認する。
「AWS IoT 1-Click」サービスを選択。
管理 > プロジェクト > 作成したプロジェクトを選択
f:id:ahrk-izo:20191130183210p:plain:w500

テンプレート > アクション の情報をみる
f:id:ahrk-izo:20191130182956p:plain:w500


「iot1click_onclick_sms_2019110311...」となっている。これは(自動で作成された)Lambda関数の名前だ。(「ラムダ」と読む)
つまり、このプロジェクトではボタンを押されたら、このLambda関数にキックされ、ここに書かれた実装コードが走る。それによってSMS送信されている。

Lambdaとは?
このLambda関数は、「AWS Lambda」というサービスで管理されている。
AWS Lambdaとは簡単にいうと、バックエンドで簡単にプログラムを実行できるサービス。
実装コードをアップロード(もしくは直接書いて保存)して、少し設定すれば、何かしらのキック(きっかけ)でそのコードが実行できる。その「キック」は定期実行もできるし、なにかしらのサービスとの連携でもできる。今回は「AWS IoT 1-Click」のサービスからのキックということだ。
※定期実行も正確にいうと「CloudWatch Events」というサービスとの連携


2. Lambda関数の内容を確認する

次にそのLambda関数を確認してみる。
「Lambda」サービスを選択。
f:id:ahrk-izo:20191130183415p:plain:w400

Lambda > 関数
「iot1click_onclick_sms_20191103113059」というLambda関数があるね。Python 3.6で書かれたコードのようだ。
f:id:ahrk-izo:20191130183621p:plain:w500
※関数名は、iot1click_onclick_sms_ + 作成日時になるんだろうな。


そのLambdaを選択し、中に入る。

このLambda関数が設定やコードがわかる。

まず目に入るのは「Designer」。
これを見ると、CloudWatch Log と SNS というAWSの他のサービスと連携していることがわかる。
f:id:ahrk-izo:20191130183906p:plain:w500

簡単に言うと、
「Amazon CloudWatch Logs」は、AWSのいろんなサービスのログを監視して保存・閲覧できるサービス。これによってLambdaの実行内容(エラーとか)チェックできる。
Amazon CloudWatch Logs とは - Amazon CloudWatch Logs

「Amazon SNS」は、EメールやSMSなどでメッセージを配信できるサービス。これによってボタンを押したときケータイにSMSが送信できている。このSNSの設定も自動でされている(なんて便利!)。こっちの説明は割愛する。
Amazon SNS(サーバーレスアプリのための pub/sub メッセージングサービス)| AWS


さて次は、「関数コード」。
ここはいわゆる「実装コード」。つまりボタンを押されたら、このコードが走るということ。
f:id:ahrk-izo:20191130200335p:plain:w600

ランタイム : Python 3.6
ハンドラ : lambda_function.lambda_handler

(lambda_function.py)

from __future__ import print_function

import boto3
import json
import logging

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

sns = boto3.client('sns')


def lambda_handler(event, context):
    logger.info('Received event: ' + json.dumps(event))

    attributes = event['placementInfo']['attributes']

    phone_number = attributes['phoneNumber']
    message = attributes['message']

    for key in attributes.keys():
        message = message.replace('{{%s}}' % (key), attributes[key])
    message = message.replace('{{*}}', json.dumps(attributes))

    dsn = event['deviceInfo']['deviceId']
    click_type = event['deviceEvent']['buttonClicked']['clickType']
    message += '\n(DSN: {}, {})'.format(dsn, click_type)

    sns.publish(PhoneNumber=phone_number, Message=message)

    logger.info('SMS has been sent to ' + phone_number)

せっかくなので、部分的にざっくり解説してみる。

スポンサーリンク




モジュールのインポート

from __future__ import print_function

import boto3
import json
import logging

冒頭のこれらの部分は、このLambda関数に必要なモジュールをインポートしている。Pythonは必要なモジュールはこうやっていちいち書く(個別の説明は割愛)


ログの準備

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

これらは、ログの準備。lambda_handler関数の中で logger.info() を使ってログ出力しているが、それを使うための準備。ログなのでSMS送信のプログラムには直接関係はしない。なので、ログ関連は省略する。


SMSサービス連携の準備

sns = boto3.client('sns')

Lambda関数AWS SNSサービスを使うための準備。boto3というモジュールを使うことで、あっさり連携できる。Pythonって便利。(boto3の中身は知らんけど、ドキュメント見ながら使えばそうなるんだから)


ハンドラ関数

def lambda_handler(event, context):
  ...

次はこちらの関数内を見ていく。「AWS IoT 1-Click」からこの関数が呼ばれ、実行される。その時引数としてeventが渡される。(コードを見ると、contenxtは使われていないから、eventのみの情報があるんだろうな)


eventの中身

    attributes = event['placementInfo']['attributes']

    phone_number = attributes['phoneNumber']
    message = attributes['message']

「AWS IoT 1-Click」(のtest-projectのsend-smsというテンプレート)から渡された情報を関数に入れている。
電話番号とメッセージということがわかる。


プレイスメント属性の値をメッセージに使う

    for key in attributes.keys():
        message = message.replace('{{%s}}' % (key), attributes[key])
    message = message.replace('{{*}}', json.dumps(attributes))

ここはsend-smsというテンプレート内で設定したプレイスメントの属性の各内容を、message内の{{ナントカ}}という文字の部分に置換している。
例えば
message : テストメールです。{{key1}}は{{key2}}です。
key1 : AWS
key2 : 最高
となっていたら、message変数に入るのは、
「テストメールです。AWSは最高です。」
となる。


SMS送信

    dsn = event['deviceInfo']['deviceId']
    click_type = event['deviceEvent']['buttonClicked']['clickType']
    message += '\n(DSN: {}, {})'.format(dsn, click_type)

    sns.publish(PhoneNumber=phone_number, Message=message)

最後の部分。ここもわかりやすい。
デバイスのDSN(登録しているボタンのID)とクリックタイプ(シングル or ダブル or 長押し)を受け取り、メッセージに追記している。
最後は冒頭にboto3を使って準備していたsnsオブジェクトを使ってSMS送信。引数には電話番号とメッセージ。

これによって以下のようなメッセージがケータイのSMSに送信される。
f:id:ahrk-izo:20191124094143p:plain:w200


3. Lambda関数を編集してみる。

実際にコードを編集してみて、どんなメッセージが送信されるか確かめてみる。それによって理解も深まる。

終盤のこの部分だけ編集してみる。

    dsn = event['deviceInfo']['deviceId']
    click_type = event['deviceEvent']['buttonClicked']['clickType']
    message += '\n(DSN: {}, {})'.format(dsn, click_type)

繰り返しだが、ここはデバイスのDSNとクリックタイプをメッセージに追記している。
ここを以下のように修正してみる。

    dsn = event['deviceInfo']['deviceId']
    click_type = event['deviceEvent']['buttonClicked']['clickType']
    message += '\n(ClickType: {})'.format(click_type)  # <- ここだけちょっと変えた

メッセージにはクリックタイプだけを追記するようにした。

右上の「保存」を押して、
f:id:ahrk-izo:20191130200754p:plain:w400


実際にボタンを押すと、ばっちり変更が反映されいる!
f:id:ahrk-izo:20191130195640p:plain:w200


実際にクリックタイプによって、SINGLE、DOUBLE、LONGとなるので、if文使って、

    if click_type == 'SINGLE':
        message += '1回押したぞい!'
    elif click_type == 'DOUBLE':
        message += '2回も押しちゃった'
    elif click_type == 'LONG':
        message += '長押しっす!'

とやってもよい。


これで、IoTボタンを押されたとき、どのようにSMS送信されているか、その仕組みと実装コードが理解できた。1からこの仕組を作るのは大変だけど、ある程度自動で作られて、そこを修正するくらいならそこまでハードルは高くない。

やはり動くものができて、それをカスタマイズできると楽しいな。

スポンサーリンク



おまけ Amazon SNSサービス

自動で設定されたSNSサービスの方もチェックしてみる。

サービスから(snsと検索して)「Simple Notification Service」を選択。
f:id:ahrk-izo:20191130201745p:plain:w400

リージョンを米国東部(バージニア北部)に変更して、トピックを見ると、「NotifyMe」というのが作られている。
f:id:ahrk-izo:20191130202432p:plain:w500

やはり、SNSはアメリカのリージョンに作られ、国際電話でSMS送信されているんだな。



あれ?関係ないけど、いつの間にかリージョン選択のところに「us-east-1」とか出てた。いつもこのコードがあやふやでググってたから便利になった!
f:id:ahrk-izo:20191130202712p:plain:w250



以上。