15
6

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 5 years have passed since last update.

SORACOM LTE-M Buttonでお母さんに親孝行しようと思った話(元気やでボタン)

Last updated at Posted at 2018-11-10

#とある休日に、何を思ったか

  • SORACOMのボタン(俗に言う「あのボタン」)が発売されるねんなぁ
  • 何作ろうかなぁ
  • そりゃ作るのはできるけどさ、せっかく作るなら使うもんがいいなぁ

そんな時、どこからともなくお母さんからLINEが

  • それに対し、息子はこう返す。 
- そういえば、そろそろ**お母さんの誕生日**やねんなぁ…

息子の悩み

実家の大阪、自分の住む関東。
元気やけど、それを言うのはなんか気恥ずかしい。
でもお母さんから来る「元気か?」「元気やろ?」はちょっと嬉しい。
お母さんに心配はかけたくない。

そうだ、これだ

いつでもどこでもお母さんに「元気やで」って言えればメッチャ良くね?
…お母さんの誕生日に贈ることにしました。あのボタン。

どんなものを作ろうと思ったか

  • ボタンを押すと、LINEに通知が届く
  • ボタンの役割によって届くメッセージが異なる
  • どうせだったら汎用的に使えるものが欲しい
  • 名付けて

fudechar_jibyt.png

#仕組み
こんな感じです。

  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側の設定
##の前に、気をつけたいこと

##コードで工夫した点

  • 例外処理ちゃんと書いて、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']
        elif LINE_NOTIFY_TOKEN == "":
            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}

    r = requests.post(LINE_NOTIFY_URL, headers=headers, params=payload)
    print(r.text)

##テストイベント用の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というかLambda初めて触ったけどメッチャ面白い
  • アカウント作って1週間くらい(いや、ずっとやりたいとは思ってたのよ)
  • お母さんに早く渡したい
  • お母さんと電話して頭出しは済んでる
  • お母さん「それよりあんた、誕生日プレゼントにひこにゃんのLINEスタンプ欲しいわ
  • まさかのスタンプおねだりかよ
  • え、VSCodeメッチャ便利…(これまでメモ帳で頑張ってた)
  • PythonいいよPython、モジュール使いやすいぜ
  • よく考えたら「元気やでボタン」やのに本文中は「元気です」とか言ってるごめん
  • IoTって技術ありきじゃなくて、アイデア勝負やんな、やっぱ
  • IoTはきっと人を幸せにできる

#今後考えてること

  • DynamoDBに入れたいなぁ
  • もうちょい可視化したいなぁ
  • LINEじゃなくてAlexaに出力しても面白いなぁ
  • Wio + モータードライバ or リレーとか使って、元気ならぬいぐるみ動かしても面白いなぁ

以上

15
6
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
15
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?