fix: use Scriptable Health API (new Health with string units)

This commit is contained in:
Anthony Merlo 2026-08-21 00:05:56 +01:00
parent 191f5f473b
commit c65affc66c

View file

@ -1,34 +1,24 @@
// Health Sync — reads Apple Health and POSTs to nutrition-mcp server // Health Sync — reads Apple Health and POSTs to nutrition-mcp server
// Run via Scriptable/Scripting automation at 9:30am daily // Run via Scriptable automation at 9:30am daily
// Server: http://chronos:9432/ingest // Server: http://chronos:9432/ingest
// //
// Uses Health.queryQuantitySamples() (current Scripting API). // Uses Scriptable's Health API: new Health() instance with string units.
// The old Health.read() / Health.Types.* / .quantity API was removed.
const SERVER_URL = "http://chronos:9432/ingest"; const SERVER_URL = "http://chronos:9432/ingest";
const API_KEY = "333f09ce904e9cbbe3b578fda393be92869122c7222dbccd"; const API_KEY = "333f09ce904e9cbbe3b578fda393be92869122c7222dbccd";
// --- Units for each quantity type ---
const U = {
kg: HealthUnit.gram(HealthMetricPrefix.kilo),
mmHg: HealthUnit.millimeterOfMercury(),
bpm: HealthUnit.count().divided(HealthUnit.minute()),
count: HealthUnit.count(),
percent: HealthUnit.percent()
};
// --- Helpers ---
// Read the most recent sample of a type. Returns { value, startDate } or null. // Read the most recent sample of a type. Returns { value, startDate } or null.
async function readLatest(type, unit) { async function readLatest(type, unit) {
try { try {
const samples = await Health.queryQuantitySamples(type, { const h = new Health();
limit: 1, h.setTypeIdentifier(type);
sortDescriptors: [{ key: "startDate", order: "reverse" }] h.setUnit(unit);
}); h.setLimit(1);
h.setDescendingSorting();
const samples = await h.quantitySamples();
if (!samples || samples.length === 0) return null; if (!samples || samples.length === 0) return null;
const s = samples[0]; const s = samples[0];
return { value: s.quantityValue(unit), startDate: s.startDate }; return { value: s.value, startDate: new Date(s.startDate) };
} catch (e) { } catch (e) {
return null; return null;
} }
@ -39,14 +29,15 @@ async function readTodaySum(type, unit) {
try { try {
const start = new Date(); const start = new Date();
start.setHours(0, 0, 0, 0); start.setHours(0, 0, 0, 0);
const samples = await Health.queryQuantitySamples(type, { const h = new Health();
startDate: start, h.setTypeIdentifier(type);
endDate: new Date() h.setUnit(unit);
}); const samples = await h.quantitySamples();
if (!samples || samples.length === 0) return null; if (!samples || samples.length === 0) return null;
let total = 0; let total = 0;
for (const s of samples) { for (const s of samples) {
total += s.quantityValue(unit); const sd = new Date(s.startDate);
if (sd >= start) total += s.value;
} }
return total; return total;
} catch (e) { } catch (e) {
@ -54,10 +45,6 @@ async function readTodaySum(type, unit) {
} }
} }
function isoNow() {
return new Date().toISOString();
}
function todayDate() { function todayDate() {
return new Date().toISOString().slice(0, 10); return new Date().toISOString().slice(0, 10);
} }
@ -70,13 +57,13 @@ function notify(body) {
} }
// --- Read all health metrics --- // --- Read all health metrics ---
const weight = await readLatest("bodyMass", U.kg); const weight = await readLatest("bodyMass", "kg");
const bpSys = await readLatest("bloodPressureSystolic", U.mmHg); const bpSys = await readLatest("bloodPressureSystolic", "mmHg");
const bpDia = await readLatest("bloodPressureDiastolic", U.mmHg); const bpDia = await readLatest("bloodPressureDiastolic", "mmHg");
const hr = await readLatest("heartRate", U.bpm); const hr = await readLatest("heartRate", "count/min");
const restingHr = await readLatest("restingHeartRate", U.bpm); const restingHr = await readLatest("restingHeartRate", "count/min");
const steps = await readTodaySum("stepCount", U.count); const steps = await readTodaySum("stepCount", "count");
const spo2 = await readLatest("oxygenSaturation", U.percent); const spo2 = await readLatest("oxygenSaturation", "%");
// --- Build samples array — only include metrics that have data --- // --- Build samples array — only include metrics that have data ---
const samples = []; const samples = [];