Python实现天猫精灵OAuth2.0和语音技能配置

之前用tornado实现tcp server与硬件的client的连接,以便下发指令。基于django/tornado与wifi模块,lora设备的TCP/UDP即时通讯
现在考虑到天猫精灵可以语音接入。也就用tornado来实现天猫精灵的OAuth2.0.
发了两天空闲的时间去摸索,终于实现成功了。
我的参考文章。

  1. Java实现Aligenie天猫精灵OAuth2.0认证授权流程

重要的还是官方文档,一开始我也是小白,所以我后面尽量讲的详细一点,因为开始看别人的文章也是一脸懵逼
OAuth2.0复杂就在于我们的站点与天猫之间的几次来回的跳转,详细的可以去看看文档里面的图和上面文章的图,理解跳转之后,就好办多了,在下面的代码中,我也会讲清楚里面的跳转
先上天猫精灵的配置图
在这里插入图片描述
tornado中url对应的配置
在这里插入图片描述
在这里插入图片描述
等我们配置好之后,点击上图的账户配置就会向天猫精灵的配置图中的账户授权链接发起一个get请求(文档中的(A) 用户打开授权链接进行授权
天猫精灵先请求1获取到code,然后在请求2.成功完成认证过程
下图的1处代码进行处理会回把code传回天猫精灵,然后天猫精灵带着code会再次请求这个OAuth2Homeurl.然后下面图中2处的代码并接url重定向回去。
在这里插入图片描述
最后的,天猫精灵会带着codepost
文档中的(B) 通过code换取合作方访问令牌
我们的天猫精灵配置里面的Access Token URL也就是我们的Token
最后都没问题的话,会出现这样的画面
在这里插入图片描述
跳转之后,天猫精灵会post我们的RevTmCommand,然后就可以根据自己的需要进行响应。
里面还又很多地方需要修改,比如随机生成code,Token,验证Token,client_id,client_sercert,点击天猫精灵的账户配置应该先跳到一个是否授权的页面。

天猫精灵POST我们的RevTmCommand,初始话我们要返回设备列表回去

class RevTmCommand(web.RequestHandler):
    async def post(self):
        dicts = eval(self.request.body.decode('utf-8'))
        if dicts['header']['namespace'] == "AliGenie.Iot.Device.Discovery":
            print('发现设备')
            data = '''{
                      "header":{
                          "namespace":"AliGenie.Iot.Device.Discovery",
                          "name":"DiscoveryDevicesResponse",
                          "messageId":"1bd5d003-31b9-476f-ad03-71d471922820",
                          "payLoadVersion":1
                       },
                       "payload":{
                          "devices":[
                          {
                        
                          "deviceId":"fan-2",
                          "deviceName":"2号风扇",
                          "deviceType":"fan",
                          "zone":"",          
                          "brand":"",
                          "model":"",     
                          "icon":"https://git.cn-hangzhou.oss-cdn.aliyun-inc.com/uploads/aicloud/aicloud-proxy-service/41baa00903a71c97e3533cf4e19a88bb/image.png",
                          "properties":[{
                            "name":"color",
                            "value":"Red"
                           }
                           ],
                          "actions":[
                            "TurnOn",
                            "TurnOff",
                            "SetBrightness",       
                            "AdjustBrightness",     
                            "SetTemperature",
                            "Query"        
                         ],
                          "extensions":{
                             "extension1":"",
                             "extension2":""
                          }
                         }]
                       }
                    }'''
            self.write(data)
        elif dicts['header']['namespace'] == "AliGenie.Iot.Device.Control":
            name = dicts['header']['name']
            messageId = dicts['header']['messageId']
            deviceId = dicts['payload']['deviceId']
            if name == 'TurnOn':
                print('开')
                send_data = '''{'device_name': 'fan-lamp-curtain', 'class': 'G406', '%s': '1'}''' % deviceId
            elif name == 'TurnOff':
                print('关')
                send_data = '''{'device_name': 'fan-lamp-curtain', 'class': 'G406', '%s': '0'}'''% deviceId
            # try:
            print(send_data)
            send_data = eval(send_data)
            if isinstance(send_data, dict):
                if send_data['device_name'] + send_data['class'] in TCP_CONNECTION.keys():
                    await TCP_CONNECTION[send_data['device_name'] + send_data['class']].write(
                        bytes(str(send_data), encoding='utf-8'))
                    return_data = {
                                      "header":{
                                          "namespace":"AliGenie.Iot.Device.Control",
                                          "name":"TurnOnResponse",
                                          "messageId": messageId,
                                          "payLoadVersion":1
                                       },
                                       "payload":{
                                          "deviceId": deviceId
                                        }
                                    }
                    print('下发成功')
                    self.write(return_data)
                else:
                    return_data = {
                                  "header":{
                                      "namespace":"AliGenie.Iot.Device.Control",
                                      "name":"ErrorResponse",
                                      "messageId": messageId,
                                      "payLoadVersion":1
                                   },
                                   "payload":{
                                        "deviceId": deviceId,
                                         "errorCode":"DEVICE_NOT_SUPPORT_FUNCTION",
                                         "message": "设备tcp未连接"
                                    }
                    }
                    print('下发失败')
                    self.write(return_data)
            else:
                return_data = {
                                  "header":{
                                      "namespace":"AliGenie.Iot.Device.Control",
                                      "name":"ErrorResponse",
                                      "messageId": messageId,
                                      "payLoadVersion":1
                                   },
                                   "payload":{
                                        "deviceId": deviceId,
                                         "errorCode":"DEVICE_NOT_SUPPORT_FUNCTION",
                                         "message": "命令有错"
                                    }
                    }
                print('指令有错')
                self.write(return_data)

初始化我设置了一个风扇,然后我们在手机上测试,在手机我们与天猫精灵对话,“打开2号风扇,然后天猫那边会post一个请求到我们的RevTmCommand,格式与文档中的一样,然后我们就用TCP下发指令。
在这里插入图片描述
技能设置
在这里插入图片描述

意图
在这里插入图片描述
意图里面的内容(其中普通语料和连续对话语料填写的信息相同)
在这里插入图片描述
在这里插入图片描述
回复配置
URL:https://域名/WebHook
在这里插入图片描述
下载证书,不要更改名字.稍后我们用nginx来配置.

class WebHook(web.RequestHandler):
    """
    天猫技能接口
    """
    async def post(self):
        return_dict = {
            "returnCode": "0",
            "returnErrorSolution": "",
            "returnMessage": "",
            "returnValue": {
                "reply": "好的",
                "resultType": "RESULT",
                "actions": [
                    {
                        "name": "audioPlayGenieSource",
                        "properties": {
                            "audioGenieId": "123"
                        }
                    }
                ],
                "properties": {},
                "executeCode": "SUCCESS",
                "msgInfo": ""
            }
        }
        get_json = self.request.body.decode('utf-8')
        logging.info(get_json)
        get_json = get_json.replace('true', '1')
        dicts = eval(get_json.replace('false', '0'))
        # print(/)
        if dicts['intentName'] == '参观':
            logging.info('参观')
            json_info = {'device_name': 'android', 'class': 'D712'}
            if json_info['device_name'] + json_info['class'] in TCP_CONNECTION.keys():
                logging.info('TCP_CONNECTION:{}'.format(TCP_CONNECTION))
                await TCP_CONNECTION[json_info['device_name'] + json_info['class']].write(
                    bytes(str('start'), encoding='utf-8'))
                # return_data['returnValue']['resultType'] = ''
                logging.info("好的{}".format(return_dict))
                self.write(return_dict)
            else:
                return_dict['returnValue']['reply'] = "安卓设备未连接"
                logging.info("安卓设备未连接{}".format(return_dict))
                self.write(return_dict)
        else:
            return_dict['returnValue']['reply'] = "非参观意图"
            logging.info('非{}'.format(return_dict))
            self.write(return_dict)

WebHook证书nginx配置
先把证书复制到
天猫精灵要求要https,

server {
    listen 80;
    server_name 你的域名;
    rewrite ^(.*)$ https://$host$1 permanent;
	   # 匹配天猫精灵语音技能webhook证书
}

在这里插入图片描述
测试结果:
出现success为成功,返回“安卓设备未连接”是我们自己项目自定义的。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值