Skip to main content

Sleep

The TSSleep module provides comprehensive sleep data management and analysis capabilities for TopStepComKit iOS SDK. It enables synchronization of detailed sleep data from wearable devices, including night sleep, daytime naps, and sleep stage information (Awake, Light, Deep, and REM stages). The module offers both raw sleep segment data for fine-grained analysis and daily aggregated sleep summaries with customizable statistics rules.

Prerequisites

  • TopStepComKit iOS SDK initialized and connected to a compatible wearable device
  • Device must support sleep monitoring functionality
  • Proper permissions granted for health data access
  • Valid time intervals provided in Unix timestamp (seconds) format

Data Models

TSSleepDetailItem

Represents a single sleep stage segment with stage type, timing, and belonging date information.

PropertyTypeDescription
stageTSSleepStageSleep stage type (Awake/Light/Deep/REM)
belongingDateNSTimeIntervalUnix timestamp of 00:00:00 of the day this sleep belongs to. Sleep data uses 20:00 as day boundary [20:00→20:00)
startTimeNSTimeIntervalUnix timestamp of segment start time (inherited from TSHealthValueItem)
durationNSTimeIntervalDuration of this sleep stage segment in seconds (inherited from TSHealthValueItem)

TSSleepSummary

Statistical summary of sleep data including durations, percentages, and quality metrics.

PropertyTypeDescription
startTimeNSTimeIntervalUnix timestamp of sleep start time
endTimeNSTimeIntervalUnix timestamp of sleep end time
durationNSTimeIntervalTotal duration from start to end time in seconds
totalSleepDurationNSTimeIntervalTotal effective sleep time excluding awake periods (seconds)
qualityScoreUInt8Sleep quality score (0-100) based on duration, deep sleep percentage, and awakenings
awakeDurationNSTimeIntervalTotal awake duration during sleep period (seconds)
lightSleepDurationNSTimeIntervalTotal light sleep duration (seconds)
deepSleepDurationNSTimeIntervalTotal deep sleep duration (seconds)
remDurationNSTimeIntervalTotal REM sleep duration (seconds)
awakePercentageUInt8Awake time percentage relative to total sleep duration (0-100)
lightSleepPercentageUInt8Light sleep percentage relative to total sleep duration (0-100)
deepSleepPercentageUInt8Deep sleep percentage relative to total sleep duration (0-100)
remPercentageUInt8REM sleep percentage relative to total sleep duration (0-100)
awakeCountUInt16Number of awake episodes
lightSleepCountUInt16Number of light sleep episodes
deepSleepCountUInt16Number of deep sleep episodes
remCountUInt16Number of REM episodes

TSSleepSegment

Represents a continuous sleep segment with period type, summary statistics, and detailed stage items.

PropertyTypeDescription
periodTypeTSSleepPeriodTypeSleep period type (Night or Daytime)
summaryTSSleepSummary *Statistical summary of this sleep segment
detailItemsNSArray<TSSleepDetailItem *> *Detailed sleep stage items in chronological order

TSSleepDailyModel

Daily sleep data model representing one sleep calendar day with segments and raw items.

PropertyTypeDescription
statisticsRuleTSSleepStatisticsRuleStatistics rule used for this sleep record
dailySummaryTSSleepSummary *Overall daily sleep summary after processing
rawSleepItemsNSArray<TSSleepDetailItem *> *Array of raw sleep detail items synced from device before processing
nightSleepsNSArray<TSSleepSegment *> *One or more continuous night-sleep segments for this day
daytimeSleepsNSArray<TSSleepSegment *> *All daytime sleep segments classified for this day

Enumerations

TSSleepStage

Defines different stages of sleep according to AASM standards.

ValueDescription
TSSleepStageAwakeSubject is awake during sleep period
TSSleepStageLightLight sleep phase (N1 and N2 stages)
TSSleepStageDeepDeep sleep phase (N3 stage, slow-wave sleep)
TSSleepStageREMRapid Eye Movement sleep phase (dream sleep)

TSSleepPeriodType

Defines the period of sleep based on data header time.

ValueDescription
TSSleepPeriodTypeNightNight sleep period (20:00-09:00)
TSSleepPeriodTypeDaytimeDaytime sleep period (09:00-20:00)

TSSleepStatisticsRule

Sleep statistics rule type determining how sleep data is processed and categorized.

ValueDescription
TSSleepStatisticsRuleWithoutNapBasic rule without nap support: sensor active 20:00-12:00, all sleep treated as night sleep
TSSleepStatisticsRuleWithNapWith nap support: sensor active 24h, distinguishes night/day sleep
TSSleepStatisticsRuleLongestNightUses longest continuous night sleep segment (20:00-08:00), valid naps counted
TSSleepStatisticsRuleLongestOnlyNo distinction between night/day, uses longest continuous sleep segment only

Callback Types

Raw Data Completion

void (^)(NSArray<TSSleepDetailItem *> *_Nullable sleepItems, NSError *_Nullable error)

Callback for raw sleep segment data synchronization.

ParameterTypeDescription
sleepItemsNSArray<TSSleepDetailItem *> *Array of raw sleep detail items, or nil if error occurred
errorNSError *Error information if synchronization failed, nil on success

Daily Data Completion

void (^)(NSArray<TSSleepDailyModel *> *_Nullable sleepModel, NSError *_Nullable error)

Callback for daily aggregated sleep data synchronization.

ParameterTypeDescription
sleepModelNSArray<TSSleepDailyModel *> *Array of daily sleep models, or nil if error occurred
errorNSError *Error information if synchronization failed, nil on success

API Reference

Check REM Sleep Support

Determine if the device supports REM sleep stage detection and recording.

- (BOOL)isSupportREMSleep;

**Parameters**

None

**Return Value**

TypeDescription
BOOLYES if device supports REM sleep stage detection, NO otherwise

**Code Example**

id<TSSleepInterface> sleepInterface = /* obtained from kit */;

BOOL supportsREM = [sleepInterface isSupportREMSleep];
if (supportsREM) {
TSLog(@"Device supports REM sleep detection");
} else {
TSLog(@"Device does not support REM sleep detection");
}

Synchronize Raw Sleep Segments From Start Time

Synchronize raw sleep segments starting from a specified time point.

- (void)syncRawDataFromStartTime:(NSTimeInterval)startTime
completion:(nonnull void (^)(NSArray<TSSleepDetailItem *> *_Nullable sleepItems, NSError *_Nullable error))completion;

**Parameters**

NameTypeDescription
startTimeNSTimeIntervalUnix timestamp (seconds) of the starting point
completionvoid (^)(NSArray<TSSleepDetailItem *> *, NSError *)Callback block returning sleep items array or error

**Code Example**

id<TSSleepInterface> sleepInterface = /* obtained from kit */;

// Create a start time: 30 days ago
NSTimeInterval startTime = [[NSDate dateWithTimeIntervalSinceNow:-30*24*60*60] timeIntervalSince1970];

[sleepInterface syncRawDataFromStartTime:startTime
completion:^(NSArray<TSSleepDetailItem *> *sleepItems, NSError *error) {
if (error) {
TSLog(@"Failed to sync raw sleep data: %@", error.localizedDescription);
return;
}

TSLog(@"Successfully synced %lu raw sleep items", (unsigned long)sleepItems.count);
for (TSSleepDetailItem *item in sleepItems) {
NSString *stageName = @[@"Awake", @"Light", @"Deep", @"REM"][item.stage];
TSLog(@"Sleep stage: %@, Duration: %.0f seconds", stageName, item.duration);
}
}];

Synchronize Raw Sleep Segments Within Time Range

Synchronize raw sleep segments within a specified time range.

- (void)syncRawDataFromStartTime:(NSTimeInterval)startTime
endTime:(NSTimeInterval)endTime
completion:(nonnull void (^)(NSArray<TSSleepDetailItem *> *_Nullable sleepItems, NSError *_Nullable error))completion;

**Parameters**

NameTypeDescription
startTimeNSTimeIntervalUnix timestamp (seconds) of range start (inclusive)
endTimeNSTimeIntervalUnix timestamp (seconds) of range end (exclusive). Range is [startTime, endTime)
completionvoid (^)(NSArray<TSSleepDetailItem *> *, NSError *)Callback block returning sleep items array or error

**Code Example**

id<TSSleepInterface> sleepInterface = /* obtained from kit */;

// Get sleep data for the last 7 days
NSTimeInterval endTime = [[NSDate date] timeIntervalSince1970];
NSTimeInterval startTime = endTime - (7 * 24 * 60 * 60);

[sleepInterface syncRawDataFromStartTime:startTime
endTime:endTime
completion:^(NSArray<TSSleepDetailItem *> *sleepItems, NSError *error) {
if (error) {
TSLog(@"Failed to sync raw sleep data: %@", error.localizedDescription);
return;
}

NSTimeInterval totalSleep = 0;
for (TSSleepDetailItem *item in sleepItems) {
if (item.stage != TSSleepStageAwake) {
totalSleep += item.duration;
}
}

TSLog(@"Total sleep in last 7 days: %.0f hours", totalSleep / 3600);
}];

Synchronize Daily Aggregated Sleep Data From Start Time

Synchronize daily aggregated sleep summaries starting from a specified date.

- (void)syncDailyDataFromStartTime:(NSTimeInterval)startTime
completion:(nonnull void (^)(NSArray<TSSleepDailyModel *> *_Nullable sleepModel, NSError *_Nullable error))completion;

**Parameters**

NameTypeDescription
startTimeNSTimeIntervalUnix timestamp (seconds) of the starting day
completionvoid (^)(NSArray<TSSleepDailyModel *> *, NSError *)Callback block returning daily sleep models array or error

**Code Example**

id<TSSleepInterface> sleepInterface = /* obtained from kit */;

// Get daily sleep data from 60 days ago
NSTimeInterval startTime = [[NSDate dateWithTimeIntervalSinceNow:-60*24*60*60] timeIntervalSince1970];

[sleepInterface syncDailyDataFromStartTime:startTime
completion:^(NSArray<TSSleepDailyModel *> *sleepModels, NSError *error) {
if (error) {
TSLog(@"Failed to sync daily sleep data: %@", error.localizedDescription);
return;
}

for (TSSleepDailyModel *model in sleepModels) {
TSSleepSummary *summary = model.dailySummary;
TSLog(@"Date: %@, Total Sleep: %.0f hours, Quality: %u, Deep Sleep: %u%%",
[NSDate dateWithTimeIntervalSince1970:model.startTime],
summary.totalSleepDuration / 3600,
summary.qualityScore,
summary.deepSleepPercentage);
}
}];

Synchronize Daily Aggregated Sleep Data Within Time Range

Synchronize daily aggregated sleep summaries within a specified date range.

- (void)syncDailyDataFromStartTime:(NSTimeInterval)startTime
endTime:(NSTimeInterval)endTime
completion:(nonnull void (^)(NSArray<TSSleepDailyModel *> *_Nullable sleepModel, NSError *_Nullable error))completion;

**Parameters**

NameTypeDescription
startTimeNSTimeIntervalUnix timestamp (seconds) of range start day (inclusive)
endTimeNSTimeIntervalUnix timestamp (seconds) of range end day (exclusive). Range is [startTime, endTime)
completionvoid (^)(NSArray<TSSleepDailyModel *> *, NSError *)Callback block returning daily sleep models array or error

**Code Example**

id<TSSleepInterface> sleepInterface = /* obtained from kit */;

// Get sleep data for a specific month
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *now = [NSDate date];
NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth
fromDate:now];
components.day = 1;
NSDate *monthStart = [calendar dateFromComponents:components];

NSDateComponents *nextMonthComponents = [NSDateComponents new];
nextMonthComponents.month = 1;
NSDate *monthEnd = [calendar dateByAddingComponents:nextMonthComponents toDate:monthStart options:0];

NSTimeInterval startTime = [monthStart timeIntervalSince1970];
NSTimeInterval endTime = [monthEnd timeIntervalSince1970];

[sleepInterface syncDailyDataFromStartTime:startTime
endTime:endTime
completion:^(NSArray<TSSleepDailyModel *> *sleepModels, NSError *error) {
if (error) {
TSLog(@"Failed to sync daily sleep data: %@", error.localizedDescription);
return;
}

NSUInteger goodSleepDays = 0;
for (TSSleepDailyModel *model in sleepModels) {
if (model.dailySummary.qualityScore >= 80) {
goodSleepDays++;
}
}

TSLog(@"Days with good sleep (score >= 80): %lu out of %lu",
(unsigned long)goodSleepDays,
(unsigned long)sleepModels.count);
}];

Process Raw Sleep Items Into Daily Models

Process raw sleep detail items into per-day models using a specified statistics rule.

+ (nullable NSArray<TSSleepDailyModel *> *)processWithStatisticsRule:(TSSleepStatisticsRule)statisticsRule
rawItems:(NSArray<TSSleepDetailItem *> *)rawItems;

**Parameters**

NameTypeDescription
statisticsRuleTSSleepStatisticsRuleStatistics rule to use for processing (WithoutNap, WithNap, LongestNight, or LongestOnly)
rawItemsNSArray<TSSleepDetailItem *> *Array of raw sleep detail items from device/sync

**Return Value**

TypeDescription
NSArray<TSSleepDailyModel *> *Array of processed daily sleep models sorted by sleep day, or nil if no input data

**Code Example**

// Assuming rawSleepItems is obtained from previous sync
NSArray<TSSleepDetailItem *> *rawItems = /* obtained from sync */;

// Process using WithNap rule
NSArray<TSSleepDailyModel *> *dailyModels = [TSSleepDailyModel processWithStatisticsRule:TSSleepStatisticsRuleWithNap
rawItems:rawItems];

if (dailyModels) {
for (TSSleepDailyModel *model in dailyModels) {
TSLog(@"Night sleep segments: %lu", (unsigned long)model.nightSleeps.count);
TSLog(@"Daytime sleep segments: %lu", (unsigned long)model.daytimeSleeps.count);
TSLog(@"Valid naps: %lu", (unsigned long)model.validNaps.count);
}
}

Get Valid Daytime Naps

Filter daytime sleep segments by valid nap duration criteria.

- (NSArray<TSSleepSegment *> *)validNaps;

**Parameters**

None

**Return Value**

TypeDescription
NSArray<TSSleepSegment *> *Subset of daytime segments where duration is greater than 20 minutes and less than or equal to 3 hours; empty array if none match

**Code Example**

TSSleepDailyModel *dailyModel = /* obtained from sync or processing */;

NSArray<TSSleepSegment *> *validNaps = [dailyModel validNaps];
if (validNaps.count > 0) {
for (TSSleepSegment *nap in validNaps) {
NSUInteger napDurationMinutes = nap.summary.totalSleepDuration / 60;
TSLog(@"Valid nap duration: %lu minutes", (unsigned long)napDurationMinutes);
}
}

Get Debug Description

Generate a human-readable multi-line description of daily sleep data for debugging.

- (NSString *)debugDescription;

**Parameters**

None

**Return Value**

TypeDescription
NSString *String summarizing date, rule, raw count, summary metrics, and segment counts

**Code Example**

TSSleepDailyModel *dailyModel = /* obtained from sync or processing */;

TSLog(@"%@", [dailyModel debugDescription]);

Important Notes

  1. **Sleep Day Boundary**: Sleep data uses 20:00 (8 PM) as the day boundary instead of midnight. A sleep session starting at 21:00 on November 19 belongs to November 20, and a session at 08:00 on November 20 also belongs to November 20. The day boundary resets at 20:00 ([20:00→20:00) range).

  2. **Time Interval Format**: All time parameters and return values use Unix timestamps in seconds (NSTimeInterval). Use [NSDate timeIntervalSince1970] for current time or [NSDate dateWithTimeIntervalSince1970:] for conversion.

  3. **Statistics Rules**: Choose the appropriate TSSleepStatisticsRule based on device capabilities. Different devices support different rules (WithoutNap, WithNap, LongestNight, or LongestOnly), affecting how naps and multiple sleep segments are processed.

  4. **Valid Nap Duration**: A daytime sleep segment is considered a valid nap if its total sleep duration is greater than 20 minutes and less than or equal to 3 hours. Segments outside this range are still included in daytimeSleeps but excluded from validNaps.

  5. **REM Support Verification**: Always check isSupportREMSleep before assuming REM stage data is available. Not all devices support REM detection, and TSSleepDetailItem data may not include REM stage segments if unsupported.

  6. **Raw vs Aggregated Data**: Use syncRawDataFromStartTime:completion: for fine-grained timeline analysis and custom calculations. Use syncDailyDataFromStartTime:completion: for summary-level reporting and simplified access to daily statistics.

  7. **Segment Classification**: Night sleep is determined by the statistics rule's time window (typically 20:00-09:00 or 20:00-12:00). Sleep sessions outside this window are classified as daytime sleep regardless of their actual clock time if nap support is enabled.

  8. **Data Processing**: Raw items from sync may include awake segments and fragmented data. Use the processing methods to automatically group items by day, merge segments, and apply the selected statistics strategy.

  9. **Chronological Order**: All returned arrays maintain chronological order for sleep items within segments and chronological ordering by sleep day for daily models, facilitating timeline visualization.

  10. **Null Safety**: Completion callbacks may receive nil for the data parameter if an error occurs. Always check both the returned data and error parameters before processing results.