SORACOM LTE-M Buttonでお母さんに親孝行しようと思った話(元気やでボタン)
SORACOM LTE-M Buttonでお母さんに親孝行しようと思った話(元気やでボタン):
実家の大阪、自分の住む関東。
元気やけど、それを言うのはなんか気恥ずかしい。
でもお母さんから来る「元気か?」「元気やろ?」はちょっと嬉しい。
お母さんに心配はかけたくない。
いつでもどこでもお母さんに「元気やで」って言えればメッチャ良くね?
…お母さんの誕生日に贈ることにしました。あのボタン。
こんな感じです。
1. AWS IoT 1-Clickで、ボタンにLambdaの関数を割り当て
2. ボタンの属性に、それぞれのクリックに対応するメッセージを仕込む
3. ボタンの押された種別に応じて、LambdaからLINE Notifyにメッセージを発行
SORACOMのMaxさんが分かりやすく書いてくれてます。
SORACOM LTE-M Button powered by AWS を用いた開発 TIPS - SORACOM Blog
これを基にして、今回のプロジェクトで設定した内容を図解したので参考になれば。
messageのところは、適宜書き換えて好きなフォーマットで出力してください。
これをLambdaのテストイベントの箇所に貼り付けてテストしたら、LINEに通知されます。
(トークンだけ書き換えてね)
エラー出力
とある休日に、何を思ったか
- SORACOMのボタン(俗に言う「あのボタン」)が発売されるねんなぁ
- 何作ろうかなぁ
- そりゃ作るのはできるけどさ、せっかく作るなら使うもんがいいなぁ
そんな時、どこからともなくお母さんからLINEが
息子の悩み
実家の大阪、自分の住む関東。元気やけど、それを言うのはなんか気恥ずかしい。
でもお母さんから来る「元気か?」「元気やろ?」はちょっと嬉しい。
お母さんに心配はかけたくない。
そうだ、これだ
いつでもどこでもお母さんに「元気やで」って言えればメッチャ良くね?…お母さんの誕生日に贈ることにしました。あのボタン。
どんなものを作ろうと思ったか
- ボタンを押すと、LINEに通知が届く
- ボタンの役割によって届くメッセージが異なる
- どうせだったら汎用的に使えるものが欲しい
- 名付けて
仕組み
こんな感じです。1. AWS IoT 1-Clickで、ボタンにLambdaの関数を割り当て
2. ボタンの属性に、それぞれのクリックに対応するメッセージを仕込む
3. ボタンの押された種別に応じて、LambdaからLINE Notifyにメッセージを発行
AWS IoT 1-Clickの設定について
SORACOMのMaxさんが分かりやすく書いてくれてます。SORACOM LTE-M Button powered by AWS を用いた開発 TIPS - SORACOM Blog
これを基にして、今回のプロジェクトで設定した内容を図解したので参考になれば。
Lambda側の設定
の前に、気をつけたいこと
-
Lambdaのプロジェクトを作るときに、Python3.6を使う
(いや別になんでもいいけど笑)
-
LambdaのPythonにはデフォルトでrequestsモジュールが入っていない
- 一旦ローカルにpipでモジュールをダウンロード
- そこに下記のlambda_function.pyと一緒にzipで固めてアップロードする必要がある
- 参考:【AWS】Lambdaでpipしたいと思ったときにすべきこと - Qiita
-
zipでアップロードしたらさっきまでLambdaのWebで書いてたコードは上書きされるぞ
- これで泣いたぞ、1回
コードで工夫した点
- 例外処理ちゃんと書いて、CloudWatchで出力されるログに、エラーが出るようにした
- LINE Notifyのトークンが設定されていれば、そのログをLINE側に通知するようにした
- LINE Notifyのトークンをコード内に設定できるようにした(環境変数にしたら良かった…)
実際のコード
messageのところは、適宜書き換えて好きなフォーマットで出力してください。lambda_function.py
# -*- coding:utf-8 -*- import json import requests import datetime as dt # LINE NotifyのURLとデフォルトの通知先トークン(これよりもボタン側に設定したトークンが優先される) LINE_NOTIFY_URL = "https://notify-api.line.me/api/notify" LINE_NOTIFY_TOKEN = "" # UTCとの時差(時間) UTC = 9 def lambda_handler(event, context): global LINE_NOTIFY_TOKEN print("Received event: " + json.dumps(event)) # デバイス情報(デバッグ用) deviceInfo = event['deviceInfo'] deviceId = deviceInfo['deviceId'] deviceAttributes = deviceInfo['attributes'] # プロジェクト名、プレイスメント名(デバッグ用) projectName = deviceAttributes['projectName'] placementName = deviceAttributes['placementName'] # クリック種別とクリック時間の取得 buttonClicked = event['deviceEvent']['buttonClicked'] clickType = buttonClicked['clickType'] reportedTime = buttonClicked['reportedTime'] # AWSデフォルト表記:2018-11-09T12:37:10.614Z input_datetime_format = '%Y-%m-%dT%H:%M:%S.%fZ' # 出力表記:2018/11/09 12:37:10 output_datetime_format = '%Y/%m/%d %H:%M:%S' # datetimeオブジェクト作成 datetime_obj = dt.datetime.strptime(reportedTime, input_datetime_format) # 時差補正 td = dt.timedelta(hours=UTC) # 日時フォーマット整形 reportedTime = (datetime_obj + td).strftime(output_datetime_format) # 属性情報の取得 attributes = event['placementInfo']['attributes'] try: # トークンが設定されていれば if 'LINE_NOTIFY_TOKEN' in attributes: LINE_NOTIFY_TOKEN = attributes['LINE_NOTIFY_TOKEN'] else: raise AttributeError("LINE Notifyのトークンが見つかりません。") # ボタン名が設定されていれば if 'BUTTON_NAME' in attributes: BUTTON_NAME = attributes['BUTTON_NAME'] else: raise AttributeError("ボタン名が見つかりません。") # クリック種別に応じた処理 if clickType == "SINGLE": if 'SINGLE_MESSAGE' in attributes: message = attributes['SINGLE_MESSAGE'] else: raise AttributeError("シングルクリック時のメッセージが定義されていません。") elif clickType == "DOUBLE": if 'DOUBLE_MESSAGE' in attributes: message = attributes['DOUBLE_MESSAGE'] else: raise AttributeError("ダブルクリック時のメッセージが定義されていません。") elif clickType == "LONG": if 'LONG_MESSAGE' in attributes: message = attributes['LONG_MESSAGE'] else: raise AttributeError("ロングクリック時のメッセージが定義されていません。") # メッセージ生成 message = "\n"+BUTTON_NAME+"が「"+message+"」と言っています。\n" \ + "時刻:"+reportedTime # + "時刻:"+reportedTime+"\n" \ # + "ボタン名:"+placementName+"\n" \ # + "シリアル:"+deviceId # LINE送信処理 send_to_line(message) except AttributeError as e: error_message = "\nプロジェクト名["+projectName+"]の端末["+placementName+"("+deviceId+")]でエラーが発生しました:"+e.args[0]+"\n" \ + "時刻:"+reportedTime print(error_message) # LINE Notifyのトークンが設定されていれば、エラーメッセージを通知 if 'LINE_NOTIFY_TOKEN' in attributes: send_to_line(error_message) def send_to_line(message): headers = {"Authorization": "Bearer " + LINE_NOTIFY_TOKEN} payload = {"message": message} requests.post(LINE_NOTIFY_URL, headers=headers, params=payload)
テストイベント用のJSON
これをLambdaのテストイベントの箇所に貼り付けてテストしたら、LINEに通知されます。(トークンだけ書き換えてね)
test_event.json
{ "deviceInfo": { "deviceId": "1AB2CDEFGHI3456", "type": "button", "remainingLife": 98.4, "attributes": { "projectRegion": "ap-northeast-1", "projectName": "howareyou_mom", "placementName": "button_01", "deviceTemplateName": "notifyToLINE" } }, "deviceEvent": { "buttonClicked": { "clickType": "SINGLE", "reportedTime": "2018-11-09T16:29:40.474Z" } }, "placementInfo": { "projectName": "howareyou_mom", "placementName": "button_01", "attributes": { "SINGLE_MESSAGE": "元気です。", "DOUBLE_MESSAGE": "元気してる?", "LINE_NOTIFY_TOKEN": "(LINE Notifyトークン)", "LONG_MESSAGE2": "連絡ちょうだい!", "BUTTON_NAME": "息子" }, "devices": { "notifyToLINE": "1AB2CDEFGHI3456" } } }
実際の画面
できたー!オカンがもうすぐ誕生日やから、このボタン渡して親孝行するんだ!日本初の「オカンにソラコムボタン渡した息子」になりたい…!やりとりのイメージ
AWS IoT 1-Click側の設定だけでLambdaには手を加えなくていい親切設計です。メッチャ汎用的。(近日Qiitaに書きます)#SORACOM #あのボタン #AWS #IoT pic.twitter.com/lqdj3xm0Uj
— itox(dev) (@itoxdev) 2018年11月9日
エラー出力
作ってみた感想
-
実は今回AWSというかLambda初めて触ったけどメッチャ面白い
- アカウント作って1週間くらい(いや、ずっとやりたいとは思ってたのよ)
-
お母さんに早く渡したい
- お母さんと電話して頭出しは済んでる
- お母さん「それよりあんた、誕生日プレゼントにひこにゃんのLINEスタンプ欲しいわ」
- まさかのスタンプおねだりかよ
- え、VSCodeメッチャ便利…(これまでメモ帳で頑張ってた)
- PythonいいよPython、モジュール使いやすいぜ
- よく考えたら「元気やでボタン」やのに本文中は「元気です」とか言ってるごめん
- IoTって技術ありきじゃなくて、アイデア勝負やんな、やっぱ
- IoTはきっと人を幸せにできる
今後考えてること
- DynamoDBに入れたいなぁ
- もうちょい可視化したいなぁ
- LINEじゃなくてAlexaに出力しても面白いなぁ
- Wio + モータードライバ or リレーとか使って、元気ならぬいぐるみ動かしても面白いなぁ
コメント
コメントを投稿