关于 terra-streaming
terra-streaming 是构建 Terra API 实时穿戴设备数据流应用的技能,面向开发者说明生产端与消费端架构、令牌处理、WebSocket 协议及常见问题。
主要功能
- 01生产端与消费端架构指引
- 02令牌生命周期与认证指引
- 03WebSocket 协议和重放细节
- 04穿戴设备数据类型与限制
- 05CLI 和 MCP 账户检查指引
适用场景
- 01构建实时穿戴设备数据流应用
- 02实现后端 WebSocket 消费端
- 03排查凭据或用户连接问题
MCP 相关
说明聊天助手可使用 Terra API 管理 MCP 服务检查账户。MCP 不会签发生产端或消费端套接字令牌;这些令牌由后端签发。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ tryterra/ agent-skills --skill terra-streaming安装后在 Claude Code 中输入/terra-streaming确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.jsonREADME.mdreferences/android.mdconsumer-protocol.mddata-types.mdflutter.mdios.mdreact-native.mdwear-os.md详细介绍
Terra API 流式传输最佳实践
构建基于 Terra API Streaming(实时)API 的指南,该 API 可从可穿戴设备实时传送大约每秒一次的指标。本技能内含架构说明和协议注意事项;平台设置和完整的消费者协议位于 references/ 中。
从示例应用开始
对于新应用,请从已发布的示例开始,并根据用户的需求进行调整:React Native 生产端使用 streaming-mobile-app,Web 消费端使用 streaming-consumer-web-app。运行 terra version;如果缺少 CLI,请提出安装建议(见下文)。然后列出当前目录并克隆最匹配的示例:
terra examples list --select name,title,description
terra examples clone streaming-mobile-app my-app
这两个示例都不需要登录。阅读下载的 README 和 AGENTS.md,并按照 next_steps 安装依赖、完成配置并运行,然后再基于它进行开发。克隆操作只会下载文件。对于现有应用,请将示例用作参考,并在原处调整相关部分。对于无法运行 CLI 的聊天助手,请提供这些命令,让用户在自己的终端中运行,或链接到 https://github.com/tryterra/terra-examples/tree/main/examples/streaming-mobile-app 上的源代码。
账户工具:CLI 或 MCP
流式传输 WebSocket 接口没有账户命令,而且CLI 和 MCP 都不会签发套接字进行身份验证所用的生产端或消费端令牌:这些令牌由你的后端按照本技能所述的流程,为每个会话签发。账户工具负责的是更底层的部分:后端持有的长期凭证,以及要传输数据的用户是否实际存在。
流无法打开,通常是因为凭证没有正确的作用域、用户 ID 没有关联的连接,或此环境中从未启用相应的提供商。这三项检查都是只读的,因此请在调试套接字之前先运行:
terra environments list --select dev_id,name
terra data-tokens list --env <dev-id> --select token_id,name,scopes,expires_at,last_used_at,revoked_at
terra users list --env <dev-id> --user-id <uuid> --select user_id,provider,active
terra unified-api sources list --env <dev-id>
data-tokens list 可以在不打印机密的情况下回答凭证相关问题:它会显示哪些令牌存在、每个令牌的作用域,以及令牌是否已过期或被撤销。不要为了确认令牌是否可用而签发新令牌,也不要在这里使用 terra environments retrieve-api-key:它会打印环境的 API 密钥和 Webhook 签名密钥,这两项信息都无法说明套接字的情况,而且在 CI 中,它们都会出现在作业日志里。
签发令牌是设置步骤,而不是诊断步骤。如果列表确实显示没有可用令牌,terra data-tokens create --env <dev-id> --name streaming --scopes auth:write 会返回 Bearer 令牌;每个环境可以同时存在多个令牌,因此旧令牌会继续生效,直到你将其撤销。通过 MCP 签发数据令牌需要用户在控制面板中批准,且需要默认 MCP 登录不具备的访问级别,因此这一步使用 CLI 更简单。
在编码 Agent(Claude Code、Codex、Cursor 等,在用户的设备或云端运行)中,请使用 CLI;如果尚未安装,请提供安装建议:macOS 和 Linux 上运行 curl -fsSL https://cli.tryterra.co/install.sh | sh,Windows PowerShell 中运行 irm "https://cli.tryterra.co/install.ps1" | iex,或者在用户已经使用 Homebrew 或 npm 的情况下通过它们安装。在聊天助手(claude.ai、Claude Desktop、ChatGPT)中,请使用 Terra API 管理 MCP 服务,即使它能够运行代码也是如此:其沙盒无法安装 CLI 或登录。每条管理命令都是一个工具,其名称和 method 与命令相对应(terra users list 对应 users_read,method: "list")。只有 CLI 提供 terra data-api、terra admin-api 和 terra examples;MCP 没有与 --select 和 --jq 对应的功能。terra-cli 和 terra-mcp 技能包含防护措施(确认更改、避免在对话记录中泄露凭证)、错误说明,以及按任务划分的操作手册。它们用于管理集成,并不能替代本技能所述的 API 调用。
流式传输与健康和健身
Streaming API 仅用于实时、亚秒级至秒级信号。RT SDK 接受 17 个 DataTypes 值,涵盖心脏数据(心率、HRV、RR 间期、ECG)、运动数据(步数、步频、距离、速度、爬楼层数、活动)、骑行数据(功率、骑行踏频)、运动传感器数据(加速度、陀螺仪)、能量数据(卡路里、MET)和位置。完整枚举请参阅 references/data-types.md。跨度更长的数据——训练、睡眠、每日总量、身体数据、营养——应使用 Unified API,而非此 API。如果你需要的是已完成训练的摘要,而不是实时数据流,那么你用错了 API。连接 Apple Health、Samsung Health 或 Health Connect 应使用移动 SDK(terra-mobile-sdk),而非 Real-Time SDK。
只有在设备通过 BLE、ANT+ 或受支持的自定义蓝牙协议实际广播时,设备才会出现在数据流中(例如 Polar H10 或 Wahoo TICKR 等心率带,以及部分手表)。不广播就没有数据流。
请求某种数据类型,不代表一定能收到该数据。 Terra API 不会按设备限制或筛选数据:代理会不加处理地传递负载,因此实际收到什么完全取决于可穿戴设备自身的广播配置。大多数心率带只会提供心脏数据,无论 SDK 如何配置,它们都不会生成 STEPS 或 LOCATION。请按信号分别呈现状态,并优雅地处理数据缺失,而不要将缺少某种数据类型视为错误。请参阅 references/data-types.md。
架构:生产者、代理、消费者
实时流式传输包含四个部分,你需要在它们之间建立三个连接。请参阅 getting-started。
- 可穿戴设备 – 通过 BLE 或 ANT+ 广播的心率带、手表或传感器。
- 生产者 – 运行 Terra API Real-Time(RT)SDK 的移动应用。它接收可穿戴设备的数据并转发给 Terra API。
- Terra API WebSocket 代理 – 路由实时数据流的服务端。这是 Terra API 的基础设施,你无需自行托管。
- 消费者 – 连接代理并接收数据流的后端。
你需要建立的三个连接:
- 可穿戴设备到应用:用户通过 RT SDK 使用蓝牙/ANT+ 将可穿戴设备与应用配对。
- 应用到代理:应用打开一个 生产者 连接,并转发可穿戴设备的数据。
- 代理到后端:后端打开一个 消费者 连接,并实时接收数据。
你使用自己的 reference_id 来标识用户。Terra API 会为该用户生成一个 Terra API 用户 ID(无需身份验证小组件);令牌端点需要此 ID,每个负载中的 uid 字段也会携带此 ID。
令牌
每个 WebSocket 连接都需要通过由你的后端生成的短时令牌进行身份验证;生成该令牌时,需使用 auth:write 数据令牌(Authorization: Bearer terra_dt_...),或环境的 dev-id 和 x-api-key 进行身份验证。这三种令牌都只能使用一次——服务器会在 IDENTIFY 成功后删除相应令牌,因此每次重新连接都需要生成新令牌。切勿在应用中携带可生成令牌的凭据,无论是开发环境还是生产环境;应在服务端生成令牌,再传递给应用。对于手机注册令牌,你的后端持有的凭据应为上文“Account tools”中的 auth:write 数据令牌,而非环境 API 密钥。
| 令牌 | 端点 | 使用方 | IDENTIFY 类型 |
|---|---|---|---|
| 手机注册 | POST https://api.tryterra.co/v2/auth/tokens | RT SDK initConnection(将手机注册为数据提供方) | n/a(SDK 管理) |
| 数据提供方 | POST https://ws.tryterra.co/auth/user?id=<terra_user_id> | 发送数据的数据提供方连接 | 0(USER) |
| 数据使用方 / 开发者 | POST https://ws.tryterra.co/auth/developer | 你的后端数据使用方 | 1(DEVELOPER) |
请注意主机名:只有手机注册端点位于主 API(api.tryterra.co);参考文件和已发布的 SDK 会使用其已弃用但名称相同的 /auth/generateAuthToken,新代码应使用 /auth/tokens。数据提供方和数据使用方令牌端点通过 WebSocket 主机(ws.tryterra.co)上的 HTTPS 提供,不存在于 api.tryterra.co 上。构建请求时,请获取REST 端点参考,查看准确的请求和响应架构。
手机注册令牌只能使用一次,且会在生成 3 分钟后过期(以 expires_in 返回),因此应在恰当时机生成——即应用即将调用 initConnection 时,而不是应用启动时或提前生成后放入队列。数据提供方端点要求在 id 查询参数中提供 Terra API 用户 ID;请通过 SDK 的 getUserId 获取该 ID。
WebSocket
两个角色共用一个端点:wss://ws.tryterra.co/connect。IDENTIFY 的 type 字段(0 表示数据提供方,1 表示数据使用方)决定连接的角色。SDK 会为你打开并驱动数据提供方连接;你需要参照逐步指南手动编写数据使用方连接。
协议采用操作码分帧:先是 HELLO 和心跳,然后是 IDENTIFY 和 READY,接着是 DISPATCH 数据载荷,以及用于补传数据的 REPLAY(SUBMIT 位于数据提供方一侧,并由 SDK 封装)。编写数据帧时,请获取terra-greater-than-your-backend.md,查看完整操作码表和精确的 JSON 载荷格式。
协议注意事项
以下是容易踩坑的地方。分步客户端使用指南见 references/consumer-protocol.md。
- 连接后 15 秒内必须发送 IDENTIFY,否则服务器将以 4000 关闭连接。
- **成功发送 IDENTIFY 后,令牌会被删除。**连接断开后无法重复使用该令牌;重新连接前请生成新令牌。
- **心跳。**HELLO 会携带
heartbeat_interval(毫秒)。首次心跳应在heartbeat_interval * jitter后发送(jitter 是 0..1 之间的随机数),之后每个间隔最多发送一次。如果没有收到 HEARTBEAT_ACK,请关闭连接并重新连接。如果服务器在时间窗口内没有收到心跳,会以 4005 关闭连接。 - **关闭代码分为两组。**4000、4003、4004 和 1003 表示客户端存在错误——请修复客户端,不要循环重试,因为盲目重连只会重复遇到相同错误。4001 表示需要生成新令牌。4002 表示服务器因消费者会话数量上限拒绝连接——不要将架构设计为依赖任何有保障的并发消费者数量;遇到 4002 时,请关闭现有会话或延迟重试,而不要循环重试。
- **
seq单调递增,但不连续。**连续序列号之间存在间隔是正常的,并不表示数据丢失。仅使用seq对 DISPATCH 排序,并将其用作重放的after边界。 - **REPLAY 使用排他边界;两者都要发送。**必须同时提供
after和before——省略before的 REPLAY 不会返回任何消息。重连时,将after设为已处理的最后一个seq,并将before设为第一条实时 DISPATCH 的seq,以精确补齐间隙。 - **重放会延迟几秒。**实时投递后,数据需要几秒才可供重放。如果 REPLAY 返回的消息少于预期,请稍等片刻后重新请求。
- **无需硬件即可测试。**在 Terra API dashboard 的 Streaming 页面创建一个测试用户;Terra API 会通过真实 API 流式传输合成实时数据,因此你可以在连接设备前端到端验证消费者。
- **每次打开应用或切换到前台时,都要重新初始化 RT SDK。**生产者注册不会在应用转入后台后保留。
- **Apple Watch 在非锻炼会话期间会以较低频率记录数据。**在手表上启动锻炼会话,即可按最高频率采集数据。
参考资料
请阅读与你正在构建的内容对应的参考资料。
- references/consumer-protocol.md – **编写后端消费者前请先阅读此文档。**其中包含握手流程(HELLO、心跳、IDENTIFY、READY、DISPATCH)、DISPATCH 字段语义、REPLAY 回填方法以及关闭代码处理,并附有实时文档链接以查看确切的载荷结构。
- references/data-types.md – 选择 RT SDK 的请求内容或遇到数据流无响应时阅读。文档包含完整的
DataTypes和Connections枚举、说明为何请求不等于接收,以及 Wear OS 运动类型前缀标签。 - references/ios.md – 生产者应用为原生 iOS 应用或需要连接 Apple Watch 时阅读。需要加入 Apple Developer Program。
- references/android.md – 生产者应用为原生 Android 应用时阅读,其中包括 ANT+ 和以编程方式扫描设备。
- references/react-native.md – 生产者应用为 React Native 应用时阅读。
- references/flutter.md – 生产者应用为 Flutter 应用时阅读(注意
startRealtimeToApp与startRealtimeToServer的区别)。 - references/wear-os.md – 从与 Android 手机配对的 Wear OS 手表进行流式传输时阅读。
完整文档:docs.tryterra.co/streaming-api。获取页面前,请使用 terra docs ask(或通过 MCP 使用 docs_ask);它会基于文档作答并注明来源。任何文档 URL 后追加 .md 即可获取 Markdown。
由你决定的事项
文档特意将以下事项留给你决定;请选择适合你应用的方案,而不是假设存在默认设置:
- 要流式传输的数据类型。 你需要将数据类型集合传给 SDK;只传输你会用到的数据。
- 设备扫描缓存。
useCache和showWidgetIfCacheNotFound(Android)等标志用于权衡:是加快重新连接到已知设备,还是始终显示选择器。 - 仅本地流式传输还是向服务器流式传输。 在应用本地进行流式传输和向代理进行流式传输是两个独立的选择。Flutter 会明确区分这两种方式:
startRealtimeToApp(仅本地回调)与startRealtimeToServer(仅代理)。在其他平台上,传入令牌时,同一个startRealtime调用会向代理进行流式传输。 - 令牌交接。 应用如何从你的后端获取生产者令牌(端点形式、身份验证方式),由你决定。
- 重新连接和回填策略。 重新连接的积极程度、每次断连时是否重放,以及如何持久化上次处理的
seq,都由你决定。 - 消费者拓扑。 由一个消费者在内部扇出,还是使用多个消费者,取决于你的架构(但受会话上限约束)。
reference_id方案。 你的系统中如何映射reference_id,由你决定。