☰
如何实时掌握用户健康数据:Open Wearables Webhooks 完整配置与调试教程
2026/10/4 3:12:30 网站建设 项目流程

如何实时掌握用户健康数据:Open Wearables Webhooks 完整配置与调试教程

【免费下载链接】open-wearablesSelf-hosted platform to unify wearable health data through one AI-ready API.项目地址: https://gitcode.com/gh_mirrors/op/open-wearables

Open Wearables 是一个自托管的穿戴设备数据平台,它将 Garmin、Oura、Apple Health 等设备的健康数据统一为一个 AI 友好的 API。本教程带你用 Webhooks 实时接收用户的心率、睡眠、运动等健康数据事件——无需轮询,数据一到就推送,并覆盖从启用、注册端点、签名验收到调试排查的完整流程。

为什么用 Webhooks 而不是轮询

传统做法是让服务器每隔几分钟调用一次拉取接口,检查有没有新数据。而 Open Wearables 的 Outgoing Webhooks 会在每个新运动保存、每段睡眠入库、每批时序数据写入的瞬间,向你的服务器发起一次 HTTP POST 推送。

  • ⚡实时性:数据落库即触发,没有轮询间隔带来的延迟
  • 🔄零空转:没有新数据就不打扰你的服务器
  • 🧩完整载荷:时序事件直接携带samples数组,无需二次调用 API
  • 🔁自动重试:基于 Svix 投递,失败事件按指数退避自动重发

📌 注意:自托管部署中 Webhooks默认关闭,需要先启用才能收到事件。

第一步:启用 Outgoing Webhooks

在后端.env中设置开关,然后重启容器即可:

OUTGOING_WEBHOOKS_ENABLED=true

配置项位置见 .env.example。如果你使用的是托管 Postgres(AWS RDS / Railway),需要确保应用数据库用户有权创建数据库,或提前建好svix数据库——Svix 服务把它的表结构放在那里。

启用状态的检查逻辑在 outgoing_webhooks.py 中,未启用时 API 会明确返回 403 并提示你设置该环境变量。

第二步:注册一个 Webhook 端点

有两种方式,新手推荐从 Web 控制台入手(对应源码 webhooks.tsx):

  1. 登录后进入Webhooks页面,点击创建端点
  2. 填入一个公网可达的 HTTPS 地址,例如https://yourapp.com/webhooks/health
  3. 可选填描述、事件过滤器和用户过滤器

控制台表单 webhook-form.tsx 支持按事件分组勾选要订阅的事件类型。

也可以用 API 完成同样的事(需先用POST /api/v1/auth/login拿到 Bearer Token):

curl -X POST "http://localhost:8000/api/v1/webhooks/endpoints" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://yourapp.com/webhooks/health", "description": "生产环境健康数据处理器" }'

响应中会返回端点id(形如ep_xxxx),务必保存,后续获取密钥、查看投递记录都要用它。

第三步:获取签名密钥(Signing Secret)

每个端点都有一个独立的 HMAC 签名密钥,用于验证推送确实来自 Open Wearables:

curl "http://localhost:8000/api/v1/webhooks/endpoints/ep_xxx/secret" \ -H "Authorization: Bearer YOUR_JWT_TOKEN"

响应形如{ "key": "whsec_..." }。这个密钥请妥善保管在服务器环境变量里,它是防伪造、防重放攻击的唯一凭证。

理解推送载荷与签名验证

每次投递是标准 JSON,包含type(事件名)和data(业务数据),例如一段新睡眠:

{ "type": "sleep.created", "data": { "user_id": "550e8400-...", "efficiency_percent": 87.0, "stages": { "deep_minutes": 95, "rem_minutes": 80 }, "source": { "provider": "oura", "device": "Oura Ring Gen3" } } }

同时每个请求都带三个签名头:

请求头作用
svix-id唯一消息 ID,跨重试保持不变,用于幂等去重
svix-timestamp发送时间戳,超过 5 分钟的旧消息会被 SDK 自动拒绝
svix-signaturev1,<base64_hmac>签名的逗号分隔列表

推荐的验证方式(Python / Node 都有官方 SDK):安装svix库后,用Webhook(secret).verify(rawBody, headers)一步完成验签,签名不对或时间戳过旧会抛异常,此时应直接返回 400。先验签、再处理,这是安全底线。

事件类型全览:能收到哪些健康数据

事件命名遵循资源.动作约定,完整清单可通过GET /api/v1/webhooks/event-types获取,源码枚举见 event_types.py。

会话类事件(一次完整记录触发一次)

  • connection.created/connection.revoked— 用户连接或断开穿戴设备
  • workout.created— 新的运动会话(含卡路里、距离、平均心率)
  • sleep.created— 新的(或合并后的)睡眠会话,含深睡/REM 分期
  • menstrual_cycle.created— 新的月经周期记录

时序类事件(按批推送,携带完整样本)

事件覆盖的指标
heart_rate.created心率、静息心率、行走平均心率
steps.created步数
calories.created总能量、基础代谢
spo2.created血氧饱和度、外周灌注指数
body_temperature.created体温、皮肤温度
blood_glucose.created血糖、酒精含量、胰岛素输送
recovery_score.created恢复分、Garmin 身体电量

时序事件比拉取接口更"慷慨"——每条samples数据点结构与GET /api/v1/users/{user_id}/timeseries完全一致,消费端只维护一套 schema 即可。超过 2500 个样本的大批次会自动拆分为带chunk_index/total_chunks的分片事件,方便你重组。

过滤事件:只订阅你要的数据

按事件类型过滤

注册或更新端点时传filter_types,例如只关心运动和睡眠:

{ "url": "https://yourapp.com/hook", "filter_types": ["workout.created", "sleep.created"] }

不传该字段则接收全部事件。想移除过滤时发送"filter_types": [](空列表才是清除,null会保留原过滤)。

按用户过滤

传user_id可以把端点限定为只接收某个用户的事件,其他用户的数据在投递前就被丢弃。两个过滤条件可以叠加使用,例如"只接收某用户的运动事件"。

调试:确认你的端点真的在收

这是新手最容易卡住的环节,Open Wearables 提供了三个调试利器:

  1. 发测试事件(强烈推荐先做)——不等待真实数据,直接触发一个逼真样例载荷:
    curl -X POST "http://localhost:8000/api/v1/webhooks/endpoints/ep_xxx/test" \ -H "Authorization: Bearer YOUR_JWT_TOKEN" \ -d '{ "event_type": "workout.created" }'
  2. 查看投递历史——GET /api/v1/webhooks/endpoints/ep_xxx/attempts返回每一次投递的 HTTP 状态码和时间戳,4xx/5xx 一目了然
  3. 查看全部消息——GET /api/v1/webhooks/messages可看到所有已发送消息

对应前端组件为投递记录表格 webhook-attempts-table.tsx 和测试事件对话框 webhook-test-event-dialog.tsx。

常见故障速查

症状排查方向
什么都没收到确认OUTGOING_WEBHOOKS_ENABLED=true并已重启;确认端点是公网 HTTPS
收到但返回 400大概率验签失败——确认用的是原始请求体字节做 HMAC,而非反序列化后的对象
事件被重复处理用svix-id做幂等存储,重试会携带同一 ID
间歇性丢失检查 attempts 接口的状态码;端点应快速返回 2xx,重活丢进后台队列

最佳实践清单

  • ✅ 验签通过后立即返回 2xx,把重计算异步化——超时会被视为失败并重试
  • ✅ 用svix-id做幂等键,重试安全
  • ✅ 即使是"不感兴趣"的事件也返回 2xx,否则会被反复重投
  • ✅ 拉取 API 始终可用,用作补数、对账或丢失恢复
  • 🛡️ 数据入库永不因 Webhook 故障而阻塞——投递失败只会排队重试(实现见 events.py)

进阶阅读

  • 完整 API 参考与载荷字段说明:webhooks.mdx
  • Svix 投递服务封装:svix.py
  • Webhook 事件触发助手函数:events.py
  • 开发者门户中的 Webhooks 页面:前端路由 webhooks.tsx

照着以上步骤走完,你的应用就能在用户每跑完一次步、每睡完一晚的几分钟内收到推送——这才是"实时健康数据"应有的样子 🏃💤

【免费下载链接】open-wearablesSelf-hosted platform to unify wearable health data through one AI-ready API.项目地址: https://gitcode.com/gh_mirrors/op/open-wearables

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询