Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
Удаленный мониторинг пациентов с FHIR
От показаний артериального давления дома до оповещений: объекты Observations, подписанные вебхуки, идемпотентное правило и что остается за пределами слоя данных. Проверенный код.
Удаленный мониторинг пациентов (RPM) собирает измерения, которые пациент проводит дома — артериальное давление, вес, уровень глюкозы, насыщение кислородом — и позволяет команде по уходу видеть их и реагировать на них между визитами. Часть, связанная с данными, состоит из четырех шагов: внести каждое измерение в запись пациента как кодированное наблюдение, атрибутированное устройством; реагировать при поступлении нового измерения; решить с помощью четкого правила, нуждается ли оно во внимании; и вести учет того, что сделала команда. Эта страница описывает создание этого конвейера на основе HL7 FHIR R4 с использованием веб-хуков Anpheros и TypeScript SDK, с кодом, который был запущен на платформе, и перечисляет то, что остается за пределами слоя данных.
Конвейер
cuff, scale, glucose meter, pulse oximeter
│ (Bluetooth / vendor app / Apple Health / Health Connect)
▼
patient's phone app ──► your backend ──► FHIR Observation (author: device) in the patient's record
│ webhook: resource.created (signed)
▼
your monitoring service: rule → alert → care team
│
note, call, CarePlan change, next appointment
Три фактора определяют, будет ли это работать на практике:
- Одно измерение, одно наблюдение (Observation). Каждое измерение манжеты является наблюдением (Observation) с кодом LOINC 85354-9 и двумя компонентами (8480-6 систолическое, 8462-4 диастолическое), временем измерения и
author_type: device. В отличие от ежедневных сводок носимых устройств, показания RPM являются индивидуальными измерениями, которые клиницист может просматривать по одному. - Реагировать на события, а не на таймер. Вебхук для каждого нового наблюдения (Observation) позволяет правилу запускаться через несколько секунд после получения показаний.
- Правила для нескольких измерений. Одно высокое показание часто является шумом; большинство протоколов рассматривают серию. Правило ниже запрашивает три последовательных показания на уровне 140/90 или выше. Этот порог является примером, а не клинической рекомендацией: команда по уходу устанавливает правило для каждого пациента.
Запись показаний с устройства
Приложение на телефоне (или облако поставщика устройства через ваш бэкенд) записывает каждое показание:
await anpheros.observations.create(patientId, {
code: '85354-9', category: 'vital-signs', effective_at: '2026-10-13T07:15:00-04:00', author_type: 'device',
components: [{ code: '8480-6', value: 152, unit: 'mm[Hg]' }, { code: '8462-4', value: 95, unit: 'mm[Hg]' }],
}, { source_system: 'bp-cuff-app' });
Если показания поступают через Apple Health или Health Connect, а не напрямую с устройства, считывайте их на телефоне, как описано в Данные носимых устройств в FHIR, но сохраняйте отдельные показания артериального давления как отдельные Observations, а не как ежедневные средние значения.
Реакция на новые показания
Зарегистрируйте конечную точку веб-перехватчика один раз (POST /v1/webhooks с events: ["resource.created"]); ответ содержит секретный ключ подписи. Затем запустите небольшой сервис, который проверяет каждую доставку и оценивает правило:
import { createServer } from 'node:http';
import { Anpheros, apiKey, verifyWebhookSignature } from '@anpheros/sdk';
const anpheros = new Anpheros({ auth: apiKey(process.env.ANPHEROS_KEY!) });
const SECRET = process.env.WEBHOOK_SECRET!;
const seen = new Set<string>(); // deliveries are at-least-once: de-duplicate by event id
const alerted = new Set<string>(); // one alert per newest reading, however many events arrive
// Rule: the three most recent home readings all at or above 140/90 → tell the care team once
async function checkBloodPressure(patientId: string, observationId: string) {
const obs = await anpheros.observations.get(observationId);
if (obs.code !== '85354-9') return; // only blood pressure readings trigger the rule
const { data } = await anpheros.observations.list(patientId, { code: '85354-9', limit: 3 }); // newest first
const value = (o: typeof obs, code: string) => o.components.find(c => c.code === code)?.value ?? 0;
const allHigh = data.length === 3 && data.every(o => value(o, '8480-6') >= 140 || value(o, '8462-4') >= 90);
if (!allHigh || alerted.has(data[0].id)) return;
alerted.add(data[0].id);
console.log(`ALERT patient ${patientId}: last 3 readings ≥ 140/90 →`,
data.map(o => `${value(o, '8480-6')}/${value(o, '8462-4')}`).join(', ')); // in production: notify the care team
}
createServer(async (req, res) => {
const chunks: Buffer[] = [];
for await (const c of req) chunks.push(c as Buffer);
const body = Buffer.concat(chunks).toString('utf8');
const ok = await verifyWebhookSignature({ secret: SECRET, header: req.headers['anpheros-signature'] as string, body });
if (!ok) { res.writeHead(400).end(); return; } // not from Anpheros, or too old
res.writeHead(204).end(); // answer fast; do the work after
const event = JSON.parse(body);
if (seen.has(event.id)) return;
seen.add(event.id);
const d = event.data;
if (event.type === 'resource.created' && d.resource_type === 'Observation') await checkBloodPressure(d.patient, d.id);
}).listen(8799);
Как мы тестировали: четыре утренних показания (136/86, 144/92, 149/94, 152/95) были записаны синтетическому пациенту на локальном экземпляре платформы, и платформа сгенерировала одно подписанное событие resource.created на каждое показание. Эти события, подписанные собственным кодом подписи платформы, были отправлены в вышеуказанный сервис вместе с двумя дубликатами и одним запросом, подписанным неправильным секретным ключом. Результат: неправильная подпись получила 400, дубликаты были проигнорированы, а сервис выдал ровно одно оповещение — 152/95, 149/94, 144/92 — а не одно на событие.
В производственной среде храните seen и alerted в базе данных, а не в памяти, чтобы перезапуск не приводил к повторным оповещениям.
Получение веб-перехватчиков во время разработки. Anpheros принимает и доставляет только на публичные HTTPS конечные точки: localhost или частный адрес отклоняются при регистрации (400, поле url), даже в песочнице, и каждая доставка повторно проверяет адрес. Чтобы получать события на своем ноутбуке, сделайте сервис доступным через публичный HTTPS туннель и зарегистрируйте адрес туннеля. См. Веб-перехватчики.
Что должно отображаться в записи впоследствии
Сам алерт находится в вашей службе мониторинга, но запись должна отражать его результат, чтобы следующий клиницист и пациент видели полную картину:
- показания, каждое помеченное как данные устройства с указанием его исходной системы (provenance);
CarePlanс планом мониторинга (что измеряется, как часто, цель);Encounter(классVRдля удаленного контакта) при звонке пациента командой, и любое изменение медикаментов какMedicationStatement.
Anpheros хранит эти ресурсы; у него нет собственных ресурсов для оповещений или задач (Flag, Task и Communication не входят в число его типов ресурсов), поэтому очереди оповещений и маршрутизация дежурных относятся к вашей службе.
Оплата, регулирование и безопасность
Программы удаленного мониторинга физиологических показателей (RPM) часто зависят от правил возмещения расходов. В Соединенных Штатах Medicare оплачивает удаленный мониторинг физиологических показателей по определенным CPT-кодам с минимальным количеством дней с данными и временем, затраченным командой по уходу. Эти правила меняются, и платформа данных не может их сертифицировать; ознакомьтесь с текущими правилами CMS и сохраняйте доказательства (показания и время работы команды) в своей собственной системе. Программное обеспечение, которое интерпретирует показания для постановки диагноза или назначения лечения, может регулироваться как медицинское изделие. Оставляйте пороговые значения в ведении клиницистов и регистрируйте каждое оповещение и ответ.
Место Anpheros
Anpheros предоставляет запись (FHIR R4 Observations с указанием источника, CarePlan, Encounter), подписанные веб-хуки с повторными попытками, согласие, если приложение другой организации нуждается в чтении показаний, и журнал доступа, который может просмотреть пациент. Он не подключается к поставщикам устройств, не определяет, что является аномальным, не отправляет оповещения и не занимается выставлением счетов.
Часто задаваемые вопросы
Какой ресурс FHIR хранит показания артериального давления в домашних условиях?
Observation с кодом LOINC 85354-9 (панель артериального давления) и двумя компонентами: 8480-6 (систолическое) и 8462-4 (диастолическое), каждый из которых является valueQuantity в mm[Hg], с указанием времени измерения и устройства в качестве автора.
Следует ли использовать ежедневные средние значения или отдельные показания для данных RPM?
Отдельные показания для клинических измерений, таких как артериальное давление, вес или уровень глюкозы, поскольку клиницисты просматривают и подсчитывают их. Ежедневные сводки подходят для высокочастотных данных с носимых устройств, таких как частота сердечных сокращений или количество шагов.
Как инициировать оповещение при поступлении новых показаний?
Подпишитесь на веб-хуки resource.created, проверьте подпись, получите новое Observation и оцените ваше правило по последней серии данных. Доставки могут повторяться, поэтому дедуплицируйте по идентификатору события и сделайте оповещение идемпотентным.
Может ли Anpheros отправлять оповещения клиницистам?
Нет. Anpheros уведомляет ваш сервис через веб-хуки; кто получает оповещение, как и когда, решается в вашей системе.
Связанные материалы
- Данные носимых устройств в FHIR
- Виртуальная помощь и ИИ-врачи: необходимые данные
- Вебхуки
- Происхождение медицинских данных: объяснение
- Интеграции в здравоохранении
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card