Skip to main content

Data Synchronization (TSDataSync)

TSDataSync synchronizes daily aggregated and raw health data. Each requested data type reports through a per-type callback, and the final completion returns the aggregate results.

Prerequisites​

  • The device is connected and authenticated.
  • The SDK has been initialized.
  • startTime is earlier than endTime; endTime must not be in the future.
  • Check isSyncing before starting another operation.

Data models​

TSDataSyncConfig​

PropertyTypeDescription
optionsTSDataSyncOptionData types to synchronize; combine flags with bitwise OR
granularityTSDataGranularityRaw or daily aggregated data
startTimeNSTimeIntervalUnix seconds; 0 reads the last sync time from the database
endTimeNSTimeIntervalUnix seconds; 0 uses the current time
includeUserInitiatedBOOLInclude user-initiated measurements; defaults to YES

Initializers are init, initWithOptions:granularity:, and initWithOptions:granularity:startTime:endTime:. Convenience constructors are configForRawDataWithOptions:startTime:endTime:, configForDailyDataWithOptions:startTime:endTime:, and configWithOptions:granularity:startTime:.

TSHealthData​

PropertyTypeDescription
optionTSDataSyncOptionData type represented by this result
healthValuesNSArray<TSHealthValueModel *> *Values in ascending time order; empty when no data exists
fetchErrorNSError *Error for this data type; nil on success, including an empty result

Create TSHealthData with initWithOption:healthValues:fetchError: or its class methods. Use findHealthDataWithOption:fromArray: to locate one type in the final result array.

TSHealthValueType​

Value kinds are TSHealthValueTypeNormal (0), TSHealthValueTypeMax (1), TSHealthValueTypeMin (2), and TSHealthValueTypeResting (3). Resting values apply only to heart-rate data.

Enumerations and options​

TSDataGranularity​

ValueDescription
TSDataGranularityRaw (0)Individual measurements
TSDataGranularityDay (1)Daily aggregated data

TSDataSyncOption​

TSDataSyncOptionNone is 0. The remaining flags are HeartRate, BloodOxygen, BloodPressure, Stress, Sleep, Temperature, ECG, Sport, DailyActivity, and HeartRateVar. Combine them with bitwise OR. TSDataSyncOptionAll combines every flag.

Callback types​

TSDataSyncHealthDataBlock is void (^)(TSHealthData *typeData). It is called once on the main thread when each capability-filtered data type finishes. Per-type failures are reported by typeData.fetchError. Resting heart-rate values are included in the heart-rate result and are identified by valueType == TSHealthValueTypeResting on the value item.

The final completion has this signature:

void (^)(NSArray<TSHealthData *> *_Nullable results, NSError *_Nullable error)

error is reserved for fatal errors that stop synchronization. A data-type failure is reported in that type's TSHealthData.fetchError.

API reference​

Synchronize daily data from the last sync time​

- (void)syncDailyDataFromLastTime:(nullable TSDataSyncHealthDataBlock)onHealthData
completion:(void (^)(NSArray<TSHealthData *> *_Nullable results,
NSError *_Nullable error))completion;

Synchronize raw data from the last sync time​

- (void)syncRawDataFromLastTime:(nullable TSDataSyncHealthDataBlock)onHealthData
completion:(void (^)(NSArray<TSHealthData *> *_Nullable results,
NSError *_Nullable error))completion;

Synchronize using a configuration​

- (void)syncDataWithConfig:(TSDataSyncConfig *)config
onHealthData:(nullable TSDataSyncHealthDataBlock)onHealthData
completion:(void (^)(NSArray<TSHealthData *> *_Nullable results,
NSError *_Nullable error))completion;

Synchronization example​

id<TSDataSyncInterface> syncManager = [TopStepComKit sharedInstance].dataSync;
if ([syncManager isSyncing]) {
TSLog(@"[DataSync] A sync is already running");
return;
}

TSDataSyncConfig *config = [TSDataSyncConfig configForDailyDataWithOptions:
(TSDataSyncOptionHeartRate | TSDataSyncOptionBloodOxygen)
startTime:[[NSDate dateWithTimeIntervalSinceNow:-7 * 24 * 60 * 60] timeIntervalSince1970]
endTime:[[NSDate date] timeIntervalSince1970]];

[syncManager syncDataWithConfig:config
onHealthData:^(TSHealthData *typeData) {
if (typeData.fetchError) {
TSLog(@"[DataSync] Type %ld failed: %@", (long)typeData.option,
typeData.fetchError.localizedDescription);
return;
}
TSLog(@"[DataSync] Type %ld finished with %lu values",
(long)typeData.option, (unsigned long)typeData.healthValues.count);
} completion:^(NSArray<TSHealthData *> *results, NSError *error) {
if (error) {
TSLog(@"[DataSync] Fatal error: %@", error.localizedDescription);
return;
}
TSHealthData *heartRate = [TSHealthData findHealthDataWithOption:
TSDataSyncOptionHeartRate fromArray:results];
TSLog(@"[DataSync] Heart-rate result present: %@", heartRate ? @"YES" : @"NO");
}];

Cancel and check status​

- (void)cancelSync;
- (BOOL)isSyncing;

cancelSync accepts the request and returns immediately. The original completion later reports eTSErrorSyncCancelled. If no sync is active, the call is ignored. Do not start another sync or release the connection until the completion arrives.

Important notes​

  1. All callbacks run on the main thread.
  2. An empty healthValues array means that type has no data in the range; it is not a failure.
  3. Raw synchronization can return much more data than daily synchronization; use smaller time ranges when appropriate.
  4. Set includeUserInitiated to NO to exclude manual measurements.
  5. startTime == 0 uses the database's last sync time; endTime == 0 uses the current time.
  6. Invalid configuration, device-busy, authentication, and fatal network errors are reported through the final completion's error.