增加ble获取星历有效期 3219/1 3219/head 3220/target/1
authorCaisking <Casiking@zhihuishixun.com>
Wed, 25 Feb 2026 03:36:58 +0000 (11:36 +0800)
committerCaisking <Casiking@zhihuishixun.com>
Wed, 25 Feb 2026 03:36:58 +0000 (11:36 +0800)
code/sdk/zhihui/services/ble_service/bleservice/bleEvent.c
code/sdk/zhihui/services/ble_service/bleservice/bleEvent.h
code/sdk/zhihui/services/gnss/src/gnss_http_server.c
code/sdk/zhihui/utils/custom_runtime.c
code/sdk/zhihui/utils/custom_runtime.h
code/sdk/zhihui/utils/custom_utils_at_cmd.c

index 228cdff..36a93ce 100644 (file)
@@ -52,6 +52,7 @@ extern "C" {
 
 #include "custom_utils.h"
 #include "custom_runtime.h"
+#include "gnss_http_server.h"
 #include "bleANCS.h"
 #ifdef CUSTOM_ZHIHUI
 #include "Bluetooyhpabpserver.h"
@@ -5296,16 +5297,50 @@ static void GetWatchStatusCmd(uint16_t cmd,uint8_t *data,uint16_t len,uint8_t *t
     memcpy(value+11,&tmp,4);
     memcpy(value+15,&tmp_data,2);
 
-    //0空闲状态 9 usb状态 10 运动训练状态
+    /* 0=空闲 9=星历未解压或过期(非运动时上报,app 可发起星历更新) 10=运动训练 */
     uint8_t watchStatus = 0;
-     
-    if(uapi_dev_runtime_get_train_status())
-    watchStatus=10;
-   
+    if (uapi_dev_runtime_get_train_status() != 0) {
+        watchStatus = 10;
+    }
+    // } else {
+    //     /* 获取状态前先刷新星历检查结果,以便 runtime 中的星历过期状态是最新的 */
+    //     (void)gnss_check_agnss_status();
+    //     if (uapi_dev_runtime_get_epo_file_extracted_status() == 0 ||
+    //         uapi_dev_runtime_get_ephemeris_expired_status() != 0) {
+    //         /* 星历未解压或星历过期,非运动状态下上报 9,app 获取后可发起星历更新 */
+    //         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP,"GetWatchStatusCmd 星历未解压或星历过期\r\n");
+    //         watchStatus = 9;
+    //     }
+    // }
     value[17] = watchStatus;
     value[18] = Calculate_CRC(value,18);
     sendBleData(value,19);
 }
+
+/** 获取星历有效剩余秒数(协议 01.18):格式与 01.1A 一致,包头 + 数据包(4B 剩余时间 单位s) + CRC */
+static void GetEphemerisValidSecCmd(uint16_t cmd, uint8_t *data, uint16_t len, uint8_t *totaldata, uint8_t crcvalue)
+{
+    uint8_t value[22];
+    memset(value, 0, sizeof(value));
+    value[0] = 0x72;   /* 传输方向:手表发 */
+    value[1] = 0x01;   /* 指令 类型 */
+    value[2] = 0x18;   /* 指令 ID (01.18) */
+    uint32_t tmp = 1;
+    uint32_t datalen = 4;   /* 数据总长度:4 字节(剩余时间 单位s) */
+    uint16_t tmp_data = 4;  /* 分包数据长度:4 字节 */
+    memcpy(value + 3, &tmp, 4);       /* 数据包总数 */
+    memcpy(value + 7, &datalen, 4);   /* 数据总长度 */
+    memcpy(value + 11, &tmp, 4);      /* 分包索引 */
+    memcpy(value + 15, &tmp_data, 2); /* 分包数据长度 */
+
+    int remaining_minutes = gnss_check_agnss_status();
+    uint32_t valid_sec = (remaining_minutes > 0) ? (uint32_t)(remaining_minutes * 60) : 0;
+    memcpy(value + 17, &valid_sec, 4); /* 数据包:剩余时间 单位s,小端 */
+
+    value[21] = Calculate_CRC(value, 21);
+    sendBleData(value, 22);
+}
+
 //获取手表屏幕参数
 static void GetScreenParamCmd(uint16_t cmd,uint8_t *data,uint16_t len,uint8_t *totaldata,uint8_t crcvalue)
 {
@@ -6477,6 +6512,9 @@ void type2AE3Data(ble_read_data *buffer_handle,uint8_t *cmd_buf ,uint8_t *data,u
         case SEND_CURR_STATUS_CMD: //获取手表当前状态
             GetWatchStatusCmd(cmd,data,datalen,totaldata,crcvalue);
             break;
+        case GET_EPHEMERIS_VALID_SEC_CMD: //获取星历有效剩余秒数
+            GetEphemerisValidSecCmd(cmd,data,datalen,totaldata,crcvalue);
+            break;
         case GET_WATCH_LCD_PARAM_CMD: //获取手表屏幕参数
             GetScreenParamCmd(cmd,data,datalen,totaldata,crcvalue);
             break;
index 2d7ead0..aa279b5 100644 (file)
@@ -66,6 +66,7 @@ void cameram_send_data(void);
 #define SPORT_PAUSE_RESET_CMD 0x0116 //训练暂停/恢复
 #define SEND_CURR_DIAL_TOAPP_CMD 0x0117 //发送当前表盘TOapp
 #define SEND_CURR_STATUS_CMD 0x0119 //获取手表当前状态
+#define GET_EPHEMERIS_VALID_SEC_CMD 0x0118 //获取星历有效剩余秒数
 #define SEND_UPPAIR_CMD 0x0110 //发送解除配对消息 Unpairing
 #define GET_WATCH_LCD_PARAM_CMD 0x011A //获取手表屏幕参数
 #define DELETE_DIAL_CMD 0x011B //删除表盘
index de91b32..0fdaf0b 100644 (file)
@@ -2384,12 +2384,14 @@ int gnss_check_agnss_status(void)
 
     if (PGNSS_DATA_PATH == NULL || strlen(PGNSS_DATA_PATH) == 0) {
         printf("ERROR: PGNSS_DATA_PATH is empty\n");
+        uapi_dev_runtime_set_ephemeris_expired_status(1);
         return -1;
     }
 
     DIR *dir = opendir(PGNSS_DATA_PATH);
     if (dir == NULL) {
         printf("Cannot open AGNSS directory: %s\n", PGNSS_DATA_PATH);
+        uapi_dev_runtime_set_ephemeris_expired_status(1);
         return -1;
     }
 
@@ -2399,6 +2401,7 @@ int gnss_check_agnss_status(void)
     if (current_timestamp == 0) {
         printf("ERROR: Failed to get current timestamp\n");
         closedir(dir);
+        uapi_dev_runtime_set_ephemeris_expired_status(1);
         return -1;
     }
     // 调试日志:打印正确的当前时间戳
@@ -2499,14 +2502,14 @@ int gnss_check_agnss_status(void)
     // 打印未来文件夹数量(调试用)
     // printf("future_folder_count : %d\n", future_folder_count);
 
-    // 返回剩余有效分钟数
+    // 返回剩余有效分钟数,并同步星历过期状态到 runtime(供 BLE 等查询)
     if (found_valid_folder) {
         uint32_t remaining_seconds = VALID_TIME_WINDOW - min_time_diff;
         int remaining_minutes = (int)(remaining_seconds / 60) + (future_folder_count * 24 * 60);
-        // printf("Valid folder remaining minutes: %d\n", remaining_minutes);
+        uapi_dev_runtime_set_ephemeris_expired_status(0); /* 星历有效 */
         return remaining_minutes;
     } else {
-        // printf("No valid folder in 24 hours\n");
+        uapi_dev_runtime_set_ephemeris_expired_status(1); /* 星历过期 */
         return 0;
     }
 }
index f1a9cd3..0966eca 100644 (file)
@@ -70,6 +70,7 @@ typedef struct
     char current_dial_name[32];
     char current_epo_file_path[128]; // EPO文件完整路径
     uint8_t epo_file_extracted_status;//EPO文件解压状态 0 未解压, 1 解压成功
+    uint8_t ephemeris_expired_status; // 星历过期状态 0 有效,1 过期/未检查
     uint8_t time_hour_show_model;
     uint8_t sleep_monitoring_status;//睡眠监测
     uint8_t sleep_status;//睡眠状态
@@ -290,6 +291,21 @@ uint8_t uapi_dev_runtime_get_epo_file_extracted_status(void)
     return g_runtime.epo_file_extracted_status;
 }
 
+/**
+ * 设置星历过期状态(0 有效,1 过期/未检查)
+ */
+void uapi_dev_runtime_set_ephemeris_expired_status(uint8_t status)
+{
+    g_runtime.ephemeris_expired_status = status;
+}
+
+/**
+ * 获取星历过期状态(0 有效,1 过期或未检查)
+ */
+uint8_t uapi_dev_runtime_get_ephemeris_expired_status(void)
+{
+    return g_runtime.ephemeris_expired_status;
+}
 
 void uapi_dev_runtime_set_bt_powerstat(uint8_t stat)
 {
index f2bcb4b..9f781fb 100644 (file)
@@ -57,6 +57,15 @@ void uapi_dev_runtime_set_epo_file_extracted_status(uint8_t status);
 */
 uint8_t uapi_dev_runtime_get_epo_file_extracted_status(void);
 
+/**
+ * 设置星历过期状态(由 GNSS 检查后更新:0 有效,1 过期/未检查)
+ */
+void uapi_dev_runtime_set_ephemeris_expired_status(uint8_t status);
+/**
+ * 获取星历过期状态(0 有效,1 过期或未检查)
+ */
+uint8_t uapi_dev_runtime_get_ephemeris_expired_status(void);
+
 void uapi_dev_runtime_set_vibmod(uint8_t vibmod);
 
 uint8_t uapi_dev_runtime_get_vibmod(void);
index 6300ce6..0cf7f34 100644 (file)
@@ -71,6 +71,7 @@
 #include "common.h"
 #include "broadcast_feature.h"
 #include "custom_save_runtime.h"
+#include "gnss_http_server.h"
 
 static int ConvertCmdToParam(uint8_t *para, uint32_t paraLen,
         uint8_t argv[CUSTOM_UTILS_MAX_ARGC][CUSTOM_UTILS_MAX_ARGV_LEN], uint32_t* argc)
@@ -2299,6 +2300,22 @@ static uint32_t custom_goal_show(uint8_t *para, uint32_t paraLen, char *strCommo
     return ERRCODE_SUCC;
 }
 
+/* 测试获取星历有效剩余秒数协议(与 BLE GET_EPHEMERIS_VALID_SEC_CMD 0x0118 一致) */
+static uint32_t custom_at_ephemeris_valid_sec(uint8_t *para, uint32_t paraLen, char *strCommonCmd)
+{
+    UNUSED(para);
+    UNUSED(paraLen);
+    UNUSED(strCommonCmd);
+    int remaining_minutes = gnss_check_agnss_status();
+    uint32_t valid_sec = (remaining_minutes > 0) ? (uint32_t)(remaining_minutes * 60) : 0;
+    if (remaining_minutes > 0) {
+        wstp_print("+EPHVALID: %u (valid_sec), %d min left\r\n", (unsigned int)valid_sec, remaining_minutes);
+    } else {
+        wstp_print("+EPHVALID: 0 (expired or error)\r\n");
+    }
+    return ERRCODE_SUCC;
+}
+
 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 *)" " },
@@ -2418,6 +2435,7 @@ static const at_cmd_table_t g_custom_utils_cmd[] = {
     { (char *)"AT^SPIDEINIT",     custom_spi_deinit_test, (char *)" " },
 
     { (char *)"AT^GOALSHOW",      custom_goal_show, (char *)" " },
+    { (char *)"AT^EPHVALID",      custom_at_ephemeris_valid_sec, (char *)" get ephemeris valid seconds (test 0x0118)" },
 };