luat_gnss.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include "luat_base.h"
  2. #include "luat_msgbus.h"
  3. #include "luat_mem.h"
  4. #include "luat_uart.h"
  5. #include "luat_rtc.h"
  6. #include "luat_mcu.h"
  7. #define LUAT_LOG_TAG "gnss"
  8. #include "luat_log.h"
  9. #include "minmea.h"
  10. luat_libgnss_t gnssctx;
  11. char *libgnss_recvbuff;
  12. int libgnss_route_uart_id = -1;
  13. int gnss_debug = 0;
  14. void luat_libgnss_uart_recv_cb(int uart_id, uint32_t data_len) {
  15. (void)data_len;
  16. if (libgnss_recvbuff == NULL)
  17. return;
  18. // LLOGD("uart recv cb");
  19. int len = 0;
  20. while (1) {
  21. len = luat_uart_read(uart_id, libgnss_recvbuff, RECV_BUFF_SIZE - 1);
  22. if (len < 1 || len >= RECV_BUFF_SIZE)
  23. break;
  24. if (libgnss_route_uart_id > 0) {
  25. luat_uart_write(libgnss_route_uart_id, libgnss_recvbuff, len);
  26. }
  27. luat_libgnss_on_rawdata(libgnss_recvbuff, len, 0);
  28. libgnss_recvbuff[len] = 0;
  29. if (gnss_debug) {
  30. if (len > 1000) {
  31. char *crlf = strstr(&libgnss_recvbuff[900], "\r\n");
  32. if (crlf != NULL) {
  33. LLOGD(">> %.*s", (int)(crlf - libgnss_recvbuff), libgnss_recvbuff);
  34. LLOGD(">> %s", crlf);
  35. } else {
  36. LLOGD(">> %.*s", 1000, libgnss_recvbuff);
  37. LLOGD(">> %s", &libgnss_recvbuff[1000]);
  38. }
  39. } else {
  40. LLOGD(">> %s", libgnss_recvbuff);
  41. }
  42. }
  43. luat_libgnss_parse_data(libgnss_recvbuff, len);
  44. }
  45. }
  46. static void clear_data(minmea_data_t* ptr) {
  47. if (ptr) {
  48. memset(ptr, 0, sizeof(minmea_data_t));
  49. }
  50. }
  51. int luat_libgnss_init(int clear) {
  52. if (clear) {
  53. gnssctx.fix_at_ticks = 0;
  54. memset(&gnssctx.frame_rmc, 0, sizeof(struct minmea_sentence_rmc));
  55. clear_data(gnssctx.rmc);
  56. clear_data(gnssctx.gga);
  57. clear_data(gnssctx.gll);
  58. clear_data(gnssctx.gst);
  59. clear_data(gnssctx.vtg);
  60. clear_data(gnssctx.zda);
  61. clear_data(gnssctx.txt);
  62. for (size_t i = 0; i < FRAME_GSV_MAX; i++)
  63. {
  64. clear_data(gnssctx.gsv[i]);
  65. }
  66. for (size_t i = 0; i < FRAME_GSA_MAX; i++)
  67. {
  68. clear_data(gnssctx.gsa[i]);
  69. }
  70. }
  71. return 0;
  72. }
  73. #define MAX_LEN (120)
  74. static char nmea_tmp_buff[MAX_LEN] = {0}; // nmea 最大长度82,含换行符
  75. int luat_libgnss_parse_data(const char* data, size_t len) {
  76. size_t offset = strlen(nmea_tmp_buff);
  77. // 流式解析nmea数据
  78. for (size_t i = 0; i < len; i++)
  79. {
  80. if (offset >= MAX_LEN) {
  81. offset = 0;
  82. }
  83. if (data[i] == 0x0A) {
  84. nmea_tmp_buff[offset] = 0;
  85. luat_libgnss_parse_nmea((const char*)nmea_tmp_buff);
  86. offset = 0;
  87. continue;
  88. }
  89. else {
  90. nmea_tmp_buff[offset++] = data[i];
  91. }
  92. //LLOGD("当前数据 %s", nmea_tmp_buff);
  93. }
  94. nmea_tmp_buff[offset] = 0;
  95. return 0;
  96. }
  97. static void copynmea(minmea_data_t** dst, const char* src) {
  98. if (*dst == NULL) {
  99. *dst = luat_heap_malloc(sizeof(minmea_data_t));
  100. }
  101. if (*dst != NULL) {
  102. strcpy((*dst)->data, src);
  103. (*dst)->tm = luat_mcu_tick64_ms();
  104. }
  105. }
  106. int luat_libgnss_parse_nmea(const char* line) {
  107. if (strlen(line) > (LUAT_LIBGNSS_MAX_LINE - 1)) {
  108. return -1;
  109. }
  110. char tmpbuff[128] = {0};
  111. struct minmea_sentence_gsv *frame_gsv = (struct minmea_sentence_gsv*)tmpbuff;
  112. struct minmea_sentence_rmc *frame_rmc = (struct minmea_sentence_rmc*)tmpbuff;
  113. struct minmea_sentence_gsa *frame_gsa = (struct minmea_sentence_gsa*)tmpbuff;
  114. enum minmea_sentence_id id = minmea_sentence_id(line, false);
  115. if (id == MINMEA_UNKNOWN || id >= MINMEA_SENTENCE_MAX_ID || id == MINMEA_INVALID) {
  116. //LLOGD("非法的NMEA数据 %s", line);
  117. return -1;
  118. }
  119. uint64_t tnow = luat_mcu_tick64_ms();
  120. struct tm tblock = {0};
  121. int ticks = luat_mcu_ticks();
  122. switch (id) {
  123. case MINMEA_SENTENCE_RMC: {
  124. if (minmea_parse_rmc(frame_rmc, line)) {
  125. copynmea(&gnssctx.rmc, line);
  126. if (frame_rmc->valid) {
  127. memcpy(&(gnssctx.frame_rmc), frame_rmc, sizeof(struct minmea_sentence_rmc));
  128. #ifdef LUAT_USE_MCU
  129. if (gnssctx.rtc_auto && (gnssctx.fix_at_ticks == 0 || ((uint32_t)(ticks - gnssctx.fix_at_ticks)) > 600*1000)) {
  130. LLOGI("Auto-Set RTC by GNSS RMC");
  131. minmea_getdatetime(&tblock, &gnssctx.frame_rmc.date, &gnssctx.frame_rmc.time);
  132. tblock.tm_year -= 1900;
  133. luat_rtc_set(&tblock);
  134. // luat_rtc_set_tamp32(mktime(&tblock));
  135. }
  136. if (gnssctx.fix_at_ticks == 0) {
  137. LLOGI("Fixed %d %d", gnssctx.frame_rmc.latitude.value, gnssctx.frame_rmc.longitude.value);
  138. // 发布系统消息
  139. luat_libgnss_state_onchanged(GNSS_STATE_FIXED);
  140. }
  141. gnssctx.fix_at_ticks = luat_mcu_ticks();
  142. #endif
  143. }
  144. else {
  145. if (gnssctx.fix_at_ticks && gnssctx.frame_rmc.valid) {
  146. LLOGI("Lose"); // 发布系统消息
  147. luat_libgnss_state_onchanged(GNSS_STATE_LOSE);
  148. }
  149. gnssctx.fix_at_ticks = 0;
  150. gnssctx.frame_rmc.valid = 0;
  151. // if (libgnss_gnsstmp->frame_rmc.date.year > 0) {
  152. memcpy(&(gnssctx.frame_rmc.date), &(frame_rmc->date), sizeof(struct minmea_date));
  153. // }
  154. // if (libgnss_gnsstmp->frame_rmc.time.hours > 0) {
  155. memcpy(&(gnssctx.frame_rmc.time), &(frame_rmc->time), sizeof(struct minmea_time));
  156. // }
  157. }
  158. }
  159. } break;
  160. case MINMEA_SENTENCE_GSA: {
  161. if (minmea_parse_gsa(frame_gsa, line)) {
  162. copynmea(&gnssctx.gsa[gnssctx.gsa_offset], line);
  163. if (gnssctx.gsa_offset + 1 >= FRAME_GSA_MAX) {
  164. gnssctx.gsa_offset = 0;
  165. }
  166. else {
  167. gnssctx.gsa_offset ++;
  168. }
  169. // 把失效的GSA清理掉
  170. for (size_t i = 0; i < FRAME_GSA_MAX; i++)
  171. {
  172. if (gnssctx.gsa[i] && gnssctx.gsa[i]->data[0] != 0 && tnow - gnssctx.gsa[i]->tm > 950) {
  173. memset(gnssctx.gsa[i], 0, sizeof(minmea_data_t));
  174. }
  175. }
  176. }
  177. } break;
  178. case MINMEA_SENTENCE_GSV: {
  179. //LLOGD("Got GSV : %s", line);
  180. if (minmea_parse_gsv(frame_gsv, line)) {
  181. if (frame_gsv->msg_nr == 1) {
  182. // 检测到开头, 那么清空所有相同头部的数据
  183. for (size_t i = 0; i < FRAME_GSV_MAX; i++)
  184. {
  185. if (gnssctx.gsv[i] && 0 == memcmp(line, gnssctx.gsv[i], 6)) {
  186. memset(gnssctx.gsv[i]->data, 0, sizeof(minmea_data_t));
  187. }
  188. }
  189. }
  190. // 找一个空位,放进去
  191. for (size_t i = 0; i < FRAME_GSV_MAX; i++)
  192. {
  193. if (gnssctx.gsv[i] == NULL) {
  194. copynmea(&gnssctx.gsv[i], line);
  195. break;
  196. }
  197. if (gnssctx.gsv[i]->data[0] == 0) {
  198. // LLOGD("填充GSV到%d %s", i, line);
  199. copynmea(&gnssctx.gsv[i], line);
  200. break;
  201. }
  202. }
  203. }
  204. } break;
  205. case MINMEA_SENTENCE_GGA: {
  206. copynmea(&gnssctx.gga, line);
  207. } break;
  208. case MINMEA_SENTENCE_GLL: {
  209. copynmea(&gnssctx.gll, line);
  210. break;
  211. }
  212. case MINMEA_SENTENCE_GST: {
  213. copynmea(&gnssctx.gst, line);
  214. break;
  215. }
  216. case MINMEA_SENTENCE_VTG: {
  217. copynmea(&gnssctx.vtg, line);
  218. } break;
  219. case MINMEA_SENTENCE_ZDA: {
  220. copynmea(&gnssctx.zda, line);
  221. } break;
  222. case MINMEA_SENTENCE_TXT: {
  223. luat_libgnss_on_rawdata(line, strlen(line), 1);
  224. copynmea(&gnssctx.txt, line);
  225. break;
  226. }
  227. default: {
  228. luat_libgnss_on_rawdata(line, strlen(line), 2);
  229. break;
  230. }
  231. }
  232. return 0;
  233. }
  234. int luat_libgnss_data_check(minmea_data_t* data, uint32_t timeout, uint64_t tnow) {
  235. if (data == NULL) {
  236. return 0;
  237. }
  238. if (data->tm == 0 || tnow - data->tm > timeout) {
  239. return 0;
  240. }
  241. return 1;
  242. }