文档中心 > TVS文档

HTTP/2.0传输协议

更新时间:2019/10/29 访问次数:3794

TVS 通过 HTTP/2 长连接向客户端下发由云端发起的指令,比如闹钟、媒体播放控制等。本章将介绍如何创建和维护与 TVS 之间的 HTTP/2 连接。

关键概念

  • 帧: HTTP/2 协议的基本单位。每一帧都代表了不同的用途,比如 HEADERS 和 DATA 帧组成了基本的 HTTP 请求和返回。
  • 流: 在同一个 HTTP/2 连接内,设备与服务器交换的一系列独立、双向的帧序列。详情参阅 RFC 7540 中的流和多路复用。
  • 接口: TVS 为设备产品提供的访问 TVS 内建技能的接口(比如 SpeechRecognizer、AudioPlayer 等)。
  • 下行通道: HTTP/2 连接中建立的一个用于从云端向设备推送指令的流。下行通道由设备建立,保持半开状态,主要用于接收从云端推送的指令。
  • 云端指令: 由云端直接向设备发起的指令。比如当用户通过手机 App 调整设备的音量时,云端将直接通过下行通道向设备推送调整音量的指令(而不是通过语音请求)。

注意:

设备在同一个连接内应当只建立一条下行通道。

接入要求

设备和 TVS 建立 HTTP/2 连接,必须先通过 TVS 的 登录授权 获得 Access Token。

所有请求头都应当包含 Access Token,类似于:

:method = POST
:scheme = https
:path = /tvs/events
authorization = Bearer {YOUR_ACCESS_TOKEN}
content-type = multipart/form-data; boundary={BOUNDARY_TERM}

环境信息

测试环境域名: test-h2.g-aicloud.alibaba.com
提测环境域名: test2-h2.g-aicloud.alibaba.com
协议:https
端口:443

创建 HTTP/2 连接

设备开机后应当和 TVS 建立 单条 HTTP/2 连接。该连接用于处理所有指令和事件,包括通过下行通道流向设备推送的所有指令。

与 TVS 维持连接的要求:

  • 创建下行通道流
  • 向 TVS 同步设备组件状态

1、创建下行通道流,设备需要在连接开启后的 10 秒内/tvs/directives 发出一个 GET 请求,类似这样:

:method = GET
:scheme = https
:path = /tvs/directives?requestId=xxx
authorization = Bearer {YOUR_ACCESS_TOKEN}

其中,url参数requestId表示请求id,用于标识此次下行通道创建请求,客户端需要生成一个32位的随机字符串(小写字母+数字),并尽量保证唯一,例如:6cd8a3539f174ac098089b0f5d56f149。

如果请求成功,这个连接会维持在半开状态。

2、下行通道建立成功之后,设备应当向 TVS 同步自己的组件状态。实现方式是在现有的连接中( 注意: 不要开新连接)发起一个新的事件流向 /tvs/events 发出一个 POST 请求。该事件流应当在收到响应之后关闭。下面是一个 SynchronizeState 事件的例子:

:method = POST
:scheme = https
:path = /tvs/events
authorization = Bearer {YOUR_ACCESS_TOKEN}
content-type = multipart/form-data; boundary={BOUNDARY_TERM_HERE}

--{BOUNDARY_TERM_HERE}
Content-Disposition: form-data; name="metadata"
Content-Type: application/json; charset=UTF-8

{
    "context": [
       // 上下文对象的数组,用于告知 TVS 设备端所有组件的状态。
    ],
    "event": {
        "header": {
            "namespace": "System",
            "name": "SynchronizeState",
            "messageId": "{STRING}"
        },
        "payload": {
        }
    }
}

--{BOUNDARY_TERM_HERE}--

状态同步之后,设备即可利用这个连接处理以下事情:

  • 向 TVS 发送事件并接收指令响应
  • 从下行通道接收云端发起的指令

注意:

每个事件和它的响应都在自己独立的事件流中发送;响应接收完毕之后应该将流关闭。

维持 HTTP/2 连接

一旦连接建立,设备需要知道如何管理事件流、下行通道流、心跳、超时和云端发起的断开。

需要注意的点

  • 建议使用 10ms、320 字节分片(每次发送 320 字节的 DATA 帧)、流式地向 TVS 传输捕获到的音频。过大的分片可能会导致不必要的缓冲,导致延迟增加。

  • 向 TVS 发送的音频编码:

  • 16bit 线性 PCM(LPCM16)

  • 16kHz 采样率
  • 单声道
  • Little endian 字节序

详见语音识别接口

  • 单个 HTTP/2 连接仅支持 10 个并发的流,包括事件流、下行通道和心跳。再次提醒,事件流收到响应之后应该关闭。

  • 大多数请求库对读取时间可能会有超时机制。由于 TVS 的下行通道流是一个长连接,在相当长一段时间内即便没有指令下发也应当维持开启状态。因此需要将读取超时设置为至少 60 分钟

事件流生命周期

每一个事件都使用自己独立的流发送。通常情况下一条流会在当 TVS 返回指令和对应的音频附件之后关闭。

请求应该是顺序处理的。也就是说,应该在 TVS 开始响应上一个请求(设备收到了响应头)之后才发出新的请求。

  1. 设备打开一个流并发出一个 Multipart 消息,包含一个 JSON 格式的事件体和最多一个二进制音频附件。
  2. TVS 在同一个流里返回一个 Multipart 消息,包含一个或多个 JSON 格式的指令和对应的音频附件。其中 PlaySpeak 指令里 cid: 开头的 url 对应音频附件里的头。
  3. 接收响应之后,关闭该事件流。

注意:

设备可能会收到多个指令(JSON)之后才收到对应的音频附件。因此,设备应当能够关联指令和它对应的音频附件。

下行通道生命周期

一些指令也可能会并行于事件流地从下行通道发送到设备。下行通道通常用于接收云端发起的指令。

  1. 连接到 TVS 之后的 10 秒内应该向 directives 路径发起一个 GET 请求。
  2. 下行通道流用于向设备发送云端发起的指令和附件,比如说计时器、闹钟,以及通过 App 远程发起的操作。和事件流不同,下行通道流不应立刻关闭,而应该维持长时间的半开状态。
  3. 当下行通道被关闭,设备应该立刻重新建立新的下行通道,以确保及时接收云端指令。

心跳和超时

设备应该采取下列其中一个措施来维持连接,遇到失败后需要关闭连接并重试。

  • 连接空闲时每 5 分钟 向 TVS 发送一个 PING
  • 连接空闲时每 5 分钟/tvs/ping 接口发出一个 GET 请求

示例:

:method = GET
:scheme = https
:path = /tvs/ping
authorization = Bearer {YOUR_ACCESS_TOKEN}

一旦 PING 失败,设备应当关闭当前连接,并立刻重新创建一个新的连接。

注意:

如果使用 libcurl,设备需要每 5 分钟向 /tvs/ping 发一次 GET 来维持连接。

服务端主动断开连接

当服务器主动断开了连接,设备应该:

  1. 开启一个新的连接,并将所有新的请求移到这个连接上进行
  2. 在所有已开启的请求(以及他们对应的流)都处理完毕之后关闭旧的连接。
  3. 维持连接关闭前已经打开的流播 URL(比如音乐播放),直到播放结束

如果重新连接失败,设备应该采取适当的间隔重试机制。

FAQ

关于此文档暂时还没有FAQ
返回
顶部