一文看懂Open Wearables统一数据模型:摘要、时间序列与事件如何抹平设备差异
【免费下载链接】open-wearablesSelf-hosted platform to unify wearable health data through one AI-ready API.项目地址: https://gitcode.com/gh_mirrors/op/open-wearables
Open Wearables 是一个自托管的开源平台,通过一套AI-Ready API将 Garmin、Oura、Whoop、Apple Health 等穿戴设备的数据统一成一个统一数据模型(Unified Data Model)。无论你用哪块手表、哪支戒指、哪个 App,查出来的心率、睡眠、运动数据都长得一样。这篇文章带你用一张图 + 三张表,彻底搞懂它背后的设计。
先说痛点:为什么多设备数据这么难用
不同厂商的数据格式五花八门:
- Garmin 叫
Body Battery,Oura 叫Readiness,语义完全不同 - 步数有的存整数、有的存分钟级聚合值,单位还有米和公里之分
- 睡眠阶段划分标准各不相同,时区和时区偏移处理也不统一
如果每个 App 都要单独对接每家厂商的 OAuth、API 和数据映射,开发成本会爆炸。Open Wearables 的做法是:在数据入口做一次归一化,之后所有访问者(后端、前端、AI Agent)都只面对一套结构。
统一数据模型三大支柱:事件、时间序列、描述符
官方文档对架构的完整阐述见 docs/architecture/unified-data-model.mdx。整个模型围绕三类核心结构展开:
1️⃣ 事件(Events):一次完整的"发生过的事"
适用于有明确起止时间的记录:一次跑步、一夜睡眠、一次月经周期。
| 字段 | 说明 |
|---|---|
category | 事件类别,如workout、sleep |
start_datetime/end_datetime | 起止时间与时长 |
| 详情表(多态) | 按类别挂WorkoutDetails(心率 min/max/avg、距离、卡路里)或SleepDetails(深睡/REM/清醒分钟数) |
对应源码:backend/app/models/event_record.py
2️⃣ 时间序列(Time Series):所有中高频数据的"共享池"
所有心率、HRV、SpO2、步数、体重……全部存进同一张表data_point_series,靠两个维度区分:
- 类型:通过
series_type_definition表引用,每种类型绑定标准单位(bpm、kg、kcal),避免单位混乱 - 来源设备:每个数据点都带设备映射 ID,同一分钟两台设备各记各的,互不覆盖
源码参考:backend/app/models/data_point_series.py、backend/app/models/series_type_definition.py
完整支持的 100+ 数据类型清单(含单位)见 docs/architecture/data-types.mdx。
3️⃣ 描述符与 ID 映射:慢变信息与"设备身份证"
- PersonalRecord:生日、性别等静态生物特征,用于计算年龄相关指标
- DataSource(设备映射):把
用户 + 厂商 + 设备映射成一个内部 ID,其他表只需引用这个 ID,既标明来源又不撑宽时间序列表,见 backend/app/models/data_source.py
摘要 API:时间序列之上的"日报层"
原始时间序列太细(分钟级甚至秒级),看趋势不现实。Open Wearables 在上面盖了一层按天聚合的摘要接口,一次请求拿一天的全貌:
| 接口 | 内容 |
|---|---|
GET /users/{id}/summaries/activity | 步数、活动能量、站立时间等每日活动汇总 |
GET /users/{id}/summaries/sleep | 睡眠时长、效率、各阶段占比 |
GET /users/{id}/summaries/recovery | 恢复分、HRV、静息心率、SpO2 |
路由实现见 backend/app/api/routes/v1/summaries.py。时间序列查询则支持resolution参数,可按1min/5min/1hour聚合,心率取均值、步数取总和——聚合规则统一由平台代劳,你不用关心设备差异。
抹平设备差异的 4 个关键设计
- 单位标准化:每种序列类型在定义表里绑定唯一单位,Garmin 的"皮肤温度偏差"和 Ultrahuman 的"体温"会被重新归类到同一语义类型(项目里甚至专门写了 数据重标注脚本 处理历史数据)
- 运动类型归一化:各厂商的
run/跑步/TREADMILL统一映射为 100+ 个标准类型,如running、cycling - 来源可追溯:原始 ID 保留在
external_id字段,归一化不丢信息 - 数据优先级:同一指标多台设备同时上报时,可由用户配置"哪家设备说了算"
面向 AI 的数据出口:MCP Server
统一模型的直接受益者是 AI:内置 MCP Server 让 Claude、Cursor 等助手可以直接问"我上周睡得怎么样",AI 自己决定查睡眠事件还是时间序列。工具实现见 mcp/app/tools/。
路线图:数据模型还将演进
官方将演进分为四个阶段:基础模型(当前)→ 广谱数据支持 → 复杂指标计算(VO2 max、EPOC 等由计算引擎推导)→ 时间序列按整数/小数/分类拆分以优化存储:
小结
| 你想查的 | 用哪个结构 |
|---|---|
| "昨晚睡了多久、深睡多少" | 睡眠事件 + SleepDetails |
| "最近一周 HRV 趋势" | 时间序列heart_rate_variability |
| "今天走了多少步、烧了多少千卡" | 活动摘要 API |
| "上周三 5 公里跑步详情" | 运动事件 + WorkoutDetails |
一句话总结:Open Wearables 用事件管"发生过什么"、时间序列管"连续变化"、摘要管"每日全貌",再用设备映射和单位定义把 10+ 厂商的差异挡在入口,让你拿到手的永远是同一套字段、同一套单位 🏃
【免费下载链接】open-wearablesSelf-hosted platform to unify wearable health data through one AI-ready API.项目地址: https://gitcode.com/gh_mirrors/op/open-wearables
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考