Namespaces

ovok.measurements

Build, save and read measurements as FHIR Observations, with an offline queue.

  • Stable unknown
  • Release candidate since 0.4.49-rc.4
  • Development since 0.4.49-dev.517+4645a0a

ovok.measurements turns a typed measurement into FHIR Observations, saves them safely and reads the latest values back. Patient apps call it for the signed-in user; a server machine client can call it with an explicit patientId.

Save a measurement

save builds the Observations and sends them as one conditional-create transaction, so a retry cannot duplicate a reading.

import { MeasurementTypeKey } from '@ovok/core';

const result = await ovok.measurements.save({
  measurement: { measurementTypeKey: MeasurementTypeKey.heartRate, heartRate: 70 },
});

if (result.status === 'queued') {
  console.log('Saved for later', result.queueId);
}
  • Without patientId, the reading belongs to the signed-in profile.
  • result.status is 'saved' (with the server response bundle) or 'queued'.
  • build returns the Observations without saving. saveObservations saves Observations you built yourself, main observation first.
  • If the server refuses or leaves out an observation, the save throws an OvokError with the refused status; see errors and retries.
  • Observations are final, carry a FHIR category (vital-signs, or laboratory for glucose and urine), code quantities in UCUM, and are dated by the measurement's recordedAt unless you pass effectiveDateTime.
  • A reading of several observations (a blood pressure, a pulse oximeter reading, an ECG, a urine strip) ends with a group observation whose hasMember points at the others: a blood pressure's is the FHIR panel 85354-9 with the pressures as components, a urine strip's is 24357-6, and the rest use the code system https://sdk.ovok.com/fhir/CodeSystem/measurement-type. The other observations keep their codes and links, and observationsToMeasurements reads either shape. Readings saved before groups existed get theirs from scripts/backfill-reading-groups.mjs (a dry run unless --apply).
  • A measurement's memorySlot (the monitor's user) is kept on its first observation. An ECG needs its duration; without it the save throws.

Retry queued readings

A connection failure queues the reading in storage and returns { status: 'queued' }. Flush the queue when the device is back online.

const outcome = await ovok.measurements.offlineQueue.flush();

console.log(outcome.saved, outcome.queued, outcome.exhausted);
  • The queue only sends readings for the account that queued them.
  • The default storage is in memory. Pass persistent storage to the client to keep readings across restarts.
  • flush({ includeExhausted: true }) also retries readings that ran out of retries; resetExhausted: true gives them a fresh set first.

Save many readings at once

saveObservationGroups saves a monitor's stored readings in as few requests as fit. Each group is one reading with its main observation first.

await ovok.measurements.saveObservationGroups(groups, { identifierSystems: [APP_READING_SYSTEM] });
  • It is not queued offline.
  • A request with one reading is a transaction, atomic when the project enables FHIR transactions. A request with several is sent as two batches, every main observation first, so a reading's other observations never point at one that wasn't saved. If it fails, some readings may already be saved; saving them again is safe.
  • A main observation that matches several saved copies counts as saved.
  • It stops, without sending the rest, if another account signs in between requests.
  • identifierSystems names the identifiers that make a reading unique; replace: true overwrites a reading saved under the same identifiers.

Read the latest readings

const codes = ovok.measurements.codesFor([MeasurementTypeKey.heartRate]);

const newest = await ovok.measurements.latest({ me: true, codes: codes.split(',') });

const bundle = await ovok.measurements.lastn(patientId, { code: codes, max: 50, _elements: 'code,effectiveDateTime' });
  • latest returns the newest observation per code for yourself (me: true) or a patient (me: false with patientId).
  • lastn returns the newest max observations per code in one $lastn request and passes other search parameters on.
  • lastForPatient reads patient/{patientId}/observation.

Measurement categories

MeasurementTypeKey has these keys: babySleep, bloodGlucose, bloodOxygenPulseRate, bloodPressure, bodyWeight, cosinussMultiParam, ecg, heartRate, heartRateVariability, lipidPanel, photoUpload, respiratoryRate, respiratoryTherapy, restingHeartRate, spirometryPanel, stepCount, symptomQuestionnaire, temperature, urineAnalysis, vo2Max, walkingHeartRateAverage and the deprecated uricAcid. The measurement type list gives each key's value, and the pages under measurements describe each type's fields.

Reference

Last updated on

On this page