AnpherosAnpheros PlatformDevelopers

Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card

Apple Health (HealthKit) do FHIR

Odczytaj dane z Apple Watch i Apple Health za pomocą HealthKit w Swift, według lokalnego dnia, i zapisz je do rekordu FHIR R4: uprawnienia, synchronizacja w tle, zasady Apple.

Dane z Apple Watch znajdują się w Apple Health na sparowanym iPhonie, a jedynym sposobem na ich odczytanie jest HealthKit, z aplikacji na tym iPhonie, za zgodą użytkownika. Aby umieścić je w rekordzie FHIR, odczytaj dzienne statystyki za pomocą HKStatisticsCollectionQuery, wyślij wartości do swojego backendu i zapisz każdą metrykę jako Observation z kodem LOINC i jednostką UCUM. Ta strona pokazuje kod Swift (sprawdzony pod kątem typu z SDK iOS 17), uprawnienia i zasady ustalone przez Apple oraz sposób, w jaki wartości stają się FHIR R4 Observations.

Co znajduje się w Apple Health

Apple Health gromadzi dane mierzone przez iPhone'a i Apple Watch — tętno, tętno spoczynkowe, zmienność rytmu serca (SDNN), poziom tlenu we krwi, częstość oddechów, kroki, zużycie energii, fazy snu, powiadomienia o nieregularnym rytmie, zapisy EKG — oraz dane zapisywane przez inne aplikacje: Garmin Connect, Oura, Withings Health Mate, inteligentne wagi, monitory ciśnienia krwi, glukometry. Odczytując dane z Apple Health, uzyskujesz dostęp do szerszego zakresu informacji niż tylko te z Apple Watch.

Nie ma serwera HealthKit ani interfejsu API sieciowego. Dane pozostają na urządzeniu (oraz w zaszyfrowanej kopii zapasowej iCloud użytkownika); Twoja aplikacja odczytuje je lokalnie.

Uprawnienia

  1. Włącz funkcję HealthKit w Xcode i dodaj NSHealthShareUsageDescription do Info.plist (oraz NSHealthUpdateUsageDescription, jeśli piszesz).
  2. Poproś o potrzebne typy. Użytkownicy mogą zezwolić na niektóre, a odmówić innych, a HealthKit nie informuje Twojej aplikacji, czy odmówiono dostępu do odczytu: odmówiony typ po prostu zwraca brak danych. Zaprojektuj ekrany dla scenariusza "brak danych", a nie dla błędu.
  3. Poproś w momencie, gdy użytkownik się połączy, z wyjaśnieniem, dlaczego, a nie przy pierwszym uruchomieniu.

Odczytywanie dziennych wartości w Swift

import Foundation
import HealthKit

/// One day of Apple Health data, ready to send to your backend.
struct DailyValue: Codable {
    let metric: String      // "heart_rate", "steps"
    let day: String         // "2026-10-01", the user's local day
    let value: Double
    let min: Double?
    let max: Double?
}

let store = HKHealthStore()
let heartRate = HKQuantityType(.heartRate)
let steps = HKQuantityType(.stepCount)

func requestAccess() async throws {
    // Read-only: the app never writes to Apple Health.
    try await store.requestAuthorization(toShare: [], read: [heartRate, steps])
}

/// Daily statistics for the last `days` days, one value per local calendar day.
func dailyValues(_ type: HKQuantityType, metric: String, unit: HKUnit,
                 options: HKStatisticsOptions, days: Int) async throws -> [DailyValue] {
    let calendar = Calendar.current
    let end = calendar.startOfDay(for: Date()).addingTimeInterval(86_400)
    let start = calendar.date(byAdding: .day, value: -days, to: end)!
    let query = HKStatisticsCollectionQueryDescriptor(
        predicate: HKSamplePredicate.quantitySample(type: type,
                                                    predicate: HKQuery.predicateForSamples(withStart: start, end: end)),
        options: options,
        anchorDate: start,
        intervalComponents: DateComponents(day: 1))
    let collection = try await query.result(for: store)
    let fmt = DateFormatter()
    fmt.dateFormat = "yyyy-MM-dd"
    var out: [DailyValue] = []
    collection.enumerateStatistics(from: start, to: end) { stats, _ in
        let day = fmt.string(from: stats.startDate)
        if options.contains(.cumulativeSum), let sum = stats.sumQuantity() {
            out.append(DailyValue(metric: metric, day: day, value: sum.doubleValue(for: unit), min: nil, max: nil))
        } else if let avg = stats.averageQuantity() {
            out.append(DailyValue(metric: metric, day: day, value: avg.doubleValue(for: unit),
                                  min: stats.minimumQuantity()?.doubleValue(for: unit),
                                  max: stats.maximumQuantity()?.doubleValue(for: unit)))
        }
    }
    return out
}

func collect() async throws -> [DailyValue] {
    try await requestAccess()
    let bpm = HKUnit.count().unitDivided(by: .minute())
    let hr = try await dailyValues(heartRate, metric: "heart_rate", unit: bpm,
                                   options: [.discreteAverage, .discreteMin, .discreteMax], days: 30)
    let st = try await dailyValues(steps, metric: "steps", unit: .count(), options: .cumulativeSum, days: 30)
    return hr + st   // POST these to your backend, which writes them to the FHIR record
}

Dlaczego zapytania statystyczne zamiast odczytywania próbek: HKStatisticsCollectionQuery zwraca dzienne sumy i średnie, które Apple Health już zdeduplikowało między źródłami, dzięki czemu kroki policzone zarówno przez iPhone'a, jak i zegarek nie są dodawane dwukrotnie. Odczytywanie surowych próbek i samodzielne ich sumowanie jest najczęstszym źródłem zawyżonych liczników kroków.

Dni to lokalne dni kalendarzowe osoby (Calendar.current). Zachowaj je w ten sposób aż do rekordu FHIR, gdzie effectivePeriod obiektu Observation to ten lokalny dzień z przesunięciem strefy czasowej.

Utrzymanie aktualności rekordu

Od wartości Swift do obserwacji FHIR

Wyślij tablicę DailyValue do swojego zaplecza i zapisz jedną obserwację dla każdej osoby, metryki i dnia ze stabilnym identyfikatorem, aktualizując ją, gdy ten sam dzień nadejdzie ponownie. Tabela mapowania (typ HealthKit → LOINC → UCUM), zweryfikowany przykład JSON oraz kod TypeScript wykonujący tę operację upsert, uruchomiony na platformie, znajdują się w Dane z urządzeń noszonych w FHIR. Kody dla dwóch metryk tutaj to:

HealthKit LOINC UCUM Wartość na dzień
heartRate 8867-4 Heart rate /min średnia, z minimum i maksimum jako komponentami
stepCount 41950-7 Number of steps in 24 hour {steps} suma

Zasady firmy Apple dotyczące danych o stanie zdrowia

Apple Health Records

Oprócz danych dotyczących kondycji, Apple Health może przechowywać dane kliniczne pobrane z uczestniczących systemów opieki zdrowotnej (głównie w Stanach Zjednoczonych), a HealthKit udostępnia je jako obiekty HKClinicalRecord, które zawierają oryginalny zasób FHIR. Odczytanie ich wymaga osobnego uprawnienia i zgody. Jest to inna integracja niż dane z urządzeń noszonych, a Anpheros Daily ich dzisiaj nie odczytuje.

Gdzie Anpheros się mieści

Platforma Anpheros przechowuje wynik: rekord FHIR R4 osoby, z każdą wartością z urządzenia noszonego jako Observation oznaczoną jako dane urządzenia, zgodą na inne aplikacje, pochodzeniem danych i dziennikiem dostępu. Nie odczytuje bezpośrednio Apple Health — dzieje się to w Twojej aplikacji iOS. Własna aplikacja Anpheros, Anpheros Daily, odczytuje Apple Health na iPhonie (plany Plus i Max) i zapisuje codzienne podsumowania do rekordu z powyższymi kodami.

Często zadawane pytania

Czy mogę odczytywać dane z Apple Watch z serwera?

Nie. Dane z Apple Watch są synchronizowane z Apple Health na sparowanym iPhonie, a HealthKit może być używany tylko przez aplikację na tym urządzeniu. Aplikacja odczytuje dane i wysyła je na Twój serwer.

Czy istnieje internetowe lub REST API dla Apple Health?

Nie. Apple nie oferuje internetowego ani REST API dla Apple Health: HealthKit działa tylko wewnątrz aplikacji na iPhonie (lub Apple Watch) użytkownika. Aby używać danych na serwerze, Twoja aplikacja odczytuje je za zgodą użytkownika i wysyła, na przykład jako FHIR Observations do Anpheros.

Czy potrzebuję klucza API lub płacę za Apple Health API?

Żaden klucz ani opłata: HealthKit jest częścią iOS. Potrzebujesz możliwości HealthKit w swojej aplikacji, opisu użycia dla każdego typu danych i zgody użytkownika; recenzja App Store sprawdza, jak używasz danych.

Skąd mam wiedzieć, czy użytkownik odmówił dostępu do typu HealthKit?

Nie możesz, w przypadku dostępu do odczytu: HealthKit ukrywa to w celu ochrony prywatności, a odmówiony typ nie zwraca żadnych danych. Traktuj "brak danych" jako normalny stan i zaoferuj sposób na przeglądanie uprawnień w aplikacji Zdrowie.

Dlaczego moje liczniki kroków są wyższe niż w aplikacji Zdrowie?

Prawdopodobnie sumujesz surowe próbki z kilku źródeł (iPhone i Watch). Użyj HKStatisticsCollectionQuery z .cumulativeSum, które stosuje własne usuwanie duplikatów Apple Health.

Który kod LOINC odpowiada zmienności tętna Apple Watch?

Apple Health przechowuje HRV jako SDNN, co odpowiada LOINC 80404-7. Health Connect przechowuje RMSSD, inną statystykę, więc nie mieszaj tych dwóch pod jednym kodem.

Powiązane

Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card

Product updates by email

New features, guides and the end of the beta. One email a month at most.

Send me occasional Anpheros Platform updates by email (new features, API changes, guides). I'll confirm by email and can unsubscribe in one click from any email. Privacy