luat_gnss.c 9.0 KB

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