# UVS介绍

说明

UVS协议是一个相对简单的协议,为厂商接入提供方便,降低设备运行要求,本协议采取websocket进行通讯。

# 创建设备

在使用UVS协议接入UniOS前,需要先在智能设备平台创建设备。

# 授权认证

连接到 UniOS之前,你需要做以下动作

  1. 参考授权认证API,实现设备端的授权流程
  2. 通过设备中心API,获取到设备token

# 连接协议(使用 WebSocket 连接到UniOS)

  1. device_id 是指每个设备的唯一标识,是通过设备授权流程获取的udid;(UniOS将会在设备token获取、websocket连接时,进行验证,非白名单设备将无法使用UniOS)
  2. 将上面步骤获取的 设备token 和 device_id 以及appkey作为URL参数,连接websocket:
    安全地址:wss://uvs.hivoice.cn/embedded/v1?token={device_token}&device_id={device_id}&appkey={appkey}
    非安全地址:ws://uvs.hivoice.cn/embedded/v1?token={device_token}&device_id={device_id}&appkey={appkey}

注意

强烈建议选择安全地址(wss)接入UniOS,除非设备本身有无法解决的限制。

# 交互协议说明

设备发送给UniOS云端的请求
UniOS中,我们把设备发送到服务端的请求称为事件(event),一次发送一个请求object,每次发送请求时,均需要同步发送unios_header和unios_context。

{
  "unios_version":"1.0.0",
  "unios_header": {...},
  "unios_context": {...},
  "unios_event": {...}
}
1
2
3
4
5
6

通用请求unios_version
unios_version为协议版本号,采用三位数字,中间以英文句号(.)隔开,目前版本号为:1.0.0
后续协议的升级会通过升级版本号体现差异

通用请求unios_header
unios_header 中的内容为向云端报告本次请求来源(如硬件设备)的基础信息,具体包含的内容如下:

"unios_header": {
  "authorization": "xxxxxx",
  "appkey": "xxxxxx",
  "device":{
       "sdk_version": "1.0.0",
       "device_id": "xxxxxxx",
       "imei": "xxx.xxx.xxx.xxx",
       "location": {
          "latitude": 132.56481,
          "longitude": 22.36549
        },
        "platform": {
          "name": "android",
          "version": "8.0.1"
        }
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
参数 类型 说明 必填
authorization String 设备token,每一次都需要带上去,用于设备鉴权,终端保证token不过期
appkey String appkey
device Object 设备信息
device.sdk_version String 设备sdk版本号
device.device_id String 设备的唯一标识
device.imei String 设备imei号
device.location Object 设备的位置信息,设备端可通过GPS获取或在配网时候从手机获取后写入设备中
device.location.latitude Float 纬度,和 longitude 成对出现
device.location.longitude Float 经度,和 latitude 成对出现
device.platform Object 设备系统平台信息
device.platform.name String 系统平台名称。取值:android, linux, ios,web,freertos。请注意:全部字母均为小写
device.platform.version String 系统平台版本

通用请求 unios_context
unios_context 用于向云端同步当前的设备状态,以功能模块为区分,代表发送请求时设备最新的信息。每次对服务端发起的请求都要包含它,unios_context 中需要包含所有已经实现的设备模块的信息。

"unios_context": {
  "system": {...},
  "recognizer": {...},
  "speaker": {...},
  "tts_player": {...},
  "audio_player": {...},
  "alarm": {...},
  "screen": {...},
  "template": {...},
  "video_player": {...},
  "wakeword": {...},
  "playback_controller": {...},
  "launcher": {...},
  "device_controller": {...}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
参数 类型 说明 必填
system Object 系统信息
recognizer Object 语音识别器信息
tts_player Object TTS播放器,这是UniOS交互的基础
audio_player Object 音频播放器信息
speaker Object 扬声器信息
alarm Object 设备闹钟信息,若未实现设备闹钟,该项可不出现。
screen Object 设备屏幕信息,若设备无屏,该项可不出现。
template Object 设备模板显示信息。若设备不实现云端模板,该项可不出现。
video_player Object 视频播放器。若设备不支持视频播放,该项可不出现。
playback_controller Object 播放控制。若设备没实现音频播放或视频播放,该项可不出现。
launcher Object 调准控制器。若设备不支持启动器页面跳转等能力,该项可不出现。
device_controller Object 设备控制器
wakeword Object 唤醒词管理模块

上行事件(unios_event)
不同功能模块对应的unios_event不尽相同,具体详见设备能力说明中各功能模块具体描述。

UniOS云端发送给设备的回复
UniOS中,我们把设备接收到服务端下行信息称为指令(directive),一次收到一个unios_meta和unios_directives集,设备需要按unios_directives列表顺序执行操作。

{
  "unios_meta": {...},
  "unios_directives": [
    {
      "header": {
        "name": "xxx"
      },
      "payload": {...}
    },
    {
      "header": {...},
      "payload": {...}
    }
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

通用回复 unios_meta
unios_meta 中主要是云端回复的元数据,代表本次回复是对某一个event的回复。

{
  "unios_meta": {
    "trace_id": "xxxxxx",
    "message_id": "xxxxx" //当云端主动发送directive时,该字段不会出现
  }
}
1
2
3
4
5
6
参数 类型 说明 必须出现
trace_id String 本次交互的跟踪标识,云端服务之间调用链路追踪,建议打印在系统日志中。排查问题方便
message_id String 本次回复对应的请求的唯一标识,与event中的message_id一致。当云端主动发送directive时,该字段不会出现

注意:设备请求发送成功,但云端不返回执行时,会返回如下的结果:

{
  "unios_meta": {
    "trace_id": "xxxxxx",
    "message_id": "xxxx"
  },
  "unios_directives": []
}
1
2
3
4
5
6
7

# 功能模块说明

注意

  • 以下要求必须实现的event和directive,需要按要求实现
  • 以下可选实现的event和directive,你可以根据自身设备的需求进行实现
模块名称 说明 实现要求
语音识别器(recognizer) 语音识别器,这是UniOS交互的基础 必须
TTS播放器(tts_player) TTS播放器,这是UniOS交互的基础 必须
音频播放器(audio_player) 音频播放器,播放的内容可能是音乐、新闻、闹钟响铃或TTS语音 必须
系统相关(system) 系统相关 必须
本地闹钟(alarm) 设备本地闹钟 可选
扬声器控制(speaker) 扬声器控制 可选
视频播放器(video_player) 视频播放器 可选
播放控制(playback_controller) 播放控制,在部分场景下,用户可通过触控或按键控制音频播放进度 可选
屏幕控制(screen) 屏幕控制 可选
模板展示(template) 模板展示,用于通过界面模板给用户反馈更丰富的信息 可选
跳转控制器(launcher) 跳转控制器 可选
唤醒词管理(wakeword) 唤醒词管理 可选
设备控制器 (device_controller) 设备控制器 可选

# 完整示例

下面举例一个相对完整的事件(event)和指令(directive)的示例
语料:我想听笑话
请求event示例

{
    "unios_version": "1.0.0", 
    "unios_header": {
        "appkey": "xxx", 
        "device": {
            "sdk_version": "1.0.0", 
            "imei": "1.2.3.4", 
            "platform": {
                "version": "8.0.1", 
                "name": "android"
            },
            "location": {
                "latitude": 132.56481, 
                "longitude": 22.36549
            }, 
            "device_id": "xxx"
        }, 
        "authorization": "xxx"
    }, 
    "unios_context": {
        "audio_player": {
            "version": "1.0", 
			"state": "IDLE", 
			"resource_id": ""
        }, 
        "screen": {
            "state": "ON", 
            "version": "1.0", 
            "type": "percent", 
            "brightness": 78
        }, 
        "recognizer": {
            "version": "1.0"
        }, 
        "playback_controller": {
            "version": "1.0"
        }, 
        "launcher": {
            "version": "1.0"
        }, 
        "alarm": {
            "active": {
                "alarm_id": ""
            }, 
            "version": "1.0", 
            "local": [
                {
                    "alarm_id": "xxxxx", 
                    "timestamp": 1558598737
                }
            ]
        }, 
        "tts_player": {
            "version": "1.0"
        }, 
        "system": {
            "factory_reset": "true", 
            "reboot": "true", 
            "version": "1.0", 
            "software_updater": "true", 
            "device_modes": "true"
        }, 
        "video_player": {
            "state": "IDLE", 
            "version": "1.0"
        }, 
        "speaker": {
            "volume": 80, 
            "version": "1.0", 
            "type": "percent"
        },
        "wakeword": {
            "version": "1.0"
        }
    }, 
    "unios_event": {
        "header": {
            "name": "recognizer.text_in", 
            "message_id": "1258541258"
        }, 
        "payload": {
            "query": "我想听笑话", 
            "with_tts": "true"
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

返回directive示例

{
    "unios_meta": {
        "trace_id": "xxxxxx",
        "message_id": "xxxx"
    },
    "unios_directives": [
        {
            "header": {
                "name": "tts_player.audio_out"
            },
            "payload": {
                "behavior": "SERIAL",
                "metadata": {
                    "text": "那我就说个笑话吧,请听笑话【都是艺术家】"
                },
                "url": "http://tts.xxx.cn/live/a50848a955b47b8ab794bfa9381906994ce9b3ea.mp3"
            }
        },
        {
            "header": {
                "name": "audio_player.audio_out"
            },
            "payload": {
                "control": "PLAY",
                "url": "http://xxxx.com/ctimusic/joke/5202502499014251275.mp3",
                "offset": 0,
                "resource_id": "86",
                "behavior": "IMMEDIATELY"
            }
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 错误码说明

云端错误码
当设备端发送event出错时,云端通过name为system.error的directive返回错误码
错误码说明参见请求出错