增加GPS服务
authorCaisking <Casiking@zhihuishixun.com>
Tue, 1 Jul 2025 09:36:48 +0000 (17:36 +0800)
committerCaisking <Casiking@zhihuishixun.com>
Tue, 1 Jul 2025 09:36:48 +0000 (17:36 +0800)
code/sdk/application/wearable/fd230app/nativeui/traing/include/TraingModel.h
code/sdk/application/wearable/fd230app/nativeui/traing/src/TraingModel.cpp

index 83673f3..14de246 100644 (file)
@@ -250,10 +250,7 @@ struct GPSData {
   double longitude; // 经度
 };
 //画布点位结构体
-struct CanvasPoint {
-  int x;
-  int y;
-};
+
 class TraingModel {
 public:
   TraingModel();
@@ -368,11 +365,23 @@ public:
   //映射经纬度数据集映射画布绘制轨迹坐标集
   void GetPointData();
   //添加经纬度数据集
-  void AddGPSData(double latitude, double longitude);
+  void AddGPSData(uint32_t timestamp, double latitude, double longitude);
+  bool SaveCanvasData();
+  void ClearCanvasData();
+  std::string GetGPSDataPath(uint32_t timestamp);
   //获取轨迹点集
-  std::vector<CanvasPoint> GetCanvasData()const;
+  std::vector<Point> GetCanvasData()const;
   bool GetGPSConnectState();
   void SetGPSConnectState(bool state);
+  void OpenGPS();
+  void CloseGPS();
+  //运动心率、gps开启准备
+  void start_heart_gps();
+  //运动心率、gps关闭
+  void stop_heart_gps();
+  ///////////////////////////////////////////////
+  void Traing_StartTimer(uint32_t interval = 1 * 1000); // 1s定时器
+  void Traing_StopTimer(void);
 
 private:
   TraingModel(const TraingModel &) = delete;
@@ -422,7 +431,7 @@ private:
   ////////////////////GPS数据集配置/////////////////
   double latitude{0};
   double longitude{0};
-  std::vector<CanvasPoint> canvasData; // 轨迹点集
+  std::vector<Point> canvasData; // 轨迹点集
   std::vector<GPSData> gpsData;              // GPS数据集
   bool gpsconnect{false};
 };
index 0196798..83bd9df 100644 (file)
 
 #include "bleService.h"
 #include "chip_system_time.h"
-#include <custom_save_runtime.h>
 #include "cmath"
+#include "system/include/SystemLogModel.h"
+#include <custom_save_runtime.h>
 
-extern "C" errcode_t uapi_get_timestampe_ms(uint32_t *tm);
-extern "C" errcode_t uapi_get_timestampe_ss(uint32_t *tm);
+#if defined(SUPPORT_GNSS)
+#include "NMEA0183.h"
+#include "gnss_ctl.h"
+#include "gnss_sample.h"
+#include "graphic_service.h"
+gps_data_t send_gps_data = {0};
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -138,7 +144,8 @@ static void Training_Notify(void *args, const Topic topic, Request *request) {
     delete traingbleInfo;
   }
   //增加训练runtime控制
-  if (uapi_dev_runtime_get_train_status() == 0 ||  TraingModel::GetInstance()->GetSportState() == ExerciseState::End) {
+  if (uapi_dev_runtime_get_train_status() == 0 ||
+      TraingModel::GetInstance()->GetSportState() == ExerciseState::End) {
     return;
   }
   //训练基本信息更新
@@ -181,6 +188,22 @@ static void Training_Notify(void *args, const Topic topic, Request *request) {
     uint8_t heart = *((u_int8_t *)(request->data)); // 进行类型转换
     TraingModel::GetInstance()->AnalysisHeartData(heart);
   }
+  //训练GPS
+  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()->AddGPSData(send_gps_data.location.lat,
+                                           send_gps_data.location.lng);
+  }
 }
 #ifdef __cplusplus
 }
@@ -562,7 +585,7 @@ void TraingModel::AnalysisExtraData(
   }
   //最快配速
   if (cyweeInfo->max_pace != 0) {
-    sportdata->fpc =cyweeInfo->max_pace;
+    sportdata->fpc = cyweeInfo->max_pace;
   }
   //平均步频
   if (cyweeInfo->avg_step_freq != 0) {
@@ -621,7 +644,7 @@ void TraingModel::SetSportdata(SportData *data) {
     sportdata->spc = data->spc;
     sportdata->std = data->std;
     sportdata->cdc = data->cdc;
-    printf_data(data);//打印该运动数据
+    printf_data(data);                  //打印该运动数据
     IsSpecialSport(sportdata->sportId); // 配置训练特殊性
   }
 }
@@ -658,8 +681,8 @@ void TraingModel::ResetSharedTrainingData() {
 
   shock_count = 0; //重置震动计数
 
-  gpsData.clear();// 清空gps数据
-  canvasData.clear();// 清空画布数据
+  gpsData.clear();    // 清空gps数据
+  canvasData.clear(); // 清空画布数据
 }
 
 uint32_t TraingModel::get_current_time() {
@@ -754,6 +777,9 @@ void TraingModel::SetTimestamp() {
     //配置最后的训练强度(平均心率为标准)
     SetIntensity(sportdata->avgheart);
 
+    //更新gps点位
+    GetPointData();
+
     do_custom_fileoperate_service_check_msg(
         CUSTOM_FILEOPERATE_MSG_TYPE_SPORTDATA_SAVE, nullptr, 0);
 
@@ -2352,7 +2378,7 @@ bool TraingModel::LoadDataFormJson(std::vector<SportData> &sportDataVector) {
 /*
   Latitude(纬度):范围:-90° 至 +90°(或南纬 90° 至北纬 90°);
   Longitude(经度):范围:-180° 至 +180°(或西经 180° 至东经 180°);
-  
+
   -画布数据集最多是100个定位坐标,超过按比例进行拿取100个点位;
   -通过映射关系,将经纬度转换为400*400画布上的坐标;
   -但是不能靠近400,以免显示不全等问题,350*350;
@@ -2360,86 +2386,201 @@ bool TraingModel::LoadDataFormJson(std::vector<SportData> &sportDataVector) {
   -如果有正数又有负数,应该怎么处理?
 */
 
-static double getmin(double a, double b)
-{
-    return a < b ? a : b;
-}
+static double getmin(double a, double b) { return a < b ? a : b; }
 
-static double getmax(double a, double b)
-{
-    return a > b ? a : b;
-}
+static double getmax(double a, double b) { return a > b ? a : b; }
 
 // 通过经纬度数据集映射画布绘制轨迹坐标集
-void TraingModel::GetPointData()
-{
-    // 1. 按比例采样最多100个点位
-    std::vector<GPSData> sampledData;
-    if (gpsData.size() > 100) {
-        double step = static_cast<double>(gpsData.size() - 1) / 99;
-        for (int i = 0; i < 100; i++) {
-            int index = static_cast<int>(i * step);
-            sampledData.push_back(gpsData[index]);
-        }
-    } else {
-        sampledData = gpsData;
+void TraingModel::GetPointData() {
+  // 1. 按比例采样最多100个点位
+  std::vector<GPSData> sampledData;
+  if (gpsData.size() > 100) {
+    double step = static_cast<double>(gpsData.size() - 1) / 99;
+    for (int i = 0; i < 100; i++) {
+      int index = static_cast<int>(i * step);
+      sampledData.push_back(gpsData[index]);
     }
+  } else {
+    sampledData = gpsData;
+  }
 
-    // 2. 计算经纬度的最小值和最大值
-    double minLat = 90.0, maxLat = -90.0;
-    double minLon = 180.0, maxLon = -180.0;
-    for (const auto& point : sampledData) {
-        minLat = getmin(minLat, point.latitude);
-        maxLat = getmax(maxLat, point.latitude);
-        minLon = getmin(minLon, point.longitude);
-        maxLon = getmax(maxLon, point.longitude);
-    }
+  // 2. 计算经纬度的最小值和最大值
+  double minLat = 90.0, maxLat = -90.0;
+  double minLon = 180.0, maxLon = -180.0;
+  for (const auto &point : sampledData) {
+    minLat = getmin(minLat, point.latitude);
+    maxLat = getmax(maxLat, point.latitude);
+    minLon = getmin(minLon, point.longitude);
+    maxLon = getmax(maxLon, point.longitude);
+  }
 
-    // 3. 将经纬度映射到350×350画布区域(居中在400×400画布)
-    canvasData.clear();
-    const double canvasSize = 350.0;
-    const double offset = 25.0;  // 400 - 350 = 50,两边各留25的边距
-    
-    for (const auto& point : sampledData) {
-        // 归一化处理(0-1范围)
-        double normLat = (point.latitude - minLat) / (maxLat - minLat);
-        double normLon = (point.longitude - minLon) / (maxLon - minLon);
-        
-        // 映射到画布坐标(考虑偏移)
-        double x = normLon * canvasSize + offset;
-        double y = (1.0 - normLat) * canvasSize + offset;  // 注意:y轴需要反转(屏幕坐标系向下为正)
-        
-        canvasData.push_back({x, y});
-    }
+  // 3. 将经纬度映射到350×350画布区域(居中在400×400画布)
+  canvasData.clear();
+  const double canvasSize = 300.0;
+  const double offset = 50.0; // 400 - 300 = 100,两边各留50的边距
+
+  for (const auto &point : sampledData) {
+    // 归一化处理(0-1范围)
+    double normLat = (point.latitude - minLat) / (maxLat - minLat);
+    double normLon = (point.longitude - minLon) / (maxLon - minLon);
+
+    // 映射到画布坐标(考虑偏移)
+    double x = normLon * canvasSize + offset;
+    double y = (1.0 - normLat) * canvasSize +
+               offset; // 注意:y轴需要反转(屏幕坐标系向下为正)
+
+    canvasData.push_back({x, y});
+  }
+
+  //修改起点与终点
 }
 
 // 添加经纬度数据集
-void TraingModel::AddGPSData(double latitude, double longitude)
-{
-    // 判断数据是否合理
-    if (latitude < -90 || latitude > 90 || longitude < -180 || longitude > 180) {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid GPS data");
-        return;
-    }
-    // 添加数据
-    gpsData.push_back({latitude, longitude});
+void TraingModel::AddGPSData(uint32_t timestamp, double latitude,
+                             double longitude) {
+  // 判断数据是否合理
+  if (latitude < -90 || latitude > 90 || longitude < -180 || longitude > 180) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Invalid GPS data");
+    return;
+  }
+  // 添加数据
+  gpsData.push_back({latitude, longitude});
 }
 
+// //保存
+//   bool SaveCanvasData()
+//   {
+
+//   }
+
+//   void ClearCanvasData()
+
+//   std::string GetGPSDataPath(uint32_t timestamp)
+
 // 获取轨迹点集
-std::vector<CanvasPoint> TraingModel::GetCanvasData() const
-{
-    return canvasData;
-}
+std::vector<Point> TraingModel::GetCanvasData() const { return canvasData; }
 
 //获取GPS连接状态
-bool TraingModel::GetGPSConnectState()
-{
-    return gpsconnect;
-}
+bool TraingModel::GetGPSConnectState() { return gpsconnect; }
 //设置GPS连接状态
-void TraingModel::SetGPSConnectState(bool state)
-{
+void TraingModel::SetGPSConnectState(bool state) {
+  if (gpsconnect != state) {
     gpsconnect = state;
+    //状态改变记录
+    SystemLogModel::GetInstance()->save_gps_status_log_type(gpsconnect);
+  }
+}
+//开启gps
+void TraingModel::OpenGPS() {
+  // 开启GPS的代码逻辑
+  gnss_start();
+}
+//关闭gps
+void TraingModel::CloseGPS() {
+  // 关闭GPS的代码逻辑
+  gnss_stop();
+}
+//运动心率、gps开启准备
+void TraingModel::start_heart_gps() { OpenGPS(); }
+//运动心率、gps关闭
+void TraingModel::stop_heart_gps() { CloseGPS(); }
+
+/////////////////////////////////////gps定时器/////////////////////////////////////
+static osTimerId_t g_timer = nullptr;
+static int Time = 30;
+/*定时器到期时的处理*/
+static void Traing_TimerCallbackProc(int data) {
+  // 倒计时
+  Time--;
+  // 到时的处理
+  if (Time < 0) {
+    // TraingModel::GetInstance()->Traing_timer_callback_out();
+    // return;
+  }
+  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);
+  }
+}
+/*
+ * @brief 回调函数
+ */
+static void Traing_TimerCallback(int data) {
+  WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Traing_TimerCallback %d", data);
+  GraphicService::GetInstance()->PostGraphicEvent(
+      std::bind(Traing_TimerCallbackProc, data));
+}
+
+/*
+ *  @brief 开启定时器函数
+ *  @param interval 时间间隔,单位ms
+ */
+void TraingModel::Traing_StartTimer(uint32_t interval) {
+  WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "TraingModel::Traing_StartTimer");
+  /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回
+   * ------------------------- */
+  if (g_timer != nullptr) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!");
+    return;
+  }
+
+  /* --------------------------------- 2.创建定时器
+   * -------------------------------- */
+  g_timer = osTimerNew((osTimerFunc_t)Traing_TimerCallback, osTimerPeriodic,
+                       nullptr, nullptr);
+  // 检查定时器创建是否成功
+  if (g_timer == nullptr) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!");
+    return;
+  }
+
+  /* ----------------------------- 3.将毫秒转换为系统时钟节拍数
+   * ---------------------------- */
+  int tick = osMs2Tick(interval);
+
+  /* --------------------------------- 4.启动定时器
+   * -------------------------------- */
+  osStatus_t ret = osTimerStart(g_timer, tick);
+  /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为
+   * nullptr -------------------- */
+  if (ret != osOK) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!",
+                  ret);
+    if (g_timer != nullptr) {
+      ret = osTimerDelete(g_timer);
+    }
+    g_timer = nullptr;
+    return;
+  }
+}
+/*
+ * @brief 停止定时器
+ */
+void TraingModel::Traing_StopTimer(void) {
+  // 检查定时器是否存在
+  if (g_timer != nullptr) {
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "TraingModel::Traing_StopTimer");
+    osTimerStop(g_timer);
+    // 删除定时器并置为 nullptr
+    osStatus_t ret = osTimerDelete(g_timer);
+    if (ret != osOK) {
+      WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,
+                    "osTimerDelete failed, ret = %lx!!", ret);
+    }
+    g_timer = nullptr;
+  }
 }
 
 } // namespace OHOS