# Данные носимых устройств в FHIR (Apple Health, Health Connect)

> Получите данные с умных часов, колец и весов в запись FHIR: какие устройства достигают какого хранилища данных о здоровье, таблица сопоставления LOINC, ежедневные сводки и протестированное обновление.

Source: https://developers.anpheros.com/ru/guides/wearable-data-fhir

**Чтобы получить данные с умных часов, кольца или умных весов в медицинскую запись, считайте их на телефоне из хранилища данных о здоровье операционной системы — Apple Health на iOS, Health Connect на Android — суммируйте их за день, сопоставьте каждую метрику с кодом LOINC и единицей UCUM, и запишите их как FHIR R4 Observations, помеченные как данные устройства.** Чтение из хранилища данных о здоровье телефона вместо облака каждого поставщика позволяет одной интеграции охватить Apple Watch, Galaxy Watch, Pixel Watch, Garmin, Fitbit, Oura и Withings, при условии, что человек разрешил своему приложению поставщика делиться данными. На этой странице представлены путь к данным, таблица сопоставления, которую вы можете повторно использовать, проверенный пример FHIR и код, который был запущен на платформе.

## Путь данных

```
 watch, ring, scale ──► vendor app (Garmin Connect, Fitbit, Oura, Withings, Samsung Health…)
                              │  shares, with the person's permission
                              ▼
                 Apple Health (iOS)  /  Health Connect (Android)
                              │  your app reads, with the person's permission, on the phone
                              ▼
                 your app ──► your backend ──► FHIR R4 Observations in the person's record
```

Ни Apple Health, ни Health Connect не имеют серверного API: данные могут быть прочитаны только приложением на телефоне пользователя. Ваше приложение считывает их, отправляет сжатые ежедневные значения на ваш бэкенд, а бэкенд записывает их в запись.

## Какие устройства достигают какого хранилища данных о здоровье

То, чем делится каждый поставщик, меняется с версиями приложений; документация самого поставщика является эталоном.

| Устройство или приложение | Apple Health (iOS) | Health Connect (Android) | Примечания |
|---|---|---|---|
| Apple Watch | Да, нативно | — | Все, что измеряет часы, попадает в Apple Health |
| Samsung Galaxy Watch, Samsung Health | — | Частично | Samsung Health решает, какие типы данных экспортировать и как часто; см. [Samsung Health](https://developers.anpheros.com/ru/guides/samsung-health-fhir) |
| Pixel Watch, Fitbit | Нет официальной синхронизации | Да, через приложение Fitbit ([Google help](https://support.google.com/fitbit/answer/14506680)) | |
| Garmin | Да, из Garmin Connect после каждой синхронизации устройства | Да, Garmin Connect поддерживает Health Connect на Android 14 и новее ([Android Developers, August 2025](https://developer.android.com/health-and-fitness/community/newsletters/2025/08)) | Показатели, специфичные для Garmin, такие как Body Battery, не передаются |
| Oura | Да | Да ([Oura](https://ouraring.com/blog/data-sharing-partner-integrations/)) | Показатели Readiness и другие показатели Oura остаются в приложении Oura |
| Withings | Да, через Health Mate | Да ([Android Developers blog](https://android-developers.googleblog.com/2023/03/withings-reduces-data-sync-code-with--health-and-fitness-api-health-connect.html)) | Весы, тонометры, часы |

Два практических следствия. Во-первых, ваше приложение зависит от того, включил ли пользователь общий доступ в своем приложении поставщика; онбординг должен об этом сообщать. Во-вторых, хранилище данных о здоровье может содержать одни и те же шаги из двух источников (телефон и часы); читайте собственные ежедневные итоги хранилища, а не суммируйте выборки, поскольку Apple Health и Health Connect уже дедуплицируют перекрывающиеся источники.

## Таблица соответствия: тип хранилища данных → FHIR Observation

Коды, которые Anpheros Daily использует при записи данных носимых устройств в запись FHIR:

| Метрика | Apple HealthKit | Health Connect | LOINC | UCUM unit | Категория |
|---|---|---|---|---|---|
| Частота сердечных сокращений | `heartRate` | `HeartRateRecord` | 8867-4 | `/min` | vital-signs |
| Частота сердечных сокращений в покое | `restingHeartRate` | `RestingHeartRateRecord` | 40443-4 | `/min` | vital-signs |
| Вариабельность сердечного ритма | `heartRateVariabilitySDNN` | `HeartRateVariabilityRmssdRecord` | 80404-7 (только SDNN) | `ms` | vital-signs |
| Кислород в крови (SpO₂) | `oxygenSaturation` | `OxygenSaturationRecord` | 59408-5 | `%` | vital-signs |
| Частота дыхания | `respiratoryRate` | `RespiratoryRateRecord` | 9279-1 | `/min` | vital-signs |
| Шаги в день | `stepCount` | `StepsRecord` | 41950-7 | `{steps}` | activity |
| Активная энергия | `activeEnergyBurned` | `ActiveCaloriesBurnedRecord` | 41981-2 | `kcal` | activity |
| Продолжительность сна | `sleepAnalysis` (категория) | `SleepSessionRecord` | 93832-4; стадии 93831-6 глубокий сон, 93830-8 легкий сон, 93829-0 REM | `min` | activity |
| Вес тела | `bodyMass` | `WeightRecord` | 29463-7 | `kg` | vital-signs |
| Артериальное давление | `bloodPressure` (корреляция) | `BloodPressureRecord` | 85354-9 с 8480-6 и 8462-4 | `mm[Hg]` | vital-signs |
| Уровень глюкозы в крови (глюкометр) | `bloodGlucose` | `BloodGlucoseRecord` | 2339-0 | `mg/dL` | vital-signs |
| Температура тела | `bodyTemperature` | `BodyTemperatureRecord` | 8310-5 | `Cel` | vital-signs |

Обратите внимание на строку "Вариабельность сердечного ритма": Apple Health хранит **SDNN**, а Health Connect — **RMSSD**. Это разные статистические показатели, и их нельзя записывать под одним и тем же кодом. LOINC 80404-7 — это SDNN; для RMSSD Anpheros Daily использует собственную систему кодирования, а не выдает одно за другое.

## Сводки, а не каждая выборка

Устройство для отслеживания активности производит тысячи выборок частоты сердечных сокращений в день. Медицинская запись должна содержать то, что может прочитать человек или врач:

- **Одно наблюдение (Observation) на метрику в день**, с `effectivePeriod`, охватывающими местный день человека, среднесуточное значение или сумму в `valueQuantity` и, для скоростей, минимальное и максимальное значения в качестве компонентов.
- **Более детальные серии остаются там, где они полезны.** Anpheros Daily сохраняет 4-часовые сводки частоты сердечных сокращений для своих собственных диаграмм и записывает ежедневные значения в запись FHIR.
- **События отдельны.** Уведомление о нерегулярном ритме или однократное измерение артериального давления является отдельным наблюдением (Observation) со своим собственным временем, а не частью среднесуточного значения.

Ежедневная сводка частоты сердечных сокращений в формате FHIR R4 (проходит [валидатор FHIR R4](https://developers.anpheros.com/tools/fhir-validator)):

```json
{
  "resourceType": "Observation",
  "status": "final",
  "identifier": [{"system": "https://your-app.test/fhir/sid/daily-wearable", "value": "p-123:2026-10-01:heart_rate"}],
  "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "vital-signs"}]}],
  "code": {"coding": [{"system": "http://loinc.org", "code": "8867-4", "display": "Heart rate"}]},
  "subject": {"reference": "Patient/p-123"},
  "effectivePeriod": {"start": "2026-10-01T00:00:00-04:00", "end": "2026-10-02T00:00:00-04:00"},
  "valueQuantity": {"value": 71.4, "unit": "/min", "system": "http://unitsofmeasure.org", "code": "/min"},
  "component": [
    {"code": {"text": "minimum"}, "valueQuantity": {"value": 52, "unit": "/min", "system": "http://unitsofmeasure.org", "code": "/min"}},
    {"code": {"text": "maximum"}, "valueQuantity": {"value": 138, "unit": "/min", "system": "http://unitsofmeasure.org", "code": "/min"}}
  ],
  "device": {"display": "Apple Watch (via Apple Health)"}
}
```

## Запись ежедневных значений без дубликатов

Телефоны синхронизируются несколько раз в день, и последнее значение за день меняется до полуночи. Присваивайте каждому Observation стабильный идентификатор — человек, день, метрика — и обновляйте его вместо создания нового. С помощью Anpheros TypeScript SDK на вашем бэкенде:

```ts
import { Anpheros, apiKey } from '@anpheros/sdk';

const anpheros = new Anpheros({ auth: apiKey(process.env.ANPHEROS_KEY!) });

// What the phone sends: one value per metric per local day
type DailyValue = { metric: 'heart_rate' | 'steps'; day: string; value: number; min?: number; max?: number };

const CODES = {
  heart_rate: { code: '8867-4', display: 'Heart rate', unit: '/min', category: 'vital-signs' },
  steps: { code: '41950-7', display: 'Number of steps in 24 hour Measured', unit: '{steps}', category: 'activity' },
} as const;

// One Observation per person, metric and day: re-sending a day updates it instead of adding a copy.
async function upsertDaily(patientId: string, v: DailyValue, source: string) {
  const c = CODES[v.metric];
  const identifier = { system: 'https://your-app.test/fhir/sid/daily-wearable', value: `${patientId}:${v.day}:${v.metric}` };
  const resource: any = {
    resourceType: 'Observation', status: 'final',
    identifier: [identifier],
    category: [{ coding: [{ system: 'http://terminology.hl7.org/CodeSystem/observation-category', code: c.category }] }],
    code: { coding: [{ system: 'http://loinc.org', code: c.code, display: c.display }] },
    subject: { reference: `Patient/${patientId}` },
    effectivePeriod: { start: `${v.day}T00:00:00Z`, end: `${v.day}T23:59:59Z` },
    valueQuantity: { value: v.value, unit: c.unit, system: 'http://unitsofmeasure.org', code: c.unit },
  };
  if (v.min !== undefined && v.max !== undefined) {
    resource.component = [
      { code: { text: 'minimum' }, valueQuantity: { value: v.min, unit: c.unit, system: 'http://unitsofmeasure.org', code: c.unit } },
      { code: { text: 'maximum' }, valueQuantity: { value: v.max, unit: c.unit, system: 'http://unitsofmeasure.org', code: c.unit } },
    ];
  }
  const found = await anpheros.fhir.search('Observation', { identifier: `${identifier.system}|${identifier.value}` });
  const existing = found.entry?.[0]?.resource;
  return existing
    ? anpheros.fhir.update({ ...resource, id: existing.id }, { author_type: 'device' })
    : anpheros.fhir.create(resource, { author_type: 'device', source_system: source });
}
```

При выполнении на локальном экземпляре платформы с sandbox-ключом два ежедневных значения, за которыми последовала более поздняя синхронизация шагов за тот же день, привели к созданию **двух** Observations: один для шагов с версией 2 и новым значением, и provenance `v1 device apple-health · v2 device`. История сохраняет предыдущее значение, и каждый читатель может видеть, что данные поступили с устройства, а не от клинициста.

В продакшене используйте реальные границы дня в часовом поясе человека (в приведенном выше примере для краткости используется UTC), как это делает код HealthKit и Health Connect на страницах платформы.

## Чтение данных с телефона

- **iPhone и Apple Watch:** [Apple Health (HealthKit) в FHIR](https://developers.anpheros.com/ru/guides/apple-health-fhir) с кодом на Swift для ежедневной статистики.
- **Android, Wear OS, Fitbit, Garmin, Oura, Withings:** [Health Connect в FHIR](https://developers.anpheros.com/ru/guides/health-connect-fhir) с кодом на Flutter, который работает на обеих платформах.
- **Samsung Galaxy Watch и Samsung Health:** [Samsung Health в FHIR](https://developers.anpheros.com/ru/guides/samsung-health-fhir): что попадает в Health Connect и что требует собственного SDK от Samsung.

## Правила, которым стоит следовать

- **Читайте только то, что используете**, и запрашивайте каждый тип данных отдельно; люди предоставляют частичные разрешения.
- **Указывайте источник данных.** Носимые устройства потребителей не являются диагностическими приборами. Обозначайте их данные как данные устройства (`author_type: device`) и указывайте, из какого приложения они поступили, чтобы клиницист мог правильно их интерпретировать.
- **Соблюдайте правила платформы.** Руководство по проверке приложений Apple (5.1.3) запрещает использовать данные о состоянии здоровья в рекламных целях и хранить личную медицинскую информацию в iCloud; Google Play требует декларацию о приложениях для здоровья для приложений, использующих Health Connect.
- **Предоставьте пользователям возможность отключиться** и решить, остаются ли уже скопированные данные в записи.

## Что Anpheros делает и чего не делает

Платформа Anpheros сама по себе не подключается к Apple Health, Health Connect или каким-либо облачным сервисам поставщиков: ваше приложение считывает данные с телефона и записывает их через API. Собственное приложение Anpheros, **Anpheros Daily**, делает именно это: оно считывает данные из Apple Health на iPhone и Health Connect на Android, ведет ежедневные сводки и записывает их в FHIR-запись пользователя с указанными выше кодами. Подключение устройств является частью планов Plus и Max.

## Часто задаваемые вопросы

### Как получить данные Apple Watch на сервер FHIR?
Прочитайте их на iPhone из Apple Health с помощью HealthKit (серверного API нет), суммируйте их за день, и ваш бэкенд запишет каждую метрику как Observation с кодом LOINC и единицей измерения UCUM, пометив ее как данные устройства.

### Существует ли облачный API для Health Connect или Apple Health?
Нет. Оба хранят данные на телефоне; приложение, установленное на телефоне, читает их с разрешения пользователя. Облачные сервисы поставщиков, такие как Garmin, Fitbit или Oura, имеют свои собственные API, но чтение хранилища данных о здоровье телефона охватывает большинство из них с помощью одной интеграции.

### Какой код LOINC следует использовать для шагов?
41950-7, "Number of steps in 24 hour Measured", с ежедневным `effectivePeriod`. Для частоты сердечных сокращений используйте 8867-4, для SpO₂ 59408-5, для продолжительности сна 93832-4.

### Следует ли мне хранить каждый образец сердечного ритма в FHIR?
Обычно нет. Ежедневная сводка со средним, минимальным и максимальным значением — это то, что читает пользователь или врач; отдельные показания должны быть в записи только тогда, когда они имеют значение сами по себе, например, событие нерегулярного ритма.

### Могу ли я использовать один код для HRV из Apple Health и Health Connect?
Нет. Apple Health сообщает SDNN, а Health Connect сообщает RMSSD; они измеряют разные вещи и требуют разных кодов.

## Связанные материалы

- [API носимых устройств: Fitbit, Garmin, Oura и Withings](https://developers.anpheros.com/ru/guides/wearable-apis)
- [API трекеров здоровья](https://developers.anpheros.com/ru/guides/health-tracker-api): хранение данных трекера на сервере с согласия пользователя
- [Как создать приложение для персональной медицинской карты](https://developers.anpheros.com/ru/guides/personal-health-record-app)
- [Интеграции в здравоохранении](https://developers.anpheros.com/ru/guides/healthcare-integrations): устройства наряду с лабораториями, клиниками и приложениями
- [Кодовые системы FHIR](https://developers.anpheros.com/ru/guides/fhir-code-systems): LOINC и UCUM
- [Происхождение медицинских данных: объяснение](https://developers.anpheros.com/ru/guides/medical-data-provenance)
- [Как нормализовать медицинские данные](https://developers.anpheros.com/ru/guides/normalize-medical-data)
- [Удаленный мониторинг пациентов с помощью FHIR](https://developers.anpheros.com/ru/guides/remote-patient-monitoring-fhir): отдельные показания, веб-хуки и оповещения
