Repair Fitbit rows of relayed Apple Health and Health Connect data
A user who links Apple Health (or Health Connect) in the Google Health app gets that data back through the Fitbit connector, marked platform HEALTH_KIT (or HEALTH_CONNECT) in metadata.
A user who links Apple Health (or Health Connect) in the Google Health app gets that data back
through the Fitbit connector, marked platform HEALTH_KIT (or HEALTH_CONNECT) in metadata.
Before the connector told these points apart (see the changelog), it stored
them as Fitbit's own:
- Apple's HRV, which is SDNN, under
hrv_rmssd, next to Fitbit's real RMSSD; - a deep sleep RMSSD of 0 in the metadata of daily HRV figures;
- every relayed sample with source
fitbit, so Apple's or Health Connect's minutes added up with the tracker's in one stream.
New data is stored right. fitbit-relayed-points.sql repairs the rows stored before:
- An Apple HRV row the fixed connector has already stored again as
hrv_sdnn(same user, same time) is deleted. Every other one becomeshrv_sdnn, withhrv_method: sdnn; a sample that carried a standard deviation takes it as its value, as the connector now reads it. - A deep sleep RMSSD of 0 or less is removed from metadata.
- Relayed samples get source
apple_health/Apple Healthorhealth_connect/Health Connect.
It touches provider fitbit rows of ohs_data.quantity_samples only, runs in one
transaction, and a second run changes nothing.
Why it is not a migration
quantity_samples is compressed after 30 days. The rows to fix are found by a metadata field,
which compressed chunks cannot filter without decompressing, so the script decompresses the
batches of every chunk it scans. On a large instance that takes time and disk space, which a
migration run on every start must not impose. Run it once, in a quiet hour, with room on the
database disk (as much again as the compressed part of quantity_samples, at worst).
Run it
Back up first (backup and restore). Then, with the stack running:
docker compose --env-file .env -f deploy/docker-compose.yml exec -T postgres \
psql -U ohs -d ohs -v ON_ERROR_STOP=1 < docs/how-to/fitbit-relayed-points.sqlIt prints BEGIN, one DELETE n, four UPDATE n lines and COMMIT. TimescaleDB's
compression policy compresses the chunks again on its next run.
After it, a manual sync of a Fitbit connection that reaches further back than the regular pulls can store an Apple HRV night again under its new identity; run the script again after such a sync to remove the twin. Daily totals derived from the samples are recomputed the next time a sample of that day arrives.
Export Garmin Connect activities to PostgreSQL or CSV
Load a Garmin Connect account export (FIT files) into PostgreSQL: activities with distance, heart rate, GPS routes and power, queried in SQL or exported as CSV or Parquet. No Garmin API keys needed.
Client SDKs
Kotlin, Swift, React Native and Flutter clients: what they share and which credential goes where.