Files
banban/docs/voice_diagnostics.md
T

8.6 KiB
Raw Blame History

对话无回复诊断日志

设备端新增四类日志,按 round、session、单调运行时间关联。诊断不调整对话协议、VAD 阈值或回复等待时限。

标记 内容 可以缩小的范围
MIC-DIAG 录音打开结果及句柄、读取返回值/字节数、全零帧、峰值/平均绝对幅值、录音事件、PCM 缓冲写入丢失 区分未取得 PCM、全零输入、已有音频但没有通过 VAD、音频交给编码器前丢失
VOICE-TX 认证消息入队结果;START/END 的序号、类型、字节数、返回值和入队耗时;音频入队失败 区分请求未入队、内存分配失败、正常提交发送队列
WSS-IO 实际 TLS 写入结果、累计写入次数和字节;TLS 错误码、部分写入进度和重试;实际接收字节;关闭时的累计收发及未消费接收字节 区分入队后未完成写入、对端关闭、收到字节但应用层未获得完整消息
VOICE-RX 接收文本长度、前 192 字节、当前会话、是否通过会话准入检查;二进制消息计数 显示 START_ACK/END_ACK、未知回复、被准入检查丢弃的消息。二进制消息仍沿用原有忽略行为
VOICE-DIAG START/END 入队后的摘要、超时断开前和断开回调时的摘要 汇总入队成功/失败数、音频载荷字节、文本/二进制消息数、ACK 次数、末次收包距今时长和回复等待时长

拾音统计按一次录音累计,每秒及停止时输出。peak/mean_abs 是 16 位有符号 PCM 的绝对幅值,不是分贝;zero 统计有效读取长度内全部为零的帧。short 包括零长度以及所有非 640 字节的读取。PCM 写入不足或失败计入 ring_drops,同时记录丢失字节数。录音 tick 回调不打印,其他重复事件限频。

VOICE-TX ret=0 只代表入队成功。queue_bytes 只计成功入队的音频载荷,不含自定义包头、WebSocket 帧头、认证和控制消息。WSS-IO tx_bytes 是传给传输层并成功返回的明文字节数,含握手/帧头,不能与 queue_bytes 直接比较;TLS 失败时已写出的部分字节由 tls_write_failed/tls_write_timeout 的 sent 单独报告。正常写入首条和每 50 次打印一次,实际接收前 20 次及每 50 次打印,断开时输出累计值。tick/elapsed_ticks 使用 RTOS tick,其他带 ms 的字段使用单调毫秒。

start_ack/end_ack 按收到的文本子串统计,包含被准入检查拒绝的消息;它们不是对当前 session 的服务端确认保证。应结合 VOICE-RX 原文中的会话标识判断归属。若服务端协议不发送 ACK,ACK 为零本身不代表失败。accepted=1 表示通过外层会话准入检查,后续仍可能因 OTA、打断状态、URL 或 session 校验而未播放。文本仅保留前 192 字节,原有错误消息完整分块日志继续保留。

复现时保留开机到失败后第二次对话结束的完整串口日志。推荐按以下顺序判断:

  1. MIC-DIAG 检查读取长度、返回值和电平,结合既有 FVAD 语音确认日志判断拾音与 VAD。
  2. VOICE-TX 检查 START、音频、END 入队;queue_fail 和 ring_drops 应为零。
  3. WSS-IO 检查实际写入是否失败,关闭时是否有接收字节和残留未消费数据。
  4. VOICE-RX 检查 ACK、未知错误文本、被拒绝的回复或二进制数据。
  5. timeout-before-disconnect 检查 wait_ms。wait=2 是等待回复,wait=1 是无语音,wait=3 是 END 入队失败。response 表示现有业务逻辑已接收可用音频 URL,不等同于收到任意文本或 TTS_START。

即使 TLS 写入成功,也不能证明服务器应用收到完整录音。若已经看到归属正确的 END_ACK,却没有后续 TTS,优先按 session 查服务端识别和生成链路;若没有 ACK,也需要结合服务端接收记录判断。设备单侧日志不能完全区分服务端未处理、网络中断和回复延迟。

本机验证:python3 tools/test_voice_diag.py、python3 tools/test_conversation_timeout.py、python3 tools/test_wss_io.py、python3 tools/test_wss_receive.py。诊断测试直接编译实际函数并注入录音、缓冲区、队列及收包结果;不替代目标固件构建及设备实测。

GNSS 日志开关

inc/app_gnss_log.h 中的 APP_GNSS_LOG_ENABLED 默认是 0,关闭应用侧全部 GNSS/NMEA 原始输出、解析失败、模式切换、卫星搜索、坐标打印和 GPS 查询提示。需要恢复时可在编译参数中设置 -DAPP_GNSS_LOG_ENABLED=1。语音与 NITZ 时间校准诊断继续输出。

GNSS 数据解析、定位上报和硬件开关流程继续运行。原先放在打印参数内的四处 ql_gnss_close() 已分离为独立操作,避免禁用日志时跳过关闭定位。python3 tools/test_gnss_logging.py 在日志开启和关闭两种配置下验证真实解析代码、无卫星退出、卫星不足退出、搜索超时退出及 FAST 切换 SLOW 的关闭路径。

连接失败与提示音诊断

WSS-DIAG 使用 stage 区分 TLS 握手、TLS 读取、WebSocket 升级。日志记录阶段、实际耗时、超时配置、错误码和收包情况,不输出原始响应头、Cookie 或音频内容。TLS 握手仍是 20 秒总窗口,WebSocket 升级仍是 10 秒窗口,HTTP select 等待仍是 2 秒。

日志字段 含义和排查方向
stage=tls_handshake result=timeout phase=server hello TLS 等待服务器 Hello 超时,不能据此判断证书错误。结合 last_step、want_read/want_write、phase_ms、calls_ms 判断等待和本地计算耗时
stage=tls_connect failed_at=… verify_flags=… 记录 TLS 初始化/建连的失败步骤和证书校验标志;校验标志仅在已进行证书校验时有解释意义
stage=tls_read reason=peer_close_notify 对端发送 TLS 关闭通知;仅证明关闭由对端通知,不证明为何关闭
stage=tls_read reason=tls_eof/tls_read_timeout/tls_read_error 分别表示读取返回 0、TLS 读取超时、其他读取错误;保留原始十进制和十六进制返回值
stage=ws_upgrade reason=no_response_timeout 升级等待超时,缓冲中没有响应数据;对照 rx_bytes=0,服务端需核查请求是否到达及是否返回 101
stage=ws_upgrade reason=incomplete_headers_timeout 收到部分数据,但在窗口内未收到完整 HTTP 响应头
stage=ws_upgrade reason=http_rejected http=… 收到了完整响应头及非 101 状态;按实际 HTTP 状态检查代理或后端
stage=ws_upgrade reason=invalid_upgrade_response 收到非法或不符合 WebSocket 校验的响应;例如 101 响应的 Accept/Upgrade/Connection 不符合要求,或响应格式错误;当前不进一步细分具体头字段
stage=ws_upgrade reason=transport_error 等待升级期间底层连接出错,结合紧邻的 tls_read 日志及断开回调的具体错误描述
HTTP-DIAG stage=tcp_connect/response_header/response_body HTTP 在建连、响应头或响应体等待期间失败;timeout 表示 select 返回 0,select_error 表示负值,并记录立即保存的 errno;超时的 errno 字段为 0,不能用历史 errno 推断原因
NET-GATE leave recording=… pending=… mqtt=… action=… 记录留言键为什么被拦截,区分正在录音、等待留言请求回复和 MQTT 离线。忙碌分支当前仍播放原有网络提示并清除 pending,此次仅增加诊断
NET-GATE tip=network_ok reason=mqtt_connected voice_service=not_checked “已连上网络”仅由 MQTT 连通触发,不表示 TLS/WebSocket/语音业务已验证

例如此次无响应升级会输出类似以下摘要(示例,并非当前固件已有的历史日志):

[WSS-DIAG] stage=ws_upgrade result=failed reason=no_response_timeout http=0 elapsed_ms=10000 timeout_ms=10000 rx_bytes=0 buffered=0 header_bytes=0 parser=0 polls=...

http=0 表示尚未解析到有效状态码,不是服务器返回的 HTTP 状态码。成功 TLS 写入只证明本地传输层接受了数据,设备端仍不能独自证明请求到达服务器或定位中间链路丢包。诊断不会改变现有提示音、重试或业务状态机。

验证:python3 tools/test_wss_receive.py 覆盖完整/分段 101、零响应超时、部分响应头超时、503 拒绝、非法 Accept、对端关闭、TLS 读取超时等分支;python3 tools/test_wss_handshake.py 验证真实握手函数的超时/失败摘要及原有时限、重试和 tick 回绕。以上为主机侧函数测试,需重新构建并烧录目标固件后采集新日志。