272:优化压力测试结果计算方式 2753/1 2753/head 2754/target/1
authorluozheng <1732036298@qq.com>
Mon, 17 Nov 2025 08:40:58 +0000 (16:40 +0800)
committerluozheng <1732036298@qq.com>
Mon, 17 Nov 2025 08:40:58 +0000 (16:40 +0800)
code/sdk/application/wearable/fd272/nativeapp/nativeui/schedule/src/ScheduleView.cpp
code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/include/stressTestModel.h
code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/src/stressTestModel.cpp

index 96053dd..80f6a34 100644 (file)
@@ -529,7 +529,7 @@ namespace OHOS
 \r
                 ContentDeleteButton_->SetPosition(93, 0, 280, 90);\r
                 ContentDeleteButton_->SetViewId(SCHEDULE_ViewId_ContentDeleteButton_);\r
-                ContentDeleteButton_->SetStyle(STYLE_BACKGROUND_COLOR, 0xfffd5213);\r
+                ContentDeleteButton_->SetStyle(STYLE_BACKGROUND_COLOR, 0xffff5a36);\r
                 ContentDeleteButton_->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE);\r
                 ContentDeleteButton_->SetStyle(STYLE_BORDER_RADIUS, 100);\r
                 ContentDeleteButton_->SetTextId(STR_DELETE);\r
index ac018e7..65efaf0 100644 (file)
@@ -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);
         
index 5232745..d4e063f 100644 (file)
@@ -10,6 +10,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
+#include <string.h>
+#include <math.h>
 
 #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
         }
     }
 }