mcu_hi3321_watch/tjd/service/service_gps.c
2025-05-26 20:15:20 +08:00

805 lines
26 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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 <cmsis_os2.h>
#include <dirent.h>
#include <stdio.h>
#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));
}