#include "service_gps.h" #include "ble_api.h" #include "fs_user_common.h" #include "gnss/gnss_datatypes.h" #include "gnss/pgnss_encode.h" #include "minmea.h" #include "pm_definition.h" #include "rtc_api.h" #include "securec.h" #include "sys_config.h" #include "sys_typedef.h" #include "task_service_timer.h" #include "time.h" #include "tiot_service_interface.h" #include #include #include #define LOG_LEVEL_UNKNOWN 0 /*!< Log level unknown. */ #define LOG_LEVEL_ERR 1 /*!< Log level error. */ #define LOG_LEVEL_WARNING 2 /*!< Log level warning. */ #define LOG_LEVEL_INFO 3 /*!< Log level info. */ #define LOG_LEVEL_DEBUG 4 /*!< Log level debug. */ #define LOG_LEVEL LOG_LEVEL_DEBUG #define PRINT_LOG(level, func, s, ...) \ do { \ if (LOG_LEVEL >= level) { \ func(s, ##__VA_ARGS__); \ } \ } while (0) #define static_print_info(s, ...) PRINT_LOG(LOG_LEVEL_INFO, sys_gps_log_i, s, ##__VA_ARGS__) #define static_print_debug(s, ...) PRINT_LOG(LOG_LEVEL_DEBUG, sys_gps_log_d, s, ##__VA_ARGS__) #define static_print_warn(s, ...) PRINT_LOG(LOG_LEVEL_WARNING, sys_gps_log_w, s, ##__VA_ARGS__) #define static_print_error(s, ...) PRINT_LOG(LOG_LEVEL_ERR, sys_gps_log_e, s, ##__VA_ARGS__) #define GPS_PATH TJD_FS_DIR_GPS "/" #define PGNSS_FIXMODEALL_NMEADEF_SAMPLE 0 #define PGNSS_LESS_FILES_FIXMODEALL_NMEADEF_SAMPLE 1 #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 #pragma region PGNSS_ENCODE #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 NON_GLO_GNSS_TYPES 4 #define GLO_EPH_NUM_ONE_FILE 8 #define OTHER_ASSIST_TYPES 7 #define INJECT_SLEEP_MS_TIME 100 #define PGNSS_FILE_MAX_SIZE 1024000 // 监听消息 static uint8_t g_ackBuff[REPORT_MAX_BYTES] = {0}; /* 计算命令内容校准和 */ 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; } 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) { static_print_error("memcpy XgnssData failed! Errno is %d", 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'; } i++; } if (i >= 1) { 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) { static_print_error("malloc failed in EncodeAndInjectCmd"); 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) { static_print_error("Encode Cmd failed: %d", 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) { static_print_error("Inject Cmd failed: %d", cmdType); free(buff); return 0; } ListenAck(handle); static_print_debug("Inject Cmd SUCCESS: %x", cmdType); free(buff); return 1; } int32_t FormatFileName(char *fileName, char *dName) { int32_t ret = snprintf_s(fileName, FILE_PATH_LEN, (FILE_PATH_LEN - 1), "%s%s", GPS_PATH "", dName); if (ret <= 0) { return 0; } return 1; } // 以下为使用PGNSS解析数据合并输出接口生成的星历文件进行注入的代码 int32_t GetNonGloEphFileName(int32_t ts, char *fileName) { const char prefix[] = "NonGlo"; DIR *dir = opendir(GPS_PATH ""); if (dir == NULL) { static_print_debug("Failed to open /user/tjd_gps directory."); 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; } } } } } if (closestTime != 0) { ret = snprintf_s(fileName, FILE_PATH_LEN, (FILE_PATH_LEN - 1), "%s%d%s", GPS_PATH "NonGlo_", closestTime, ".eph"); closedir(dir); return ((ret <= 0) ? 0 : 1); } closedir(dir); return 0; } int32_t GetGloEphFileName(int32_t ts, char *fileName) { const char prefix[] = "GLO"; DIR *dir = opendir(GPS_PATH ""); if (dir == NULL) { static_print_debug("Failed to open /user/tjd_gps directory."); 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); // 当前时间大于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); closedir(dir); return ret; } } } } } closedir(dir); return 0; } void PgnssSendNonGloEph(tiot_handle handle, const char *fileName) { FILE *fp = fopen(fileName, "rb"); if (fp == NULL) { static_print_error("open file failed: %s", 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); static_print_error("get file len failed: %s", fileName); return; } uint8_t *buff = (uint8_t *)malloc(len); if (buff == NULL) { fclose(fp); static_print_error("malloc file len failed: %s", fileName); return; } int32_t dataSize = fread(buff, len, 1, fp); if (dataSize < 0) { fclose(fp); static_print_error("read file failed: %s", 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) { static_print_error("open file failed: %s", 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); static_print_error("get file len failed: %s", fileName); return; } uint8_t *buff = (uint8_t *)malloc(len); if (buff == NULL) { fclose(fp); static_print_error("malloc file len failed: %s", fileName); return; } int32_t dataSize = fread(buff, len, 1, fp); if (dataSize < 0) { fclose(fp); static_print_error("read file failed: %s", 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); 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) { static_print_error("GetNonGloEphFileName failed"); return; } PgnssSendNonGloEph(handle, fileName); if (GetGloEphFileName(ts, fileName) == 0) { static_print_error("GetGloEphFileName failed"); return; } PgnssSendGloEph(handle, fileName, ts); } void PgnssSendOtherAssistInfo(tiot_handle handle, const char *fileName) { FILE *fp = fopen(fileName, "rb"); if (fp == NULL) { static_print_error("open file failed: %s", 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); static_print_error("get file len failed: %s", fileName); return; } uint8_t *buff = (uint8_t *)malloc(len); if (buff == NULL) { fclose(fp); static_print_error("malloc file len failed: %s", fileName); return; } int32_t dataSize = fread(buff, len, 1, fp); if (dataSize < 0) { fclose(fp); static_print_error("read file failed: %s", 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); } #pragma endregion #pragma region GNSS_CALLBACK static gnss_service_cb_t g_gnssServiceCb; static gnss_data_t g_rmcData; static struct minmea_sentence_gga g_gga; static void gnss_service_status_changed_callback(bool open) { if (g_gnssServiceCb.service_changed_cb != NULL) { g_gnssServiceCb.service_changed_cb(open); } } static void rmc_changed_callback(const struct minmea_sentence_rmc *frame) { if (g_gnssServiceCb.rmc_status_cb != NULL) { gnss_rmc_data_t rmc_data = { .latitude = minmea_tocoord(&frame->latitude), .longitude = minmea_tocoord(&frame->longitude), .speed = minmea_tofloat(&frame->speed), .course = minmea_tofloat(&frame->course), .valid = frame->valid, }; g_gnssServiceCb.rmc_status_cb(&rmc_data); } } static void gsv_changed_callback(const struct minmea_sentence_gsv *frame) { if (g_gnssServiceCb.gsv_status_cb != NULL) { g_gnssServiceCb.gsv_status_cb(frame); } } static void zda_changed_callback(const struct minmea_sentence_zda *frame) { char time[48] = {0}; snprintf_s(time, sizeof(time), sizeof(time) - 1, "%d:%d:%d %02d.%02d.%d UTC%+03d:%02d", frame->time.hours, frame->time.minutes, frame->time.seconds, frame->date.day, frame->date.month, frame->date.year, frame->hour_offset, frame->minute_offset); if (g_gnssServiceCb.zda_status_cb != NULL) { g_gnssServiceCb.zda_status_cb(time); } } static void gga_changed_callback(const struct minmea_sentence_gga *frame) { if (g_gnssServiceCb.gga_status_cb != NULL) { g_gnssServiceCb.gga_status_cb(frame); } } static void vtg_changed_callback(const struct minmea_sentence_vtg *frame) { if (g_gnssServiceCb.vtg_status_cb != NULL) { gnss_vtg_data_t vtg_data = { .true_track_degrees = minmea_tofloat(&frame->true_track_degrees), .magnetic_track_degrees = minmea_tofloat(&frame->magnetic_track_degrees), .speed_knots = minmea_tofloat(&frame->speed_knots), .speed_kph = minmea_tofloat(&frame->speed_kph), }; g_gnssServiceCb.vtg_status_cb(&vtg_data); } } void register_gnss_changed_cb(gnss_service_cb_t *gnss_service_func) { memcpy_s(&g_gnssServiceCb, sizeof(gnss_service_cb_t), gnss_service_func, sizeof(gnss_service_cb_t)); } void unregister_gnss_changed_cb(void) { memset_s(&g_gnssServiceCb, sizeof(gnss_service_cb_t), 0, sizeof(gnss_service_cb_t)); } #pragma endregion void PgnssInjectOtherAssistLessFiles(tiot_handle handle) { PgnssSendOtherAssistInfo(handle, GPS_PATH "AssistInfo.dat"); } static FILE *g_gnssLogFp = NULL; static uint8_t *g_gnssServiceBuff = NULL; static tiot_handle g_handle; typedef int32_t (*GnssCfgFunc)(tiot_handle handle); typedef struct { uint16_t sampleId; GnssCfgFunc cfgHandle; } GnssSamplesCfgTable; 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) { static_print_error("QryVersion error: %d", ret); return 0; } return 1; } // 注入PGNSS,使用默认配置启动 int32_t InjectPgnssLessFilesCfgAutoStartFixModeAndNmeaDefault(tiot_handle handle) { const uint8_t cfgFixModeAllCmd[] = {0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00}; const uint8_t cfgLogLevelInfo[] = {0x03, 0x00, 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x10, 0x01, 0x00, 0x03}; const uint8_t cfgNmeaCmd[] = {0x03, 0x00, 0x04, 0x01, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x02, 0x00, 0xff, 0x00}; // 配置log级别:info级别。 int32_t ret = tiot_service_write(handle, cfgLogLevelInfo, sizeof(cfgLogLevelInfo)); if (ret < 0) { static_print_error("cfgLogLevelInfo error: %d", ret); return 0; } // 配置使能的GNSS星座:QZSS/GAL/BDS/GLO/GPS。 ret = tiot_service_write(handle, cfgFixModeAllCmd, sizeof(cfgFixModeAllCmd)); if (ret < 0) { static_print_error("error: cfgFixModeAllCmd error: %d", ret); return 0; } // 配置上报NMEA类型:PNT/ZDA/VTG/RMC/GSV/GSA/GLL/GGA。 ret = tiot_service_write(handle, cfgNmeaCmd, sizeof(cfgNmeaCmd)); if (ret < 0) { static_print_error("error: cfgNmeaCmd error: %d", ret); return 0; } // 注入UTC时间, 注入Pgnss辅助数据前必须先注入参考时间 struct rtc_time time; tjd_driver_rtc_get_ops()->get_rtc_utc_time(&time); // 需要用当前的UTC时间替换 GnssUtcTime utcTime = {time.tm_year, time.tm_mon, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec, 0, 1}; uint32_t ts = 0; ret = PgnssInjectUtcTime(handle, &utcTime, &ts); if (ret == 0) { static_print_error("PgnssInjectUtcTime failed!"); return 0; } static_print_debug("PgnssInjectUtcTime success! ts = %u", ts); // PGNSS注入 // 注意,默认PGNSS星历文件存放在/user/tjd_gps/目录中,如修改目录,请全局搜索替换 PgnssInjectLessFiles(handle, ts); return 1; } 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) { static_print_error("start gnss error: %d", ret); return 0; } static_print_debug("start gnss"); 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) { static_print_error("stop gnss error: %d", ret); return 0; } static_print_debug("stop gnss"); return 1; } static void gnss_data_process(char *line, uint32_t len) { switch (minmea_sentence_id(line, false)) { case MINMEA_SENTENCE_RMC: { struct minmea_sentence_rmc frame; if (minmea_parse_rmc(&frame, line)) { g_rmcData.latitude = minmea_tocoord(&frame.latitude); g_rmcData.longitude = minmea_tocoord(&frame.longitude); g_rmcData.valid = frame.valid; rmc_changed_callback(&frame); } } case MINMEA_SENTENCE_GGA: { struct minmea_sentence_gga frame; if (minmea_parse_gga(&frame, line)) { memcpy_s(&g_gga, sizeof(struct minmea_sentence_gga), &frame, sizeof(struct minmea_sentence_gga)); g_rmcData.num_sats = frame.satellites_tracked; gga_changed_callback(&frame); static_print_debug("$xxGGA: fix quality: %d, satellites_tracked: %d", frame.fix_quality, frame.satellites_tracked); } } break; case MINMEA_SENTENCE_GSV: { struct minmea_sentence_gsv frame; if (minmea_parse_gsv(&frame, line)) { // frame.gnss_type; gsv_changed_callback(&frame); static_print_debug("$xxGSV: message %d of %d", frame.msg_nr, frame.total_msgs); static_print_debug("$xxGSV: satellites in view: %d", frame.total_sats); for (int i = 0; i < 4; i++) { static_print_debug("$xxGSV: sat nr %d, elevation: %d, azimuth: %d, snr: %d dbm", frame.sats[i].nr, frame.sats[i].elevation, frame.sats[i].azimuth, frame.sats[i].snr); } } } break; case MINMEA_SENTENCE_VTG: { struct minmea_sentence_vtg frame; if (minmea_parse_vtg(&frame, line)) { vtg_changed_callback(&frame); static_print_debug("$xxVTG: true track degrees = %f", minmea_tofloat(&frame.true_track_degrees)); static_print_debug(" magnetic track degrees = %f", minmea_tofloat(&frame.magnetic_track_degrees)); static_print_debug(" speed knots = %f", minmea_tofloat(&frame.speed_knots)); static_print_debug(" speed kph = %f", minmea_tofloat(&frame.speed_kph)); } } break; case MINMEA_SENTENCE_ZDA: { struct minmea_sentence_zda frame; if (minmea_parse_zda(&frame, line)) { zda_changed_callback(&frame); static_print_debug("$xxZDA: %d:%d:%d %02d.%02d.%d UTC%+03d:%02d", frame.time.hours, frame.time.minutes, frame.time.seconds, frame.date.day, frame.date.month, frame.date.year, frame.hour_offset, frame.minute_offset); } } break; default: { } break; }; } static bool g_gps_service_is_open = false; void gps_service_task(void *argument) { g_handle = tiot_service_open("gn71", NULL); if (g_handle == 0) { static_print_debug("open tiot service fail"); return; } /* 注入离线星历,采用合并的方式注入 */ InjectPgnssLessFilesCfgAutoStartFixModeAndNmeaDefault(g_handle); QryVersion(g_handle); if (StartGnss(g_handle) == 0) { static_print_debug("start gnss fail"); return; } gnss_service_status_changed_callback(true); g_gps_service_is_open = true; if (g_gnssServiceBuff == NULL) { g_gnssServiceBuff = (uint8_t *)malloc(REPORT_MAX_BYTES); if (g_gnssServiceBuff == NULL) { static_print_error("malloc failed in gps_service_task"); return; } } for (;;) { // 监听 int32_t ret = tiot_service_read(g_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'; gnss_data_process((char *)&g_gnssServiceBuff[MSG_CONTENT_IDX], ret - MSG_CONTENT_IDX); static_print_debug("%s", (char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]); fprintf(g_gnssLogFp, "%s\n", (char *)&g_gnssServiceBuff[MSG_CONTENT_IDX]); } } } } static osThreadId_t g_gps_task_id = NULL; static void tjd_service_charger_start_send(void) { if (g_gps_task_id != NULL) { static_print_debug("gps service task is already running"); return; } osThreadAttr_t task_attr = {"tjd_gps_task", 0, NULL, 0, NULL, 0x1200, 17, 0, 0}; task_attr.stack_mem = memalign(16, task_attr.stack_size); // add g_gps_task_id = osThreadNew(gps_service_task, NULL, &task_attr); if (g_gps_task_id == NULL) { static_print_error("create gps service task failed"); return; } // queue_default_info_t msg_data = {tjd_service_charger_handle, NULL, 100, NULL}; // osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data, sizeof(queue_default_info_t), // 0); } static void tjd_service_charger_end_send(void) { if (g_gps_task_id != NULL) { osThreadTerminate(g_gps_task_id); g_gps_task_id = NULL; } // queue_default_info_t msg_data = {tjd_service_charger_handle, NULL, 0, NULL}; // osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data, sizeof(queue_default_info_t), // 0); } bool tjd_service_gps_ephemer_is_valid(void) { uint64_t ts = 0; tjd_driver_rtc_get_ops()->get_timestamp(&ts); char fileName[FILE_PATH_LEN] = {0}; static_print_debug("ts = %llu", ts); if (GetNonGloEphFileName(ts, fileName) == 0) { static_print_error("GetNonGloEphFileName failed"); return false; } if (GetGloEphFileName(ts, fileName) == 0) { static_print_error("GetGloEphFileName failed"); return false; } return true; } uint32_t tjd_service_gps_open(void) { if (g_gps_service_is_open) { static_print_debug("gnss samples is already open"); return 0; } uapi_pm_add_sleep_veto(PM_ID_SYS); static_print_debug("enter gnss samples"); g_gnssLogFp = fopen("/user/gnss.log", "w"); if (g_gnssLogFp == NULL) { static_print_error("open log file error"); return 1; } tjd_service_charger_start_send(); static_print_info("open tiot service success"); return 0; } void tjd_service_gps_close(void) { if (!g_gps_service_is_open) { static_print_debug("gnss samples is already close"); return; } tjd_service_charger_end_send(); StopGnss(g_handle); tiot_service_close(g_handle); fclose(g_gnssLogFp); g_gnssLogFp = NULL; uapi_pm_remove_sleep_veto(PM_ID_SYS); static_print_info("finish gnss samples"); gnss_service_status_changed_callback(false); if (g_gnssServiceBuff) { free(g_gnssServiceBuff); g_gnssServiceBuff = NULL; } g_gps_service_is_open = false; } static struct timespec last_time = {0}; void tjd_service_gps_sync_ephemeris_event(void) { if (!tjd_service_gps_ephemer_is_valid()) { static_print_debug("gps ephemer is not valid"); tjd_ble_request_gps(); return; } struct timespec time = {0}; clock_gettime(CLOCK_MONOTONIC, &time); if (last_time.tv_sec != 0 && (time.tv_sec - last_time.tv_sec) < 60 * 60 * 2) { static_print_debug("tjd_service_gps_sync_ephemeris_event too fast"); return; } static_print_debug("tjd_service_gps_sync_ephemeris_event"); last_time = time; tjd_ble_request_gps(); } #define GPS_SYNC_EPH_TIME (8 * 60 * 60 * 1000) #define GPS_SYNC_EPH_ERR_TIME (10 * 60 * 1000) static signed int tjd_service_gps_sync_handle(void *param) { static_print_debug("tjd_service_gps_sync_handle"); if (tjd_get_ble_is_connect()) { tjd_service_gps_sync_ephemeris_event(); } else { return GPS_SYNC_EPH_ERR_TIME; } return GPS_SYNC_EPH_TIME; } void tjd_service_gps_sync_open() { queue_default_info_t msg_data = {tjd_service_gps_sync_handle, NULL, GPS_SYNC_EPH_TIME, NULL}; osal_msg_queue_write_copy(tjd_task_service_timer_get_queue_id(), (void *)&msg_data, sizeof(msg_data), 0); } void tjd_service_gps_get_data(gnss_data_t *rmc_data) { if (rmc_data == NULL) { return; } memcpy_s(rmc_data, sizeof(gnss_data_t), &g_rmcData, sizeof(gnss_data_t)); } void tjd_service_gps_get_gga_data(struct minmea_sentence_gga *gga_data) { if (gga_data == NULL) { return; } memcpy_s(gga_data, sizeof(struct minmea_sentence_gga), &g_gga, sizeof(struct minmea_sentence_gga)); }