产测软件修改
authorxue <2144439972@qq.com>
Mon, 18 May 2026 09:00:18 +0000 (17:00 +0800)
committerxue <2144439972@qq.com>
Mon, 18 May 2026 09:00:18 +0000 (17:00 +0800)
13 files changed:
code/sdk/zhihui/UI/producttest/include/testGPS.h
code/sdk/zhihui/UI/producttest/include/testPresenter.h
code/sdk/zhihui/UI/producttest/include/testPresenterC.h
code/sdk/zhihui/UI/producttest/include/testbt.h
code/sdk/zhihui/UI/producttest/include/testbutton.h
code/sdk/zhihui/UI/producttest/src/testGPS.cpp
code/sdk/zhihui/UI/producttest/src/testPresenter.cpp
code/sdk/zhihui/UI/producttest/src/testbt.cpp
code/sdk/zhihui/UI/producttest/src/testbutton.cpp
code/sdk/zhihui/utils/custom_cmd_service.c
code/sdk/zhihui/utils/custom_utils.c
code/sdk/zhihui/utils/custom_utils.h
code/sdk/zhihui/utils/custom_utils_at_cmd.c

index 5cbc065..6e19977 100644 (file)
@@ -74,6 +74,7 @@ namespace OHOS
         // 按钮状态管理函数
         void SetGPSButtonActive(bool isActive);
         void ToggleGPSState();  // 切换GPS开关状态
+        void SetGPSState(bool isOn); /* 外部 AT/协议同步 GPS 开闭与 UI */
     private:
         UILabelButtonExt *SetTheButton_ext(ButtonConfig_ext_t &buttonconfig);//, UIView::OnTouchListener *clickListener);
         UILabel *InitLabel(LabelConfig &labelConfig);
index ab9aa8a..3f69224 100644 (file)
@@ -107,6 +107,8 @@ namespace OHOS
 \r
         void OnStart() override;\r
 \r
+        void OnResume() override;\r
+\r
         static testPresenter *GetInstance();\r
 \r
         // FactoryTestResult* GetFactoryTestResult() {return &g_factoryTestResult;}\r
index 158522d..abe8b6d 100644 (file)
@@ -4,12 +4,14 @@
  * @LastEditors: penglei 1624952103@qq.com
  * @LastEditTime: 2024-07-02 18:04:51
  * @FilePath: /FD230/code/sdk/application/wearable/fd230/nativeapp/nativeui/producttest/include/testPresenterC.h
- * @Description: 
- * 
- * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved. 
+ * @Description:
+ *
+ * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
  */
-#ifndef TEST_PRESENTER_H
-#define TEST_PRESENTER_H
+#ifndef TEST_PRESENTER_C_H
+#define TEST_PRESENTER_C_H
+
+#include <stdint.h>
 
 #ifdef __cplusplus
 #if __cplusplus
@@ -20,7 +22,20 @@ extern "C"
     void factorytest_enter_test_tp_view(void);
     void factorytest_enter_test_lcd_view(void);
     void factorytest_enter_test_button_view(void);
-    
+    void factorytest_enter_test_luminance_view(void);
+    void factorytest_enter_test_charging_view(void);
+    void factorytest_enter_test_motor_view(void);
+    void factorytest_enter_test_hr_view(void);
+    void factorytest_enter_test_gsensor_view(void);
+    void factorytest_enter_test_bt_view(void);
+    void factorytest_enter_test_sechip_view(void);
+    void factorytest_enter_test_gps_view(void);
+    void factorytest_jump_to_subview(const char *item);
+    void factorytest_jump_to_subview_id(int16_t target);
+    void factorytest_set_gps_button_state(int on);
+    void factorytest_trigger_leaklight_ui(void);
+    void factorytest_set_bt_discovery_active(int active);
+    void factorytest_deepsleep_enter(void);
 #ifdef __cplusplus
 #if __cplusplus
 }
index 293f629..b58d8d6 100644 (file)
@@ -65,6 +65,7 @@ namespace OHOS
         void set_BR_connect(char *);
         bool  br_scan_set_text(unsigned char *name ,unsigned char *addr,int16_t rssi,int i);
         UILabelButtonExt* button{NULL};
+        void SetDiscoveryActive(bool active);
 
     private:
         UILabelButtonExt *SetTheButton_ext(ButtonConfig_ext_t &buttonconfig);//, UIView::OnTouchListener *clickListener);
index 284e5f7..4e52701 100644 (file)
@@ -45,6 +45,10 @@ namespace OHOS
         
 
         UIScrollView *testBUTTONInitIView(uint8_t);
+        UIScrollView *GetTestBUTTONScrollView(void)
+        {
+            return testBUTTONScrollView;
+        }
         void ClearAll(void);
     private:
         UILabelButtonExt *SetTheButton_ext(ButtonConfig_ext_t &buttonconfig);//, UIView::OnTouchListener *clickListener);
index 45698c6..b6881d8 100644 (file)
@@ -143,6 +143,21 @@ namespace OHOS
         return button;
     }
     
+    void testGPSView::SetGPSState(bool isOn)
+    {
+        gpsIsOn = isOn;
+        SetGPSButtonActive(gpsIsOn);
+        if (gpsIsOn) {
+            if (getPGnssServerStat() != 1) {
+                gnss_start();
+            }
+        } else {
+            if (getPGnssServerStat() != 0) {
+                gnss_stop();
+            }
+        }
+    }
+
     void testGPSView::SetGPSButtonActive(bool isActive)
     {
         if (GPSbutton[0] != nullptr)
index dca3ba7..f06c0c4 100644 (file)
@@ -8,7 +8,9 @@
 #include "NativeAbility.h"
 #include "graphic_math.h"
 #include "string.h"
+#include <strings.h>
 #include "producttest/include/testPresenter.h"
+#include "producttest/include/testbutton.h"
 // #include "font/font_global_manager.h"
 // #include "font/ui_font.h"
 #ifdef CUSTOM_ZHIHUI
@@ -76,6 +78,7 @@ namespace OHOS
 
     // 当前Presenter属性实例化的内存指针
     static testPresenter *g_pSystemPresenter = nullptr;
+    static int16_t g_pendingJumpSubView = -1; /* TEST_VIEW enum value, -1 = none */
 
     testPresenter::testPresenter()
     {
@@ -88,6 +91,7 @@ namespace OHOS
     {
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "testPresenter::~testPresenter");
         g_pSystemPresenter = nullptr;
+        g_pendingJumpSubView = -1;
     }
 
     testPresenter *testPresenter::GetInstance()
@@ -100,6 +104,35 @@ namespace OHOS
     {
     }
 
+    void testPresenter::OnResume()
+    {
+        testView *tv = testView::GetInstance();
+        if (g_pendingJumpSubView >= 0 && tv != nullptr && view_ != nullptr) {
+            tv->ChangeView(TESTVIEW, g_pendingJumpSubView);
+            g_pendingJumpSubView = -1;
+        }
+
+        if (view_ == nullptr || tv == nullptr) {
+            return;
+        }
+        if (view_->GetSystemScrollView(BUTTON) == nullptr) {
+            return;
+        }
+        testbuttonView *btn = testbuttonView::GetInstance();
+        if (btn == nullptr) {
+            return;
+        }
+        UIScrollView *btnScroll = btn->GetTestBUTTONScrollView();
+        if (btnScroll == nullptr) {
+            return;
+        }
+        RootView *root = RootView::GetInstance();
+        if (root != nullptr) {
+            root->SetOnKeyActListener(this);
+        }
+        btnScroll->RequestFocus();
+    }
+
     bool testPresenter::OnPress(UIView &view, const PressEvent &event)
     {
         return true;
@@ -564,6 +597,171 @@ extern "C"
         testView::GetInstance()->ChangeView(TESTVIEW,BUTTON);
     }
 
+    void factorytest_enter_test_luminance_view(void)
+    {
+        if (testView::GetInstance()) {
+            testView::GetInstance()->ChangeView(TESTVIEW, LUMINANCE);
+        }
+    }
+
+    void factorytest_enter_test_charging_view(void)
+    {
+        if (testView::GetInstance()) {
+            testView::GetInstance()->ChangeView(TESTVIEW, CHARG);
+        }
+    }
+
+    void factorytest_enter_test_motor_view(void)
+    {
+        if (testView::GetInstance()) {
+            testView::GetInstance()->ChangeView(TESTVIEW, MOTOR);
+        }
+    }
+
+    void factorytest_enter_test_hr_view(void)
+    {
+        if (testView::GetInstance()) {
+            testView::GetInstance()->ChangeView(TESTVIEW, HRSENSON);
+        }
+    }
+
+    void factorytest_enter_test_gsensor_view(void)
+    {
+        if (testView::GetInstance()) {
+            testView::GetInstance()->ChangeView(TESTVIEW, GSENSON);
+        }
+    }
+
+    void factorytest_enter_test_bt_view(void)
+    {
+        if (testView::GetInstance()) {
+            testView::GetInstance()->ChangeView(TESTVIEW, BTTEST);
+        }
+    }
+
+    void factorytest_enter_test_sechip_view(void)
+    {
+        if (testView::GetInstance()) {
+            testView::GetInstance()->ChangeView(TESTVIEW, SEChipTest);
+        }
+    }
+
+    void factorytest_enter_test_gps_view(void)
+    {
+#if defined(SUPPORT_GNSS)
+        if (testView::GetInstance()) {
+            testView::GetInstance()->ChangeView(TESTVIEW, GPSTEST);
+        }
+#endif
+    }
+
+    void factorytest_jump_to_subview_id(int16_t target)
+    {
+        if (target < 0) {
+            return;
+        }
+        if (testView::GetInstance()) {
+            testView::GetInstance()->ChangeView(TESTVIEW, target);
+        } else {
+            g_pendingJumpSubView = target;
+        }
+    }
+
+    void factorytest_jump_to_subview(const char *item)
+    {
+        if (item == nullptr) {
+            return;
+        }
+
+        int16_t target = -1;
+        if (strcasecmp(item, "TP") == 0) {
+            target = TP;
+        } else if (strcasecmp(item, "BRIGHT") == 0) {
+            target = LUMINANCE;
+        } else if (strcasecmp(item, "CHARGE") == 0) {
+            target = CHARG;
+        } else if (strcasecmp(item, "MOTOR") == 0) {
+            target = MOTOR;
+        } else if (strcasecmp(item, "KEY") == 0) {
+            target = BUTTON;
+        } else if (strcasecmp(item, "BUTTON") == 0) {
+            target = BUTTON;
+        } else if (strcasecmp(item, "LCD") == 0) {
+            target = LCD;
+        } else if (strcasecmp(item, "LEAKLIGHT") == 0) {
+            target = HRSENSON;
+        } else if (strcasecmp(item, "GSENSOR") == 0) {
+            target = GSENSON;
+        } else if (strcasecmp(item, "BT") == 0) {
+            target = BTTEST;
+        } else if (strcasecmp(item, "SE") == 0) {
+            target = SEChipTest;
+        } else if (strcasecmp(item, "GPS") == 0) {
+#if defined(SUPPORT_GNSS)
+            target = GPSTEST;
+#endif
+        } else if (strcasecmp(item, "DEEPSLEEP") == 0) {
+            target = DEEPSLEEP;
+        }
+
+        if (target < 0) {
+            return;
+        }
+
+        factorytest_jump_to_subview_id(target);
+    }
+
+    void factorytest_set_gps_button_state(int on)
+    {
+#if defined(SUPPORT_GNSS)
+        testGPSView *gpsView = testGPSView::GetInstance();
+        if (gpsView != nullptr) {
+            gpsView->SetGPSState(on ? true : false);
+        }
+#else
+        (void)on;
+#endif
+    }
+
+    void factorytest_trigger_leaklight_ui(void)
+    {
+#if defined(SUPPORT_PPG_SERVICE)
+        testhrsenson1View *hrView = testhrsenson1View::GetInstance();
+        if (hrView != nullptr) {
+            hrView->setlightvalue();
+        }
+#endif
+    }
+
+    void factorytest_set_bt_discovery_active(int active)
+    {
+        testBTView *btView = testBTView::GetInstance();
+        if (btView != nullptr) {
+            btView->SetDiscoveryActive(active ? true : false);
+        }
+    }
+
+    void factorytest_deepsleep_enter(void)
+    {
+#ifdef SUPPORT_CYWEE_SERVICE
+        do_cywee_service_check_msg(CYWEE_SERVICE_CMD_STOP_ACC, NULL);
+#endif
+        stop_custom_ble_service();
+        LOS_Msleep(50);
+        uapi_set4GCapability(false);
+        LOS_Msleep(50);
+
+        uint8_t cnt = pm_veto_get_id_cnt(PM_ID_P_TEST);
+        if (cnt == 1) {
+            uapi_pm_remove_sleep_veto(PM_ID_P_TEST);
+        }
+
+        const power_display_svr_api_t *display_api = power_display_svr_get_api();
+        if (display_api != nullptr) {
+            display_api->turn_off_screen();
+        }
+    }
+
 #ifdef __cplusplus
 #if __cplusplus
 }
index aca5825..d22efbd 100644 (file)
@@ -166,6 +166,21 @@ namespace OHOS
    
     static bool discovery_falg=false;
    
+    void testBTView::SetDiscoveryActive(bool active)
+    {
+        discovery_falg = active;
+        if (button != nullptr) {
+            if (active) {
+                button->SetText("扫描中");
+                button->SetStyle(STYLE_BACKGROUND_COLOR, Color::Green().full);
+            } else {
+                button->SetText("发现");
+                button->SetStyle(STYLE_BACKGROUND_COLOR, Color::Blue().full);
+            }
+            RootView::GetInstance()->Invalidate();
+        }
+    }
+
     void testBTView:: BT_discovery_callback( void)
     {
         
index cdb0b89..58d41ab 100644 (file)
@@ -35,7 +35,7 @@ namespace OHOS
     {
         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "testbuttonView::~testbuttonView");
         ClearAll();
-       // g_pSystemAboutTheWatchView = nullptr;
+        g_pSystemAboutTheWatchView = nullptr;
     }
 
     testbuttonView *testbuttonView::GetInstance()
index 9857e8e..c8ae579 100644 (file)
@@ -314,6 +314,25 @@ static void custom_cmd_service_check_task(void const *arg)
             {
                 uapi_factorytest_enter_test_view(0);
             }
+#endif
+            break;
+        case CUSTOM_CMD_MSG_TYPE_PRODUCTTEST_JUMP:
+#ifdef SUPPORT_FACTORY_SERVICE
+            switch (mail.data[0]) {
+                case 1: uapi_factorytest_jump_to_subview("TP"); break;
+                case 2: uapi_factorytest_jump_to_subview("BRIGHT"); break;
+                case 3: uapi_factorytest_jump_to_subview("CHARGE"); break;
+                case 4: uapi_factorytest_jump_to_subview("MOTOR"); break;
+                case 5: uapi_factorytest_jump_to_subview("KEY"); break;
+                case 6: uapi_factorytest_jump_to_subview("LEAKLIGHT"); break;
+                case 7: uapi_factorytest_jump_to_subview("GSENSOR"); break;
+                case 8: uapi_factorytest_jump_to_subview("BT"); break;
+                case 9: uapi_factorytest_jump_to_subview("SE"); break;
+                case 10: uapi_factorytest_jump_to_subview("GPS"); break;
+                case 11: uapi_factorytest_jump_to_subview("LCD"); break;
+                case 12: uapi_factorytest_jump_to_subview("DEEPSLEEP"); break;
+                default: break;
+            }
 #endif
             break;
         case CUSTOM_CMD_MSG_TYPE_VIBRATOR_TEST:
index b2fe8f0..d7280ed 100644 (file)
@@ -3158,6 +3158,112 @@ void uapi_factorytest_hide_test_tp_button(void)
     #endif
 }
 
+void uapi_factorytest_enter_test_luminance_view(void)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_enter_test_luminance_view();
+#endif
+}
+
+void uapi_factorytest_enter_test_charging_view(void)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_enter_test_charging_view();
+#endif
+}
+
+void uapi_factorytest_enter_test_motor_view(void)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_enter_test_motor_view();
+#endif
+}
+
+void uapi_factorytest_enter_test_hr_view(void)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_enter_test_hr_view();
+#endif
+}
+
+void uapi_factorytest_enter_test_gsensor_view(void)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_enter_test_gsensor_view();
+#endif
+}
+
+void uapi_factorytest_enter_test_bt_view(void)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_enter_test_bt_view();
+#endif
+}
+
+void uapi_factorytest_enter_test_sechip_view(void)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_enter_test_sechip_view();
+#endif
+}
+
+void uapi_factorytest_enter_test_gps_view(void)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_enter_test_gps_view();
+#endif
+}
+
+void uapi_factorytest_jump_to_subview(const char *item)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_jump_to_subview(item);
+#else
+    (void)item;
+#endif
+}
+
+void uapi_factorytest_jump_to_subview_id(int16_t target)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_jump_to_subview_id(target);
+#else
+    (void)target;
+#endif
+}
+
+void uapi_factorytest_set_gps_button_state(int on)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_set_gps_button_state(on);
+#else
+    (void)on;
+#endif
+}
+
+void uapi_factorytest_trigger_leaklight_ui(void)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_trigger_leaklight_ui();
+#endif
+}
+
+void uapi_factorytest_set_bt_discovery_active(int active)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_set_bt_discovery_active(active);
+#else
+    (void)active;
+#endif
+}
+
+void uapi_factorytest_deepsleep_enter(void)
+{
+#ifdef CUSTOM_ZHIHUI
+    factorytest_deepsleep_enter();
+#endif
+}
+
 void uapi_efuse_test_write(uint8_t *data,uint32_t byte_number,uint8_t len)
 {
     uint8_t readdata[10] = {0};
index 5fbec6b..0a51b48 100644 (file)
@@ -18,6 +18,7 @@ extern "C" {
 #include <errcode.h>
 #include "thread_init.h"
 #include "pdu.h"
+#include <stdint.h>
 
 #ifdef  SINGLE_USER_PARTITION
 #define EXC_TAR_PATH "/user/log"
@@ -268,6 +269,9 @@ uint32_t uapi_calendar_store_date(void);
 
 #define CUSTOM_CMD_MSG_TYPE_CAT1_RESTART 0x2D
 
+/** 产测子界面跳转(与 AT^TESTJUMP 对应,payload 1 字节子项编码) */
+#define CUSTOM_CMD_MSG_TYPE_PRODUCTTEST_JUMP 0x2E
+
 typedef enum {
     BR_HFP_CONNECT=1,
     BR_HFP_DISCONNECT,
@@ -368,6 +372,20 @@ void uapi_factorytest_enter_test_view(int cmd);
 void uapi_factorytest_enter_test_tp_view(void);
 void uapi_factorytest_enter_test_lcd_view(void);
 void uapi_factorytest_enter_test_button_view(void);
+void uapi_factorytest_enter_test_luminance_view(void);
+void uapi_factorytest_enter_test_charging_view(void);
+void uapi_factorytest_enter_test_motor_view(void);
+void uapi_factorytest_enter_test_hr_view(void);
+void uapi_factorytest_enter_test_gsensor_view(void);
+void uapi_factorytest_enter_test_bt_view(void);
+void uapi_factorytest_enter_test_sechip_view(void);
+void uapi_factorytest_enter_test_gps_view(void);
+void uapi_factorytest_jump_to_subview(const char *item);
+void uapi_factorytest_jump_to_subview_id(int16_t target);
+void uapi_factorytest_set_gps_button_state(int on);
+void uapi_factorytest_trigger_leaklight_ui(void);
+void uapi_factorytest_set_bt_discovery_active(int active);
+void uapi_factorytest_deepsleep_enter(void);
 void uapi_factorytest_hide_test_lcd_button(void);
 void uapi_factorytest_hide_test_tp_button(void);
 void uapi_efuse_test_write(uint8_t *data,uint32_t byte_number,uint8_t len);
index cdc203b..65285ec 100644 (file)
@@ -49,6 +49,7 @@
 #endif
 
 #ifdef SUPPORT_PPG_SERVICE
+#include "ppg_service.h"
 #include "ppg_hal.h"
 #endif
 
 #include "common.h"
 #include "broadcast_feature.h"
 #include "custom_save_runtime.h"
+#include <strings.h>
+#include "cmsis_os2.h"
+#ifdef SUPPORT_GNSS
+#include "gnss_ctl.h"
+#include "NMEA0183.h"
+#include "pgnss_sample.h"
+#endif
 
 static int ConvertCmdToParam(uint8_t *para, uint32_t paraLen,
         uint8_t argv[CUSTOM_UTILS_MAX_ARGC][CUSTOM_UTILS_MAX_ARGV_LEN], uint32_t* argc)
@@ -173,9 +181,9 @@ static uint32_t lcd_test_control(uint8_t *para, uint32_t paraLen, char *strCommo
         do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_TYPE_LCD_TEST, &lcd_cmd, sizeof(lcd_cmd));
         wstp_print("LCDTEST ATCMD Enter LCD test interface\n");
 
-        for(int i = 1; i < 6; i++)
+        for(int i = 1; i < 4; i++)
         {
-            LOS_Msleep(2000);
+            LOS_Msleep(800);
             do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_TYPE_LCD_COLOR_TEST, &i, 1);
         }
 #endif
@@ -1036,6 +1044,329 @@ static uint32_t custom_get_imei(uint8_t *para, uint32_t paraLen, char *strCommon
     return ERRCODE_SUCC;
 }
 
+/* 进入指定产测子界面 */
+static uint32_t custom_producttest_jump(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    uint8_t argv[CUSTOM_UTILS_MAX_ARGC][CUSTOM_UTILS_MAX_ARGV_LEN] = { 0 };
+    uint32_t argc = 0;
+
+    int ret = ConvertCmdToParam(para, paraLen, argv, &argc);
+    if (ret != CUSTOM_UTILS_SUCCESS) {
+        wstp_print("TESTJUMP ATCMD Convert Command Failed\r\n");
+        return ERRCODE_FAIL;
+    }
+
+    if (argc != 1 || strcmp((char*)argv[0], "?") == 0) {
+        wstp_print("Usage: AT^TESTJUMP=<item>\r\n");
+        wstp_print("  item: TP|LCD|BRIGHT|CHARGE|MOTOR|KEY|BUTTON|LEAKLIGHT|GSENSOR|BT|SE|GPS|DEEPSLEEP\r\n");
+        return ERRCODE_SUCC;
+    }
+
+    const char *item = (const char*)argv[0];
+    uint8_t code = 0xFF;
+    if (strcasecmp(item, "TP") == 0) {
+        code = 1;
+    } else if (strcasecmp(item, "BRIGHT") == 0) {
+        code = 2;
+    } else if (strcasecmp(item, "CHARGE") == 0) {
+        code = 3;
+    } else if (strcasecmp(item, "MOTOR") == 0) {
+        code = 4;
+    } else if (strcasecmp(item, "KEY") == 0) {
+        code = 5;
+    } else if (strcasecmp(item, "BUTTON") == 0) {
+        code = 5;
+    } else if (strcasecmp(item, "LCD") == 0) {
+        code = 11;
+    } else if (strcasecmp(item, "LEAKLIGHT") == 0) {
+        code = 6;
+    } else if (strcasecmp(item, "GSENSOR") == 0) {
+        code = 7;
+    } else if (strcasecmp(item, "BT") == 0) {
+        code = 8;
+    } else if (strcasecmp(item, "SE") == 0) {
+        code = 9;
+    } else if (strcasecmp(item, "GPS") == 0) {
+        code = 10;
+    } else if (strcasecmp(item, "DEEPSLEEP") == 0) {
+        code = 12;
+    } else {
+        wstp_print("TESTJUMP: unknown item=%s\r\n", item);
+        wstp_print("Usage: AT^TESTJUMP=<item>\r\n");
+        wstp_print("  item: TP|LCD|BRIGHT|CHARGE|MOTOR|KEY|BUTTON|LEAKLIGHT|GSENSOR|BT|SE|GPS|DEEPSLEEP\r\n");
+        return ERRCODE_FAIL;
+    }
+
+    do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_TYPE_PRODUCTTEST_JUMP, &code, sizeof(code));
+    wstp_print("TESTJUMP: %s\r\n", item);
+    return ERRCODE_SUCC;
+}
+
+static uint32_t custom_factory_deepsleep_enter(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(para);
+    UNUSED(paraLen);
+    UNUSED(strCommonCmd);
+    wstp_print("+FACTORYDEEPSLEEP: enter, exec\r\n");
+    uapi_factorytest_deepsleep_enter();
+    wstp_print("+FACTORYDEEPSLEEP: enter, ok\r\n");
+    return ERRCODE_SUCC;
+}
+
+#ifdef SUPPORT_GNSS
+static uint32_t custom_gps_switch(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    uint8_t argv[CUSTOM_UTILS_MAX_ARGC][CUSTOM_UTILS_MAX_ARGV_LEN] = { 0 };
+    uint32_t argc = 0;
+
+    int ret = ConvertCmdToParam(para, paraLen, argv, &argc);
+    if (ret != CUSTOM_UTILS_SUCCESS) {
+        wstp_print("GPS ATCMD Convert Command Failed\r\n");
+        return ERRCODE_FAIL;
+    }
+    if (argc != 1 || strcmp((char*)argv[0], "?") == 0) {
+        wstp_print("Usage: AT^GPS=1/0\r\n");
+        return ERRCODE_SUCC;
+    }
+
+    int on = atoi((char*)argv[0]) ? 1 : 0;
+    if (on) {
+        if (getPGnssServerStat() == 1) {
+            wstp_print("GPS: already on\r\n");
+        } else {
+            errcode_t r = gnss_start();
+            wstp_print("GPS: on ret=%d\r\n", (int)r);
+        }
+    } else {
+        if (getPGnssServerStat() == 0) {
+            wstp_print("GPS: already off\r\n");
+        } else {
+            errcode_t r = gnss_stop();
+            wstp_print("GPS: off ret=%d\r\n", (int)r);
+        }
+    }
+
+    uapi_factorytest_set_gps_button_state(on);
+    return ERRCODE_SUCC;
+}
+
+static uint32_t custom_gps_info(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    UNUSED(para);
+    UNUSED(paraLen);
+
+    gps_data_t *gpsdata = getPGPSGlobaldata();
+    if (gpsdata == NULL) {
+        wstp_print("GPSINFO: gpsdata=null\r\n");
+        return ERRCODE_FAIL;
+    }
+    gps_data_t gpsd = {0};
+    memcpy(&gpsd, gpsdata, sizeof(gps_data_t));
+
+    char buf[1024] = {0};
+    dump_location_data_to_buf(&gpsd, buf, (int)sizeof(buf));
+
+    int max_cn0 = 0;
+    const start_stat_t *groups[] = { gpsd.startsP, gpsd.startsB, gpsd.startsN, gpsd.startsL, gpsd.startsQ, gpsd.startsA };
+    for (unsigned gi = 0; gi < (unsigned)(sizeof(groups) / sizeof(groups[0])); ++gi) {
+        for (int i = 0; i < 5; ++i) {
+            if (groups[gi][i].starID > 0 && groups[gi][i].snr > max_cn0) {
+                max_cn0 = groups[gi][i].snr;
+            }
+        }
+    }
+
+    wstp_print("GPSINFO: stat=%d, sats=%d, trace=%d, valid_ephemeris=%d, err=%d, vga=%d, quality=%d.%02d, max_cn0=%d, last_ms=%u\r\n",
+               (int)getPGnssServerStat(),
+               (int)gpsd.num_sats,
+               (int)gpsd.th001_trace_star_count,
+               (int)gpsd.th001_valid_star_count,
+               (int)gpsd.th001_errorcode,
+               (int)gpsd.th000_signal_vga,
+               (int)gpsd.th001_quality,
+               (int)((gpsd.th001_quality - (int)gpsd.th001_quality) * 100),
+               (int)max_cn0,
+               (unsigned int)gpsd.last_gps_time_ms);
+    wstp_print("%s\r\n", buf);
+    return ERRCODE_SUCC;
+}
+#endif
+
+static uint32_t custom_leaklight_test(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(para);
+    UNUSED(paraLen);
+    UNUSED(strCommonCmd);
+
+    uapi_factorytest_enter_test_view(1);
+    uapi_factorytest_enter_test_hr_view();
+
+#ifdef SUPPORT_PPG_SERVICE
+    send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_DO_LEAKLIGHT_TEST);
+    LOS_Msleep(1000);
+    uint32_t ch0 = 0, ch1 = 0, ch2 = 0;
+    ppg_get_factory_data(&ch0, &ch1, &ch2);
+    send_ppg_cmd_msg(PPG_SERVICE_CMD_TYPE_STOP_PPG_TEST);
+    wstp_print(">>>leaklight:green=%u,red=%u,ir=%u\r\n", (unsigned int)ch0, (unsigned int)ch1, (unsigned int)ch2);
+    uapi_factorytest_trigger_leaklight_ui();
+#else
+    wstp_print("LEAKLIGHT: not supported (SUPPORT_PPG_SERVICE disabled)\r\n");
+#endif
+    return ERRCODE_SUCC;
+}
+
+#define BRIGHTRAMP_STEPS      30
+#define BRIGHTRAMP_DURATION_MS 3000
+#define BRIGHTRAMP_MIN        51
+#define BRIGHTRAMP_MAX        255
+
+static osTimerId_t g_brightramp_timer = NULL;
+static uint8_t g_brightramp_step = 0;
+
+static void brightramp_timer_cb(void *arg)
+{
+    (void)arg;
+    if (g_brightramp_step >= BRIGHTRAMP_STEPS) {
+        if (g_brightramp_timer) {
+            osTimerStop(g_brightramp_timer);
+            osTimerDelete(g_brightramp_timer);
+            g_brightramp_timer = NULL;
+        }
+        uapi_setScreenBrightness(BRIGHTRAMP_MAX);
+        wstp_print("BRIGHTRAMP: done (100%%)\r\n");
+        return;
+    }
+    uint8_t percent = (g_brightramp_step * 100) / BRIGHTRAMP_STEPS;
+    int value = BRIGHTRAMP_MIN + ((BRIGHTRAMP_MAX - BRIGHTRAMP_MIN) * percent) / 100;
+    if (value > BRIGHTRAMP_MAX) {
+        value = BRIGHTRAMP_MAX;
+    }
+    uapi_setScreenBrightness(value);
+    g_brightramp_step++;
+}
+
+static uint32_t custom_brightramp(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(para);
+    UNUSED(paraLen);
+    UNUSED(strCommonCmd);
+
+    if (g_brightramp_timer) {
+        osTimerStop(g_brightramp_timer);
+        osTimerDelete(g_brightramp_timer);
+        g_brightramp_timer = NULL;
+    }
+
+    g_brightramp_step = 0;
+    uapi_setScreenBrightness(BRIGHTRAMP_MIN);
+
+    g_brightramp_timer = osTimerNew(brightramp_timer_cb, osTimerPeriodic, NULL, NULL);
+    if (g_brightramp_timer == NULL) {
+        wstp_print("BRIGHTRAMP: timer create failed\r\n");
+        return ERRCODE_FAIL;
+    }
+    osTimerStart(g_brightramp_timer, BRIGHTRAMP_DURATION_MS / BRIGHTRAMP_STEPS);
+    wstp_print("BRIGHTRAMP: 0%% -> 100%% in %d s\r\n", BRIGHTRAMP_DURATION_MS / 1000);
+    return ERRCODE_SUCC;
+}
+
+static osTimerId_t g_gsensor_at_timer = NULL;
+static void gsensor_at_timer_cb(void *arg)
+{
+    (void)arg;
+#ifdef SUPPORT_CYWEE_SERVICE
+    gsenson_t t;
+    cywee_get_gsensor_data(1, &t);
+    printf(">>>XYZ: X=%.2f,Y=%.2f,Z=%.2f\r\n", t.x, t.y, t.z);
+#endif
+}
+
+static uint32_t custom_gsensor_test(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    uint8_t argv[CUSTOM_UTILS_MAX_ARGC][CUSTOM_UTILS_MAX_ARGV_LEN] = { 0 };
+    uint32_t argc = 0;
+
+    int ret = ConvertCmdToParam(para, paraLen, argv, &argc);
+    if (ret != CUSTOM_UTILS_SUCCESS) {
+        wstp_print("GSENSORTEST ATCMD Convert Command Failed\r\n");
+        return ERRCODE_FAIL;
+    }
+
+    if (argc != 1 || strcmp((char*)argv[0], "?") == 0) {
+        wstp_print("Usage: AT^GSENSORTEST=1/0\r\n");
+        return ERRCODE_SUCC;
+    }
+
+    uint8_t cmd = (uint8_t)atoi((char*)argv[0]);
+    if (cmd == 1) {
+#ifdef SUPPORT_CYWEE_SERVICE
+        if (g_gsensor_at_timer == NULL) {
+            g_gsensor_at_timer = osTimerNew(gsensor_at_timer_cb, osTimerPeriodic, NULL, NULL);
+        }
+        if (g_gsensor_at_timer) {
+            osTimerStart(g_gsensor_at_timer, 1000);
+            wstp_print("GSENSORTEST: start (print xyz every 1s)\r\n");
+        } else {
+            wstp_print("GSENSORTEST: start failed (timer null)\r\n");
+        }
+#else
+        wstp_print("GSENSORTEST: not supported (SUPPORT_CYWEE_SERVICE disabled)\r\n");
+#endif
+    } else {
+        if (g_gsensor_at_timer) {
+            osTimerStop(g_gsensor_at_timer);
+            osTimerDelete(g_gsensor_at_timer);
+            g_gsensor_at_timer = NULL;
+        }
+        wstp_print("GSENSORTEST: stop\r\n");
+    }
+
+    return ERRCODE_SUCC;
+}
+
+static uint32_t custom_enter_producttest_view(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(strCommonCmd);
+    uint8_t argv[CUSTOM_UTILS_MAX_ARGC][CUSTOM_UTILS_MAX_ARGV_LEN] = { 0 };
+    uint32_t argc = 0;
+
+    int ret = ConvertCmdToParam(para, paraLen, argv, &argc);
+    if (ret != CUSTOM_UTILS_SUCCESS) {
+        wstp_print("ENTERTESTVIEW ATCMD Convert Command Failed\r\n");
+        return ERRCODE_FAIL;
+    }
+
+    uint8_t cmd = 1;
+    if (argc == 0) {
+        cmd = 1;
+    } else if (argc == 1) {
+        if (strcmp((char*)argv[0], "?") == 0) {
+            wstp_print("Usage: AT^ENTERTESTVIEW[=1|0]\r\n");
+            wstp_print("  1: enter producttest UI\r\n");
+            wstp_print("  0: exit producttest UI\r\n");
+            return ERRCODE_SUCC;
+        }
+        cmd = (uint8_t)atoi((char*)argv[0]);
+    } else {
+        wstp_print("ENTERTESTVIEW ATCMD Set Parameter Failed argc %d\r\n", argc);
+        wstp_print("Usage: AT^ENTERTESTVIEW[=1|0]\r\n");
+        return ERRCODE_FAIL;
+    }
+
+    if (cmd != 0 && cmd != 1) {
+        wstp_print("ENTERTESTVIEW invalid cmd=%d (must be 0 or 1)\r\n", cmd);
+        return ERRCODE_FAIL;
+    }
+
+    uapi_factorytest_enter_test_view(cmd);
+    wstp_print("ENTERTESTVIEW: %s\r\n", (cmd == 1) ? "enter" : "exit");
+    return ERRCODE_SUCC;
+}
+
 extern void lsfd(void);
 static uint32_t custom_lsfd(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
 {
@@ -1318,6 +1649,7 @@ static uint32_t BLE_TEST(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
         break;
     case 13:
         CustomEventPublish(TOPIC_EVENT_BLE_TRANSMIT,(uint8_t *)&type_2,1);
+        break;
     case 14:
         if(type_2)
         uapi_open_voice_recognition( );
@@ -2286,6 +2618,16 @@ static const at_cmd_table_t g_custom_utils_cmd[] = {
     { (char *)"AT^CUSTOM_SN",      custom_utils_setsn, (char *)"123456789ABCDEF2345678" },
     { (char *)"AT^CUSTOM_SN_REQ",  custom_utils_getsn, (char *)" " },
     { (char *)"AT^STARTOTA",      custom_start_ota, (char *)" " },
+    { (char *)"AT^ENTERTESTVIEW", custom_enter_producttest_view, (char *)"enter/exit producttest UI: AT^ENTERTESTVIEW[=1|0]" },
+    { (char *)"AT^TESTJUMP",      custom_producttest_jump, (char *)"jump producttest subview" },
+    { (char *)"AT^FACTORYDEEPSLEEPENTER", custom_factory_deepsleep_enter, (char *)"producttest deep sleep prep" },
+#ifdef SUPPORT_GNSS
+    { (char *)"AT^GPS",           custom_gps_switch, (char *)"gps switch: AT^GPS=1/0" },
+    { (char *)"AT^GPSINFO",       custom_gps_info, (char *)"GPS summary + dump" },
+#endif
+    { (char *)"AT^LEAKLIGHT",     custom_leaklight_test, (char *)"hr leaklight test" },
+    { (char *)"AT^GSENSORTEST",   custom_gsensor_test, (char *)"AT^GSENSORTEST=1/0" },
+    { (char *)"AT^BRIGHTRAMP",    custom_brightramp,   (char *)"brightness ramp ~3s" },
     { (char *)"AT^LCDID",      custom_lcd_getid, (char *)" " },
 
     { (char *)"AT^TOUCHID",      custom_touch_getid, (char *)" " },