Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What is going on with this article?
@itox

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

More than 1 year has passed since last update.

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

  • 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 リレーとか使って、元気ならぬいぐるみ動かしても面白いなぁ

以上

6
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
itox
駆け出しのIoTエンジニアです。関東弁と関西弁のバイリンガル。「それイケてる?」という感性を大事にしたい。忍法!クラウド隠れの術!発言は個人的な内容であり所属する組織とは関係ありません。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
6
Help us understand the problem. What is going on with this article?