Skip to main content

Blood Oxygen Module

The Blood Oxygen module provides comprehensive blood oxygen (SpO2) measurement and monitoring capabilities for wearable devices. It supports manual measurements initiated by users, automatic background monitoring with configurable schedules, and synchronization of raw and daily aggregated blood oxygen data. This module enables developers to integrate SpO2 vital sign tracking into their health and fitness applications.

Prerequisites

  • Device must support blood oxygen measurement (verify with isSupportActivityMeasureByUser and isSupportAutomaticMonitoring)
  • Proper Bluetooth connection to the wearable device must be established
  • For automatic monitoring configuration, the device must support the feature (verify with isSupportAutomaticMonitoring)
  • Time-based parameters use Unix timestamps (seconds since January 1, 1970)

Data Models

TSBOValueItem

Single blood oxygen measurement data point.

PropertyTypeDescription
oxyValueUInt8Blood oxygen value as a percentage (0-100%).
isUserInitiatedBOOLIndicates whether the measurement was initiated by the user (YES) or automatically monitored (NO).

TSBODailyModel

Daily aggregated blood oxygen data for a single day.

PropertyTypeDescription
maxOxygenItemTSBOValueItem *Reference to the TSBOValueItem with the highest SpO2 value recorded during the day.
minOxygenItemTSBOValueItem *Reference to the TSBOValueItem with the lowest SpO2 value recorded during the day.
manualItemsNSArray<TSBOValueItem *> *Array of user-initiated blood oxygen measurements, sorted in ascending time order.
autoItemsNSArray<TSBOValueItem *> *Array of automatically monitored blood oxygen measurements, sorted in ascending time order.

Enumerations

No enumerations are defined in this module.

Callback Types

TSCompletionBlock

typedef void (^TSCompletionBlock)(NSError *_Nullable error);

Generic completion callback for operations.

ParameterTypeDescription
errorNSError *Error information if the operation failed; nil if successful.

Measurement Start Handler

void(^)(BOOL success, NSError *_Nullable error)

Callback invoked when blood oxygen measurement starts or fails to start.

ParameterTypeDescription
successBOOLYES if measurement started successfully; NO otherwise.
errorNSError *Error details if the operation failed; nil if successful.

Measurement Data Handler

void(^)(TSBOValueItem *_Nullable data, NSError *_Nullable error)

Callback invoked to receive real-time blood oxygen measurement data during an ongoing measurement.

ParameterTypeDescription
dataTSBOValueItem *Real-time blood oxygen measurement data; nil if an error occurs.
errorNSError *Error information if data reception fails; nil if successful.

Measurement End Handler

void(^)(BOOL success, NSError *_Nullable error)

Callback invoked when blood oxygen measurement ends, either normally or abnormally.

ParameterTypeDescription
successBOOLYES if measurement ended normally; NO if interrupted or failed.
errorNSError *Error details if the measurement ended abnormally; nil if normal end.

Auto Monitor Config Fetch Handler

void (^)(TSAutoMonitorConfigs *_Nullable configuration, NSError *_Nullable error)

Callback for fetching automatic monitoring configuration.

ParameterTypeDescription
configurationTSAutoMonitorConfigs *Current automatic monitoring configuration; nil if an error occurs.
errorNSError *Error information if the fetch failed; nil if successful.

Raw Data Sync Handler

void (^)(NSArray<TSBOValueItem *> *_Nullable boItems, NSError *_Nullable error)

Callback for raw blood oxygen data synchronization.

ParameterTypeDescription
boItemsNSArray<TSBOValueItem *> *Array of raw blood oxygen measurement items synchronized; nil if an error occurs.
errorNSError *Error information if synchronization failed; nil if successful.

Daily Data Sync Handler

void (^)(NSArray<TSBODailyModel *> *_Nullable dailyModels, NSError *_Nullable error)

Callback for daily aggregated blood oxygen data synchronization.

ParameterTypeDescription
dailyModelsNSArray<TSBODailyModel *> *Array of daily blood oxygen models synchronized; nil if an error occurs.
errorNSError *Error information if synchronization failed; nil if successful.

API Reference

Check manual blood oxygen measurement support

Determine whether the connected device supports user-initiated blood oxygen measurements.

- (BOOL)isSupportActivityMeasureByUser;

Returns: BOOL indicating device capability for manual measurement.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;

if ([boInterface isSupportActivityMeasureByUser]) {
TSLog(@"Device supports manual blood oxygen measurement");
} else {
TSLog(@"Device does not support manual blood oxygen measurement");
}

Start blood oxygen measurement

Begin a blood oxygen measurement session with real-time data streaming.

- (void)startMeasureWithParam:(TSActivityMeasureParam *_Nonnull)measureParam
startHandler:(void(^_Nullable)(BOOL success, NSError * _Nullable error))startHandler
dataHandler:(void(^_Nullable)(TSBOValueItem * _Nullable data, NSError * _Nullable error))dataHandler
endHandler:(void(^_Nullable)(BOOL success, NSError * _Nullable error))endHandler;
ParameterTypeDescription
measureParamTSActivityMeasureParam *Configuration parameters for the measurement activity.
startHandlervoid(^)(BOOL success, NSError *)Callback invoked when measurement starts or fails to start.
dataHandlervoid(^)(TSBOValueItem *, NSError *)Callback to receive real-time measurement data during the measurement.
endHandlervoid(^)(BOOL success, NSError *)Callback invoked when the measurement ends or is interrupted.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;
TSActivityMeasureParam *param = [[TSActivityMeasureParam alloc] init];

[boInterface startMeasureWithParam:param
startHandler:^(BOOL success, NSError * _Nullable error) {
if (success) {
TSLog(@"Blood oxygen measurement started successfully");
} else {
TSLog(@"Failed to start measurement: %@", error.localizedDescription);
}
}
dataHandler:^(TSBOValueItem * _Nullable data, NSError * _Nullable error) {
if (data) {
TSLog(@"Real-time SpO2: %d%%, User-initiated: %@",
data.oxyValue, data.isUserInitiated ? @"YES" : @"NO");
} else if (error) {
TSLog(@"Error receiving data: %@", error.localizedDescription);
}
}
endHandler:^(BOOL success, NSError * _Nullable error) {
if (success) {
TSLog(@"Measurement ended normally");
} else {
TSLog(@"Measurement interrupted: %@", error.localizedDescription);
}
}];

Stop blood oxygen measurement

Terminate the currently active blood oxygen measurement session.

- (void)stopMeasureCompletion:(nonnull TSCompletionBlock)completion;
ParameterTypeDescription
completionTSCompletionBlockCompletion callback invoked when the measurement stops or fails to stop.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;

[boInterface stopMeasureCompletion:^(NSError * _Nullable error) {
if (!error) {
TSLog(@"Blood oxygen measurement stopped successfully");
} else {
TSLog(@"Failed to stop measurement: %@", error.localizedDescription);
}
}];

Check automatic monitoring support

Determine whether the connected device supports automatic blood oxygen monitoring.

- (BOOL)isSupportAutomaticMonitoring;

Returns: BOOL indicating device capability for automatic monitoring.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;

if ([boInterface isSupportAutomaticMonitoring]) {
TSLog(@"Device supports automatic blood oxygen monitoring");
} else {
TSLog(@"Device does not support automatic blood oxygen monitoring");
}

Check monitor schedule time support

Determine whether the device supports configuring specific time ranges for automatic monitoring.

- (BOOL)isSupportMonitorScheduleTime;

Returns: BOOL indicating device support for time range configuration (startTime and endTime fields).

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;

if ([boInterface isSupportMonitorScheduleTime]) {
TSLog(@"Device supports configuring monitor time range");
} else {
TSLog(@"Device does not support time range configuration");
}

Check monitor schedule interval support

Determine whether the device supports configuring the monitoring interval.

- (BOOL)isSupportMonitorScheduleInterval;

Returns: BOOL indicating device support for interval configuration.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;

if ([boInterface isSupportMonitorScheduleInterval]) {
TSLog(@"Device supports configuring monitor interval");
} else {
TSLog(@"Device does not support interval configuration");
}

Configure automatic blood oxygen monitoring

Push automatic monitoring configuration to the device.

- (void)pushAutoMonitorConfigs:(TSAutoMonitorConfigs *_Nonnull)configuration
completion:(nonnull TSCompletionBlock)completion;
ParameterTypeDescription
configurationTSAutoMonitorConfigs *Automatic monitoring configuration parameters (enable/disable, schedule, interval).
completionTSCompletionBlockCompletion callback invoked when the configuration is applied or fails.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;
TSAutoMonitorConfigs *config = [[TSAutoMonitorConfigs alloc] init];
config.isEnabled = YES;
// Configure additional properties as needed

[boInterface pushAutoMonitorConfigs:config
completion:^(NSError * _Nullable error) {
if (!error) {
TSLog(@"Automatic monitoring configuration applied successfully");
} else {
TSLog(@"Failed to apply configuration: %@", error.localizedDescription);
}
}];

Fetch current automatic monitoring configuration

Retrieve the current automatic blood oxygen monitoring settings from the device.

- (void)fetchAutoMonitorConfigsWithCompletion:(nonnull void (^)(TSAutoMonitorConfigs *_Nullable configuration, NSError *_Nullable error))completion;
ParameterTypeDescription
completionvoid(^)(TSAutoMonitorConfigs *, NSError *)Callback returning current configuration or error.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;

[boInterface fetchAutoMonitorConfigsWithCompletion:^(TSAutoMonitorConfigs * _Nullable configuration, NSError * _Nullable error) {
if (configuration) {
TSLog(@"Current monitoring config - Enabled: %@",
configuration.isEnabled ? @"YES" : @"NO");
} else if (error) {
TSLog(@"Failed to fetch configuration: %@", error.localizedDescription);
}
}];

Synchronize raw blood oxygen data (time range)

Retrieve all raw blood oxygen measurement data points within a specified time range.

- (void)syncRawDataFromStartTime:(NSTimeInterval)startTime
endTime:(NSTimeInterval)endTime
completion:(nonnull void (^)(NSArray<TSBOValueItem *> *_Nullable boItems, NSError *_Nullable error))completion;
ParameterTypeDescription
startTimeNSTimeIntervalStart time (Unix timestamp in seconds) for data retrieval.
endTimeNSTimeIntervalEnd time (Unix timestamp in seconds) for data retrieval.
completionvoid(^)(NSArray<TSBOValueItem *> *, NSError *)Callback with raw blood oxygen items or error.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;

NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:-86400]; // 24 hours ago
NSDate *endDate = [NSDate date];

[boInterface syncRawDataFromStartTime:startDate.timeIntervalSince1970
endTime:endDate.timeIntervalSince1970
completion:^(NSArray<TSBOValueItem *> * _Nullable boItems, NSError * _Nullable error) {
if (boItems) {
TSLog(@"Synchronized %lu raw blood oxygen measurements", (unsigned long)boItems.count);
for (TSBOValueItem *item in boItems) {
TSLog(@"SpO2: %d%% at %f, User-initiated: %@",
item.oxyValue, item.timestamp, item.isUserInitiated ? @"YES" : @"NO");
}
} else if (error) {
TSLog(@"Failed to sync raw data: %@", error.localizedDescription);
}
}];

Synchronize raw blood oxygen data (from start time)

Retrieve all raw blood oxygen measurement data points from a specified start time until now.

- (void)syncRawDataFromStartTime:(NSTimeInterval)startTime
completion:(nonnull void (^)(NSArray<TSBOValueItem *> *_Nullable boItems, NSError *_Nullable error))completion;
ParameterTypeDescription
startTimeNSTimeIntervalStart time (Unix timestamp in seconds) for data retrieval. Synchronizes from this time to the current time.
completionvoid(^)(NSArray<TSBOValueItem *> *, NSError *)Callback with raw blood oxygen items or error.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;

NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:-604800]; // 7 days ago

[boInterface syncRawDataFromStartTime:startDate.timeIntervalSince1970
completion:^(NSArray<TSBOValueItem *> * _Nullable boItems, NSError * _Nullable error) {
if (boItems) {
TSLog(@"Synchronized %lu raw blood oxygen measurements from 7 days ago",
(unsigned long)boItems.count);
} else if (error) {
TSLog(@"Failed to sync raw data: %@", error.localizedDescription);
}
}];

Synchronize daily blood oxygen data (time range)

Retrieve daily aggregated blood oxygen data within a specified time range.

- (void)syncDailyDataFromStartTime:(NSTimeInterval)startTime
endTime:(NSTimeInterval)endTime
completion:(nonnull void (^)(NSArray<TSBODailyModel *> *_Nullable dailyModels, NSError *_Nullable error))completion;
ParameterTypeDescription
startTimeNSTimeIntervalStart time (Unix timestamp in seconds). Automatically normalized to 00:00:00 of the specified day.
endTimeNSTimeIntervalEnd time (Unix timestamp in seconds). Automatically normalized to 23:59:59 of the specified day. Must be after startTime and not in the future.
completionvoid(^)(NSArray<TSBODailyModel *> *, NSError *)Callback with daily aggregated blood oxygen models or error.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;

NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:-604800]; // 7 days ago
NSDate *endDate = [NSDate date];

[boInterface syncDailyDataFromStartTime:startDate.timeIntervalSince1970
endTime:endDate.timeIntervalSince1970
completion:^(NSArray<TSBODailyModel *> * _Nullable dailyModels, NSError * _Nullable error) {
if (dailyModels) {
TSLog(@"Synchronized %lu days of blood oxygen data", (unsigned long)dailyModels.count);
for (TSBODailyModel *daily in dailyModels) {
TSLog(@"Day - Max: %d%%, Min: %d%%, Manual: %lu, Auto: %lu",
[daily maxOxygenValue], [daily minOxygenValue],
(unsigned long)daily.manualItems.count,
(unsigned long)daily.autoItems.count);
}
} else if (error) {
TSLog(@"Failed to sync daily data: %@", error.localizedDescription);
}
}];

Synchronize daily blood oxygen data (from start time)

Retrieve daily aggregated blood oxygen data from a specified start time until now.

- (void)syncDailyDataFromStartTime:(NSTimeInterval)startTime
completion:(nonnull void (^)(NSArray<TSBODailyModel *> *_Nullable dailyModels, NSError *_Nullable error))completion;
ParameterTypeDescription
startTimeNSTimeIntervalStart time (Unix timestamp in seconds). Automatically normalized to 00:00:00 of the specified day. Synchronizes from this time to the current time.
completionvoid(^)(NSArray<TSBODailyModel *> *, NSError *)Callback with daily aggregated blood oxygen models or error.

Code Example:

id<TSBloodOxygenInterface> boInterface = /* obtained from health manager */;

NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:-2592000]; // 30 days ago

[boInterface syncDailyDataFromStartTime:startDate.timeIntervalSince1970
completion:^(NSArray<TSBODailyModel *> * _Nullable dailyModels, NSError * _Nullable error) {
if (dailyModels) {
TSLog(@"Synchronized %lu days of daily blood oxygen aggregates",
(unsigned long)dailyModels.count);
for (TSBODailyModel *daily in dailyModels) {
NSArray<TSBOValueItem *> *allItems = [daily allMeasuredItems];
TSLog(@"Day aggregate - Total samples: %lu, Max: %d%%, Min: %d%%",
(unsigned long)allItems.count,
[daily maxOxygenValue],
[daily minOxygenValue]);
}
} else if (error) {
TSLog(@"Failed to sync daily data: %@", error.localizedDescription);
}
}];

Important Notes

  1. **Device Capability Verification**: Always verify device capabilities using the isSupportXXX methods before attempting to use features. Not all devices support manual measurement, automatic monitoring, or schedule configuration.

  2. **Time Parameters**: All time-based API parameters use Unix timestamps (seconds since January 1, 1970). Use NSDate.timeIntervalSince1970 to convert dates to timestamps.

  3. **Daily Data Normalization**: When calling daily data synchronization methods, time parameters are automatically normalized to day boundaries (00:00:00 to 23:59:59). The startTime must be earlier than endTime, and endTime must not be in the future.

  4. **Real-time Data Streaming**: The data handler callback during measurement may be called multiple times with updated real-time measurements. Ensure the handler is thread-safe and does not block the main thread.

  5. **Measurement Session Management**: Only one active measurement session can run at a time. Call stopMeasure before starting a new measurement to ensure proper resource cleanup.

  6. **Automatic Monitoring Schedule**: Use isSupportMonitorScheduleTime and isSupportMonitorScheduleInterval to determine which schedule fields are supported before configuring automatic monitoring.

  7. **Data Ordering**: All data arrays are sorted in ascending time order (oldest to newest). Manual and auto items are maintained separately in daily models; use allMeasuredItems to retrieve a combined, time-sorted array.

  8. **Callback Thread**: Completion handlers are called on the main thread. Avoid performing long-running operations directly in callbacks.

  9. **Error Handling**: Always check both the return values and error parameters in callbacks. A nil data/model combined with a non-nil error indicates a failure.

  10. **SpO2 Value Range**: Blood oxygen values are represented as UInt8 percentages (0–100%). Values outside the typical physiological range (typically 94–100% for healthy individuals at sea level) may indicate measurement issues or health concerns.