|
|
@ -1,18 +1,31 @@ |
|
|
|
package com.whitefish.ring.data |
|
|
|
|
|
|
|
import com.whitefish.app.ui.chart.sleep.SleepSegment |
|
|
|
import com.whitefish.ring.DeviceManager |
|
|
|
import com.whitefish.ring.bean.ui.HeartRate |
|
|
|
import com.whitefish.ring.bean.ui.SleepState |
|
|
|
import com.whitefish.ring.objc.DBHeartRate |
|
|
|
import com.whitefish.ring.objc.DBSleepData |
|
|
|
import com.whitefish.ring.objc.StagingListObj |
|
|
|
import com.whitefish.ring.objc.StagingSubObj |
|
|
|
import com.whitefish.ring.obtainDeviceManager |
|
|
|
import com.whitefish.ring.utils.getCurrentTimestamp |
|
|
|
import com.whitefish.ring.utils.timestampToDate |
|
|
|
import com.whitefish.ring.utils.today |
|
|
|
import io.github.aakira.napier.Napier |
|
|
|
import kotlinx.cinterop.ExperimentalForeignApi |
|
|
|
import kotlinx.coroutines.Dispatchers |
|
|
|
import kotlinx.coroutines.IO |
|
|
|
import kotlinx.coroutines.withContext |
|
|
|
import kotlinx.datetime.LocalDate |
|
|
|
import kotlinx.datetime.LocalTime |
|
|
|
import kotlinx.datetime.TimeZone |
|
|
|
import kotlinx.datetime.UtcOffset |
|
|
|
import kotlinx.datetime.atStartOfDayIn |
|
|
|
import kotlinx.datetime.atTime |
|
|
|
import kotlinx.datetime.toInstant |
|
|
|
import kotlinx.datetime.toNSDateComponents |
|
|
|
import platform.Foundation.NSAllocateMemoryPages |
|
|
|
import platform.Foundation.timeIntervalSince1970 |
|
|
|
import kotlin.coroutines.resume |
|
|
|
import kotlin.coroutines.suspendCoroutine |
|
|
@ -50,56 +63,52 @@ actual suspend fun getSleep( |
|
|
|
return@withContext suspendCoroutine { coroutine -> |
|
|
|
macAddress?.let { |
|
|
|
val segments = mutableListOf<SleepSegment>() |
|
|
|
|
|
|
|
Napier.i { "${start.timestampToDate()} --> ${end.timestampToDate()}" } |
|
|
|
DBSleepData.queryDbSleepBy( |
|
|
|
it, start.timestampToDate().timeIntervalSince1970, |
|
|
|
end.timestampToDate().timeIntervalSince1970 |
|
|
|
) { result -> |
|
|
|
val sleepDataList = result?.map { it as DBSleepData } |
|
|
|
var totalSeconds = 0 |
|
|
|
|
|
|
|
result?.let { |
|
|
|
it.forEach { |
|
|
|
(it as DBSleepData).apply { |
|
|
|
totalSeconds += it.duration.intValue |
|
|
|
Napier.i { "sleep isNap:${isNap},start:${it.sleepStart},end:${it.sleepEnd},duration:${duration}" } |
|
|
|
stagingData.ousideStagingList?.forEach { |
|
|
|
(it as StagingSubObj).apply { |
|
|
|
Napier.i { "staging type:${type.value}, list size:${list.size} ========>" } |
|
|
|
list.forEach { item -> |
|
|
|
(item as StagingListObj).apply { |
|
|
|
Napier.i { "staging item time:${time.doubleValue}" } |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
val sleepDataList = result?.map { it as DBSleepData } |
|
|
|
|
|
|
|
sleepDataList?.let { dataList -> |
|
|
|
dataList.forEach { sleepData -> |
|
|
|
if (!sleepData.isNap) { |
|
|
|
totalSeconds += sleepData.duration.intValue |
|
|
|
|
|
|
|
// 处理睡眠分期数据 |
|
|
|
sleepData.stagingData?.ousideStagingList?.let { stagingList -> |
|
|
|
sleepData.stagingData.ousideStagingList?.let { stagingList -> |
|
|
|
for (i in 0 until stagingList.size) { |
|
|
|
val stagingObj = stagingList[i] as StagingSubObj |
|
|
|
|
|
|
|
// 计算该阶段的持续时间 |
|
|
|
val duration = if (i == 0) { |
|
|
|
// 第一个阶段:从开始到结束 |
|
|
|
stagingObj.list.let { list -> |
|
|
|
val firstTime = (list.first() as? StagingListObj)?.time?.doubleValue ?: 0.0 |
|
|
|
val lastTime = (list.last() as? StagingListObj)?.time?.doubleValue ?: 0.0 |
|
|
|
lastTime - firstTime |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 后续阶段:从前一个阶段结束到当前阶段结束 |
|
|
|
val prevStagingObj = stagingList[i - 1] as StagingSubObj |
|
|
|
val currentEndTime = (stagingObj.list.first() as? StagingListObj)?.time?.doubleValue ?: 0.0 |
|
|
|
val prevEndTime = (prevStagingObj.list.last() as? StagingListObj)?.time?.doubleValue ?: 0.0 |
|
|
|
currentEndTime - prevEndTime |
|
|
|
} |
|
|
|
|
|
|
|
// 转换睡眠状态类型到用户定义的状态 |
|
|
|
val stageDuration = (stagingObj.list.last() as StagingListObj).time.doubleValue - (stagingObj.list.first() as StagingListObj).time.doubleValue / 60 |
|
|
|
val mappedState = mapSleepStageToState(stagingObj.type.value.toInt()) |
|
|
|
|
|
|
|
// 只添加有效的睡眠状态(跳过 NONE 状态) |
|
|
|
if (mappedState >= 0) { |
|
|
|
val durationMinutes = (duration / 60.0).toFloat() |
|
|
|
if (durationMinutes > 0) { |
|
|
|
segments.add(SleepSegment(mappedState, durationMinutes)) |
|
|
|
} |
|
|
|
segments.add(SleepSegment(mappedState, stageDuration.toFloat())) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
coroutine.resume(SleepState(totalSeconds =totalSeconds, segments = segments )) |
|
|
|
|
|
|
|
coroutine.resume(SleepState(totalSeconds =totalSeconds,segments = segments)) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|