272:hrv数据存储逻辑添加,还需优化
authorluozheng <1732036298@qq.com>
Tue, 18 Nov 2025 09:08:53 +0000 (17:08 +0800)
committerluozheng <1732036298@qq.com>
Tue, 18 Nov 2025 09:08:53 +0000 (17:08 +0800)
code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/include/stressTestModel.h
code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/include/stressTestUIConfig.h
code/sdk/application/wearable/fd272/nativeapp/nativeui/stress/src/stressTestModel.cpp

index 65efaf0..e0def7e 100644 (file)
@@ -38,6 +38,21 @@ namespace OHOS
         void HandleResultValue(uint16_t value);
         void SaveResultToFile(void);
         void LoadResultFromFile(void);
+        
+        // 获取最近一次测试的时间戳
+        uint32_t GetLastTestTimestamp(void);
+        void SetLastTestTimestamp(uint32_t timestamp);
+        
+        // 获取当前日期字符串(格式:YYYY_MM_DD)
+        std::string GetCurrentDateString(void);
+        // 创建目录(如果不存在)
+        bool CreateDirectoryIfNotExists(const char* dirPath);
+        
+        // 保存历史记录到日期文件
+        void SaveHistoryRecord(uint32_t timestamp, uint16_t value);
+        
+        // 获取指定日期的平均值(用于HRV slice显示)
+        int16_t GetDateAverage(const char* dateStr);
 
         // 定时器相关
         void StressTest_StartTimer(uint32_t interval = 1 * 1000, int type = 0);
@@ -60,6 +75,7 @@ namespace OHOS
         uint8_t currentFailType{FAIL_TYPE_NOT_WORN};   // 当前错误类型
         uint8_t currentResultType{RESULT_TYPE_NORMAL}; // 当前结果类型
         uint16_t currentResultValue{35};               // 当前压力测试结果值
+        uint32_t lastTestTimestamp{0};                 // 最近一次测试的时间戳
     };
 }
 
index 31bc44e..2e6d9df 100644 (file)
@@ -4,8 +4,10 @@
 #include <stdint.h>
 namespace OHOS
 {
-    // 压力测试结果文件路径
-    static constexpr const char *STRESS_TEST_RESULT_FILE_PATH = "/user/userdata/stresstest_result.bin";
+    // 最近一次压力测试结果文件路径(覆盖存储)
+    static constexpr const char *STRESS_TEST_LAST_RESULT_FILE_PATH = "/user/userdata/hrv/last_hrv_test/stresstest_result.bin";
+    // 压力测试历史数据文件夹路径
+    static constexpr const char *STRESS_TEST_HISTORY_DIR = "/user/userdata/hrv/history/";
     // 结果阈值(单位:ms),可按需要调参:
     // EXCELLENT:   [0, STRESS_THRESHOLD_EXCELLENT_MAX]
     // NORMAL:      (STRESS_THRESHOLD_EXCELLENT_MAX, STRESS_THRESHOLD_NORMAL_MAX]
index d4e063f..8db5dc2 100644 (file)
 #include <time.h>
 #include <string.h>
 #include <math.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <string>
+#include "errcode.h"
+#include "custom_runtime.h"
 
 #ifdef SUPPORT_PPG_SERVICE
 #include "ppg_service.h"
 
 namespace OHOS
 {
-    StressTestModel::StressTestModel() {}
+    StressTestModel::StressTestModel() 
+    {
+        CreateDirectoryIfNotExists("/user/userdata/hrv/");
+        // 构造函数中加载最近一次测试结果
+    }
     StressTestModel::~StressTestModel() {}
     StressTestModel &StressTestModel::GetInstance()
     {
@@ -28,48 +37,198 @@ namespace OHOS
         return instance;
     }
 
+    // 获取当前日期字符串(格式:YYYY_MM_DD)
+    std::string StressTestModel::GetCurrentDateString(void)
+    {
+        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);
+        return std::string(dateStr);
+    }
+
+    // 创建目录(如果不存在)
+    bool StressTestModel::CreateDirectoryIfNotExists(const char* dirPath)
+    {
+        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) {  // 尝试创建目录,如果创建失败
+                WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Create directory %s failed\n", dirPath);
+                return false;
+            }
+        } else {  // 如果路径存在
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Directory %s already exists\n", dirPath);
+        }
+        return true;
+    }
+
     void StressTestModel::SaveResultToFile(void)
     {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::SaveResultToFile: 保存压力测试结果到文件");
-        FILE *fp = fopen(STRESS_TEST_RESULT_FILE_PATH, "w+");
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::SaveResultToFile: 保存压力测试结果");
+        
+        // 获取当前时间戳
+        uint32_t timestamp = 0;
+        if (uapi_get_timestampe_ss(&timestamp) != ERRCODE_SUCC)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "获取时间戳失败");
+            return;
+        }
+        lastTestTimestamp = timestamp;
+        
+        // 1. 保存最近一次测试结果(覆盖存储)
+        // 确保目录存在
+        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)
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveResultToFile open fail: %s", STRESS_TEST_RESULT_FILE_PATH);
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveResultToFile open fail: %s", STRESS_TEST_LAST_RESULT_FILE_PATH);
             return;
         }
-        // ä»¥çº¯æ\96\87æ\9c¬å\86\99å\85¥ä¸\80个æ\95´æ\95°å\80¼ï¼\8c便äº\8eæ\8e\92æ\9f¥
-        fprintf(fp, "%u\n", static_cast<unsigned>(currentResultValue));
+        // ä¿\9då­\98æ ¼å¼\8fï¼\9aæ\97¶é\97´æ\88³(ç§\92) + ç»\93æ\9e\9cå\80¼
+        fprintf(fp, "%u %u\n", timestamp, static_cast<unsigned>(currentResultValue));
         fclose(fp);
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "保存最近一次结果: timestamp=%u, value=%u", timestamp, currentResultValue);
+        
+        // 2. 保存历史记录到日期文件(追加模式)
+        SaveHistoryRecord(timestamp, currentResultValue);
     }
 
     void StressTestModel::LoadResultFromFile(void)
     {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::LoadResultFromFile: 加载压力测试结果到文件");
-        FILE *fp = fopen(STRESS_TEST_RESULT_FILE_PATH, "r");
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::LoadResultFromFile: 加载最近一次压力测试结果");
+        FILE *fp = fopen(STRESS_TEST_LAST_RESULT_FILE_PATH, "r");
         if (fp == nullptr)
         {
-            // 文件不存在则写入默认值并返回
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::LoadResultFromFile: 压力测试结果文件不存在,写入默认值");
+            // 文件不存在,使用默认值
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "压力测试结果文件不存在,使用默认值");
             SetCurrentResultValue(35);
             SetCurrentResultType(RESULT_TYPE_NORMAL);
-            SaveResultToFile();
+            lastTestTimestamp = 0;
             return;
         }
+        
+        // 读取格式:时间戳(秒) + 结果值
+        unsigned timestamp = 0;
         unsigned value = 35;
-        if (fscanf(fp, "%u", &value) != 1)
+        if (fscanf(fp, "%u %u", &timestamp, &value) != 2)
         {
-            // 读失败/格式不对,回退默认
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::LoadResultFromFile: 读取压力测试结果失败,回退默认值");
-            value = 35;
+            // 旧格式兼容:只有值
+            fseek(fp, 0, SEEK_SET);
+            if (fscanf(fp, "%u", &value) != 1)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "读取压力测试结果失败,使用默认值");
+                value = 35;
+                timestamp = 0;
+            }
         }
         fclose(fp);
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::LoadResultFromFile: 读取压力测试结果成功,值为: %u", value);
+        
         if (value > 1000) // 简单有效性约束,防止脏数据
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::LoadResultFromFile: 值大于1000,回退默认值");
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "值大于1000,使用默认值");
             value = 35;
+            timestamp = 0;
         }
+        
+        lastTestTimestamp = timestamp;
         HandleResultValue(static_cast<uint16_t>(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)
+    {
+        // 确保历史数据目录存在
+        if (!CreateDirectoryIfNotExists(STRESS_TEST_HISTORY_DIR))
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "创建历史数据目录失败");
+            return;
+        }
+        
+        // 获取日期字符串(格式:YYYY_MM_DD)
+        std::string dateStr = GetCurrentDateString();
+        
+        // 构建文件路径
+        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)
+        {
+            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);
+    }
+    
+    // 获取指定日期的平均值(用于HRV slice显示)
+    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);
+        
+        FILE *fp = fopen(filePath, "r");
+        if (fp == nullptr)
+        {
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "日期文件不存在: %s", filePath);
+            return -1;
+        }
+        
+        uint32_t sum = 0;
+        uint16_t count = 0;
+        uint32_t timestamp = 0;
+        uint16_t value = 0;
+        
+        // 读取所有记录并计算平均值
+        while (fscanf(fp, "%u %u", &timestamp, &value) == 2)
+        {
+            if (value > 0 && value <= 100) // 有效性检查
+            {
+                sum += value;
+                count++;
+            }
+        }
+        fclose(fp);
+        
+        if (count == 0)
+        {
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "日期 %s 无有效数据", dateStr);
+            return -1;
+        }
+        
+        uint16_t average = sum / count;
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "日期 %s 平均值: %u (共%d条记录)", dateStr, average, count);
+        return average;
     }
 
     uint8_t StressTestModel::GetCurrentView(void)
@@ -161,9 +320,9 @@ namespace OHOS
         {
             currentResultType = RESULT_TYPE_OVERLOAD; // <20
         }
-        SaveResultToFile();
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::HandleResultValue: %d", currentResultType);
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "StressTestModel::HandleResultValue: %dms", currentResultValue);
+        SaveResultToFile();
     }
 
     // 压力测量相关常量定义(参考心率测量的定义)