博客搬遷至https://blog.wangjiegulu.comweb
RSS訂閱:https://blog.wangjiegulu.com/feed.xmljson
原文連接:https://blog.wangjiegulu.com/2018/09/26/private-smart-life-cloud-b--working-with-ifttt-slack/api
上一篇咱們破解了塗鴉的插座,搭建了本身的 web 服務,暴露了一個接口來控制插座的開關。這篇咱們配合 IFTTT、Slack 來控制插座:服務器
Angelia
,對它發消息「幫我打開臥室的電源」,而後插座打開, Angelia
回覆說 「好的,已經打開」。Angelia
,發送 Slash Commands,打開關閉插座。打開 Slack,根據提示建立本身的 Slack Workspace: https://slack.com/createapp
好比個人 Workspace 爲 https://wangjie.slack.com。dom
建立完畢登陸以後,默認應該有 #general
、#random
等 channel,但暫時不用這兩個 channel。post
接下來,咱們來建立一個 App。ui
打開 https://api.slack.com/,點擊 Start Building
this
輸入 App 名稱和你要添加到的 workspace。google
建立完畢以後,咱們須要設置這個 app 的機器人相關信息,打開 app 設置頁面,選擇 Bot Users
:
設置機器人的名稱(Display name 和 Default name)。勾選 Always Show My Bot as Online
,點擊 Save Changes
。
Event API 能夠在各類時間發生的時候觸發調用,好比 消息發送的時候、channels 改變的時候等等。
咱們先回到咱們的 web 服務,打開上一章建立的 AngeliaController
,新增一個處理 Event 的 api:
@PostMapping("/say/at") fun say(@RequestBody request: BotEventRequestVo): JSONObject { logger.info("[slack event request]request -> \n$request") return JsonResult.success( "token" to request.token, "challenge" to request.challenge, "message" to message ) } data class BotEventRequestVo( val challenge: String?, val token: String?, val team_id: String?, val api_app_id: String?, val event: BotEventVo?, val type: String?, val event_id: String?, val event_time: String?, val authed_users: List<String>? ) data class BotEventVo( val type: String?, val user: String?, val text: String?, val client_msg_id: String?, val ts: String?, val channel: String?, val event_ts: String?, val channel_type: String? )
構建,部署到服務器。
打開 Slack App 設置頁面的 Event Subscriptions
:
在 Request URL
中填寫剛剛在咱們 web 服務上建立的接口 http://[server ip]:xxx/angelia/say/at
,而且點擊驗證。
注意:這裏認證的依據是,你的接口 Response 須要返回請求中的
challenge
數據就算認證成功。
而後在 Subscribe to Bot Events
中添加訂閱的事件,須要增長的是 message.im
message.im
表示當你跟 bot 的私聊中產生消息的時候(有多是你發送消息給 Bot,也有多是 Bot 發消息給你),事件就會觸發。
點擊保存。
這時,當你在 Slack 中發送消息給機器人的時候,你的 web 服務端就能收到請求了。
你的 web 服務器收到請求以後,須要對此進行處理,因此你須要去解析發的消息中的信息,而後打開/關閉對應設備(插座)的開關。完善以前的 say
接口:
@Autowired lateinit var tuyaClientService: TuyaClientService @Autowired lateinit var angeliaSlackProperties: AngeliaSlackProperties /** * Angelia 機器人 對話入口 */ @PostMapping("/say/at") fun say(@RequestBody request: BotEventRequestVo): JSONObject { try { val text = request.event?.text val eventType = request.event?.type if (eventType == "message" // 直接對話 || request.event.user != angeliaSlackProperties.angelia_id // angelia本身發的忽略掉 ) { val message = angeliaBotService.parseTuyaClient(text) ?: "Sorry, I can not understand." angeliaSlackService.postMessage(JSONObject().apply { this["text"] = "$message" this["channel"] = request.event.channel this["as_user"] = true }) } return JsonResult.success( "token" to request.token, "challenge" to request.challenge, "message" to "Request eventId(${request.event_id}) done." ) } catch (e: Exception) { angeliaSlackService.postMessage(JSONObject().apply { this["text"] = "Sorry! Something is wrong: ${e.message}" this["channel"] = request.event?.channel this["as_user"] = true }) return JsonResult.error(e.message) } }
上面代碼的邏輯很簡單:
angeliaBotService.parseTuyaClient()
方法進行文本解析和處理這裏須要作一些 Slack 的配置 slack.properties:
# token for bot angelia.slack.bot_token=Bearer xoxb-2923xxxxxxxxxxxxxxxxxxxx # slack api angelia.slack.api_base_url=https://slack.com/api angelia.slack.api_chat_post_message=/chat.postMessage angelia.slack.angelia_id=UCWxxxxxx
angelia.slack.bot_token
:是 Bot 發送消息到 Slack 的token,這個 token 能夠在 app 設置頁面的 OAuth & Permissions
中拿到
注意:是下面的那個
Bot User OAuth Access Token
,而且添加到配置文件的時候須要加上Bearer
(注意後面有個空格)
angelia.slack.api_base_url
和 angelia.slack.api_chat_post_message
是發送消息的 url,不用改動。
angelia.slack.angelia_id
表示機器人的id,能夠經過在 slack 左側選中機器人右鍵複製連接,path 最後部分就是 id
最後,你就能在 slack 中打開與機器人聊天框,發送「關閉插座a」來控制插座:
首先確保你的手機裝有 Google Assistant(Google Home 先不討論。。。是的,我沒買- -)。
首先咱們須要在 web 服務器端再建立以下一個接口:
/** * 插座控制接口 */ @PostMapping("/control/plug") fun controlPlug(@RequestBody request: PlugRequestVo): JSONObject { val dev = tuyaClientProperties.findDev(request.alias) return try { if (null == dev) { JsonResult.error("Device named ${request.alias} is not found") } else { tuyaClientService.controlPlug(dev.devId, request.turnOn) JsonResult.success() } } catch (e: Exception) { JsonResult.error(e.message) } } data class PlugRequestVo( val alias: String, val turnOn: Boolean )
構建部署到服務器。
而後打開IFTTT、註冊(若是尚未帳戶)登陸,建立 Applet
This:選擇 Google Assistant:
That:選擇 Webhook:
注意:POST 請求,在 body 中填寫如上 json 數據。
關閉的 Applet 也是相似,把 body 中的 turnOn 改爲 false 就能夠了
最後,你就能夠經過 「OK, Google」 喚醒 Google Assistant,而後說"Turn on plug a"來打開插座了。
原本想直接使用 Google Assistant 的 Smart Life 的,可是一直沒成功,不少人也在反映這個事情,不過貌似沒什麼效果(看下面這個評分,估計反映一直是被無視的- -):
在 web 服務中再新增兩個接口用於 Slash Command:
/** * 插座控制接口,For Slack command line(slash commands) */ @PostMapping("/plug/turnon") fun plugTurnOnForCommand(@RequestBody body: String): JSONObject { return JsonResult.success("text" to plugControlForCommand(body, true)) } /** * For Slack command line(slash commands) */ @PostMapping("/plug/turnoff") fun plugTurnOffForCommand(@RequestBody body: String): JSONObject { return JsonResult.success("text" to plugControlForCommand(body, false)) } /** * For Slack command line(slash commands) control */ private fun plugControlForCommand(body: String, turnOn: Boolean): String { try { return body.split("&").map { val pair = it.split("=") Pair(pair[0], URLDecoder.decode(pair[1], "UTF-8")) }.firstOrNull { it.first == "text" }?.let { val dev = tuyaClientProperties.findContainsDev(it.second) if (null == dev) { "Sorry for failed command, Device named ${it.second} is not found." } else { tuyaClientService.controlPlug(dev.devId, turnOn) "${if (turnOn) "Turn On" else "Turn Off"} Done(${it.second})." } } ?: "Sorry for failed command, Device name required." } catch (e: Exception) { return "Sorry for failed command, ${e.message}." } }
打開 App 設置頁面的 Slash Commands
,
點擊 Create New Command
,
而後在聊天的輸入框中就能夠經過"/"顯示 command 提示,選擇命令,後面跟上你要執行該命令的設備別名就好了。
還有其它不少場景能夠實現。好比:
如今愈來愈多的廠商製做着各類各樣的智能設備,可是又在本身的一畝三分地固步自封。作個插座,提供一個 app 控制下開關、定個時、作個 schedule 就是所謂的智能了,你買了個人設備就必需要用個人軟硬件產品。那些須要用戶花心思去考慮何時我該怎麼的設備不是冰冷的,沒有生命的麼?智能是人類賦予了設備生命,掌握了「思考」的能力,如今的生活如此多元化,再牛的公司也不可能覆蓋你的全部生活領域,若是買了這樣的智能設備但自此被囚困在這裏,我想,這纔是我非智能生活的開始吧。