150 lines
6.6 KiB
Markdown
150 lines
6.6 KiB
Markdown
# 平台注册火山与设备取参
|
||||
|
|
|
|||
|
|
2026-09-15 · 新流程:平台代注册,绑定直接下发凭据;设备本地初始化 SDK 后直接 chat/start,不再登记 boot_id 或上报初始化回执。第 3、4 节仅供旧固件兼容,新设备不要实现。
|
|||
|
|
|
|||
|
|
## 1. 业务分工
|
|||
|
|
|
|||
|
|
平台在 ble-bind 请求中绑定老人、调用火山 DynamicRegister,保存物理设备的专属密钥和 RTCAppID,拿齐配置后才返回成功。后台任务保留作恢复兜底,与请求处理共用同一注册记录,不重复注册。设备不拿 product_secret,不调用 DynamicRegister。
|
|||
|
|
|
|||
|
|
物理设备只注册一次。重新绑定老人不重复注册;聊天时的 bot_id 跟随老人变化。注册超时不等于失败,平台标记待核对,不自动重复消耗注册流程。
|
|||
|
|
|
|||
|
|
## 2. 绑定时直接返回 5 个字段
|
|||
|
|
|
|||
|
|
`POST https://82.157.201.114/api/v1/device/ble-bind`
|
|||
|
|
|
|||
|
|
输入:`{"bind_token":"<原令牌>"}`。
|
|||
|
|
|
|||
|
|
成功 data(不再包含 voice_status / voice):
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"status":"success",
|
|||
|
|
"instance_id":"<实例>",
|
|||
|
|
"product_key":"<产品>",
|
|||
|
|
"device_name":"<火山设备名>",
|
|||
|
|
"device_secret":"<本设备的火山密钥>",
|
|||
|
|
"RTCAppID":"<应用ID>"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
success 必须带齐以上字段;设备保存它们和 Wi-Fi 后再向小程序报告 success。无需另调取参接口等待 ready。开机读取本地凭据初始化 SDK,聊天请求只需 device_id 和 session_id。
|
|||
|
|
|
|||
|
|
设备请求超时设 45 秒,平台取参等待上限 35 秒。HTTP 504 / VOICE_REGISTRATION_TIMEOUT 表示等待超时;502 / VOICE_REGISTRATION_FAILED 表示失败或结果未确认;503 / VOICE_REGISTRATION_PAUSED 表示服务暂停;502 / VOICE_CONFIG_INVALID 表示配置不完整;409 / VOICE_MIGRATION_REQUIRED 表示旧设备需补交凭据。它们都不返回成功或空配置,也不删除已完成的绑定。网络超时、5xx 保留原 bind_token 和 X-Request-ID 重试,刷新时间、nonce 和签名;注册结果不确定时由平台核对,不盲目重复注册。
|
|||
|
|
|
|||
|
|
若等待期间解绑,返回 409 / BINDING_CHANGED,不下发凭据。成功响应丢失后,即使原令牌已过期,只要原绑定仍有效,也能用原令牌重新取得相同配置。
|
|||
|
|
|
|||
|
|
以下是**可选恢复接口,正常绑定不需要调用**:
|
|||
|
|
|
|||
|
|
`POST https://82.157.201.114/api/v1/device/voice-config`
|
|||
|
|
|
|||
|
|
输入:`{}`。可在绑定后直接调用,不要求先完成本次 boot 登记。
|
|||
|
|
|
|||
|
|
成功 data 示例:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"voice_status":"ready",
|
|||
|
|
"voice":{
|
|||
|
|
"instance_id":"<实例>",
|
|||
|
|
"product_key":"<产品>",
|
|||
|
|
"device_name":"<火山设备名>",
|
|||
|
|
"device_secret":"<本设备的火山密钥>",
|
|||
|
|
"RTCAppID":"<应用ID>"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
preparing 时每 5 秒重试;paused、reconcile_required 时提示平台处理;migration_required 见第 5 节。非 ready 时 voice=null。解绑后返回 409 DEVICE_UNBOUND,不下发旧凭据。
|
|||
|
|
|
|||
|
|
## 3. 旧固件兼容:开机获取 SDK 配置(新设备不调用)
|
|||
|
|
|
|||
|
|
设备照常完成 time-challenges → register 后,调用:
|
|||
|
|
|
|||
|
|
`POST https://82.157.201.114/api/v1/device/voice-runtime`
|
|||
|
|
|
|||
|
|
输入:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{"boot_id":"<本次已登记的开机UUID>"}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
输出 data 中有:
|
|||
|
|
|
|||
|
|
| 字段 | 用途 |
|
|||
|
|
|---|---|
|
|||
|
|
| voice_status / voice | 与 voice-config 相同的状态和 5 个字段 |
|
|||
|
|
| state | 当前绑定和激活状态 |
|
|||
|
|
| command | ready 时的配置命令;未就绪时可为 null |
|
|||
|
|
| command.payload.config_b64 | Base64URL 编码的配置,下例为解码后的内容 |
|
|||
|
|
| command.payload.config_mac | 现有 CFG1 配置签名 |
|
|||
|
|
| call_contract | 旧兼容字段,不据此切回旧聊天接口 |
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"contract_version":"ONBOARDING-1.1",
|
|||
|
|
"device_id":"KP01-020000260914",
|
|||
|
|
"activation_id":"<平台激活任务UUID>",
|
|||
|
|
"config_version":1,
|
|||
|
|
"binding_generation":1,
|
|||
|
|
"expires_at_ms":1789459200000,
|
|||
|
|
"iot":{
|
|||
|
|
"instance_id":"<实例>",
|
|||
|
|
"product_key":"<产品>",
|
|||
|
|
"device_name":"<火山设备名>",
|
|||
|
|
"device_secret":"<本设备的火山密钥>",
|
|||
|
|
"RTCAppID":"<应用ID>"
|
|||
|
|
},
|
|||
|
|
"bot_id":"<兼容的默认值,实际聊天仍用chat/start返回值>"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
校验 `config_mac=小写hex(HMAC_SHA256(烧录设备密钥, UTF8("CFG1\n"+config_b64)))`,再 Base64URL 解码 config_b64 并解析 JSON。核对 device_id、binding_generation 与 state 一致,expires_at_ms 未过期。新固件沿用此封装,不再提取 product_secret。
|
|||
|
|
|
|||
|
|
preparing 时自动等待,每 5 秒再次请求;不要把 preparing 当成需要解绑。获取配置后保存 5 个语音字段,以及 activation_id、config_version,再初始化 RTC SDK。
|
|||
|
|
|
|||
|
|
## 4. 旧固件兼容:SDK 初始化完成通知(新设备不调用)
|
|||
|
|
|
|||
|
|
`POST https://82.157.201.114/api/v1/device/activation-acks`
|
|||
|
|
|
|||
|
|
输入:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{"activation_id":"<上一步UUID>","config_version":1,"local_generation":1}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
activation_id、config_version 使用最新配置原值,local_generation 可使用 config_version。输出 data 中 accepted=true 表示平台已记录配置保存和 SDK 初始化完成;不是说用户已经完成第一次聊天。
|
|||
|
|
|
|||
|
|
随后每次聊天调用 chat/start,结合平台下发的凭据,用 SDK 获取 RTC 房间并收发音频。聊天结束继续调用 chat/end。
|
|||
|
|
|
|||
|
|
新设备不再调用 activation-attempts,也不发送 SDK_REGISTER activation-results。旧结果接口保留用于尚未上报完成的旧固件任务恢复。
|
|||
|
|
|
|||
|
|
## 5. 已注册旧设备的一次性迁移
|
|||
|
|
|
|||
|
|
旧固件可能只把火山密钥保存在本机,平台只有“已注册”记录。此时返回 migration_required,**不能重新注册这台设备**。
|
|||
|
|
|
|||
|
|
更新后的固件读取本机原凭据,调用:
|
|||
|
|
|
|||
|
|
`POST https://82.157.201.114/api/v1/device/voice-credentials`
|
|||
|
|
|
|||
|
|
输入:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"instance_id":"<本机原实例>",
|
|||
|
|
"product_key":"<本机原产品>",
|
|||
|
|
"device_name":"<本机原火山设备名>",
|
|||
|
|
"device_secret":"<本机原火山密钥>",
|
|||
|
|
"RTCAppID":"<本机原应用ID>"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
输出 data:`{"accepted":true}`。然后重新调用 voice-runtime。
|
|||
|
|
|
|||
|
|
平台只接受本设备已完成注册、身份匹配的旧凭据;相同内容重试不会重复写入,不允许覆盖平台已有的不同凭据。如果旧设备密钥已丢失,或注册结果不确定,需要运维核对,不能伪造凭据或盲目注册。
|
|||
|
|
|
|||
|
|
## 6. 接入与发布说明
|
|||
|
|
|
|||
|
|
以上设备 HTTP 接口均使用已有 DEVREQ1 请求头和 `{ok,code,request_id,server_time_ms,data}` 外层。设备凭据不经过小程序/蓝牙,不打印日志。平台凭据沿用既有加密存储格式。
|
|||
|
|
|
|||
|
|
后端 API 和 worker 已部署新服务器,旧 IP 暂时转发到新服务器。尚需用受控实物验证真实火山注册、设备持久化、SDK 初始化和实际通话。已有设备先备份运行凭据,不能把测试用凭据写入实物。
|