Table of Contents
一、云云对接流程
二、创建智能家居技能
1、授权信息配置
配置服务需要填写授权信息配置时需要填写以下内容。
- response_type: 授权类型,此处是固定值code。
- 授权地址: 开发者授权访问的地址,遵守OAuth 2.0标准。
- Client_Id: 客户端ID。
- Scope:scope权限,多个权限之间请使用空格进行分开。
- 回调地址: 每个技能创建时,在开放平台上生成的唯一URL地址,该地址不能修改。
- Token地址:用于获取Access Token的地址,遵守OAuth 2.0标准协议。
- ClientSecret:客户端Secret。
- WebService:智能家居设备的设备云服务部署地址。
填写的参数说明
1、授权地址:我们自己定义的一个登录页面的URL
Python代码:
@permission_escape
def bmail_login(request, *args, **kwargs):
if request.method == 'GET':
print(request.GET)
# redirect_uri使用户平台get调用我们的接口是传过来的
redirect_uri = request.GET.get("redirect_uri")
print(redirect_uri)
return render(request, 'bmail_login.html', {"redirect_uri": redirect_uri})
else:
mobile = request.POST.get("mobile")
password = request.POST.get("password")
redirect_uri = request.POST.get("redirect_uri")
print(request.POST)
print(redirect_uri + '?' + "code=9788")
return redirect(redirect_uri + '?' + "code=9788")
bmail_login.html代码:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>授权</title>
</head>
<body>
<div>
<form id="form1" method="post" action="https://ts.zhinengtuodi.com/web/bmail/login_page/">
手机号:<input type="text" name="mobile" value="" />
<br />
密码:<input type="text" name="passwod" value="" />
<br />
回调地址:<input type="text" name="redirect_uri" value={{ redirect_uri }} />
<br />
<input type="submit" value="提交" />
</form>
</div>
</body>
</html>
2、Client_Id:随便写
3、Token地址:我们自己定义的获取Token的URL地址
Python代码
@permission_escape
def bmail_token(request, *args, **kwargs):
if request.method == "POST":
# print(request.POST.get("code"))
print(request.POST)
return return_succ(access_token="666666", refresh_token="666666", expires_in=3600 * 72)
4、ClientSecret:随便写
5、WebService:我们自定义的,接收控制机器人请求的URL
Python代码:
@permission_escape
def bmail_robot(request, *args, **kwargs):
if request.method == "POST":
payload = request.json_data.get("payload")
name = request.json_data.get("header").get("name")
namespace = request.json_data.get("header").get("namespace")
header = request.json_data.get("header")
print(request.json_data, 3)
print(3333, namespace)
# 第一次控制机器人会走发现机器人的逻辑,后面操作机器人就不会再执行了,这个时候要想小度音响说:查找设备
if namespace == "DuerOS.ConnectedHome.Discovery":
print("Discovery robot")
header["name"] = "DiscoverAppliancesResponse"
json_data = {
"header": header,
"payload": {
"discoveredAppliances": [
{
"actions": [
"turnOn",
"turnOff",
"pause",
"continue",
"setSuction",
"setWaterLevel",
"chargeTurnOn",
"chargeTurnOff",
"setMovingDirection",
"setMode",
"timingSetMode",
"getElectricityCapacity",
],
"applianceTypes": [
"SWEEPING_ROBOT"
],
"additionalApplianceDetails": {
"extraDetail1": "optionalDetailForSkillAdapterToReferenceThisDevice",
"extraDetail2": "There can be multiple entries",
"extraDetail3": "but they should only be used for reference purposes",
"extraDetail4": "This is not a suitable place to maintain current device state"
},
# 机器人的machine_id
"applianceId": "11-01-05-55",
"friendlyDescription": "展现给用户的详细介绍",
"friendlyName": "扫地机器人",
"isReachable": True,
"manufacturerName": "设备制造商的名称",
"modelName": "fancySweepingRobot",
"version": "your software version number here.",
"attributes": [
{
"name": "name",
"value": "扫地机器人",
"scale": "",
"timestampOfSample": int(time.time()),
"uncertaintyInMilliseconds": 0
},
{
"name": "connectivity",
"value": "REACHABLE",
"scale": "",
"timestampOfSample": int(time.time()),
"uncertaintyInMilliseconds": 0
},
{
"name": "turnOnState",
"value": "ON",
"scale": "",
"timestampOfSample": int(time.time()),
"uncertaintyInMilliseconds": 10
},
{
"name": "pauseState",
"value": False,
"scale": "",
"timestampOfSample": int(time.time()),
"uncertaintyInMilliseconds": 10
},
{
"name": "mode",
"value": "ANTI_DISTURB",
"scale": "",
"timestampOfSample": int(time.time()),
"uncertaintyInMilliseconds": 10
},
{
"name": "suction",
"value": "standard",
"scale": "",
"timestampOfSample": int(time.time()),
"uncertaintyInMilliseconds": 10
},
{
"name": "waterLevel",
"value": "MEDIUM",
"scale": "",
"timestampOfSample": int(time.time()),
"uncertaintyInMilliseconds": 10
},
{
"name": "electricityCapacity",
"value": 23,
"scale": "%",
"timestampOfSample": int(time.time()),
"uncertaintyInMilliseconds": 10
}
]
},
],
"discoveredGroups": []
}}
return JsonResponse(json_data)
elif namespace == "DuerOS.ConnectedHome.Control":
channel_name = "AppWs1"
device_id = payload.get("appliance").get("applianceId")
print(device_id)
if name == "TurnOnRequest":
print(device_id + "开始扫地")
message = "%s|VMdvpCdDDxbiGfsq7tpKavztywlw2wT+0tIAzQkJtNDQDtlYfh4b7E+PdsEybzNAh4gEhvmwY97XxgqMtTsDy+Q6sYVoFUU7KAwBd5wOb2N8URQxZBZfgblFKm/XvgyEc1cIIGBf/REgBLe+rJjLjoXhpPM9pwI3j0DV+fHqjDyS9EWuHtTrtDHIznvdO6SA01jzrII+kx9JR7qn0jQ6I7RQUz/2mff016TZpvq56SfSLd74guZ5YZefaDuISOsVAgv5s5sX4SMzGrAmslQganM4RKMRawTEkNRg1olMLhXgv2hADYhvQShZx626N8qKlqzcnlLdLIOD+riS0Vus53nx8ONy+M71zFbCXBngq/UDGjmr5XjaF8Tbr0qq48uL3eJYXUck80Gxd/R0zZlnxjDP1Kq4wEjeZJVK5wB1OT+jXC0t6qMZ8VmGWTbRF5bja5nLeESoSTnr3JZwjX7ENg==" % device_id
print(message)
RedisPool.publish(channel_name, message)
res_data = {
"header": {
"namespace": "DuerOS.ConnectedHome.Control",
"name": "TurnOnConfirmation",
"messageId": header.get("messageId"), # messageI要和请求的一样
"payloadVersion": "1"
},
"payload": {
"attributes": []
}
}
print("return TurnOnRequest 23333")
return JsonResponse(res_data)
elif name == "TurnOffRequest":
print(device_id + "结束扫地")
message = "%s|IeYjcthpUEW54pve5ZTg6csP1HArCenUDgqZ+gbA3pLGxIKiAzg1gNMG0ZxusA+Ouwfn7cl/i7wOwhdVFhyqn2SDnsfBgPKGqlLnIwwdSSo0WcEoXTit/80cYJkFJmDUBJ9pSJXKJ0OFf9/zsIApofv9MuXC93x6v3C19lZrwTnp4c4g6eqoom8eadGhkxwi08g9HqO7Rm/IoOQlYGW0bZzlsfofnQkYBqWZdz3PBpziIZqqfZCeulMQWLsDpKKYaKhwUrOmj3JMZIfRGtQDRBMglajzWd/PQYHPnY56wiY=" % device_id
RedisPool.publish(channel_name, message)
res_data = {
"header": {
"namespace": "DuerOS.ConnectedHome.Control",
"name": "TurnOffConfirmation",
"messageId": header.get("messageId"),
"payloadVersion": "1"
},
"payload": {
"attributes": []
}
}
return JsonResponse(res_data)
elif name == "PauseRequest":
print(device_id + "暂停扫地")
message = "%s|IeYjcthpUEW54pve5ZTg6csP1HArCenUDgqZ+gbA3pLGxIKiAzg1gNMG0ZxusA+OO+k53MKNjbEsd4bVMbtiXGSDnsfBgPKGqlLnIwwdSSo0WcEoXTit/80cYJkFJmDUBJ9pSJXKJ0OFf9/zsIApofv9MuXC93x6v3C19lZrwTnp4c4g6eqoom8eadGhkxwi08g9HqO7Rm/IoOQlYGW0bZzlsfofnQkYBqWZdz3PBpziIZqqfZCeulMQWLsDpKKYaKhwUrOmj3JMZIfRGtQDRBMglajzWd/PQYHPnY56wiY=" % device_id
RedisPool.publish(channel_name, message)
res_data = {
"header": {
"namespace": "DuerOS.ConnectedHome.Control",
"name": "PauseConfirmation",
"messageId": header.get("messageId"),
"payloadVersion": "1"
},
"payload": {
"attributes": []
}
}
return JsonResponse(res_data)
elif name == "ContinueRequest":
print(device_id + "继续扫地")
message = "%s|IeYjcthpUEW54pve5ZTg6csP1HArCenUDgqZ+gbA3pLGxIKiAzg1gNMG0ZxusA+OO+k53MKNjbEsd4bVMbtiXGSDnsfBgPKGqlLnIwwdSSo0WcEoXTit/80cYJkFJmDUBJ9pSJXKJ0OFf9/zsIApofv9MuXC93x6v3C19lZrwTnp4c4g6eqoom8eadGhkxwi08g9HqO7Rm/IoOQlYGW0bZzlsfofnQkYBqWZdz3PBpziIZqqfZCeulMQWLsDpKKYaKhwUrOmj3JMZIfRGtQDRBMglajzWd/PQYHPnY56wiY=" % device_id
RedisPool.publish(channel_name, message)
res_data = {
"header": {
"namespace": "DuerOS.ConnectedHome.Control",
"name": "ContinueConfirmation",
"messageId": header.get("messageId"),
"payloadVersion": "1"
},
"payload": {
"attributes": []
}
}
return JsonResponse(res_data)