App-Architektur

Technische Architektur der HyponaTrack-App

Zweck: Multimodales Home-Monitoring nach transsphenoidaler Hypophysenchirurgie zur Frühwarnung einer verzögerten postoperativen Hyponaträmie (DPH).

Systemübersicht

Die HyponaTrack-App ist als native iOS-Anwendung (SwiftUI, iOS 18.0+) mit MVVM-Architektur und Service Layer implementiert. Die App gliedert sich in fünf Hauptbereiche: Dashboard (Ampel), Erfassung (Eingabe), Trends (Charts), Alarme (Push) und Export (CSV/PDF/REDCap-Sync).

arch cluster_app HyponaTrack App cluster_server Studienserver cluster_devices Datenquellen waage Withings-Waage Gewicht 2×/Tag hk HealthKit waage->hk watch Apple Watch HRV · Schlaf · Schritte watch->hk refr Refraktometer Urin-SG (OCR) sd SwiftData (Persistenz) refr->sd man Manuelle Eingabe Symptome · Flüssigkeit man->sd hk->sd ee EscalationEngine Ampel-Logik sd->ee rc REDCap EDC Studiendaten sd->rc Auto-Sync nf Notifications Push-Alerts ee->nf la Live Activity Lock Screen ee->la nurse Study Nurse iPad Dashboard ee->nurse ROT-Alert rc->nurse

App-Architektur — Datenfluss von Sensoren zum Studienserver

Technologie-Stack

Komponente Technologie Begründung
UI Framework SwiftUI (iOS 18+) Deklarativ, Charts-Framework nativ
Persistenz SwiftData Nativer Swift-Stack, kein CoreData-Boilerplate
Gesundheitsdaten HealthKit Gewicht, Aktivität, HRV, Schlaf, Wasser
Charts Swift Charts Nativ, performant, für Trend-Darstellung
Notifications UserNotifications Lokale Erinnerungen + Eskalations-Alerts
Care Plan CareKit + CareKitStore Care Plan Management, Aufgabenplanung
Consent ResearchKit Einwilligungsflow gemäß Studienprotokoll
Studien-EDC REDCap REST API Automatischer Datensync zur Studien-EDC
Lock-Screen Widget Live Activity / ActivityKit Monitoring-Widget auf dem Sperrbildschirm
Watch Companion WatchConnectivity Apple Watch Companion-App
Architektur MVVM + Service Layer Standard für SwiftUI, testbar
Minimum Target iOS 18.0 SwiftData + ActivityKit Voraussetzung
Tabelle 1: Technologie-Stack der HyponaTrack-App.

Datenmodell

datamodel PatientProfile PatientProfile studyID : String surgeryDate : Date age : Int sex : Sex bmi : Double baselineWeight : Double Kat A: Histologie, Stieldev., Medik. Kat B: POD-Na⁺, OP-Dauer, Liquor Kat C: Erbrechen, Desmopressin buildRiskProfile() → RiskProfile buildBaseline() → PatientBaseline currentPostOpDay : Int DailyEntry DailyEntry date : Date postOpDay : Int weightMorning / Evening : Double? fluidIntakeML : Double urineSG : Double? stepCount, hrvSDNN, sleepMin alertLevel : AlertLevel alertReasons : [String] PatientProfile->DailyEntry 1 : n (14 Tage) RiskProfile RiskProfile scoreKatA : Int scoreKatB : Int scoreKatC : Int riskScore : Int riskClass : niedrig/mittel/hoch PatientProfile->RiskProfile berechnet SymptomEntry SymptomEntry timestamp : Date nausea (×3), headache (×3) fatigue (×2), confusion (×4) muscleCramps (×2), VAS totalScore : Int DailyEntry->SymptomEntry 1 : 2 (morgens/abends) CognitiveTest CognitiveTestResult meanReactionTime : Double medianReactionTime : Double errorCount : Int deltaFromBaseline : Double DailyEntry->CognitiveTest 1 : 0..1 AlertLevel AlertLevel green : Routine yellow : Ambulanz-Kontakt red : Sofort NA DailyEntry->AlertLevel hat
Abbildung 1: Datenmodell — SwiftData Entity-Relationship-Diagramm

PatientProfile (SwiftData)

Zentrale Patientenstammdaten inkl. aller Risikofaktoren (Kat. A/B/C): surgeryDate, age, sex, bmi, baselineWeight, studyID (Pseudonym, z. B. „UKE-2026-0042”), risikoMedikamenteCSV (kommagetrennte Enum-Werte), isLoanDevice, baselineIsPraeOp, isSimplifiedMode (vereinfachter Modus, von Study Nurse aktivierbar).

Berechnete Eigenschaften: isKatBPending (Intra-OP-Daten fehlen noch), isMonitoringActive (Monitoring läuft), currentPostOpDay (aktueller POD). buildRiskProfile() → RiskProfile für Algorithmus. buildBaseline() → PatientBaseline für Trend-Analyse.

DailyEntry (SwiftData)

Ein Eintrag pro Tag (POD), enthält alle Messwerte: Gewicht (morgens/abends), Fluid, Urin-SG, Symptom-Referenzen, HealthKit-Daten (Steps, HRV, Sleep, HR), Alert-Level + Reasons, isMorningCheckComplete, isEveningCheckComplete.

SymptomEntry (SwiftData)

6-Item-Score: Übelkeit, Kopfschmerz, Müdigkeit, Verwirrtheit, Muskelkrämpfe, Wohlbefinden-VAS.

Scoring: totalScore = nausea x 3 + headache x 3 + fatigue x 2 + confusion x 4 + muscleCramps x 2 + max(0, 10 − VAS)

AlertLevel (Ampel)

Drei Stufen: green (Routine-Monitoring fortführen), yellow (Telefonische Rückmeldung Ambulanz), red (Sofortige Vorstellung NA/Ambulanz).

Services und Module

services cluster_input Eingabe cluster_vm ViewModels cluster_services Services / Business Logic cluster_persist Persistenz views SwiftUI Views Dashboard · DataEntry Trends · Settings dvm DashboardVM views->dvm ee EscalationEngine ROT/GELB/GRÜN Ampel-Logik dvm->ee evm DataEntryVM ovm OnboardingVM sd SwiftData PatientProfile DailyEntry ee->sd re RiskEngine Kat A/B/C Score ta TrendAnalyzer Gewicht · Aktivität hk HealthKitService Schritte · HRV · Schlaf hk->sd rc REDCapService Auto-Sync (Actor) rc->sd Offline-Queue ck CareKitStore Pflegeplan ns NotificationService Push-Alerts ars AdaptiveReminderService Intensitaetssteuerung ars->ns ocr RefractometerOCR Urin-SG Kamera kc Keychain PIN · REDCap-Token
Abbildung 2: Services und Module — Architekturübersicht der Service-Schicht

Eskalations-Engine (Kernalgorithmus)

Der Kern-Algorithmus in EscalationEngine.swift: EscalationEngine.evaluate(entry:profile:) → EvaluationResult(level, reasons).

Ablauf: (1) PatientProfile.buildRiskProfile() → Risiko-Score → Risikoklasse. (2) AlertThresholds.forRiskClass(_, pod:) → angepasste Schwellenwerte. (3) PatientProfile.buildBaseline() → Baseline-Werte. (4) DailyEntry → DailySnapshot (Mapping). (5) AlertEngine.evaluate(snapshot:thresholds:) → Level + Trigger-Gründe. (6) Ergebnis wird in DailyEntry.alertLevel und .alertReasons gespeichert.

Bei hohem Risiko werden Gelb/Rot-Schwellen um ~20 % gesenkt.

Adaptive Erinnerungen (AdaptiveReminderService)

Der AdaptiveReminderService berechnet einmal täglich die Erinnerungsintensität (minimal / normal / erhöht / maximal) basierend auf der 3-Tage-Adhärenz, der POD-Phase und dem heutigen Morgen-Check-Status. Die Intensität bestimmt, welche Benachrichtigungen über den NotificationService geplant werden — von nur Morgen-/Abend-Check (minimal) bis hin zu task-spezifischen Erinnerungen mit Nachmittags-Nachhol-Reminder (maximal). Im kritischen Fenster (POD 5–9) wird die Intensität automatisch auf mindestens „erhöht” gesetzt.

Vereinfachter Modus (isSimplifiedMode)

Von der Study Nurse beim Onboarding oder in den Einstellungen aktivierbar. Reduziert die Tab-Leiste auf Dashboard + Kontakte, blendet kognitive Tests (Reaktionszeit, Feinmotorik, Trail Making) aus der Aufgabenliste aus, entfernt Sync-Status und Kat-B-Hinweise vom Dashboard. Die adaptiven Erinnerungen berücksichtigen den Modus und versenden keine Reminder für ausgeblendete Tasks.

adaptive start Taglicher Check (DashboardViewModel) adh 3-Tage-Adhaerenz berechnen start->adh pod POD-Phase pruefen adh->pod crit POD 5-9? (Kritisches Fenster) pod->crit low Adhaerenz < 60%? crit->low Ja crit->low Nein elev ERHOHT Alle Task-Reminder crit->elev Ja + Adh OK high Adhaerenz >= 80% + Morgen OK? low->high Nein max MAXIMAL Alle + Nachmittag low->max Ja + POD 5-9 low->elev Ja norm NORMAL + Missed-Reminder high->norm Nein mini MINIMAL Nur Morgen/Abend high->mini Ja ns NotificationService Reschedule max->ns elev->ns norm->ns mini->ns
Abbildung 3: Adaptive Erinnerungen — Entscheidungslogik

REDCap-Integration

redcap entry DailyEntry (SwiftData) queue Offline-Queue (SwiftData) Retry mit Backoff entry->queue Neuer Eintrag sync REDCapService (Actor) Background-Sync queue->sync Netzwerk verfügbar sync->queue Fehler → Retry api REDCap REST API /api/?content=record &format=json sync->api POST importRecords edc REDCap EDC Studiendatenbank api->edc
Abbildung 4: REDCap-Synchronisation — Offline-fähiger Datenfluss

REDCapService (Actor)

Actor-basierter Auto-Sync mit Offline-Queue: configure(serverURL:token:) mit HTTPS-Pflicht, autoSync(entry:profile:) nach jeder Eingabe, exportAll(profile:entries:) für manuellen Vollexport, retryPendingIfNeeded() für Offline-Queue.

Sicherheit: API-Token im Keychain (nicht UserDefaults). HTTPS wird erzwungen. Offline-Queue: Fehlgeschlagene Requests werden gespeichert und bei nächster Verbindung nachgesendet.

Datenmapping: Baseline → patient_baseline Instrument. Tageseinträge → daily_monitoring Repeating Instrument (Instance = POD).

HealthKit-Integration

healthkit cluster_read Lesen → App cluster_sources Datenquellen waage WLAN-Waage (Withings) hk HealthKit Store waage->hk watch Apple Watch watch->hk manual App-Eingabe (Fluid) manual->hk Schreiben r1 Schritte Aktivitäts-Trend hk->r1 r2 Ruhe-HF Kontext hk->r2 r3 HRV (SDNN) Kontext hk->r3 r4 Schlaf Kontext hk->r4 r5 Gewicht Primärparameter hk->r5 bg Background Delivery hk->bg Gewicht Schritte
Abbildung 5: HealthKit-Integration — Datentypen und Flussrichtung
Typ Richtung Verwendung
Schritte Lesen Aktivitäts-Trend
Ruheherzfrequenz Lesen Kontext
HRV (SDNN) Lesen Kontext
Schlafdauer Lesen Kontext
Gewicht Lesen + Schreiben Automatischer Import von WLAN-Waagen
Wasser Schreiben Manuelle Eingabe → HealthKit
Tabelle 2: HealthKit-Datentypen und Verwendung in HyponaTrack.

Background Delivery: Gewicht und Schritte werden im Hintergrund aktualisiert.

CareKit-Integration

carekit cluster_morning Morgen-Check cluster_evening Abend-Check cluster_day Über den Tag manager CareKitStoreManager Pflegeplan-Setup schedule OCKSchedule OP-Datum → 14 Tage Morgen · Tag · Abend manager->schedule t1 Gewicht (morgens) t2 Symptom-Score (morgens) t3 Flüssigkeit (kontinuierlich) t4 Urin-SG (1x/Tag) t5 Kognitiv-Test (1x/Tag) t6 Tapping-Test (1x/Tag) t7 Gewicht (abends) t8 Symptom-Score (abends) optional Desmopressin (optional, falls verordnet) schedule->t1 schedule->t3 schedule->t7 schedule->optional
Abbildung 6: CareKit-Integration — Pflegeplan und Aufgabenstruktur

CareKitStoreManager erstellt den Pflegeplan mit 7–9 OCKTasks (Gewicht, Symptome, Fluid, Urin-SG, Kognition, Tapping, optional Desmopressin). Schedules basieren auf dem OP-Datum und laufen 14 Tage.

Sicherheit

Maßnahme Implementierung
PIN-Hashing SHA-256 + Salt (CryptoKit) in KeychainService
Biometrische Auth Face ID → Passcode Fallback (AppLockManager)
Token-Speicherung Keychain (kSecAttrAccessibleWhenUnlockedThisDeviceOnly)
HTTPS-Pflicht Erzwungen in REDCapService.configure() und .post()
Kein Passcode App bleibt gesperrt (Simulator ausgenommen)
Datenlokalität SwiftData lokal, kein Cloud-Backend
Tabelle 3: Sicherheitsmaßnahmen der HyponaTrack-App.