增加GPS数据的存储服务 1919/1
authorCaisking <Casiking@zhihuishixun.com>
Thu, 3 Jul 2025 06:07:01 +0000 (14:07 +0800)
committerCaisking <Casiking@zhihuishixun.com>
Thu, 3 Jul 2025 06:07:01 +0000 (14:07 +0800)
code/sdk/application/wearable/fd230app/nativeui/traing/include/TraingModel.h
code/sdk/application/wearable/fd230app/nativeui/traing/src/TraingEnddataView.cpp
code/sdk/application/wearable/fd230app/nativeui/traing/src/TraingModel.cpp
code/sdk/application/wearable/fd230app/nativeui/traingrecord/src/TraingRecordPresenter.cpp

index 14de246..7f1bfe0 100644 (file)
@@ -110,6 +110,7 @@ namespace OHOS {
 #define TRAINING_RECORD_FILE "user/userdata/sport/Record.json"
 #define TRAINING_HEART_FILE "user/userdata/sport/HeartTabel/"
 #define TRAINING_PACE_FILE "user/userdata/sport/PaceTabel/"
+#define TRAINING_GPS_FILE "user/userdata/sport/GPS/"
 #define MAX_DATA_COUNT 10
 
 #define TIMER 1
@@ -246,6 +247,7 @@ struct SportData {
 
 //经纬度结构体
 struct GPSData {
+  uint32_t timestamp; // 时间戳
   double latitude;  // 纬度
   double longitude; // 经度
 };
@@ -365,14 +367,16 @@ public:
   //映射经纬度数据集映射画布绘制轨迹坐标集
   void GetPointData();
   //添加经纬度数据集
+  void add_gps_data();
   void AddGPSData(uint32_t timestamp, double latitude, double longitude);
   bool SaveCanvasData();
   void ClearCanvasData();
   std::string GetGPSDataPath(uint32_t timestamp);
   //获取轨迹点集
-  std::vector<Point> GetCanvasData()const;
+  std::vector<Point> GetCanvasData() const;
   bool GetGPSConnectState();
   void SetGPSConnectState(bool state);
+  bool LoadGPSData(const std::string &filePath);
   void OpenGPS();
   void CloseGPS();
   //运动心率、gps开启准备
@@ -432,7 +436,7 @@ private:
   double latitude{0};
   double longitude{0};
   std::vector<Point> canvasData; // 轨迹点集
-  std::vector<GPSData> gpsData;              // GPS数据集
+  std::vector<GPSData> gpsData;  // GPS数据集
   bool gpsconnect{false};
 };
 } // namespace OHOS
index d484818..f903366 100644 (file)
@@ -651,6 +651,16 @@ void TraingEnddataView::InitData() {
       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Stride length set: %s\r\n",
                     strideStr.c_str()); // 打印步幅
     }
+
+    //读取一下gps文件
+    std::string gpsFilePath =
+        TraingModel::GetInstance()->GetGPSDataPath(enddata->starttime);
+    if (!gpsFilePath.empty()) {
+      if (TraingModel::GetInstance()->LoadGPSData(gpsFilePath) == false) {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "gps文件加载失败");
+        return;
+      }
+    }
   }
 
   WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
index ca1b0f4..e086904 100644 (file)
@@ -14,6 +14,7 @@
 #include "uicomponents/UIComponents.h"
 #include "wearable_log.h"
 #include <cmsis_os2.h>
+#include <cstdint>
 #include <fstream>
 #include <iomanip>
 #include <iostream>
@@ -188,6 +189,18 @@ static void Training_Notify(void *args, const Topic topic, Request *request) {
     uint8_t heart = *((u_int8_t *)(request->data)); // 进行类型转换
     TraingModel::GetInstance()->AnalysisHeartData(heart);
   }
+#if 0
+  //使用随机数来进行测试
+  srand(time(NULL));
+  // 纬度范围: 22.45° 到 22.87° ,适当扩大一点范围
+  float lat = (rand() % 420) / 10.0f + 224.5;
+  lat = lat / 10.0f;
+  // 经度范围: 113.75° 到 114.64° ,适当扩大一点范围
+  float lng = (rand() % 890) / 10.0f + 1137.5;
+  lng = lng / 10.0f;
+  TraingModel::GetInstance()->AddGPSData(0, lat, lng);
+  return;
+#endif
 #if defined(SUPPORT_GNSS)
   //训练GPS
   gps_data_t *gps_data = getGPSGlobaldata();
@@ -201,10 +214,12 @@ static void Training_Notify(void *args, const Topic topic, Request *request) {
   }
   //判断是否定位成功
   if (send_gps_data.status > 1) {
-    //添加经纬度 时间戳?
-    TraingModel::GetInstance()->AddGPSData(0,send_gps_data.location.lat,
+    //添加经纬度
+    uint32_t time = TraingModel::GetInstance()->get_current_time();
+    TraingModel::GetInstance()->AddGPSData(time, send_gps_data.location.lat,
                                            send_gps_data.location.lng);
   }
+  return;
 #endif
 }
 #ifdef __cplusplus
@@ -646,8 +661,9 @@ void TraingModel::SetSportdata(SportData *data) {
     sportdata->spc = data->spc;
     sportdata->std = data->std;
     sportdata->cdc = data->cdc;
-    printf_data(data);                  //打印该运动数据
-    IsSpecialSport(sportdata->sportId); // 配置训练特殊性
+    sportdata->starttime = data->starttime; //更新开始时间
+    printf_data(data);                      //打印该运动数据
+    IsSpecialSport(sportdata->sportId);     // 配置训练特殊性
   }
 }
 /*获取训练卡路里*/
@@ -1006,7 +1022,6 @@ void TraingModel::SetSportTag(ExerciseTag tagtpye, int tag) {
 /* 设置训练强度 */
 void TraingModel::SetIntensity(int heart) {
   // sportdata->intensity = active_state;
-#if 1
   /*
       训练强度
       220-年龄=最高心率
@@ -1050,7 +1065,6 @@ void TraingModel::SetIntensity(int heart) {
   WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP,
                 "maxHeartRate: %d, heartRate: %d, intensityPercentage: %.2f",
                 maxHeartRate, heart, intensityPercentage);
-#endif
 }
 /*获取训练强度STR*/
 UIResourceTextId TraingModel::GetIntensity() {
@@ -1410,6 +1424,12 @@ bool TraingModel::SaveSportData() {
       // uapi_dev_runtime_set_train_storage_status(0); // 恢复状态
       // return false;
     }
+    // 保存GPS数据
+    if (!SaveCanvasData()) {
+      WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveGpsData is error!");
+      // uapi_dev_runtime_set_train_storage_status(0); // 恢复状态
+      // return false;
+    }
   }
 
   // 如果所有操作成功,则恢复训练存储状态
@@ -2203,6 +2223,9 @@ bool TraingModel::SaveDataToJson(SportData *data) {
   cJSON_AddNumberToObject(sportData, "cdc", data->cdc); // 训练步频
   cJSON_AddNumberToObject(sportData, "std", data->std); // 训练步幅
   cJSON_AddNumberToObject(sportData, "calories", data->calories); //卡路里
+  WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "starttime is %d", data->starttime);
+  cJSON_AddNumberToObject(sportData, "start_time",
+                          data->starttime); // 开始时间戳
 
   // 添加运动数据节点到数组并限制数量
   cJSON_AddItemToArray(dataArray, sportData);
@@ -2226,153 +2249,314 @@ bool TraingModel::SaveDataToJson(SportData *data) {
   return true;
 }
 
+/* 加载训练数据函数 */
 /* 加载训练数据函数 */
 bool TraingModel::LoadDataFormJson(std::vector<SportData> &sportDataVector) {
+  // 清空输出向量,避免旧数据干扰
+  sportDataVector.clear();
+
+  // 打开JSON文件
   std::ifstream file(TRAINING_RECORD_FILE);
   if (!file.is_open()) {
-    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file");
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to open file: %s",
+                  TRAINING_RECORD_FILE);
     return false;
   }
 
+  // 读取文件内容到字符串
   std::string jsonData((std::istreambuf_iterator<char>(file)),
                        std::istreambuf_iterator<char>());
   file.close();
 
+  WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Read %zu bytes from JSON file",
+                jsonData.size());
+
+  // 解析JSON根对象
   cJSON *root = cJSON_Parse(jsonData.c_str());
   if (root == NULL) {
+    const char *errorPtr = cJSON_GetErrorPtr();
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to parse JSON: %s",
-                  cJSON_GetErrorPtr());
+                  errorPtr ? errorPtr : "Unknown error");
     return false;
   }
 
+  // 查找并验证data数组
   cJSON *dataArray = cJSON_GetObjectItem(root, "data");
-  if (dataArray == NULL || !cJSON_IsArray(dataArray)) {
-    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
-                  "Invalid or missing 'data' array in JSON");
+  if (dataArray == NULL) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Missing 'data' array in JSON");
+    cJSON_Delete(root);
+    return false;
+  }
+  if (!cJSON_IsArray(dataArray)) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "'data' is not an array in JSON");
     cJSON_Delete(root);
     return false;
   }
 
+  // 检查数组大小
   int dataCount = cJSON_GetArraySize(dataArray);
   if (dataCount == 0) {
-    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "error dataCount is 0");
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Empty 'data' array in JSON");
     cJSON_Delete(root);
     return false;
   }
 
-  WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "dataCount is %d", dataCount);
+  WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Found %d items in 'data' array",
+                dataCount);
 
+  // 遍历解析每个数据项
   for (int i = 0; i < dataCount; i++) {
     cJSON *item = cJSON_GetArrayItem(dataArray, i);
     if (item == NULL) {
-      WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid item at index %d", i);
-      continue; // 跳过无效项目
+      WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+                    "Null item at index %d in 'data' array", i);
+      continue; // 跳过无效项,继续处理其他项
     }
 
     SportData sportData;
-    bool isValid = true; // 用于标记 sportData 是否有效
+    bool isValid = true;
+    std::string missingFields; // 记录缺失的字段
 
-    // 检查并获取每个字段,确保其存在且类型正确
-    if (cJSON *sportTypeIdItem = cJSON_GetObjectItem(item, "sportTypeId");
-        sportTypeIdItem && cJSON_IsNumber(sportTypeIdItem))
-      sportData.sportType = (Exercisetype)sportTypeIdItem->valueint;
-    else
+    // 解析sportTypeId字段
+    if (cJSON *sportTypeIdItem = cJSON_GetObjectItem(item, "sportTypeId")) {
+      if (cJSON_IsNumber(sportTypeIdItem)) {
+        sportData.sportType = (Exercisetype)sportTypeIdItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "sportTypeId ";
+      }
+    } else {
       isValid = false;
+      missingFields += "sportTypeId ";
+    }
 
-    if (cJSON *sportIdItem = cJSON_GetObjectItem(item, "sportId");
-        sportIdItem && cJSON_IsNumber(sportIdItem))
-      sportData.sportId = (UIResourceTextId)sportIdItem->valueint;
-    else
+    // 解析sportId字段
+    if (cJSON *sportIdItem = cJSON_GetObjectItem(item, "sportId")) {
+      if (cJSON_IsNumber(sportIdItem)) {
+        sportData.sportId = (UIResourceTextId)sportIdItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "sportId ";
+      }
+    } else {
       isValid = false;
+      missingFields += "sportId ";
+    }
 
-    if (cJSON *startDateItem = cJSON_GetObjectItem(item, "startDate");
-        startDateItem && cJSON_IsString(startDateItem))
-      sportData.start_date = startDateItem->valuestring;
-    else
+    // 解析startDate字段
+    if (cJSON *startDateItem = cJSON_GetObjectItem(item, "startDate")) {
+      if (cJSON_IsString(startDateItem) && startDateItem->valuestring) {
+        sportData.start_date = startDateItem->valuestring;
+      } else {
+        isValid = false;
+        missingFields += "startDate ";
+      }
+    } else {
       isValid = false;
+      missingFields += "startDate ";
+    }
 
-    if (cJSON *startTimeItem = cJSON_GetObjectItem(item, "startTime");
-        startTimeItem && cJSON_IsString(startTimeItem))
-      sportData.start_time = startTimeItem->valuestring;
-    else
+    // 解析startTime字段
+    if (cJSON *startTimeItem = cJSON_GetObjectItem(item, "startTime")) {
+      if (cJSON_IsString(startTimeItem) && startTimeItem->valuestring) {
+        sportData.start_time = startTimeItem->valuestring;
+      } else {
+        isValid = false;
+        missingFields += "startTime ";
+      }
+    } else {
       isValid = false;
+      missingFields += "startTime ";
+    }
 
-    if (cJSON *endTimeItem = cJSON_GetObjectItem(item, "endTime");
-        endTimeItem && cJSON_IsString(endTimeItem))
-      sportData.end_time = endTimeItem->valuestring;
-    else
+    // 解析endTime字段
+    if (cJSON *endTimeItem = cJSON_GetObjectItem(item, "endTime")) {
+      if (cJSON_IsString(endTimeItem) && endTimeItem->valuestring) {
+        sportData.end_time = endTimeItem->valuestring;
+      } else {
+        isValid = false;
+        missingFields += "endTime ";
+      }
+    } else {
       isValid = false;
+      missingFields += "endTime ";
+    }
 
-    if (cJSON *goalDegreeItem = cJSON_GetObjectItem(item, "goalDegree");
-        goalDegreeItem && cJSON_IsNumber(goalDegreeItem))
-      sportData.goaldegree = goalDegreeItem->valueint;
-    else
+    // 解析goalDegree字段
+    if (cJSON *goalDegreeItem = cJSON_GetObjectItem(item, "goalDegree")) {
+      if (cJSON_IsNumber(goalDegreeItem)) {
+        sportData.goaldegree = goalDegreeItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "goalDegree ";
+      }
+    } else {
       isValid = false;
+      missingFields += "goalDegree ";
+    }
 
-    if (cJSON *durationItem = cJSON_GetObjectItem(item, "duration");
-        durationItem && cJSON_IsNumber(durationItem))
-      sportData.duration = durationItem->valueint;
-    else
+    // 解析duration字段
+    if (cJSON *durationItem = cJSON_GetObjectItem(item, "duration")) {
+      if (cJSON_IsNumber(durationItem)) {
+        sportData.duration = durationItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "duration ";
+      }
+    } else {
       isValid = false;
+      missingFields += "duration ";
+    }
 
-    if (cJSON *distanceItem = cJSON_GetObjectItem(item, "distance");
-        distanceItem && cJSON_IsNumber(distanceItem))
-      sportData.distance = distanceItem->valueint;
-    else
+    // 解析distance字段
+    if (cJSON *distanceItem = cJSON_GetObjectItem(item, "distance")) {
+      if (cJSON_IsNumber(distanceItem)) {
+        sportData.distance = distanceItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "distance ";
+      }
+    } else {
       isValid = false;
+      missingFields += "distance ";
+    }
 
-    if (cJSON *avgHeartRateItem = cJSON_GetObjectItem(item, "avgHeartRate");
-        avgHeartRateItem && cJSON_IsNumber(avgHeartRateItem))
-      sportData.avgheart = avgHeartRateItem->valueint;
-    else
+    // 解析avgHeartRate字段
+    if (cJSON *avgHeartRateItem = cJSON_GetObjectItem(item, "avgHeartRate")) {
+      if (cJSON_IsNumber(avgHeartRateItem)) {
+        sportData.avgheart = avgHeartRateItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "avgHeartRate ";
+      }
+    } else {
       isValid = false;
+      missingFields += "avgHeartRate ";
+    }
 
-    if (cJSON *stepsItem = cJSON_GetObjectItem(item, "steps");
-        stepsItem && cJSON_IsNumber(stepsItem))
-      sportData.steps = stepsItem->valueint;
-    else
+    // 解析steps字段
+    if (cJSON *stepsItem = cJSON_GetObjectItem(item, "steps")) {
+      if (cJSON_IsNumber(stepsItem)) {
+        sportData.steps = stepsItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "steps ";
+      }
+    } else {
       isValid = false;
+      missingFields += "steps ";
+    }
 
-    if (cJSON *intensityItem = cJSON_GetObjectItem(item, "intensity");
-        intensityItem && cJSON_IsNumber(intensityItem))
-      sportData.intensity = intensityItem->valueint;
-    else
+    // 解析intensity字段
+    if (cJSON *intensityItem = cJSON_GetObjectItem(item, "intensity")) {
+      if (cJSON_IsNumber(intensityItem)) {
+        sportData.intensity = intensityItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "intensity ";
+      }
+    } else {
       isValid = false;
+      missingFields += "intensity ";
+    }
 
-    if (cJSON *apcItem = cJSON_GetObjectItem(item, "apc");
-        apcItem && cJSON_IsNumber(apcItem))
-      sportData.apc = apcItem->valueint;
-    else
+    // 解析apc字段
+    if (cJSON *apcItem = cJSON_GetObjectItem(item, "apc")) {
+      if (cJSON_IsNumber(apcItem)) {
+        sportData.apc = apcItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "apc ";
+      }
+    } else {
       isValid = false;
+      missingFields += "apc ";
+    }
 
-    if (cJSON *cdcItem = cJSON_GetObjectItem(item, "cdc");
-        cdcItem && cJSON_IsNumber(cdcItem))
-      sportData.cdc = cdcItem->valueint;
-    else
+    // 解析cdc字段
+    if (cJSON *cdcItem = cJSON_GetObjectItem(item, "cdc")) {
+      if (cJSON_IsNumber(cdcItem)) {
+        sportData.cdc = cdcItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "cdc ";
+      }
+    } else {
       isValid = false;
+      missingFields += "cdc ";
+    }
 
-    if (cJSON *stdItem = cJSON_GetObjectItem(item, "std");
-        stdItem && cJSON_IsNumber(stdItem))
-      sportData.std = stdItem->valueint;
-    else
+    // 解析std字段
+    if (cJSON *stdItem = cJSON_GetObjectItem(item, "std")) {
+      if (cJSON_IsNumber(stdItem)) {
+        sportData.std = stdItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "std ";
+      }
+    } else {
       isValid = false;
+      missingFields += "std ";
+    }
 
-    if (cJSON *caloriesItem = cJSON_GetObjectItem(item, "calories");
-        caloriesItem && cJSON_IsNumber(caloriesItem))
-      sportData.calories = caloriesItem->valueint;
-    else
+    // 解析calories字段
+    if (cJSON *caloriesItem = cJSON_GetObjectItem(item, "calories")) {
+      if (cJSON_IsNumber(caloriesItem)) {
+        sportData.calories = caloriesItem->valueint;
+      } else {
+        isValid = false;
+        missingFields += "calories ";
+      }
+    } else {
       isValid = false;
+      missingFields += "calories ";
+    }
 
-    // 只有在所有字段都有效的情况下才添加 sportData 到向量中
+    // 解析starttime字段(时间戳)
+    if (cJSON *starttimeItem = cJSON_GetObjectItem(item, "start_time")) {
+      WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Found starttime field. Type: %d",
+                    starttimeItem->type);
+      if (cJSON_IsNumber(starttimeItem)) {
+        sportData.starttime = starttimeItem->valueint;
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Parsed starttime: %d",
+                      sportData.starttime);
+      } else {
+        // 打印详细信息,帮助定位问题
+        const char *valueStr =
+            starttimeItem->valuestring ? starttimeItem->valuestring : "null";
+        WEARABLE_LOGE(
+            WEARABLE_LOG_MODULE_APP,
+            "Invalid starttime type. Expected number, got type %d (value: %s)",
+            starttimeItem->type, valueStr);
+        isValid = false;
+      }
+    } else {
+      WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Missing starttime field");
+      isValid = false;
+    }
+
+    // 处理解析结果
     if (isValid) {
       sportDataVector.push_back(sportData);
+      WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Successfully parsed item %d", i);
     } else {
-      WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid data in item %d", i);
+      WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+                    "Invalid data in item %d. Missing fields: %s", i,
+                    missingFields.c_str());
     }
   }
 
   cJSON_Delete(root);
-  WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "LoadDataFormJson is ok");
+
+  // 检查是否成功解析了任何数据
+  if (sportDataVector.empty()) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "No valid data items found in JSON");
+    return false;
+  }
+
+  WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP,
+                "Successfully loaded %zu valid data items",
+                sportDataVector.size());
   return true;
 }
 
@@ -2445,20 +2629,114 @@ void TraingModel::AddGPSData(uint32_t timestamp, double latitude,
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid GPS data");
     return;
   }
+  // 校验时间戳是不是重复 比较最后一个?
+  if (gpsData.size() > 0 && timestamp <= gpsData.back().timestamp) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timestamp is not increasing");
+    return;
+  }
   // 添加数据
-  gpsData.push_back({latitude, longitude});
+  gpsData.push_back({timestamp, latitude, longitude});
 }
 
-// //保存
-//   bool SaveCanvasData()
-//   {
+//保存gps数据
+bool TraingModel::SaveCanvasData() {
 
-//   }
+  //打印一下gps的数据
+  for (const auto &point : gpsData) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+                  "GPS Data: Latitude = %f, Longitude = %f", point.latitude,
+                  point.longitude);
+  }
 
-//   void ClearCanvasData()
+  if (canvasData.size() == 0) {
+    WEARABLE_LOGE(WEARING_LOG_MODULE_APP, "canvasData is empty");
+    return false;
+  }
+
+  CreateDirectoryIfNotExists(TRAINING_GPS_FILE);
 
-//   std::string GetGPSDataPath(uint32_t timestamp)
+  WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "canvasData.size() = %zu",
+                canvasData.size());
+
+  std::string filePath =
+      TRAINING_GPS_FILE + std::to_string(sportdata->starttime) + ".bin";
+  WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveCanvasData filePath: %s",
+                filePath.c_str());
 
+  std::ofstream gpsFile(filePath, std::ios::binary);
+  if (!gpsFile) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "无法打开文件: %s",
+                  filePath.c_str());
+    return false; // 返回失败
+  }
+  // 写入gps数据
+  if (!gpsFile.write(reinterpret_cast<const char *>(canvasData.data()),
+                     canvasData.size() * sizeof(Point))) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "写入GPS数据失败。");
+    return false; // 返回失败
+  }
+
+  gpsFile.close();
+  WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SaveGPSData Success.");
+  return true; // 返回成功
+}
+void TraingModel::ClearCanvasData() { canvasData.clear(); }
+
+std::string TraingModel::GetGPSDataPath(uint32_t timestamp) {
+  // 首先检查完全匹配的时间戳
+  std::string exactFilePath =
+      TRAINING_GPS_FILE + std::to_string(timestamp) + ".bin";
+  WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "gps表: %s", exactFilePath.c_str());
+  if (IsFileAccessibleAndNotEmpty(exactFilePath)) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "找到gps表: %s",
+                  exactFilePath.c_str());
+    return exactFilePath; // 返回完全匹配的文件路径
+  }
+
+  // 如果未找到,检查时间戳相差1到2秒的文件
+  for (int i = -2; i <= 2; ++i) {
+    uint32_t checkTimestamp = timestamp + i;
+    std::string filePath =
+        TRAINING_GPS_FILE + std::to_string(checkTimestamp) + ".bin";
+    if (IsFileAccessibleAndNotEmpty(filePath)) {
+      WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "找到gps表: %s", filePath.c_str());
+      return filePath; // 返回找到的文件路径
+    }
+  }
+
+  WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "未找到与时间戳相关的找到gps表。");
+  return ""; // 未找到文件
+}
+// 加载GPS数据
+bool TraingModel::LoadGPSData(const std::string &filePath) {
+  std::ifstream gpsFile(filePath, std::ios::binary);
+  if (!gpsFile) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "无法打开文件: %s",
+                  filePath.c_str());
+    return false;
+  }
+
+  // 清空现有数据
+  canvasData.clear();
+
+  // 动态读取数据(假设文件格式允许逐点读取)
+  Point point;
+  while (gpsFile.read(reinterpret_cast<char *>(&point), sizeof(Point))) {
+    canvasData.push_back(point);
+  }
+
+  gpsFile.close();
+
+  if (canvasData.empty()) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "未读取到有效数据: %s",
+                  filePath.c_str());
+    return false;
+  }
+
+  WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "LoadGPSData Success. 加载了 %zu 个点",
+                canvasData.size());
+  return true;
+}
 // 获取轨迹点集
 std::vector<Point> TraingModel::GetCanvasData() const { return canvasData; }
 
@@ -2474,17 +2752,17 @@ void TraingModel::SetGPSConnectState(bool state) {
 }
 //开启gps
 void TraingModel::OpenGPS() {
-  // 开启GPS的代码逻辑
-  #if defined(SUPPORT_GNSS)
+// 开启GPS的代码逻辑
+#if defined(SUPPORT_GNSS)
   gnss_start();
-  #endif
+#endif
 }
 //关闭gps
 void TraingModel::CloseGPS() {
-  // 关闭GPS的代码逻辑
-  #if defined(SUPPORT_GNSS)
+// 关闭GPS的代码逻辑
+#if defined(SUPPORT_GNSS)
   gnss_stop();
-  #endif
+#endif
 }
 //运动心率、gps开启准备
 void TraingModel::start_heart_gps() { OpenGPS(); }
@@ -2503,24 +2781,11 @@ static void Traing_TimerCallbackProc(int data) {
     // TraingModel::GetInstance()->Traing_timer_callback_out();
     // return;
   }
-  #if defined(SUPPORT_GNSS)
-  gps_data_t *gps_data = getGPSGlobaldata();
-  if (gps_data == NULL) {
-    PRINT("gps_data == NULL \n");
-    return;
-  }
-  //判断是否为第一次定位
-  if (gps_data->last_gps_time_ms > 0) {
-    memcpy_s(&send_gps_data, sizeof(gps_data_t), gps_data, sizeof(gps_data_t));
-  }
-  //判断是否定位成功
-  if (send_gps_data.status > 1) {
-    //定位成功
-    TraingModel::GetInstance()->SetGPSConnectState(true);
-  } else {
-    TraingModel::GetInstance()->SetGPSConnectState(false);
-  }
-  #endif
+#if defined(SUPPORT_GNSS)
+
+  TraingModel::GetInstance()->;
+  
+#endif
 }
 /*
  * @brief 回调函数
index e934164..4f61990 100644 (file)
@@ -144,6 +144,8 @@ namespace OHOS
                 // 选择点击按键的历史数据
                 int arraynum = sportDataVector.size() - 1;
                 SportData sportData = sportDataVector[arraynum - index]; // 显示是倒序 id同理
+                //打印日志信息
+                // TraingModel::GetInstance()->printf_data(&sportData);
                 NativeAbility::GetInstance().EnterSlice(VIEW_TRAININGENDDATA);
                 TraingModel::GetInstance()->SetSportdata(&sportData);
                 return true;