#include <stdio.h>
#include <stdlib.h>
#include <time.h>
+#include <string.h>
+#include <math.h>
#ifdef SUPPORT_PPG_SERVICE
#include "ppg_service.h"
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;
}
}
+ // 优化:计算压力测试合理值(返回-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; // 清空无效计数器
StressTest_StopTimer();
// 震动提醒
custom_VibratorFunc_int(0);
+ // 亮屏
+ uapi_set_screen_on_api();
// 切换到失败页面
if (StressTestPresenter::GetInstance())
{
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)
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
}
}
ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON);
// 重置压力测试定时器数据
resetStressTestData();
- #ifdef SUPPORT_PPG_SERVICE
+#ifdef SUPPORT_PPG_SERVICE
ppg_hrv_stop();
- #endif
+#endif
}
}
}