--- /dev/null
+/*\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.\r
+ * Description: pgnss encode\r
+ * Author:\r
+ * Create:\r
+ */\r
+#include "pgnss_encode.h"\r
+#include <stdio.h>\r
+#include <dirent.h>\r
+#include <string.h>\r
+#include "securec.h"\r
+#include "tiot_service_interface.h"\r
+#include "gnss_datatypes.h"\r
+#include "cywee_hal.h"\r
+\r
+#define GNSS_ENCODE_BUFF_MAX_LEN 9300\r
+#define FILE_PATH_LEN 1024\r
+#define GLO_EPH_VALID_TIME 900\r
+#define OTHER_EPH_VALID_TIME 7200\r
+#define ONE_CENTURY_YEARS 100\r
+#define FOUR_CENTURY_YEARS 400\r
+#define LEAP_YEAR_LENGTH 4\r
+#define UNIX_TIME_START_YEAR 1970 // start year of unix time\r
+#define TIME_UNIT 1000\r
+#define SECONDS_PER_MIN (60)\r
+#define SECONDS_PER_HOUR (60 * SECONDS_PER_MIN)\r
+#define SECONDS_PER_DAY (24 * SECONDS_PER_HOUR)\r
+#define SECONDS_PER_NORMAL_YEAR (365 * SECONDS_PER_DAY)\r
+#define NON_GLO_GNSS_TYPES 4\r
+#define GLO_EPH_NUM_ONE_FILE 8\r
+#define OTHER_ASSIST_TYPES 7\r
+#define INJECT_SLEEP_MS_TIME 500\r
+#define PGNSS_FILE_MAX_SIZE 1024000\r
+\r
+/** days per month on normal and leap year */\r
+int32_t g_normMonthDays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r
+int32_t g_leapMonthDays[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };\r
+// 监听消息\r
+static uint8_t g_ackBuff[REPORT_MAX_BYTES] = { 0 };\r
+\r
+/* 获取begin和end年份之间的闰年数 */\r
+int32_t GetLeapYearNum(uint16_t begin, uint16_t end)\r
+{\r
+ if (end <= begin || end < 1) {\r
+ return 0;\r
+ }\r
+ int32_t numPer400Year = (end - 1) / FOUR_CENTURY_YEARS - begin / FOUR_CENTURY_YEARS;\r
+ int32_t numPer100Year = (end - 1) / ONE_CENTURY_YEARS - begin / ONE_CENTURY_YEARS;\r
+ int32_t numPer4Year = (end - 1) / LEAP_YEAR_LENGTH - begin / LEAP_YEAR_LENGTH;\r
+ return (numPer400Year + numPer4Year - numPer100Year);\r
+}\r
+\r
+/* 闰年判断 */\r
+int32_t CheckIfLeapYear(uint16_t year)\r
+{\r
+ if ((year % ONE_CENTURY_YEARS) == 0) {\r
+ if ((year % FOUR_CENTURY_YEARS) == 0) {\r
+ return 1;\r
+ }\r
+ } else {\r
+ if ((year % LEAP_YEAR_LENGTH) == 0) {\r
+ return 1;\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+/* 将日历时(年月日时分秒) 转换为 unix时间(1970年1月1日起的时间秒数) */\r
+int32_t Utc2UnixTime(GnssUtcTime utcTime, uint32_t *unixTime)\r
+{\r
+ if (unixTime == NULL) {\r
+ CWM_OS_dbgPrintf("\nerror: [Utc2UnixTime] null pointer!\n");\r
+ return 0;\r
+ }\r
+\r
+ if (utcTime.month > 12 || utcTime.valid == 0) {\r
+ CWM_OS_dbgPrintf("\nerror: [Utc2UnixTime] utcTime invalid!\n");\r
+ return 0;\r
+ }\r
+\r
+ // 判断是否为闰年\r
+ int32_t *monthDays = (CheckIfLeapYear(utcTime.year) == 1) ? g_leapMonthDays : g_normMonthDays;\r
+\r
+ // 计算从1970.01.01开始的unix 秒数\r
+ uint32_t timestamp = 0;\r
+ timestamp += (uint32_t)(utcTime.year - UNIX_TIME_START_YEAR) * SECONDS_PER_NORMAL_YEAR;\r
+ timestamp += (uint32_t)GetLeapYearNum(UNIX_TIME_START_YEAR, utcTime.year) * SECONDS_PER_DAY;\r
+\r
+ for (int32_t i = 1; i < utcTime.month; i++) {\r
+ timestamp += (uint32_t)monthDays[i - 1] * SECONDS_PER_DAY;\r
+ }\r
+\r
+ timestamp += (uint32_t)(utcTime.day - 1) * SECONDS_PER_DAY;\r
+ timestamp += (uint32_t)utcTime.hour * SECONDS_PER_HOUR;\r
+ timestamp += (uint32_t)utcTime.minute * SECONDS_PER_MIN;\r
+ uint32_t timestampSec = (uint32_t)(utcTime.second + utcTime.ms / TIME_UNIT);\r
+\r
+ *unixTime = timestamp + timestampSec;\r
+ return 1;\r
+}\r
+\r
+/* 计算命令内容校准和 */\r
+static uint16_t CalcChecksum(uint8_t *buff, uint16_t len)\r
+{\r
+ uint16_t checksum = 0;\r
+ uint16_t i = 0;\r
+ while (i++ < len) {\r
+ checksum += *buff;\r
+ buff++;\r
+ }\r
+ return checksum;\r
+}\r
+\r
+int32_t PgnssInjectUtcTime(tiot_handle handle, GnssUtcTime *utcTime, uint32_t* ts)\r
+{\r
+ uint8_t *buff = (uint8_t *)malloc(GNSS_ENCODE_BUFF_MAX_LEN);\r
+ if (buff == NULL) {\r
+ CWM_OS_dbgPrintf("\nerror: malloc failed in PgnssINjectUtcTime\r\n");\r
+ return 0;\r
+ }\r
+ memset_s(buff, GNSS_ENCODE_BUFF_MAX_LEN, 0, GNSS_ENCODE_BUFF_MAX_LEN);\r
+\r
+ GnssMsg *hdr = (GnssMsg *)buff;\r
+ hdr->cmd = 0x0404;\r
+ hdr->sequence = 0;\r
+ errno_t copyRet = memcpy_s(hdr->data, (GNSS_ENCODE_BUFF_MAX_LEN - sizeof(GnssMsg)), utcTime, sizeof(GnssUtcTime));\r
+ if (copyRet != EOK) {\r
+ CWM_OS_dbgPrintf("\nmemcpy UtcTime failed! Errno is %d\r\n", copyRet);\r
+ free(buff);\r
+ return 0;\r
+ }\r
+ hdr->dataLength = sizeof(GnssUtcTime);\r
+ hdr->checkSum = CalcChecksum(hdr->data, hdr->dataLength);\r
+ int32_t ret = tiot_service_write(handle, buff, (sizeof(GnssMsg) + hdr->dataLength));\r
+ if (ret < 0) {\r
+ CWM_OS_dbgPrintf("\nerror: PgnssInjectUtcTime error: %d\r\n", ret);\r
+ free(buff);\r
+ return 0;\r
+ }\r
+ if (Utc2UnixTime((*utcTime), ts) == 0) {\r
+ CWM_OS_dbgPrintf("\nerror: Utc2UnixTime error\r\n");\r
+ free(buff);\r
+ return 0;\r
+ }\r
+\r
+ free(buff);\r
+ return 1;\r
+}\r
+\r
+static uint16_t FillGnssMessageData(uint8_t *inBuff, uint32_t inLen, uint8_t *outBuff, uint32_t outLen)\r
+{\r
+ errno_t ret = memcpy_s(outBuff, outLen, inBuff, inLen);\r
+ if (ret != EOK) {\r
+ CWM_OS_dbgPrintf("memcpy XgnssData failed! Errno is %d \r\n", ret);\r
+ return 0;\r
+ }\r
+\r
+ return inLen;\r
+}\r
+\r
+static int32_t EncodeGnssMsg(uint8_t *inBuff, uint32_t inLen, uint8_t *outBuff, uint32_t outLen)\r
+{\r
+ uint16_t len = FillGnssMessageData(inBuff, inLen, outBuff, outLen);\r
+ if (len > 0) {\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static void ListenAck(tiot_handle handle)\r
+{\r
+ int32_t i = 0;\r
+ for (;;) {\r
+ // 监听\r
+ int32_t ret = tiot_service_read(handle, g_ackBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR);\r
+ if (ret > 0) {\r
+ uint16_t *type = (uint16_t *)g_ackBuff;\r
+ // 二进制消息类型\r
+ if (type[0] == 0) {\r
+ g_ackBuff[ret] = '\0';\r
+ CWM_OS_dbgPrintf("%s\r\n", (char *)&g_ackBuff[MSG_CONTENT_IDX]);\r
+ }\r
+ i++;\r
+ }\r
+ if (i >= 1) {\r
+ CWM_OS_dbgPrintf("\r\ncnt enough\r\n");\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+static int32_t EncodeAndInjectCmd(tiot_handle handle, GnssCmdType cmdType, uint8_t* inBuff, uint32_t inLen)\r
+{\r
+ // 获取GNSS业务消息头\r
+ int32_t len = 0;\r
+ uint8_t *buff = (uint8_t *)malloc(GNSS_ENCODE_BUFF_MAX_LEN);\r
+ if (buff == NULL) {\r
+ CWM_OS_dbgPrintf("\r\nerror: malloc failed in EncodeAndInjectCmd\r\n");\r
+ return 0;\r
+ }\r
+ memset_s(buff, GNSS_ENCODE_BUFF_MAX_LEN, 0, GNSS_ENCODE_BUFF_MAX_LEN);\r
+\r
+ GnssMsg *gnssHdr = (GnssMsg *)buff;\r
+ len += sizeof(GnssMsg);\r
+\r
+ gnssHdr->sequence = 0;\r
+\r
+ int32_t retLen = EncodeGnssMsg(inBuff, inLen, buff + len, (GNSS_ENCODE_BUFF_MAX_LEN - len));\r
+ if (retLen != 1) {\r
+ CWM_OS_dbgPrintf("\nerror: Encode Cmd failed: %d\r\n", cmdType);\r
+ free(buff);\r
+ return retLen;\r
+ }\r
+ gnssHdr->cmd = cmdType;\r
+ gnssHdr->dataLength = inLen;\r
+ gnssHdr->checkSum = CalcChecksum(gnssHdr->data, gnssHdr->dataLength);\r
+ int32_t ret = tiot_service_write(handle, buff, (sizeof(GnssMsg) + gnssHdr->dataLength));\r
+ if (ret < 0) {\r
+ CWM_OS_dbgPrintf("\r\nerror: Inject Cmd failed: %d\r\n", cmdType);\r
+ free(buff);\r
+ return 0;\r
+ }\r
+ ListenAck(handle);\r
+ CWM_OS_dbgPrintf("\r\nInject Cmd SUCCESS: %x\r\n", cmdType);\r
+ free(buff);\r
+ return 1;\r
+}\r
+\r
+void PgnssSendFileContent(tiot_handle handle, const char *fileName, GnssCmdType cmdType)\r
+{\r
+ FILE *fp = fopen(fileName, "rb");\r
+ if (fp == NULL) {\r
+ CWM_OS_dbgPrintf("\r\nerror: open file failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ fseek(fp, 0, SEEK_END);\r
+ int32_t len = ftell(fp);\r
+ fseek(fp, 0, SEEK_SET);\r
+ if (len < 0 || len > PGNSS_FILE_MAX_SIZE) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\r\nerror: get file len failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ uint8_t *buff = (uint8_t *)malloc(len);\r
+ if (buff == NULL) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\r\nerror: malloc file len failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ int32_t dataSize = fread(buff, len, 1, fp);\r
+ if (dataSize < 0) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\r\nerror: read file failed: %s\r\n", fileName);\r
+ free(buff);\r
+ return;\r
+ }\r
+ fclose(fp);\r
+ EncodeAndInjectCmd(handle, cmdType, buff, len);\r
+ free(buff);\r
+}\r
+\r
+int32_t FormatFileName(char *fileName, char *dName)\r
+{\r
+ int32_t ret = snprintf_s(fileName, FILE_PATH_LEN, (FILE_PATH_LEN - 1), "%s%s", "/user/userdata/gnss/", dName);\r
+ if (ret <= 0) {\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+int32_t GetEphFileName(int32_t ts, const char *prefix, char *fileName)\r
+{\r
+ int32_t interval = (strcmp(prefix, "GLO") == 0) ? GLO_EPH_VALID_TIME : OTHER_EPH_VALID_TIME;\r
+ DIR *dir = opendir("/user/userdata/gnss/");\r
+ if (dir == NULL) {\r
+ CWM_OS_dbgPrintf("Failed to open /user/xgnss directory.\r\n");\r
+ return 0;\r
+ }\r
+ int32_t time, ret;\r
+ struct dirent *entry;\r
+ for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) {\r
+ // 检查文件名\r
+ if (strstr(entry->d_name, ".eph") != NULL) {\r
+ char *p = strrchr(entry->d_name, '_');\r
+ if (p != NULL) {\r
+ char *q = strstr(entry->d_name, prefix);\r
+ if (q != NULL) {\r
+ time = atoi(p + 1);\r
+ if (abs(time - ts) <= interval) {\r
+ ret = FormatFileName(fileName, entry->d_name);\r
+ closedir(dir);\r
+ return ret;\r
+ }\r
+ else\r
+ {\r
+ CWM_OS_dbgPrintf("time:%d,ts:%d,interval:%d\r\n",time,ts,interval);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ closedir(dir);\r
+ CWM_OS_dbgPrintf("closedir(dir);\r\n");\r
+ return 0;\r
+}\r
+\r
+void PgnssSendEphFile(tiot_handle handle, const char *prefix, GnssCmdType cmdType, uint32_t ts)\r
+{\r
+ char fileName[FILE_PATH_LEN] = {0};\r
+ int32_t ret = GetEphFileName(ts, prefix, fileName);\r
+ if (ret == 0) {\r
+ CWM_OS_dbgPrintf("\r\nerror: GetEphFileName failed\r\n");\r
+ return;\r
+ }\r
+ CWM_OS_dbgPrintf("\nGetEphFileName success\r\n");\r
+ PgnssSendFileContent(handle, fileName, cmdType);\r
+}\r
+\r
+void PgnssInjectAllEph(tiot_handle handle, uint32_t ts)\r
+{\r
+ PgnssSendEphFile(handle, "GPS", CMD_PGNSS_INJECT_EPH_GPS, ts);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send GPS eph success\r\n");\r
+ PgnssSendEphFile(handle, "GLO", CMD_PGNSS_INJECT_EPH_GANSS, ts);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send GLO eph success\r\n");\r
+ PgnssSendEphFile(handle, "BDS", CMD_PGNSS_INJECT_EPH_GANSS, ts);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send BDS eph success\r\n");\r
+ PgnssSendEphFile(handle, "GAL", CMD_PGNSS_INJECT_EPH_GANSS, ts);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send GAL eph success\r\n");\r
+ PgnssSendEphFile(handle, "QZS", CMD_PGNSS_INJECT_EPH_GANSS, ts);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send QZS eph success\r\n");\r
+}\r
+\r
+void PgnssInjectOtherAssist(tiot_handle handle)\r
+{\r
+ PgnssSendFileContent(handle, "/user/userdata/gnss/GPS_UTC.dat", CMD_PGNSS_INJECT_UTC_GPS);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send GPS_UTC success\r\n");\r
+ PgnssSendFileContent(handle, "/user/userdata/gnss/GPS_RTI.dat", CMD_PGNSS_INJECT_RTI_GPS);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send GPS_RTI success\r\n");\r
+ PgnssSendFileContent(handle, "/user/userdata/gnss/GPS_ION.dat", CMD_PGNSS_INJECT_ION_GPS);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send GPS_ION success\r\n");\r
+ PgnssSendFileContent(handle, "/user/userdata/gnss/GLO_RTI.dat", CMD_PGNSS_INJECT_RTI_GANSS);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send GLO_RTI success\r\n");\r
+ PgnssSendFileContent(handle, "/user/userdata/gnss/GLO_AUX.dat", CMD_PGNSS_INJECT_AUX_GANSS);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send GLO_AUX success\r\n");\r
+ PgnssSendFileContent(handle, "/user/userdata/gnss/BDS_RTI.dat", CMD_PGNSS_INJECT_RTI_GANSS);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send BDS_RTI success\r\n");\r
+ PgnssSendFileContent(handle, "/user/userdata/gnss/GAL_RTI.dat", CMD_PGNSS_INJECT_RTI_GANSS);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ CWM_OS_dbgPrintf("send GAL_RTI success\r\n");\r
+}\r
+\r
+void PgnssInject(tiot_handle handle, uint32_t ts)\r
+{\r
+ // 注入Pgnss辅助数据\r
+ PgnssInjectAllEph(handle, ts);\r
+ PgnssInjectOtherAssist(handle);\r
+}\r
+\r
+\r
+// 以下为使用PGNSS解析数据合并输出接口生成的星历文件进行注入的代码\r
+int32_t GetNonGloEphFileName(int32_t ts, char *fileName)\r
+{\r
+ const char prefix[] = "NonGlo";\r
+ DIR *dir = opendir("/user/userdata/gnss/");\r
+ if (dir == NULL) {\r
+ CWM_OS_dbgPrintf("Failed to open /user/xgnss directory.\r\n");\r
+ return 0;\r
+ }\r
+ int32_t time, ret;\r
+ int32_t minDist = OTHER_EPH_VALID_TIME;\r
+ int32_t closestTime = 0;\r
+ struct dirent *entry;\r
+ for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) {\r
+ // 检查文件名\r
+ if (strstr(entry->d_name, ".eph") != NULL) {\r
+ char *p = strrchr(entry->d_name, '_');\r
+ if (p != NULL) {\r
+ char *q = strstr(entry->d_name, prefix);\r
+ if (q != NULL) {\r
+ time = atoi(p + 1);\r
+ // 查找星历文件时间戳与当前时间相差2小时以内且距离最近的\r
+ if (abs(time - ts) < minDist) {\r
+ minDist = abs(time - ts);\r
+ closestTime = time;\r
+ }\r
+ else\r
+ {\r
+ CWM_OS_dbgPrintf("time:%d,ts:%d,minDist:%d\r\n",time,ts,minDist);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (closestTime != 0) {\r
+ ret = snprintf_s(fileName, FILE_PATH_LEN, (FILE_PATH_LEN - 1), "%s%d%s", "/user/userdata/gnss/NonGlo_", closestTime,\r
+ ".eph");\r
+ CWM_OS_dbgPrintf("closest eph fileName:%s\r\n", fileName);\r
+ closedir(dir);\r
+ return ((ret <= 0) ? 0 : 1);\r
+ }\r
+ else\r
+ {\r
+ CWM_OS_dbgPrintf("closestTime == 0\r\n");\r
+ }\r
+ closedir(dir);\r
+ return 0;\r
+}\r
+\r
+int32_t GetGloEphFileName(int32_t ts, char *fileName)\r
+{\r
+ const char prefix[] = "GLO";\r
+ DIR *dir = opendir("/user/userdata/gnss/");\r
+ if (dir == NULL) {\r
+ CWM_OS_dbgPrintf("Failed to open /user/xgnss directory.\r\n");\r
+ return 0;\r
+ }\r
+ int32_t ephTime, ret;\r
+ struct dirent *entry;\r
+ for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) {\r
+ // 检查文件名\r
+ if (strstr(entry->d_name, ".eph") != NULL) {\r
+ char *p = strrchr(entry->d_name, '_');\r
+ if (p != NULL) {\r
+ char *q = strstr(entry->d_name, prefix);\r
+ if (q != NULL) {\r
+ ephTime = atoi(p + 1);\r
+ CWM_OS_dbgPrintf("ephTime:%ld, ts:%ld\n", ephTime, ts);\r
+ // 当前时间大于GLO星历文件时间戳,则需要选取相差2小时以内的星历\r
+ // 当前时间小于GLO星历文件时间戳,则需要选取相差小于15分钟的星历\r
+ if (((ts - ephTime) >= 0 && abs(ephTime - ts) < OTHER_EPH_VALID_TIME) ||\r
+ ((ts - ephTime) <= 0 && abs(ephTime - ts) < GLO_EPH_VALID_TIME)) {\r
+ ret = FormatFileName(fileName, entry->d_name);\r
+ CWM_OS_dbgPrintf("glo eph fileName:%s\n", fileName);\r
+ closedir(dir);\r
+ return ret;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ closedir(dir);\r
+ return 0;\r
+}\r
+\r
+void PgnssSendNonGloEph(tiot_handle handle, const char *fileName)\r
+{\r
+ FILE *fp = fopen(fileName, "rb");\r
+ if (fp == NULL) {\r
+ CWM_OS_dbgPrintf("\nerror: open file failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ fseek(fp, 0, SEEK_END);\r
+ int32_t len = ftell(fp);\r
+ fseek(fp, 0, SEEK_SET);\r
+ if (len < 0 || len > PGNSS_FILE_MAX_SIZE) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\nerror: get file len failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ uint8_t *buff = (uint8_t *)malloc(len);\r
+ if (buff == NULL) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\nerror: malloc file len failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ int32_t dataSize = fread(buff, len, 1, fp);\r
+ if (dataSize < 0) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\nerror: read file failed: %s\r\n", fileName);\r
+ free(buff);\r
+ return;\r
+ }\r
+ fclose(fp);\r
+ int32_t fileLen = 0;\r
+ for (int32_t i = 0; i < NON_GLO_GNSS_TYPES && fileLen <= len; i++) {\r
+ EphHeadInfo *ephHdr = (EphHeadInfo *)(buff + fileLen);\r
+ EncodeAndInjectCmd(handle, ephHdr->cmd, (buff + fileLen + sizeof(EphHeadInfo)), ephHdr->len);\r
+ fileLen += (ephHdr->len + sizeof(EphHeadInfo));\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ }\r
+ free(buff);\r
+}\r
+\r
+void PgnssSendGloEph(tiot_handle handle, const char *fileName, int32_t ts)\r
+{\r
+ FILE *fp = fopen(fileName, "rb");\r
+ if (fp == NULL) {\r
+ CWM_OS_dbgPrintf("\nerror: open file failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ fseek(fp, 0, SEEK_END);\r
+ int32_t len = ftell(fp);\r
+ fseek(fp, 0, SEEK_SET);\r
+ if (len < 0 || len > PGNSS_FILE_MAX_SIZE) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\nerror: get file len failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ uint8_t *buff = (uint8_t *)malloc(len);\r
+ if (buff == NULL) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\nerror: malloc file len failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ int32_t dataSize = fread(buff, len, 1, fp);\r
+ if (dataSize < 0) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\nerror: read file failed: %s\r\n", fileName);\r
+ free(buff);\r
+ return;\r
+ }\r
+ fclose(fp);\r
+ int32_t fileLen = 0;\r
+ for (int32_t i = 0; i < GLO_EPH_NUM_ONE_FILE && fileLen <= len; i++) {\r
+ EphHeadInfo *ephHdr = (EphHeadInfo *)(buff + fileLen);\r
+ CWM_OS_dbgPrintf("glo eph, time:%u, ts:%d\r\n", ephHdr->time, ts);\r
+ if (abs((int32_t)ephHdr->time - ts) < GLO_EPH_VALID_TIME) {\r
+ EncodeAndInjectCmd(handle, ephHdr->cmd, (buff + fileLen + sizeof(EphHeadInfo)), ephHdr->len);\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ break;\r
+ }\r
+ fileLen += (ephHdr->len + sizeof(EphHeadInfo));\r
+ }\r
+ free(buff);\r
+}\r
+\r
+void PgnssInjectAllEphLessFiles(tiot_handle handle, uint32_t ts)\r
+{\r
+ char fileName[FILE_PATH_LEN] = {0};\r
+ if (GetNonGloEphFileName(ts, fileName) == 0) {\r
+ CWM_OS_dbgPrintf("\nerror: GetNonGloEphFileName failed\r\n");\r
+ return;\r
+ }\r
+ PgnssSendNonGloEph(handle, fileName);\r
+ if (GetGloEphFileName(ts, fileName) == 0) {\r
+ CWM_OS_dbgPrintf("\nerror: GetGloEphFileName failed\r\n");\r
+ return;\r
+ }\r
+ PgnssSendGloEph(handle, fileName, ts);\r
+}\r
+\r
+void PgnssSendOtherAssistInfo(tiot_handle handle, const char *fileName)\r
+{\r
+ FILE *fp = fopen(fileName, "rb");\r
+ if (fp == NULL) {\r
+ CWM_OS_dbgPrintf("\nerror: open file failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ fseek(fp, 0, SEEK_END);\r
+ int32_t len = ftell(fp);\r
+ fseek(fp, 0, SEEK_SET);\r
+ if (len < 0 || len > PGNSS_FILE_MAX_SIZE) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\nerror: get file len failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ uint8_t *buff = (uint8_t *)malloc(len);\r
+ if (buff == NULL) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\nerror: malloc file len failed: %s\r\n", fileName);\r
+ return;\r
+ }\r
+ int32_t dataSize = fread(buff, len, 1, fp);\r
+ if (dataSize < 0) {\r
+ fclose(fp);\r
+ CWM_OS_dbgPrintf("\nerror: read file failed: %s\r\n", fileName);\r
+ free(buff);\r
+ return;\r
+ }\r
+ fclose(fp);\r
+ int32_t fileLen = 0;\r
+ for (int32_t i = 0; i < OTHER_ASSIST_TYPES && fileLen <= len; i++) {\r
+ OtherAssistHeadInfo *otherHdr = (OtherAssistHeadInfo *)(buff + fileLen);\r
+ EncodeAndInjectCmd(handle, otherHdr->cmd, (buff + fileLen + sizeof(OtherAssistHeadInfo)), otherHdr->len);\r
+ fileLen += (otherHdr->len + sizeof(OtherAssistHeadInfo));\r
+ osal_msleep(INJECT_SLEEP_MS_TIME);\r
+ }\r
+ free(buff);\r
+}\r
+\r
+void PgnssInjectOtherAssistLessFiles(tiot_handle handle)\r
+{\r
+ PgnssSendOtherAssistInfo(handle, "/user/userdata/gnss/AssistInfo.dat");\r
+}\r
+\r
+// 注入PGNSS解析数据合并输出接口生成的星历文件\r
+void PgnssInjectLessFiles(tiot_handle handle, uint32_t ts)\r
+{\r
+ // 注入Pgnss辅助数据\r
+ PgnssInjectAllEphLessFiles(handle, ts);\r
+ PgnssInjectOtherAssistLessFiles(handle);\r
+}
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2024-2024. All rights reserved.\r
+ * Description: pgnss sample\r
+ * Author:\r
+ * Create:\r
+ */\r
+#include "pgnss_sample.h"\r
+#include <stdio.h>\r
+#include "securec.h"\r
+#include "tiot_service_interface.h"\r
+#include "pm_definition.h"\r
+#include "gnss_datatypes.h"\r
+#include "pgnss_encode.h"\r
+#include "NMEA0183.h"\r
+#include "sys/time.h"\r
+#include "time.h"\r
+#include "gnss_ctl.h"\r
+#ifdef SUPPORT_CYWEE_SERVICE\r
+#include "cywee_hal.h"\r
+#include "cywee_service.h"\r
+#endif\r
+\r
+\r
+#define PGNSS_FIXMODEALL_NMEADEF_SAMPLE 0\r
+#define PGNSS_LESS_FILES_FIXMODEALL_NMEADEF_SAMPLE 0\r
+\r
+#ifndef ARRAY_SIZE\r
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))\r
+#endif\r
+#define MSG_TYPE_BINRY 0\r
+#define MSG_TYPE_ASCII 1\r
+#define LISTEN_DATA_MAX_LINES 1000\r
+\r
+static FILE* g_gnssLogFp = NULL;\r
+static uint8_t g_gnssServiceBuff[REPORT_MAX_BYTES] = { 0 };\r
+\r
+typedef int32_t (*GnssCfgFunc)(tiot_handle handle);\r
+\r
+typedef struct {\r
+ uint16_t sampleId;\r
+ GnssCfgFunc cfgHandle;\r
+} GnssSamplesCfgTable;\r
+\r
+static NMEA0183 g_nmeadata={0};\r
+static gps_data_t g_global_gpsData={0};\r
+\r
+/**GPS状态位*/\r
+static int g_is_pgnss_poweron=0;\r
+static int g_is_pgnss_logon=0;\r
+static int g_pgnss_stopflag=0;\r
+\r
+static int32_t QryVersion(tiot_handle handle)\r
+{\r
+ const uint8_t qryVersion[] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};\r
+ // 查询版本号\r
+ int32_t ret = tiot_service_write(handle, qryVersion, sizeof(qryVersion));\r
+ if (ret < 0) {\r
+ CWM_OS_dbgPrintf("\nerror: QryVersion error: %d\r\n", ret);\r
+ return 0;\r
+ }\r
+ return 1;\r
+}\r
+\r
+static int decode_nmea(char c)\r
+{\r
+ int ret=0;\r
+ ret=0;\r
+ if(nmea_decode(&g_nmeadata,c) ==1 ) ///调用解析函数\r
+ {\r
+ dump_nmea_str(&(g_nmeadata.gpsParse));\r
+ if (g_nmeadata.gpsParse.sentence_type == GPS_SENTENCE_TH002 )\r
+ {\r
+ //一组数据最后一条\r
+ memcpy_s(&g_global_gpsData,sizeof(gps_data_t),&(g_nmeadata.gpsData),sizeof(gps_data_t));\r
+ ret = 1;\r
+ memset(&g_nmeadata,0,sizeof(g_nmeadata));\r
+#ifdef SUPPORT_CYWEE_SERVICE\r
+ if(uapi_dev_runtime_get_train_status())\r
+ do_cywee_service_check_msg(CYWEE_SERVICE_CMD_GNSS_UPDATE,NULL);\r
+#endif\r
+ }\r
+ } \r
+\r
+ return ret;\r
+}\r
+\r
+gps_data_t * getPGPSGlobaldata(void)\r
+{\r
+ return &g_global_gpsData;\r
+}\r
+\r
+\r
+// 注入PGNSS,使用默认配置启动\r
+int32_t InjectPgnssCfgAutoStartFixModeAndNmeaDefault(tiot_handle handle)\r
+{\r
+ const uint8_t cfgLogLevelInfo[] = {0x03, 0x00, 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x10, 0x01, 0x00, 0x03};\r
+\r
+ // 配置log级别:info级别。\r
+ int32_t ret = tiot_service_write(handle, cfgLogLevelInfo, sizeof(cfgLogLevelInfo));\r
+ if (ret < 0) {\r
+ CWM_OS_dbgPrintf("\nerror: cfgLogLevelInfo error: %d\r\n", ret);\r
+ return 0;\r
+ }\r
+\r
+ // 注入UTC时间, 注入Pgnss辅助数据前必须先注入参考时间\r
+ GnssUtcTime utcTime = {2024, 2, 26, 6, 0, 0, 0, 1}; // 需要用当前的UTC时间替换\r
+\r
+ time_t rawtime;\r
+ struct tm* timeinfo;\r
+\r
+ time(&rawtime); // 获取UTC时间戳\r
+ timeinfo = gmtime(&rawtime); // 转换为UTC时间(无时区偏移)\r
+\r
+ utcTime.year = timeinfo->tm_year + 1900;\r
+ utcTime.month = timeinfo->tm_mon + 1;\r
+ utcTime.day = timeinfo->tm_mday;\r
+ utcTime.hour = timeinfo->tm_hour;\r
+ utcTime.minute = timeinfo->tm_min;\r
+ utcTime.second = timeinfo->tm_sec;\r
+\r
+ CWM_OS_dbgPrintf("year[%d], mon[%d], day[%d], hour[%d], min[%d], sec[%d] \r\n",\r
+ utcTime.year,utcTime.month,utcTime.day,\r
+ utcTime.hour,utcTime.minute,utcTime.second);\r
+\r
+ uint32_t ts = 0;\r
+ ret = PgnssInjectUtcTime(handle, &utcTime, &ts);\r
+ if (ret == 0) {\r
+ CWM_OS_dbgPrintf("\nerror: PgnssInjectUtcTime failed!\r\n");\r
+ return 0;\r
+ }\r
+ CWM_OS_dbgPrintf("\nPgnssInjectUtcTime success!\r\n");\r
+\r
+ // PGNSS注入\r
+ // 注意,默认PGNSS星历文件存放在/user/xgnss/目录中,如修改目录,请全局搜索替换\r
+ PgnssInject(handle, ts);\r
+\r
+ return 1;\r
+}\r
+\r
+// 注入PGNSS,使用默认配置启动\r
+int32_t InjectPgnssLessFilesCfgAutoStartFixModeAndNmeaDefault(tiot_handle handle)\r
+{\r
+ const uint8_t cfgLogLevelInfo[] = {0x03, 0x00, 0x15, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x10, 0x01, 0x00, 0x03};\r
+\r
+ // 配置log级别:info级别。\r
+ int32_t ret = tiot_service_write(handle, cfgLogLevelInfo, sizeof(cfgLogLevelInfo));\r
+ if (ret < 0) {\r
+ CWM_OS_dbgPrintf("\nerror: cfgLogLevelInfo error: %d\r\n", ret);\r
+ return 0;\r
+ }\r
+\r
+ // 注入UTC时间, 注入Pgnss辅助数据前必须先注入参考时间\r
+ GnssUtcTime utcTime = {2024, 3, 14, 12, 0, 0, 0, 1}; // 需要用当前的UTC时间替换\r
+\r
+ time_t rawtime;\r
+ struct tm* timeinfo;\r
+\r
+ time(&rawtime); // 获取UTC时间戳\r
+ timeinfo = gmtime(&rawtime); // 转换为UTC时间(无时区偏移)\r
+\r
+ utcTime.year = timeinfo->tm_year + 1900;\r
+ utcTime.month = timeinfo->tm_mon + 1;\r
+ utcTime.day = timeinfo->tm_mday;\r
+ utcTime.hour = timeinfo->tm_hour;\r
+ utcTime.minute = timeinfo->tm_min;\r
+ utcTime.second = timeinfo->tm_sec;\r
+\r
+ CWM_OS_dbgPrintf("year[%d], mon[%d], day[%d], hour[%d], min[%d], sec[%d] \r\n",\r
+ utcTime.year,utcTime.month,utcTime.day,\r
+ utcTime.hour,utcTime.minute,utcTime.second);\r
+\r
+\r
+ uint32_t ts = 0;\r
+ ret = PgnssInjectUtcTime(handle, &utcTime, &ts);\r
+ if (ret == 0) {\r
+ CWM_OS_dbgPrintf("\nerror: PgnssInjectUtcTime failed!\r\n");\r
+ return 0;\r
+ }\r
+ CWM_OS_dbgPrintf("\nPgnssInjectUtcTime success!\r\n");\r
+\r
+ // PGNSS注入\r
+ // 注意,默认PGNSS星历文件存放在/user/xgnss/目录中,如修改目录,请全局搜索替换\r
+ PgnssInjectLessFiles(handle, ts);\r
+\r
+ return 1;\r
+}\r
+\r
+static const GnssSamplesCfgTable g_gnssSamplesCfg[] = {\r
+ // {PGNSS_FIXMODEALL_NMEADEF_SAMPLE, InjectPgnssCfgAutoStartFixModeAndNmeaDefault},\r
+ {PGNSS_LESS_FILES_FIXMODEALL_NMEADEF_SAMPLE, InjectPgnssLessFilesCfgAutoStartFixModeAndNmeaDefault}\r
+};\r
+\r
+static int32_t StartGnss(tiot_handle handle)\r
+{\r
+ const uint8_t startCmd[] = {0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,\r
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00};\r
+ // 启动GNSS\r
+ int32_t ret = tiot_service_write(handle, startCmd, sizeof(startCmd));\r
+ if (ret < 0) {\r
+ CWM_OS_dbgPrintf("\nerror: start gnss error: %d\r\n", ret);\r
+ return 0;\r
+ }\r
+ CWM_OS_dbgPrintf("\nstart gnss\r\n");\r
+ return 1;\r
+}\r
+\r
+static int32_t StopGnss(tiot_handle handle)\r
+{\r
+ const uint8_t stopCmd[] = {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\r
+ // 停止GNSS\r
+ int32_t ret = tiot_service_write(handle, stopCmd, sizeof(stopCmd));\r
+ if (ret < 0) {\r
+ CWM_OS_dbgPrintf("\nerror: stop gnss error: %d\r\n", ret);\r
+ return 0;\r
+ }\r
+ CWM_OS_dbgPrintf("\nstop gnss\r\n");\r
+ return 1;\r
+}\r
+\r
+\r
+static void ListenGnssData(tiot_handle handle)\r
+{\r
+ int32_t i = 0;\r
+ // 写日志\r
+ for (;;) { // 写日志条件\r
+\r
+ if (i >= LISTEN_DATA_MAX_LINES) {\r
+ CWM_OS_dbgPrintf("\r\ncnt enough\r\n");\r
+ break;\r
+ }\r
+ if (g_pgnss_stopflag == 1)\r
+ {\r
+ break;\r
+ }\r
+ // 监听\r
+ int32_t ret = tiot_service_read(handle, g_gnssServiceBuff, REPORT_MAX_BYTES, LISTEN_TIME_THR);\r
+ if (ret > 0) {\r
+ uint16_t *type = (uint16_t *)g_gnssServiceBuff;\r
+ if (type[0] == MSG_TYPE_ASCII) {\r
+ g_gnssServiceBuff[ret] = '\0';\r
+ char* pbuf=(char *)&g_gnssServiceBuff[MSG_CONTENT_IDX];\r
+ CWM_OS_dbgPrintf("%s\r\n", pbuf);\r
+ if (g_is_pgnss_logon)\r
+ fprintf(g_gnssLogFp, "%s\n", pbuf);\r
+ for (int index=0;index < ret ;index++)\r
+ {\r
+ if (decode_nmea(pbuf[index])==1)\r
+ {\r
+ // dump_location_data(&g_global_gpsData);\r
+ CWM_OS_dbgPrintf("decode_nmea done\r\n");\r
+ }\r
+ }\r
+ }\r
+ i++;\r
+ }\r
+\r
+ }\r
+}\r
+\r
+void PGnssServerStop(void)\r
+{\r
+ g_pgnss_stopflag=1;\r
+}\r
+\r
+int getPGnssServerStat(void)\r
+{\r
+ return g_is_pgnss_poweron;\r
+}\r
+\r
+int is_PGnssLogEnabled(void)\r
+{\r
+ return g_is_pgnss_logon;\r
+}\r
+\r
+int PGnssLogEnable(bool enable)\r
+{\r
+ if (enable)\r
+ g_is_pgnss_logon = 1;\r
+ else\r
+ g_is_pgnss_logon = 0;\r
+\r
+ return g_is_pgnss_logon;\r
+}\r
+\r
+\r
+void PGnssServerStart(void)\r
+{\r
+ CWM_OS_dbgPrintf("\nenter gnss samples\r\n");\r
+ if(g_is_pgnss_poweron == 1)\r
+ {\r
+ CWM_OS_dbgPrintf("gnss already on\r\n");\r
+ return ;\r
+ }\r
+ uapi_pm_add_sleep_veto(PM_ID_SYS);\r
+\r
+ #ifdef DOWNLOAD_GNSS_SWITCH\r
+ download_gnss_switch(SWITCH_TO_GNSS);\r
+ #endif\r
+ g_is_pgnss_poweron = 1;\r
+ g_pgnss_stopflag = 0;\r
+\r
+ // Step1: init\r
+ int32_t ret = tiot_service_init();\r
+ if (ret != 0) {\r
+ CWM_OS_dbgPrintf("tiot service init fail\r\n");\r
+ g_is_pgnss_poweron = 0;\r
+ g_pgnss_stopflag = 1;\r
+ }\r
+\r
+ // 打开日志文件\r
+ if (g_is_pgnss_logon)\r
+ {\r
+ g_gnssLogFp = fopen("/user/log/gnss.log", "w");\r
+ if (g_gnssLogFp == NULL) {\r
+ CWM_OS_dbgPrintf("error: open log file error\n");\r
+ return;\r
+ }\r
+ }\r
+ CWM_OS_dbgPrintf("before open tiot service\n");\r
+\r
+ // Step2: power on gnss\r
+ tiot_handle handle = tiot_service_open("gn71", NULL);\r
+ if (handle == 0) {\r
+ CWM_OS_dbgPrintf("open tiot service fail\r\n");\r
+ g_is_pgnss_poweron = 0;\r
+ g_pgnss_stopflag = 1;\r
+ return;\r
+ }\r
+ CWM_OS_dbgPrintf("open tiot service success\r\n");\r
+\r
+ int32_t cfgRet;\r
+ // ---- loop ----------\r
+ for (uint16_t i = 0; i < ARRAY_SIZE(g_gnssSamplesCfg); i++) {\r
+ cfgRet = 0;\r
+ if (g_gnssSamplesCfg[i].sampleId == i) {\r
+ // Step3: config gnss\r
+ if (g_gnssSamplesCfg[i].cfgHandle != NULL) {\r
+ cfgRet = g_gnssSamplesCfg[i].cfgHandle(handle);\r
+ }\r
+ if (cfgRet == 0) {\r
+ continue;\r
+ }\r
+ CWM_OS_dbgPrintf("cfg sample id:%u\r\n", g_gnssSamplesCfg[i].sampleId);\r
+ QryVersion(handle);\r
+\r
+ // Step4: start gnss\r
+ if (StartGnss(handle) == 0) {\r
+ continue;\r
+ }\r
+ // Step5: listening gnss data\r
+ ListenGnssData(handle);\r
+ // Step6: stop gnss\r
+ if (StopGnss(handle) == 0) {\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+ // ---------------------\r
+ // Step7: power off gnss\r
+ tiot_service_close(handle);\r
+ // 关日志文件\r
+ if (g_is_pgnss_logon)\r
+ {\r
+ fclose(g_gnssLogFp);\r
+ g_gnssLogFp = NULL;\r
+ }\r
+ // Step8: deinit\r
+ tiot_service_deinit();\r
+\r
+ #ifdef DOWNLOAD_GNSS_SWITCH\r
+ download_gnss_switch(SWITCH_TO_DOWNLOAD);\r
+ #endif\r
+ uapi_pm_remove_sleep_veto(PM_ID_SYS);\r
+ g_is_pgnss_poweron=0;\r
+ CWM_OS_dbgPrintf("finish gnss samples\r\n");\r
+}\r