mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
feat(import): read Health Connect exports
Upload the ZIP the Android Health Connect app writes and import its `health_connect_export.db` in the background, the same way an Apple Health export is imported: streamed to disk with a SHA-256, capped at 1 GiB, one import per account, a job row of kind `health_connect` that the shared reconcile cron and staging sweep now look up on its own queue. The worker extracts the database (4 GiB ceiling, zip-bomb checks) and opens it read-only with `immutable=1`, `trusted_schema=OFF` and `query_only`. A view in place of a record table refuses the file, columns are found by name, and schema versions below 9 are refused. Records are read in batches of 500 and aggregated in SQLite: steps, energy and distance as one total per day from the app the person's Health Connect priority list ranks first, heart rate per minute for 90 days and as hourly means before that, sleep stages with the unknown stage counted only in sessions without real stages, workouts, cycle days, water and micronutrients. Apps whose integration the account has connected are left out, and a reading already stored under another source is skipped. Rows carry source HEALTH_CONNECT, `hc:<uuid>` or the `stats:` ids, so a second import of the same export writes nothing. Both staged files are removed on every way out; the job result holds counts per type and per app only. Settings gain a Health Connect card with the export steps, progress and the outcome, in all seven languages, and the import is documented in docs/integrations/health-connect.md.
This commit is contained in:
1 parent
2622f63571
commit
996d2519d1
45 files changed
+6289
-100
No files matched your search
+16
-8
@@ -14136,28 +14136,29 @@ paths:
|
||||
$ref: "#/components/schemas/ErrorEnvelope"
|
||||
"401": *a1
|
||||
"409":
|
||||
description: An import for this account is already queued or running with different bytes. The upload was discarded.
|
||||
description: An import for this account (Health Connect or Apple Health) is already queued or running. The upload was
|
||||
discarded. `errorCode` is `import.apple_health.busy` for either kind, `jobId` names the running job.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorEnvelope"
|
||||
"413":
|
||||
description: The declared `Content-Length` exceeds the upload cap.
|
||||
description: The declared `Content-Length` exceeds the 1 GiB upload cap.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorEnvelope"
|
||||
"422":
|
||||
description: "The upload is not a Health Connect export the importer can read: no `file` part, no export database in the
|
||||
ZIP, or a database version older than the importer supports."
|
||||
description: "The multipart body could not be read: no `file` part, a malformed body, or more bytes than the cap.
|
||||
Whether the ZIP is a readable Health Connect export is decided by the worker and reported on the job
|
||||
(`status: failed`, `failureReason`)."
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ErrorEnvelope"
|
||||
"429": *a5
|
||||
"501": *a9
|
||||
"503":
|
||||
description: No background worker is bound, so nothing would run the import.
|
||||
description: No background worker is bound, or the queue did not take the job, so nothing would run the import.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@@ -14178,7 +14179,6 @@ paths:
|
||||
"401": *a1
|
||||
"422": *a4
|
||||
"429": *a5
|
||||
"501": *a9
|
||||
/api/import/csv:
|
||||
post:
|
||||
tags:
|
||||
@@ -66181,11 +66181,19 @@ components:
|
||||
type: string
|
||||
additionalProperties: {}
|
||||
- type: "null"
|
||||
description: The worker's outcome summary, null until it finishes.
|
||||
description: "The worker's outcome summary, null until it finishes. Counts only: `perType` (read / inserted / updated /
|
||||
unchanged / skipped per measurement type), `perApp` (records per Android package, `leftOut` for an app whose
|
||||
integration the account has connected), `workouts`, `sleep`, `cycle`, `nutrients`, `skipped` (reason →
|
||||
count), `warnings` (codes for tables or columns the importer could not read), `totals`. Never a value, a
|
||||
timestamp or text from the file."
|
||||
failureReason:
|
||||
anyOf:
|
||||
- type: string
|
||||
- type: "null"
|
||||
description: Why the job failed. Starts with a code the client can key on when the file was refused —
|
||||
`unsupported_version` (database older than version 9), `not_health_connect` (no `health_connect_export.db`,
|
||||
or not a Health Connect database), `unsafe_schema` (a record table is a view), `too_large`,
|
||||
`staging_missing` — else free text.
|
||||
required:
|
||||
- jobId
|
||||
- status
|
||||
|
||||
Reference in new issue
Block a user