From 0ce9456a4e013e2c7d027427e0547283618cc9e4 Mon Sep 17 00:00:00 2001 From: luozheng <1732036298@qq.com> Date: Sat, 22 Nov 2025 17:27:15 +0800 Subject: [PATCH] =?utf8?q?fd272:hrv=E7=95=8C=E9=9D=A2=E6=B7=BB=E5=8A=A0?= =?utf8?q?=E6=95=B0=E6=8D=AE=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../nativeapp/nativeui/hrv/src/HrvView.cpp | 21 ++- .../nativeui/stress/include/stressTestModel.h | 9 +- .../nativeui/stress/src/stressTestModel.cpp | 123 ++++++++++++------ 3 files changed, 106 insertions(+), 47 deletions(-) diff --git a/code/sdk/application/wearable/fd272/nativeapp/nativeui/hrv/src/HrvView.cpp b/code/sdk/application/wearable/fd272/nativeapp/nativeui/hrv/src/HrvView.cpp index 2c646c7b8..f34da6189 100644 --- a/code/sdk/application/wearable/fd272/nativeapp/nativeui/hrv/src/HrvView.cpp +++ b/code/sdk/application/wearable/fd272/nativeapp/nativeui/hrv/src/HrvView.cpp @@ -11,6 +11,7 @@ #include "common/key_code.h" #include "custom_utils.h" #include "ui_resource_string.h" +#include "stress/include/stressTestModel.h" namespace OHOS { @@ -47,6 +48,7 @@ void HrvView::OnStart() group->SetPosition(0, 0, 466, 466); group->SetStyle(STYLE_BACKGROUND_COLOR, 0xff000000); group->SetStyle(STYLE_BACKGROUND_OPA, 0xD0); + group->SetOnDragListener((UIView::OnDragListener *)OHOS::HrvPresenter::GetInstance()); RootView::GetInstance()->Add(group); Label_init(); @@ -75,7 +77,15 @@ bool HrvView::Label_init() { hrv_average_value_label = new UILabel(); hrv_average_value_label->SetPosition(149, 115, 96, 97); - hrv_average_value_label->SetText("--"); + int16_t avg = StressTestModel::GetInstance().GetLastSevenDaysHrvAverage(); + if (avg != -1) + { + hrv_average_value_label->SetText(std::to_string(avg).c_str()); + } + else + { + hrv_average_value_label->SetText("--"); + } hrv_average_value_label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 80); hrv_average_value_label->SetStyle(STYLE_TEXT_COLOR, 0xFFFFFFFF); hrv_average_value_label->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); @@ -135,7 +145,14 @@ bool HrvView::Label_init() { last_average_value_label = new UILabelExt(); last_average_value_label->SetPosition(83, 391, 300, 35); - last_average_value_label->SetText("-- ms"); + std::string last_average_value = "-- ms"; + //获取昨日平均值 + int16_t avg = StressTestModel::GetInstance().GetYesterdayHrvAverage(); + if (avg != -1) + { + last_average_value = std::to_string(avg) + " ms"; + } + last_average_value_label->SetText(last_average_value.c_str()); last_average_value_label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30); last_average_value_label->SetStyle(STYLE_TEXT_COLOR, 0xFFFFFFFF); last_average_value_label->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER); diff --git a/code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/include/stressTestModel.h b/code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/include/stressTestModel.h index e0def7e51..f0b6db541 100644 --- a/code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/include/stressTestModel.h +++ b/code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/include/stressTestModel.h @@ -43,16 +43,19 @@ namespace OHOS uint32_t GetLastTestTimestamp(void); void SetLastTestTimestamp(uint32_t timestamp); - // 获取当前日期字符串(格式:YYYY_MM_DD) - std::string GetCurrentDateString(void); + // 获取指定天数前的日期字符串(格式:YYYY_MM_DD) + std::string GetDaysAgoDateString(int daysAgo = 0); // 创建目录(如果不存在) bool CreateDirectoryIfNotExists(const char* dirPath); // 保存历史记录到日期文件 void SaveHistoryRecord(uint32_t timestamp, uint16_t value); - // 获取指定日期的平均值(用于HRV slice显示) int16_t GetDateAverage(const char* dateStr); + // 获取昨日hrv平均值 + int16_t GetYesterdayHrvAverage(void); + //获取七天hrv平均值 + int16_t GetLastSevenDaysHrvAverage(void); // 定时器相关 void StressTest_StartTimer(uint32_t interval = 1 * 1000, int type = 0); diff --git a/code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/src/stressTestModel.cpp b/code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/src/stressTestModel.cpp index e3f56ee75..5488fc45a 100644 --- a/code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/src/stressTestModel.cpp +++ b/code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/src/stressTestModel.cpp @@ -17,6 +17,7 @@ #include #include "errcode.h" #include "custom_runtime.h" +#include #ifdef SUPPORT_PPG_SERVICE #include "ppg_service.h" @@ -25,7 +26,7 @@ namespace OHOS { - StressTestModel::StressTestModel() + StressTestModel::StressTestModel() { CreateDirectoryIfNotExists("/user/userdata/hrv/"); // 构造函数中加载最近一次测试结果 @@ -37,27 +38,33 @@ namespace OHOS return instance; } - // 获取当前日期字符串(格式:YYYY_MM_DD) - std::string StressTestModel::GetCurrentDateString(void) + std::string StressTestModel::GetDaysAgoDateString(int daysAgo) { char dateStr[32]; time_t now = time(nullptr); - struct tm *tm_info = localtime(&now); - snprintf(dateStr, sizeof(dateStr), "%04d_%02d_%02d", - tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday); + struct tm tm_info; + tm_info = *localtime_r(&now, &tm_info); // 线程安全版本 + tm_info.tm_mday -= daysAgo; + mktime(&tm_info); // 自动处理月份/年份变更 + snprintf(dateStr, sizeof(dateStr), "%04d_%02d_%02d", + tm_info.tm_year + 1900, tm_info.tm_mon + 1, tm_info.tm_mday); return std::string(dateStr); } // 创建目录(如果不存在) - bool StressTestModel::CreateDirectoryIfNotExists(const char* dirPath) + bool StressTestModel::CreateDirectoryIfNotExists(const char *dirPath) { - if (access(dirPath, F_OK) == -1) { // 如果路径不存在 + if (access(dirPath, F_OK) == -1) + { // 如果路径不存在 WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Directory %s not exist, creating directory\n", dirPath); - if (mkdir(dirPath, 0777)!= 0) { // 尝试创建目录,如果创建失败 + if (mkdir(dirPath, 0777) != 0) + { // 尝试创建目录,如果创建失败 WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Create directory %s failed\n", dirPath); return false; } - } else { // 如果路径存在 + } + else + { // 如果路径存在 WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Directory %s already exists\n", dirPath); } return true; @@ -66,7 +73,7 @@ namespace OHOS void StressTestModel::SaveResultToFile(void) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::SaveResultToFile: 保存压力测试结果"); - + // 获取当前时间戳 uint32_t timestamp = 0; if (uapi_get_timestampe_ss(×tamp) != ERRCODE_SUCC) @@ -75,16 +82,16 @@ namespace OHOS return; } lastTestTimestamp = timestamp; - + // 1. 保存最近一次测试结果(覆盖存储) // 确保目录存在 - const char* lastResultDir = "/user/userdata/hrv/last_hrv_test/"; + const char *lastResultDir = "/user/userdata/hrv/last_hrv_test/"; if (!CreateDirectoryIfNotExists(lastResultDir)) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "创建最近结果目录失败"); return; } - + FILE *fp = fopen(STRESS_TEST_LAST_RESULT_FILE_PATH, "w+"); if (fp == nullptr) { @@ -95,7 +102,7 @@ namespace OHOS fprintf(fp, "%u %u\n", timestamp, static_cast(currentResultValue)); fclose(fp); WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "保存最近一次结果: timestamp=%u, value=%u", timestamp, currentResultValue); - + // 2. 保存历史记录到日期文件(追加模式) SaveHistoryRecord(timestamp, currentResultValue); } @@ -113,7 +120,7 @@ namespace OHOS lastTestTimestamp = 0; return; } - + // 读取格式:时间戳(秒) + 结果值 unsigned timestamp = 0; unsigned value = 35; @@ -129,29 +136,29 @@ namespace OHOS } } fclose(fp); - + if (value > 1000) // 简单有效性约束,防止脏数据 { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "值大于1000,使用默认值"); value = 35; timestamp = 0; } - + lastTestTimestamp = timestamp; HandleResultValue(static_cast(value)); WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "加载成功: timestamp=%u, value=%u", timestamp, value); } - + uint32_t StressTestModel::GetLastTestTimestamp(void) { return lastTestTimestamp; } - + void StressTestModel::SetLastTestTimestamp(uint32_t timestamp) { lastTestTimestamp = timestamp; } - + // 保存历史记录到日期文件 void StressTestModel::SaveHistoryRecord(uint32_t timestamp, uint16_t value) { @@ -161,14 +168,14 @@ namespace OHOS WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "创建历史数据目录失败"); return; } - + // 获取日期字符串(格式:YYYY_MM_DD) - std::string dateStr = GetCurrentDateString(); - + std::string dateStr = GetDaysAgoDateString(); + // 构建文件路径 - char filePath[256]={0}; + char filePath[256] = {0}; snprintf(filePath, sizeof(filePath), "%s%s.txt", STRESS_TEST_HISTORY_DIR, dateStr.c_str()); - + // 追加模式打开文件 FILE *fp = fopen(filePath, "a+"); if (fp == nullptr) @@ -176,39 +183,45 @@ namespace OHOS WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "打开历史记录文件失败: %s", filePath); return; } - + // 写入格式:时间戳(秒) + 结果值,每行一条记录 fprintf(fp, "%u %u\n", timestamp, value); fclose(fp); - - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "保存历史记录: date=%s, timestamp=%u, value=%u", - dateStr.c_str(), timestamp, value); + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "保存历史记录: date=%s, timestamp=%u, value=%u", + dateStr.c_str(), timestamp, value); } - + // 获取指定日期的平均值(用于HRV slice显示) - int16_t StressTestModel::GetDateAverage(const char* dateStr) + int16_t StressTestModel::GetDateAverage(const char *dateStr) { if (dateStr == nullptr) { return -1; } - + // 构建文件路径 char filePath[256]; snprintf(filePath, sizeof(filePath), "%s%s.txt", STRESS_TEST_HISTORY_DIR, dateStr); - + + // 先检查文件是否存在 + if (access(filePath, F_OK) == -1) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "日期文件不存在: %s", filePath); + return -1; + } + FILE *fp = fopen(filePath, "r"); if (fp == nullptr) { - WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "日期文件不存在: %s", filePath); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "打开日期文件失败: %s, 错误: %s", filePath, strerror(errno)); return -1; } - + uint32_t sum = 0; uint16_t count = 0; uint32_t timestamp = 0; uint16_t value = 0; - + // 读取所有记录并计算平均值 while (fscanf(fp, "%u %u", ×tamp, &value) == 2) { @@ -219,18 +232,44 @@ namespace OHOS } } fclose(fp); - + if (count == 0) { WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "日期 %s 无有效数据", dateStr); return -1; } - + uint16_t average = sum / count; WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "日期 %s 平均值: %u (共%d条记录)", dateStr, average, count); return average; } + // 获取昨日hrv平均值 + int16_t StressTestModel::GetYesterdayHrvAverage(void) + { + std::string yesterday_date = GetDaysAgoDateString(1); + return GetDateAverage(yesterday_date.c_str()); + } + + // 获取七天hrv平均值:当天的和过去六天的hrv平均值 + int16_t StressTestModel::GetLastSevenDaysHrvAverage(void) + { + int16_t avg = 0; + int count = 0; + for (int i = 0; i < 7; i++) // i=0:昨天, i=6:6天前 + { + std::string date = GetDaysAgoDateString(i); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "获取日期 %s 的平均值", date.c_str()); + int16_t day_avg = GetDateAverage(date.c_str()); + if (day_avg != -1) + { + avg += day_avg; + count++; + } + } + return (count > 0) ? (avg / count) : -1; // 无有效数据时返回-1更合理 + } + uint8_t StressTestModel::GetCurrentView(void) { return currentView; @@ -493,7 +532,7 @@ namespace OHOS if ((test_duration_sec_ >= STRESS_TEST_DURATION_SEC) && ringBufferIndex >= MAX_VALID_STRESS_COUNT) { - #if 1 +#if 1 // 计算最终结果,有效值的均值 uint16_t sum = 0; uint16_t count = (ringBufferIndex < 60) ? ringBufferIndex : 60; @@ -513,7 +552,7 @@ namespace OHOS StressTestPresenter::GetInstance()->ChangeViewOperation( StressTestModel::GetInstance().GetCurrentView(), STRESSTESTRESULTVIEW); } - #else +#else uint16_t finalMs = CalculateReasonableStress(); if (finalMs == -1) { @@ -536,7 +575,7 @@ namespace OHOS StressTestModel::GetInstance().GetCurrentView(), STRESSTESTRESULTVIEW); } } - #endif +#endif // 停止压力测试 StressTest_StopTimer(); // 震动 -- 2.17.1