以下是一份基于代码实现整理的 WebSocket 通信协议文档,概述客户端(设备)与服务器之间如何通过 WebSocket 进行交互。该文档仅基于所提供的代码推断,实际部署时可能需要结合服务器端实现进行进一步确认或补充。
设备端初始化
Application:Protocol 接口的 WebSocket 协议实例(WebsocketProtocol)建立 WebSocket 连接
OpenAudioChannel():CONFIG_WEBSOCKET_URL)Authorization, Protocol-Version, Device-Id, Client-Id)Connect() 与服务器建立 WebSocket 连接发送客户端 “hello” 消息
连接成功后,设备会发送一条 JSON 消息,示例结构如下:
{
"type": "hello",
"version": 1,
"transport": "websocket",
"audio_params": {
"format": "opus",
"sample_rate": 16000,
"channels": 1,
"frame_duration": 60
}
}
其中 "frame_duration" 的值对应 OPUS_FRAME_DURATION_MS(例如 60ms)。
服务器回复 “hello”
"type": "hello" 的 JSON 消息,并检查 "transport": "websocket" 是否匹配。后续消息交互
设备端和服务器端之间可发送两种主要类型的数据:
在代码里,接收回调主要分为:
OnData(...):binary 为 true 时,认为是音频帧;设备会将其当作 Opus 数据进行解码。binary 为 false 时,认为是 JSON 文本,需要在设备端用 cJSON 进行解析并做相应业务逻辑处理(见下文消息结构)。当服务器或网络出现断连,回调 OnDisconnected() 被触发:
on_audio_channel_closed_(),并最终回到空闲状态。关闭 WebSocket 连接
CloseAudioChannel() 主动断开连接,并回到空闲状态。在建立 WebSocket 连接时,代码示例中设置了以下请求头:
Authorization: 用于存放访问令牌,形如 "Bearer <token>"Protocol-Version: 固定示例中为 "1"Device-Id: 设备物理网卡 MAC 地址Client-Id: 设备 UUID(可在应用中唯一标识设备)这些头会随着 WebSocket 握手一起发送到服务器,服务器可根据需求进行校验、认证等。
WebSocket 文本帧以 JSON 方式传输,以下为常见的 "type" 字段及其对应业务逻辑。若消息里包含未列出的字段,可能为可选或特定实现细节。
Hello
例:
{
"type": "hello",
"version": 1,
"transport": "websocket",
"audio_params": {
"format": "opus",
"sample_rate": 16000,
"channels": 1,
"frame_duration": 60
}
}
Listen
"session_id":会话标识"type": "listen""state":"start", "stop", "detect"(唤醒检测已触发)"mode":"auto", "manual" 或 "realtime",表示识别模式。例:开始监听
{
"session_id": "xxx",
"type": "listen",
"state": "start",
"mode": "manual"
}
Abort
例:
{
"session_id": "xxx",
"type": "abort",
"reason": "wake_word_detected"
}
reason 值可为 "wake_word_detected" 或其他。
Wake Word Detected
例:
{
"session_id": "xxx",
"type": "listen",
"state": "detect",
"text": "你好小明"
}
IoT
例:
{
"session_id": "xxx",
"type": "iot",
"descriptors": { ... }
}
或
{
"session_id": "xxx",
"type": "iot",
"states": { ... }
}
Hello
"type": "hello" 和 "transport": "websocket"。audio_params,表示服务器期望的音频参数,或与客户端对齐的配置。STT
{"type": "stt", "text": "..."}LLM
{"type": "llm", "emotion": "happy", "text": "😀"}TTS
{"type": "tts", "state": "start"}:服务器准备下发 TTS 音频,客户端进入 “speaking” 播放状态。{"type": "tts", "state": "stop"}:表示本次 TTS 结束。{"type": "tts", "state": "sentence_start", "text": "..."}
IoT
{"type": "iot", "commands": [ ... ]}音频数据:二进制帧
客户端发送录音数据
客户端播放收到的音频
以下简述设备端关键状态流转,与 WebSocket 消息对应:
Idle → Connecting
OpenAudioChannel() → 建立 WebSocket 连接 → 发送 "type":"hello"。Connecting → Listening
SendStartListening(...),则进入录音状态。此时设备会持续编码麦克风数据并发送到服务器。Listening → Speaking
{"type":"tts","state":"start"}) → 停止录音并播放接收到的音频。Speaking → Idle
{"type":"tts","state":"stop"}) → 音频播放结束。若未继续进入自动监听,则返回 Idle;如果配置了自动循环,则再度进入 Listening。Listening / Speaking → Idle(遇到异常或主动中断)
SendAbortSpeaking(...) 或 CloseAudioChannel() → 中断会话 → 关闭 WebSocket → 状态回到 Idle。连接失败
Connect(url) 返回失败或在等待服务器 “hello” 消息时超时,触发 on_network_error_() 回调。设备会提示“无法连接到服务”或类似错误信息。服务器断开
OnDisconnected():on_audio_channel_closed_()鉴权
Authorization: Bearer <token> 提供鉴权,服务器端需验证是否有效。会话控制
session_id,用于区分独立的对话或操作。服务端可根据需要对不同会话做分离处理,WebSocket 协议为空。音频负载
sample_rate = 16000,单声道。帧时长由 OPUS_FRAME_DURATION_MS 控制,一般为 60ms。可根据带宽或性能做适当调整。IoT 指令
"type":"iot" 的消息用户端代码对接 thing_manager 执行具体命令,因设备定制而不同。服务器端需确保下发格式与客户端保持一致。错误或异常 JSON
{"type": ...},客户端会记录错误日志(ESP_LOGE(TAG, "Missing message type, data: %s", data);),不会执行任何业务。下面给出一个典型的双向消息示例(流程简化示意):
客户端 → 服务器(握手)
{
"type": "hello",
"version": 1,
"transport": "websocket",
"audio_params": {
"format": "opus",
"sample_rate": 16000,
"channels": 1,
"frame_duration": 60
}
}
服务器 → 客户端(握手应答)
{
"type": "hello",
"transport": "websocket",
"audio_params": {
"sample_rate": 16000
}
}
客户端 → 服务器(开始监听)
{
"session_id": "",
"type": "listen",
"state": "start",
"mode": "auto"
}
同时客户端开始发送二进制帧(Opus 数据)。
服务器 → 客户端(ASR 结果)
{
"type": "stt",
"text": "用户说的话"
}
服务器 → 客户端(TTS开始)
{
"type": "tts",
"state": "start"
}
接着服务器发送二进制音频帧给客户端播放。
服务器 → 客户端(TTS结束)
{
"type": "tts",
"state": "stop"
}
客户端停止播放音频,若无更多指令,则回到空闲状态。
本协议通过在 WebSocket 上层传输 JSON 文本与二进制音频帧,完成功能包括音频流上传、TTS 音频播放、语音识别与状态管理、IoT 指令下发等。其核心特征:
"type":"hello",等待服务器返回。"type" 为核心字段标识不同业务逻辑,包括 TTS、STT、IoT、WakeWord 等。服务器与客户端需提前约定各类消息的字段含义、时序逻辑以及错误处理规则,方能保证通信顺畅。上述信息可作为基础文档,便于后续对接、开发或扩展。