GoogleNest(Home) に話しかけた内容を、オリジナルデバイスへの指示としてサーバで受取り、SLACKへコマンドとして投稿を行う部分を作成する。
以下の図の赤枠の部分。

スマートホームサービス用サーバの立上げ
前の記事 からの続き。
Action on GoogleHome からデバイスの操作指示を受けて、その内容をslackに書込みするサーバの作成。
本来であれば、自社の製品等をコントロールするサーバとして動作させるのだと思います。
今回は、ソースコードはpythonで書くこととして、flaskを使用してサーバを立てることとします。
サーバ処理のソースコード
サーバの処理用のサンプルコードです。
さしあたり、動かすだけならこれで大丈夫です。
config.cfg ファイルの内容は、ソースから必要な項目を設定してください。
ソースコードは、コメントを参考にしていただければ、ある程度わかると思います。
詳細は、こちらのページ がわかりやすいと思います。
<main.py>
import sys
import json
import io
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
app.config["JSON_AS_ASCII"] = False #文字コードをUTF8に
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
# 設定ファイルの読み込み
app.config.from_pyfile('config.cfg')
#SLACK WebHook URL
SLACK_URL = app.config['SLACK_URL']
### SLACK に送る ###
def goSlack( str ):
requests.post(SLACK_URL, data=json.dumps({
"text" : str,
}))
#########################################
### 動作定義をGoogleに送るJSON読込み ###
#########################################
# 電気
with open('light.json', 'r', encoding='utf-8') as f:
denki_sync = json.load(f, strict=False)
# テレビ
with open('tv.json', 'r', encoding='utf-8') as f:
tv_sync = json.load(f, strict=False)
#デバイスの定義
DEV_LIGHT = "10"
DEV_TV = "20"
# デバイスリスト登録
dev = [ denki_sync, tv_sync ]
##########################
### 実行のメイン処理 ###
##########################
def executecmd( device_id, execute ):
### 電気 ###
if device_id == DEV_LIGHT:
if execute["command"] == "action.devices.commands.OnOff": # つける / 消す
if execute["params"]["on"]:
goSlack( "電気をつけて" )
else:
goSlack( "電気を消して" )
### テレビ ###
elif device_id == DEV_TV:
if execute["command"] == "action.devices.commands.OnOff": # つける / 消す
if execute["params"]["on"]:
goSlack( "テレビをつけて" )
else:
goSlack( "テレビを消して" )
elif execute["command"] == "action.devices.commands.selectChannel": # チャンネル
ch = execute["params"]["channelNumber"]
goSlack( "テレビのチャンネルを" + ch + "にして" )
elif execute["command"] == "action.devices.commands.volumeRelative": # 音量 調整
lv = execute["params"]["relativeSteps"]
if lv > 0:
goSlack("テレビの音量を" + str(lv) + "上げて")
else:
goSlack("テレビの音量を" + str(abs(lv)) + "下げて")
return
############################
### Googleとの通信処理 ###
############################
@app.route("/your_service/gran/")
def gran():
# 認証したことにして、必要なリダイレクトだけ行えるようにする
# 本来は、何らかの認証を行うべき
req = request.args
redirecturi = req.get('redirect_uri') + "?code=" + app.config['CODEX'] + "&state=" + req.get('state')
ret_str = "<!DOCTYPE html><html lang=\"ja\">"
ret_str += "<BODY><A HREF=\"" + redirecturi + "\">redirecturi</A></BODY></HTML>"
return ret_str
@app.route("/your_service/talken/", methods=["POST"])
def talken():
# 適当にトークンぽいものを返しておく
if request.form['grant_type'] == "authorization_code":
ret_str = {"token_type": "Bearer","access_token": app.config['CODEX'] , "refresh_token": app.config['CODEXRE'], "expires_in": app.config['EXPIREIN'] }
if request.form['grant_type'] == "refresh_token":
ret_str = {"token_type": "Bearer", "access_token": app.config['CODEX'] , "expires_in": app.config['EXPIREIN'] }
return jsonify(ret_str)
@app.route("/your_service/intent/", methods=["GET","POST"])
def intent():
requestId = request.json['requestId']
inputs = request.json['inputs']
intent = inputs[0]["intent"]
# SYNC
if intent == "action.devices.SYNC":
return jsonify( {'requestId': requestId, "payload": { "agentUserId": app.config['AGENTUSERID'], "devices": dev } })
# EXECUTE
elif intent == "action.devices.EXECUTE":
command = inputs[0]["payload"]["commands"][0]
device_id = command["devices"][0]["id"]
execute = command["execution"][0]
executecmd( device_id, execute )
return jsonify({'requestId': requestId, "payload": { "commands": [{"ids": [device_id], "status": "SUCCESS", "states":{"online":True}}]}})
# QUERY
if intent == "action.devices.QUERY":
# onlineであることだけを返す
devicelist = {}
for deviceinfo in inputs[0]["payload"]['devices']:
devicelist |= { deviceinfo["id"] : { "online": True, "on": True }}
return jsonify({'requestId': requestId, "payload": { "devices": devicelist } })
##################
### FLASK 実行 ###
##################
if __name__ == "__main__":
app.run(debug=False)
<light.json>
{
"id": "10",
"type": "action.devices.types.LIGHT",
"traits": [
"action.devices.traits.OnOff"
],
"name": {
"defaultNames": [
"電気"
],
"name": "電気",
"nicknames": [
"ライト"
]
},
"willReportState": false,
"roomHint": "リビング",
"attributes": {
"commandOnlyOnOff": true,
"commandOnlyBrightness": true
},
"deviceInfo": {
"manufacturer": "サンプル",
"model": "light",
"hwVersion": "1.0",
"swVersion": "1.0"
},
"customData": {}
}
<tv.json>
{
"id": "20",
"type": "action.devices.types.TV",
"traits": [
"action.devices.traits.OnOff",
"action.devices.traits.Channel",
"action.devices.traits.Volume"
],
"name": {
"name": "テレビ",
"defaultNames": [
"テレビ"
],
"nicknames": [
"テレビ"
]
},
"roomHint": "リビング",
"willReportState": false,
"attributes": {
"availableChannels": [
{
"number": "0"
},
{
"number": "1"
},
{
"number": "2"
},
{
"number": "3"
},
{
"number": "4"
},
{
"number": "5"
},
{
"number": "6"
},
{
"number": "8"
},
{
"number": "10"
}
],
"orderedInputs": false,
"volumeMaxLevel": 25,
"volumeCanMuteAndUnmute": false,
"levelStepSize": 3,
"commandOnlyVolume": true,
"supportActivityState": false,
"supportPlaybackState": false
},
"deviceInfo": {
"manufacturer": "sample",
"model": "xx",
"hwVersion": "1.0",
"swVersion": "1.0"
}
}
これを Flask で実行する。
続いて、Actions on Google から SLACK へ ③へ
コメント