修改心率血氧的开启 3305/1 3305/head 3306/target/1
authorCaisking <Casiking@zhihuishixun.com>
Tue, 24 Mar 2026 06:35:43 +0000 (14:35 +0800)
committerCaisking <Casiking@zhihuishixun.com>
Tue, 24 Mar 2026 06:35:43 +0000 (14:35 +0800)
code/sdk/application/wearable/fd272/nativeapp/nativeui/bloodoxygen/include/BloodOxygenModel.h
code/sdk/application/wearable/fd272/nativeapp/nativeui/bloodoxygen/src/BloodDetectionPresenter.cpp
code/sdk/application/wearable/fd272/nativeapp/nativeui/bloodoxygen/src/BloodOxygenModel.cpp
code/sdk/application/wearable/fd272/nativeapp/nativeui/heartrate/include/HeartModel.h
code/sdk/application/wearable/fd272/nativeapp/nativeui/heartrate/src/HeartModel.cpp
code/sdk/application/wearable/fd272/nativeapp/nativeui/traing/src/TraingModel.cpp

index 2558f89..6eebd5c 100644 (file)
@@ -58,6 +58,8 @@ namespace OHOS
         void Blood_Result(void);
 
         void Blood_Control(BloodState state);
+        void Blood_Switch(bool enable);
+        void SwitchPpgSpo2Sensor(bool enable);
         void ClearDisplayData();
         void CleanAllData();
 
index ee0910a..0853c8b 100644 (file)
@@ -36,7 +36,7 @@ namespace OHOS
 
         if (!BloodCheckState)
         {
-            BloodOxygenModel::GetInstance()->Blood_Start();
+            BloodOxygenModel::GetInstance()->Blood_Switch(true);
             BloodCheckState = true;
         }
     }
@@ -49,7 +49,7 @@ namespace OHOS
 
         if (BloodCheckState)
         {
-            BloodOxygenModel::GetInstance()->Blood_Stop();
+            BloodOxygenModel::GetInstance()->Blood_Switch(false);
             BloodCheckState = false;
         }
     }
index cb15e40..eab51e0 100644 (file)
 #define BLOOD_TIMER_DATA 1
 
 namespace OHOS {
+static osTimerId_t g_delayed_blood_stop_timer = nullptr;
+static uint32_t g_blood_stop_request_token = 0;
+static uint32_t g_blood_stop_execute_token = 0;
+
+static void blood_delayed_stop_timer_callback(void *arg) {
+  (void)arg;
+  if (g_blood_stop_execute_token != g_blood_stop_request_token) {
+    return;
+  }
+  ppg_spo2_stop();
+}
 /**
  * @brief Constructor for the BloodOxygenModel class.
  */
@@ -64,10 +75,8 @@ void BloodOxygenModel::ClearDisplayData() {
 void BloodOxygenModel::Blood_Control(BloodState state) {
   if (state == BloodState::End && startspo2 == true) {
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "startspo2 End");
-#ifdef SUPPORT_PPG_SERVICE
-    ppg_spo2_stop();
-    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ppg_spo2_stop");
-#endif
+    SwitchPpgSpo2Sensor(false);
+    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ppg_spo2_stop(delayed)");
     startspo2 = false;
 #ifdef SYSTEM_LOG_SERVICE
     uapi_save_runtime_log(RUNTIME_LOG_OXYGEN_MEASURE_END);
@@ -83,10 +92,8 @@ void BloodOxygenModel::Blood_Control(BloodState state) {
       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "充电不能检测");
       return;
     }
-#ifdef SUPPORT_PPG_SERVICE
-    ppg_spo2_start();
+    SwitchPpgSpo2Sensor(true);
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "ppg_spo2_start");
-#endif
     startspo2 = true;
 #ifdef SYSTEM_LOG_SERVICE
     uapi_save_runtime_log(RUNTIME_LOG_OXYGEN_MEASURE);
@@ -95,6 +102,41 @@ void BloodOxygenModel::Blood_Control(BloodState state) {
   }
 }
 
+void BloodOxygenModel::SwitchPpgSpo2Sensor(bool enable) {
+#ifdef SUPPORT_PPG_SERVICE
+  if (enable) {
+    g_blood_stop_request_token++;
+    if (g_delayed_blood_stop_timer != nullptr) {
+      osTimerStop(g_delayed_blood_stop_timer);
+    }
+    ppg_spo2_start();
+    return;
+  }
+  g_blood_stop_request_token++;
+  g_blood_stop_execute_token = g_blood_stop_request_token;
+  if (g_delayed_blood_stop_timer == nullptr) {
+    g_delayed_blood_stop_timer =
+        osTimerNew((osTimerFunc_t)blood_delayed_stop_timer_callback, osTimerOnce, nullptr, nullptr);
+  }
+  if (g_delayed_blood_stop_timer != nullptr) {
+    osTimerStop(g_delayed_blood_stop_timer);
+    osTimerStart(g_delayed_blood_stop_timer, osMs2Tick(3 * 1000));
+  } else {
+    ppg_spo2_stop();
+  }
+#else
+  (void)enable;
+#endif
+}
+
+void BloodOxygenModel::Blood_Switch(bool enable) {
+  if (enable) {
+    Blood_Start();
+  } else {
+    Blood_Stop();
+  }
+}
+
 uint16_t BloodOxygenModel::GetSPO2data() { return currentspo2; }
 
 uint16_t BloodOxygenModel::GetShowSPO2data() { return displayspo2; }
index e5393ee..bdd0d5c 100644 (file)
@@ -143,6 +143,7 @@ public:
   void Heart_Result(void);\r
 \r
   void Heart_Control(HeartState state, HeartCheck check);\r
+  void Heart_Switch(bool enable, HeartCheck check, uint32_t stopDelayMs = 0);\r
   void ClearDisplayData();\r
   void Heart_Update_View(void);\r
   void CleanAllData(void);\r
@@ -163,6 +164,7 @@ public:
   void heart_data_timer(uint32_t interval = 1000);\r
   void heart_stop_data_timer();\r
 \r
+  void SwitchPpgHeartSensor(bool enable);\r
 \r
 private:\r
   HealthAllDatas healthDatas;\r
index 3e7f008..5b7926c 100644 (file)
@@ -184,6 +184,47 @@ using namespace OHOS;
 // #endif\r
 \r
 namespace OHOS {\r
+#ifdef SUPPORT_PPG_SERVICE\r
+static osTimerId_t g_delayed_ppg_stop_timer = nullptr;\r
+static uint32_t g_ppg_stop_request_token = 0;\r
+static uint32_t g_ppg_stop_execute_token = 0;\r
+\r
+static void ppg_delayed_stop_timer_callback(void *arg) {\r
+  (void)arg;\r
+  if (g_ppg_stop_execute_token != g_ppg_stop_request_token) {\r
+    return;\r
+  }\r
+  ppg_hr_stop();\r
+}\r
+#endif\r
+\r
+void HeartModel::SwitchPpgHeartSensor(bool enable) {\r
+#ifdef SUPPORT_PPG_SERVICE\r
+  if (enable) {\r
+    g_ppg_stop_request_token++;\r
+    if (g_delayed_ppg_stop_timer != nullptr) {\r
+      osTimerStop(g_delayed_ppg_stop_timer);\r
+    }\r
+    ppg_hr_start();\r
+  } else {\r
+    g_ppg_stop_request_token++;\r
+    g_ppg_stop_execute_token = g_ppg_stop_request_token;\r
+    if (g_delayed_ppg_stop_timer == nullptr) {\r
+      g_delayed_ppg_stop_timer =\r
+          osTimerNew((osTimerFunc_t)ppg_delayed_stop_timer_callback, osTimerOnce, nullptr, nullptr);\r
+    }\r
+    if (g_delayed_ppg_stop_timer != nullptr) {\r
+      osTimerStop(g_delayed_ppg_stop_timer);\r
+      osTimerStart(g_delayed_ppg_stop_timer, osMs2Tick(3 * 1000));\r
+    } else {\r
+      ppg_hr_stop();\r
+    }\r
+  }\r
+#else\r
+  (void)enable;\r
+#endif\r
+}\r
+\r
 void HeartModel::ClearHeartData(void) {\r
   pretime = 0;\r
   entryTimes = 0;\r
@@ -433,9 +474,7 @@ void HeartModel::Heart_Control(HeartState state, HeartCheck check) {
     unwear_counter_ = 0;\r
     display_counter_ = 0;\r
     displayheart = 0;\r
-#ifdef SUPPORT_PPG_SERVICE\r
-    ppg_hr_stop();\r
-#endif\r
+    SwitchPpgHeartSensor(false);\r
     heartstate = false;\r
     if (checkstate == HeartCheck::CARDCHECK) {\r
       //重置传感器状态\r
@@ -465,14 +504,12 @@ void HeartModel::Heart_Control(HeartState state, HeartCheck check) {
       return;\r
     }\r
     // 如果处于训练模式,提前返回\r
-    if (uapi_dev_runtime_get_train_status() == 1){\r
+    if (uapi_dev_runtime_get_train_status() == 1 && check != HeartCheck::EXERCISE){\r
       WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "处于训练模式,不进行心率检测");\r
       return;\r
     }\r
     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "HeartState Start");\r
-#ifdef SUPPORT_PPG_SERVICE\r
-    ppg_hr_start();\r
-#endif\r
+    SwitchPpgHeartSensor(true);\r
     heartstate = true;\r
     checkstate = check;\r
 #ifdef SYSTEM_LOG_SERVICE\r
index 5061bc1..21e15a6 100644 (file)
@@ -80,6 +80,7 @@
  #include "NativeAbility.h"
  #include "AppViewIDs.h"
  #include "sport_countdown/CountdownPresenter.h"
+#include "heartrate/include/HeartModel.h"
  
  #if defined(SUPPORT_GNSS)
  #include "NMEA0183.h"
@@ -3225,11 +3226,8 @@ static void gnss_delayed_stop_timer_callback(void *arg) {
 
 //运动心率开启准备
  void TraingModel::start_training_heart() {
-     //开启心率检测
- #ifdef SUPPORT_PPG_SERVICE
-     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "启动心率检测服务");
-     ppg_hr_start();
- #endif
+     // 心率统一通过 HeartModel 接口控制
+     HeartModel::GetInstance()->SwitchPpgHeartSensor(true);
      //提前设置训练状态为1
      uapi_dev_runtime_set_train_status(1);
  }
@@ -3266,11 +3264,8 @@ static void gnss_delayed_stop_timer_callback(void *arg) {
                   "GPS延迟关闭已安排,等待10s确认后再真正关闭");
 #endif
     }
-     //关闭心率检测
- #ifdef SUPPORT_PPG_SERVICE
-     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "关闭心率检测服务");
-     ppg_hr_stop();
- #endif
+     // 心率统一通过 HeartModel 接口控制,延迟 3 秒关闭防抖
+     HeartModel::GetInstance()->SwitchPpgHeartSensor(false);
 
      //设置训练状态为0
      uapi_dev_runtime_set_train_status(0);