PAYATHON 2026

为何 Alexa StateReport 看似正常,App 仍显示 Server Unresponsive?

数据阿明

结论

仅凭这份 StateReport 无法确定故障原因。报告中有状态属性、设备标识和关联令牌,还需要对照实际请求、设备发现响应和运行日志,才能判断 Alexa 是否收到并正确关联了这次响应。

“force deep queries”成功是一个值得优先跟进的线索:至少在这次测试中,状态查询可以完成。普通查询与强制查询的状态获取路径可能存在差异,但目前不能直接认定是缓存问题,也不能断言某个字段是根因。

先核对设备发现配置

检查实际发送的 Discover.Response。状态查询能返回属性,并不代表设备发现时已经正确声明了这些属性。

重点核对:

  • Milos_Room 是否与发现响应中的 endpointId 完全一致。
  • targetSetpoint、thermostatMode、temperature 和 connectivity 是否分别声明在对应接口的 properties.supported 中。
  • 需要查询状态的接口是否设置了 retrievable: true。
  • 如果声明了 proactivelyReported: true,是否确实实现了相应的 Alexa.ChangeReport 上报。

retrievable 控制状态查询,proactivelyReported 控制主动变更上报。Amazon 的状态上报指南建议对可报告属性启用这两项,并实现相应流程,供 App 获取和显示设备状态。不能只修改声明而不实现上报。状态与变更上报说明

对于 Alexa.EndpointHealth,还要检查发现阶段是否声明了 connectivity。示例中报告的值是 OK,但这个值本身不能证明 App 已收到报告。EndpointHealth 接口说明

对照请求检查 StateReport

Alexa 发出的状态查询指令名称是 Alexa.ReportState,成功响应是 Alexa.StateReport。如果 reportStatus 只是内部函数名,无须修改;需要核对的是实际处理的指令名称。

按照官方协议,成功响应应同步返回,correlationToken 应原样取自当前请求,context 应包含该设备的全部可查询属性,payload 为 {}。官方示例中的响应 endpoint 只有 endpointId,因此不能因为这份响应没有 scope 就认定它导致了故障。ReportState 与 StateReport 接口说明

排查时,特别确认:

  1. 当前响应使用的是当前请求的 correlationToken,没有复用示例或上一次请求的值。
  2. 每条响应都生成新的 messageId,并返回对应请求的 endpointId。
  3. 日志中打印的对象确实由处理函数返回,期间没有发生异常或超时。
  4. timeOfSample 对应真实采样时间。示例中的日期不能单独证明数据过期,应与当时的请求时间对照;也不要为了让数据显得新鲜,把旧数据的采样时间改成当前时间。

下面的 Python 示例仅展示响应封装方式。properties 需要由业务代码根据真实设备状态构造,不能直接复用问题中的固定数据。

from uuid import uuid4


def build_state_report(request, properties):
    directive = request["directive"]

    return {
        "context": {
            "properties": properties
        },
        "event": {
            "header": {
                "namespace": "Alexa",
                "name": "StateReport",
                "payloadVersion": "3",
                "messageId": str(uuid4()),
                "correlationToken": directive["header"]["correlationToken"]
            },
            "endpoint": {
                "endpointId": directive["endpoint"]["endpointId"]
            },
            "payload": {}
        }
    }

用两组日志区分故障位置

对同一设备分别执行一次 App 普通操作和一次“force deep queries”,比较请求是否到达、指令类型、处理耗时、返回内容,以及使用的服务部署环境。

  • 普通操作没有对应请求,强制查询有请求:优先检查发现配置和主动上报记录,并确认两次测试使用的账号、环境是否一致。此时还没有依据认定状态查询处理函数出错。
  • 两种操作都有请求,但普通操作失败或超时:沿失败请求检查鉴权、设备状态读取和异常处理,确认差异发生在哪一步。
  • 两种操作均返回成功,App 仍显示无响应:继续核对请求与响应的关联关系、发现属性是否完整,以及主动上报是否真正送达。不要只凭服务端打印的 JSON 判断成功。

由于所有设备都在发现后出现同样现象,建议先检查共用的发现逻辑、状态上报逻辑和服务配置。目前最缺少的证据是实际 Discover.Response、与示例对应的 ReportState 请求,以及 App 报错时的调用日志。有了这些信息,才能把可能原因缩小到具体环节。

备注:内容仅供参考。