主题
4.2 设备注册与绑定
本篇介绍设备如何在 JoyInside 平台完成注册与绑定。
接入前需先理清一个关键点: 平时说的「设备ID」通常指硬件SN,而平台建连、鉴权实际使用的是botId——本文会带您弄清 productId、botId、SN 三层身份的映射关系。
产品与智能体
- 产品: 一类硬件形态的对外身份,承载产品名称、版本、型号、开发板信息、序列号前缀、产品描述等硬件维度的信息,同时作为设备绑定的归属单元
- 智能体: 挂在产品下的「交互大脑」,承载人设、音色、技能、指令、交互策略、MCP 服务等交互维度的配置。
⚠ 当前一个产品下仅有一个「默认智能体」,暂不支持新建 / 切换多智能体,后续版本会开放。
三层身份映射
| 身份 | 是什么 | 哪里拿 | 谁用 |
|---|---|---|---|
| productId | 产品唯一标识,一个产品对应一个产品型号, 一个默认智能体。智能体承载人设、音色、技能、指令等 | 产品管理页, 产品ID | 注册设备、调用 API |
| botId | 设备在平台的唯一标识,注册设备后生成,WS 建联必需 | 设备管理页,设备「ID」列 | WS 建联参数、getToken 参数 |
| sn / deviceId | 厂商为每个产品分配的序列号,硬件物理标识 | 厂商自行分配(建议作为 deviceId) | 注册设备时传入 |
典型流程:
设备注册
注册三要素
特别说明:接口参数productId,新产品对接请直接使用产品productId,历史产品保持兼容。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| vendorId | String | 是 | 厂商唯一标识 |
| productId | String | 是 | 产品唯一标识 |
| deviceId | String | 是 | 设备唯一标识,厂商保证唯一,建议用设备 SN |
| type | String | 是 | APP_ROBOT(测试设备) / PHYSICAL_ROBOT(生产设备) |
| name | String | 是 | 设备名称 |
| deviceModel | String | 否 | 设备型号,非标准参数, 在运营平台创建且与IOT指令技能有关 |
| timbreId | String | 否 | 音色 id |
| desc | String | 否 | 描述 |
| resourceAuthedList | List<String> | 否 | JoyInside支持播放自有以及三方的音乐、故事资源。 通过该字段指定设备后续进行资源检索、播放及计费所使用的资源提供方。 若不传该字段,则默认使用 JoyInside 自有资源。 注意:如需使用该字段,请提前联系JoyInside产品运营完成相关配置。 取值: WANG_YI_CLOUD:网易云音乐 |
注册接口:
| 项 | 值 |
|---|---|
| URL | https://api.joyinside.com/device/register |
| 方式 | POST |
| Header | Authorization: Bearer ${accessToken} |
注册方式:
- 测试阶段:运营平台设备管理处手动添加单个虚拟设备
- 正式接入:每台设备开机配网后通过 API 单设备注册(
type=PHYSICAL_ROBOT)
注册示例(Python,点击展开)
python
headers = {"Authorization": "Bearer " + token}
params = {
"vendorId": "企业ID",
"productId":"产品ID", # 新创建的产品必须使用该参数
"deviceId": "建议用SN编码",
"type": "APP_ROBOT", # 测试设备
"name": "测试"
}
res = requests.post("https://api.joyinside.com/device/register", headers=headers, json=params)
# 返回 data 字段即为 botId返回示例(点击展开)
python
{
"state": "SUCCESS",
"code": "0000",
"result": "创建成功",
"data": "xxxxx" # ← 这就是 botId
}特别注意:一个deviceId只能注册一个设备,如果重复注册,则返回已经注册的botId,不会生成新的botId,不会更新第一次注册的信息
设备绑定角色(AI 伙伴)
一台设备(botId)可以绑定一个 AI 角色(系统角色或自定义角色),绑定后该设备的对话人设、音色、开场白等均以该角色为准。角色不通过 WS 建连参数传入,改用 HTTP 绑定接口。
| 操作 | 说明 | 接口 |
|---|---|---|
| 绑定角色 | 把 roleId 绑定到 botId | /soulmate/role/botBindRole/save |
| 查询绑定 | 查 botId 当前绑定的角色 | /soulmate/role/botBindRole/get |
⚠ 旧方式
roleCode建连参数不再推荐,新接入统一用绑定接口。 ⚠ 切换角色需重建 WebSocket 连接才能生效(见 9.5 音色/查询类)。 绑定接口走 HTTP,通常由小程序或后台调用,不是设备端 WS 协议。系统角色 / 自定义角色列表查询、绑定接口完整字段见 附录 A.4 AI 角色管理。
设备绑定用户(uid)
一台设备(botId)可以绑定一个用户(uid),绑定后该设备的对话归属到这个用户名下,产生长期记忆与聊天报告。uid 是用户唯一标识(如京东用户 pin,也可由厂商自行维护),详细规则(≤128 字节、必须真实)见 4.3 重要参数介绍。
| 操作 | 说明 | 接口 |
|---|---|---|
| 绑定用户 | 把 uid 绑定到 botId | /device/bindUser |
| 查询绑定 | 查 botId 当前绑定的 uid | /device/queryBotBind |
| 解绑用户 | 解除 uid 与 botId 的绑定 | /device/unbindUser |
上述HTTP接口,通常由小程序或后台调用。接口明细见 附录 A.6 用户绑定。
uid 在 WS 建联时的传递
绑定后,设备端 WS 建联与上行事件里也可带 uid(非必传,但传了就必须一致):
- 可以不传:不传 uid 时,服务端按匿名会话处理
- 传了就必须一直传:同一设备要么始终传 uid,要么始终不传,禁止值与 null 混着来
- 禁止所有设备用固定值:如所有设备都传
123456,会导致不同用户的记忆混在一起
如接入有声书技能,无论是否关联用户场景,
ws 建连以及有声书的全部上行事件,uid 参数要么全部增加,要么全部不增加,且 uid 必须保持一致。⚠ uid 长度不超过 128 字节,且必须真实。完整规则见 4.3 重要参数介绍。
互踢机制
同一个 botId 同时建立两个 WebSocket 连接时,后建的连接会踢掉先建的连接,先建的连接收到
REPEAT_CLIENT_SESSION事件后被关闭。
为什么这么设计:一个 botId 代表一台设备,同一台设备不应同时有两个活跃对话通道(否则上下文、打断、TTS 播放都会混乱)。
互踢时序
常见触发场景
| 场景 | 后果 |
|---|---|
| 调试时开两个 Demo 实例用同一 botId | 互相踢,对话中断 |
| 生产设备重连时未等旧连接释放就建新连接 | 旧连接被踢 |
| 同一台设备多处入口同时建联 | 后建的踢先建的 |
| 客户端多线程导致的重复建连 | 互相踢 |
排查:设备端有REPEAT_CLIENT_SESSION 事件出现,说明同一 botId 有多处连接。排查设备是否重复建联,或是否有调试实例在跑。
下一步
- 核心参数理解:4.3 重要参数介绍
- 理解语音对话协议:4.4 WebSocket语音通道
- 排查互踢问题:9.1 建联失败类