#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);
// 全局变量,存储当前有效的时间戳文件夹路径
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};
// 从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)
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)
{
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)
{
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时间替换
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;
{
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) {
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);
}
}
// 清除监听状态标志
g_is_listening_data = 0;
printf("GPS data listening stopped\r\n");
+
+ // 清理GNSS服务缓冲区
+ cleanup_gnss_service_buffer();
}
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");
}
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);
// 打开日志文件
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) {
}
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);
}
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);
// 关日志文件
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
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内存
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;
}
// 打开日志文件
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) {
}
return;
}
+ // 写入日志开启时间戳
+ write_log_start_timestamp(g_gnssLogFp);
+ printf("GNSS log file opened with timestamp (normal start)\n");
}
printf("before open tiot service\n");
// 关日志文件
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();
}
if(g_cold_start_pgnss_stopflag == 1)
{
- PGnssServerStartColdStart();
+ PGnssServerStartAutoModeStart();
}
}