やりたいこと
Sesameを買って、スマートホーム化を進めているところ。
どうしてもSesameの公式アプリのレスポンスが遅い。
「開けて」って言ったら、すぐ開けてほしい。
※Sesameとは
自宅の鍵に取り付けるだけで、スマホから開け閉めできる!というやつ。
https://jp.candyhouse.co
できたこと
Lineの個人チャンネルにて「鍵あけて」「鍵しめて」というと、Sesameがスッと起動する。
構成
Line→AWS API Gateway→Lambda→Sesame
Lambda上はPythonで書いてます。
コードはPycharmで書いて、そのままデプロイまでしちゃいます。簡単。
ローカル環境はMacOSです。
1.SesameのAPIを確認する。
まず公式ページの「ダッシュボード(BETA)」からログイン。
「API設定」から認証コードを入手します。
入手した認証コードを使いながら、とりあえずcurlで叩いてみます。
API仕様の詳細は、公式見てください。
https://docs.candyhouse.co/#get-sesame-list
curl -H "Authorization: **************" \
https://api.candyhouse.co/public/sesames
{
"device_id": "*******************",
"serial": "********",
"nickname": "************"
}
応答はすべてJSON形式。
上の"device_id"をもとに、ロック・ロック解除・ステータス確認のAPIを使います。
2.LambdaからAPIを叩く
pythonで書くことにしているので、line-bot-sdkを使いました。
line-bot-sdkの使い方はこちら。
https://github.com/line/line-bot-sdk-python
1.でCURLしていたのは、requestsで実現します。
CURLをpython形式にしてくれるサイトが合ったので、使わせて頂きました。
https://curl.trillworks.com
pythonのソースは以下のとおり。
鍵のOPEN/CLOSEの指示のあと、10秒Sleepしてから、鍵の状態を返却します。
ちなみにAWS Lambdaのタイムアウト値は初期値が3秒なので、広げないと永遠に成立しません。
(実は結構ハマった)
import os, sys
import json
import time
import requests
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,
)
from linebot.exceptions import (
LineBotApiError, InvalidSignatureError
)
channel_secret = os.getenv('LINE_CHANNEL_SECRET', None)
channel_access_token = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None)
if channel_secret is None:
print('Specify LINE_CHANNEL_SECRET as environment variable.')
sys.exit(1)
if channel_access_token is None:
print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
sys.exit(1)
line_bot_api = LineBotApi(channel_access_token)
handler = WebhookHandler(channel_secret)
def lambda_handler(event, context):
signature = event["headers"]["X-Line-Signature"]
body = event["body"]
ok_json = {"isBase64Encoded": False,
"statusCode": 200,
"headers": {},
"body": ""}
error_json = {"isBase64Encoded": False,
"statusCode": 403,
"headers": {},
"body": "Error"}
def controll_sesame(controll):
# ロック解除
controll_headers = {
'Authorization': '**************************',
'Content-Type': 'application/json',
}
if controll == "OPEN":
controll_data = '{"command":"unlock"}'
elif controll == "CLOSE":
controll_data = '{"command":"lock"}'
else:
pass
controll_response = requests.post(
'https://api.candyhouse.co/public/sesame/*************************',
headers=controll_headers, data=controll_data)
time.sleep(10)
# 状態確認
confirm_headers = {
'Authorization': '*************************',
}
confirm_response = requests.get('https://api.candyhouse.co/public/sesame/*************************',
headers=confirm_headers)
response_data = confirm_response.json()
locked = response_data['locked']
# 結果返却
if locked:
message_text = "閉まってるよ"
else:
message_text = "空いてるよ"
return message_text
@handler.add(MessageEvent, message=TextMessage)
def message(line_event):
text = line_event.message.text
if text == "鍵あけて":
message_text = controll_sesame("OPEN")
elif text == "鍵しめて":
message_text = controll_sesame("CLOSE")
else:
message_text = text
line_bot_api.reply_message(line_event.reply_token, TextSendMessage(text=message_text))
try:
handler.handle(body, signature)
except LineBotApiError:
return error_json
except InvalidSignatureError:
return error_json
return ok_json
3.API Gatewayを設定する
AWSコンソールからAPI GatewayをLambdaに括り付ける。
あまり詳しく学びきれてないので、公式見ながらチクチク作る。
最近?HTTP APIができたようですが、REST APIを選択します。
できたら「ダッシュボード」に書かれているURLを控えておきます。
4.LineからAPI Gatewayに接続する。
まずはDeveloperとして登録。
https://developers.line.biz/ja/
Messaging APIとしてチャンネルを作成します。
「Webhook URL」に3.で控えたAPI GatewayのURLを指定します。
またLineチャンネルに設定されているチャネルアクセストークンと
チャネルシークレットは、Lambdaの環境変数に登録しておきます。
5.ハマりどころ
pythonのコードはPycharmで書いていました。
PycharmにはAWS Toolkitというプラグインがあり、
これを導入することでローカルからLambdaへのデプロイが可能になります。
ただこれをやる際、IAMロールに権限をつけておく必要があるのに気付かず
手探りで権限を広げて、とりあえずデプロイが成功。
結果として、Lambda、IAM、S3、APIGateway、CloudFormationの権限を付与しました。
不足はないですが、過剰はあるかもしれません。
勉強不足。。