From: penglei <1624952103@qq.com> Date: Thu, 30 Oct 2025 01:33:29 +0000 (+0800) Subject: 修复gps丢数据问题 X-Git-Tag: V1.0.9_20251128_194606_LN~147 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=c7f8392d68dac18d340af50b3cace8d4ca398ebb;p=mirrors%2FFD230.git 修复gps丢数据问题 --- diff --git a/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_sample.c b/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_sample.c index af6396158..d1d6e3059 100644 --- a/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_sample.c +++ b/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_sample.c @@ -39,7 +39,7 @@ #define LISTEN_DATA_MAX_LINES 1000 static FILE* g_gnssLogFp = NULL; -static uint8_t g_gnssServiceBuff[REPORT_MAX_BYTES] = { 0 }; +static uint8_t *g_gnssServiceBuff = NULL; typedef int32_t (*GnssCfgFunc)(tiot_handle handle); @@ -64,6 +64,99 @@ static char *pgnss_log = NULL; // 全局变量,存储当前有效的时间戳文件夹路径 static char *g_current_agnss_folder = NULL; +// 初始化GNSS服务缓冲区 +static int init_gnss_service_buffer(void) { + if (g_gnssServiceBuff == NULL) { + g_gnssServiceBuff = (uint8_t *)malloc(REPORT_MAX_BYTES); + if (g_gnssServiceBuff == NULL) { + printf("Error: Failed to allocate memory for GNSS service buffer\n"); + return -1; + } + memset(g_gnssServiceBuff, 0, REPORT_MAX_BYTES); + printf("GNSS service buffer allocated: %d bytes\n", REPORT_MAX_BYTES); + } + return 0; +} + +// 清理GNSS服务缓冲区 +static void cleanup_gnss_service_buffer(void) { + if (g_gnssServiceBuff != NULL) { + free(g_gnssServiceBuff); + g_gnssServiceBuff = NULL; + printf("GNSS service buffer freed\n"); + } +} + +// 获取当前时间戳字符串 +static void get_current_timestamp(char *timestamp_str, size_t max_len) { + time_t rawtime; + struct tm *timeinfo; + + time(&rawtime); + timeinfo = localtime(&rawtime); + + snprintf(timestamp_str, max_len, "%04d-%02d-%02d %02d:%02d:%02d", + timeinfo->tm_year + 1900, + timeinfo->tm_mon + 1, + timeinfo->tm_mday, + timeinfo->tm_hour, + timeinfo->tm_min, + timeinfo->tm_sec); +} + +// 获取当前时间戳字符串(毫秒精度) +static void get_current_timestamp_ms(char *timestamp_str, size_t max_len) { + struct timeval tv; + struct tm *timeinfo; + + gettimeofday(&tv, NULL); + timeinfo = localtime(&tv.tv_sec); + + snprintf(timestamp_str, max_len, "%04d-%02d-%02d %02d:%02d:%02d.%03ld", + timeinfo->tm_year + 1900, + timeinfo->tm_mon + 1, + timeinfo->tm_mday, + timeinfo->tm_hour, + timeinfo->tm_min, + timeinfo->tm_sec, + tv.tv_usec / 1000); +} + +// 记录读取结果到日志文件 +static void log_read_result(int32_t ret, const char *status_desc) { + if (g_gnssLogFp != NULL) { + char timestamp[64]; + get_current_timestamp_ms(timestamp, sizeof(timestamp)); + + fprintf(g_gnssLogFp, "[READ_LOG][%s] ret=%d, status=%s\n", + timestamp, ret, status_desc); + fflush(g_gnssLogFp); // 立即刷新到文件 + } +} + +// 写入日志文件开启时间戳 +static void write_log_start_timestamp(FILE *fp) { + if (fp != NULL) { + char timestamp[64]; + get_current_timestamp(timestamp, sizeof(timestamp)); + fprintf(fp, "=== GNSS Log Started at %s ===\n", timestamp); + fprintf(fp, "Format: NMEA data lines and [READ_LOG] entries\n"); + fprintf(fp, "[READ_LOG] Status: SUCCESS(>0), TIMEOUT(=0), ERROR(<0), BINARY_DATA\n"); + fprintf(fp, "================================================\n"); + fflush(fp); + } +} + +// 写入日志文件关闭时间戳 +static void write_log_end_timestamp(FILE *fp) { + if (fp != NULL) { + char timestamp[64]; + get_current_timestamp(timestamp, sizeof(timestamp)); + fprintf(fp, "=== GNSS Log Ended at %s ===\n", timestamp); + fflush(fp); + } +} + static int32_t QryVersion(tiot_handle handle) { const uint8_t qryVersion[] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; @@ -105,9 +198,8 @@ gps_data_t * getPGPSGlobaldata(void) // 从gnss_sample.c中复制冷启动相关的命令定义 // 函数声明 -void PGnssServerStartColdStart(void); +void PGnssServerStartAutoModeStart(void); static int pgnss_startup_check(void); -static int check_agnss_files_exist(void); // 获取当前有效的时间戳文件夹路径 const char* get_current_agnss_folder_path(void) @@ -126,13 +218,51 @@ void cleanup_agnss_folder_path(void) g_current_agnss_folder = NULL; } } +// 冷启动模式命令 static const uint8_t cfgColdStartCmd[] = {0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; +// 自动模式命令(热启动/冷启动自动选择) +static const uint8_t cfgAutoStartCmd[] = {0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00}; +// 配置定位使用的卫星系统 static const uint8_t cfgFixModeAllCmd[] = {0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00}; +// 配置NMEA显示内容 static const uint8_t cfgNmeaAllCmd[] = {0x03, 0x00, 0x04, 0x01, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x02, 0x00, 0xff, 0x00}; +static const uint8_t cfgNmeaDefaultCmd[] = {0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x02, 0x00, 0x11, 0x00}; +// 低功耗配置 static const uint8_t CFG_TRK_LPW_DISABLE[] = {0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00}; static const uint8_t CFG_ACQ_LPW_DISABLE[] = {0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00}; +// 抗干扰配置 static const uint8_t CFG_ANTIJAM_ENABLE[] = {0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x08, 0x00, 0x06, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00}; +static const uint8_t cfg_turn_down_gps_threshold_low[] = +{ +0x03 , 0x00 , 0xc2 , 0x00 , 0x00 , 0x00 , 0x20 , +0x00 , 0x02 , 0x00 , 0x1c , 0x00 , 0x00 , 0x64 , +0x40 ,0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , +0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , +0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , +0x00 , 0x00 , 0x00 , 0x00 , 0x00 +}; + +static const uint8_t cfg_turn_down_gps_threshold_high[] = +{ +0x03 , 0x00 , 0x02 , 0x01 , 0x00 , 0x00 , 0x20 , +0x00 , 0x02 , 0x00 , 0x1c , 0x00 , 0x00 , 0x64 , +0x80 ,0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , +0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , +0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , +0x00 , 0x00 , 0x00 , 0x00 , 0x00 +}; + +static const uint8_t cfg_turn_down_gps_threshold_high_150[] = +{ +0x03 , 0x00 , 0x34 , 0x01 , 0x00 , 0x00 , 0x20 , +0x00 , 0x02 , 0x00 , 0x1c , 0x00 , 0x00 , 0x96 , +0x80 ,0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , +0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , +0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , +0x00 , 0x00 , 0x00 , 0x00 , 0x00 +}; + // 普通GNSS冷启动配置函数实现 static int32_t CfgColdStartFixModeGpsNmeaAll(tiot_handle handle) { @@ -174,11 +304,75 @@ static int32_t CfgColdStartFixModeGpsNmeaAll(tiot_handle handle) printf("\nerror: CFG_ANTIJAM_ENABLE error: %d\r\n", ret); return 0; } + + //降低定位门限 + ret = tiot_service_write(handle, cfg_turn_down_gps_threshold_high, sizeof(cfg_turn_down_gps_threshold_high)); + if (ret < 0) { + printf("\nerror: cfg_turn_down_gps_threshold_high error: %d\r\n", ret); + return 0; + } + + printf("Cold start mode configured successfully\r\n"); return 1; } +static int32_t CfgAutoStartFixModeAllNmeaDefault(tiot_handle handle) +{ + // 配置启动模式:自动模式(有历史信息则热启动,无则冷启动) + int32_t ret = tiot_service_write(handle, cfgAutoStartCmd, sizeof(cfgAutoStartCmd)); + if (ret < 0) { + printf("\nerror: cfgAutoStartCmd error: %d\r\n", ret); + return 0; + } + + // 配置使能的GNSS星座:QZSS/GAL/BDS/GLO/GPS + ret = tiot_service_write(handle, cfgFixModeAllCmd, sizeof(cfgFixModeAllCmd)); + if (ret < 0) { + printf("\nerror: cfgFixModeAllCmd error: %d\r\n", ret); + return 0; + } + + // 配置上报NMEA类型:RMC/GGA(默认) + ret = tiot_service_write(handle, cfgNmeaDefaultCmd, sizeof(cfgNmeaDefaultCmd)); + if (ret < 0) { + printf("\nerror: cfgNmeaDefaultCmd error: %d\r\n", ret); + return 0; + } + + // 禁用TRK轨迹低功耗 + ret = tiot_service_write(handle, CFG_TRK_LPW_DISABLE, sizeof(CFG_TRK_LPW_DISABLE)); + if (ret < 0) { + printf("\nerror: CFG_TRK_LPW_DISABLE error: %d\r\n", ret); + return 0; + } + + // 禁用ACQ捕获低功耗 + ret = tiot_service_write(handle, CFG_ACQ_LPW_DISABLE, sizeof(CFG_ACQ_LPW_DISABLE)); + if (ret < 0) { + printf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\r\n", ret); + return 0; + } + + // 使能抗干扰特性 + ret = tiot_service_write(handle, CFG_ANTIJAM_ENABLE, sizeof(CFG_ANTIJAM_ENABLE)); + if (ret < 0) { + printf("\nerror: CFG_ANTIJAM_ENABLE error: %d\r\n", ret); + return 0; + } + + //降低定位门限 + ret = tiot_service_write(handle, cfg_turn_down_gps_threshold_high, sizeof(cfg_turn_down_gps_threshold_high)); + if (ret < 0) { + printf("\nerror: cfg_turn_down_gps_threshold_high error: %d\r\n", ret); + return 0; + } + + printf("Auto start mode configured successfully\r\n"); + return 1; +} + // 修改后的PGNSS配置函数,支持降级到普通GNSS int32_t InjectPgnssWithFallbackToColdStart(tiot_handle handle) { @@ -191,6 +385,27 @@ int32_t InjectPgnssWithFallbackToColdStart(tiot_handle handle) return 0; } + //降低定位门限 + ret = tiot_service_write(handle, cfg_turn_down_gps_threshold_high, sizeof(cfg_turn_down_gps_threshold_high)); + if (ret < 0) { + printf("\nerror: cfg_turn_down_gps_threshold_high error: %d\r\n", ret); + return 0; + } + + // 禁用TRK轨迹低功耗 + ret = tiot_service_write(handle, CFG_TRK_LPW_DISABLE, sizeof(CFG_TRK_LPW_DISABLE)); + if (ret < 0) { + printf("\nerror: CFG_TRK_LPW_DISABLE error: %d\r\n", ret); + return 0; + } + + // 禁用ACQ捕获低功耗 + ret = tiot_service_write(handle, CFG_ACQ_LPW_DISABLE, sizeof(CFG_ACQ_LPW_DISABLE)); + if (ret < 0) { + printf("\nerror: CFG_ACQ_LPW_DISABLE error: %d\r\n", ret); + return 0; + } + // 注入UTC时间, 注入Pgnss辅助数据前必须先注入参考时间 GnssUtcTime utcTime = {2024, 2, 26, 6, 0, 0, 0, 1}; // 需要用当前的UTC时间替换 @@ -289,6 +504,13 @@ static int32_t StopGnss(tiot_handle handle) static void ListenGnssData(tiot_handle handle) { int32_t i = 0; + int32_t timeout_count = 0; // 连续超时计数器 + + // 初始化GNSS服务缓冲区 + if (init_gnss_service_buffer() != 0) { + printf("Error: Failed to initialize GNSS service buffer\n"); + return; + } // 设置监听状态标志 g_is_listening_data = 1; @@ -306,20 +528,58 @@ static void ListenGnssData(tiot_handle handle) { break; } + // 检查缓冲区是否有效 + if (g_gnssServiceBuff == NULL) { + printf("Error: GNSS service buffer is NULL\n"); + break; + } + // 监听 int32_t ret = tiot_service_read(handle, g_gnssServiceBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR); + + // 记录读取结果(无论成功失败都记录) if (ret > 0) { + log_read_result(ret, "SUCCESS"); + timeout_count = 0; // 重置超时计数器 + + if (ret >= REPORT_MAX_BYTES) { + printf("Warning: Received data size (%d) >= buffer size (%d), truncating\n", ret, REPORT_MAX_BYTES); + ret = REPORT_MAX_BYTES - 1; + } + uint16_t *type = (uint16_t *)g_gnssServiceBuff; if (type[0] == MSG_TYPE_ASCII) { + g_gnssServiceBuff[ret] = '\0'; - char* pbuf=(char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]; - printf("%s\r\n", pbuf); - if (g_is_pgnss_logon) - fprintf(g_gnssLogFp, "%s\n", pbuf); - for (int index=0;index < ret ;index++) - { - if (decode_nmea(pbuf[index])==1) + + if (ret > MSG_CONTENT_IDX) { + char* pbuf = (char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]; + + int str_len = strnlen(pbuf, ret - MSG_CONTENT_IDX); + if (str_len > 0) { + printf("%s\r\n", pbuf); + + if (g_is_pgnss_logon && g_gnssLogFp != NULL) { + int fprintf_result = fprintf(g_gnssLogFp, "%s\n", pbuf); + if (fprintf_result < 0) { + printf("Warning: Failed to write to log file\n"); + } else { + fflush(g_gnssLogFp); + } + } + } else { + printf("Warning: Empty or invalid NMEA string received\n"); + } + } else { + printf("Warning: Received data too short (ret=%d, MSG_CONTENT_IDX=%d)\n", ret, MSG_CONTENT_IDX); + } + + if (ret > MSG_CONTENT_IDX) { + char* pbuf = (char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]; + for (int index=0;index < (ret - MSG_CONTENT_IDX) ;index++) { + if (decode_nmea(pbuf[index])==1) + { // dump_location_data(&g_global_gpsData); char *temp_buf = (char *)malloc(512); if (temp_buf == NULL) { @@ -344,10 +604,38 @@ static void ListenGnssData(tiot_handle handle) printf("decode_nmea done\r\n"); free(temp_buf); + } } } + } else { + log_read_result(ret, "BINARY_DATA"); + timeout_count = 0; // 重置超时计数器 } i++; + } else if (ret == 0) { + log_read_result(ret, "TIMEOUT"); + timeout_count++; // 增加超时计数 + printf("GNSS read timeout (no data received in %dms) - count: %d\n", LISTEN_TIME_THR, timeout_count); + + // 连续10次超时后发送版本查询命令 + if (timeout_count >= 10) { + printf("*** 连续10次超时,发送QryVersion命令尝试唤醒GPS模块 ***\n"); + if (g_gnssLogFp != NULL) { + fprintf(g_gnssLogFp, "[READ_LOG] 连续10次超时,发送QryVersion命令\n"); + fflush(g_gnssLogFp); + } + ret = QryVersion(handle); + if (g_gnssLogFp != NULL) { + fprintf(g_gnssLogFp, "[READ_LOG] QryVersion命令 ret:%d\n",ret); + fflush(g_gnssLogFp); + } + + timeout_count = 0; // 重置计数器 + } + } else { + log_read_result(ret, "ERROR"); + timeout_count = 0; // 重置超时计数器 + printf("GNSS read error: ret=%d\n", ret); } } @@ -355,6 +643,9 @@ static void ListenGnssData(tiot_handle handle) // 清除监听状态标志 g_is_listening_data = 0; printf("GPS data listening stopped\r\n"); + + // 清理GNSS服务缓冲区 + cleanup_gnss_service_buffer(); } void PGnssServerStop(void) @@ -384,12 +675,20 @@ void PGnssServerStop(void) // 设置停止标志 g_pgnss_stopflag = 1; + // 如果当前正在下载星历,关闭下载服务 + printf("PGnssServerStop: Checking and stopping AGNSS download service...\r\n"); + uapi_gnss_http_server_deinit(); + printf("PGnssServerStop: AGNSS download service stopped\r\n"); + // 清理pgnss_sample模块的内存 cleanup_agnss_folder_path(); // 清理pgnss_encode模块的内存 cleanup_pgnss_encode_agnss_folder_path(); + // 清理GNSS服务缓冲区 + cleanup_gnss_service_buffer(); + printf("PGnssServerStop: Force stop completed\r\n"); } @@ -418,10 +717,10 @@ int PGnssLogEnable(bool enable) return g_is_pgnss_logon; } -// 直接启动冷启动模式的函数 -void PGnssServerStartColdStart(void) +// 直接启动普通GNSS模式的函数(使用自动模式:有历史信息则热启动,无则冷启动) +void PGnssServerStartAutoModeStart(void) { - printf("\nenter cold start mode\r\n"); + printf("\nenter auto start mode (cold/hot auto select)\r\n"); uapi_pm_add_sleep_veto(PM_ID_SYS); @@ -452,7 +751,7 @@ void PGnssServerStartColdStart(void) // 打开日志文件 if (g_is_pgnss_logon) { - g_gnssLogFp = fopen("/user/log/gnss.log", "w"); + g_gnssLogFp = fopen("/user/userdata/gnsslog.txt", "w"); if (g_gnssLogFp == NULL) { printf("error: open log file error\n"); if (pgnss_log != NULL) { @@ -461,8 +760,11 @@ void PGnssServerStartColdStart(void) } return; } + // 写入日志开启时间戳 + write_log_start_timestamp(g_gnssLogFp); + printf("GNSS log file opened with timestamp (auto start)\n"); } - printf("before open tiot service for cold start\n"); + printf("before open tiot service for auto start\n"); // Step2: power on gnss tiot_handle handle = tiot_service_open("gn71", NULL); @@ -477,17 +779,18 @@ void PGnssServerStartColdStart(void) } return; } - printf("open tiot service success for cold start\n"); + printf("open tiot service success for auto start\n"); - // 直接配置为冷启动模式 - printf("Configuring cold start mode...\r\n"); + // 配置为自动模式(有历史信息则热启动,无则冷启动) + // printf("Configuring auto start mode...\r\n"); + // int32_t cfgRet = CfgAutoStartFixModeAllNmeaDefault(handle); int32_t cfgRet = CfgColdStartFixModeGpsNmeaAll(handle); if (cfgRet == 0) { - printf("Cold start configuration failed\r\n"); + printf("Auto start configuration failed\r\n"); tiot_service_close(handle); return; } - printf("Cold start mode configured successfully\r\n"); + printf("Auto start mode configured successfully\r\n"); QryVersion(handle); @@ -512,8 +815,11 @@ void PGnssServerStartColdStart(void) // 关日志文件 if (g_is_pgnss_logon) { + // 写入日志结束时间戳 + write_log_end_timestamp(g_gnssLogFp); fclose(g_gnssLogFp); g_gnssLogFp = NULL; + printf("GNSS log file closed with timestamp (auto start)\n"); } // Step8: deinit @@ -529,7 +835,7 @@ void PGnssServerStartColdStart(void) g_pgnss_stopflag = 0; // 清除停止标志 sw_debug_uart_deinit(); uart_config_init(); - printf("finish cold start mode\r\n"); + printf("finish auto start mode\r\n"); // 释放pgnss_log内存 @@ -869,20 +1175,20 @@ void PGnssServerStart(void) g_cold_start_pgnss_stopflag = 0; g_is_listening_data = 0; // 初始化监听状态 - //未绑定直接冷启动 + //未绑定直接使用普通GNSS自动模式 if(cm_getisFirstTimeStart()) { - printf("PGnssServerStartColdStart \n"); - PGnssServerStartColdStart(); + printf("First time start, using auto start mode (cold/hot auto select)\n"); + PGnssServerStartAutoModeStart(); return; } // 执行PGNSS启动前检查 int check_result = pgnss_startup_check(); if (check_result != 0) { - printf("PGNSS startup check failed. Starting cold start mode\n"); + printf("PGNSS startup check failed. Starting auto start mode (cold/hot auto select)\n"); if(!g_pgnss_stopflag) - PGnssServerStartColdStart(); + PGnssServerStartAutoModeStart(); return; } @@ -928,7 +1234,7 @@ void PGnssServerStart(void) // 打开日志文件 if (g_is_pgnss_logon) { - g_gnssLogFp = fopen("/user/log/gnss.log", "w"); + g_gnssLogFp = fopen("/user/userdata/gnsslog.txt", "w"); if (g_gnssLogFp == NULL) { printf("error: open log file error\n"); if (pgnss_log != NULL) { @@ -937,6 +1243,9 @@ void PGnssServerStart(void) } return; } + // 写入日志开启时间戳 + write_log_start_timestamp(g_gnssLogFp); + printf("GNSS log file opened with timestamp (normal start)\n"); } printf("before open tiot service\n"); @@ -990,8 +1299,11 @@ void PGnssServerStart(void) // 关日志文件 if (g_is_pgnss_logon) { + // 写入日志结束时间戳 + write_log_end_timestamp(g_gnssLogFp); fclose(g_gnssLogFp); g_gnssLogFp = NULL; + printf("GNSS log file closed with timestamp (normal start)\n"); } // Step8: deinit tiot_service_deinit(); @@ -1020,7 +1332,7 @@ void PGnssServerStart(void) } if(g_cold_start_pgnss_stopflag == 1) { - PGnssServerStartColdStart(); + PGnssServerStartAutoModeStart(); } }