博客搬迁至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 就是所谓的智能了,你买了个人设备就必需要用个人软硬件产品。那些须要用户花心思去考虑何时我该怎么的设备不是冰冷的,没有生命的么?智能是人类赋予了设备生命,掌握了“思考”的能力,如今的生活如此多元化,再牛的公司也不可能覆盖你的全部生活领域,若是买了这样的智能设备但自此被囚困在这里,我想,这才是我非智能生活的开始吧。