# Apple Health (HealthKit) إلى FHIR

> اقرأ بيانات Apple Watch و Apple Health باستخدام HealthKit في Swift، لكل يوم محلي، واكتبها إلى سجل FHIR R4: الأذونات، والمزامنة في الخلفية، وقواعد Apple.

Source: https://developers.anpheros.com/ar/guides/apple-health-fhir

**توجد بيانات Apple Watch في Apple Health على جهاز iPhone المقترن، والطريقة الوحيدة لقراءتها هي HealthKit، من تطبيق على هذا الـ iPhone، بإذن الشخص.** لوضعها في سجل FHIR، اقرأ الإحصائيات اليومية باستخدام `HKStatisticsCollectionQuery`، وأرسل القيم إلى الواجهة الخلفية الخاصة بك، واكتب كل مقياس كملاحظة (Observation) مع رمز LOINC ووحدة UCUM. تعرض هذه الصفحة كود Swift (تم التحقق من النوع مقابل iOS 17 SDK)، والأذونات والقواعد التي تضعها Apple، وكيف تصبح القيم ملاحظات FHIR R4.

## ما هو موجود في Apple Health

تجمع Apple Health ما تقيسه iPhone و Apple Watch — معدل ضربات القلب، ومعدل ضربات القلب أثناء الراحة، وتقلب معدل ضربات القلب (SDNN)، والأكسجين في الدم، ومعدل التنفس، والخطوات، والطاقة، ومراحل النوم، وإشعارات عدم انتظام ضربات القلب، وتسجيلات ECG — وما تكتبه التطبيقات الأخرى: Garmin Connect، و Oura، و Withings Health Mate، والمقاييس الذكية، وأجهزة قياس ضغط الدم، وأجهزة قياس نسبة الجلوكوز. لذلك، فإن قراءة Apple Health تغطي أكثر من مجرد Apple Watch.

لا يوجد خادم HealthKit أو واجهة برمجة تطبيقات ويب. تبقى البيانات على الجهاز (وفي النسخة الاحتياطية المشفرة لـ iCloud الخاصة بالشخص)؛ يقرأها تطبيقك محليًا.

## الأذونات

1. قم بتشغيل إمكانية **HealthKit** في Xcode وأضف `NSHealthShareUsageDescription` إلى `Info.plist` (بالإضافة إلى `NSHealthUpdateUsageDescription` فقط إذا كنت تكتب).
2. اطلب أنواع البيانات التي تحتاجها. يمكن للأشخاص السماح ببعضها ورفض البعض الآخر، و**لا يخبر HealthKit تطبيقك ما إذا كان الوصول للقراءة قد تم رفضه**: النوع المرفوض ببساطة لا يُرجع أي بيانات. صمم الشاشات لـ "عدم وجود بيانات" بدلاً من تصميمها لخطأ.
3. اطلب في اللحظة التي يتصل فيها الشخص، مع جملة تشرح السبب، وليس عند التشغيل الأول.

## قراءة القيم اليومية في Swift

```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
}
```

لماذا استعلامات الإحصائيات بدلاً من قراءة العينات: `HKStatisticsCollectionQuery` تُرجع الإجماليات والمتوسطات لكل يوم والتي قامت Apple Health بإلغاء تكرارها بالفعل عبر المصادر، لذلك لا تتم إضافة الخطوات التي تم حسابها بواسطة كل من iPhone و Watch مرتين. قراءة العينات الأولية وجمعها بنفسك هو المصدر الأكثر شيوعًا لزيادة عدد الخطوات.

الأيام هي أيام التقويم المحلية للشخص (`Calendar.current`). احتفظ بها على هذا النحو طوال الطريق إلى سجل FHIR، حيث يكون `effectivePeriod` في Observation هو ذلك اليوم المحلي مع إزاحة المنطقة الزمنية الخاصة به.

## الحفاظ على تحديث السجل

- **عند الفتح:** اقرأ عدد الأيام منذ آخر مزامنة ناجحة في كل مرة يعود فيها التطبيق إلى الواجهة الأمامية. هذا هو الأساس الموثوق.
- **في الخلفية:** `HKObserverQuery` مع `enableBackgroundDelivery(for:frequency:)` توقظ تطبيقك عند وصول بيانات جديدة؛ يتطلب ذلك صلاحية تسليم الخلفية لـ HealthKit، ويقرر نظام iOS التوقيت الفعلي.
- **الاتصال الأول:** قم باستيراد سجل محدود (على سبيل المثال، 30 يومًا) بدلاً من سنوات، ثم تقدم للأمام.

## من قيم Swift إلى ملاحظات FHIR

أرسل مصفوفة `DailyValue` إلى الواجهة الخلفية الخاصة بك واكتب ملاحظة (Observation) واحدة لكل شخص ومقياس ويوم بمعرف ثابت، وقم بتحديثها عندما يأتي نفس اليوم مرة أخرى. جدول الربط (نوع HealthKit → LOINC → UCUM)، مثال JSON تم التحقق منه، وشفرة TypeScript التي تقوم بعملية التحديث/الإدراج هذه، والتي تعمل على المنصة، موجودة في [بيانات الأجهزة القابلة للارتداء في FHIR](https://developers.anpheros.com/ar/guides/wearable-data-fhir). الرموز للمقياسين هنا هي:

| HealthKit | LOINC | UCUM | القيمة لليوم الواحد |
|---|---|---|---|
| `heartRate` | 8867-4 Heart rate | `/min` | متوسط، مع الحد الأدنى والأقصى كمكونات |
| `stepCount` | 41950-7 Number of steps in 24 hour | `{steps}` | الإجمالي |

## قواعد Apple لبيانات الصحة

- إرشادات مراجعة التطبيقات 5.1.3: لا يجوز استخدام بيانات الصحة للإعلان أو التنقيب عن البيانات، ولا يجوز مشاركتها مع أطراف ثالثة دون موافقة الشخص، ولا يجوز تخزين معلومات الصحة الشخصية في iCloud.
- يجب أن تذكر سياسة الخصوصية الخاصة بك ما تقرأه ولماذا؛ تتحقق Apple من ذلك.
- البيانات التي يكتبها تطبيقك إلى Apple Health تُنسب إلى تطبيقك؛ البيانات التي تقرأها تحتفظ بمصدرها الأصلي (`HKSource`)، والذي يجب عليك نقله إلى السجل كنظام المصدر.

## سجلات صحة Apple

بصرف النظر عن بيانات اللياقة البدنية، يمكن لـ Apple Health الاحتفاظ بالسجلات السريرية التي تم تنزيلها من أنظمة صحية مشاركة (معظمها في الولايات المتحدة)، ويكشف HealthKit عنها ككائنات `HKClinicalRecord` تحمل مورد FHIR الأصلي. تتطلب قراءتها إذنًا وحقًا خاصين بها. إنها تكامل مختلف عن بيانات الأجهزة القابلة للارتداء، ولا تقرأها Anpheros Daily حاليًا.

## أين يتناسب Anpheros

يقوم Anpheros Platform بتخزين النتيجة: سجل FHIR R4 للشخص، مع كل قيمة من الأجهزة القابلة للارتداء كـ Observation تم تمييزها كبيانات جهاز، وموافقة للتطبيقات الأخرى، وبيانات المصدر، وسجل وصول. لا يقرأ Apple Health بنفسه - يحدث ذلك في تطبيق iOS الخاص بك. يقرأ تطبيق Anpheros الخاص، **Anpheros Daily**، Apple Health على iPhone (خطط Plus و Max) ويكتب ملخصات يومية إلى السجل باستخدام الرموز المذكورة أعلاه.

## أسئلة متكررة

### هل يمكنني قراءة بيانات Apple Watch من خادم؟
لا. تتم مزامنة بيانات Apple Watch مع Apple Health على جهاز iPhone المقترن، ولا يمكن استخدام HealthKit إلا بواسطة تطبيق على هذا الجهاز. يقرأ التطبيق البيانات ويرسلها إلى خادمك.

### هل توجد واجهة برمجة تطبيقات ويب أو واجهة برمجة تطبيقات REST لـ Apple Health؟
لا. لا تقدم Apple واجهة برمجة تطبيقات ويب أو REST لـ Apple Health: يعمل HealthKit فقط داخل تطبيق على iPhone (أو Apple Watch) الخاص بالشخص. لاستخدام البيانات على خادم، يقرأها تطبيقك بإذن الشخص ويرسلها، على سبيل المثال كـ FHIR Observations إلى Anpheros.

### هل أحتاج إلى مفتاح API أو الدفع مقابل واجهة برمجة تطبيقات Apple Health؟
لا يوجد مفتاح ولا رسوم: HealthKit هو جزء من iOS. تحتاج إلى إمكانية HealthKit في تطبيقك، ووصف استخدام لكل نوع بيانات، وإذن الشخص؛ يقوم مراجعة App Store بالتحقق من كيفية استخدامك للبيانات.

### كيف أعرف إذا رفض الشخص الوصول إلى نوع HealthKit؟
لا يمكنك ذلك، بالنسبة لوصول القراءة: يخفي HealthKit ذلك لحماية الخصوصية، ويعيد النوع المرفوض عدم وجود بيانات. تعامل مع "عدم وجود بيانات" كحالة طبيعية وقدم طريقة لمراجعة الأذونات في تطبيق Health.

### لماذا عدد خطواتي أعلى مما هو عليه في تطبيق Health؟
من المحتمل أنك تجمع عينات خام من عدة مصادر (iPhone و Watch). استخدم `HKStatisticsCollectionQuery` مع `.cumulativeSum`، والذي يطبق إزالة التكرار الخاصة بـ Apple Health.

### ما هو رمز LOINC لمعدل ضربات القلب المتغيرة لساعة Apple Watch؟
يخزن Apple Health معدل ضربات القلب المتغيرة (HRV) كـ SDNN، والذي يتطابق مع LOINC 80404-7. يخزن Health Connect RMSSD، وهو إحصائية مختلفة، لذا لا تخلط بين الاثنين تحت رمز واحد.

## ذات الصلة

- [بيانات الأجهزة القابلة للارتداء في FHIR](https://developers.anpheros.com/ar/guides/wearable-data-fhir): جدول التعيين والرمز الخلفي
- [Health Connect إلى FHIR](https://developers.anpheros.com/ar/guides/health-connect-fhir): نفس الشيء على Android
- [كيفية بناء تطبيق سجل صحي شخصي](https://developers.anpheros.com/ar/guides/personal-health-record-app)
- [كيفية بناء تطبيق رعاية صحية باستخدام Flutter](https://developers.anpheros.com/guides/healthcare-app-flutter)
