|
...
|
...
|
@@ -243,11 +243,17 @@ class OHOSHealthRawDataCoreService { |
|
|
|
throw ArgumentError.value(endTime, 'endTime');
|
|
|
|
}
|
|
|
|
final hasAuthorization = await _hasHealthReadAuthorizationSafely();
|
|
|
|
final willSyncRawData =
|
|
|
|
hasAuthorization && _rawDataSource is OhosHealthRawDataSource;
|
|
|
|
final syncStartTime = willSyncRawData ? DateTime.now() : null;
|
|
|
|
final syncResults = await _syncCalculationRawDataSafely(
|
|
|
|
hasAuthorization: hasAuthorization,
|
|
|
|
startTime: forceStartTime,
|
|
|
|
endTime: effectiveEndTime,
|
|
|
|
);
|
|
|
|
final syncElapsed = syncStartTime == null
|
|
|
|
? Duration.zero
|
|
|
|
: DateTime.now().difference(syncStartTime);
|
|
|
|
final syncedRawStartTime = _earliestStoredTime(syncResults);
|
|
|
|
_logInfo(
|
|
|
|
'calculate_sync_finish startTime=$requestedStartTime '
|
|
...
|
...
|
@@ -255,6 +261,7 @@ class OHOSHealthRawDataCoreService { |
|
|
|
'syncResults=$syncResults',
|
|
|
|
);
|
|
|
|
|
|
|
|
final calculationStartTime = DateTime.now();
|
|
|
|
final storedResult = await _calculateAndStoreSafely(
|
|
|
|
userId: userId,
|
|
|
|
requestedStartTime: requestedStartTime,
|
|
...
|
...
|
@@ -263,12 +270,17 @@ class OHOSHealthRawDataCoreService { |
|
|
|
syncedRawStartTime: syncedRawStartTime,
|
|
|
|
readChunkDays: readChunkDays,
|
|
|
|
);
|
|
|
|
final calculationElapsed = DateTime.now().difference(calculationStartTime);
|
|
|
|
_scheduleResultUpload();
|
|
|
|
await _sendLocalNotificationsAfterCalculationSafely(
|
|
|
|
result: storedResult.result,
|
|
|
|
hasExistingHrv: storedResult.hasExistingHrv,
|
|
|
|
hasExistingSleep: storedResult.hasExistingSleep,
|
|
|
|
);
|
|
|
|
_showDebugTimingToast(
|
|
|
|
syncElapsed: syncElapsed,
|
|
|
|
calculationElapsed: calculationElapsed,
|
|
|
|
);
|
|
|
|
return storedResult.result;
|
|
|
|
}
|
|
|
|
|
|
...
|
...
|
@@ -293,6 +305,15 @@ class OHOSHealthRawDataCoreService { |
|
|
|
final latestSleepResultTime = await _localStore.latestSleepResultTime(
|
|
|
|
userId,
|
|
|
|
);
|
|
|
|
final latestRawHrvDataTime = await _latestOhosRawDataTime(
|
|
|
|
HealthDataUploadType.hrv.type,
|
|
|
|
);
|
|
|
|
final latestRawHrDataTime = await _latestOhosRawDataTime(
|
|
|
|
HealthDataUploadType.heartRate.type,
|
|
|
|
);
|
|
|
|
final latestRawSleepDataTime = await _latestOhosRawDataTime(
|
|
|
|
OhosHealthRawDataType.sleepAnalysis,
|
|
|
|
);
|
|
|
|
hasExistingHrv = latestHrvRawEndTime != null;
|
|
|
|
hasExistingSleep = latestSleepResultTime != null;
|
|
|
|
|
|
...
|
...
|
@@ -301,13 +322,30 @@ class OHOSHealthRawDataCoreService { |
|
|
|
requestedStartTime,
|
|
|
|
earliestStartTime,
|
|
|
|
);
|
|
|
|
final hrvRawAnchorStart = _rawBackfillStartTime(latestRawHrvDataTime);
|
|
|
|
final realtimeRawAnchorStart = _rawBackfillStartTime(
|
|
|
|
latestRawHrDataTime,
|
|
|
|
);
|
|
|
|
final sleepRawAnchorStart = _rawBackfillStartTime(
|
|
|
|
latestRawSleepDataTime,
|
|
|
|
);
|
|
|
|
final hrvStartTime = math.max(
|
|
|
|
_minNullable(hrvContextStart, calculationStartTime) ??
|
|
|
|
_minNullableValues([
|
|
|
|
hrvContextStart,
|
|
|
|
hrvRawAnchorStart,
|
|
|
|
syncedRawStartTime,
|
|
|
|
requestedStartTime,
|
|
|
|
]) ??
|
|
|
|
calculationStartTime,
|
|
|
|
earliestStartTime,
|
|
|
|
);
|
|
|
|
final realtimeStartTime = math.max(
|
|
|
|
_minNullable(realtimeContextStart, calculationStartTime) ??
|
|
|
|
_minNullableValues([
|
|
|
|
realtimeContextStart,
|
|
|
|
realtimeRawAnchorStart,
|
|
|
|
syncedRawStartTime,
|
|
|
|
requestedStartTime,
|
|
|
|
]) ??
|
|
|
|
calculationStartTime,
|
|
|
|
earliestStartTime,
|
|
|
|
);
|
|
...
|
...
|
@@ -319,7 +357,21 @@ class OHOSHealthRawDataCoreService { |
|
|
|
? calculationStartTime
|
|
|
|
: latestSleepResultTime - Duration.secondsPerDay;
|
|
|
|
final sleepStartTime = math.max(
|
|
|
|
_minNullable(sleepAnchorTime, syncedRawStartTime) ?? sleepAnchorTime,
|
|
|
|
_minNullableValues([
|
|
|
|
sleepAnchorTime,
|
|
|
|
sleepRawAnchorStart,
|
|
|
|
syncedRawStartTime,
|
|
|
|
requestedStartTime,
|
|
|
|
]) ??
|
|
|
|
sleepAnchorTime,
|
|
|
|
earliestStartTime,
|
|
|
|
);
|
|
|
|
final hrvRecomputeStartTime = _boundedNullableStartTime(
|
|
|
|
_minNullable(syncedRawStartTime, hrvRawAnchorStart),
|
|
|
|
earliestStartTime,
|
|
|
|
);
|
|
|
|
final realtimeRecomputeStartTime = _boundedNullableStartTime(
|
|
|
|
_minNullable(syncedRawStartTime, realtimeRawAnchorStart),
|
|
|
|
earliestStartTime,
|
|
|
|
);
|
|
|
|
_logInfo(
|
|
...
|
...
|
@@ -331,8 +383,18 @@ class OHOSHealthRawDataCoreService { |
|
|
|
'latestHrvRawEndTime=$latestHrvRawEndTime '
|
|
|
|
'latestRealtimeRawEndTime=$latestRealtimeRawEndTime '
|
|
|
|
'latestSleepResultTime=$latestSleepResultTime '
|
|
|
|
'hrvStartTime=$hrvStartTime heartRateStartTime=$heartRateStartTime '
|
|
|
|
'sleepStartTime=$sleepStartTime',
|
|
|
|
'latestRawHrvDataTime=$latestRawHrvDataTime '
|
|
|
|
'latestRawHrDataTime=$latestRawHrDataTime '
|
|
|
|
'latestRawSleepDataTime=$latestRawSleepDataTime '
|
|
|
|
'hrvRawAnchorStart=$hrvRawAnchorStart '
|
|
|
|
'realtimeRawAnchorStart=$realtimeRawAnchorStart '
|
|
|
|
'sleepRawAnchorStart=$sleepRawAnchorStart '
|
|
|
|
'hrvStartTime=$hrvStartTime '
|
|
|
|
'realtimeStartTime=$realtimeStartTime '
|
|
|
|
'heartRateStartTime=$heartRateStartTime '
|
|
|
|
'sleepStartTime=$sleepStartTime '
|
|
|
|
'hrvRecomputeStartTime=$hrvRecomputeStartTime '
|
|
|
|
'realtimeRecomputeStartTime=$realtimeRecomputeStartTime',
|
|
|
|
);
|
|
|
|
|
|
|
|
final hrvPoints = await _fetchRawDataInChunks(
|
|
...
|
...
|
@@ -402,12 +464,12 @@ class OHOSHealthRawDataCoreService { |
|
|
|
hrvStressPoints: _filterNewHrvStressPoints(
|
|
|
|
result.hrvStressPoints,
|
|
|
|
latestHrvRawEndTime,
|
|
|
|
recomputeStartTime: syncedRawStartTime,
|
|
|
|
recomputeStartTime: hrvRecomputeStartTime,
|
|
|
|
),
|
|
|
|
realtimeStressPoints: _filterNewRealtimeStressPoints(
|
|
|
|
result.realtimeStressPoints,
|
|
|
|
latestRealtimeRawEndTime,
|
|
|
|
recomputeStartTime: syncedRawStartTime,
|
|
|
|
recomputeStartTime: realtimeRecomputeStartTime,
|
|
|
|
),
|
|
|
|
);
|
|
|
|
_logInfo(
|
|
...
|
...
|
@@ -947,6 +1009,30 @@ class OHOSHealthRawDataCoreService { |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<int?> _latestOhosRawDataTime(int dataType) async {
|
|
|
|
final rawDataSource = _rawDataSource;
|
|
|
|
if (rawDataSource is! OhosHealthRawDataSource) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return rawDataSource.latestDataTime(dataType: dataType);
|
|
|
|
}
|
|
|
|
|
|
|
|
int? _rawBackfillStartTime(int? latestDataTime) {
|
|
|
|
if (latestDataTime == null) return null;
|
|
|
|
final backfillTime = math.max(
|
|
|
|
0,
|
|
|
|
latestDataTime -
|
|
|
|
OhosHealthRawDataSyncService.incrementalBackfillDays *
|
|
|
|
Duration.secondsPerDay,
|
|
|
|
);
|
|
|
|
return _localDay(backfillTime).millisecondsSinceEpoch ~/ 1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
int? _boundedNullableStartTime(int? startTime, int earliestStartTime) {
|
|
|
|
if (startTime == null) return null;
|
|
|
|
return math.max(startTime, earliestStartTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<bool> _hasHealthReadAuthorizationSafely() async {
|
|
|
|
try {
|
|
|
|
return await _hasHealthReadAuthorization();
|
|
...
|
...
|
@@ -1258,6 +1344,30 @@ class OHOSHealthRawDataCoreService { |
|
|
|
return math.min(a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int? _minNullableValues(Iterable<int?> values) {
|
|
|
|
int? minValue;
|
|
|
|
for (final value in values) {
|
|
|
|
if (value == null) continue;
|
|
|
|
minValue = minValue == null ? value : math.min(minValue, value);
|
|
|
|
}
|
|
|
|
return minValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _showDebugTimingToast({
|
|
|
|
required Duration syncElapsed,
|
|
|
|
required Duration calculationElapsed,
|
|
|
|
}) {
|
|
|
|
if (!_isDebug) return;
|
|
|
|
_toastSink?.call(
|
|
|
|
'【测试】本轮同步耗时${_elapsedSecondsText(syncElapsed)} s、'
|
|
|
|
'计算耗时${_elapsedSecondsText(calculationElapsed)} s',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
String _elapsedSecondsText(Duration elapsed) {
|
|
|
|
return (elapsed.inMilliseconds / 1000).toStringAsFixed(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int _dateKeyFromUnixSeconds(int seconds) {
|
|
|
|
final date = DateTime.fromMillisecondsSinceEpoch(seconds * 1000);
|
|
|
|
return _dateKeyFromDateTime(date);
|
...
|
...
|
|