Saltar al contenido principal

Uso del SDK iOS

Inicialización

El SDK se consume como un framework KMP en iOS. Utilice el patrón builder para crear una instancia. La función build() es asíncrona y realiza la generación del par de claves DPoP (Secure Enclave), la activación del token y la verificación de permisos.

import VitaleraSdkCore

let sdk = try await VitaleraSdk.companion.builder()
.clientId(clientId: "your-org-license-key")
.addProvider(providerName: "omron")
.addProvider(providerName: "polar")
.addProvider(providerName: "standard-ble")
.connectedMode(enabled: true)
.build()

Gestione los errores de autenticación:

do {
let sdk = try await VitaleraSdk.companion.builder()
.clientId(clientId: "your-org-license-key")
.build()
} catch let error as SdkAuthException {
switch error.errorCode {
case "activation_failed":
showInvalidLicenseError()
case "entitlements_expired":
showConnectToInternetPrompt()
case "no_cache":
showFirstLaunchOfflineError()
default:
showGenericError(error.message)
}
}

Permisos

Añada los permisos requeridos en su Info.plist:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app uses Bluetooth to connect with medical devices.</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app uses Bluetooth to communicate with devices.</string>

Para HealthKit:

<key>NSHealthShareUsageDescription</key>
<string>This app reads health data for monitoring.</string>

Descubrimiento de dispositivos

El descubrimiento utiliza Swift AsyncSequence. Cada dispositivo descubierto se devuelve como un DeviceDescriptor.

let filter = DiscoveryFilter(
providers: nil,
capabilities: [DeviceCapability.bloodPressure],
namePrefix: nil
)

for try await descriptor in sdk.devices.discover(filter: filter, timeoutMs: 15_000) {
print("Found: \(descriptor.name) (\(descriptor.provider))")
}

Opciones de filtrado

// Only Polar devices
let polarFilter = DiscoveryFilter(
providers: ["polar"],
capabilities: nil,
namePrefix: nil
)

// Only heart rate monitors
let hrFilter = DiscoveryFilter(
providers: nil,
capabilities: [DeviceCapability.heartRate],
namePrefix: nil
)

Conexión de dispositivos

Cree un dispositivo a partir de un descriptor y conéctese. La función connect() es asíncrona con un tiempo de espera configurable.

let device = sdk.devices.createDevice(descriptor: descriptor)

// Connect (async, with timeout)
try await device.connect(timeoutMs: 10_000)

Recopilación de datos

El método collect() devuelve un AsyncSequence de clases de observación tipadas.

for try await observation in device.collect() {
if let bp = observation as? BloodPressureObservation {
print("BP: \(bp.systolic)/\(bp.diastolic) mmHg")
if let pulse = bp.pulseRate {
print("Pulse: \(pulse) bpm")
}
} else if let hr = observation as? HeartRateObservation {
print("HR: \(hr.heartRate) bpm")
} else if let temp = observation as? TemperatureObservation {
print("Temp: \(temp.temperature) C")
} else if let weight = observation as? WeightObservation {
print("Weight: \(weight.weight) kg")
} else if let spo2 = observation as? OxygenSaturationObservation {
print("SpO2: \(spo2.spo2)%")
}
}

// Disconnect when done
try await device.disconnect()

Modo conectado

Cuando el modo conectado está habilitado, resuelva pacientes y envíe observaciones:

let patient = try await sdk.connected().resolveMonitored(externalId: "patient-ext-id")

try await sdk.connected().postObservation(
monitoredId: patient.id,
observation: BaseObservation(
observationType: "blood-pressure",
issued: ISO8601DateFormatter().string(from: Date()),
components: [
ObservationComponent(name: "systolic", value: "120", valueUnit: "mmHg"),
ObservationComponent(name: "diastolic", value: "80", valueUnit: "mmHg"),
]
)
)

Gestión de errores

do {
try await device.connect(timeoutMs: 10_000)
for try await obs in device.collect() {
// process observation
}
} catch let error as SdkError {
switch error {
case is SdkError.ConnectionTimeout:
showError("Connection timed out. Move closer to the device.")
case is SdkError.BluetoothDisabled:
showError("Please enable Bluetooth.")
case is SdkError.BluetoothPermissionDenied:
showError("Bluetooth permissions required.")
default:
showError("Device error: \(error.localizedDescription)")
}
}

HealthKit

Lea de Apple HealthKit (no requiere escaneo BLE):

let descriptor = try await sdk.devices.discover(
filter: DiscoveryFilter(providers: ["apple-healthkit"], capabilities: nil, namePrefix: nil),
timeoutMs: 5_000
).first { _ in true }!

let store = sdk.devices.createDevice(descriptor: descriptor)
try await store.connect()
for try await observation in store.collect() {
// Process HealthKit observations
}
try await store.disconnect()

Liberación de recursos

Llame siempre a close() cuando el SDK ya no sea necesario:

sdk.close()