From 9df02a668cc4579c5af24c5bf9be75cabab01b00 Mon Sep 17 00:00:00 2001 From: Caisking <3449750381@qq.com> Date: Wed, 18 Sep 2024 20:52:35 +0800 Subject: [PATCH] =?utf8?q?=E4=BF=AE=E6=94=B9=E5=BF=83=E7=8E=87=E7=9A=84?= =?utf8?q?=E6=98=BE=E7=A4=BA=E6=9C=80=E5=A4=A7=E6=9C=80=E5=B0=8F=E5=80=BC?= =?utf8?q?=E4=B8=BA=E5=AE=9E=E9=99=85=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../health_service/health_service.cpp | 951 +++++++++--------- .../nativeui/heartrate/include/HeartModel.h | 7 +- .../nativeui/heartrate/src/HeartChartView.cpp | 4 +- .../nativeui/heartrate/src/HeartModel.cpp | 32 +- 4 files changed, 493 insertions(+), 501 deletions(-) diff --git a/code/sdk/application/wearable/fd230app/nativeui/heart_blood/health_service/health_service.cpp b/code/sdk/application/wearable/fd230app/nativeui/heart_blood/health_service/health_service.cpp index 6d9550e4f..a8491bd4e 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/heart_blood/health_service/health_service.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/heart_blood/health_service/health_service.cpp @@ -1,36 +1,32 @@ #include "health_service.h" -#include -#include "wearable_log.h" +#include "bloodoxygen/include/BloodOxygenModel.h" #include "cJSON.h" -#include -#include -#include "kv_store.h" #include "custom_utils.h" +#include "heartrate/include/HeartModel.h" +#include "kv_store.h" +#include "wearable_log.h" +#include +#include #include +#include #include #include -#include -#include "heartrate/include/HeartModel.h" -#include "bloodoxygen/include/BloodOxygenModel.h" -namespace OHOS -{ - extern "C" - { - void save_heart_data() - { - printf("save_heart_data\r\n"); - OHOS::HealthService::GetInstance()->SaveDailyHeartRate(); - return; - } - } +#include +namespace OHOS { +extern "C" { +void save_heart_data() { + printf("save_heart_data\r\n"); + OHOS::HealthService::GetInstance()->SaveDailyHeartRate(); + return; +} +} - static HealthService *g_pHealthService = nullptr; - /*获取日期*/ - std::string GetCurrentDate() - { - char date[9]; - uapi_get_YYMMDD_Time(date, '\0'); - return std::string(date); +static HealthService *g_pHealthService = nullptr; +/*获取日期*/ +std::string GetCurrentDate() { + char date[9]; + uapi_get_YYMMDD_Time(date, '\0'); + return std::string(date); #if 0 time_t now = time(0); tm *ltm = localtime(&now); @@ -38,478 +34,471 @@ namespace OHOS strftime(date, sizeof(date), "%m%d%Y", ltm); // Use "%m%d%Y" for MMDDYYYY format return std::string(date); #endif - } - // static char *JSON_F_buf=NULL; +} +// static char *JSON_F_buf=NULL; - HealthService::HealthService() - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HealthService::HealthService"); - g_pHealthService = this; - } - HealthService::~HealthService() - { - g_pHealthService = nullptr; - } - HealthService *HealthService::GetInstance() - { - static HealthService instance; - return &instance; - } +HealthService::HealthService() { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HealthService::HealthService"); + g_pHealthService = this; +} +HealthService::~HealthService() { g_pHealthService = nullptr; } +HealthService *HealthService::GetInstance() { + static HealthService instance; + return &instance; +} - static constexpr const char *HEALTH_JSON_PATH = "/user/userdata/health/"; - static constexpr const char *HEALTH_JSON_PATH_HEART = "/user/userdata/health/heart/"; - static constexpr const char *HEALTH_JSON_PATH_OXYGEN = "/user/userdata/health/oxygen/"; - const char *GET_HEALTH_JSON_PATH_C_STR_HEART() - { - return HEALTH_JSON_PATH_HEART; +static constexpr const char *HEALTH_JSON_PATH = "/user/userdata/health/"; +static constexpr const char *HEALTH_JSON_PATH_HEART = + "/user/userdata/health/heart/"; +static constexpr const char *HEALTH_JSON_PATH_OXYGEN = + "/user/userdata/health/oxygen/"; +const char *GET_HEALTH_JSON_PATH_C_STR_HEART() { + return HEALTH_JSON_PATH_HEART; +} +const char *GET_HEALTH_JSON_PATH_C_STR_OXYGEN() { + return HEALTH_JSON_PATH_OXYGEN; +} +/* --------------------------------- 文件IO操作 + * --------------------------------- */ +/*创建文件夹*/ +bool HealthService::CreateHealthFolder() { + struct stat info; + if (stat(HEALTH_JSON_PATH, &info) != 0) { + if (mkdir(HEALTH_JSON_PATH, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "mkdir HEALTH_JSON_PATH is error"); + return false; } - const char *GET_HEALTH_JSON_PATH_C_STR_OXYGEN() - { - return HEALTH_JSON_PATH_OXYGEN; + } + if (stat(HEALTH_JSON_PATH_HEART, &info) != 0) { + if (mkdir(HEALTH_JSON_PATH_HEART, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != + 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "mkdir HEALTH_JSON_PATH_HEART is error"); + return false; } - /* --------------------------------- 文件IO操作 --------------------------------- */ - /*创建文件夹*/ - bool HealthService::CreateHealthFolder() - { - struct stat info; - if (stat(HEALTH_JSON_PATH, &info) != 0) - { - if (mkdir(HEALTH_JSON_PATH, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "mkdir HEALTH_JSON_PATH is error"); - return false; - } - } - if (stat(HEALTH_JSON_PATH_HEART, &info) != 0) - { - if (mkdir(HEALTH_JSON_PATH_HEART, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "mkdir HEALTH_JSON_PATH_HEART is error"); - return false; - } - } - if (stat(HEALTH_JSON_PATH_OXYGEN, &info) != 0) - { - if (mkdir(HEALTH_JSON_PATH_OXYGEN, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "mkdir HEALTH_JSON_PATH_OXYGEN is error"); - return false; - } - } - - return true; + } + if (stat(HEALTH_JSON_PATH_OXYGEN, &info) != 0) { + if (mkdir(HEALTH_JSON_PATH_OXYGEN, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != + 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "mkdir HEALTH_JSON_PATH_OXYGEN is error"); + return false; } + } - /*生成bin*/ - std::string GetBinFilePath(uint8_t type) - { - std::string currentDate = GetCurrentDate(); - const char *healthTypePath = (type == HEALTH_TYPE_HEART) ? HEALTH_JSON_PATH_HEART : HEALTH_JSON_PATH_OXYGEN; - - return healthTypePath + currentDate + ".bin"; - } - - /* --------------------------------- json操作 --------------------------------- */ - static constexpr const char *HEART_JSON_PATH = "/user/userdata/health/heart.json"; - static constexpr const char *BLOOD_JSON_PATH = "/user/userdata/health/blood.json"; + return true; +} - // 读取血氧数据 - BloodOxygenData *HealthService::ReadBloodOxygenData() - { - // 判断文件夹是否存在 - if (!CreateHealthFolder()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CreateHealthFolder file"); - return nullptr; - } - - // 读取文件 - std::ifstream inFile(BLOOD_JSON_PATH); - if (!inFile.is_open()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open JSON file"); - return nullptr; - } - - // 读取文件内容到字符串 - std::stringstream buffer; - buffer << inFile.rdbuf(); - std::string jsonDataString = buffer.str(); - const char *jsonData = jsonDataString.c_str(); - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jsonData: %s", jsonData); - - // 关闭文件 - inFile.close(); - - if (jsonDataString.empty()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jsonDataString is empty"); - return nullptr; - } - - cJSON *oxygen_root = cJSON_Parse(jsonData); - if (oxygen_root == NULL) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "oxygen_root is empty"); - return nullptr; - } - - BloodOxygenData *data = new BloodOxygenData(); - - cJSON *value_item = cJSON_GetObjectItem(oxygen_root, "value"); - cJSON *timestamp_item = cJSON_GetObjectItem(oxygen_root, "timestamp"); - - if (value_item && timestamp_item) - { - data->SPO2 = value_item->valueint; - data->timestamp = timestamp_item->valuedouble; - } - else - { - // 读取的数据异常 - cJSON_Delete(oxygen_root); - delete data; - return nullptr; - } - cJSON_Delete(oxygen_root); - return data; - } - // 读取心率数据 - HeartRateData *HealthService::ReadHeartRateData() - { - // 判断文件夹是否存在 - if (!CreateHealthFolder()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CreateHealthFolder file"); - return nullptr; - } - - // 读取文件 - std::ifstream inFile(HEART_JSON_PATH); - if (!inFile.is_open()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open JSON file"); - // 创建一个默认值为 0的数据 存储到json里面 ? - return nullptr; - } - - // 读取文件内容到字符串 - std::stringstream buffer; - buffer << inFile.rdbuf(); - std::string jsonDataString = buffer.str(); - const char *jsonData = jsonDataString.c_str(); - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jsonData: %s", jsonData); - - // 关闭文件 - inFile.close(); - - if (jsonDataString.empty()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jsonDataString is empty"); - return nullptr; - } - - cJSON *heart_root = cJSON_Parse(jsonData); - if (heart_root == NULL) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "heart_root is empty"); - return nullptr; - } - - HeartRateData *data = new HeartRateData(); - - cJSON *value_item = cJSON_GetObjectItem(heart_root, "value"); - cJSON *timestamp_item = cJSON_GetObjectItem(heart_root, "timestamp"); - - if (value_item && timestamp_item) - { - data->Heart = value_item->valueint; - data->timestamp = timestamp_item->valuedouble; - } - else - { - // 读取的数据异常 - cJSON_Delete(heart_root); - delete data; - return nullptr; - } - cJSON_Delete(heart_root); - return data; - } - // 保存血氧数据 - bool HealthService::UpdateHealthData(const BloodOxygenData &data) - { - // 判断文件夹是否存在 - if (!CreateHealthFolder()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CreateHealthFolder file"); - return false; - } - - // 判断文件是否存在 不存在即创建 并打开以输出模式 - std::ofstream outFile(BLOOD_JSON_PATH, std::ios::trunc); - if (!outFile.is_open()) - { - // 文件创建失败 - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to create or open JSON file for writing"); - return false; - } - - // 创建一个 JSON 对象 - cJSON *oxygen_root = cJSON_CreateObject(); - if (oxygen_root == NULL) - { - outFile.close(); - return false; - } - - cJSON_AddItemToObject(oxygen_root, "value", cJSON_CreateNumber(data.SPO2)); - cJSON_AddItemToObject(oxygen_root, "timestamp", cJSON_CreateNumber(data.timestamp)); - - char *jsonData = cJSON_Print(oxygen_root); - if (jsonData == NULL) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to generate JSON data"); - cJSON_free(oxygen_root); - outFile.close(); - return false; - } - - // 写入 JSON 数据到文件 - outFile << jsonData; - - cJSON_free(oxygen_root); - free(jsonData); - outFile.close(); - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateHealthData SPO2 JSON is ok"); - - /* 存储bin文件[协议使用] */ - std::string binFilePath = GetBinFilePath(HEALTH_TYPE_OXYGEN); - FILE *fp = fopen(binFilePath.c_str(), "ab+"); - if (fp == NULL) - { - return false; - } - - fwrite(&data.timestamp, 4, 1, fp); - fwrite(&data.SPO2, 1, 1, fp); - - fclose(fp); - - return true; - } +/*生成bin*/ +std::string GetBinFilePath(uint8_t type) { + std::string currentDate = GetCurrentDate(); + const char *healthTypePath = (type == HEALTH_TYPE_HEART) + ? HEALTH_JSON_PATH_HEART + : HEALTH_JSON_PATH_OXYGEN; - // 存储心率 - bool HealthService::UpdateHealthData(const HeartRateData &data) - { - // 判断文件夹是否存在 - if (!CreateHealthFolder()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CreateHealthFolder file"); - return false; - } - - // 判断文件是否存在 不存在即创建 并打开以输出模式 - std::ofstream outFile(HEART_JSON_PATH, std::ios::trunc); - if (!outFile.is_open()) - { - // 文件创建失败 - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to create or open JSON file for writing"); - return false; - } - - // 创建一个 JSON 对象 - cJSON *heart_root = cJSON_CreateObject(); - if (heart_root == NULL) - { - outFile.close(); - return false; - } - - cJSON_AddItemToObject(heart_root, "value", cJSON_CreateNumber(data.Heart)); - cJSON_AddItemToObject(heart_root, "timestamp", cJSON_CreateNumber(data.timestamp)); - - char *jsonData = cJSON_Print(heart_root); - if (jsonData == NULL) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to generate JSON data"); - cJSON_free(heart_root); - outFile.close(); - return false; - } - - // 写入 JSON 数据到文件 - outFile << jsonData; - - cJSON_free(heart_root); - free(jsonData); - outFile.close(); - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateHealthData Heart JSON is ok"); - - // 写入文件到当天历史数据 - UpdateHourlyHeartRate(data.timestamp, data.Heart); - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateHourlyHeartRate is ok"); - - /* 存储bin文件[协议使用] */ - std::string binFilePath = GetBinFilePath(HEALTH_TYPE_HEART); - FILE *fp = fopen(binFilePath.c_str(), "ab+"); - if (fp == NULL) - { - return false; - } - - fwrite(&data.timestamp, 4, 1, fp); - fwrite(&data.Heart, 1, 1, fp); - - fclose(fp); - - return true; - } - // 清空健康数据 - bool HealthService::CleanHealthData() - { - ClearHourlyHeartRates(); - HeartModel::GetInstance()->ClearDisplayData(); - BloodOxygenModel::GetInstance()->ClearDisplayData(); + return healthTypePath + currentDate + ".bin"; +} - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CleanHealthData is ok"); - return true; - } +/* --------------------------------- json操作 --------------------------------- + */ +static constexpr const char *HEART_JSON_PATH = + "/user/userdata/health/heart.json"; +static constexpr const char *BLOOD_JSON_PATH = + "/user/userdata/health/blood.json"; + +// 读取血氧数据 +BloodOxygenData *HealthService::ReadBloodOxygenData() { + // 判断文件夹是否存在 + if (!CreateHealthFolder()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CreateHealthFolder file"); + return nullptr; + } + + // 读取文件 + std::ifstream inFile(BLOOD_JSON_PATH); + if (!inFile.is_open()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open JSON file"); + return nullptr; + } + + // 读取文件内容到字符串 + std::stringstream buffer; + buffer << inFile.rdbuf(); + std::string jsonDataString = buffer.str(); + const char *jsonData = jsonDataString.c_str(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jsonData: %s", jsonData); + + // 关闭文件 + inFile.close(); + + if (jsonDataString.empty()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jsonDataString is empty"); + return nullptr; + } + + cJSON *oxygen_root = cJSON_Parse(jsonData); + if (oxygen_root == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "oxygen_root is empty"); + return nullptr; + } + + BloodOxygenData *data = new BloodOxygenData(); + + cJSON *value_item = cJSON_GetObjectItem(oxygen_root, "value"); + cJSON *timestamp_item = cJSON_GetObjectItem(oxygen_root, "timestamp"); + + if (value_item && timestamp_item) { + data->SPO2 = value_item->valueint; + data->timestamp = timestamp_item->valuedouble; + } else { + // 读取的数据异常 + cJSON_Delete(oxygen_root); + delete data; + return nullptr; + } + cJSON_Delete(oxygen_root); + return data; +} +// 读取心率数据 +HeartRateData *HealthService::ReadHeartRateData() { + // 判断文件夹是否存在 + if (!CreateHealthFolder()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CreateHealthFolder file"); + return nullptr; + } + + // 读取文件 + std::ifstream inFile(HEART_JSON_PATH); + if (!inFile.is_open()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open JSON file"); + // 创建一个默认值为 0的数据 存储到json里面 ? + return nullptr; + } + + // 读取文件内容到字符串 + std::stringstream buffer; + buffer << inFile.rdbuf(); + std::string jsonDataString = buffer.str(); + const char *jsonData = jsonDataString.c_str(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jsonData: %s", jsonData); + + // 关闭文件 + inFile.close(); + + if (jsonDataString.empty()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "jsonDataString is empty"); + return nullptr; + } + + cJSON *heart_root = cJSON_Parse(jsonData); + if (heart_root == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "heart_root is empty"); + return nullptr; + } + + HeartRateData *data = new HeartRateData(); + + cJSON *value_item = cJSON_GetObjectItem(heart_root, "value"); + cJSON *timestamp_item = cJSON_GetObjectItem(heart_root, "timestamp"); + + if (value_item && timestamp_item) { + data->Heart = value_item->valueint; + data->timestamp = timestamp_item->valuedouble; + } else { + // 读取的数据异常 + cJSON_Delete(heart_root); + delete data; + return nullptr; + } + cJSON_Delete(heart_root); + return data; +} +// 保存血氧数据 +bool HealthService::UpdateHealthData(const BloodOxygenData &data) { + // 判断文件夹是否存在 + if (!CreateHealthFolder()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CreateHealthFolder file"); + return false; + } + + // 判断文件是否存在 不存在即创建 并打开以输出模式 + std::ofstream outFile(BLOOD_JSON_PATH, std::ios::trunc); + if (!outFile.is_open()) { + // 文件创建失败 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Failed to create or open JSON file for writing"); + return false; + } + + // 创建一个 JSON 对象 + cJSON *oxygen_root = cJSON_CreateObject(); + if (oxygen_root == NULL) { + outFile.close(); + return false; + } + + cJSON_AddItemToObject(oxygen_root, "value", cJSON_CreateNumber(data.SPO2)); + cJSON_AddItemToObject(oxygen_root, "timestamp", + cJSON_CreateNumber(data.timestamp)); + + char *jsonData = cJSON_Print(oxygen_root); + if (jsonData == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to generate JSON data"); + cJSON_free(oxygen_root); + outFile.close(); + return false; + } + + // 写入 JSON 数据到文件 + outFile << jsonData; + + cJSON_free(oxygen_root); + free(jsonData); + outFile.close(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateHealthData SPO2 JSON is ok"); + + /* 存储bin文件[协议使用] */ + std::string binFilePath = GetBinFilePath(HEALTH_TYPE_OXYGEN); + FILE *fp = fopen(binFilePath.c_str(), "ab+"); + if (fp == NULL) { + return false; + } + + fwrite(&data.timestamp, 4, 1, fp); + fwrite(&data.SPO2, 1, 1, fp); + + fclose(fp); + + return true; +} - HealthState HealthService::GetHealthCurrent() - { - return healthState_; - } - void HealthService::SetHealthCurrent(HealthState healthState) - { - healthState_ = healthState; - } - /* ------------------------------- 心率当天历史数据处理 ------------------------------ */ - static constexpr const char *HEART_DATA_PATH = "/user/userdata/health/heart_history.bin"; - bool HealthService::LoadDailyHeartRate() - { - // 初始化心率数组为 0 - ClearHourlyHeartRates(); - - // 获取当前时间 - time_t currentTime = time(nullptr); - tm *currentTm = localtime(¤tTime); - - // 检查是否为同一天 - std::ifstream file(HEART_DATA_PATH, std::ios::binary); - if (!file.is_open()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Unable to open heart rate data file for reading"); - return false; // 文件打开失败 - } - - // 读取时间戳 - file.read(reinterpret_cast(&lastLoadTime), sizeof(lastLoadTime)); - - // 检查是否为同一天 - if (lastLoadTime != 0) // 确保 lastLoadTime 有效 - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "************************************************"); - tm *lastTm = localtime(&lastLoadTime); - if (currentTm->tm_year == lastTm->tm_year && - currentTm->tm_yday == lastTm->tm_yday) - { - // 如果是同一天,直接读取心率数据 - for (int i = 0; i < MAX_HOURS; ++i) - { - uint16_t heartRate; - if (!file.read(reinterpret_cast(&heartRate), sizeof(heartRate))) // 读取心率 - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Failed to read heart rate data."); - file.close(); - return false; // 读取失败 - } - dailyHeartRates[i] = heartRate; - - // 打印心率数据 - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Hour %d: Heart Rate %d", i, heartRate); - } - file.close(); - return true; // 成功读取 - } - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "************************************************"); - } - - // 如果不是同一天,关闭文件 - file.close(); - - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Not same-day data"); - return false; // 不是同一天 - } +// 存储心率 +bool HealthService::UpdateHealthData(const HeartRateData &data) { + // 判断文件夹是否存在 + if (!CreateHealthFolder()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CreateHealthFolder file"); + return false; + } + + // 判断文件是否存在 不存在即创建 并打开以输出模式 + std::ofstream outFile(HEART_JSON_PATH, std::ios::trunc); + if (!outFile.is_open()) { + // 文件创建失败 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Failed to create or open JSON file for writing"); + return false; + } + + // 创建一个 JSON 对象 + cJSON *heart_root = cJSON_CreateObject(); + if (heart_root == NULL) { + outFile.close(); + return false; + } + + cJSON_AddItemToObject(heart_root, "value", cJSON_CreateNumber(data.Heart)); + cJSON_AddItemToObject(heart_root, "timestamp", + cJSON_CreateNumber(data.timestamp)); + + char *jsonData = cJSON_Print(heart_root); + if (jsonData == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to generate JSON data"); + cJSON_free(heart_root); + outFile.close(); + return false; + } + + // 写入 JSON 数据到文件 + outFile << jsonData; + + cJSON_free(heart_root); + free(jsonData); + outFile.close(); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateHealthData Heart JSON is ok"); + + // 写入文件到当天历史数据 + UpdateHourlyHeartRate(data.timestamp, data.Heart); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "UpdateHourlyHeartRate is ok"); + + /* 存储bin文件[协议使用] */ + std::string binFilePath = GetBinFilePath(HEALTH_TYPE_HEART); + FILE *fp = fopen(binFilePath.c_str(), "ab+"); + if (fp == NULL) { + return false; + } + + fwrite(&data.timestamp, 4, 1, fp); + fwrite(&data.Heart, 1, 1, fp); + + fclose(fp); + + return true; +} +// 清空健康数据 +bool HealthService::CleanHealthData() { + ClearHourlyHeartRates(); + HeartModel::GetInstance()->ClearDisplayData(); + BloodOxygenModel::GetInstance()->ClearDisplayData(); + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CleanHealthData is ok"); + return true; +} - bool HealthService::SaveDailyHeartRate() - { - // 判断文件是否存在 不存在即创建 并打开以输出模式 - std::ofstream outFile(HEART_DATA_PATH, std::ios::trunc); - if (!outFile.is_open()) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Unable to open heart rate data file for reading"); - return false; // 文件打开失败 - } - - // 存储一个时间戳最前面 - time_t currentTime = time(nullptr); - outFile.write(reinterpret_cast(¤tTime), sizeof(currentTime)); - - for (int i = 0; i < MAX_HOURS; ++i) - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveDailyHeartRate:: Time is %d Heart is %d", i, dailyHeartRates[i]); - if (!outFile.write(reinterpret_cast(&dailyHeartRates[i]), sizeof(dailyHeartRates[i]))) // 保存心率值 - { - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Failed to write heart rate data."); - outFile.close(); - return false; // 写入失败 - } - } - outFile.close(); - return true; // 成功保存 - } - void HealthService::ClearHourlyHeartRates() +HealthState HealthService::GetHealthCurrent() { return healthState_; } +void HealthService::SetHealthCurrent(HealthState healthState) { + healthState_ = healthState; +} +/* ------------------------------- 心率当天历史数据处理 + * ------------------------------ */ +static constexpr const char *HEART_DATA_PATH = + "/user/userdata/health/heart_history.bin"; +bool HealthService::LoadDailyHeartRate() +{ + // 初始化心率数组为 0 + ClearHourlyHeartRates(); + + // 获取当前时间 + time_t currentTime = time(nullptr); + tm *currentTm = localtime(¤tTime); + + // 检查是否为同一天 + std::ifstream file(HEART_DATA_PATH, std::ios::binary); + if (!file.is_open()) + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Unable to open heart rate data file for reading"); + return false; // 文件打开失败 + } + + // 读取时间戳 + file.read(reinterpret_cast(&lastLoadTime), sizeof(lastLoadTime)); + + // 检查是否为同一天 + if (lastLoadTime != 0) // 确保 lastLoadTime 有效 + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "************************************************"); + tm *lastTm = localtime(&lastLoadTime); + if (currentTm->tm_year == lastTm->tm_year && + currentTm->tm_yday == lastTm->tm_yday) + { + // 如果是同一天,直接读取心率数据 + for (int i = 0; i < MAX_HOURS; ++i) + { + uint16_t heartRate; + if (!file.read(reinterpret_cast(&heartRate), sizeof(heartRate))) // 读取心率 + { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Failed to read heart rate data."); + file.close(); + return false; // 读取失败 + } + dailyHeartRates[i] = heartRate; + + // 打印心率数据 + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Hour %d: Heart Rate %d", i, heartRate); + } + + // 计算最大和最小心率 + int maxHeartRate = dailyHeartRates[0]; + int minHeartRate = dailyHeartRates[0]; + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "maxHeartRate %d: minHeartRate %d", minHeartRate, maxHeartRate); + + for (int i = 1; i < MAX_HOURS; ++i) + { + if (dailyHeartRates[i] > maxHeartRate) + { + maxHeartRate = dailyHeartRates[i]; + } + if ((minHeartRate == 0 && dailyHeartRates[i] != 0)||(dailyHeartRates[i] < minHeartRate && dailyHeartRates[i] != 0)) + { + minHeartRate = dailyHeartRates[i]; + } + } + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "for maxHeartRate %d: minHeartRate %d", minHeartRate, maxHeartRate); + + // 设置最大和最小心率 + HeartModel::GetInstance()->SetTopAndBottom(maxHeartRate, minHeartRate); + + file.close(); + return true; // 成功读取 + } + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "************************************************"); + } + + // 如果不是同一天,关闭文件 + file.close(); + + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error: Not same-day data"); + return false; // 不是同一天 +} + +bool HealthService::SaveDailyHeartRate() { + // 判断文件是否存在 不存在即创建 并打开以输出模式 + std::ofstream outFile(HEART_DATA_PATH, std::ios::trunc); + if (!outFile.is_open()) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Error: Unable to open heart rate data file for reading"); + return false; // 文件打开失败 + } + + // 存储一个时间戳最前面 + time_t currentTime = time(nullptr); + outFile.write(reinterpret_cast(¤tTime), + sizeof(currentTime)); + + for (int i = 0; i < MAX_HOURS; ++i) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "SaveDailyHeartRate:: Time is %d Heart is %d", i, + dailyHeartRates[i]); + if (!outFile.write(reinterpret_cast(&dailyHeartRates[i]), + sizeof(dailyHeartRates[i]))) // 保存心率值 { - // 清空心率数据,将数组置为 0 - for (int i = 0; i < MAX_HOURS; ++i) - { - dailyHeartRates[i] = 0; - } + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Error: Failed to write heart rate data."); + outFile.close(); + return false; // 写入失败 } - void HealthService::UpdateHourlyHeartRate(time_t timestamp, uint16_t heartRate) - { - // 将时间戳转换为 tm 结构体 - struct tm *timeInfo = localtime(×tamp); // 使用 localtime 获取本地时间 + } + outFile.close(); + return true; // 成功保存 +} +void HealthService::ClearHourlyHeartRates() { + // 清空心率数据,将数组置为 0 + for (int i = 0; i < MAX_HOURS; ++i) { + dailyHeartRates[i] = 0; + } +} +void HealthService::UpdateHourlyHeartRate(time_t timestamp, + uint16_t heartRate) { + // 将时间戳转换为 tm 结构体 + struct tm *timeInfo = localtime(×tamp); // 使用 localtime 获取本地时间 - // 提取小时 - uint16_t hour = static_cast(timeInfo->tm_hour); + // 提取小时 + uint16_t hour = static_cast(timeInfo->tm_hour); - WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Updating heart rate: 小时 %d, 心率值 %d", hour, heartRate); + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, + "Updating heart rate: 小时 %d, 心率值 %d", hour, heartRate); - // 确保 hour 在有效范围内,并且心率不是异常值(例如负值) - if (hour < MAX_HOURS && heartRate > 0) // 心率不应为负 并且 小时不能为24 - { - dailyHeartRates[hour] = heartRate; + // 确保 hour 在有效范围内,并且心率不是异常值(例如负值) + if (hour < MAX_HOURS && heartRate > 0) // 心率不应为负 并且 小时不能为24 + { + dailyHeartRates[hour] = heartRate; - // 记录目前更新时间点 - currenthour = hour; - } - } + // 记录目前更新时间点 + currenthour = hour; + } +} - uint16_t HealthService::GetHourlyHeartRate(uint16_t hour) - { - // 返回指定小时的心率 - if (hour < MAX_HOURS) - { - return dailyHeartRates[hour]; // 默认为 0 如果未更新 - } - return 0; // 或者返回一个异常值 - } +uint16_t HealthService::GetHourlyHeartRate(uint16_t hour) { + // 返回指定小时的心率 + if (hour < MAX_HOURS) { + return dailyHeartRates[hour]; // 默认为 0 如果未更新 + } + return 0; // 或者返回一个异常值 +} - uint16_t HealthService::GetCurrentHour() - { - // 返回目前小时 - return currenthour; - } +uint16_t HealthService::GetCurrentHour() { + // 返回目前小时 + return currenthour; } +} // namespace OHOS diff --git a/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartModel.h b/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartModel.h index 4827a8abc..9f47cc005 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartModel.h +++ b/code/sdk/application/wearable/fd230app/nativeui/heartrate/include/HeartModel.h @@ -150,7 +150,8 @@ public: std::string GetCheckString(); uint16_t *GetArrayData(); void SetArrayData(); - + void SetTopAndBottom(int maxheart,int minheart); + void UpdateTopAndBottom(int heart); private: HealthAllDatas healthDatas; uint16_t pretime{0}; @@ -167,8 +168,8 @@ private: uint16_t displayheart; // 显示心率 uint16_t currentheart; // 保存心率 - uint16_t displayheart_max; // 显示最大心率 - uint16_t displayheart_min; // 显示最小心率 + uint16_t displayheart_max = 0; // 显示最大心率 + uint16_t displayheart_min = 0; // 显示最小心率 uint32 timestamp_ms; // 检测时间(存(时、分),大于24小时,改为1天前,小于1分钟为刚刚) diff --git a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp index 7b2663177..6584bba87 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartChartView.cpp @@ -561,7 +561,7 @@ UIViewGroup *HeartChartView::GetchartGroup() { } // HeartImageAnimator(); 暂时屏蔽 InitChartView(); - UpdateChartConfig(); + // UpdateChartConfig(); 屏蔽动态适配 SetDataChart(); SetLastHeart(); SetDataTopAndBottom(); @@ -582,7 +582,7 @@ void HeartChartView::OnStart() { HeartImageAnimator(); InitChartView(); - UpdateChartConfig(); + // UpdateChartConfig(); 屏蔽动态适配 SetDataChart(); SetLastHeart(); SetDataTopAndBottom(); diff --git a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartModel.cpp b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartModel.cpp index f21f91f53..aa044d279 100644 --- a/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartModel.cpp +++ b/code/sdk/application/wearable/fd230app/nativeui/heartrate/src/HeartModel.cpp @@ -200,7 +200,7 @@ HeartModel::HeartModel() { timestamp_ms = 0; } //配置动态数组 - SetArrayData(); + // SetArrayData(); } HeartModel::~HeartModel() { @@ -574,20 +574,6 @@ void HeartModel::UpHeartdata(uint16_t heart) { currentheart = displayheart; // 更新当前心率 valid_counter_++; // 增加有效计数器 disvalid_counter_ = 0; // 清空无效计数器 - - // 更新最大和最小心率 - displayheart_max = - (displayheart_max < displayheart ? displayheart : displayheart_max); - - // 确保最小心率的第一次赋值大于50 - if (displayheart_min == 0 && displayheart > MIN_DISPLAY_HEART) { - displayheart_min = displayheart; // 初始化最小心率 - } else { - displayheart_min = - (displayheart_min > displayheart && displayheart > MIN_DISPLAY_HEART) - ? displayheart - : displayheart_min; - } } else { disvalid_counter_++; // 增加无效计数器 valid_counter_ = 0; // 清零有效计数器 @@ -609,6 +595,7 @@ void HeartModel::UpHeartdata(uint16_t heart) { "检测结果: 成功 valid_counter: %d currentheart: %d", valid_counter_, currentheart); SetResult(HeartResult::SUCCESS); // 标记为成功检测 + UpdateTopAndBottom(currentheart); Heart_Stop(); return; } @@ -649,6 +636,20 @@ void HeartModel::CleanAllData(void) { } } +//设置最大最小值 +void HeartModel::SetTopAndBottom(int maxheart, int minheart) { + displayheart_max = maxheart; + displayheart_min = minheart; +} +//更新最大最小值 +void HeartModel::UpdateTopAndBottom(int heart) { + if (heart > displayheart_max) { + displayheart_max = heart; + } else if (heart < displayheart_min || displayheart_min == 0) { + displayheart_min = heart; + } +} + //配置5个动态心率数据 //最大 最小 void HeartModel::SetArrayData() { @@ -694,6 +695,7 @@ uint16_t *HeartModel::GetArrayData() { return dynamic_heartrate; } // 获取检测字符串 // 获取检测字符串 +// TODO: 适配多国语言 std::string HeartModel::GetCheckString() { std::string check_string = "检测结果未知"; // 默认返回值 -- 2.17.1