docs: add multi-provider SDK architecture plan#487
docs: add multi-provider SDK architecture plan#487bartmichalak wants to merge 2 commits intomainfrom
Conversation
| backend/app/ | ||
| schemas/ | ||
| sdk/ | ||
| sync_request.py # UNIFIED schema for all providers |
There was a problem hiding this comment.
not sure about that. Since we have specific types for each provider, shouldn't we have separate schemas (for records, sleep, workouts) - to be able to define custom enums for each provider?
Alternatives:
- not validate types completely (don't think that's a good idea)
- enums aggregating types from all providers (also doesn't seem to be a good idea)
There was a problem hiding this comment.
Or we can just create mapping (provider type -> our unified type), which will do validation anyway (we can raise exception if mapping won't recognize type).
There was a problem hiding this comment.
|
|
||
| The difference stems from how each platform's health API models sleep: | ||
|
|
||
| - **Apple HealthKit** has no concept of a "sleep session". It stores sleep as individual `HKCategorySample` records, each representing a single phase transition (e.g., "deep sleep from 22:00 to 22:45"). All records share the same type (`HKCategoryTypeIdentifierSleepAnalysis`) and differ only by `value` (0=IN_BED, 1=ASLEEP_UNSPECIFIED, 2=AWAKE, 3=LIGHT, 4=DEEP, 5=REM). There is no parent record linking them -- HealthKit simply returns a flat list of time-stamped phase samples. Our backend already reconstructs sessions from these flat phases using a Redis-based state machine (`sleep_service.py`) that groups consecutive phases and detects session boundaries via gap analysis (>1 hour gap = session end). |
There was a problem hiding this comment.
I would add that it's not only in the case of sleep sessions that it differs.
Samsung and Google have the concept of a 'master record' also for health metrics, example:
// ----- BLOOD_PRESSURE -----
{
"uid": "bp-uuid-001",
"dataType": "BLOOD_PRESSURE",
"startTime": 1706774400000,
"endTime": null,
"dataSource": { "appId": "com.sec.android.app.shealth", "deviceId": "phone-001" },
"device": { /* ... */ },
"values": [
{"type": "SYSTOLIC", "value": 120.0}, // mmHg - systolic pressure (Float)
{"type": "DIASTOLIC", "value": 80.0}, // mmHg - diastolic pressure (Float)
{"type": "PULSE", "value": 72.0} // BPM - pulse during measurement (Float, optional)
]
},
bartmichalak
left a comment
There was a problem hiding this comment.
very preliminary review and just two thoughts off the top of my head, will come back to it tomorrow
KaliszS
left a comment
There was a problem hiding this comment.
Would be useful to have here comparison of what we can get from all 3 providers (in form of table).
| backend/app/ | ||
| schemas/ | ||
| sdk/ | ||
| sync_request.py # UNIFIED schema for all providers |
There was a problem hiding this comment.
Or we can just create mapping (provider type -> our unified type), which will do validation anyway (we can raise exception if mapping won't recognize type).
There was a problem hiding this comment.
I attached a document with full explanation, examples, and comparisons.
Main idea:
- We normalize data from Health Connect and Samsung to match the Apple Health structure.
- Sleep data: In Health Connect and Samsung, one record contains stages[]. We split them into separate records to match Apple’s flat structure.
- Workouts: If a workout contains sessions[], we also split them into separate records (like in Apple).
- Other records - If a record contains nested samples or seriesData, we split them into separate records too.
In short, we flatten all nested arrays into individual records to keep one consistent internal structure across all providers.
|
@kmlpiekarz could you please review the document or just run the agant against current implementation, update the spec and merge? 🙏 |
Yes, starting working on docs now |

Architecture plan for expanding the SDK from Apple Health-only to multi-provider (Apple Health, Google Health Connect, Samsung Health) across Flutter and React Native.
Feel free to leave comments and join the discussion!