From 11592980dfbd7350baefacedd8fa1998a6cca93a Mon Sep 17 00:00:00 2001 From: luozheng <1732036298@qq.com> Date: Mon, 17 Nov 2025 16:40:58 +0800 Subject: [PATCH] =?utf8?q?272=EF=BC=9A=E4=BC=98=E5=8C=96=E5=8E=8B=E5=8A=9B?= =?utf8?q?=E6=B5=8B=E8=AF=95=E7=BB=93=E6=9E=9C=E8=AE=A1=E7=AE=97=E6=96=B9?= =?utf8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../nativeui/schedule/src/ScheduleView.cpp | 2 +- .../nativeui/stress/include/stressTestModel.h | 2 + .../nativeui/stress/src/stressTestModel.cpp | 184 ++++++++++++++---- 3 files changed, 148 insertions(+), 40 deletions(-) diff --git a/code/sdk/application/wearable/fd272/nativeapp/nativeui/schedule/src/ScheduleView.cpp b/code/sdk/application/wearable/fd272/nativeapp/nativeui/schedule/src/ScheduleView.cpp index 96053ddd1..80f6a3496 100644 --- a/code/sdk/application/wearable/fd272/nativeapp/nativeui/schedule/src/ScheduleView.cpp +++ b/code/sdk/application/wearable/fd272/nativeapp/nativeui/schedule/src/ScheduleView.cpp @@ -529,7 +529,7 @@ namespace OHOS ContentDeleteButton_->SetPosition(93, 0, 280, 90); ContentDeleteButton_->SetViewId(SCHEDULE_ViewId_ContentDeleteButton_); - ContentDeleteButton_->SetStyle(STYLE_BACKGROUND_COLOR, 0xfffd5213); + ContentDeleteButton_->SetStyle(STYLE_BACKGROUND_COLOR, 0xffff5a36); ContentDeleteButton_->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE); ContentDeleteButton_->SetStyle(STYLE_BORDER_RADIUS, 100); ContentDeleteButton_->SetTextId(STR_DELETE); 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 ac018e76c..65efaf052 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,6 +43,8 @@ namespace OHOS void StressTest_StartTimer(uint32_t interval = 1 * 1000, int type = 0); void StressTest_StopTimer(void); + //计算压力测试合理值 + int16_t CalculateReasonableStress(); // 压力数据处理(参考UpHeartdata) void UpStressData(uint8_t stress); 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 52327458d..d4e063fac 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 @@ -10,6 +10,8 @@ #include #include #include +#include +#include #ifdef SUPPORT_PPG_SERVICE #include "ppg_service.h" @@ -164,20 +166,24 @@ namespace OHOS WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::HandleResultValue: %dms", currentResultValue); } -// 压力测量相关常量定义(参考心率测量的定义) -#define MAX_VALID_STRESS_COUNT 40 // 最大有效数据个数(60秒内至少需要40个有效数据) -#define MAX_DISVALID_STRESS_COUNT 15 // 最大无效数据个数(连续15次无效则停止) -#define MAX_UNWEAR_COUNT 2 // 最大未佩戴次数 -#define STRESS_TEST_DURATION_SEC 100 // 压力测试持续时间(秒) + // 压力测量相关常量定义(参考心率测量的定义) + #define MAX_VALID_STRESS_COUNT 10 // 最大有效数据个数(60秒内至少需要40个有效数据) + #define MAX_DISVALID_STRESS_COUNT 5 // 最大无效数据个数(连续15次无效则停止) + #define MAX_UNWEAR_COUNT 2 // 最大未佩戴次数 + #define STRESS_TEST_DURATION_SEC 60 // 压力测试持续时间(秒) + // 新增:压力测试配置参数(可根据需求调整) + #define STRESS_BUF_SIZE 60 // 环形缓冲区大小(同原有ringBuffer) + #define MAX_OUTLIER_THRESHOLD 1.5 // 异常值判断阈值(IQR倍数) + #define MAX_FLUCTUATION 10 // 最大允许波动值(超过则判定数据不稳定) // 压力测量状态变量 - static uint16_t valid_counter_ = 0; // 有效数据计数器 - static uint16_t disvalid_counter_ = 0; // 无效数据计数器 - static uint16_t unwear_counter_ = 0; // 未佩戴计数器 - static uint16_t test_duration_sec_ = 0; // 测试持续时间(秒) - static uint8_t stress_value_ = 0; // 当前压力值 - static uint8_t ringBuffer[60]{0}; // 压力测试结果环形缓冲区 - static uint16_t ringBufferIndex = 0; // 环形缓冲区索引 + static uint16_t valid_counter_ = 0; // 有效数据计数器 + static uint16_t disvalid_counter_ = 0; // 无效数据计数器 + static uint16_t unwear_counter_ = 0; // 未佩戴计数器 + static uint16_t test_duration_sec_ = 0; // 测试持续时间(秒) + static uint8_t stress_value_ = 0; // 当前压力值 + static uint8_t ringBuffer[STRESS_BUF_SIZE]{0}; // 压力测试结果环形缓冲区 + static uint16_t ringBufferIndex = 0; // 环形缓冲区索引 GraphicTimer *g_stressTestTimer = nullptr; @@ -196,22 +202,102 @@ namespace OHOS } } + // 优化:计算压力测试合理值(返回-1表示计算失败) + int16_t StressTestModel::CalculateReasonableStress() + { + // 1. 检查有效数据量(至少需要10个有效数据,可根据需求调整) + uint16_t validCount = (ringBufferIndex < STRESS_BUF_SIZE) ? ringBufferIndex : STRESS_BUF_SIZE; + if (validCount < 10) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "有效数据不足(%d个),无法计算", validCount); + return -1; + } + + // 2. 复制数据到临时数组并排序(便于后续分位数计算) + uint8_t tempBuf[STRESS_BUF_SIZE]; + memcpy(tempBuf, ringBuffer, validCount * sizeof(uint8_t)); + // 简单冒泡排序(数据量小,效率足够) + for (int i = 0; i < validCount - 1; i++) + { + for (int j = 0; j < validCount - 1 - i; j++) + { + if (tempBuf[j] > tempBuf[j + 1]) + { + uint8_t swap = tempBuf[j]; + tempBuf[j] = tempBuf[j + 1]; + tempBuf[j + 1] = swap; + } + } + } + + // 3. 剔除异常值(基于四分位距IQR) + uint16_t q1Index = validCount * 0.25; // 25%分位数位置 + uint16_t q3Index = validCount * 0.75; // 75%分位数位置 + uint8_t q1 = tempBuf[q1Index]; + uint8_t q3 = tempBuf[q3Index]; + uint8_t iqr = q3 - q1; // 四分位距 + uint8_t lowerBound = (iqr == 0) ? q1 : (q1 - MAX_OUTLIER_THRESHOLD * iqr); // 下限 + uint8_t upperBound = (iqr == 0) ? q3 : (q3 + MAX_OUTLIER_THRESHOLD * iqr); // 上限 + + // 收集过滤后的数据 + uint8_t filteredBuf[STRESS_BUF_SIZE]; + uint16_t filteredCount = 0; + for (int i = 0; i < validCount; i++) + { + if (tempBuf[i] >= lowerBound && tempBuf[i] <= upperBound) + { + filteredBuf[filteredCount++] = tempBuf[i]; + } + else + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "过滤异常值:%d(范围:%d-%d)", + tempBuf[i], lowerBound, upperBound); + } + } + + // 4. 检查过滤后的数据量(至少保留50%原始有效数据) + if (filteredCount < validCount * 0.5) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "异常值过多(剩余%d个),结果不可靠", filteredCount); + return -1; + } + + // 5. 计算P50分位数(中位数,代表典型压力值) + uint16_t p50Index = filteredCount * 0.5; + uint8_t p50Value = filteredBuf[p50Index]; + + // 6. 校验数据波动(最大值-最小值 ≤ 允许波动值,确保稳定性) + uint8_t minVal = filteredBuf[0]; + uint8_t maxVal = filteredBuf[filteredCount - 1]; + if (maxVal - minVal > MAX_FLUCTUATION) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "数据波动过大(%d-%d),结果无效", minVal, maxVal); + return -1; + } + + // 7. 输出计算过程日志(便于调试) + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "压力计算完成:P50=%d,有效数据=%d,过滤后=%d,波动范围=%d-%d", + p50Value, validCount, filteredCount, minVal, maxVal); + + return p50Value; + } + // 处理压力数据(参考UpHeartdata函数) void StressTestModel::UpStressData(uint8_t stress) { stress_value_ = stress; test_duration_sec_++; WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "测试时长:%d", test_duration_sec_); - if(test_duration_sec_ < 40) + if (test_duration_sec_ < 40) { - return;//至少要30s后才能出值 + return; // 至少要30s后才能出值 } // 更新压力值和计数器 if (stress_value_ > 0 && stress_value_ <= 100) { // 有效数据:存储到环形缓冲区 - ringBuffer[ringBufferIndex % 60] = stress_value_; + ringBuffer[ringBufferIndex % STRESS_BUF_SIZE] = stress_value_; ringBufferIndex++; valid_counter_++; // 增加有效计数器 disvalid_counter_ = 0; // 清空无效计数器 @@ -235,6 +321,8 @@ namespace OHOS StressTest_StopTimer(); // 震动提醒 custom_VibratorFunc_int(0); + // 亮屏 + uapi_set_screen_on_api(); // 切换到失败页面 if (StressTestPresenter::GetInstance()) { @@ -244,33 +332,51 @@ namespace OHOS return; } - if (ringBufferIndex >= MAX_VALID_STRESS_COUNT) + if ((test_duration_sec_ >= STRESS_TEST_DURATION_SEC) && ringBufferIndex >= MAX_VALID_STRESS_COUNT) { // 计算最终结果,有效值的均值 - uint16_t sum = 0; - uint16_t count = (ringBufferIndex < 60) ? ringBufferIndex : 60; - printf("测试结果:\n"); - for (int i = 0; i < count; i++) + // uint16_t sum = 0; + // uint16_t count = (ringBufferIndex < 60) ? ringBufferIndex : 60; + // printf("测试结果:\n"); + // for (int i = 0; i < count; i++) + // { + // sum += ringBuffer[i]; + // printf("%d ", ringBuffer[i]); + // } + // printf("\n"); + // uint16_t finalMs = sum / count; + // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "压力测试完成: 最终结果 %dms, 有效数据个数: %d", finalMs, count); + + + uint16_t finalMs = CalculateReasonableStress(); + if (finalMs == -1) { - sum += ringBuffer[i]; - printf("%d ",ringBuffer[i]); + // 计算失败(异常值过多或波动过大) + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "压力测试计算失败"); + StressTestModel::GetInstance().SetCurrentFailType(StressTestModel::FAIL_TYPE_INVALID_DATA); + if (StressTestPresenter::GetInstance()) + { + StressTestPresenter::GetInstance()->ChangeViewOperation( + StressTestModel::GetInstance().GetCurrentView(), STRESSTESTFAILVIEW); + } } - printf("\n"); - uint16_t finalMs = sum / count; - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "压力测试完成: 最终结果 %dms, 有效数据个数: %d", finalMs, count); - // 停止压力测试 - StressTest_StopTimer(); - - StressTestModel &m = StressTestModel::GetInstance(); - m.HandleResultValue(finalMs); // 分档上报 - - // 切换到结果页面 - if (StressTestPresenter::GetInstance()) + else { - StressTestPresenter::GetInstance()->ChangeViewOperation( - StressTestModel::GetInstance().GetCurrentView(), STRESSTESTRESULTVIEW); + StressTestModel::GetInstance().HandleResultValue(finalMs); // 分档上报 + // 切换到结果页面 + if (StressTestPresenter::GetInstance()) + { + StressTestPresenter::GetInstance()->ChangeViewOperation( + StressTestModel::GetInstance().GetCurrentView(), STRESSTESTRESULTVIEW); + } } + // 停止压力测试 + StressTest_StopTimer(); + // 震动 + custom_VibratorFunc_int(0); + // 亮屏 uapi_set_screen_on_api(); + return; } // 检查是否达到测试时长且有效数据足够 if ((test_duration_sec_ >= STRESS_TEST_DURATION_SEC) && ringBufferIndex < MAX_VALID_STRESS_COUNT) @@ -375,9 +481,9 @@ namespace OHOS WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::StressTest_StartTimer: 压力测试定时器启动成功"); // 常亮屏幕 ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON); - #ifdef SUPPORT_PPG_SERVICE +#ifdef SUPPORT_PPG_SERVICE ppg_hrv_start(); - #endif +#endif } } @@ -394,9 +500,9 @@ namespace OHOS ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON); // 重置压力测试定时器数据 resetStressTestData(); - #ifdef SUPPORT_PPG_SERVICE +#ifdef SUPPORT_PPG_SERVICE ppg_hrv_stop(); - #endif +#endif } } } -- 2.17.1