From b61222e6d3292ba8c4f55f9b8f89da90368e284d Mon Sep 17 00:00:00 2001 From: penglei <1624952103@qq.com> Date: Thu, 28 Aug 2025 18:53:43 +0800 Subject: [PATCH] =?utf8?q?=E4=BF=AE=E5=A4=8D=E8=A1=A8=E5=86=A0=E8=BD=AC?= =?utf8?q?=E5=8A=A8=E4=BC=9A=E6=81=AF=E5=B1=8F=E9=97=AE=E9=A2=98=EF=BC=8C?= =?utf8?q?=E4=BC=98=E5=8C=96=E4=BD=A9=E6=88=B4=E6=A3=80=E6=B5=8B=E6=9C=AA?= =?utf8?q?=E6=AD=A3=E5=B8=B8=E5=90=AF=E5=8A=A8bug=EF=BC=8C=E4=BC=98?= =?utf8?q?=E5=8C=96PGNSS=E6=95=B0=E6=8D=AE=E6=B3=A8=E5=85=A5=EF=BC=8C?= =?utf8?q?=E5=A2=9E=E5=8A=A0pgnss=E7=9A=84http=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../brandy/brandy_standard/thread_pri_init.c | 7 +- .../nativeui/traing/src/TraingModel.cpp | 3 +- .../power_manager/src/power_display_service.c | 1 + .../power_manager/src/power_display_service.c | 1 + .../brandy_evb/linker/standard/acore.prelds | 18 +- .../UI/producttest/include/testPresenter.h | 2 +- .../zhihui/UI/producttest/src/testView.cpp | 6 + code/sdk/zhihui/config/include/ConfigModelC.h | 3 + code/sdk/zhihui/config/src/ConfigModel.cpp | 5 + .../zhihui/drivers/mag/service/mag_service.c | 2 +- .../drivers/ppg/pah8009/sensor/pah800x_main.c | 2 +- code/sdk/zhihui/services/gnss/CMakeLists.txt | 2 +- .../services/gnss/inc/gnss_http_server.h | 50 + .../services/gnss/inc/gnss_tcp_server.h | 45 - .../gnss/sample/pgnss_sample/pgnss_encode.c | 1273 +++++++------ .../gnss/sample/pgnss_sample/pgnss_encode.h | 35 +- .../gnss/sample/pgnss_sample/pgnss_sample.c | 1218 +++++++----- .../services/gnss/src/gnss_http_server.c | 1631 +++++++++++++++++ .../services/gnss/src/gnss_tcp_server.c | 1216 ------------ code/sdk/zhihui/utils/custom_utils.c | 44 +- 20 files changed, 3247 insertions(+), 2317 deletions(-) create mode 100644 code/sdk/zhihui/services/gnss/inc/gnss_http_server.h delete mode 100644 code/sdk/zhihui/services/gnss/inc/gnss_tcp_server.h create mode 100644 code/sdk/zhihui/services/gnss/src/gnss_http_server.c delete mode 100644 code/sdk/zhihui/services/gnss/src/gnss_tcp_server.c diff --git a/code/sdk/application/brandy/brandy_standard/thread_pri_init.c b/code/sdk/application/brandy/brandy_standard/thread_pri_init.c index c1fd48725..47bc99e4f 100644 --- a/code/sdk/application/brandy/brandy_standard/thread_pri_init.c +++ b/code/sdk/application/brandy/brandy_standard/thread_pri_init.c @@ -128,6 +128,10 @@ #include "mixo_service.h" #endif +#ifdef SUPPORT_GNSS +#include "gnss_http_server.h" +#endif + #define EMMC_BASE_ADDR 0x52062000 #define TASK_PRIORITY_APP (osPriority_t)(17) #define TICK_TEN_MS (10U) @@ -574,8 +578,9 @@ static void thread_main(const void *unused) uapi_pin_set_ie(S_MGPIO34, HAL_PIO_IE_ENBALE); //启动期间关闭uart输入中断,启动后开启 #endif -#ifdef SUPPORT_GNSS_SERVER +#ifdef SUPPORT_GNSS gnss_uart_init(); + uapi_gnss_http_server_init(); #endif #ifdef SUPPORT_OHOSFWK diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/traing/src/TraingModel.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/traing/src/TraingModel.cpp index fa50c4aca..cc5d5f3cc 100644 --- a/code/sdk/application/wearable/fd230/nativeapp/nativeui/traing/src/TraingModel.cpp +++ b/code/sdk/application/wearable/fd230/nativeapp/nativeui/traing/src/TraingModel.cpp @@ -72,10 +72,11 @@ #include "system/include/SystemLogModel.h" #include +#include "graphic_service.h" + #if defined(SUPPORT_GNSS) #include "NMEA0183.h" #include "gnss_ctl.h" -#include "graphic_service.h" #include "pgnss_sample.h" #endif diff --git a/code/sdk/application/wearable/fd230/service/power_manager/src/power_display_service.c b/code/sdk/application/wearable/fd230/service/power_manager/src/power_display_service.c index cfbb7f063..5e40905aa 100644 --- a/code/sdk/application/wearable/fd230/service/power_manager/src/power_display_service.c +++ b/code/sdk/application/wearable/fd230/service/power_manager/src/power_display_service.c @@ -620,6 +620,7 @@ errcode_t uapi_power_display_init(void) g_event_filter_map[TIMER_EVENT] = display_get_timer_filter(); g_event_filter_map[SLICE_EVENT] = display_get_slice_filter(); ts_register_power_manager_cb(power_display_touch_event_cb); + re_register_power_manager_cb(power_display_key_event_cb); button_register_power_display_cb(power_display_key_event_cb); return ERRCODE_SUCC; } diff --git a/code/sdk/application/wearable/service/power_manager/src/power_display_service.c b/code/sdk/application/wearable/service/power_manager/src/power_display_service.c index 2a27a6662..297dd3a53 100644 --- a/code/sdk/application/wearable/service/power_manager/src/power_display_service.c +++ b/code/sdk/application/wearable/service/power_manager/src/power_display_service.c @@ -618,6 +618,7 @@ errcode_t uapi_power_display_init(void) g_event_filter_map[TIMER_EVENT] = display_get_timer_filter(); g_event_filter_map[SLICE_EVENT] = display_get_slice_filter(); ts_register_power_manager_cb(power_display_touch_event_cb); + re_register_power_manager_cb(power_display_key_event_cb); button_register_power_display_cb(power_display_key_event_cb); return ERRCODE_SUCC; } diff --git a/code/sdk/drivers/boards/brandy_evb/linker/standard/acore.prelds b/code/sdk/drivers/boards/brandy_evb/linker/standard/acore.prelds index 54f57b5d5..4d419a074 100644 --- a/code/sdk/drivers/boards/brandy_evb/linker/standard/acore.prelds +++ b/code/sdk/drivers/boards/brandy_evb/linker/standard/acore.prelds @@ -93,12 +93,20 @@ SECTIONS SORT(*libbms*.a:*.o*) (.data .data* .sdata .sdata*) SORT(*libace.a:*.o*) (.data .data* .sdata .sdata*) SORT(*liblwip.a:*.o*) (.data .data* .sdata .sdata*) - SORT(*libcat1Service.a:*.o*) (.data .data* .sdata .sdata*) + SORT(*libcat1*.a:*.o*) (.data .data* .sdata .sdata*) SORT(*libppg*.a:*.o*) (.data .data* .sdata .sdata*) SORT(*libmag*.a:*.o*) (.data .data* .sdata .sdata*) SORT(*libcywee*.a:*.o*) (.data .data* .sdata .sdata*) SORT(*libbatterry*.a:*.o*) (.data .data* .sdata .sdata*) +#ifdef SUPPORT_GNSS SORT(*libgnss*.a:*.o*) (.data .data* .sdata .sdata*) + SORT(*libpgnss*.a:*.o*) (.data .data* .sdata .sdata*) +#endif + SORT(*librotary*.a:*.o*) (.data .data* .sdata .sdata*) + SORT(*libvibrator*.a:*.o*) (.data .data* .sdata .sdata*) +#ifdef SUPPORT_GYRO_SERVICE + SORT(*libgyro*.a:*.o*) (.data .data* .sdata .sdata*) +#endif SORT(*libace_adapt.a:*.o*) (.data .data* .sdata .sdata*) SORT(*libace_http*.a:*.o*) (.data .data* .sdata .sdata*) SORT(*libnetstack_http*.a:*.o*) (.data .data* .sdata .sdata*) @@ -133,7 +141,15 @@ SECTIONS SORT(*libmag*.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) SORT(*libcywee*.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) SORT(*libbatterry*.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) +#ifdef SUPPORT_GNSS SORT(*libgnss*.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) + SORT(*libpgnss*.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) +#endif + SORT(*librotary*.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) + SORT(*libvibrator*.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) +#ifdef SUPPORT_GYRO_SERVICE + SORT(*libgyro*.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) +#endif SORT(*libace_adapt.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) SORT(*libace_http*.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) SORT(*libnetstack_http*.a:*.o*) (.bss .bss* .sbss .sbss* COMMON) diff --git a/code/sdk/zhihui/UI/producttest/include/testPresenter.h b/code/sdk/zhihui/UI/producttest/include/testPresenter.h index 793064683..1ff73a05d 100644 --- a/code/sdk/zhihui/UI/producttest/include/testPresenter.h +++ b/code/sdk/zhihui/UI/producttest/include/testPresenter.h @@ -53,6 +53,7 @@ namespace OHOS typedef enum { TESTVIEW = 0, // 系统视图(slice) + QRCODE, // 添加二维码视图 VISON, LCD, TP, @@ -78,7 +79,6 @@ namespace OHOS // pressuretest, PRESSURETEST, OLDTEST, - QRCODE, // 添加二维码视图 DEEPSLEEP, shutdown, diff --git a/code/sdk/zhihui/UI/producttest/src/testView.cpp b/code/sdk/zhihui/UI/producttest/src/testView.cpp index c227524ae..9e5900401 100644 --- a/code/sdk/zhihui/UI/producttest/src/testView.cpp +++ b/code/sdk/zhihui/UI/producttest/src/testView.cpp @@ -920,6 +920,12 @@ namespace OHOS { switch (hideView) { + case QRCODE: + group->Remove(SystemScrollView[hideView]); + delete test_QRCode_view; + test_QRCode_view = nullptr; + SystemScrollView[hideView] = nullptr; + break; case VISON: group->Remove(SystemScrollView[hideView]); delete test_about_view; diff --git a/code/sdk/zhihui/config/include/ConfigModelC.h b/code/sdk/zhihui/config/include/ConfigModelC.h index 8e6291b37..9f60a0155 100644 --- a/code/sdk/zhihui/config/include/ConfigModelC.h +++ b/code/sdk/zhihui/config/include/ConfigModelC.h @@ -144,6 +144,9 @@ void set_save_runtime_log_switch(int value); int get_save_runtime_log_switch(void); +/*手表是否绑定*/ +bool cm_getisFirstTimeStart(void); + #ifdef __cplusplus #if __cplusplus diff --git a/code/sdk/zhihui/config/src/ConfigModel.cpp b/code/sdk/zhihui/config/src/ConfigModel.cpp index 730f171dc..7370ceb92 100644 --- a/code/sdk/zhihui/config/src/ConfigModel.cpp +++ b/code/sdk/zhihui/config/src/ConfigModel.cpp @@ -1362,6 +1362,11 @@ int cm_getScreenBrightness(void) return OHOS::ConfigModel::GetInstance()->GetBrightness(); } +bool cm_getisFirstTimeStart(void) +{ + return OHOS::ConfigModel::GetInstance()->GetisFirstTimeStart(); +} + void cm_initializeScreenDuration(void) { WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "cm_initializeScreenDuration"); diff --git a/code/sdk/zhihui/drivers/mag/service/mag_service.c b/code/sdk/zhihui/drivers/mag/service/mag_service.c index 817da8812..3161de5f1 100644 --- a/code/sdk/zhihui/drivers/mag/service/mag_service.c +++ b/code/sdk/zhihui/drivers/mag/service/mag_service.c @@ -17,7 +17,7 @@ osTimerId_t g_mag_service_timer = NULL; static bool g_mag_sensor_exist = false; static bool g_bat_timer_is_running = false; -#define MAG_CHECK_MS 40 +#define MAG_CHECK_MS 20 static unsigned long g_app_queue= 0xFFFFFFFF; static bool mag_service_running_stat = false; diff --git a/code/sdk/zhihui/drivers/ppg/pah8009/sensor/pah800x_main.c b/code/sdk/zhihui/drivers/ppg/pah8009/sensor/pah800x_main.c index 185c382c4..da7c969e0 100644 --- a/code/sdk/zhihui/drivers/ppg/pah8009/sensor/pah800x_main.c +++ b/code/sdk/zhihui/drivers/ppg/pah8009/sensor/pah800x_main.c @@ -1925,7 +1925,7 @@ void pah8009_control(char *mode,uint8_t enable) time_cnt = 0; - if(g_pah8009_timer != NULL && work_mode < 3 && work_mode > 0) + if(g_pah8009_timer != NULL && work_mode < 4 && work_mode > 0) { // printf("time_out : %d\n",time_out); osTimerStart(g_pah8009_timer,time_out); diff --git a/code/sdk/zhihui/services/gnss/CMakeLists.txt b/code/sdk/zhihui/services/gnss/CMakeLists.txt index 912d56bee..3794b391e 100644 --- a/code/sdk/zhihui/services/gnss/CMakeLists.txt +++ b/code/sdk/zhihui/services/gnss/CMakeLists.txt @@ -12,7 +12,7 @@ set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/uart_gnss.c ${CMAKE_CURRENT_SOURCE_DIR}/src/gnss_ctl.c ${CMAKE_CURRENT_SOURCE_DIR}/src/NMEA0183.c - # ${CMAKE_CURRENT_SOURCE_DIR}/src/gnss_tcp_server.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/gnss_http_server.c ${TIOT_SRC_LIST} ) set(PUBLIC_HEADER diff --git a/code/sdk/zhihui/services/gnss/inc/gnss_http_server.h b/code/sdk/zhihui/services/gnss/inc/gnss_http_server.h new file mode 100644 index 000000000..a0d09f08f --- /dev/null +++ b/code/sdk/zhihui/services/gnss/inc/gnss_http_server.h @@ -0,0 +1,50 @@ +/* + * @Author: penglei 1624952103@qq.com + * @Date: 2025-02-14 10:30:32 + * @LastEditors: penglei 1624952103@qq.com + * @LastEditTime: 2025-07-17 12:13:52 + * @FilePath: /sdk615/code/sdk/zhihui/drivers/gnss/service/gnss_ble_service.h + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ + + #ifndef _GNSS_HTTP_SERVER_H_ + #define _GNSS_HTTP_SERVER_H_ + + + #ifdef __cplusplus + #if __cplusplus + extern "C" { + #endif /* __cplusplus */ + #endif /* __cplusplus */ + + #include "stdint.h" + #include "errcode.h" + + typedef struct { + int cmd; + char *data; + uint32_t len; + } gnss_http_data_mail_t; + + + #define GNSS_HTTP_SERVICE_CMD_DATA_UPLOAD 0x1 + #define GNSS_HTTP_SERVICE_CMD_SERVER_INIT 0x2 + #define GNSS_HTTP_SERVICE_CMD_SERVER_DEINIT 0x3 + #define GNSS_HTTP_SERVICE_CMD_DOWNLOAD_AGNSS 0x4 + #define GNSS_HTTP_SERVICE_CMD_AGNSS_RECV 0x5 + + + + // void do_gnss_http_server_send_data(int cmd,int *data,uint32_t len); + int gnss_http_init(void); + errcode_t uapi_gnss_http_server_init(void); + int gnss_agnss_get_ephemeris(void); + void do_gnss_http_server_send_data(int cmd,char *data,uint32_t len); + + #ifdef __cplusplus + #if __cplusplus + } + #endif /* __cplusplus */ + #endif /* __cplusplus */ + + #endif /* _GNSS_HTTP_SERVER_H_ */ \ No newline at end of file diff --git a/code/sdk/zhihui/services/gnss/inc/gnss_tcp_server.h b/code/sdk/zhihui/services/gnss/inc/gnss_tcp_server.h deleted file mode 100644 index e67dfcd71..000000000 --- a/code/sdk/zhihui/services/gnss/inc/gnss_tcp_server.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * @Author: penglei 1624952103@qq.com - * @Date: 2025-02-14 10:30:32 - * @LastEditors: penglei 1624952103@qq.com - * @LastEditTime: 2025-07-17 12:13:52 - * @FilePath: /sdk615/code/sdk/zhihui/drivers/gnss/service/gnss_ble_service.h - * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE - */ - -#ifndef _GNSS_TCP_SERVER_H_ -#define _GNSS_TCP_SERVER_H_ - - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif /* __cplusplus */ -#endif /* __cplusplus */ - -#include "stdint.h" -#include "errcode.h" - -typedef struct { - int cmd; - char *data; - uint32_t len; -} gnss_tcp_data_mail_t; - - -#define GNSS_TCP_SERVICE_CMD_DATA_UPLOAD 0x1 -#define GNSS_TCP_SERVICE_CMD_SERVER_INIT 0x2 -#define GNSS_TCP_SERVICE_CMD_SERVER_DEINIT 0x3 - -// void do_gnss_tcp_server_send_data(int cmd,int *data,uint32_t len); -int gnss_tcp_init(void); -errcode_t uapi_gnss_tcp_server_init(void); -int gnss_tcp_sign_up(void); - -#ifdef __cplusplus -#if __cplusplus -} -#endif /* __cplusplus */ -#endif /* __cplusplus */ - -#endif \ No newline at end of file diff --git a/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_encode.c b/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_encode.c index 5d677d42a..efe4eb3a5 100644 --- a/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_encode.c +++ b/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_encode.c @@ -1,603 +1,672 @@ -/* - * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. - * Description: pgnss encode - * Author: - * Create: - */ -#include "pgnss_encode.h" -#include -#include -#include -#include "securec.h" -#include "tiot_service_interface.h" -#include "gnss_datatypes.h" - - -#define GNSS_ENCODE_BUFF_MAX_LEN 9300 -#define FILE_PATH_LEN 1024 -#define GLO_EPH_VALID_TIME 900 -#define OTHER_EPH_VALID_TIME 7200 -#define ONE_CENTURY_YEARS 100 -#define FOUR_CENTURY_YEARS 400 -#define LEAP_YEAR_LENGTH 4 -#define UNIX_TIME_START_YEAR 1970 // start year of unix time -#define TIME_UNIT 1000 -#define SECONDS_PER_MIN (60) -#define SECONDS_PER_HOUR (60 * SECONDS_PER_MIN) -#define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR) -#define SECONDS_PER_NORMAL_YEAR (365 * SECONDS_PER_DAY) -#define NON_GLO_GNSS_TYPES 4 -#define GLO_EPH_NUM_ONE_FILE 8 -#define OTHER_ASSIST_TYPES 7 -#define INJECT_SLEEP_MS_TIME 500 -#define PGNSS_FILE_MAX_SIZE 1024000 - -/** days per month on normal and leap year */ -int32_t g_normMonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -int32_t g_leapMonthDays[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -// 监听消息 -static uint8_t g_ackBuff[REPORT_MAX_BYTES] = { 0 }; - -/* 获取begin和end年份之间的闰年数 */ -int32_t GetLeapYearNum(uint16_t begin, uint16_t end) -{ - if (end <= begin || end < 1) { - return 0; - } - int32_t numPer400Year = (end - 1) / FOUR_CENTURY_YEARS - begin / FOUR_CENTURY_YEARS; - int32_t numPer100Year = (end - 1) / ONE_CENTURY_YEARS - begin / ONE_CENTURY_YEARS; - int32_t numPer4Year = (end - 1) / LEAP_YEAR_LENGTH - begin / LEAP_YEAR_LENGTH; - return (numPer400Year + numPer4Year - numPer100Year); -} - -/* 闰年判断 */ -int32_t CheckIfLeapYear(uint16_t year) -{ - if ((year % ONE_CENTURY_YEARS) == 0) { - if ((year % FOUR_CENTURY_YEARS) == 0) { - return 1; - } - } else { - if ((year % LEAP_YEAR_LENGTH) == 0) { - return 1; - } - } - return 0; -} - -/* 将日历时(年月日时分秒) 转换为 unix时间(1970å¹´1月1日起的时间秒数) */ -int32_t Utc2UnixTime(GnssUtcTime utcTime, uint32_t *unixTime) -{ - if (unixTime == NULL) { - printf("\nerror: [Utc2UnixTime] null pointer!\n"); - return 0; - } - - if (utcTime.month > 12 || utcTime.valid == 0) { - printf("\nerror: [Utc2UnixTime] utcTime invalid!\n"); - return 0; - } - - // 判断是否为闰年 - int32_t *monthDays = (CheckIfLeapYear(utcTime.year) == 1) ? g_leapMonthDays : g_normMonthDays; - - // 计算从1970.01.01开始的unix 秒数 - uint32_t timestamp = 0; - timestamp += (uint32_t)(utcTime.year - UNIX_TIME_START_YEAR) * SECONDS_PER_NORMAL_YEAR; - timestamp += (uint32_t)GetLeapYearNum(UNIX_TIME_START_YEAR, utcTime.year) * SECONDS_PER_DAY; - - for (int32_t i = 1; i < utcTime.month; i++) { - timestamp += (uint32_t)monthDays[i - 1] * SECONDS_PER_DAY; - } - - timestamp += (uint32_t)(utcTime.day - 1) * SECONDS_PER_DAY; - timestamp += (uint32_t)utcTime.hour * SECONDS_PER_HOUR; - timestamp += (uint32_t)utcTime.minute * SECONDS_PER_MIN; - uint32_t timestampSec = (uint32_t)(utcTime.second + utcTime.ms / TIME_UNIT); - - *unixTime = timestamp + timestampSec; - return 1; -} - -/* 计算命令内容校准和 */ -static uint16_t CalcChecksum(uint8_t *buff, uint16_t len) -{ - uint16_t checksum = 0; - uint16_t i = 0; - while (i++ < len) { - checksum += *buff; - buff++; - } - return checksum; -} - -int32_t PgnssInjectUtcTime(tiot_handle handle, GnssUtcTime *utcTime, uint32_t* ts) -{ - uint8_t *buff = (uint8_t *)malloc(GNSS_ENCODE_BUFF_MAX_LEN); - if (buff == NULL) { - printf("\nerror: malloc failed in PgnssINjectUtcTime\r\n"); - return 0; - } - memset_s(buff, GNSS_ENCODE_BUFF_MAX_LEN, 0, GNSS_ENCODE_BUFF_MAX_LEN); - - GnssMsg *hdr = (GnssMsg *)buff; - hdr->cmd = 0x0404; - hdr->sequence = 0; - errno_t copyRet = memcpy_s(hdr->data, (GNSS_ENCODE_BUFF_MAX_LEN - sizeof(GnssMsg)), utcTime, sizeof(GnssUtcTime)); - if (copyRet != EOK) { - printf("\nmemcpy UtcTime failed! Errno is %d\r\n", copyRet); - free(buff); - return 0; - } - hdr->dataLength = sizeof(GnssUtcTime); - hdr->checkSum = CalcChecksum(hdr->data, hdr->dataLength); - int32_t ret = tiot_service_write(handle, buff, (sizeof(GnssMsg) + hdr->dataLength)); - if (ret < 0) { - printf("\nerror: PgnssInjectUtcTime error: %d\r\n", ret); - free(buff); - return 0; - } - if (Utc2UnixTime((*utcTime), ts) == 0) { - printf("\nerror: Utc2UnixTime error\r\n"); - free(buff); - return 0; - } - - free(buff); - return 1; -} - -static uint16_t FillGnssMessageData(uint8_t *inBuff, uint32_t inLen, uint8_t *outBuff, uint32_t outLen) -{ - errno_t ret = memcpy_s(outBuff, outLen, inBuff, inLen); - if (ret != EOK) { - printf("memcpy XgnssData failed! Errno is %d \r\n", ret); - return 0; - } - - return inLen; -} - -static int32_t EncodeGnssMsg(uint8_t *inBuff, uint32_t inLen, uint8_t *outBuff, uint32_t outLen) -{ - uint16_t len = FillGnssMessageData(inBuff, inLen, outBuff, outLen); - if (len > 0) { - return 1; - } - return 0; -} - -static void ListenAck(tiot_handle handle) -{ - int32_t i = 0; - for (;;) { - // 监听 - int32_t ret = tiot_service_read(handle, g_ackBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR); - if (ret > 0) { - uint16_t *type = (uint16_t *)g_ackBuff; - // 二进制消息类型 - if (type[0] == 0) { - g_ackBuff[ret] = '\0'; - printf("%s\r\n", (char *)&g_ackBuff[MSG_CONTENT_IDX]); - } - i++; - } - if (i >= 1) { - printf("\r\ncnt enough\r\n"); - break; - } - } -} - -static int32_t EncodeAndInjectCmd(tiot_handle handle, GnssCmdType cmdType, uint8_t* inBuff, uint32_t inLen) -{ - // 获取GNSS业务消息头 - int32_t len = 0; - uint8_t *buff = (uint8_t *)malloc(GNSS_ENCODE_BUFF_MAX_LEN); - if (buff == NULL) { - printf("\r\nerror: malloc failed in EncodeAndInjectCmd\r\n"); - return 0; - } - memset_s(buff, GNSS_ENCODE_BUFF_MAX_LEN, 0, GNSS_ENCODE_BUFF_MAX_LEN); - - GnssMsg *gnssHdr = (GnssMsg *)buff; - len += sizeof(GnssMsg); - - gnssHdr->sequence = 0; - - int32_t retLen = EncodeGnssMsg(inBuff, inLen, buff + len, (GNSS_ENCODE_BUFF_MAX_LEN - len)); - if (retLen != 1) { - printf("\nerror: Encode Cmd failed: %d\r\n", cmdType); - free(buff); - return retLen; - } - gnssHdr->cmd = cmdType; - gnssHdr->dataLength = inLen; - gnssHdr->checkSum = CalcChecksum(gnssHdr->data, gnssHdr->dataLength); - int32_t ret = tiot_service_write(handle, buff, (sizeof(GnssMsg) + gnssHdr->dataLength)); - if (ret < 0) { - printf("\r\nerror: Inject Cmd failed: %d\r\n", cmdType); - free(buff); - return 0; - } - ListenAck(handle); - printf("\r\nInject Cmd SUCCESS: %x\r\n", cmdType); - free(buff); - return 1; -} - -void PgnssSendFileContent(tiot_handle handle, const char *fileName, GnssCmdType cmdType) -{ - FILE *fp = fopen(fileName, "rb"); - if (fp == NULL) { - printf("\r\nerror: open file failed: %s\r\n", fileName); - return; - } - fseek(fp, 0, SEEK_END); - int32_t len = ftell(fp); - fseek(fp, 0, SEEK_SET); - if (len < 0 || len > PGNSS_FILE_MAX_SIZE) { - fclose(fp); - printf("\r\nerror: get file len failed: %s\r\n", fileName); - return; - } - uint8_t *buff = (uint8_t *)malloc(len); - if (buff == NULL) { - fclose(fp); - printf("\r\nerror: malloc file len failed: %s\r\n", fileName); - return; - } - int32_t dataSize = fread(buff, len, 1, fp); - if (dataSize < 0) { - fclose(fp); - printf("\r\nerror: read file failed: %s\r\n", fileName); - free(buff); - return; - } - fclose(fp); - EncodeAndInjectCmd(handle, cmdType, buff, len); - free(buff); -} - -int32_t FormatFileName(char *fileName, char *dName) -{ - int32_t ret = snprintf_s(fileName, FILE_PATH_LEN, (FILE_PATH_LEN - 1), "%s%s", "/user/userdata/gnss/", dName); - if (ret <= 0) { - return 0; - } - return 1; -} - -int32_t GetEphFileName(int32_t ts, const char *prefix, char *fileName) -{ - int32_t interval = (strcmp(prefix, "GLO") == 0) ? GLO_EPH_VALID_TIME : OTHER_EPH_VALID_TIME; - DIR *dir = opendir("/user/userdata/gnss/"); - if (dir == NULL) { - printf("Failed to open /user/xgnss directory.\r\n"); - return 0; - } - int32_t time, ret; - struct dirent *entry; - for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) { - // 检查文件名 - if (strstr(entry->d_name, ".eph") != NULL) { - char *p = strrchr(entry->d_name, '_'); - if (p != NULL) { - char *q = strstr(entry->d_name, prefix); - if (q != NULL) { - time = atoi(p + 1); - if (abs(time - ts) <= interval) { - ret = FormatFileName(fileName, entry->d_name); - closedir(dir); - return ret; - } - else - { - printf("time:%d,ts:%d,interval:%d\r\n",time,ts,interval); - } - } - } - } - } - closedir(dir); - printf("closedir(dir);\r\n"); - return 0; -} - -void PgnssSendEphFile(tiot_handle handle, const char *prefix, GnssCmdType cmdType, uint32_t ts) -{ - char fileName[FILE_PATH_LEN] = {0}; - int32_t ret = GetEphFileName(ts, prefix, fileName); - if (ret == 0) { - printf("\r\nerror: GetEphFileName failed\r\n"); - return; - } - printf("\nGetEphFileName success\r\n"); - PgnssSendFileContent(handle, fileName, cmdType); -} - -void PgnssInjectAllEph(tiot_handle handle, uint32_t ts) -{ - PgnssSendEphFile(handle, "GPS", CMD_PGNSS_INJECT_EPH_GPS, ts); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send GPS eph success\r\n"); - PgnssSendEphFile(handle, "GLO", CMD_PGNSS_INJECT_EPH_GANSS, ts); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send GLO eph success\r\n"); - PgnssSendEphFile(handle, "BDS", CMD_PGNSS_INJECT_EPH_GANSS, ts); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send BDS eph success\r\n"); - PgnssSendEphFile(handle, "GAL", CMD_PGNSS_INJECT_EPH_GANSS, ts); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send GAL eph success\r\n"); - PgnssSendEphFile(handle, "QZS", CMD_PGNSS_INJECT_EPH_GANSS, ts); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send QZS eph success\r\n"); -} - -void PgnssInjectOtherAssist(tiot_handle handle) -{ - PgnssSendFileContent(handle, "/user/userdata/gnss/GPS_UTC.dat", CMD_PGNSS_INJECT_UTC_GPS); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send GPS_UTC success\r\n"); - PgnssSendFileContent(handle, "/user/userdata/gnss/GPS_RTI.dat", CMD_PGNSS_INJECT_RTI_GPS); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send GPS_RTI success\r\n"); - PgnssSendFileContent(handle, "/user/userdata/gnss/GPS_ION.dat", CMD_PGNSS_INJECT_ION_GPS); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send GPS_ION success\r\n"); - PgnssSendFileContent(handle, "/user/userdata/gnss/GLO_RTI.dat", CMD_PGNSS_INJECT_RTI_GANSS); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send GLO_RTI success\r\n"); - PgnssSendFileContent(handle, "/user/userdata/gnss/GLO_AUX.dat", CMD_PGNSS_INJECT_AUX_GANSS); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send GLO_AUX success\r\n"); - PgnssSendFileContent(handle, "/user/userdata/gnss/BDS_RTI.dat", CMD_PGNSS_INJECT_RTI_GANSS); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send BDS_RTI success\r\n"); - PgnssSendFileContent(handle, "/user/userdata/gnss/GAL_RTI.dat", CMD_PGNSS_INJECT_RTI_GANSS); - osal_msleep(INJECT_SLEEP_MS_TIME); - printf("send GAL_RTI success\r\n"); -} - -void PgnssInject(tiot_handle handle, uint32_t ts) -{ - // 注入Pgnss辅助数据 - PgnssInjectAllEph(handle, ts); - PgnssInjectOtherAssist(handle); -} - - -// 以下为使用PGNSS解析数据合并输出接口生成的星历文件进行注入的代码 -int32_t GetNonGloEphFileName(int32_t ts, char *fileName) -{ - const char prefix[] = "NonGlo"; - DIR *dir = opendir("/user/userdata/gnss/"); - if (dir == NULL) { - printf("Failed to open /user/xgnss directory.\r\n"); - return 0; - } - int32_t time, ret; - int32_t minDist = OTHER_EPH_VALID_TIME; - int32_t closestTime = 0; - struct dirent *entry; - for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) { - // 检查文件名 - if (strstr(entry->d_name, ".eph") != NULL) { - char *p = strrchr(entry->d_name, '_'); - if (p != NULL) { - char *q = strstr(entry->d_name, prefix); - if (q != NULL) { - time = atoi(p + 1); - // 查找星历文件时间戳与当前时间相差2小时以内且距离最近的 - if (abs(time - ts) < minDist) { - minDist = abs(time - ts); - closestTime = time; - } - else - { - printf("time:%d,ts:%d,minDist:%d\r\n",time,ts,minDist); - } - } - } - } - } - if (closestTime != 0) { - ret = snprintf_s(fileName, FILE_PATH_LEN, (FILE_PATH_LEN - 1), "%s%d%s", "/user/userdata/gnss/NonGlo_", closestTime, - ".eph"); - printf("closest eph fileName:%s\r\n", fileName); - closedir(dir); - return ((ret <= 0) ? 0 : 1); - } - else - { - printf("closestTime == 0\r\n"); - } - closedir(dir); - return 0; -} - -int32_t GetGloEphFileName(int32_t ts, char *fileName) -{ - const char prefix[] = "GLO"; - DIR *dir = opendir("/user/userdata/gnss/"); - if (dir == NULL) { - printf("Failed to open /user/xgnss directory.\r\n"); - return 0; - } - int32_t ephTime, ret; - struct dirent *entry; - for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) { - // 检查文件名 - if (strstr(entry->d_name, ".eph") != NULL) { - char *p = strrchr(entry->d_name, '_'); - if (p != NULL) { - char *q = strstr(entry->d_name, prefix); - if (q != NULL) { - ephTime = atoi(p + 1); - printf("ephTime:%ld, ts:%ld\n", ephTime, ts); - // 当前时间大于GLO星历文件时间戳,则需要选取相差2小时以内的星历 - // 当前时间小于GLO星历文件时间戳,则需要选取相差小于15分钟的星历 - if (((ts - ephTime) >= 0 && abs(ephTime - ts) < OTHER_EPH_VALID_TIME) || - ((ts - ephTime) <= 0 && abs(ephTime - ts) < GLO_EPH_VALID_TIME)) { - ret = FormatFileName(fileName, entry->d_name); - printf("glo eph fileName:%s\n", fileName); - closedir(dir); - return ret; - } - } - } - } - } - closedir(dir); - return 0; -} - -void PgnssSendNonGloEph(tiot_handle handle, const char *fileName) -{ - FILE *fp = fopen(fileName, "rb"); - if (fp == NULL) { - printf("\nerror: open file failed: %s\r\n", fileName); - return; - } - fseek(fp, 0, SEEK_END); - int32_t len = ftell(fp); - fseek(fp, 0, SEEK_SET); - if (len < 0 || len > PGNSS_FILE_MAX_SIZE) { - fclose(fp); - printf("\nerror: get file len failed: %s\r\n", fileName); - return; - } - uint8_t *buff = (uint8_t *)malloc(len); - if (buff == NULL) { - fclose(fp); - printf("\nerror: malloc file len failed: %s\r\n", fileName); - return; - } - int32_t dataSize = fread(buff, len, 1, fp); - if (dataSize < 0) { - fclose(fp); - printf("\nerror: read file failed: %s\r\n", fileName); - free(buff); - return; - } - fclose(fp); - int32_t fileLen = 0; - for (int32_t i = 0; i < NON_GLO_GNSS_TYPES && fileLen <= len; i++) { - EphHeadInfo *ephHdr = (EphHeadInfo *)(buff + fileLen); - EncodeAndInjectCmd(handle, ephHdr->cmd, (buff + fileLen + sizeof(EphHeadInfo)), ephHdr->len); - fileLen += (ephHdr->len + sizeof(EphHeadInfo)); - osal_msleep(INJECT_SLEEP_MS_TIME); - } - free(buff); -} - -void PgnssSendGloEph(tiot_handle handle, const char *fileName, int32_t ts) -{ - FILE *fp = fopen(fileName, "rb"); - if (fp == NULL) { - printf("\nerror: open file failed: %s\r\n", fileName); - return; - } - fseek(fp, 0, SEEK_END); - int32_t len = ftell(fp); - fseek(fp, 0, SEEK_SET); - if (len < 0 || len > PGNSS_FILE_MAX_SIZE) { - fclose(fp); - printf("\nerror: get file len failed: %s\r\n", fileName); - return; - } - uint8_t *buff = (uint8_t *)malloc(len); - if (buff == NULL) { - fclose(fp); - printf("\nerror: malloc file len failed: %s\r\n", fileName); - return; - } - int32_t dataSize = fread(buff, len, 1, fp); - if (dataSize < 0) { - fclose(fp); - printf("\nerror: read file failed: %s\r\n", fileName); - free(buff); - return; - } - fclose(fp); - int32_t fileLen = 0; - for (int32_t i = 0; i < GLO_EPH_NUM_ONE_FILE && fileLen <= len; i++) { - EphHeadInfo *ephHdr = (EphHeadInfo *)(buff + fileLen); - printf("glo eph, time:%u, ts:%d\r\n", ephHdr->time, ts); - if (abs((int32_t)ephHdr->time - ts) < GLO_EPH_VALID_TIME) { - EncodeAndInjectCmd(handle, ephHdr->cmd, (buff + fileLen + sizeof(EphHeadInfo)), ephHdr->len); - osal_msleep(INJECT_SLEEP_MS_TIME); - break; - } - fileLen += (ephHdr->len + sizeof(EphHeadInfo)); - } - free(buff); -} - -void PgnssInjectAllEphLessFiles(tiot_handle handle, uint32_t ts) -{ - char fileName[FILE_PATH_LEN] = {0}; - if (GetNonGloEphFileName(ts, fileName) == 0) { - printf("\nerror: GetNonGloEphFileName failed\r\n"); - return; - } - PgnssSendNonGloEph(handle, fileName); - if (GetGloEphFileName(ts, fileName) == 0) { - printf("\nerror: GetGloEphFileName failed\r\n"); - return; - } - PgnssSendGloEph(handle, fileName, ts); -} - -void PgnssSendOtherAssistInfo(tiot_handle handle, const char *fileName) -{ - FILE *fp = fopen(fileName, "rb"); - if (fp == NULL) { - printf("\nerror: open file failed: %s\r\n", fileName); - return; - } - fseek(fp, 0, SEEK_END); - int32_t len = ftell(fp); - fseek(fp, 0, SEEK_SET); - if (len < 0 || len > PGNSS_FILE_MAX_SIZE) { - fclose(fp); - printf("\nerror: get file len failed: %s\r\n", fileName); - return; - } - uint8_t *buff = (uint8_t *)malloc(len); - if (buff == NULL) { - fclose(fp); - printf("\nerror: malloc file len failed: %s\r\n", fileName); - return; - } - int32_t dataSize = fread(buff, len, 1, fp); - if (dataSize < 0) { - fclose(fp); - printf("\nerror: read file failed: %s\r\n", fileName); - free(buff); - return; - } - fclose(fp); - int32_t fileLen = 0; - for (int32_t i = 0; i < OTHER_ASSIST_TYPES && fileLen <= len; i++) { - OtherAssistHeadInfo *otherHdr = (OtherAssistHeadInfo *)(buff + fileLen); - EncodeAndInjectCmd(handle, otherHdr->cmd, (buff + fileLen + sizeof(OtherAssistHeadInfo)), otherHdr->len); - fileLen += (otherHdr->len + sizeof(OtherAssistHeadInfo)); - osal_msleep(INJECT_SLEEP_MS_TIME); - } - free(buff); -} - -void PgnssInjectOtherAssistLessFiles(tiot_handle handle) -{ - PgnssSendOtherAssistInfo(handle, "/user/userdata/gnss/AssistInfo.dat"); -} - -// 注入PGNSS解析数据合并输出接口生成的星历文件 -void PgnssInjectLessFiles(tiot_handle handle, uint32_t ts) -{ - // 注入Pgnss辅助数据 - PgnssInjectAllEphLessFiles(handle, ts); - PgnssInjectOtherAssistLessFiles(handle); +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * Description: pgnss encode + * Author: + * Create: + */ +#include "pgnss_encode.h" +#include +#include +#include +#include "securec.h" +#include "tiot_service_interface.h" +#include "gnss_datatypes.h" + + +#define GNSS_ENCODE_BUFF_MAX_LEN 9300 +#define FILE_PATH_LEN 1024 +#define GLO_EPH_VALID_TIME 900 +#define OTHER_EPH_VALID_TIME 7200 +#define ONE_CENTURY_YEARS 100 +#define FOUR_CENTURY_YEARS 400 +#define LEAP_YEAR_LENGTH 4 +#define UNIX_TIME_START_YEAR 1970 // start year of unix time +#define TIME_UNIT 1000 +#define SECONDS_PER_MIN (60) +#define SECONDS_PER_HOUR (60 * SECONDS_PER_MIN) +#define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR) +#define SECONDS_PER_NORMAL_YEAR (365 * SECONDS_PER_DAY) +#define NON_GLO_GNSS_TYPES 4 +#define GLO_EPH_NUM_ONE_FILE 8 +#define OTHER_ASSIST_TYPES 7 +#define INJECT_SLEEP_MS_TIME 500 +#define PGNSS_FILE_MAX_SIZE 1024000 + +/** days per month on normal and leap year */ +static int32_t g_normMonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static int32_t g_leapMonthDays[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +// 监听消息 +static uint8_t g_ackBuff[REPORT_MAX_BYTES] = { 0 }; + +/* 获取begin和end年份之间的闰年数 */ +int32_t GetLeapYearNum(uint16_t begin, uint16_t end) +{ + if (end <= begin || end < 1) { + return 0; + } + int32_t numPer400Year = (end - 1) / FOUR_CENTURY_YEARS - begin / FOUR_CENTURY_YEARS; + int32_t numPer100Year = (end - 1) / ONE_CENTURY_YEARS - begin / ONE_CENTURY_YEARS; + int32_t numPer4Year = (end - 1) / LEAP_YEAR_LENGTH - begin / LEAP_YEAR_LENGTH; + return (numPer400Year + numPer4Year - numPer100Year); +} + +/* 闰年判断 */ +int32_t CheckIfLeapYear(uint16_t year) +{ + if ((year % ONE_CENTURY_YEARS) == 0) { + if ((year % FOUR_CENTURY_YEARS) == 0) { + return 1; + } + } else { + if ((year % LEAP_YEAR_LENGTH) == 0) { + return 1; + } + } + return 0; +} + +/* 将日历时(年月日时分秒) 转换为 unix时间(1970å¹´1月1日起的时间秒数) */ +int32_t Utc2UnixTime(GnssUtcTime utcTime, uint32_t *unixTime) +{ + if (unixTime == NULL) { + printf("\nerror: [Utc2UnixTime] null pointer!\n"); + return 0; + } + + if (utcTime.month > 12 || utcTime.valid == 0) { + printf("\nerror: [Utc2UnixTime] utcTime invalid!\n"); + return 0; + } + + // 判断是否为闰年 + int32_t *monthDays = (CheckIfLeapYear(utcTime.year) == 1) ? g_leapMonthDays : g_normMonthDays; + + // 计算从1970.01.01开始的unix 秒数 + uint32_t timestamp = 0; + timestamp += (uint32_t)(utcTime.year - UNIX_TIME_START_YEAR) * SECONDS_PER_NORMAL_YEAR; + timestamp += (uint32_t)GetLeapYearNum(UNIX_TIME_START_YEAR, utcTime.year) * SECONDS_PER_DAY; + + for (int32_t i = 1; i < utcTime.month; i++) { + timestamp += (uint32_t)monthDays[i - 1] * SECONDS_PER_DAY; + } + + timestamp += (uint32_t)(utcTime.day - 1) * SECONDS_PER_DAY; + timestamp += (uint32_t)utcTime.hour * SECONDS_PER_HOUR; + timestamp += (uint32_t)utcTime.minute * SECONDS_PER_MIN; + uint32_t timestampSec = (uint32_t)(utcTime.second + utcTime.ms / TIME_UNIT); + + *unixTime = timestamp + timestampSec; + return 1; +} + +/* 计算命令内容校准和 */ +static uint16_t CalcChecksum(uint8_t *buff, uint16_t len) +{ + uint16_t checksum = 0; + uint16_t i = 0; + while (i++ < len) { + checksum += *buff; + buff++; + } + return checksum; +} + +int32_t PgnssInjectUtcTime(tiot_handle handle, GnssUtcTime *utcTime, uint32_t* ts) +{ + uint8_t *buff = (uint8_t *)malloc(GNSS_ENCODE_BUFF_MAX_LEN); + if (buff == NULL) { + printf("\nerror: malloc failed in PgnssINjectUtcTime\r\n"); + return 0; + } + memset_s(buff, GNSS_ENCODE_BUFF_MAX_LEN, 0, GNSS_ENCODE_BUFF_MAX_LEN); + + GnssMsg *hdr = (GnssMsg *)buff; + hdr->cmd = 0x0404; + hdr->sequence = 0; + errno_t copyRet = memcpy_s(hdr->data, (GNSS_ENCODE_BUFF_MAX_LEN - sizeof(GnssMsg)), utcTime, sizeof(GnssUtcTime)); + if (copyRet != EOK) { + printf("\nmemcpy UtcTime failed! Errno is %d\r\n", copyRet); + free(buff); + return 0; + } + hdr->dataLength = sizeof(GnssUtcTime); + hdr->checkSum = CalcChecksum(hdr->data, hdr->dataLength); + int32_t ret = tiot_service_write(handle, buff, (sizeof(GnssMsg) + hdr->dataLength)); + if (ret < 0) { + printf("\nerror: PgnssInjectUtcTime error: %d\r\n", ret); + free(buff); + return 0; + } + if (Utc2UnixTime((*utcTime), ts) == 0) { + printf("\nerror: Utc2UnixTime error\r\n"); + free(buff); + return 0; + } + + free(buff); + return 1; +} + +static uint16_t FillGnssMessageData(uint8_t *inBuff, uint32_t inLen, uint8_t *outBuff, uint32_t outLen) +{ + errno_t ret = memcpy_s(outBuff, outLen, inBuff, inLen); + if (ret != EOK) { + printf("memcpy XgnssData failed! Errno is %d \r\n", ret); + return 0; + } + + return inLen; +} + +static int32_t EncodeGnssMsg(uint8_t *inBuff, uint32_t inLen, uint8_t *outBuff, uint32_t outLen) +{ + uint16_t len = FillGnssMessageData(inBuff, inLen, outBuff, outLen); + if (len > 0) { + return 1; + } + return 0; +} + +static void ListenAck(tiot_handle handle) +{ + int32_t i = 0; + for (;;) { + // 监听 + int32_t ret = tiot_service_read(handle, g_ackBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR); + if (ret > 0) { + uint16_t *type = (uint16_t *)g_ackBuff; + // 二进制消息类型 + if (type[0] == 0) { + g_ackBuff[ret] = '\0'; + printf("%s\r\n", (char *)&g_ackBuff[MSG_CONTENT_IDX]); + } + i++; + } + if (i >= 1) { + printf("\r\ncnt enough\r\n"); + break; + } + } +} + +static int32_t EncodeAndInjectCmd(tiot_handle handle, GnssCmdType cmdType, uint8_t* inBuff, uint32_t inLen) +{ + // 获取GNSS业务消息头 + int32_t len = 0; + uint8_t *buff = (uint8_t *)malloc(GNSS_ENCODE_BUFF_MAX_LEN); + if (buff == NULL) { + printf("\r\nerror: malloc failed in EncodeAndInjectCmd\r\n"); + return 0; + } + memset_s(buff, GNSS_ENCODE_BUFF_MAX_LEN, 0, GNSS_ENCODE_BUFF_MAX_LEN); + + GnssMsg *gnssHdr = (GnssMsg *)buff; + len += sizeof(GnssMsg); + + gnssHdr->sequence = 0; + + int32_t retLen = EncodeGnssMsg(inBuff, inLen, buff + len, (GNSS_ENCODE_BUFF_MAX_LEN - len)); + if (retLen != 1) { + printf("\nerror: Encode Cmd failed: %d\r\n", cmdType); + free(buff); + return retLen; + } + gnssHdr->cmd = cmdType; + gnssHdr->dataLength = inLen; + gnssHdr->checkSum = CalcChecksum(gnssHdr->data, gnssHdr->dataLength); + int32_t ret = tiot_service_write(handle, buff, (sizeof(GnssMsg) + gnssHdr->dataLength)); + if (ret < 0) { + printf("\r\nerror: Inject Cmd failed: %d\r\n", cmdType); + free(buff); + return 0; + } + ListenAck(handle); + printf("\r\nInject Cmd SUCCESS: %x\r\n", cmdType); + free(buff); + return 1; +} + +void PgnssSendFileContent(tiot_handle handle, const char *fileName, GnssCmdType cmdType) +{ + FILE *fp = fopen(fileName, "rb"); + if (fp == NULL) { + printf("\r\nerror: open file failed: %s\r\n", fileName); + return; + } + fseek(fp, 0, SEEK_END); + int32_t len = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (len < 0 || len > PGNSS_FILE_MAX_SIZE) { + fclose(fp); + printf("\r\nerror: get file len failed: %s\r\n", fileName); + return; + } + uint8_t *buff = (uint8_t *)malloc(len); + if (buff == NULL) { + fclose(fp); + printf("\r\nerror: malloc file len failed: %s\r\n", fileName); + return; + } + int32_t dataSize = fread(buff, len, 1, fp); + if (dataSize < 0) { + fclose(fp); + printf("\r\nerror: read file failed: %s\r\n", fileName); + free(buff); + return; + } + fclose(fp); + EncodeAndInjectCmd(handle, cmdType, buff, len); + free(buff); +} + +int32_t FormatFileName(char *fileName, char *dName) +{ + int32_t ret = snprintf_s(fileName, FILE_PATH_LEN, (FILE_PATH_LEN - 1), "%s%s", "/user/userdata/gnss/", dName); + if (ret <= 0) { + return 0; + } + return 1; +} + +int32_t GetEphFileName(int32_t ts, const char *prefix, char *fileName) +{ + int32_t interval = (strcmp(prefix, "GLO") == 0) ? GLO_EPH_VALID_TIME : OTHER_EPH_VALID_TIME; + DIR *dir = opendir("/user/userdata/gnss/"); + if (dir == NULL) { + printf("Failed to open /user/xgnss directory.\r\n"); + return 0; + } + int32_t time, ret; + struct dirent *entry; + for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) { + // 检查文件名 + if (strstr(entry->d_name, ".eph") != NULL) { + char *p = strrchr(entry->d_name, '_'); + if (p != NULL) { + char *q = strstr(entry->d_name, prefix); + if (q != NULL) { + time = atoi(p + 1); + if (abs(time - ts) <= interval) { + ret = FormatFileName(fileName, entry->d_name); + closedir(dir); + return ret; + } + else + { + printf("time:%d,ts:%d,interval:%d\r\n",time,ts,interval); + } + } + } + } + } + closedir(dir); + printf("closedir(dir);\r\n"); + return 0; +} + +void PgnssSendEphFile(tiot_handle handle, const char *prefix, GnssCmdType cmdType, uint32_t ts) +{ + char fileName[FILE_PATH_LEN] = {0}; + int32_t ret = GetEphFileName(ts, prefix, fileName); + if (ret == 0) { + printf("\r\nerror: GetEphFileName failed\r\n"); + return; + } + printf("\nGetEphFileName success\r\n"); + PgnssSendFileContent(handle, fileName, cmdType); +} + +void PgnssInjectAllEph(tiot_handle handle, uint32_t ts) +{ + PgnssSendEphFile(handle, "GPS", CMD_PGNSS_INJECT_EPH_GPS, ts); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send GPS eph success\r\n"); + PgnssSendEphFile(handle, "GLO", CMD_PGNSS_INJECT_EPH_GANSS, ts); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send GLO eph success\r\n"); + PgnssSendEphFile(handle, "BDS", CMD_PGNSS_INJECT_EPH_GANSS, ts); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send BDS eph success\r\n"); + PgnssSendEphFile(handle, "GAL", CMD_PGNSS_INJECT_EPH_GANSS, ts); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send GAL eph success\r\n"); + PgnssSendEphFile(handle, "QZS", CMD_PGNSS_INJECT_EPH_GANSS, ts); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send QZS eph success\r\n"); +} + +void PgnssInjectOtherAssist(tiot_handle handle) +{ + PgnssSendFileContent(handle, "/user/userdata/gnss/GPS_UTC.dat", CMD_PGNSS_INJECT_UTC_GPS); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send GPS_UTC success\r\n"); + PgnssSendFileContent(handle, "/user/userdata/gnss/GPS_RTI.dat", CMD_PGNSS_INJECT_RTI_GPS); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send GPS_RTI success\r\n"); + PgnssSendFileContent(handle, "/user/userdata/gnss/GPS_ION.dat", CMD_PGNSS_INJECT_ION_GPS); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send GPS_ION success\r\n"); + PgnssSendFileContent(handle, "/user/userdata/gnss/GLO_RTI.dat", CMD_PGNSS_INJECT_RTI_GANSS); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send GLO_RTI success\r\n"); + PgnssSendFileContent(handle, "/user/userdata/gnss/GLO_AUX.dat", CMD_PGNSS_INJECT_AUX_GANSS); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send GLO_AUX success\r\n"); + PgnssSendFileContent(handle, "/user/userdata/gnss/BDS_RTI.dat", CMD_PGNSS_INJECT_RTI_GANSS); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send BDS_RTI success\r\n"); + PgnssSendFileContent(handle, "/user/userdata/gnss/GAL_RTI.dat", CMD_PGNSS_INJECT_RTI_GANSS); + osal_msleep(INJECT_SLEEP_MS_TIME); + printf("send GAL_RTI success\r\n"); +} + +void PgnssInject(tiot_handle handle, uint32_t ts) +{ + // 注入Pgnss辅助数据 + PgnssInjectAllEph(handle, ts); + PgnssInjectOtherAssist(handle); +} + + +// 以下为使用PGNSS解析数据合并输出接口生成的星历文件进行注入的代码 +// 全局变量,存储AGNSS文件夹路径 +static char *g_agnss_folder_path = NULL; + +// 新增接口:设置AGNSS文件夹路径 +void set_agnss_folder_path(const char *path) +{ + if (g_agnss_folder_path != NULL) { + free(g_agnss_folder_path); + g_agnss_folder_path = NULL; + } + if (path != NULL) { + g_agnss_folder_path = strdup(path); + } +} + +// 新增接口:获取AGNSS文件夹路径 +const char* get_agnss_folder_path(void) +{ + return g_agnss_folder_path != NULL ? g_agnss_folder_path : "/user/userdata/gnss"; +} + +// 新增接口:清理AGNSS文件夹路径 +void cleanup_pgnss_encode_agnss_folder_path(void) +{ + if (g_agnss_folder_path != NULL) { + free(g_agnss_folder_path); + g_agnss_folder_path = NULL; + } +} + +int32_t GetNonGloEphFileName(int32_t ts, char *fileName) +{ + const char prefix[] = "NonGlo"; + const char *search_path = get_agnss_folder_path(); + if(search_path == NULL) + { + printf("search_path == NULL\r\n"); + return 0; + } + DIR *dir = opendir(search_path); + if (dir == NULL) { + printf("Failed to open directory: %s\r\n", search_path); + return 0; + } + int32_t time, ret; + int32_t minDist = OTHER_EPH_VALID_TIME; + int32_t closestTime = 0; + struct dirent *entry; + for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) { + // 检查文件名 + if (strstr(entry->d_name, ".eph") != NULL) { + char *p = strrchr(entry->d_name, '_'); + if (p != NULL) { + char *q = strstr(entry->d_name, prefix); + if (q != NULL) { + time = atoi(p + 1); + // 查找星历文件时间戳与当前时间相差2小时以内且距离最近的 + if (abs(time - ts) < minDist) { + minDist = abs(time - ts); + closestTime = time; + } + else + { + printf("time:%d,ts:%d,minDist:%d\r\n",time,ts,minDist); + } + } + } + } + } + if (closestTime != 0) { + ret = snprintf_s(fileName, FILE_PATH_LEN, (FILE_PATH_LEN - 1), "%s/NonGlo_%d.eph", search_path, closestTime); + printf("closest eph fileName:%s\r\n", fileName); + closedir(dir); + return ((ret <= 0) ? 0 : 1); + } + else + { + printf("closestTime == 0\r\n"); + } + closedir(dir); + return 0; +} + +int32_t GetGloEphFileName(int32_t ts, char *fileName) +{ + const char prefix[] = "GLO"; + const char *search_path = get_agnss_folder_path(); + if(search_path == NULL) + { + printf("search_path == NULL\r\n"); + return 0; + } + DIR *dir = opendir(search_path); + if (dir == NULL) { + printf("search_path open failed %s\r\n", search_path); + return 0; + } + int32_t ephTime, ret; + struct dirent *entry; + for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) { + // 检查文件名 + if (strstr(entry->d_name, ".eph") != NULL) { + char *p = strrchr(entry->d_name, '_'); + if (p != NULL) { + char *q = strstr(entry->d_name, prefix); + if (q != NULL) { + ephTime = atoi(p + 1); + printf("ephTime:%ld, ts:%ld\n", ephTime, ts); + // 当前时间大于GLO星历文件时间戳,则需要选取相差2小时以内的星历 + // 当前时间小于GLO星历文件时间戳,则需要选取相差小于15分钟的星历 + if (((ts - ephTime) >= 0 && abs(ephTime - ts) < OTHER_EPH_VALID_TIME) || + ((ts - ephTime) <= 0 && abs(ephTime - ts) < GLO_EPH_VALID_TIME)) { + ret = FormatFileName(fileName, entry->d_name); + printf("glo eph fileName:%s\n", fileName); + closedir(dir); + return ret; + } + } + } + } + } + closedir(dir); + return 0; +} + +void PgnssSendNonGloEph(tiot_handle handle, const char *fileName) +{ + FILE *fp = fopen(fileName, "rb"); + if (fp == NULL) { + printf("\nerror: open file failed: %s\r\n", fileName); + return; + } + fseek(fp, 0, SEEK_END); + int32_t len = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (len < 0 || len > PGNSS_FILE_MAX_SIZE) { + fclose(fp); + printf("\nerror: get file len failed: %s\r\n", fileName); + return; + } + uint8_t *buff = (uint8_t *)malloc(len); + if (buff == NULL) { + fclose(fp); + printf("\nerror: malloc file len failed: %s\r\n", fileName); + return; + } + int32_t dataSize = fread(buff, len, 1, fp); + if (dataSize < 0) { + fclose(fp); + printf("\nerror: read file failed: %s\r\n", fileName); + free(buff); + return; + } + fclose(fp); + int32_t fileLen = 0; + for (int32_t i = 0; i < NON_GLO_GNSS_TYPES && fileLen <= len; i++) { + EphHeadInfo *ephHdr = (EphHeadInfo *)(buff + fileLen); + EncodeAndInjectCmd(handle, ephHdr->cmd, (buff + fileLen + sizeof(EphHeadInfo)), ephHdr->len); + fileLen += (ephHdr->len + sizeof(EphHeadInfo)); + osal_msleep(INJECT_SLEEP_MS_TIME); + } + free(buff); +} + +void PgnssSendGloEph(tiot_handle handle, const char *fileName, int32_t ts) +{ + FILE *fp = fopen(fileName, "rb"); + if (fp == NULL) { + printf("\nerror: open file failed: %s\r\n", fileName); + return; + } + fseek(fp, 0, SEEK_END); + int32_t len = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (len < 0 || len > PGNSS_FILE_MAX_SIZE) { + fclose(fp); + printf("\nerror: get file len failed: %s\r\n", fileName); + return; + } + uint8_t *buff = (uint8_t *)malloc(len); + if (buff == NULL) { + fclose(fp); + printf("\nerror: malloc file len failed: %s\r\n", fileName); + return; + } + int32_t dataSize = fread(buff, len, 1, fp); + if (dataSize < 0) { + fclose(fp); + printf("\nerror: read file failed: %s\r\n", fileName); + free(buff); + return; + } + fclose(fp); + int32_t fileLen = 0; + for (int32_t i = 0; i < GLO_EPH_NUM_ONE_FILE && fileLen <= len; i++) { + EphHeadInfo *ephHdr = (EphHeadInfo *)(buff + fileLen); + printf("glo eph, time:%u, ts:%d\r\n", ephHdr->time, ts); + if (abs((int32_t)ephHdr->time - ts) < GLO_EPH_VALID_TIME) { + EncodeAndInjectCmd(handle, ephHdr->cmd, (buff + fileLen + sizeof(EphHeadInfo)), ephHdr->len); + osal_msleep(INJECT_SLEEP_MS_TIME); + break; + } + fileLen += (ephHdr->len + sizeof(EphHeadInfo)); + } + free(buff); +} + +int32_t PgnssInjectAllEphLessFiles(tiot_handle handle, uint32_t ts) +{ + char fileName[FILE_PATH_LEN] = {0}; + if (GetNonGloEphFileName(ts, fileName) == 0) { + printf("\nerror: GetNonGloEphFileName failed\r\n"); + return 0; // 返回失败状态 + } + PgnssSendNonGloEph(handle, fileName); + if (GetGloEphFileName(ts, fileName) == 0) { + printf("\nerror: GetGloEphFileName failed\r\n"); + return 0; // 返回失败状态 + } + PgnssSendGloEph(handle, fileName, ts); + return 1; // 返回成功状态 +} + +void PgnssSendOtherAssistInfo(tiot_handle handle, const char *fileName) +{ + FILE *fp = fopen(fileName, "rb"); + if (fp == NULL) { + printf("\nerror: open file failed: %s\r\n", fileName); + return; + } + fseek(fp, 0, SEEK_END); + int32_t len = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (len < 0 || len > PGNSS_FILE_MAX_SIZE) { + fclose(fp); + printf("\nerror: get file len failed: %s\r\n", fileName); + return; + } + uint8_t *buff = (uint8_t *)malloc(len); + if (buff == NULL) { + fclose(fp); + printf("\nerror: malloc file len failed: %s\r\n", fileName); + return; + } + int32_t dataSize = fread(buff, len, 1, fp); + if (dataSize < 0) { + fclose(fp); + printf("\nerror: read file failed: %s\r\n", fileName); + free(buff); + return; + } + fclose(fp); + int32_t fileLen = 0; + for (int32_t i = 0; i < OTHER_ASSIST_TYPES && fileLen <= len; i++) { + OtherAssistHeadInfo *otherHdr = (OtherAssistHeadInfo *)(buff + fileLen); + EncodeAndInjectCmd(handle, otherHdr->cmd, (buff + fileLen + sizeof(OtherAssistHeadInfo)), otherHdr->len); + fileLen += (otherHdr->len + sizeof(OtherAssistHeadInfo)); + osal_msleep(INJECT_SLEEP_MS_TIME); + } + free(buff); +} + +int32_t PgnssInjectOtherAssistLessFiles(tiot_handle handle) +{ + char *assist_file_path = malloc(256); + if (assist_file_path == NULL) { + printf("Failed to allocate memory for assist file path\n"); + return 0; + } + + const char *agnss_folder_path = get_agnss_folder_path(); + int ret = snprintf(assist_file_path, 256, "%s/AssistInfo.dat", agnss_folder_path); + if (ret < 0 || ret >= 256) { + printf("ERROR: snprintf failed or buffer overflow for assist_file_path\n"); + free(assist_file_path); + return 0; + } + PgnssSendOtherAssistInfo(handle, assist_file_path); + + free(assist_file_path); + return 1; // 返回成功状态 +} + +// 注入PGNSS解析数据合并输出接口生成的星历文件 +int32_t PgnssInjectLessFiles(tiot_handle handle, uint32_t ts, const char *agnss_folder_path) +{ + // 设置AGNSS文件夹路径 + set_agnss_folder_path(agnss_folder_path); + + // 注入Pgnss辅助数据 + int32_t ephRet = PgnssInjectAllEphLessFiles(handle, ts); + int32_t assistRet = PgnssInjectOtherAssistLessFiles(handle); + + // 如果星历注入失败,返回失败状态 + if (ephRet == 0) { + printf("PGNSS ephemeris injection failed\r\n"); + return 0; + } + + return 1; // 返回成功状态 } \ No newline at end of file diff --git a/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_encode.h b/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_encode.h index a666edc91..8456ef0a9 100644 --- a/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_encode.h +++ b/code/sdk/zhihui/services/gnss/sample/pgnss_sample/pgnss_encode.h @@ -1,16 +1,21 @@ -/* - * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. - * Description: pgnss encode - * Author: - * Create: - */ -#ifndef PGNSS_ENCODE_H -#define PGNSS_ENCODE_H - -#include "gnss_datatypes.h" -#include "tiot_service_interface.h" - -int32_t PgnssInjectUtcTime(tiot_handle handle, GnssUtcTime *utcTime, uint32_t* ts); -void PgnssInject(tiot_handle handle, uint32_t ts); -void PgnssInjectLessFiles(tiot_handle handle, uint32_t ts); +/* + * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. + * Description: pgnss encode + * Author: + * Create: + */ +#ifndef PGNSS_ENCODE_H +#define PGNSS_ENCODE_H + +#include "gnss_datatypes.h" +#include "tiot_service_interface.h" + +int32_t PgnssInjectUtcTime(tiot_handle handle, GnssUtcTime *utcTime, uint32_t* ts); +void PgnssInject(tiot_handle handle, uint32_t ts); +int32_t PgnssInjectLessFiles(tiot_handle handle, uint32_t ts, const char *agnss_folder_path); + +// 新增接口:获取时间戳文件夹路径 +const char* get_agnss_folder_path(void); +void set_agnss_folder_path(const char *path); +void cleanup_pgnss_encode_agnss_folder_path(void); #endif \ No newline at end of file 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 a97b0783e..9843b9174 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 @@ -1,423 +1,795 @@ -/* - * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. - * Description: pgnss sample - * Author: - * Create: - */ -#include "pgnss_sample.h" -#include -#include -#include -#include -#include -#include "securec.h" -#include "tiot_service_interface.h" -#include "pm_definition.h" -#include "gnss_datatypes.h" -#include "pgnss_encode.h" -#include "NMEA0183.h" -#include "sys/time.h" -#include "time.h" -#include "gnss_ctl.h" - - -#define PGNSS_FIXMODEALL_NMEADEF_SAMPLE 0 -#define PGNSS_LESS_FILES_FIXMODEALL_NMEADEF_SAMPLE 0 - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#endif -#define MSG_TYPE_BINRY 0 -#define MSG_TYPE_ASCII 1 -#define LISTEN_DATA_MAX_LINES 1000 - -static FILE* g_gnssLogFp = NULL; -static uint8_t g_gnssServiceBuff[REPORT_MAX_BYTES] = { 0 }; - -typedef int32_t (*GnssCfgFunc)(tiot_handle handle); - -typedef struct { - uint16_t sampleId; - GnssCfgFunc cfgHandle; -} GnssSamplesCfgTable; - -static NMEA0183 g_nmeadata={0}; -static gps_data_t g_global_gpsData={0}; - -/**GPS状态位*/ -static int g_is_pgnss_poweron=0; -static int g_is_pgnss_logon=0; -static int g_pgnss_stopflag=0; - -static char *pgnss_log = NULL; - -static int32_t QryVersion(tiot_handle handle) -{ - const uint8_t qryVersion[] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; - // 查询版本号 - int32_t ret = tiot_service_write(handle, qryVersion, sizeof(qryVersion)); - if (ret < 0) { - printf("\nerror: QryVersion error: %d\r\n", ret); - return 0; - } - return 1; -} - -static int decode_nmea(char c) -{ - int ret=0; - ret=0; - if(nmea_decode(&g_nmeadata,c) ==1 ) ///调用解析函数 - { - dump_nmea_str(&(g_nmeadata.gpsParse)); - if (g_nmeadata.gpsParse.sentence_type == GPS_SENTENCE_TH002 ) - { - //一组数据最后一条 - memcpy_s(&g_global_gpsData,sizeof(gps_data_t),&(g_nmeadata.gpsData),sizeof(gps_data_t)); - ret = 1; - memset(&g_nmeadata,0,sizeof(g_nmeadata)); - } - } - - return ret; -} - -gps_data_t * getPGPSGlobaldata(void) -{ - return &g_global_gpsData; -} - - -// 注入PGNSS,使用默认配置启动 -int32_t InjectPgnssCfgAutoStartFixModeAndNmeaDefault(tiot_handle handle) -{ - const uint8_t cfgLogLevelInfo[] = {0x03, 0x00, 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x10, 0x01, 0x00, 0x03}; - - // 配置log级别:info级别。 - int32_t ret = tiot_service_write(handle, cfgLogLevelInfo, sizeof(cfgLogLevelInfo)); - if (ret < 0) { - printf("\nerror: cfgLogLevelInfo error: %d\r\n", ret); - return 0; - } - - // 注入UTC时间, 注入Pgnss辅助数据前必须先注入参考时间 - GnssUtcTime utcTime = {2024, 2, 26, 6, 0, 0, 0, 1}; // 需要用当前的UTC时间替换 - - time_t rawtime; - struct tm* timeinfo; - - time(&rawtime); // 获取UTC时间戳 - timeinfo = gmtime(&rawtime); // 转换为UTC时间(无时区偏移) - - utcTime.year = timeinfo->tm_year + 1900; - utcTime.month = timeinfo->tm_mon + 1; - utcTime.day = timeinfo->tm_mday; - utcTime.hour = timeinfo->tm_hour; - utcTime.minute = timeinfo->tm_min; - utcTime.second = timeinfo->tm_sec; - - printf("year[%d], mon[%d], day[%d], hour[%d], min[%d], sec[%d] \r\n", - utcTime.year,utcTime.month,utcTime.day, - utcTime.hour,utcTime.minute,utcTime.second); - - uint32_t ts = 0; - ret = PgnssInjectUtcTime(handle, &utcTime, &ts); - if (ret == 0) { - printf("\nerror: PgnssInjectUtcTime failed!\r\n"); - return 0; - } - printf("\nPgnssInjectUtcTime success!\r\n"); - - // PGNSS注入 - // 注意,默认PGNSS星历文件存放在/user/xgnss/目录中,如修改目录,请全局搜索替换 - PgnssInject(handle, ts); - - return 1; -} - -// 注入PGNSS,使用默认配置启动 -int32_t InjectPgnssLessFilesCfgAutoStartFixModeAndNmeaDefault(tiot_handle handle) -{ - const uint8_t cfgLogLevelInfo[] = {0x03, 0x00, 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x10, 0x01, 0x00, 0x03}; - - // 配置log级别:info级别。 - int32_t ret = tiot_service_write(handle, cfgLogLevelInfo, sizeof(cfgLogLevelInfo)); - if (ret < 0) { - printf("\nerror: cfgLogLevelInfo error: %d\r\n", ret); - return 0; - } - - // 注入UTC时间, 注入Pgnss辅助数据前必须先注入参考时间 - GnssUtcTime utcTime = {2024, 3, 14, 12, 0, 0, 0, 1}; // 需要用当前的UTC时间替换 - - time_t rawtime; - struct tm* timeinfo; - - time(&rawtime); // 获取UTC时间戳 - timeinfo = gmtime(&rawtime); // 转换为UTC时间(无时区偏移) - - utcTime.year = timeinfo->tm_year + 1900; - utcTime.month = timeinfo->tm_mon + 1; - utcTime.day = timeinfo->tm_mday; - utcTime.hour = timeinfo->tm_hour; - utcTime.minute = timeinfo->tm_min; - utcTime.second = timeinfo->tm_sec; - - printf("year[%d], mon[%d], day[%d], hour[%d], min[%d], sec[%d] \r\n", - utcTime.year,utcTime.month,utcTime.day, - utcTime.hour,utcTime.minute,utcTime.second); - - - uint32_t ts = 0; - ret = PgnssInjectUtcTime(handle, &utcTime, &ts); - if (ret == 0) { - printf("\nerror: PgnssInjectUtcTime failed!\r\n"); - return 0; - } - printf("\nPgnssInjectUtcTime success!\r\n"); - - // PGNSS注入 - // 注意,默认PGNSS星历文件存放在/user/xgnss/目录中,如修改目录,请全局搜索替换 - PgnssInjectLessFiles(handle, ts); - - return 1; -} - -static const GnssSamplesCfgTable g_gnssSamplesCfg[] = { - // {PGNSS_FIXMODEALL_NMEADEF_SAMPLE, InjectPgnssCfgAutoStartFixModeAndNmeaDefault}, - {PGNSS_LESS_FILES_FIXMODEALL_NMEADEF_SAMPLE, InjectPgnssLessFilesCfgAutoStartFixModeAndNmeaDefault} -}; - -static int32_t StartGnss(tiot_handle handle) -{ - const uint8_t startCmd[] = {0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; - // 启动GNSS - int32_t ret = tiot_service_write(handle, startCmd, sizeof(startCmd)); - if (ret < 0) { - printf("\nerror: start gnss error: %d\r\n", ret); - return 0; - } - printf("\nstart gnss\r\n"); - return 1; -} - -static int32_t StopGnss(tiot_handle handle) -{ - const uint8_t stopCmd[] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - // 停止GNSS - int32_t ret = tiot_service_write(handle, stopCmd, sizeof(stopCmd)); - if (ret < 0) { - printf("\nerror: stop gnss error: %d\r\n", ret); - return 0; - } - printf("\nstop gnss\r\n"); - return 1; -} - - -static void ListenGnssData(tiot_handle handle) -{ - int32_t i = 0; - // 写日志 - for (;;) { // 写日志条件 - - if (i >= LISTEN_DATA_MAX_LINES) { - printf("\r\ncnt enough\r\n"); - break; - } - if (g_pgnss_stopflag == 1) - { - break; - } - // 监听 - int32_t ret = tiot_service_read(handle, g_gnssServiceBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR); - if (ret > 0) { - 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) - { - // dump_location_data(&g_global_gpsData); - char temp_buf[512]; - dump_location_data_to_buf(&g_global_gpsData, temp_buf, sizeof(temp_buf)); - - // 追加到pgnss_log中 - if (pgnss_log != NULL) { - int current_len = strlen(pgnss_log); - int data_len = strlen(temp_buf); - if (current_len + data_len < 2047) { // 留1字节给字符串结束符 - snprintf(pgnss_log + current_len, 2048 - current_len, "%s", temp_buf); - } - } - - printf("decode_nmea done\r\n"); - } - } - } - i++; - } - - } -} - -void PGnssServerStop(void) -{ - g_pgnss_stopflag=1; -} - -int getPGnssServerStat(void) -{ - return g_is_pgnss_poweron; -} - -int is_PGnssLogEnabled(void) -{ - return g_is_pgnss_logon; -} - -int PGnssLogEnable(bool enable) -{ - if (enable) - g_is_pgnss_logon = 1; - else - g_is_pgnss_logon = 0; - - return g_is_pgnss_logon; -} - - -void PGnssServerStart(void) -{ - printf("\nenter gnss samples\r\n"); - - if (pgnss_log == NULL) - { - pgnss_log = (char *)malloc(2048); - if (pgnss_log == NULL) { - printf("error: malloc pgnss_log failed!\n"); - return; - } - memset(pgnss_log, 0, 2048); - } - - if(g_is_pgnss_poweron == 1) - { - printf("gnss already on\r\n"); - if (pgnss_log != NULL) { - free(pgnss_log); - pgnss_log = NULL; - } - return ; - } - uapi_pm_add_sleep_veto(PM_ID_SYS); - - #ifdef DOWNLOAD_GNSS_SWITCH - download_gnss_switch(SWITCH_TO_GNSS); - #endif - g_is_pgnss_poweron = 1; - g_pgnss_stopflag = 0; - sw_debug_uart_deinit(); - // Step1: init - int32_t ret = tiot_service_init(); - if (ret != 0) { - printf("tiot service init fail\r\n"); - g_is_pgnss_poweron = 0; - g_pgnss_stopflag = 1; - if (pgnss_log != NULL) { - free(pgnss_log); - pgnss_log = NULL; - } - return; - } - - // 打开日志文件 - if (g_is_pgnss_logon) - { - g_gnssLogFp = fopen("/user/log/gnss.log", "w"); - if (g_gnssLogFp == NULL) { - printf("error: open log file error\n"); - if (pgnss_log != NULL) { - free(pgnss_log); - pgnss_log = NULL; - } - return; - } - } - printf("before open tiot service\n"); - - // Step2: power on gnss - tiot_handle handle = tiot_service_open("gn71", NULL); - if (handle == 0) { - printf("open tiot service fail\r\n"); - g_is_pgnss_poweron = 0; - g_pgnss_stopflag = 1; - if (pgnss_log != NULL) { - free(pgnss_log); - pgnss_log = NULL; - } - return; - } - printf("open tiot service success\r\n"); - - int32_t cfgRet; - // ---- loop ---------- - for (uint16_t i = 0; i < ARRAY_SIZE(g_gnssSamplesCfg); i++) { - cfgRet = 0; - if (g_gnssSamplesCfg[i].sampleId == i) { - // Step3: config gnss - if (g_gnssSamplesCfg[i].cfgHandle != NULL) { - cfgRet = g_gnssSamplesCfg[i].cfgHandle(handle); - } - if (cfgRet == 0) { - continue; - } - printf("cfg sample id:%u\r\n", g_gnssSamplesCfg[i].sampleId); - QryVersion(handle); - - // Step4: start gnss - if (StartGnss(handle) == 0) { - continue; - } - // Step5: listening gnss data - ListenGnssData(handle); - // Step6: stop gnss - if (StopGnss(handle) == 0) { - continue; - } - } - } - // --------------------- - // Step7: power off gnss - tiot_service_close(handle); - // 关日志文件 - if (g_is_pgnss_logon) - { - fclose(g_gnssLogFp); - g_gnssLogFp = NULL; - } - // Step8: deinit - tiot_service_deinit(); - - #ifdef DOWNLOAD_GNSS_SWITCH - download_gnss_switch(SWITCH_TO_DOWNLOAD); - #endif - uapi_pm_remove_sleep_veto(PM_ID_SYS); - g_is_pgnss_poweron=0; - sw_debug_uart_deinit(); - uart_config_init(); - printf("finish gnss samples\r\n"); - - printf("pgnss_log: %s\r\n", pgnss_log); - // 释放pgnss_log内存 - if (pgnss_log != NULL) { - free(pgnss_log); - pgnss_log = NULL; - } -} +/* +* Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved. +* Description: pgnss sample +* Author: +* Create: +*/ +#include "pgnss_sample.h" +#include +#include +#include +#include "securec.h" +#include "tiot_service_interface.h" +#include "pm_definition.h" +#include "gnss_datatypes.h" +#include "pgnss_encode.h" +#include "NMEA0183.h" +#include "sys/time.h" +#include "time.h" +#include "gnss_ctl.h" +#include "custom_runtime.h" +#include "los_base.h" +#include "ConfigModelC.h" +#include "gnss_http_server.h" +#include "custom_utils.h" +#include +#include +// #include "gnss_sample.h" + +#define PGNSS_DATA_PATH "/user/userdata/gnss" + +#define PGNSS_FIXMODEALL_NMEADEF_SAMPLE 0 +#define PGNSS_LESS_FILES_FIXMODEALL_NMEADEF_SAMPLE 0 + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#endif +#define MSG_TYPE_BINRY 0 +#define MSG_TYPE_ASCII 1 +#define LISTEN_DATA_MAX_LINES 1000 + +static FILE* g_gnssLogFp = NULL; +static uint8_t g_gnssServiceBuff[REPORT_MAX_BYTES] = { 0 }; + +typedef int32_t (*GnssCfgFunc)(tiot_handle handle); + +typedef struct { + uint16_t sampleId; + GnssCfgFunc cfgHandle; +} GnssSamplesCfgTable; + +static NMEA0183 g_nmeadata={0}; +static gps_data_t g_global_gpsData={0}; + +/**GPS状态位*/ +static int g_is_pgnss_poweron=0; +static int g_is_pgnss_logon=0; +static int g_pgnss_stopflag=0; +static int g_cold_start_pgnss_stopflag = 0; + +static char *pgnss_log = NULL; + +// 全局变量,存储当前有效的时间戳文件夹路径 +static char *g_current_agnss_folder = NULL; + +static int32_t QryVersion(tiot_handle handle) +{ + const uint8_t qryVersion[] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; + // 查询版本号 + int32_t ret = tiot_service_write(handle, qryVersion, sizeof(qryVersion)); + if (ret < 0) { + printf("\nerror: QryVersion error: %d\r\n", ret); + return 0; + } + return 1; +} + +static int decode_nmea(char c) +{ + int ret=0; + ret=0; + if(nmea_decode(&g_nmeadata,c) ==1 ) ///调用解析函数 + { + dump_nmea_str(&(g_nmeadata.gpsParse)); + if (g_nmeadata.gpsParse.sentence_type == GPS_SENTENCE_TH002 ) + { + //一组数据最后一条 + memcpy_s(&g_global_gpsData,sizeof(gps_data_t),&(g_nmeadata.gpsData),sizeof(gps_data_t)); + ret = 1; + memset(&g_nmeadata,0,sizeof(g_nmeadata)); + } + } + + return ret; +} + +gps_data_t * getPGPSGlobaldata(void) +{ + return &g_global_gpsData; +} + + +// 添加普通GNSS冷启动配置函数的声明和实现 +// 从gnss_sample.c中复制冷启动相关的命令定义 + +// 函数声明 +void PGnssServerStartColdStart(void); +static int pgnss_startup_check(void); +static int check_agnss_files_exist(void); + +// 获取当前有效的时间戳文件夹路径 +const char* get_current_agnss_folder_path(void) +{ + if (g_current_agnss_folder != NULL) { + return g_current_agnss_folder; + } + return PGNSS_DATA_PATH; +} + +// 清理AGNSS文件夹路径内存 +void cleanup_agnss_folder_path(void) +{ + if (g_current_agnss_folder != NULL) { + free(g_current_agnss_folder); + 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 cfgFixModeAllCmd[] = {0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00}; +static const uint8_t cfgNmeaAllCmd[] = {0x03, 0x00, 0x04, 0x01, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x02, 0x00, 0xff, 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}; + +// 普通GNSS冷启动配置函数实现 +static int32_t CfgColdStartFixModeGpsNmeaAll(tiot_handle handle) +{ + // 配置启动模式:冷启动模式 + int32_t ret = tiot_service_write(handle, cfgColdStartCmd, sizeof(cfgColdStartCmd)); + if (ret < 0) { + printf("\nerror: cfgColdStartCmd error: %d\r\n", ret); + return 0; + } + + // 配置使能的GNSS星座:GPS + ret = tiot_service_write(handle, cfgFixModeAllCmd, sizeof(cfgFixModeAllCmd)); + if (ret < 0) { + printf("\nerror: cfgFixModeAllCmd error: %d\r\n", ret); + return 0; + } + + // 配置上报NMEA类型:PNT/ZDA/VTG/RMC/GSV/GSA/GLL/GGA + ret = tiot_service_write(handle, cfgNmeaAllCmd, sizeof(cfgNmeaAllCmd)); + if (ret < 0) { + printf("\nerror: cfgNmeaAllCmd error: %d\r\n", ret); + return 0; + } + + 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; + } + + 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; + } + + printf("Cold start mode configured successfully\r\n"); + return 1; +} + +// 修改后的PGNSS配置函数,支持降级到普通GNSS +int32_t InjectPgnssWithFallbackToColdStart(tiot_handle handle) +{ + const uint8_t cfgLogLevelInfo[] = {0x03, 0x00, 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x10, 0x01, 0x00, 0x03}; + + // 配置log级别:info级别。 + int32_t ret = tiot_service_write(handle, cfgLogLevelInfo, sizeof(cfgLogLevelInfo)); + if (ret < 0) { + printf("\nerror: cfgLogLevelInfo error: %d\r\n", ret); + return 0; + } + + // 注入UTC时间, 注入Pgnss辅助数据前必须先注入参考时间 + GnssUtcTime utcTime = {2024, 2, 26, 6, 0, 0, 0, 1}; // 需要用当前的UTC时间替换 + + time_t rawtime; + struct tm* timeinfo; + + time(&rawtime); // 获取UTC时间戳 + timeinfo = gmtime(&rawtime); // 转换为UTC时间(无时区偏移) + + utcTime.year = timeinfo->tm_year + 1900; + utcTime.month = timeinfo->tm_mon + 1; + utcTime.day = timeinfo->tm_mday; + utcTime.hour = timeinfo->tm_hour; + utcTime.minute = timeinfo->tm_min; + utcTime.second = timeinfo->tm_sec; + + printf("year[%d], mon[%d], day[%d], hour[%d], min[%d], sec[%d] \r\n", + utcTime.year,utcTime.month,utcTime.day, + utcTime.hour,utcTime.minute,utcTime.second); + + uint32_t ts = 0; + ret = PgnssInjectUtcTime(handle, &utcTime, &ts); + if (ret == 0) { + printf("\nerror: PgnssInjectUtcTime failed!\r\n"); + return 0; + } + printf("\nPgnssInjectUtcTime success!\r\n"); + + // PGNSS注入 + // 使用当前有效的时间戳文件夹路径 + // 设置AGNSS文件夹路径到pgnss_encode模块 + set_agnss_folder_path(get_current_agnss_folder_path()); + int32_t injectRet = PgnssInjectLessFiles(handle, ts, get_current_agnss_folder_path()); + if (injectRet == 0) { + // PGNSS注入失败,设置停止标志并重新启动 + printf("PGNSS injection failed, restarting with cold start mode\r\n"); + // if(uapi_dev_runtime_get_cat1_powerstat()) + // { + + // } + // else + // { + // 设置停止标志 + g_cold_start_pgnss_stopflag = 1; + // } + + return 0; // 返回0表示需要重新启动 + } + + printf("PGNSS injection completed successfully\r\n"); + return 1; +} + + +// 注入PGNSS,使用默认配置启动 +int32_t InjectPgnssLessFilesCfgAutoStartFixModeAndNmeaDefault(tiot_handle handle) +{ + // 调用新的带降级功能的函数 + return InjectPgnssWithFallbackToColdStart(handle); +} + +static const GnssSamplesCfgTable g_gnssSamplesCfg[] = { + // {PGNSS_FIXMODEALL_NMEADEF_SAMPLE, InjectPgnssCfgAutoStartFixModeAndNmeaDefault}, + {PGNSS_LESS_FILES_FIXMODEALL_NMEADEF_SAMPLE, InjectPgnssLessFilesCfgAutoStartFixModeAndNmeaDefault} +}; + +static int32_t StartGnss(tiot_handle handle) +{ + const uint8_t startCmd[] = {0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}; + // 启动GNSS + int32_t ret = tiot_service_write(handle, startCmd, sizeof(startCmd)); + if (ret < 0) { + printf("\nerror: start gnss error: %d\r\n", ret); + return 0; + } + printf("\nstart gnss\r\n"); + return 1; +} + +static int32_t StopGnss(tiot_handle handle) +{ + const uint8_t stopCmd[] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + // 停止GNSS + int32_t ret = tiot_service_write(handle, stopCmd, sizeof(stopCmd)); + if (ret < 0) { + printf("\nerror: stop gnss error: %d\r\n", ret); + return 0; + } + printf("\nstop gnss\r\n"); + return 1; +} + + +static void ListenGnssData(tiot_handle handle) +{ + int32_t i = 0; + // 写日志 + for (;;) { // 写日志条件 + + if (i >= LISTEN_DATA_MAX_LINES) { + printf("\r\ncnt enough\r\n"); + break; + } + if (g_pgnss_stopflag == 1) + { + break; + } + // 监听 + int32_t ret = tiot_service_read(handle, g_gnssServiceBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR); + if (ret > 0) { + 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) + { + // dump_location_data(&g_global_gpsData); + char temp_buf[512]; + dump_location_data_to_buf(&g_global_gpsData, temp_buf, sizeof(temp_buf)); + + // 追加到pgnss_log中 + if (pgnss_log != NULL) { + int current_len = strlen(pgnss_log); + int data_len = strlen(temp_buf); + if (current_len + data_len < 2047) { // 留1字节给字符串结束符 + snprintf(pgnss_log + current_len, 2048 - current_len, "%s", temp_buf); + } + } + + printf("decode_nmea done\r\n"); + } + } + } + i++; + } + + } +} + +void PGnssServerStop(void) +{ + g_pgnss_stopflag=1; + + // 清理pgnss_sample模块的内存 + cleanup_agnss_folder_path(); + + // 清理pgnss_encode模块的内存 + cleanup_pgnss_encode_agnss_folder_path(); + + if (pgnss_log != NULL) { + free(pgnss_log); + pgnss_log = NULL; + } +} + +int getPGnssServerStat(void) +{ + return g_is_pgnss_poweron; +} + +int is_PGnssLogEnabled(void) +{ + return g_is_pgnss_logon; +} + +int PGnssLogEnable(bool enable) +{ + if (enable) + g_is_pgnss_logon = 1; + else + g_is_pgnss_logon = 0; + + return g_is_pgnss_logon; +} + +// 直接启动冷启动模式的函数 +void PGnssServerStartColdStart(void) +{ + printf("\nenter cold start mode\r\n"); + + if (pgnss_log == NULL) + { + pgnss_log = (char *)malloc(2048); + if (pgnss_log == NULL) { + printf("error: malloc pgnss_log failed!\n"); + return; + } + memset(pgnss_log, 0, 2048); + } + + uapi_pm_add_sleep_veto(PM_ID_SYS); + + #ifdef DOWNLOAD_GNSS_SWITCH + download_gnss_switch(SWITCH_TO_GNSS); + #endif + g_is_pgnss_poweron = 1; + g_pgnss_stopflag = 0; + g_cold_start_pgnss_stopflag = 0; + sw_debug_uart_deinit(); + + // Step1: init + int32_t ret = tiot_service_init(); + if (ret != 0) { + printf("tiot service init fail\r\n"); + g_is_pgnss_poweron = 0; + g_pgnss_stopflag = 1; + if (pgnss_log != NULL) { + free(pgnss_log); + pgnss_log = NULL; + } + return; + } + + // 打开日志文件 + if (g_is_pgnss_logon) + { + g_gnssLogFp = fopen("/user/log/gnss.log", "w"); + if (g_gnssLogFp == NULL) { + printf("error: open log file error\n"); + if (pgnss_log != NULL) { + free(pgnss_log); + pgnss_log = NULL; + } + return; + } + } + printf("before open tiot service for cold start\n"); + + // Step2: power on gnss + tiot_handle handle = tiot_service_open("gn71", NULL); + if (handle == 0) { + printf("open tiot service fail\r\n"); + g_is_pgnss_poweron = 0; + g_pgnss_stopflag = 1; + if (pgnss_log != NULL) { + free(pgnss_log); + pgnss_log = NULL; + } + return; + } + printf("open tiot service success for cold start\n"); + + // 直接配置为冷启动模式 + printf("Configuring cold start mode...\r\n"); + int32_t cfgRet = CfgColdStartFixModeGpsNmeaAll(handle); + if (cfgRet == 0) { + printf("Cold start configuration failed\r\n"); + tiot_service_close(handle); + return; + } + printf("Cold start mode configured successfully\r\n"); + + QryVersion(handle); + + // Step4: start gnss + if (StartGnss(handle) == 0) { + printf("Start GNSS failed\r\n"); + tiot_service_close(handle); + return; + } + + // Step5: listening gnss data + ListenGnssData(handle); + + // Step6: stop gnss + if (StopGnss(handle) == 0) { + printf("Stop GNSS failed\r\n"); + } + + // Step7: power off gnss + tiot_service_close(handle); + + // 关日志文件 + if (g_is_pgnss_logon) + { + fclose(g_gnssLogFp); + g_gnssLogFp = NULL; + } + + // Step8: deinit + tiot_service_deinit(); + + #ifdef DOWNLOAD_GNSS_SWITCH + download_gnss_switch(SWITCH_TO_DOWNLOAD); + #endif + uapi_pm_remove_sleep_veto(PM_ID_SYS); + + g_is_pgnss_poweron = 0; + sw_debug_uart_deinit(); + uart_config_init(); + printf("finish cold start mode\r\n"); + + printf("gnss_log: %s\r\n", pgnss_log); + // 释放pgnss_log内存 + if (pgnss_log != NULL) { + free(pgnss_log); + pgnss_log = NULL; + } +} + +// 检查AGNSS文件夹是否过期的函数 +static int check_agnss_folder_expired(void) +{ + DIR *dir = opendir(PGNSS_DATA_PATH); + if (dir == NULL) { + printf("AGNSS directory does not exist: %s\n", PGNSS_DATA_PATH); + return 1; // 目录不存在,认为过期 + } + + // 获取当前时间戳 + uint32_t current_timestamp = 0; + uapi_get_timestampe_ss(¤t_timestamp); + + struct dirent *entry; + int found_valid_folder = 0; + uint32_t min_time_diff = 0xFFFFFFFF; + + while ((entry = readdir(dir)) != NULL) { + // 跳过 . 和 .. 目录 + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + // 检查是否是数字文件夹(时间戳文件夹) + char *endptr; + uint32_t folder_timestamp = strtoul(entry->d_name, &endptr, 10); + + // 如果转换成功且没有剩余字符,说明是纯数字文件夹 + if (*endptr == '\0' && folder_timestamp > 0) { + // 计算时间差 + uint32_t time_diff = 0; + if (current_timestamp >= folder_timestamp) { + time_diff = current_timestamp - folder_timestamp; + } else { + time_diff = folder_timestamp - current_timestamp; + } + + // 检查是否在24小时内 + if (time_diff < 86400) { // 24小时 = 86400秒 + found_valid_folder = 1; + if (time_diff < min_time_diff) { + min_time_diff = time_diff; + // 更新全局变量,存储最接近的时间戳文件夹路径 + if (g_current_agnss_folder != NULL) { + free(g_current_agnss_folder); + g_current_agnss_folder = NULL; + } + g_current_agnss_folder = malloc(256); + if (g_current_agnss_folder != NULL) { + int ret = snprintf(g_current_agnss_folder, 256, "%s/%s", PGNSS_DATA_PATH, entry->d_name); + if (ret < 0 || ret >= 256) { + printf("ERROR: snprintf failed or buffer overflow for g_current_agnss_folder\n"); + free(g_current_agnss_folder); + g_current_agnss_folder = NULL; + } + } else { + printf("ERROR: Failed to allocate memory for g_current_agnss_folder\n"); + } + } + printf("Found valid AGNSS folder: %s (time diff: %u seconds)\n", + entry->d_name, time_diff); + } else { + printf("Found expired AGNSS folder: %s (time diff: %u seconds, %.1f days)\n", + entry->d_name, time_diff, time_diff / 86400.0); + } + } + } + + closedir(dir); + + if (!found_valid_folder) { + printf("No valid AGNSS folder found within 24 hours\n"); + return 1; // 过期 + } + + return 0; // 未过期 +} + +// PGNSS启动前检查函数:检查AGNSS文件夹是否过期,过期则尝试下载 +// 返回值:0=检查通过,可以正常启动PGNSS;1=检查失败,需要冷启动 +static int pgnss_startup_check(void) +{ + printf("=== PGNSS Startup Check ===\n"); + + // 首先检查AGNSS文件夹是否过期 + int agnss_expired = check_agnss_folder_expired(); + if (!agnss_expired) { + printf("=== PGNSS Startup Check Passed ===\n"); + return 0; // 检查通过,可以正常启动PGNSS + } + + printf("AGNSS folder is expired or does not exist. Attempting to download...\n"); + + // 检查4G状态 + int cat1_status = uapi_dev_runtime_get_cat1_powerstat(); + printf("CAT1 power status: %d (1=powered on, 0=powered off)\n", cat1_status); + + if (cat1_status != 1) { + printf("ERROR: CAT1 is not powered on! Need cold start mode\n"); + return 1; // 检查失败,需要冷启动 + } + + printf("4G is powered on. Starting AGNSS download process...\n"); + + // 第一次发送下载指令 + printf("Sending first download command...\n"); + do_gnss_http_server_send_data(GNSS_HTTP_SERVICE_CMD_DOWNLOAD_AGNSS, NULL, 0); + + // 每10秒检查一次,最多检查6次(60秒) + int check_count = 0; + int max_checks = 6; // 60秒 / 10秒 = 6次检查 + int retry_sent = 0; // 标记是否已发送重试指令 + + while (check_count < max_checks) { + // 等待10秒 + printf("Waiting 10 seconds for download (check %d/%d)...\n", check_count + 1, max_checks); + LOS_Msleep(10000); + check_count++; + + // 检查是否有文件 + if (check_agnss_folder_expired()) { + printf("✓ AGNSS files downloaded successfully after %d seconds\n", check_count * 10); + printf("=== PGNSS Startup Check Passed ===\n"); + + return 0; // 检查通过,可以正常启动PGNSS + } + + // 在第3次检查后(30秒)发送重试指令 + if (check_count == 3 && !retry_sent) { + printf("No files found after 30s. Sending second download command...\n"); + do_gnss_http_server_send_data(GNSS_HTTP_SERVICE_CMD_DOWNLOAD_AGNSS, NULL, 0); + retry_sent = 1; + } + } + + // 60秒后还没有数据,降级为冷启动 + printf("ERROR: No AGNSS files downloaded after 60 seconds. Need cold start mode\n"); + + + return 1; // 检查失败,需要冷启动 +} + +void PGnssServerStart(void) +{ + //未绑定直接冷启动 + if(cm_getisFirstTimeStart()) + { + printf("PGnssServerStartColdStart \n"); + PGnssServerStartColdStart(); + return; + } + + // 执行PGNSS启动前检查 + int check_result = pgnss_startup_check(); + if (check_result != 0) { + printf("PGNSS startup check failed. Starting cold start mode\n"); + PGnssServerStartColdStart(); + return; + } + + printf("PGNSS startup check passed. Proceeding with PGNSS mode\n"); + + printf("\nenter gnss samples\r\n"); + + if (pgnss_log == NULL) + { + pgnss_log = (char *)malloc(2048); + if (pgnss_log == NULL) { + printf("error: malloc pgnss_log failed!\n"); + return; + } + memset(pgnss_log, 0, 2048); + } + + if(g_is_pgnss_poweron == 1) + { + printf("gnss already on\r\n"); + if (pgnss_log != NULL) { + free(pgnss_log); + pgnss_log = NULL; + } + return ; + } + uapi_pm_add_sleep_veto(PM_ID_SYS); + + #ifdef DOWNLOAD_GNSS_SWITCH + download_gnss_switch(SWITCH_TO_GNSS); + #endif + g_is_pgnss_poweron = 1; + g_pgnss_stopflag = 0; + g_cold_start_pgnss_stopflag = 0; + sw_debug_uart_deinit(); + // Step1: init + int32_t ret = tiot_service_init(); + if (ret != 0) { + printf("tiot service init fail\r\n"); + g_is_pgnss_poweron = 0; + g_pgnss_stopflag = 1; + if (pgnss_log != NULL) { + free(pgnss_log); + pgnss_log = NULL; + } + return; + } + + // 打开日志文件 + if (g_is_pgnss_logon) + { + g_gnssLogFp = fopen("/user/log/gnss.log", "w"); + if (g_gnssLogFp == NULL) { + printf("error: open log file error\n"); + if (pgnss_log != NULL) { + free(pgnss_log); + pgnss_log = NULL; + } + return; + } + } + printf("before open tiot service\n"); + + // Step2: power on gnss + tiot_handle handle = tiot_service_open("gn71", NULL); + if (handle == 0) { + printf("open tiot service fail\r\n"); + g_is_pgnss_poweron = 0; + g_pgnss_stopflag = 1; + g_cold_start_pgnss_stopflag = 1; + if (pgnss_log != NULL) { + free(pgnss_log); + pgnss_log = NULL; + } + return; + } + printf("open tiot service success\r\n"); + + int32_t cfgRet; + // ---- loop ---------- + for (uint16_t i = 0; i < ARRAY_SIZE(g_gnssSamplesCfg); i++) { + cfgRet = 0; + if (g_gnssSamplesCfg[i].sampleId == i) { + // Step3: config gnss + if (g_gnssSamplesCfg[i].cfgHandle != NULL) { + cfgRet = g_gnssSamplesCfg[i].cfgHandle(handle); + } + if (cfgRet == 0) { + // continue; + break; + } + printf("cfg sample id:%u\r\n", g_gnssSamplesCfg[i].sampleId); + QryVersion(handle); + + // Step4: start gnss + if (StartGnss(handle) == 0) { + continue; + } + // Step5: listening gnss data + ListenGnssData(handle); + // Step6: stop gnss + if (StopGnss(handle) == 0) { + continue; + } + } + } + // --------------------- + // Step7: power off gnss + tiot_service_close(handle); + // 关日志文件 + if (g_is_pgnss_logon) + { + fclose(g_gnssLogFp); + g_gnssLogFp = NULL; + } + // Step8: deinit + tiot_service_deinit(); + + #ifdef DOWNLOAD_GNSS_SWITCH + download_gnss_switch(SWITCH_TO_DOWNLOAD); + #endif + uapi_pm_remove_sleep_veto(PM_ID_SYS); + if(!g_cold_start_pgnss_stopflag) + g_is_pgnss_poweron = 0; + sw_debug_uart_deinit(); + uart_config_init(); + printf("finish gnss samples\r\n"); + + printf("pgnss_log: %s\r\n", pgnss_log); + // 释放pgnss_log内存 + if (pgnss_log != NULL) { + free(pgnss_log); + pgnss_log = NULL; + } + if(g_cold_start_pgnss_stopflag == 1) + { + // GnssServerStart(); + PGnssServerStartColdStart(); + } + +} diff --git a/code/sdk/zhihui/services/gnss/src/gnss_http_server.c b/code/sdk/zhihui/services/gnss/src/gnss_http_server.c new file mode 100644 index 000000000..ef9616a6e --- /dev/null +++ b/code/sdk/zhihui/services/gnss/src/gnss_http_server.c @@ -0,0 +1,1631 @@ +#include "pinctrl.h" +#include "debug_print.h" +#include "rtc.h" +#include "timer.h" +#include "systick.h" + +#include "tcxo.h" + +#include "cmsis_os2.h" +#include "input_app.h" +#include "gnss_service.h" +#include "custom_utils.h" +#include "gnss_http_server.h" +#include "custom_runtime.h" +#include +#include "pm_definition.h" +#include "mbedtls/md5.h" +#include "mbedtls/base64.h" +#include "cJSON.h" +#include "mbedtls/hmac_drbg.h" +#include "gnss_http_server.h" +#include "mbedtls/md.h" +#include "mbedtls/base64.h" +#include "mbedtls/md5.h" +#include "netinet/in.h" +#include "arpa/inet.h" +// 使用新的httpclient.h接口 +#include "netstack/http/include/httpclient.h" +// code/sdk/open_source/openharmony/foundation/ace/ace_engine_lite/modules/netstack/http/include/httpclient.h +#include + +#define PGNSS_DATA_PATH "/user/userdata/gnss" + +// 全局变量用于存储接收到的数据 +static char *g_agnss_response_buffer = NULL; +static size_t g_agnss_response_size = 0; +static size_t g_agnss_response_capacity = 0; + +// 全局静态变量用于防止重复处理 +static int g_processing_count = 0; + +static unsigned long g_app_recv_queue= 0xFFFFFFFF; +static unsigned long g_app_send_queue= 0xFFFFFFFF; + +static app_task_definition_t send_taskcfg={0}; +static app_task_definition_t recv_taskcfg={0}; + + +static void cleanup_agnss_response_buffer(void); +static void agnss_accumulate_data(const char *data, size_t len); +static void emergency_cleanup(void); +static void smart_json_cleanup(void); +static char* extract_folder_path(const char *download_url); + +// URL解析结构体 +typedef struct { + char *protocol; + char *host; + int port; + char *path; + char *query; + char *error; +} BK_URL; + +// URL解析函数 +static BK_URL parse_url(const char *url); +static void free_url(BK_URL *url); +int download_agnss_file(const char *filename); + + +void do_gnss_http_server_recv_data(int cmd,char *data,uint32_t len); + +// 使用新的httpclient.h接口的下载结果处理函数 +static void agnss_download_result_handler(const char *filename, HTTPC_RESULT result, int response_code, const char *response_data, int data_len) +{ + if (filename) { + // 单个文件下载的结果处理 - 只保留成功信息 + if (result == HTTP_SUCCESS && response_code == 200) { + // 验证文件是否真的写入成功 - 在时间戳文件夹中查找 + char filepath[512]; + int file_found = 0; + + // 首先尝试在根目录查找 + snprintf(filepath, sizeof(filepath), "%s/%s", PGNSS_DATA_PATH, filename); + FILE *fp = fopen(filepath, "rb"); + if (fp != NULL) { + fseek(fp, 0, SEEK_END); + long file_size = ftell(fp); + fclose(fp); + + if (file_size > 0) { + printf("✓ %s: %ld bytes\n", filename, file_size); + file_found = 1; + } + } + + // 如果根目录没有找到,在时间戳文件夹中查找 + if (!file_found) { + DIR *dir = opendir(PGNSS_DATA_PATH); + if (dir != NULL) { + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + // 跳过 . 和 .. 目录 + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + // 检查是否是数字文件夹(时间戳文件夹) + char *endptr; + uint32_t folder_timestamp = strtoul(entry->d_name, &endptr, 10); + if (*endptr == '\0' && folder_timestamp > 0) { + // 在时间戳文件夹中查找文件 + snprintf(filepath, sizeof(filepath), "%s/%s/%s", PGNSS_DATA_PATH, entry->d_name, filename); + fp = fopen(filepath, "rb"); + if (fp != NULL) { + fseek(fp, 0, SEEK_END); + long file_size = ftell(fp); + fclose(fp); + + if (file_size > 0) { + printf("✓ %s: %ld bytes (in %s)\n", filename, file_size, entry->d_name); + file_found = 1; + break; + } + } + } + } + closedir(dir); + } + } + } + } else { + // AGNSS文件列表下载的结果处理 + if (result == HTTP_SUCCESS && response_code == 200) { + // 处理接收到的数据 + if (data_len > 0 && response_data) { + agnss_accumulate_data(response_data, data_len); + } + + // 发送完成信号到接收任务 + do_gnss_http_server_recv_data(GNSS_HTTP_SERVICE_CMD_AGNSS_RECV, NULL, 0); + } + } +} + +// 使用简单的socket直接下载文件 +static HTTPC_RESULT download_file_with_httpclient(const char *filename, const char *url) +{ + + // 解析URL + char host[256] = {0}; + char path[512] = {0}; + int port = 80; + + // 简单解析 http://host/path 格式 + if (strncmp(url, "http://", 7) == 0) { + const char *url_path = url + 7; + const char *path_start = strchr(url_path, '/'); + if (path_start) { + int host_len = path_start - url_path; + if (host_len >= sizeof(host)) { + printf("Host name too long: %d bytes\n", host_len); + return HTTP_EARG; + } + strncpy(host, url_path, host_len); + host[host_len] = '\0'; + + if (strlen(path_start) >= sizeof(path)) { + printf("Path too long: %zu bytes\n", strlen(path_start)); + return HTTP_EARG; + } + strcpy(path, path_start); + } else { + printf("Invalid URL format - no path found\n"); + return HTTP_EARG; + } + } else { + printf("Unsupported URL scheme: %s\n", url); + return HTTP_EARG; + } + + // 保存到时间戳文件夹中 + char filepath[512]; + char timestamp_folder[64]; + + // 从URL中提取时间戳文件夹名 + char *folder_pos = strstr(url, "/iot_gnss/"); + if (folder_pos) { + folder_pos += 10; // 跳过 "/iot_gnss/" + char *next_slash = strchr(folder_pos, '/'); + if (next_slash) { + int folder_len = next_slash - folder_pos; + if (folder_len > 0 && folder_len < sizeof(timestamp_folder) - 1) { + strncpy(timestamp_folder, folder_pos, folder_len); + timestamp_folder[folder_len] = '\0'; + + // 文件夹已在下载开始前创建,直接使用路径 + char full_folder_path[512]; + snprintf(full_folder_path, sizeof(full_folder_path), "%s/%s", PGNSS_DATA_PATH, timestamp_folder); + + // 保存文件到时间戳文件夹 + snprintf(filepath, sizeof(filepath), "%s/%s/%s", PGNSS_DATA_PATH, timestamp_folder, filename); + } else { + // 如果无法提取时间戳,使用默认路径 + snprintf(filepath, sizeof(filepath), "%s/%s", PGNSS_DATA_PATH, filename); + } + } else { + // 如果无法找到第二个斜杠,使用默认路径 + snprintf(filepath, sizeof(filepath), "%s/%s", PGNSS_DATA_PATH, filename); + } + } else { + // 如果无法找到 /iot_gnss/,使用默认路径 + snprintf(filepath, sizeof(filepath), "%s/%s", PGNSS_DATA_PATH, filename); + } + + // 初始化HTTP客户端 + HttpClient client = {0}; + HttpClientData clientData = {0}; + + // 设置HTTP客户端参数 + client.isHttp = true; + client.remotePort = port; + + // 准备客户端数据 + HTTPC_RESULT prep_result = HttpClientPrepare(&clientData, 2048, 256 * 1024); + if (prep_result != HTTP_SUCCESS) { + return prep_result; + } + + // 构建完整URL + char full_url[512]; + snprintf(full_url, sizeof(full_url), "http://%s%s", host, path); + + // 执行HTTP GET请求 + HTTPC_RESULT result = HttpClientGetRequest(&client, full_url, &clientData); + + if (result == HTTP_SUCCESS) { + // 检查响应状态码 + int response_code = HttpClientGetResponseCode(&client); + + if (response_code == 200) { + // 将响应数据写入文件 + if (clientData.responseBuf && clientData.responseBufLen > 0) { + // 简化数据长度计算 + int actual_size = clientData.responseContentLen; + if (actual_size <= 0) { + actual_size = clientData.responseBufLen; + } + + FILE *fp = fopen(filepath, "wb"); + if (fp != NULL) { + size_t written = fwrite(clientData.responseBuf, 1, actual_size, fp); + fclose(fp); + + if (written == actual_size) { + result = HTTP_SUCCESS; + } else { + result = HTTP_ESEND; + } + } else { + result = HTTP_ESEND; + } + } else { + result = HTTP_ERECV; + } + } else { + result = HTTP_EPROTO; + } + } else if (result == HTTP_EAGAIN) { + // 检查socket是否仍然有效 + if (client.socket <= 0) { + // 检查响应状态码 + int response_code = HttpClientGetResponseCode(&client); + + if (response_code == 200) { + // 检查响应数据 + if (clientData.responseBuf && clientData.responseBufLen > 0) { + // 检查缓冲区内容,查找实际的数据结束位置 + int actual_data_end = clientData.responseBufLen; + for (int i = 0; i < clientData.responseBufLen; i++) { + if (clientData.responseBuf[i] == 0) { + // 检查是否连续多个零(可能是填充) + int consecutive_zeros = 0; + for (int j = i; j < clientData.responseBufLen && clientData.responseBuf[j] == 0; j++) { + consecutive_zeros++; + } + if (consecutive_zeros > 100) { // 如果连续100个以上的零,认为是填充 + actual_data_end = i; + break; + } + } + } + + // 优先使用服务器返回的实际长度,只有在明显错误时才使用检测结果 + int actual_size = clientData.responseContentLen; + if (actual_size <= 0) { + // 如果responseContentLen无效,使用检测到的实际数据结束位置 + actual_size = actual_data_end; + if (actual_size <= 0) { + actual_size = clientData.responseBufLen; + } + } else { + // 如果responseContentLen有效,检查是否明显错误(比如太大) + if (actual_data_end > 0 && actual_data_end < actual_size) { + actual_size = actual_data_end; + } else if (actual_size > 50000) { // 如果Content-Length超过50KB,可能错误 + // AssistInfo.dat文件:固定大小验证(通常几百字节) + if (strcmp(filename, "AssistInfo.dat") == 0) { + if (actual_size > 0 && actual_size < 10000) { // AssistInfo.dat通常几百字节,最大10KB + printf(" [DEBUG] AssistInfo.dat 文件大小: %d bytes (固定大小验证通过)\n", actual_size); + } else { + printf(" WARNING: AssistInfo.dat 文件大小异常: %d bytes\n", actual_size); + actual_size = actual_data_end; + } + } else { + actual_size = actual_data_end; + } + } + } + + // 将响应数据写入文件 + FILE *fp = fopen(filepath, "wb"); + if (fp != NULL) { + size_t written = fwrite(clientData.responseBuf, 1, actual_size, fp); + fclose(fp); + + if (written == actual_size) { + printf("✓ %s (%zu bytes)\n", filename, written); + result = HTTP_SUCCESS; + } else { + printf("✗ %s: write failed\n", filename); + result = HTTP_ESEND; + } + } else { + printf("✗ %s: file open failed\n", filename); + result = HTTP_ESEND; + } + } else { + printf("✗ %s: no data\n", filename); + result = HTTP_ERECV; + } + } else { + printf("✗ %s: HTTP %d\n", filename, response_code); + result = HTTP_EPROTO; + } + } else { + // 尝试接收响应数据 + HTTPC_RESULT recv_result = HttpClientRecvResponse(&client, &clientData); + + if (recv_result == HTTP_SUCCESS) { + // 检查响应状态码 + int response_code = HttpClientGetResponseCode(&client); + + if (response_code == 200) { + // 处理响应数据 + if (clientData.responseBuf && clientData.responseBufLen > 0) { + // 检查缓冲区内容,查找实际的数据结束位置 + int actual_data_end = clientData.responseBufLen; + for (int i = 0; i < clientData.responseBufLen; i++) { + if (clientData.responseBuf[i] == 0) { + // 检查是否连续多个零(可能是填充) + int consecutive_zeros = 0; + for (int j = i; j < clientData.responseBufLen && clientData.responseBuf[j] == 0; j++) { + consecutive_zeros++; + } + if (consecutive_zeros > 100) { // 如果连续100个以上的零,认为是填充 + actual_data_end = i; + break; + } + } + } + + // 优先使用服务器返回的实际长度,只有在明显错误时才使用检测结果 + int actual_size = clientData.responseContentLen; + if (actual_size <= 0) { + // 如果responseContentLen无效,使用检测到的实际数据结束位置 + actual_size = actual_data_end; + if (actual_size <= 0) { + actual_size = clientData.responseBufLen; + } + } else { + // 如果responseContentLen有效,检查是否明显错误(比如太大) + if (actual_data_end > 0 && actual_data_end < actual_size) { + actual_size = actual_data_end; + } else if (actual_size > 50000) { // 如果Content-Length超过50KB,可能错误 + actual_size = actual_data_end; + } + } + + // 将响应数据写入文件 + FILE *fp = fopen(filepath, "wb"); + if (fp != NULL) { + size_t written = fwrite(clientData.responseBuf, 1, actual_size, fp); + fclose(fp); + + if (written == actual_size) { + printf("✓ %s (%zu bytes)\n", filename, written); + result = HTTP_SUCCESS; + } else { + printf("✗ %s: write failed\n", filename); + result = HTTP_ESEND; + } + } else { + printf("✗ %s: file open failed\n", filename); + result = HTTP_ESEND; + } + } else { + printf("✗ %s: no data\n", filename); + result = HTTP_ERECV; + } + } else { + printf("✗ %s: HTTP %d\n", filename, response_code); + result = HTTP_EPROTO; + } + } else { + printf("✗ %s: recv failed %d\n", filename, recv_result); + result = recv_result; + } + } + } else { + printf("✗ %s: request failed %d\n", filename, result); + } + + // 清理资源 + HttpClientUnprepare(&clientData); + HttpClientClse(&client); + + return result; +} + +// 从URL中提取文件夹路径 +static char* extract_folder_path(const char *download_url) { + static char folder_path[256] = {0}; + + // 跳过协议部分 (http://) + const char *path_start = strstr(download_url, "://"); + if (!path_start) { + return NULL; + } + path_start += 3; // 跳过 "://" + + // 跳过主机名部分 + const char *first_slash = strchr(path_start, '/'); + if (!first_slash) { + return NULL; + } + + // 查找最后一个斜杠(文件名之前) + const char *last_slash = strrchr(first_slash, '/'); + if (!last_slash || last_slash == first_slash) { + return NULL; + } + + // 提取文件夹路径 + int folder_len = last_slash - first_slash; + if (folder_len > 0 && folder_len < sizeof(folder_path) - 1) { + strncpy(folder_path, first_slash, folder_len); + folder_path[folder_len] = '\0'; + return folder_path; + } + + return NULL; +} + +// 创建文件夹路径 +static int create_folder_structure(const char *folder_path) { + if (!folder_path || strlen(folder_path) == 0) { + return 0; // 没有文件夹路径,直接返回成功 + } + + char full_path[512]; + snprintf(full_path, sizeof(full_path), "%s%s", PGNSS_DATA_PATH, folder_path); + + printf(" [DEBUG] 创建文件夹: %s\n", full_path); + + // 使用uapi_create_folder创建文件夹 + uapi_create_folder(full_path); + // if (result == 0) { + // printf(" [DEBUG] 文件夹创建成功: %s\n", full_path); + // } else { + // printf(" [WARNING] 文件夹创建失败: %s (错误码: %d)\n", full_path, result); + // } + + return 0; +} + +static int download_agnss_file_with_url(const char *filename, const char *download_url) +{ + // 文件夹已在下载开始前创建,无需重复创建 + + // 添加重试机制 + int max_retries = 2; + int retry_count = 0; + HTTPC_RESULT result = HTTP_SUCCESS; + + while (retry_count < max_retries) { + if (retry_count > 0) { + LOS_Msleep(200); + } + + // 使用新的httpclient.h接口下载文件 + result = download_file_with_httpclient(filename, download_url); + + if (result == HTTP_SUCCESS) { + break; + } else { + retry_count++; + } + } + + if (result != HTTP_SUCCESS) { + return -1; + } + + return 0; +} + +// AGNSS数据处理函数 +static void agnss_accumulate_data(const char *data, size_t len) +{ + // 验证输入数据 + if (data == NULL || len == 0) { + printf("Invalid data received: data=%p, len=%zu\n", data, len); + return; + } + + // 检查数据是否以JSON开始(简单验证) + if (g_agnss_response_size == 0) { + // 第一个数据包,检查是否以 { 开始 + if (len > 0 && data[0] != '{') { + printf("Warning: First data packet doesn't start with '{', data[0]=0x%02X\n", (unsigned char)data[0]); + // 尝试查找JSON开始位置 + for (size_t i = 0; i < len; i++) { + if (data[i] == '{') { + printf("Found JSON start at position %zu, adjusting data\n", i); + data += i; + len -= i; + break; + } + } + } + } + + // 扩展缓冲区 + if (g_agnss_response_buffer == NULL) { + g_agnss_response_capacity = 512 * 1024; + g_agnss_response_buffer = (char *)malloc(g_agnss_response_capacity); + if (g_agnss_response_buffer == NULL) { + return; + } + g_agnss_response_size = 0; + memset(g_agnss_response_buffer, 0, g_agnss_response_capacity); + } + + // 检查是否需要扩展缓冲区 + if (g_agnss_response_size + len > g_agnss_response_capacity) { + size_t new_capacity = g_agnss_response_capacity * 2; + if (new_capacity > 8 * 1024 * 1024) { + return; + } + char *new_buffer = (char *)realloc(g_agnss_response_buffer, new_capacity); + if (new_buffer == NULL) { + return; + } + g_agnss_response_buffer = new_buffer; + g_agnss_response_capacity = new_capacity; + } + + // 复制数据到缓冲区 + memcpy(g_agnss_response_buffer + g_agnss_response_size, data, len); + g_agnss_response_size += len; + g_agnss_response_buffer[g_agnss_response_size] = '\0'; +} + + +// 递归验证下载的文件 +static void verify_files_recursive(const char *base_path, int *total_count) +{ + DIR *dir = opendir(base_path); + if (dir == NULL) { + return; + } + + struct dirent *entry; + + while ((entry = readdir(dir)) != NULL) { + // 跳过 . 和 .. 目录 + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + + char full_path[512]; + snprintf(full_path, sizeof(full_path), "%s/%s", base_path, entry->d_name); + + // 检查是否是目录 + DIR *sub_dir = opendir(full_path); + if (sub_dir != NULL) { + // 这是一个目录,递归遍历 + closedir(sub_dir); + verify_files_recursive(full_path, total_count); + } else { + // 这是一个文件,检查是否是AGNSS相关文件 + if (strstr(entry->d_name, ".eph") != NULL || + strstr(entry->d_name, ".dat") != NULL || + strstr(entry->d_name, "AssistInfo") != NULL) { + + // 检查文件是否存在并获取大小 + FILE *fp = fopen(full_path, "rb"); + if (fp != NULL) { + // 获取文件大小 + fseek(fp, 0, SEEK_END); + long file_size = ftell(fp); + fclose(fp); + + if (file_size > 0) { + // 检查是否在时间戳文件夹中 + char *timestamp_folder = strrchr(base_path, '/'); + if (timestamp_folder && timestamp_folder != base_path) { + timestamp_folder++; // 跳过 '/' + printf("✓ %s: %ld bytes (in %s)\n", entry->d_name, file_size, timestamp_folder); + } else { + printf("✓ %s: %ld bytes\n", entry->d_name, file_size); + } + (*total_count)++; + } + } + } + } + } + + closedir(dir); +} + +// 验证下载的文件 +static void verify_downloaded_files(uint32_t selected_timestamp) +{ + printf("\n=== Downloaded Files ===\n"); + + int total_count = 0; + verify_files_recursive(PGNSS_DATA_PATH, &total_count); + + printf("Total: %d files in timestamp folder: %s/%u\n", total_count, PGNSS_DATA_PATH, selected_timestamp); +} + + +static void agnss_process_complete_response(void) +{ + // 声明所有变量在函数开始,确保作用域正确 + char **file_list = NULL; + int valid_file_count = 0; + int file_list_capacity = 0; + char **processed_files = NULL; + int processed_count = 0; + + // 防止重复处理 + g_processing_count++; + if (g_processing_count > 5) + { + printf("Warning: Too many processing attempts (%d), skipping to prevent infinite loop\n", g_processing_count); + emergency_cleanup(); + return; + } + + // 获取当前时间戳 + uint32_t current_timestamp = 0; + uapi_get_timestampe_ss(¤t_timestamp); + printf("Current timestamp: %u\n", current_timestamp); + + // 添加调试信息,显示当前时间的可读格式 + time_t current_time = (time_t)current_timestamp; + printf("Current time: %s", ctime(¤t_time)); + + if (g_agnss_response_buffer && g_agnss_response_size > 0) + { + printf("Processing complete AGNSS response, size: %zu bytes\n", g_agnss_response_size); + + // 智能清理JSON数据 + smart_json_cleanup(); + + // 验证JSON格式并修复截断问题 - 更智能的版本 + if (g_agnss_response_buffer[0] != '{' || g_agnss_response_buffer[g_agnss_response_size - 1] != '}') + { + printf("Warning: Response doesn't appear to be valid JSON\n"); + printf("First char: '%c', Last char: '%c'\n", + g_agnss_response_buffer[0], + g_agnss_response_buffer[g_agnss_response_size - 1]); + + // 检查是否有明显的截断标记 + if (strstr(g_agnss_response_buffer, "1ff8") || strstr(g_agnss_response_buffer, "0x0D")) + { + printf("Warning: JSON data appears to be truncated with corruption markers\n"); + // 尝试找到最后一个完整的JSON对象 + char *last_complete = NULL; + char *search_pos = g_agnss_response_buffer; + while ((search_pos = strstr(search_pos, "}]")) != NULL) + { + last_complete = search_pos + 2; + search_pos += 2; + } + if (last_complete) + { + size_t new_size = last_complete - g_agnss_response_buffer; + g_agnss_response_size = new_size; + g_agnss_response_buffer[g_agnss_response_size] = '\0'; + printf("Truncated JSON to last complete object, new size: %zu bytes\n", g_agnss_response_size); + } + } + + // 尝试查找JSON开始和结束 + char *json_start = strchr(g_agnss_response_buffer, '{'); + char *json_end = strrchr(g_agnss_response_buffer, '}'); + + // 检查是否有截断的JSON数据 + if (strstr(g_agnss_response_buffer, "1ff8") || strstr(g_agnss_response_buffer, "0x0D")) + { + printf("Warning: Detected corrupted JSON data with truncation markers\n"); + // 尝试找到最后一个完整的JSON对象 + char *last_complete = NULL; + char *search_pos = g_agnss_response_buffer; + while ((search_pos = strstr(search_pos, "}]")) != NULL) + { + last_complete = search_pos + 2; + search_pos += 2; + } + if (last_complete) + { + json_end = last_complete - 1; // 指向 '}' 字符 + printf("Truncated to last complete JSON object at position %ld\n", + json_end - g_agnss_response_buffer); + } + } + + if (json_start && json_end && json_end > json_start) + { + printf("Found JSON content between positions %ld and %ld\n", + json_start - g_agnss_response_buffer, + json_end - g_agnss_response_buffer); + + // 验证这个JSON片段是否完整 + int brace_count = 0; + int bracket_count = 0; + for (char *p = json_start; p <= json_end; p++) + { + if (*p == '{') brace_count++; + else if (*p == '}') brace_count--; + else if (*p == '[') bracket_count++; + else if (*p == ']') bracket_count--; + } + + if (brace_count == 0 && bracket_count == 0) + { + // 调整缓冲区指针和大小 + size_t new_size = json_end - json_start + 1; + memmove(g_agnss_response_buffer, json_start, new_size); + g_agnss_response_size = new_size; + g_agnss_response_buffer[g_agnss_response_size] = '\0'; + printf("Adjusted buffer size to %zu bytes (complete JSON)\n", g_agnss_response_size); + } + else + { + printf("Found JSON fragment but structure incomplete - braces: %d, brackets: %d\n", brace_count, bracket_count); + // 尝试查找最后一个完整的JSON对象 + char *last_complete = NULL; + char *search_pos = g_agnss_response_buffer; + + // 查找最后一个完整的 "}]" + while ((search_pos = strstr(search_pos, "}]")) != NULL) + { + last_complete = search_pos + 2; + search_pos += 2; + } + + // 如果没有找到 "}]",尝试查找最后一个 "}" + if (!last_complete) + { + search_pos = g_agnss_response_buffer; + while ((search_pos = strchr(search_pos, '}')) != NULL) + { + last_complete = search_pos + 1; + search_pos += 1; + } + } + + if (last_complete) + { + size_t new_size = last_complete - g_agnss_response_buffer; + g_agnss_response_size = new_size; + g_agnss_response_buffer[g_agnss_response_size] = '\0'; + printf("Truncated to last complete JSON object, size: %zu bytes\n", g_agnss_response_size); + } + else + { + printf("Could not find any complete JSON structure, using original data\n"); + } + } + } + else + { + printf("Error: Could not find valid JSON boundaries\n"); + printf("JSON start found: %s\n", json_start ? "yes" : "no"); + printf("JSON end found: %s\n", json_end ? "yes" : "no"); + + // 尝试查找最后一个完整的JSON对象 + char *last_complete = NULL; + char *search_pos = g_agnss_response_buffer; + + // 查找最后一个完整的 "}]" + while ((search_pos = strstr(search_pos, "}]")) != NULL) + { + last_complete = search_pos + 2; + search_pos += 2; + } + + // 如果没有找到 "}]",尝试查找最后一个 "}" + if (!last_complete) + { + search_pos = g_agnss_response_buffer; + while ((search_pos = strchr(search_pos, '}')) != NULL) + { + last_complete = search_pos + 1; + search_pos += 1; + } + } + + if (last_complete) + { + size_t new_size = last_complete - g_agnss_response_buffer; + g_agnss_response_size = new_size; + g_agnss_response_buffer[g_agnss_response_size] = '\0'; + printf("Truncated to last complete JSON object, size: %zu bytes\n", g_agnss_response_size); + } + else + { + printf("Could not find any complete JSON structure, using original data\n"); + } + } + } + + printf("AGNSS JSON data:\n%s\n", g_agnss_response_buffer); + + // 检查JSON数据完整性 + int brace_count = 0; + int bracket_count = 0; + for (size_t i = 0; i < g_agnss_response_size; i++) { + if (g_agnss_response_buffer[i] == '{') brace_count++; + else if (g_agnss_response_buffer[i] == '}') brace_count--; + else if (g_agnss_response_buffer[i] == '[') bracket_count++; + else if (g_agnss_response_buffer[i] == ']') bracket_count--; + } + + if (brace_count != 0 || bracket_count != 0) { + printf("Warning: JSON structure incomplete - braces: %d, brackets: %d\n", brace_count, bracket_count); + + // 如果JSON结构不完整,尝试修复 + if (brace_count > 0 || bracket_count > 0) { + // 缺少右大括号或右方括号,尝试添加 + printf("Attempting to fix incomplete JSON by adding missing braces/brackets\n"); + size_t needed_braces = (brace_count > 0) ? brace_count : 0; + size_t needed_brackets = (bracket_count > 0) ? bracket_count : 0; + + // 防止过度修复 + if (needed_braces > 10 || needed_brackets > 10) { + printf("Warning: Too many missing braces/brackets (%zu/%zu), skipping fix to prevent corruption\n", + needed_braces, needed_brackets); + } else { + // 计算需要扩展的缓冲区大小 + size_t additional_size = needed_braces + needed_brackets; + char *new_buffer = (char *)realloc(g_agnss_response_buffer, g_agnss_response_size + additional_size + 1); + if (new_buffer) { + g_agnss_response_buffer = new_buffer; + + // 添加缺少的右方括号和右大括号 + for (size_t i = 0; i < needed_brackets; i++) { + g_agnss_response_buffer[g_agnss_response_size++] = ']'; + } + for (size_t i = 0; i < needed_braces; i++) { + g_agnss_response_buffer[g_agnss_response_size++] = '}'; + } + g_agnss_response_buffer[g_agnss_response_size] = '\0'; + + printf("Fixed JSON structure, new size: %zu bytes\n", g_agnss_response_size); + } else { + printf("Failed to allocate memory for JSON fix\n"); + } + } + } + } else { + printf("JSON structure appears complete\n"); + } + + // 使用已在函数开始处声明的文件列表变量 + + // 优化逻辑:找出符合条件的时间戳文件夹,选择最接近当前时间的 + printf("\n=== 分析文件夹时间戳,选择最接近的文件夹 ===\n"); + printf("当前时间戳: %u\n", current_timestamp); + + // 存储找到的符合条件的时间戳 + uint32_t selected_timestamp = 0; + uint32_t min_time_diff = 0xFFFFFFFF; + int valid_folder_count = 0; + + // 从JSON数据中提取所有downloadUrl,分析文件夹时间戳 + char *search_pos = g_agnss_response_buffer; + while ((search_pos = strstr(search_pos, "\"downloadUrl\":")) != NULL) { + search_pos += 14; // 跳过 "downloadUrl": + + // 找到URL的开始和结束 + char *url_start = strchr(search_pos, '"'); + if (!url_start) continue; + url_start++; // 跳过开始的引号 + + char *url_end = strchr(url_start, '"'); + if (!url_end) continue; + + // 提取URL + int url_len = url_end - url_start; + if (url_len > 0 && url_len < 512) { + char download_url[512] = {0}; + strncpy(download_url, url_start, url_len); + download_url[url_len] = '\0'; + + // 从URL中提取文件夹时间戳 + char *folder_pos = strstr(download_url, "/iot_gnss/"); + if (folder_pos) { + folder_pos += 10; // 跳过 "/iot_gnss/" + char *next_slash = strchr(folder_pos, '/'); + if (next_slash) { + int folder_len = next_slash - folder_pos; + if (folder_len > 0 && folder_len < 32) { + char folder_timestamp_str[32] = {0}; + strncpy(folder_timestamp_str, folder_pos, folder_len); + folder_timestamp_str[folder_len] = '\0'; + + uint32_t folder_timestamp = strtoul(folder_timestamp_str, NULL, 10); + + // 检查时间戳是否在24小时内且小于当前时间 + if (folder_timestamp <= current_timestamp) { + uint32_t time_diff = current_timestamp - folder_timestamp; + if (time_diff < 86400) { // 24小时 = 86400秒 + valid_folder_count++; + + // 选择时间差最小的文件夹 + if (time_diff < min_time_diff) { + min_time_diff = time_diff; + selected_timestamp = folder_timestamp; + } + } + } + } + } + } + } + + search_pos = url_end + 1; + } + + if (selected_timestamp > 0) { + printf("找到 %d 个有效文件夹,选择最接近的: %u (时间差: %u秒)\n", + valid_folder_count, selected_timestamp, min_time_diff); + + // 一次性创建选定的时间戳文件夹,避免重复创建 + char selected_folder_path[512]; + snprintf(selected_folder_path, sizeof(selected_folder_path), "%s/%u", PGNSS_DATA_PATH, selected_timestamp); + + // 检查文件夹是否已存在 + DIR *dir = opendir(selected_folder_path); + if (dir == NULL) { + // 文件夹不存在,创建它 + uapi_create_folder(selected_folder_path); + } else { + // 文件夹已存在,关闭目录句柄 + closedir(dir); + } + } else { + printf("没有找到符合条件的时间戳文件夹\n"); + } + + // 简化逻辑:通过字符串比较筛选downloadURL + if (strstr(g_agnss_response_buffer, "\"success\":true") && strstr(g_agnss_response_buffer, "\"code\":20000")) { + printf("AGNSS API call successful, parsing file list...\n"); + + // 解析JSON,提取文件列表 + char *data_start = strstr(g_agnss_response_buffer, "\"data\":["); + + if (selected_timestamp > 0) { + printf("开始下载时间戳 %u 的文件...\n", selected_timestamp); + + // 将选定的时间戳转换为字符串,用于字符串比较 + char selected_timestamp_str[32]; + snprintf(selected_timestamp_str, sizeof(selected_timestamp_str), "%u", selected_timestamp); + + if (data_start) { + data_start += 8; // 跳过 "data":[ + + // 遍历所有文件项 + char *item_start = data_start; + int download_count = 0; + + while ((item_start = strstr(item_start, "{")) != NULL && + (item_start - g_agnss_response_buffer) < (long)g_agnss_response_size) { + + // 提取fileName + char *filename_start = strstr(item_start, "\"fileName\":\""); + if (!filename_start) { + item_start++; + continue; + } + filename_start += 12; // 跳过 "fileName":" + + char *filename_end = strchr(filename_start, '"'); + if (!filename_end) { + item_start++; + continue; + } + + int filename_len = filename_end - filename_start; + if (filename_len <= 0 || filename_len >= 256) { + item_start++; + continue; + } + + char filename[256] = {0}; + strncpy(filename, filename_start, filename_len); + filename[filename_len] = '\0'; + + // 提取downloadUrl + char *url_start = strstr(item_start, "\"downloadUrl\":\""); + if (!url_start) { + item_start++; + continue; + } + url_start += 15; // 跳过 "downloadUrl":" + + char *url_end = strchr(url_start, '"'); + if (!url_end) { + item_start++; + continue; + } + + int url_len = url_end - url_start; + if (url_len <= 0 || url_len >= 512) { + item_start++; + continue; + } + + char download_url[512] = {0}; + strncpy(download_url, url_start, url_len); + download_url[url_len] = '\0'; + + // 通过字符串比较检查URL是否属于选定的时间戳文件夹 + char *folder_check = strstr(download_url, selected_timestamp_str); + if (folder_check) { + // 确保这是文件夹名,而不是文件名中的时间戳 + char *iot_gnss_pos = strstr(download_url, "/iot_gnss/"); + if (iot_gnss_pos && folder_check > iot_gnss_pos) { + // 下载文件 + if (download_agnss_file_with_url(filename, download_url) == 0) { + download_count++; + } + } + } + + // 移动到下一个文件项 + char *next_item = strstr(item_start, "},"); + if (next_item) { + item_start = next_item + 2; + } else { + char *last_item = strstr(item_start, "}"); + if (last_item) { + item_start = last_item + 1; + } else { + break; + } + } + } + + printf("成功下载 %d 个文件到时间戳文件夹: %s/%u\n", download_count, PGNSS_DATA_PATH, selected_timestamp); + } else { + printf("没有找到符合条件的时间戳文件夹,跳过下载\n"); + } + } else { + printf("没有找到符合条件的时间戳文件夹\n"); + } + } else { + printf("AGNSS API call failed or returned error\n"); + } + + // 清理缓冲区 + free(g_agnss_response_buffer); + g_agnss_response_buffer = NULL; + g_agnss_response_size = 0; + g_agnss_response_capacity = 0; + + // 重置处理计数器 + g_processing_count = 0; + + // 验证下载的文件 + verify_downloaded_files(selected_timestamp); + + } else { + printf("No response buffer or empty response\n"); + } +} + +// 使用新的httpclient.h接口的AGNSS文件下载函数 +int download_agnss_file(const char *filename) +{ + printf("Downloading file: %s\n", filename); + + // 获取当前时间戳 + uint32_t timestamp = 0; + uapi_get_timestampe_ss(×tamp); + + // 构建完整URL + char full_url[512]; + snprintf(full_url, sizeof(full_url), + "http://iot-pub.tos-cn-guangzhou.volces.com/dev/AGNSS/geteph?deviceId=121314243×tamp=%u", + timestamp); + + printf("Download URL: %s\n", full_url); + + // 使用新的httpclient.h接口下载文件 + HTTPC_RESULT result = download_file_with_httpclient(filename, full_url); + + if (result == HTTP_SUCCESS) { + printf("File %s downloaded successfully\n", filename); + return 0; + } else { + printf("File %s download failed: %d\n", filename, result); + return -1; + } +} + + +// URL解析函数 +static BK_URL parse_url(const char *url) { + BK_URL result = {NULL, NULL, 0, NULL, NULL, NULL}; + + if (!url) { + result.error = "URL is NULL"; + return result; + } + + char *temp_url = strdup(url); + if (!temp_url) { + result.error = "Failed to allocate memory"; + return result; + } + + char *temp_ptr = temp_url; + + // 解析协议 + char *colon = strchr(temp_ptr, ':'); + if (!colon) { + result.error = "Invalid URL: No protocol specified"; + free(temp_url); + return result; + } + *colon = '\0'; + result.protocol = strdup(temp_ptr); + temp_ptr = colon + 3; // 跳过 "://" + + // 解析主机和端口 + char *slash = strchr(temp_ptr, '/'); + if (!slash) { + result.error = "Invalid URL: No path specified"; + free(temp_url); + return result; + } + *slash = '\0'; + + char *colon_port = strchr(temp_ptr, ':'); + if (colon_port) { + *colon_port = '\0'; + result.host = strdup(temp_ptr); + result.port = atoi(colon_port + 1); + if (!result.port) { + result.error = "Invalid port number"; + free(temp_url); + return result; + } + } else { + result.host = strdup(temp_ptr); + if (!strcmp(result.protocol, "http")) { + result.port = 80; + } else if (!strcmp(result.protocol, "https")) { + result.port = 443; + } + } + + temp_ptr = slash + 1; + + // 解析路径和查询字符串 + char *question = strchr(temp_ptr, '?'); + if (question) { + *question = '\0'; + result.path = strdup(temp_ptr); + result.query = strdup(question + 1); + } else { + result.path = strdup(temp_ptr); + result.query = NULL; + } + + free(temp_url); + return result; +} + +// 释放URL结构体 +static void free_url(BK_URL *url) { + if (url) { + free(url->protocol); + free(url->host); + free(url->path); + free(url->query); + free(url->error); + memset(url, 0, sizeof(BK_URL)); + } +} + + + + +int download_agnss_files(void) +{ + //通讯开始,唤醒cat1 + cat1_api_add_cat1_vote(); + cat1_api_wakeup_cat1(1); + cat1_api_keep_wakeup(1); + cat1_api_disable_cat1_cmd(1); + + // 等待CAT1就绪 + LOS_Msleep(1000); + + // 获取当前时间戳 + uint32_t timestamp = 0; + uapi_get_timestampe_ss(×tamp); + + // 构建完整URL + char full_url[512]; + snprintf(full_url, sizeof(full_url), + "http://app.api.thisiot.com/dev/AGNSS/geteph?deviceId=121314243×tamp=%u", + timestamp); + + // 清理之前的缓冲区 + cleanup_agnss_response_buffer(); + + // 添加重试机制 + int max_retries = 6; + int retry_count = 0; + HTTPC_RESULT result = HTTP_EDNS; + + while (retry_count < max_retries) { + if (retry_count > 0) { + LOS_Msleep(300); // 减少重试等待时间 + } + + // 初始化HTTP客户端 + HttpClient client = {0}; + HttpClientData clientData = {0}; + + // 设置HTTP客户端参数 + client.isHttp = true; + client.remotePort = 80; + + // 准备客户端数据 + HTTPC_RESULT prep_result = HttpClientPrepare(&clientData, 2048, 256 * 1024); + if (prep_result != HTTP_SUCCESS) { + retry_count++; + continue; + } + + // 执行HTTP GET请求 + result = HttpClientGetRequest(&client, full_url, &clientData); + + if (result == HTTP_SUCCESS) { + // 检查响应状态码 + int response_code = HttpClientGetResponseCode(&client); + + if (response_code == 200) { + // 处理响应数据 + if (clientData.responseBuf && clientData.responseBufLen > 0) { + // 调用结果处理函数 + agnss_download_result_handler(NULL, HTTP_SUCCESS, response_code, + clientData.responseBuf, clientData.responseBufLen); + } else { + agnss_download_result_handler(NULL, HTTP_ERECV, response_code, NULL, 0); + } + } else { + agnss_download_result_handler(NULL, HTTP_EPROTO, response_code, NULL, 0); + } + break; + } else { + // 简化错误处理,只保留必要的等待 + if (result == HTTP_EDNS) { + LOS_Msleep(500); + } else if (result == HTTP_ECONN) { + cleanup_agnss_response_buffer(); + LOS_Msleep(300); + } else if (result == HTTP_ENOBUFS) { + cleanup_agnss_response_buffer(); + LOS_Msleep(300); + } + } + + // 清理资源 + HttpClientUnprepare(&clientData); + HttpClientClse(&client); + + retry_count++; + } + + if (result != HTTP_SUCCESS) { + agnss_download_result_handler(NULL, result, 0, NULL, 0); + } + + return 0; +} + + +void do_gnss_http_server_send_data(int cmd,char *data,uint32_t len) +{ + errcode_t ret; + gnss_http_data_mail_t send_data = {0}; + send_data.cmd = cmd; + if(len && data) + { + send_data.len = len; + send_data.data = (char *)malloc(len); + if(send_data.data == NULL) + { + PRINT("malloc failed\n"); + return; + } + memcpy_s(send_data.data,len,data,len); + } + + uint32_t send_len = sizeof(send_data); + + ret = osal_msg_queue_write_copy(g_app_send_queue, (void *)&send_data, + send_len, 0); + if (ret != OSAL_SUCCESS) { + PRINT("Error gnss Check MSG 0x send failed! err=0x%x! \r\n", ret); + } +} + +void do_gnss_http_server_recv_data(int cmd,char *data,uint32_t len) +{ + errcode_t ret; + gnss_http_data_mail_t send_data = {0}; + send_data.cmd = cmd; + if(len && data) + { + send_data.len = len; + send_data.data = (char *)malloc(len); + if(send_data.data == NULL) + { + PRINT("malloc failed\n"); + return; + } + memcpy_s(send_data.data,len,data,len); + } + + uint32_t send_len = sizeof(send_data); + + ret = osal_msg_queue_write_copy(g_app_recv_queue, (void *)&send_data, + send_len, 0); + if (ret != OSAL_SUCCESS) { + PRINT("Error gnss Check MSG 0x send failed! err=0x%x! \r\n", ret); + } +} + +// 清理AGNSS响应缓冲区 +static void cleanup_agnss_response_buffer(void) +{ + if (g_agnss_response_buffer) { + free(g_agnss_response_buffer); + g_agnss_response_buffer = NULL; + g_agnss_response_size = 0; + g_agnss_response_capacity = 0; + printf("AGNSS response buffer cleaned up\n"); + } +} + +// 紧急清理函数 - 在检测到问题时调用 +static void emergency_cleanup(void) +{ + printf("Emergency cleanup initiated\n"); + cleanup_agnss_response_buffer(); + + // 重置所有静态变量 + g_processing_count = 0; + + // 清理可能的内存泄漏 + printf("Emergency cleanup completed\n"); +} + +// 网络连接检查函数 +static int check_network_connectivity(void) +{ + printf("=== Checking Network Connectivity ===\n"); + + // 检查CAT1电源状态 + int cat1_status = uapi_dev_runtime_get_cat1_powerstat(); + printf("CAT1 power status: %d (1=powered on, 0=powered off)\n", cat1_status); + + if (cat1_status != 1) { + printf("ERROR: CAT1 is not powered on!\n"); + return -1; + } + + // 检查网络接口状态(如果有相关API) + printf("Network interface appears to be available\n"); + + // 等待CAT1完全启动 + printf("Waiting for CAT1 to fully initialize...\n"); + LOS_Msleep(1000); // 减少到1秒 + + // 尝试简单的网络测试 + printf("Network connectivity check completed\n"); + return 0; +} + +// 内存状态检查函数 +static void check_memory_status(void) +{ + printf("=== Checking Memory Status ===\n"); + + // 检查AGNSS响应缓冲区状态 + if (g_agnss_response_buffer) { + printf("AGNSS response buffer: allocated %zu bytes\n", g_agnss_response_capacity); + } else { + printf("AGNSS response buffer: not allocated\n"); + } + + // 清理可能的内存泄漏 + cleanup_agnss_response_buffer(); + + printf("Memory status check completed\n"); +} + + +// 智能JSON清理函数 +static void smart_json_cleanup(void) +{ + if (g_agnss_response_buffer && g_agnss_response_size > 0) { + // 查找最后一个完整的JSON对象 + char *last_complete = NULL; + char *search_pos = g_agnss_response_buffer; + while ((search_pos = strstr(search_pos, "}]")) != NULL) { + last_complete = search_pos + 2; + search_pos += 2; + } + if (last_complete) { + size_t new_size = last_complete - g_agnss_response_buffer; + if (new_size < g_agnss_response_size) { + g_agnss_response_size = new_size; + g_agnss_response_buffer[g_agnss_response_size] = '\0'; + printf("Smart JSON cleanup: truncated to %zu bytes\n", g_agnss_response_size); + } + } + } +} + +static void gnss_http_server_send_task(void const *arg) +{ + unused(arg); + errcode_t ret; + + gnss_http_data_mail_t mail = {0}; + uint32_t msgsize = sizeof(gnss_http_data_mail_t); + + while (1) { + ret = osal_msg_queue_read_copy(g_app_send_queue, (void *)&mail, &msgsize, + OSAL_MSGQ_WAIT_FOREVER); + if (ret != OSAL_SUCCESS) { + continue; + } + + if(mail.cmd == GNSS_HTTP_SERVICE_CMD_DATA_UPLOAD) + { + // http_data_handler((int *)mail.data,mail.len); + // http_recv_data_handler(mail.data,mail.len); + if(mail.data != NULL) + { + printf("free(mail.data)\n"); + free(mail.data); + } + } + else if(mail.cmd == GNSS_HTTP_SERVICE_CMD_SERVER_INIT) + { + // gnss_http_init(); + uapi_delete_files(PGNSS_DATA_PATH); + // 检查文件夹是否已存在,避免重复创建 + DIR *dir = opendir(PGNSS_DATA_PATH); + if (dir == NULL) { + uapi_create_folder(PGNSS_DATA_PATH); + } else { + closedir(dir); + } + + // gnss_http_sign_up(); + // if(LK_STATUS == 1) + // { + // gnss_agnss_get_ephemeris(); + // } + // else + // { + // printf("NOT LK\n"); + // } + + } + else if(mail.cmd == GNSS_HTTP_SERVICE_CMD_SERVER_DEINIT) + { + // gnss_http_deinit(); + } + else if(mail.cmd == GNSS_HTTP_SERVICE_CMD_DOWNLOAD_AGNSS) + { + uapi_delete_files(PGNSS_DATA_PATH); + // 检查文件夹是否已存在,避免重复创建 + DIR *dir = opendir(PGNSS_DATA_PATH); + if (dir == NULL) { + uapi_create_folder(PGNSS_DATA_PATH); + } else { + closedir(dir); + } + + printf("Starting AGNSS files download via queue...\n"); + download_agnss_files(); + printf("AGNSS files download completed via queue.\n"); + } + } +} + + +static void gnss_http_server_recv_task(void const *arg) +{ + unused(arg); + errcode_t ret; + + gnss_http_data_mail_t mail = {0}; + uint32_t msgsize = sizeof(gnss_http_data_mail_t); + + // 添加任务保护计数器 + int task_loop_count = 0; + const int max_loop_count = 10000; // 防止无限循环 + + while (1) { + task_loop_count++; + if (task_loop_count > max_loop_count) { + printf("Warning: Task loop count exceeded %d, resetting counter\n", max_loop_count); + task_loop_count = 0; + // 清理可能的内存泄漏 + cleanup_agnss_response_buffer(); + } + + ret = osal_msg_queue_read_copy(g_app_recv_queue, (void *)&mail, &msgsize, + OSAL_MSGQ_WAIT_FOREVER); + if (ret != OSAL_SUCCESS) { + continue; + } + + if(mail.cmd == GNSS_HTTP_SERVICE_CMD_AGNSS_RECV) + { + if (mail.data == NULL) { + // 数据接收完成,处理完整的响应 + printf("AGNSS data reception completed, processing response...\n"); + agnss_process_complete_response(); + task_loop_count = 0; // 重置计数器 + } else { + // 接收数据片段 + printf("AGNSS data received via queue: %d bytes\n", mail.len); + agnss_accumulate_data(mail.data, mail.len); + free(mail.data); // 释放数据内存 + } + } + } +} + +static void create_gnss_http_send_queue(void) +{ + + if (osal_msg_queue_create("gnss_http_service_send_queue", 24, &g_app_send_queue, + 0, sizeof(gnss_http_data_mail_t)) != ERRCODE_SUCC) { + PRINT("[gnss][service] app create mail fail\n"); + } +} + +static void create_gnss_http_recv_queue(void) +{ + + if (osal_msg_queue_create("gnss_http_service_recv_queue", 24, &g_app_recv_queue, + 0, sizeof(gnss_http_data_mail_t)) != ERRCODE_SUCC) { + PRINT("[gnss][service] app create mail fail\n"); + } +} + +#define GNSS_HTTP_BOARD_TASK_SIZE 0x2000 +errcode_t uapi_gnss_http_server_init(void) +{ + PRINT("uapi_gnss_http_server_init !\r\n"); + + send_taskcfg.create_queue_handle = create_gnss_http_send_queue; + send_taskcfg.attr.name="gnss_http_server_send_task"; + send_taskcfg.attr.priority = osPriorityNormal; + send_taskcfg.attr.stack_size = GNSS_HTTP_BOARD_TASK_SIZE; + send_taskcfg.func = gnss_http_server_send_task; + send_taskcfg.use_mem = USE_EXTEND_MEM; + + errcode_t ret=uapi_create_osThread_custom(&send_taskcfg); + if(ret != ERRCODE_SUCC) + { + PRINT("create gnss_send_service failed %d!\r\n",ret); + return ERRCODE_FAIL; + } + + recv_taskcfg.create_queue_handle = create_gnss_http_recv_queue; + recv_taskcfg.attr.name="gnss_http_server_recv_task"; + recv_taskcfg.attr.priority = osPriorityNormal1; + recv_taskcfg.attr.stack_size = GNSS_HTTP_BOARD_TASK_SIZE; + recv_taskcfg.func = gnss_http_server_recv_task; + recv_taskcfg.use_mem = USE_EXTEND_MEM; + + ret=uapi_create_osThread_custom(&recv_taskcfg); + if(ret != ERRCODE_SUCC) + { + PRINT("create gnss_recv_service failed %d!\r\n",ret); + return ERRCODE_FAIL; + } + + return ERRCODE_SUCC; +} diff --git a/code/sdk/zhihui/services/gnss/src/gnss_tcp_server.c b/code/sdk/zhihui/services/gnss/src/gnss_tcp_server.c deleted file mode 100644 index 21c9f01b7..000000000 --- a/code/sdk/zhihui/services/gnss/src/gnss_tcp_server.c +++ /dev/null @@ -1,1216 +0,0 @@ -#include "pinctrl.h" -#include "debug_print.h" -#include "rtc.h" -#include "timer.h" -#include "systick.h" - -#include "tcxo.h" - -#include "cmsis_os2.h" -#include "input_app.h" -#include "gnss_service.h" -#include "custom_utils.h" -#include "gnss_tcp_server.h" -#include "custom_runtime.h" -#include -#include "lwip/ip.h" -#include "lwip/netif.h" -#include "lwip/init.h" -#include "lwip/inet_chksum.h" - -#include "lwip/err.h" -#include "lwip/sockets.h" -#include "lwip/sys.h" -#include -// #include -#include "lwip/inet.h" -#include "lwip/ip_addr.h" -#include "pm_definition.h" -#include "mbedtls/md5.h" -#include "mbedtls/base64.h" -#include "cJSON.h" -#include "mbedtls/hmac_drbg.h" - -#define BID "hu4kZYyYMGO" -#define KEY "tcUpJpeGpsIBXvjG" - -#define HOST "iot.socket.thisiot.com" -#define PORT 9999 - -#define URL "https://geo-drcn.platform.dbankcloud.cn/higeo/v1/xgnss/agnss" -#define APP_ID "coolwearable" -#define APP_SECRET "a0e0852c9fd25fad56b6e281b542020d7d01c975907c0b9585ed7f9462447a59" - -#define PGNSS_DATA_PATH "/user/userdata/gnss" - -static unsigned long g_app_queue= 0xFFFFFFFF; - -static int g_tcp_sock = -1; - -static uint8_t LK_STATUS = 0; - -static char *imei = NULL; - -static char *rx_buffer = NULL; - -static uint8_t GNSS_TCP_SERVER_STAT = 0; - -static app_task_definition_t send_taskcfg={0}; -static app_task_definition_t recv_taskcfg={0}; - -struct gnss_ipaddr_t -{ - osSemaphoreId_t dns_done_sem; - ip_addr_t ip; -}; - - -// Base64 编码函数 -static char *base64_encode(const unsigned char *input, size_t length) -{ - // 计算 Base64 编码后的最大长度 - size_t encoded_len = 4 * ((length + 2) / 3) + 1; - char *encoded = (char *)malloc(encoded_len); - if (encoded == NULL) { - return NULL; - } - - size_t output_len; - int ret = mbedtls_base64_encode((unsigned char *)encoded, encoded_len, &output_len, input, length); - if (ret != 0) { - free(encoded); - return NULL; - } - - return encoded; -} - -static char *compute_hmac_sha256_base64(const char *str_to_sign) -{ - if (str_to_sign == NULL) { - fprintf(stderr, "Error: str_to_sign is NULL\n"); - return NULL; - } - - // 输出缓冲区 - unsigned char hmac_result[32]; - size_t hmac_len = sizeof(hmac_result); - - // Base64 编码结果缓冲区 - size_t b64_len = 4 * ((hmac_len + 2) / 3) + 1; - char *base64_result = (char *)malloc(b64_len); - if (base64_result == NULL) { - fprintf(stderr, "Memory allocation failed\n"); - return NULL; - } - - // 获取 SHA-256 算法信息 - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); - if (md_info == NULL) { - fprintf(stderr, "Failed to get SHA-256 algorithm\n"); - goto cleanup; - } - - // 使用标准 HMAC 计算 API - int ret = mbedtls_md_hmac( - md_info, // 算法信息 - (const unsigned char *)APP_SECRET, // 密钥 - strlen(APP_SECRET), // 密钥长度 - (const unsigned char *)str_to_sign, // 待签名数据 - strlen(str_to_sign), // 数据长度 - hmac_result // 输出结果 - ); - - if (ret != 0) { - fprintf(stderr, "HMAC calculation failed: %d\n", ret); - goto cleanup; - } - - // 调试输出 - printf("HMAC-SHA256 result (hex): "); - for (int i = 0; i < hmac_len; i++) { - printf("%02x", hmac_result[i]); - } - printf("\n"); - - // Base64 编码 - size_t olen; - ret = mbedtls_base64_encode( - (unsigned char *)base64_result, - b64_len, - &olen, - hmac_result, - hmac_len - ); - - if (ret != 0) { - fprintf(stderr, "Base64 encoding failed: %d\n", ret); - free(base64_result); - base64_result = NULL; - goto cleanup; - } - - printf("Base64 result: %s\n", base64_result); - -cleanup: - return base64_result; -} - -static void dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg) -{ - struct gnss_ipaddr_t *ip_sem = (struct gnss_ipaddr_t *)arg; - char ip_str[20] = {0}; - - // if (ipaddr == NULL) { - // printf("DNS解析失败,IP地址为空\n"); - // (void)osSemaphoreRelease(ip_sem->dns_done_sem); - // return; - // } - - printf("hostname: %s, ", hostname); - - // 处理IPv4地址(现在ip4是包含addr成员的结构体) - if (IP_IS_V4(ipaddr)) { - u32_t ip_num = ipaddr->u_addr.ip4.addr; // 直接获取32位地址 - - // 分解为4字节打印 - u8_t byte0 = (ip_num >> 24) & 0xFF; - u8_t byte1 = (ip_num >> 16) & 0xFF; - u8_t byte2 = (ip_num >> 8) & 0xFF; - u8_t byte3 = ip_num & 0xFF; - // printf("IPv4: %d.%d.%d.%d\n", byte0, byte1, byte2, byte3); - - // 转换为struct in_addr(已为网络字节序) - struct in_addr ipv4_addr; - ipv4_addr.s_addr = ip_num; - inet_ntop(AF_INET, &ipv4_addr, ip_str, sizeof(ip_str)); - printf("ip: %s\n", ip_str); - } - - // 复制IP地址到上下文 - if(ipaddr->u_addr.ip4.addr != 0) - memcpy(&(ip_sem->ip), ipaddr, sizeof(ip_addr_t)); - (void)osSemaphoreRelease(ip_sem->dns_done_sem); -} - -int gnss_tcp_socket_init(void) -{ - uint8_t cnt = pm_veto_get_id_cnt(PM_ID_CAT1); - if (cnt == 0) { - uapi_pm_add_sleep_veto(PM_ID_CAT1); - } - - struct sockaddr_in server_addr; - struct gnss_ipaddr_t ip_sem = {0}; // 定义信号量结构 - int listen_socket = -1; - - // 创建信号量 - ip_sem.dns_done_sem = osSemaphoreNew(1, 0, NULL); - - // 解析域名 - dns_gethostbyname(HOST, &(ip_sem.ip), dns_found, &ip_sem); - - osSemaphoreAcquire(ip_sem.dns_done_sem, 1000); // 等待 DNS 解析完成 - - memcpy(&server_addr.sin_addr.s_addr, &ip_sem.ip.u_addr.ip4, 4); - - // 创建套接字 - - if(listen_socket < 0) - { - listen_socket = lwip_socket(AF_INET, SOCK_STREAM, 0); - if(listen_socket < 0) - { - int err = errno; - printf("socket create errno: %d, reason: %s\n", err, strerror(err)); - goto FAILED; - } - } - - int opt = 1; - - lwip_setsockopt(listen_socket, SOL_SOCKET, SO_KEEPALIVE, (const void*)&opt, sizeof(opt)); - lwip_setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR,(const void*)&opt, sizeof(opt)); - - // 设置服务器地址 - server_addr.sin_family = AF_INET; - server_addr.sin_port = htons(PORT); - - // 连接服务器 - if (lwip_connect(listen_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) - { - printf("server_addr.sin_addr.s_addr:%d\n",server_addr.sin_addr.s_addr); - int err = errno; - printf("connect failed, errno: %d, reason: %s\n", err, strerror(err)); - - goto FAILED; - } - - printf("socket init succed\n"); - osSemaphoreDelete(ip_sem.dns_done_sem); // 释放信号量 - - cnt = pm_veto_get_id_cnt(PM_ID_CAT1); - if (cnt == 1) { - uapi_pm_remove_sleep_veto(PM_ID_CAT1); - } - - return listen_socket; - -FAILED: - if (listen_socket >= 0) - { - lwip_close(listen_socket); - } - if (ip_sem.dns_done_sem != NULL) - { - osSemaphoreDelete(ip_sem.dns_done_sem); - } - cnt = pm_veto_get_id_cnt(PM_ID_CAT1); - if (cnt == 1) - { - uapi_pm_remove_sleep_veto(PM_ID_CAT1); - } - return -1; -} - -static int tcp_send(int listen_socket, const char *data, size_t size) -{ - if (data == NULL || size == 0) - return -1; - - uint8_t retry = 0; - while(listen_socket < 0 && retry < 5) - { - retry++; - LOS_Msleep(2000); - } - - if(listen_socket < 0) - { - printf("listen_socket < 0 \n"); - return -1; - } - - int ret = 0; - - // const char *buffer = (const char *)data; - const char *buffer = (const char *)malloc(size); - if(buffer == NULL) - return -1; - - memcpy_s(buffer,size,(const char *)data,size); - // printf("size : %d\n",size); - // printf("strlen(buffer) : %d\n",strlen(buffer)); - // printf("buffer : %s\n",buffer); - - size_t total_sent = 0; - - while (total_sent < size) - { - ssize_t sent = lwip_send(listen_socket, buffer + total_sent, size - total_sent, 0); - if (sent < 0) { - printf("errno : %d\n",errno); - // 处理错误情况 - if (errno == EINTR) { - PRINT("被信号中断,继续尝试\n"); - ret = -1; - continue; - } else if (errno == EAGAIN || errno == EWOULDBLOCK) { - PRINT("非阻塞模式下暂时无法发送,可选择等待或返回\n"); - ret = -1; - goto FAILED; - } else if (errno == ENETUNREACH) { - PRINT("网络不可达,检查路由或远程主机状态\n"); - ret = -1; - goto FAILED; - } - else { - PRINT("其他错误(如连接断开)\n"); - ret = -1; - goto FAILED; - } - } - - total_sent += sent; - } - printf("tcp send succed size : %d\n",total_sent); - ret = 0; -FAILED: - - if(buffer != NULL) - { - free(buffer); - buffer = NULL; - } - return ret; -} - -static int active_md5_sign(const char *data,int data_len,char*md5_str) -{ - char md5_buf[16]={0}; - - char *code_str = (const char*)malloc(data_len); - if(md5_str == NULL) - return -1; - - memcpy_s(code_str,data_len,data,data_len); - mbedtls_md5_context ctx; - - // 初始化MD5上下文 - mbedtls_md5_init(&ctx); - - // 开始计算MD5哈希 - mbedtls_md5_starts(&ctx); - // 更新要计算哈希的数据 - mbedtls_md5_update(&ctx, (const unsigned char *)code_str, data_len); - - // 完成哈希计算 - mbedtls_md5_finish(&ctx, (unsigned char *)md5_buf); - - // printf("md5_buf\r\n"); - // for (int i = 0; i < 16; i++) { - // printf("%02X\n", (uint8_t)md5_buf[i]); - // } - // printf("md5_buf end\r\n"); - - // 清理MD5上下文 - mbedtls_md5_free(&ctx); - for (int i = 0; i < 16; i++) - sprintf(&md5_str[i * 2], "%02x", (uint8_t)md5_buf[i]); - - md5_str[32] = '\0'; - - free(code_str); - - return 0; -} - -static void calculate_md5(const char* input, char* md5_str) -{ - mbedtls_md5_context md5; - unsigned char md5_digest[16] = {0}; - int i; - - // printf("input:%s\n",input); - - mbedtls_md5_init(&md5); - mbedtls_md5_starts(&md5); - mbedtls_md5_update(&md5, (const unsigned char*)input, strlen(input)); - mbedtls_md5_finish(&md5, md5_digest); - mbedtls_md5_free(&md5); - - // 转换为十六进制字符串 - for (i = 0; i < 16; i++) { - sprintf(md5_str + i*2, "%02x", md5_digest[i]); - } - md5_str[32] = '\0'; // 确保字符串终止 -} - -int gnss_tcp_sign_up(void) -{ - int ret = 0; - char len_str[5] = {0}; - sprintf(len_str, "%04x", 2); - - if(imei == NULL) - { - imei = uapi_dev_runtime_get_cat1_imei(); - - if(imei == NULL || strlen(imei) == 0) - { - LOS_Msleep(2000); - imei = uapi_dev_runtime_get_cat1_imei(); - } - - if (imei == NULL || strlen(imei) == 0) - { - printf("IMEI get failed\n"); - ret = -1; - goto FAILED; - } - } - // printf("imei:%s\n", imei); - - // head_str长度:BID + * + IMEI + * + len_str + * + LK + \0 - int head_len = strlen(BID) + 1 + strlen(imei) + 1 + strlen(len_str) + 1 + strlen("LK") + 1; - char *head_str = (char *)malloc(head_len); - if(head_str == NULL) - { - printf("tcp_sign_up head_str malloc failed\n"); - ret = -1; - goto FAILED; - } - - snprintf(head_str, head_len, "%s*%s*%s*LK", BID,imei,len_str); - head_len = strlen(head_str); - - char md5_str[33] = {0}; // MD5为32字符+1终止符 - - // code_str长度:head_str + KEY + \0 - int code_len = head_len + strlen(KEY) + 1; - char *code_str = (char *)malloc(code_len); - if(code_str == NULL) - { - printf("code_str malloc failed\n"); - ret = -1; - goto FAILED; - } - - snprintf(code_str, code_len, "%s%s", head_str, KEY); - code_len = strlen(code_str); - - calculate_md5(code_str,md5_str); - - // if(active_md5_sign(code_str, code_len, md5_str) != 0) - // { - // printf("active_md5_sign failed\n"); - // ret = -1; - // goto FAILED; - // } - - // 计算send_str长度:[ + md5_str + head_str + ] + \0 - int send_len = 1 + strlen(md5_str) + strlen(head_str) + 1 + 1; - char *send_str = (char *)malloc(send_len); - if(send_str == NULL) - { - printf("send_str malloc failed\n"); - ret = -1; - goto FAILED; - } - - snprintf(send_str, send_len, "[%s%s]", md5_str, head_str); - send_len = strlen(send_str); - - // printf("md5_str:%s\n", md5_str); - // printf("md5_len:%zu\n", strlen(md5_str)); - // printf("head_len:%d\n", head_len); - // printf("head_str:%s\n", head_str); - printf("send_len : %d\n", send_len); - printf("send_str : %s\n", send_str); - - // 发送数据 - while(LK_STATUS != 1) - { - ret = tcp_send(g_tcp_sock, send_str, send_len); - if(ret != 0) - { - printf("tcp_send failed\n"); - goto FAILED; - } - - LOS_Msleep(2000); - } - - -FAILED: - // 释放资源 - if(head_str != NULL) - { - free(head_str); - head_str = NULL; - } - if(code_str != NULL) - { - free(code_str); - code_str = NULL; - } - if(send_str != NULL) - { - free(send_str); - send_str = NULL; - } - - return ret; -} - - -static int calculate_base64_length(int cnt) -{ - if (cnt <= 0) - return -1; - - // 1. 计算int数组转换为字符串的最大可能长度 - // int的最大字符串长度:11个字符(如"-2147483648") - // 每个int后加一个逗号(最后一个int除外) - int str_length = cnt * 11 + (cnt - 1); - - // 2. 计算Base64编码长度 - // Base64编码规则:每3字节明文→4字节编码,不足3字节用'='填充 - int base64_length = (str_length * 4 + 2) / 3; - - // 3. 确保编码长度足够容纳终止符 - base64_length += 1; // 预留终止符空间 - - return base64_length; -} - -int gnss_tcp_login(void) -{ - int ret = -1; - char *data_str = NULL; - int data_len = 0; - char *encode_str = NULL; - int encode_len = 0; - - int head_len = 0; - char *code_str = NULL; - int code_len = 0; - char *send_str = NULL; - int send_len = 0; - uint32_t output_len = 0; - int temp_len = 0; - - char len_str[5] = {0}; - char md5_str[33] = {0}; - - uint32_t time = 0; - uapi_get_timestampe_ss(&time); - printf("time:%d \n",time); - - char *sign_str = (char *)malloc(256); - if(sign_str == NULL) - { - printf("sign_str malloc failed\n"); - goto FAILED; - } - - snprintf(sign_str,256, "GET&/higeo/v1/xgnss/agnss&&&appid=%s×tamp=%lld", APP_ID,(long long)time * 1000); - // snprintf(sign_str,256, "GET&/higeo/v1/xgnss/agnss&&appid=%s×tamp=%lld", APP_ID,(long long)time * 1000); - // snprintf(sign_str,256, "GET&/higeo/v1/xgnss/agnss&&appid=%s×tamp=%d", APP_ID,time*1000); - // snprintf(sign_str,256, "GET&/higeo/v1/xgnss/agnss&&&appid=coolwearable×tamp=1752717734000"); - - printf("sign_str : %s\n",sign_str); - char *ret_str = compute_hmac_sha256_base64(sign_str); - if(ret_str == NULL) - { - printf("compute_hmac_sha256_base64 failed\n"); - goto FAILED; - } - - printf("ret_str : %s\n",ret_str); - - - char *header_json = (char *)malloc(512); - if(header_json == NULL) - goto FAILED; - - temp_len = 0; - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "{\"headers\":["); - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "{\"key\":\"Authorization\","); - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "\"value\":\"HMAC-SHA256\"},"); - - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "{\"key\":\"appid\","); - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "\"value\":\"%s\"},", APP_ID); - - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "{\"key\":\"timestamp\","); - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "\"value\":\"%lld\"},", (long long)time * 1000); - - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "{\"key\":\"signature\","); - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "\"value\":\"%s\"},", ret_str); - - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "{\"key\":\"X-Request-ID\","); - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "\"value\":\"%s\"}", imei); - // temp_len += snprintf(header_json + temp_len,512 - temp_len, "]}"); - - - temp_len += snprintf(header_json + temp_len,256 - temp_len, "{\"headers\":["); - temp_len += snprintf(header_json + temp_len,256 - temp_len, "{\"key\":\"X-Request-ID\","); - temp_len += snprintf(header_json + temp_len,256 - temp_len, "\"value\":\"%s\"},", imei); - temp_len += snprintf(header_json + temp_len,256 - temp_len, "{\"key\":\"Authorization\","); - temp_len += snprintf(header_json + temp_len,256 - temp_len, "\"value\":\"HMAC-SHA256 appid=%s,timestamp=%lld,signature=%s\"}", APP_ID,(long long)time * 1000,ret_str); - temp_len += snprintf(header_json + temp_len,256 - temp_len, "]}"); - - if(temp_len > 512) - { - printf("temp_len > 512 \n"); - goto FAILED; - } - printf("URL : %s\n",URL); - printf("header_json : %s\n",header_json); - - int encode_header_len = temp_len * 3 / 2; - char *encode_header_str = (char *)malloc(encode_header_len); - if(NULL == encode_header_str) - { - printf("encode_header_str malloc failed\n"); - goto FAILED; - } - - memset(encode_header_str,0, encode_header_len); - size_t output_header_len = 0; - if(0 != mbedtls_base64_encode((unsigned char*)encode_header_str, encode_header_len, &output_header_len, (const unsigned char*)header_json, temp_len)) - { - printf("encode_header_str base64 encode failed\n"); - goto FAILED; - } - - data_len = 1 + strlen("GET") + 1 + strlen(URL) + 1 + 1 + output_header_len + 1; - data_str = (char *)malloc(data_len); - if (data_str == NULL) { - printf("data_str malloc failed\n"); - goto FAILED; - } - memset(data_str, 0, data_len); - snprintf(data_str,data_len, ",GET,%s,%s,", URL,encode_header_str); - - data_len = strlen(data_str); - sprintf(len_str, "%04x", data_len + 8); - - head_len = strlen(BID) + 1 + strlen(imei) + 1 + strlen(len_str) + 1 + strlen("TCP_HTTP") + 1; - // head_len = strlen(BID) + 1 + 15 + 1 + strlen(len_str) + 1 + strlen("TCP_HTTP") + 1; - char *head_str = (char *)malloc(head_len); - if (head_str == NULL) { - printf("head_str malloc failed\n"); - goto FAILED; - } - snprintf(head_str, head_len, "%s*%s*%s*TCP_HTTP", BID, imei, len_str); - // snprintf(head_str, head_len, "%s*864430010001091*%s*TCP_HTTP", BID, len_str); - - head_len = strlen(head_str); - - code_len = head_len + strlen(KEY) + 1; - code_str = (char *)malloc(code_len); - if (code_str == NULL) { - printf("code_str malloc failed\n"); - goto FAILED; - } - snprintf(code_str, code_len, "%s%s", head_str, KEY); - // printf("code_str:%s\n", code_str); - // printf("code_len:%d\n", code_len); - - calculate_md5(code_str,md5_str); - if(strlen(md5_str) == 0) - { - printf("MD5 failed\n"); - goto FAILED; - } - // if (active_md5_sign(code_str, code_len, md5_str) != 0) { - // printf("MD5签名失败\n"); - // goto FAILED; - // } - - send_len = 1 + strlen(md5_str) + head_len + data_len + 1 + 1; // [ + md5 + head + data + ] + \0 - - send_str = (char *)malloc(send_len); - if (send_str == NULL) { - printf("send_str malloc failed\n"); - goto FAILED; - } - snprintf(send_str, send_len, "[%s%s%s]", md5_str, head_str, data_str); - send_len = strlen(send_str); - - - // printf("md5_str:%s\n", md5_str); - // printf("md5_len:%zu\n", strlen(md5_str)); - // printf("head_len:%d\n", head_len); - // printf("head_str:%s\n", head_str); - // printf("data_len:%d\n", data_len); - // printf("data_str:%s\n", data_str); - printf("send_len : %d\n", send_len); - printf("send_str : %s\n", send_str); - - // 发送数据 - ret = tcp_send(g_tcp_sock, send_str, send_len); - if(ret != 0) - { - printf("tcp_send failed\n"); - goto FAILED; - } - -FAILED: - if (header_json != NULL) { - free(header_json); - header_json = NULL; - } - if (sign_str != NULL) { - free(sign_str); - sign_str = NULL; - } - if (ret_str != NULL) { - free(ret_str); - ret_str = NULL; - } - if (send_str != NULL) { - free(send_str); - send_str = NULL; - } - if (code_str != NULL) { - free(code_str); - code_str = NULL; - } - if (head_str != NULL) { - free(head_str); - head_str = NULL; - } - if (data_str != NULL) { - free(data_str); - data_str = NULL; - } - if (encode_str != NULL) { - free(encode_str); - encode_str = NULL; - } - - return ret; -} - -void do_gnss_tcp_server_send_data(int cmd,char *data,uint32_t len) -{ - if((data == NULL || len == 0) && cmd == GNSS_TCP_SERVICE_CMD_DATA_UPLOAD) - return; - - errcode_t ret; - gnss_tcp_data_mail_t send_data = {0}; - send_data.cmd = cmd; - if(len && data) - { - send_data.len = len; - send_data.data = (char *)malloc(len); - if(send_data.data == NULL) - { - PRINT("malloc failed\n"); - return; - } - memcpy_s(send_data.data,len,data,len); - } - - uint32_t send_len = sizeof(send_data); - - ret = osal_msg_queue_write_copy(g_app_queue, (void *)&send_data, - send_len, 0); - if (ret != OSAL_SUCCESS) { - PRINT("Error gnss Check MSG 0x send failed! err=0x%x! \r\n", ret); - } -} - -static void gnss_tcp_deinit(void) -{ - printf("gnss_tcp_deinit \n"); - - GNSS_TCP_SERVER_STAT = 0; - - LK_STATUS = 0; - - if(rx_buffer != NULL) - { - printf("free rx_buffer\n"); - free(rx_buffer); - rx_buffer = NULL; - } - if(g_tcp_sock >= 0) - { - if(lwip_close(g_tcp_sock) != 0) - printf("lwip_close failed\n"); - else - printf("lwip_close succed\n"); - - g_tcp_sock = -1; - } - -} - -int gnss_tcp_init(void) -{ - if(LK_STATUS != 1) - { - printf("NOT LK\n"); - return -1; - } - gnss_tcp_login(); - return 0; -} - -static void pgnss_data_save(uint8_t *rx_buffer, uint32_t len) -{ - if (rx_buffer == NULL || len == 0) { - printf("invalid param\n"); - return; - } - - FILE *fp = fopen(PGNSS_DATA_PATH, "a+b"); - if (fp == NULL) { - printf("open %s failed\n", PGNSS_DATA_PATH); - return; - } - - size_t written = fwrite(rx_buffer, 1, len, fp); - if (written != len) { - printf("fwrite failed\n"); - } else { - printf("fwrite succed :%d\n", written); - } - - fflush(fp); - fclose(fp); -} - -static void tcp_recv_data_handler(const char *input, int input_len) -{ - if(input[0] == '[') - { - const char *data = input + 1; - size_t data_len = input_len - 2; - - const char *comma1 = memchr(data, ',', data_len); - const char *comma2 = comma1 ? memchr(comma1 + 1, ',', data_len - (comma1 - data + 1)) : NULL; - - const char *star1 = memchr(data, '*', data_len); - const char *star2 = star1 ? memchr(star1 + 1, '*', data_len - (star1 - data + 1)) : NULL; - const char *star3 = star2 ? memchr(star2 + 1, '*', data_len - (star2 - data + 1)) : NULL; - - if (!star1 || !star2 || !star3) - { - printf("解析失败: 头部格式错误(缺少星号分隔符)\n"); - return; - } - - const char *bid = data; - const char *imei = star1 + 1; - const char *len_str = star2 + 1; - const char *cmd = star3 + 1; - - size_t bid_len = star1 - data; - size_t imei_len = star2 - (star1 + 1); - size_t len_str_len = star3 - (star2 + 1); - size_t cmd_len = data_len - (star3 - data + 1); - - // 打印头部解析结果 - // printf("BID: %.*s\n", (int)bid_len, bid); - // printf("IMEI: %.*s\n", (int)imei_len, imei); - // printf("内容长度: %.*s\n", (int)len_str_len, len_str); - // printf("指令: %.*s\n", (int)cmd_len, cmd); - - // 验证IMEI长度(假设为15位) - if (imei_len != 15) - { - printf("解析失败: IMEI长度应为15位,实际: %zu位\n", imei_len); - return; - } - - uint32_t content_len = 0; - sscanf(len_str, "%x", &content_len); - printf("解析后的内容长度: %u\n", content_len); - - if (comma1 && comma2) - { - size_t status_len = comma2 - (comma1 + 1); - size_t base64_len = data_len - (comma2 - data + 1); - - printf("状态码: %.*s\n", (int)status_len, comma1 + 1); - - if (strncmp(comma1 + 1, "200", status_len) != 0) - { - printf("解析失败: 状态码必须为200,实际: %.*s\n", (int)status_len, comma1 + 1); - return; - } - - size_t decoded_len = (base64_len * 3) / 4 + 1; - unsigned char *decoded_data = malloc(decoded_len); - if (!decoded_data) - { - printf("解析失败: 内存分配失败\n"); - return; - } - - size_t actual_decoded_len = 0; - int ret = mbedtls_base64_decode(decoded_data, decoded_len, &actual_decoded_len,(const unsigned char *)(comma2 + 1), base64_len); - - if (ret != 0) - { - printf("解析失败: Base64解码失败 (错误码: %d) :%s\n", ret,input); - free(decoded_data); - return; - } - decoded_data[actual_decoded_len] = '\0'; - - for (uint32_t i = 0; i < actual_decoded_len; i++) - { - printf("%02X ", decoded_data[i]); - } - printf("\n"); - - // remove(AGNSS_DATA_PATH); - pgnss_data_save(decoded_data,actual_decoded_len); - } - } - else if(input[input_len - 1] == ']') - { - size_t decoded_len = ((input_len - 1) * 3) / 4 + 1; - unsigned char *decoded_data = malloc(decoded_len); - if (!decoded_data) - { - printf("解析失败: 内存分配失败\n"); - return; - } - - size_t actual_decoded_len = 0; - int ret = mbedtls_base64_decode(decoded_data, decoded_len, &actual_decoded_len,(const unsigned char *)(input), input_len - 1); - - if (ret != 0) - { - printf("解析失败: Base64解码失败 (错误码: %d) :%s\n", ret,input); - free(decoded_data); - return; - } - decoded_data[actual_decoded_len] = '\0'; - - for (uint32_t i = 0; i < actual_decoded_len; i++) - { - printf("%02X ", decoded_data[i]); - } - printf("\n"); - pgnss_data_save(decoded_data,actual_decoded_len); - LOS_Msleep(1000); - do_gnss_tcp_server_send_data(GNSS_TCP_SERVICE_CMD_SERVER_DEINIT,NULL,0); - } - else - { - size_t decoded_len = (input_len * 3) / 4 + 1; - unsigned char *decoded_data = malloc(decoded_len); - if (!decoded_data) - { - printf("解析失败: 内存分配失败\n"); - return; - } - - size_t actual_decoded_len = 0; - int ret = mbedtls_base64_decode(decoded_data, decoded_len, &actual_decoded_len,(const unsigned char *)(input), input_len); - - if (ret != 0) - { - printf("解析失败: Base64解码失败 (错误码: %d) :%s\n", ret,input); - free(decoded_data); - return; - } - decoded_data[actual_decoded_len] = '\0'; - - for (uint32_t i = 0; i < actual_decoded_len; i++) - { - printf("%02X ", decoded_data[i]); - } - printf("\n"); - pgnss_data_save(decoded_data,actual_decoded_len); - } - -} - -static void gnss_tcp_server_send_task(void const *arg) -{ - unused(arg); - errcode_t ret; - - gnss_tcp_data_mail_t mail = {0}; - uint32_t msgsize = sizeof(gnss_tcp_data_mail_t); - - while (GNSS_TCP_SERVER_STAT) { - ret = osal_msg_queue_read_copy(g_app_queue, (void *)&mail, &msgsize, - OSAL_MSGQ_WAIT_FOREVER); - if (ret != OSAL_SUCCESS) { - continue; - } - - if(mail.cmd == GNSS_TCP_SERVICE_CMD_DATA_UPLOAD) - { - // tcp_data_handler((int *)mail.data,mail.len); - tcp_recv_data_handler(mail.data,mail.len); - if(mail.data != NULL) - { - printf("free(mail.data)\n"); - free(mail.data); - } - } - else if(mail.cmd == GNSS_TCP_SERVICE_CMD_SERVER_INIT) - { - // gnss_tcp_init(); - uapi_delete_files(PGNSS_DATA_PATH); - uapi_create_folder(PGNSS_DATA_PATH); - - gnss_tcp_sign_up(); - if(LK_STATUS == 1) - { - gnss_tcp_login(); - } - else - { - printf("NOT LK\n"); - } - - } - else if(mail.cmd == GNSS_TCP_SERVICE_CMD_SERVER_DEINIT) - { - gnss_tcp_deinit(); - } - } -} - - -static void gnss_tcp_server_recv_task(void *pvParameters) -{ - while (GNSS_TCP_SERVER_STAT) - { - if (!uapi_cat1_get_power_stat()) - { - PRINT("wating cat1 power on\n"); - LOS_Msleep(2000); - continue; - } - - if (g_tcp_sock < 0) - { - g_tcp_sock = gnss_tcp_socket_init(); - if (g_tcp_sock < 0) - { - PRINT("wating tcp socket init\n"); - LOS_Msleep(1000); - continue; - } - else - do_gnss_tcp_server_send_data(GNSS_TCP_SERVICE_CMD_SERVER_INIT,NULL,0); - } - - if(rx_buffer == NULL) - { - rx_buffer = (char *)malloc(2048); - if(rx_buffer == NULL) - { - printf("rx_buffer malloc failed\n"); - do_gnss_tcp_server_send_data(GNSS_TCP_SERVICE_CMD_SERVER_DEINIT,NULL,0); - return; - } - } - - // if (tcp_socket_init() != 0) - // { - // PRINT("wating tcp socket init\n"); - // LOS_Msleep(100); - // continue; - // } - - // PRINT("tcp socket init succed\n"); - - // get_active_code(); - // if(tcp_sign_up() != 0) - // { - // LOS_Msleep(1000); - // continue; - // } - - // printf("tcp_sign_up\n"); - - memset(rx_buffer, 0, 2048); - int len = recv(g_tcp_sock, rx_buffer, 2048 - 1, 0); - if (len > 0) - { - rx_buffer[len] = '\0'; - // printf("Received %d bytes: %s\n", len, rx_buffer); - if(strstr(rx_buffer,"LK") != NULL) - { - printf("LK succed\n"); - LK_STATUS = 1; - } - else - { - do_gnss_tcp_server_send_data(GNSS_TCP_SERVICE_CMD_DATA_UPLOAD,rx_buffer,len); - } - } - else if (len == 0) - { - printf("Connection closed by peer\n"); - do_gnss_tcp_server_send_data(GNSS_TCP_SERVICE_CMD_SERVER_DEINIT,NULL,0); - } - } -} - -static void create_gnss_tcp_queue(void) -{ - - if (osal_msg_queue_create("gnss_tcp_service_queue", 24, &g_app_queue, - 0, sizeof(gnss_tcp_data_mail_t)) != ERRCODE_SUCC) { - PRINT("[gnss][service] app create mail fail\n"); - } -} - -#define GNSS_TCP_BOARD_TASK_SIZE 0x2000 -errcode_t uapi_gnss_tcp_server_init(void) -{ - PRINT("uapi_gnss_tcp_server_init !\r\n"); - - if(GNSS_TCP_SERVER_STAT == 1) - { - PRINT("uapi_gnss_tcp_server already init !\r\n"); - return ERRCODE_SUCC; - } - - GNSS_TCP_SERVER_STAT = 1; - - send_taskcfg.create_queue_handle = create_gnss_tcp_queue; - send_taskcfg.attr.name="gnss_tcp_server_send_task"; - send_taskcfg.attr.priority = osPriorityNormal; - send_taskcfg.attr.stack_size = GNSS_TCP_BOARD_TASK_SIZE; - send_taskcfg.func = gnss_tcp_server_send_task; - send_taskcfg.use_mem = USE_EXTEND_MEM; - - errcode_t ret=uapi_create_osThread_custom(&send_taskcfg); - if(ret != ERRCODE_SUCC) - { - PRINT("create gnss_send_service failed %d!\r\n",ret); - return ERRCODE_FAIL; - } - - recv_taskcfg.create_queue_handle = NULL; - recv_taskcfg.attr.name="gnss_tcp_server_recv_task"; - recv_taskcfg.attr.priority = osPriorityNormal1; - recv_taskcfg.attr.stack_size = GNSS_TCP_BOARD_TASK_SIZE; - recv_taskcfg.func = gnss_tcp_server_recv_task; - recv_taskcfg.use_mem = USE_EXTEND_MEM; - - ret=uapi_create_osThread_custom(&recv_taskcfg); - if(ret != ERRCODE_SUCC) - { - PRINT("create gnss_recv_service failed %d!\r\n",ret); - return ERRCODE_FAIL; - } - - // g_gnss_service_timer = osTimerNew((osTimerFunc_t)gnss_service_check_timer_callback, osTimerPeriodic, NULL, NULL); - - return ERRCODE_SUCC; -} - -// void gnss_tcp_server_suspend(void) -// { -// if(recv_taskcfg.task_handle == NULL || send_taskcfg.task_handle) -// return; - - -// errcode_t ret = uapi_suspend_thread(recv_taskcfg.task_handle); -// if(ret != ERRCODE_SUCC) -// PRINT("gnss_recv_thread_suspend failed ret : %d \n",ret); -// else -// PRINT("gnss_recv_thread_suspend succed\n"); - -// ret = uapi_suspend_thread(send_taskcfg.task_handle); -// if(ret != ERRCODE_SUCC) -// PRINT("gnss_send_thread_suspend failed ret : %d \n",ret); -// else -// PRINT("gnss_send_thread_suspend succed\n"); - -// } - -// void gnss_tcp_server_resume(void) -// { -// if(recv_taskcfg.task_handle == NULL || send_taskcfg.task_handle) -// return; - -// errcode_t ret = uapi_suspend_thread(recv_taskcfg.task_handle); -// if(ret != ERRCODE_SUCC) -// PRINT("gnss_recv_thread_suspend failed ret : %d \n",ret); -// else -// PRINT("gnss_recv_thread_suspend succed\n"); - -// ret = uapi_suspend_thread(send_taskcfg.task_handle); -// if(ret != ERRCODE_SUCC) -// PRINT("gnss_send_thread_suspend failed ret : %d \n",ret); -// else -// PRINT("gnss_send_thread_suspend succed\n"); - -// } \ No newline at end of file diff --git a/code/sdk/zhihui/utils/custom_utils.c b/code/sdk/zhihui/utils/custom_utils.c index ead43e5f0..fc5be2ded 100644 --- a/code/sdk/zhihui/utils/custom_utils.c +++ b/code/sdk/zhihui/utils/custom_utils.c @@ -1969,17 +1969,25 @@ int removeFilesInFolder(const char *folderPath) snprintf(filePath, sizeof(filePath), "%s/%s", folderPath, entry->d_name); stat(filePath,&s_buf); if(S_ISDIR(s_buf.st_mode)) - ret = removeFilesInFolder(filePath); + ret = removeFilesInFolder(filePath); // 递归删除子文件夹 else - ret = remove(filePath); + ret = remove(filePath); // 删除文件 if(ret != 0) PRINT("%s remove failed !!! \r\n",filePath); - // else - // // PRINT("%s remove succeed !!! \r\n",filePath); + else + PRINT("%s remove succeed !!! \r\n",filePath); } } closedir(dir); + + // 删除空文件夹本身 + ret = rmdir(folderPath); + if(ret != 0) + PRINT("%s folder remove failed !!! \r\n",folderPath); + else + PRINT("%s folder remove succeed !!! \r\n",folderPath); + return ret; } /*删除文件*/ @@ -1988,27 +1996,45 @@ int uapi_delete_files(const char *file_path) struct stat s_buf; int ret = 0; + if(file_path == NULL) + { + PRINT("file_path is NULL!!!\r\n"); + return 0; + } + if(access(file_path, F_OK) == -1) { PRINT("%s does not exist!!!\r\n", file_path); - return 0 ; + return 0; } - stat(file_path,&s_buf); + + if(stat(file_path,&s_buf) != 0) + { + PRINT("Failed to get stat for %s!!!\r\n", file_path); + return 0; + } + if(S_ISDIR(s_buf.st_mode)) + { + PRINT("Deleting directory: %s (including subdirectories)\r\n", file_path); ret = removeFilesInFolder(file_path); + } else + { + PRINT("Deleting file: %s\r\n", file_path); ret = remove(file_path); + } + if(ret != 0) { - // PRINT("%s remove failed !!! \r\n",file_path); + PRINT("%s remove failed !!! \r\n",file_path); return 0; } else { - // PRINT("%s remove succeed !!! \r\n",file_path); + PRINT("%s remove succeed !!! \r\n",file_path); return 1; } - } /*删除文件夹*/ -- 2.17.1