hd_gnss_demo.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568
  1. /*================================================================
  2. Copyright (c) 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
  3. Quectel Wireless Solution Proprietary and Confidential.
  4. =================================================================*/
  5. /*=================================================================
  6. EDIT HISTORY FOR MODULE
  7. This section contains comments describing changes made to the module.
  8. Notice that changes are listed in reverse chronological order.
  9. WHEN WHO WHAT, WHERE, WHY
  10. ------------ ------- -------------------------------------------------------------------------------
  11. =================================================================*/
  12. /*===========================================================================
  13. * include files
  14. ===========================================================================*/
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include "ql_api_osi.h"
  19. #include "ql_log.h"
  20. #include "hd_gnss_demo.h"
  21. #include "ql_api_datacall.h"
  22. /*===========================================================================
  23. * Macro Definition
  24. ===========================================================================*/
  25. #define MAX_UINT32 4294967295U
  26. #define QL_GNSSDEMO_LOG_LEVEL QL_LOG_LEVEL_INFO
  27. #define QL_GNSSDEMO_LOG(msg, ...) QL_LOG(QL_GNSSDEMO_LOG_LEVEL, "ql_GNSSDEMO", msg, ##__VA_ARGS__)
  28. #define nmea_dbg_log(msg, ...) QL_LOG(QL_GNSSDEMO_LOG_LEVEL,"ql_nmaea", msg, ##__VA_ARGS__)
  29. /*===========================================================================
  30. * Variate
  31. ===========================================================================*/
  32. ql_task_t gnss_task = NULL;
  33. ql_gnss_data_t g_gps_data = {0};
  34. nmeasrc_sentences nmea_handle={0};
  35. char gnss_device_info[100]={0};
  36. static uint32 prev_ms_gsv =0;
  37. static bool tick_overflow = FALSE;
  38. //EG800GCN_GB使用的是UART5,EC200GCN_GD使用的是UART6
  39. char hd_uart_channel = QL_UART_PORT_5;
  40. //char hd_uart_channel = QL_UART_PORT_6;
  41. /*===========================================================================
  42. * Functions
  43. ===========================================================================*/
  44. void ql_hd_gnss_notify_cb(ql_gnss_callback_s *callback_s)
  45. {
  46. if( callback_s->ind_type == QUEC_UART_RX_RECV_DATA_IND )
  47. {
  48. ql_event_t event;
  49. event.id = callback_s->ind_type;
  50. event.param1 = callback_s->port;
  51. event.param2 = callback_s->size;
  52. ql_rtos_event_send(gnss_task, &event);
  53. QL_GNSSDEMO_LOG("gnss demo port is %d, size is %d", event.param1, event.param2);
  54. }
  55. else
  56. {
  57. QL_GNSSDEMO_LOG("gnss demo recv overflow error!");
  58. }
  59. }
  60. static void ql_hd_gnss_demo_thread(void *param)
  61. {
  62. QL_GNSSDEMO_LOG("gnss demo thread enter, param 0x%x", param);
  63. ql_event_t event;
  64. int ret=0;
  65. static int total_bytes = 0;
  66. static char buffer[2048]={0};
  67. unsigned char nmea_buff[256];
  68. char *start, *end;
  69. struct nmea_s *nmea = NULL;
  70. unsigned char *recbuff=NULL;
  71. /* open GNSS */
  72. ret = ql_gnss_switch(GNSS_ENABLE);
  73. if(ret == QL_GNSS_ALREADY_OPEN)
  74. {
  75. QL_GNSSDEMO_LOG("GNSS demo already open");
  76. }
  77. if( ret == QL_GNSS_NOT_SUPPORT_ERR)
  78. {
  79. goto exit;
  80. }
  81. while(ql_gnss_state_info_get()==GNSS_FIRMWARE_UPDATE)
  82. {
  83. ql_rtos_task_sleep_ms(1000);
  84. }
  85. ql_gnss_callback_register_ex(ql_hd_gnss_notify_cb);
  86. if(ret ==QL_GNSS_CB_NULL_ERR)
  87. {
  88. goto exit;
  89. }
  90. ql_gnss_device_info_request();
  91. ql_gnss_cfg_s gnss_cfg;
  92. ret = ql_gnss_get_cfg(&gnss_cfg);
  93. if (ret == QL_GNSS_SUCCESS)
  94. {
  95. QL_GNSSDEMO_LOG("get sys_type=%d", gnss_cfg.nmea_cfg.gnss_nmea_sys_type);
  96. }
  97. while(1)
  98. {
  99. if( ql_event_try_wait(&event) != 0 )
  100. {
  101. continue;
  102. }
  103. if( event.id == QUEC_UART_RX_RECV_DATA_IND )
  104. {
  105. recbuff=calloc(1,QUEC_GPS_RECBUF_LEN_MAX); //recbuff是接收底层uart的buffer,增大recbuff size,与底层UART RX buffer保持一致,防止在get nmea内存越界
  106. if(NULL==recbuff)
  107. {
  108. QL_GNSSDEMO_LOG("malloc err\r\n");
  109. break;
  110. }
  111. if(ql_gnss_nmea_get( event.param1,recbuff, event.param2)<0)
  112. {
  113. if(NULL != recbuff)
  114. {
  115. free(recbuff);
  116. recbuff=NULL;
  117. }
  118. break;
  119. }
  120. total_bytes += event.param2;
  121. if (total_bytes > sizeof(buffer)-150)
  122. {
  123. total_bytes = 0;
  124. QL_GNSSDEMO_LOG("nmea data Overflow\r\n");
  125. if(NULL != recbuff)
  126. {
  127. free(recbuff);
  128. recbuff=NULL;
  129. }
  130. continue;
  131. }
  132. memcpy(buffer+total_bytes-event.param2, recbuff, event.param2);
  133. if(NULL != recbuff)
  134. {
  135. free(recbuff);
  136. recbuff=NULL;
  137. }
  138. if(event.param2>0)
  139. {
  140. end=buffer;
  141. while(1)
  142. {
  143. int i=0;
  144. start = NULL;
  145. while(i < (total_bytes-(end-buffer)))
  146. {
  147. if((buffer[i] == 0xF1) && (buffer[i+1] == 0xD9))
  148. {
  149. if((buffer[i+2] == 0x05) && (buffer[i+3] == 0x01))
  150. {
  151. QL_GNSSDEMO_LOG("0x%02X 0x%02X ACK RECIEVE\r\n",buffer[i+6],buffer[i+7]);
  152. }
  153. else if ((buffer[i+2] == 0x05) && (buffer[i+3] == 0x00))
  154. {
  155. QL_GNSSDEMO_LOG("0x%02X 0x%02X NAK RECIEVE\r\n",buffer[i+6],buffer[i+7]);
  156. }
  157. else if((buffer[i+2] == 0x0A) && (buffer[i+3] == 0x04) && (buffer[i+4] == 0x20))
  158. {
  159. memcpy(gnss_device_info,buffer+i+6,32);
  160. QL_GNSSDEMO_LOG("gnss_device_info:%s %s\r\n",gnss_device_info,&gnss_device_info[16]);
  161. }
  162. break;
  163. }
  164. i++;
  165. }
  166. start = memchr(end, '$', total_bytes-(end-buffer));
  167. if (NULL == start) {
  168. total_bytes = 0;
  169. break;
  170. }
  171. end = memchr(start, NMEA_END_CHAR_1, total_bytes-(start-buffer));
  172. if (NULL==end || NMEA_END_CHAR_2 != *(++end)) {
  173. if (buffer != memmove(buffer, start, total_bytes-(start-buffer))) {
  174. total_bytes = 0;
  175. }
  176. total_bytes = total_bytes-(start-buffer);
  177. break;
  178. }
  179. memset(nmea_buff, 0, sizeof(nmea_buff));
  180. memcpy(nmea_buff, start, jmin(sizeof(nmea_buff)-1, end-start-1));
  181. QL_GNSSDEMO_LOG("%s\r\n", nmea_buff);
  182. /* nmea string parse */
  183. nmea = nmea_parse(start, end-start+1, 1);
  184. if (nmea)
  185. {
  186. ret=nmea_value_update(nmea, &g_gps_data);
  187. if(ret)
  188. {
  189. QL_GNSSDEMO_LOG("nmea_value_update error. \r\n");
  190. QL_GNSSDEMO_LOG("GSV: %s", nmea_buff);
  191. }
  192. if (nmea->data) {
  193. free(nmea->data);
  194. nmea->data = NULL;
  195. }
  196. free(nmea);
  197. nmea = NULL;
  198. }
  199. if(end==buffer+total_bytes)
  200. {
  201. total_bytes=0;
  202. break;
  203. }
  204. end=end+1;
  205. }
  206. }
  207. }
  208. }
  209. exit:
  210. if(NULL != recbuff)
  211. {
  212. free(recbuff);
  213. recbuff=NULL;
  214. }
  215. ql_gnss_switch(GNSS_DISABLE);
  216. QL_GNSSDEMO_LOG("gnss demo thread exit, param 0x%x", param);
  217. ql_rtos_task_delete(NULL);
  218. }
  219. void ql_hd_gnss_app_init(void)
  220. {
  221. QlOSStatus err = QL_OSI_SUCCESS;
  222. err = ql_rtos_task_create(&gnss_task, 4096, APP_PRIORITY_NORMAL, "ql_hd_gnssdemo", ql_hd_gnss_demo_thread, NULL, 5);
  223. if( err != QL_OSI_SUCCESS )
  224. {
  225. QL_GNSSDEMO_LOG("gnss demo task created failed");
  226. }
  227. }
  228. int ql_gnss_assist_data_delete(unsigned int reset_type)
  229. {
  230. int send_len=9;
  231. int ret=0;
  232. unsigned char reset_cmd[9]={0xF1,0xD9,0x06,0x40,0x01,0x0,0x0,0x0,0x0};
  233. if(reset_type==0)//cold
  234. {
  235. reset_cmd[6] = 0x01;
  236. reset_cmd[7] = 0x48;
  237. reset_cmd[8] = 0x22;
  238. }
  239. else if(reset_type==1)//warm
  240. {
  241. reset_cmd[6] = 0x02;
  242. reset_cmd[7] = 0x49;
  243. reset_cmd[8] = 0x23;
  244. }
  245. else if(reset_type==2)//hot
  246. {
  247. reset_cmd[6] = 0x03;
  248. reset_cmd[7] = 0x4A;
  249. reset_cmd[8] = 0x24;
  250. }
  251. else
  252. {
  253. ret=QL_GNSS_INVALID_PARAM_ERR;
  254. return ret;
  255. }
  256. QL_GNSSDEMO_LOG("reset_type=%d cmd_len=%d",reset_type,send_len);
  257. if(ql_uart_write(hd_uart_channel,reset_cmd,send_len)==send_len)
  258. {
  259. QL_GNSSDEMO_LOG("GNSS DATA SEND\r\n");
  260. }
  261. else
  262. {
  263. ret=QL_GNSS_EXECUTE_ERR;
  264. }
  265. return ret;
  266. }
  267. int ql_gnss_device_info_request(void)
  268. {
  269. unsigned char info_cmd[8]={0xF1,0xD9,0x0A,0x04,0x0,0x0,0x0E,0x34};
  270. int send_len=8;
  271. int ret=0;
  272. if((ql_gnss_state_info_get()==GNSS_FIRMWARE_UPDATE)||(ql_gnss_state_info_get()==GNSS_CLOSE))
  273. {
  274. QL_GNSSDEMO_LOG("gnss dev not ready\r\n");
  275. return QL_GNSS_EXECUTE_ERR;
  276. }
  277. if(ql_uart_write(hd_uart_channel,info_cmd,send_len)!=send_len)
  278. {
  279. QL_GNSSDEMO_LOG("gnss device info request fail\r\n");
  280. ret=QL_GNSS_EXECUTE_ERR;
  281. return ret;
  282. }
  283. return ret;
  284. }
  285. /**
  286. * strptime
  287. **/
  288. #define TM_YEAR_BASE 1900
  289. /*
  290. * We do not implement alternate representations. However, we always
  291. * check whether a given modifier is allowed for a certain conversion.
  292. */
  293. #define ALT_E 0x01
  294. #define ALT_O 0x02
  295. #define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); }
  296. static const char *day[7] = {
  297. "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
  298. "Friday", "Saturday"
  299. };
  300. static const char *abday[7] = {
  301. "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
  302. };
  303. static const char *mon[12] = {
  304. "January", "February", "March", "April", "May", "June", "July",
  305. "August", "September", "October", "November", "December"
  306. };
  307. static const char *abmon[12] = {
  308. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  309. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  310. };
  311. static const char *am_pm[2] = {
  312. "AM", "PM"
  313. };
  314. char nmea_get_checksum(const char *sentence)
  315. {
  316. const char *n = sentence + 1;
  317. char chk = 0;
  318. /* While current char isn't '*' or sentence ending (newline) */
  319. while ('*' != *n && NMEA_END_CHAR_1 != *n && '\0' != *n) {
  320. chk ^= (char) *n;
  321. n++;
  322. }
  323. return chk;
  324. }
  325. int nmea_has_checksum(const char *sentence, int length)
  326. {
  327. if ('*' == sentence[length - 5]) {
  328. return 0;
  329. }
  330. return -1;
  331. }
  332. int nmea_validate(const char *sentence, int length, int check_checksum)
  333. {
  334. const char *n = NULL;
  335. //nmea_dbg_log("%s\n", __FUNCTION__);
  336. /* should have atleast 9 characters */
  337. if (9 > length) {
  338. return -1;
  339. }
  340. /* should be less or equal to 82 characters */
  341. if (NMEA_MAX_LENGTH < length) {
  342. return -1;
  343. }
  344. /* should start with $ */
  345. if ('$' != *sentence) {
  346. return -1;
  347. }
  348. /* should end with \r\n, or other... */
  349. if (NMEA_END_CHAR_2 != sentence[length - 1] || NMEA_END_CHAR_1 != sentence[length - 2]) {
  350. nmea_dbg_log("\r\n");
  351. return -1;
  352. }
  353. /* should have a 5 letter, uppercase word */
  354. n = sentence;
  355. while (++n < sentence + 6) {
  356. if (*n < 'A' || *n > 'Z') {
  357. /* not uppercase letter */
  358. return -1;
  359. }
  360. }
  361. /* should have a comma after the type word */
  362. if (',' != sentence[6]) {
  363. nmea_dbg_log("\r\n");
  364. return -1;
  365. }
  366. /* check for checksum */
  367. if (1 == check_checksum && 0 == nmea_has_checksum(sentence, length)) {
  368. char actual_chk=0;
  369. char expected_chk=0;
  370. char checksum[3]={0};
  371. checksum[0] = sentence[length - 4];
  372. checksum[1] = sentence[length - 3];
  373. checksum[2] = '\0';
  374. actual_chk = nmea_get_checksum(sentence);
  375. expected_chk = (char) strtol(checksum, NULL, 16);
  376. if (expected_chk != actual_chk) {
  377. nmea_dbg_log("\r\n");
  378. return -1;
  379. }
  380. }
  381. return 0;
  382. }
  383. /**
  384. * Crop a sentence from the type word and checksum.
  385. *
  386. * The type word at the beginning along with the dollar sign ($) will be
  387. * removed. If there is a checksum, it will also be removed. The two end
  388. * characters (usually <CR><LF>) will not be included in the new string.
  389. *
  390. * sentence is a validated NMEA sentence string.
  391. * length is the char length of the sentence string.
  392. *
  393. * Returns pointer (char *) to the new string.
  394. */
  395. static char * _crop_sentence(char *sentence, size_t length)
  396. {
  397. /* Skip type word, 7 characters (including $ and ,) */
  398. sentence += NMEA_PREFIX_LENGTH + 2;
  399. /* Null terminate before end of line/sentence, 2 characters */
  400. sentence[length - 9] = '\0';
  401. /* Remove checksum, if there is one */
  402. if ('*' == sentence[length - 12]) {
  403. sentence[length - 12] = '\0';
  404. }
  405. return sentence;
  406. }
  407. /**
  408. * Splits a string by comma.
  409. *
  410. * string is the string to split, will be manipulated. Needs to be
  411. * null-terminated.
  412. * values is a char pointer array that will be filled with pointers to the
  413. * splitted values in the string.
  414. * max_values is the maximum number of values to be parsed.
  415. *
  416. * Returns the number of values found in string.
  417. */
  418. static int _split_string_by_comma(char *string, char **values, int max_values)
  419. {
  420. int i = 0;
  421. values[i++] = string;
  422. while (i < max_values && NULL != (string = strchr(string, ','))) {
  423. *string = '\0';
  424. values[i++] = ++string;
  425. }
  426. return i;
  427. }
  428. nmea_type nmea_get_type(const char *sentence)
  429. {
  430. if (strncmp(sentence + 3, "RMC", 3) == 0)
  431. {
  432. return NMEA_RMC;
  433. }
  434. else if (strncmp(sentence + 3, "GGA", 3) == 0)
  435. {
  436. return NMEA_GGA;
  437. }
  438. else if (strncmp(sentence + 3, "GSA", 3) == 0)
  439. {
  440. return NMEA_GSA;
  441. }
  442. else if (strncmp(sentence + 3, "GSV", 3) == 0)
  443. {
  444. return NMEA_GSV;
  445. }
  446. else if (strncmp(sentence + 3, "TXT", 3) == 0)
  447. {
  448. return NMEA_TXT;
  449. }
  450. else if (strncmp(sentence + 3, "VTG", 3) == 0)
  451. {
  452. return NMEA_VTG;
  453. }
  454. return NMEA_UNKNOWN;
  455. }
  456. /**
  457. * Check if a value is not NULL and not empty.
  458. *
  459. * Returns 0 if set, otherwise -1.
  460. */
  461. static int _is_value_set(const char *value)
  462. {
  463. if (NULL == value || '\0' == *value) {
  464. return -1;
  465. }
  466. return 0;
  467. }
  468. int nmea_position_parse(char *s, struct nmea_position *pos)
  469. {
  470. char *cursor=NULL;
  471. pos->degrees = 0;
  472. pos->minutes = 0;
  473. if (s == NULL || *s == '\0') {
  474. return -1;
  475. }
  476. /* decimal minutes */
  477. if (NULL == (cursor = strchr(s, '.'))) {
  478. return -1;
  479. }
  480. /* minutes starts 2 digits before dot */
  481. cursor -= 2;
  482. pos->minutes = atof(cursor);
  483. *cursor = '\0';
  484. /* integer degrees */
  485. cursor = s;
  486. pos->degrees = atoi(cursor);
  487. return 0;
  488. }
  489. nmea_cardinal_t nmea_cardinal_direction_parse(char *s)
  490. {
  491. if (NULL == s || '\0'== *s) {
  492. return NMEA_CARDINAL_DIR_UNKNOWN;
  493. }
  494. switch (*s) {
  495. case NMEA_CARDINAL_DIR_NORTH:
  496. return NMEA_CARDINAL_DIR_NORTH;
  497. case NMEA_CARDINAL_DIR_EAST:
  498. return NMEA_CARDINAL_DIR_EAST;
  499. case NMEA_CARDINAL_DIR_SOUTH:
  500. return NMEA_CARDINAL_DIR_SOUTH;
  501. case NMEA_CARDINAL_DIR_WEST:
  502. return NMEA_CARDINAL_DIR_WEST;
  503. default:
  504. break;
  505. }
  506. return NMEA_CARDINAL_DIR_UNKNOWN;
  507. }
  508. int nmea_validate_parse(char *s)
  509. {
  510. if (NULL == s || '\0'== *s) {
  511. return 0;
  512. }
  513. return (*s == 'A');
  514. }
  515. int nmea_time_parse(char *s, struct tm *time)
  516. {
  517. //char *rv;
  518. memset(time, 0, sizeof (struct tm));
  519. if (s == NULL || *s == '\0') {
  520. return -1;
  521. }
  522. strptime(s, NMEA_TIME_FORMAT, time);
  523. // if (NULL == rv || (int) (rv - s) != NMEA_TIME_FORMAT_LEN) {
  524. // return -1;
  525. // }
  526. return 0;
  527. }
  528. int nmea_date_parse(char *s, struct tm *time)
  529. {
  530. //char *rv;
  531. // Assume it has been already cleared
  532. memset(time, 0, sizeof (struct tm));
  533. if (s == NULL || *s == '\0') {
  534. return -1;
  535. }
  536. strptime(s, NMEA_DATE_FORMAT, time);
  537. // if (NULL == rv || (int) (rv - s) != NMEA_DATE_FORMAT_LEN) {
  538. // return -1;
  539. // }
  540. return 0;
  541. }
  542. int nmea_parse_rmc(struct nmea_s *nmea, char *sentence)
  543. {
  544. unsigned int n_vals=0, val_index=0;
  545. char *value=NULL;
  546. char *values[255]={NULL};
  547. struct nmea_gprmc_s *data = NULL;
  548. /* Split the sentence into values */
  549. n_vals = _split_string_by_comma(sentence, values, ARRAY_LENGTH(values));
  550. if (0 == n_vals)
  551. {
  552. return -1;
  553. }
  554. data = malloc(sizeof(struct nmea_gprmc_s));
  555. if (data == NULL)
  556. {
  557. nmea_dbg_log("rmc nmea data malloc error. \r\n");
  558. return -1;
  559. }
  560. memset(data, 0, sizeof(struct nmea_gprmc_s));
  561. for (val_index = 0; val_index < n_vals; val_index++)
  562. {
  563. value = values[val_index];
  564. if (-1 == _is_value_set(value))
  565. {
  566. continue;
  567. }
  568. switch (val_index)
  569. {
  570. case NMEA_GPRMC_TIME:
  571. /* Parse time */
  572. if (-1 == nmea_time_parse(value, &data->time))
  573. {
  574. nmea_dbg_log("nmea_time_parse error. \r\n");
  575. goto _error;
  576. }
  577. break;
  578. case NMEA_GPRMC_STATUS:
  579. data->valid = nmea_validate_parse(value);
  580. break;
  581. case NMEA_GPRMC_LATITUDE:
  582. /* Parse latitude */
  583. if (-1 == nmea_position_parse(value, &data->latitude))
  584. {
  585. nmea_dbg_log("nmea_position_parse error. \r\n");
  586. goto _error;
  587. }
  588. break;
  589. case NMEA_GPRMC_LATITUDE_CARDINAL:
  590. /* Parse cardinal direction */
  591. data->latitude.cardinal = nmea_cardinal_direction_parse(value);
  592. if (NMEA_CARDINAL_DIR_UNKNOWN == data->latitude.cardinal)
  593. {
  594. nmea_dbg_log("nmea_cardinal_direction_parse error. \r\n");
  595. goto _error;
  596. }
  597. break;
  598. case NMEA_GPRMC_LONGITUDE:
  599. /* Parse longitude */
  600. if (-1 == nmea_position_parse(value, &data->longitude))
  601. {
  602. nmea_dbg_log("nmea_position_parse error. \r\n");
  603. goto _error;
  604. }
  605. break;
  606. case NMEA_GPRMC_LONGITUDE_CARDINAL:
  607. /* Parse cardinal direction */
  608. data->longitude.cardinal = nmea_cardinal_direction_parse(value);
  609. if (NMEA_CARDINAL_DIR_UNKNOWN == data->longitude.cardinal)
  610. {
  611. nmea_dbg_log("nmea_cardinal_direction_parse error. \r\n");
  612. goto _error;
  613. }
  614. break;
  615. case NMEA_GPRMC_DATE:
  616. /* Parse date */
  617. if (-1 == nmea_date_parse(value, &data->time))
  618. {
  619. nmea_dbg_log("nmea_date_parse error. \r\n");
  620. goto _error;
  621. }
  622. break;
  623. case NMEA_GPRMC_COURSE:
  624. data->course = atof(value);
  625. break;
  626. case NMEA_GPRMC_SPEED:
  627. /* Parse ground speed in knots */
  628. data->speed = atof(value);
  629. break;
  630. default:
  631. break;
  632. }
  633. }
  634. nmea->data = data;
  635. return 0;
  636. _error:
  637. if (data)
  638. {
  639. free(data);
  640. data = NULL;
  641. }
  642. return -1;
  643. }
  644. int nmea_parse_gsv(struct nmea_s *nmea, char *sentence)
  645. {
  646. unsigned int n_vals=0, val_index=0;
  647. char *value=NULL;
  648. char *values[255]={NULL};
  649. struct nmea_gpgsv_s *data = NULL;
  650. /* Split the sentence into values */
  651. n_vals = _split_string_by_comma(sentence, values, ARRAY_LENGTH(values));
  652. if (0 == n_vals)
  653. {
  654. return -1;
  655. }
  656. data = malloc(sizeof(struct nmea_gpgsv_s));
  657. if (data == NULL)
  658. {
  659. nmea_dbg_log("nmea data malloc error. \r\n");
  660. return -1;
  661. }
  662. memset(data, 0, sizeof(struct nmea_gpgsv_s));
  663. data->sig_id = 0;
  664. data->cur_sats = (n_vals-3)/4;
  665. for (val_index = 0; val_index < n_vals; val_index++)
  666. {
  667. value = values[val_index];
  668. if (-1 == _is_value_set(value))
  669. {
  670. continue;
  671. }
  672. switch (val_index)
  673. {
  674. case NMEA_GPGSV_TOTAL_MSGS:
  675. data->total_msgs = atoi(value);
  676. break;
  677. case NMEA_GPGSV_MSG_NR:
  678. data->msg_nr = atoi(value);
  679. break;
  680. case NMEA_GPGSV_SATS:
  681. data->total_sats = atoi(value);
  682. break;
  683. case NMEA_GPGSV_SAT_INFO_NR1:
  684. data->sats[0].nr = atoi(value);
  685. break;
  686. case NMEA_GPGSV_SAT_INFO_ELEV1:
  687. data->sats[0].elevation = atoi(value);
  688. break;
  689. case NMEA_GPGSV_SAT_INFO_AZIMUTH1:
  690. data->sats[0].azimuth = atoi(value);
  691. break;
  692. case NMEA_GPGSV_SAT_INFO_SNR1:
  693. data->sats[0].snr = atoi(value);
  694. break;
  695. case NMEA_GPGSV_SAT_INFO_NR2:
  696. data->sats[1].nr = atoi(value);
  697. break;
  698. case NMEA_GPGSV_SAT_INFO_ELEV2:
  699. data->sats[1].elevation = atoi(value);
  700. break;
  701. case NMEA_GPGSV_SAT_INFO_AZIMUTH2:
  702. data->sats[1].azimuth = atoi(value);
  703. break;
  704. case NMEA_GPGSV_SAT_INFO_SNR2:
  705. data->sats[1].snr = atoi(value);
  706. break;
  707. case NMEA_GPGSV_SAT_INFO_NR3:
  708. data->sats[2].nr = atoi(value);
  709. break;
  710. case NMEA_GPGSV_SAT_INFO_ELEV3:
  711. data->sats[2].elevation = atoi(value);
  712. break;
  713. case NMEA_GPGSV_SAT_INFO_AZIMUTH3:
  714. data->sats[2].azimuth = atoi(value);
  715. break;
  716. case NMEA_GPGSV_SAT_INFO_SNR3:
  717. data->sats[2].snr = atoi(value);
  718. break;
  719. case NMEA_GPGSV_SAT_INFO_NR4:
  720. data->sats[3].nr = atoi(value);
  721. break;
  722. case NMEA_GPGSV_SAT_INFO_ELEV4:
  723. data->sats[3].elevation = atoi(value);
  724. break;
  725. case NMEA_GPGSV_SAT_INFO_AZIMUTH4:
  726. data->sats[3].azimuth = atoi(value);
  727. break;
  728. case NMEA_GPGSV_SAT_INFO_SNR4:
  729. data->sats[3].snr = atoi(value);
  730. break;
  731. case NMEA_GPGSV_SAT_INFO_SIGID:
  732. if(nmea->sat_type == SAT_GPS)
  733. {
  734. data->sig_id = atoi(value);
  735. }
  736. break;
  737. default:
  738. break;
  739. }
  740. }
  741. nmea->data = data;
  742. return 0;
  743. }
  744. int nmea_parse_gga(struct nmea_s *nmea, char *sentence)
  745. {
  746. unsigned int n_vals=0, val_index=0;
  747. char *value=NULL;
  748. char *values[255]={NULL};
  749. struct nmea_gpgga_s *data = NULL;
  750. /* Split the sentence into values */
  751. n_vals = _split_string_by_comma(sentence, values, ARRAY_LENGTH(values));
  752. if (0 == n_vals)
  753. {
  754. return -1;
  755. }
  756. data = malloc(sizeof(struct nmea_gpgga_s));
  757. if (data == NULL)
  758. {
  759. nmea_dbg_log("gga nmea data malloc error. \r\n");
  760. return -1;
  761. }
  762. memset(data, 0, sizeof(struct nmea_gpgga_s));
  763. for (val_index = 0; val_index < n_vals; val_index++)
  764. {
  765. value = values[val_index];
  766. if (-1 == _is_value_set(value))
  767. {
  768. continue;
  769. }
  770. switch (val_index)
  771. {
  772. case NMEA_GPGGA_UTC:
  773. data->time = atof(value);
  774. break;
  775. case NMEA_GPGGA_LATITUDE:
  776. if (-1 == nmea_position_parse(value, &data->latitude))
  777. {
  778. goto _error;
  779. }
  780. break;
  781. case NMEA_GPGGA_LATITUDE_CARDINAL:
  782. data->latitude.cardinal = nmea_cardinal_direction_parse(value);
  783. if (NMEA_CARDINAL_DIR_UNKNOWN == data->latitude.cardinal)
  784. {
  785. goto _error;
  786. }
  787. break;
  788. case NMEA_GPGGA_LONGITUDE:
  789. if (-1 == nmea_position_parse(value, &data->longitude))
  790. {
  791. goto _error;
  792. }
  793. break;
  794. case NMEA_GPGGA_LONGITUDE_CARDINAL:
  795. data->longitude.cardinal = nmea_cardinal_direction_parse(value);
  796. if (NMEA_CARDINAL_DIR_UNKNOWN == data->longitude.cardinal)
  797. {
  798. goto _error;
  799. }
  800. break;
  801. case NMEA_GPGGA_QUALITY:
  802. data->quality = atoi(value);
  803. break;
  804. case NMEA_GPGGA_SATELLITES_TRACKED:
  805. data->satellites_tracked = atoi(value);
  806. break;
  807. case NMEA_GPGGA_HDOP:
  808. data->hdop = atof(value);
  809. break;
  810. case NMEA_GPGGA_ALTITUDE:
  811. data->altitude = atof(value);
  812. break;
  813. default:
  814. break;
  815. }
  816. }
  817. nmea->data = data;
  818. return 0;
  819. _error:
  820. if (data)
  821. {
  822. free(data);
  823. data = NULL;
  824. }
  825. return -1;
  826. }
  827. int nmea_parse_gsa(struct nmea_s *nmea, char *sentence)
  828. {
  829. unsigned int n_vals=0, val_index=0;
  830. char *value=NULL;
  831. char *values[255]={NULL};
  832. struct nmea_gpgsa_s *data = NULL;
  833. /* Split the sentence into values */
  834. n_vals = _split_string_by_comma(sentence, values, ARRAY_LENGTH(values));
  835. if (0 == n_vals)
  836. {
  837. return -1;
  838. }
  839. data = malloc(sizeof(struct nmea_gpgsa_s));
  840. if (data == NULL)
  841. {
  842. nmea_dbg_log("gsa nmea data malloc error. \r\n");
  843. return -1;
  844. }
  845. memset(data, 0, sizeof(struct nmea_gpgsa_s));
  846. for (val_index = 0; val_index < n_vals; val_index++)
  847. {
  848. value = values[val_index];
  849. if (-1 == _is_value_set(value))
  850. {
  851. continue;
  852. }
  853. switch (val_index)
  854. {
  855. case NMEA_GPGSA_MODE:
  856. data->mode = *value;
  857. break;
  858. case NMEA_GPGSA_NAVMODE:
  859. data->navmode = atoi(value);
  860. break;
  861. case NMEA_GPGSA_PDOP:
  862. data->pdop = atof(value);
  863. break;
  864. case NMEA_GPGSA_HDOP:
  865. data->hdop = atof(value);
  866. break;
  867. case NMEA_GPGSA_VDOP:
  868. data->vdop = atof(value);
  869. break;
  870. case NMEA_GPGSA_systemID:
  871. data->systemid = atoi(value);
  872. default:
  873. break;
  874. }
  875. }
  876. nmea->data = data;
  877. return 0;
  878. }
  879. satellite_type nmea_satellite_check(char *sentence)
  880. {
  881. if (strncmp(sentence + 1, "GP", 2) == 0)
  882. {
  883. return SAT_GPS;
  884. }
  885. else if ((strncmp(sentence + 1, "GB", 2) == 0)||(strncmp(sentence + 1, "BD", 2) == 0))
  886. {
  887. memcpy(sentence+1,"PQ",2);
  888. return SAT_BDS;
  889. }
  890. else if (strncmp(sentence + 1, "GN", 2) == 0)
  891. {
  892. return SAT_MULSYS;
  893. }
  894. else if (strncmp(sentence + 1, "GA", 2) == 0)
  895. {
  896. return SAT_GALILEO;
  897. }
  898. else if (strncmp(sentence + 1, "GL", 2) == 0)
  899. {
  900. return SAT_GLONASS;
  901. }
  902. return SAT_UNKNOWN;
  903. }
  904. static int conv_num(const char **buf, int *dest, int llim, int ulim)
  905. {
  906. int result = 0;
  907. /* The limit also determines the number of valid digits. */
  908. int rulim = ulim;
  909. if (**buf < '0' || **buf > '9')
  910. return (0);
  911. do {
  912. result *= 10;
  913. result += *(*buf)++ - '0';
  914. rulim /= 10;
  915. } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
  916. if (result < llim || result > ulim)
  917. return (0);
  918. *dest = result;
  919. return (1);
  920. }
  921. //window上自己实现strptime函数,linux已经提供strptime
  922. //strptime函数windows平台上实现
  923. char *strptime(const char *buf, const char *fmt, struct tm *tm)
  924. {
  925. char c=0;
  926. const char *bp=NULL;
  927. size_t len = 0;
  928. int alt_format=0, i=0, split_year = 0;
  929. bp = buf;
  930. while ((c = *fmt) != '\0') {
  931. /* Clear `alternate' modifier prior to new conversion. */
  932. alt_format = 0;
  933. /* Eat up white-space. */
  934. if (ql_isspace(c)) {
  935. while (ql_isspace(*bp))
  936. bp++;
  937. fmt++;
  938. continue;
  939. }
  940. if ((c = *fmt++) != '%')
  941. goto literal;
  942. again: switch (c = *fmt++) {
  943. case '%': /* "%%" is converted to "%". */
  944. literal:
  945. if (c != *bp++)
  946. return (0);
  947. break;
  948. /*
  949. * "Alternative" modifiers. Just set the appropriate flag
  950. * and start over again.
  951. */
  952. case 'E': /* "%E?" alternative conversion modifier. */
  953. LEGAL_ALT(0);
  954. alt_format |= ALT_E;
  955. goto again;
  956. case 'O': /* "%O?" alternative conversion modifier. */
  957. LEGAL_ALT(0);
  958. alt_format |= ALT_O;
  959. goto again;
  960. /*
  961. * "Complex" conversion rules, implemented through recursion.
  962. */
  963. case 'c': /* Date and time, using the locale's format. */
  964. LEGAL_ALT(ALT_E);
  965. if (!(bp = strptime(bp, "%x %X", tm)))
  966. return (0);
  967. break;
  968. case 'D': /* The date as "%m/%d/%y". */
  969. LEGAL_ALT(0);
  970. if (!(bp = strptime(bp, "%m/%d/%y", tm)))
  971. return (0);
  972. break;
  973. case 'R': /* The time as "%H:%M". */
  974. LEGAL_ALT(0);
  975. if (!(bp = strptime(bp, "%H:%M", tm)))
  976. return (0);
  977. break;
  978. case 'r': /* The time in 12-hour clock representation. */
  979. LEGAL_ALT(0);
  980. if (!(bp = strptime(bp, "%I:%M:%S %p", tm)))
  981. return (0);
  982. break;
  983. case 'T': /* The time as "%H:%M:%S". */
  984. LEGAL_ALT(0);
  985. if (!(bp = strptime(bp, "%H:%M:%S", tm)))
  986. return (0);
  987. break;
  988. case 'X': /* The time, using the locale's format. */
  989. LEGAL_ALT(ALT_E);
  990. if (!(bp = strptime(bp, "%H:%M:%S", tm)))
  991. return (0);
  992. break;
  993. case 'x': /* The date, using the locale's format. */
  994. LEGAL_ALT(ALT_E);
  995. if (!(bp = strptime(bp, "%m/%d/%y", tm)))
  996. return (0);
  997. break;
  998. /*
  999. * "Elementary" conversion rules.
  1000. */
  1001. case 'A': /* The day of week, using the locale's form. */
  1002. case 'a':
  1003. LEGAL_ALT(0);
  1004. for (i = 0; i < 7; i++) {
  1005. /* Full name. */
  1006. len = strlen(day[i]);
  1007. if (strncmp(day[i], bp, len) == 0)
  1008. break;
  1009. /* Abbreviated name. */
  1010. len = strlen(abday[i]);
  1011. if (strncmp(abday[i], bp, len) == 0)
  1012. break;
  1013. }
  1014. /* Nothing matched. */
  1015. if (i == 7)
  1016. return (0);
  1017. tm->tm_wday = i;
  1018. bp += len;
  1019. break;
  1020. case 'B': /* The month, using the locale's form. */
  1021. case 'b':
  1022. case 'h':
  1023. LEGAL_ALT(0);
  1024. for (i = 0; i < 12; i++) {
  1025. /* Full name. */
  1026. len = strlen(mon[i]);
  1027. if (strncmp(mon[i], bp, len) == 0)
  1028. break;
  1029. /* Abbreviated name. */
  1030. len = strlen(abmon[i]);
  1031. if (strncmp(abmon[i], bp, len) == 0)
  1032. break;
  1033. }
  1034. /* Nothing matched. */
  1035. if (i == 12)
  1036. return (0);
  1037. tm->tm_mon = i;
  1038. bp += len;
  1039. break;
  1040. case 'C': /* The century number. */
  1041. LEGAL_ALT(ALT_E);
  1042. if (!(conv_num(&bp, &i, 0, 99)))
  1043. return (0);
  1044. if (split_year) {
  1045. tm->tm_year = (tm->tm_year % 100) + (i * 100);
  1046. } else {
  1047. tm->tm_year = i * 100;
  1048. split_year = 1;
  1049. }
  1050. break;
  1051. case 'd': /* The day of month. */
  1052. case 'e':
  1053. LEGAL_ALT(ALT_O);
  1054. if (!(conv_num(&bp, &tm->tm_mday, 1, 31)))
  1055. return (0);
  1056. break;
  1057. case 'k': /* The hour (24-hour clock representation). */
  1058. LEGAL_ALT(0);
  1059. /* FALLTHROUGH */
  1060. case 'H':
  1061. LEGAL_ALT(ALT_O);
  1062. if (!(conv_num(&bp, &tm->tm_hour, 0, 23)))
  1063. return (0);
  1064. break;
  1065. case 'l': /* The hour (12-hour clock representation). */
  1066. LEGAL_ALT(0);
  1067. /* FALLTHROUGH */
  1068. case 'I':
  1069. LEGAL_ALT(ALT_O);
  1070. if (!(conv_num(&bp, &tm->tm_hour, 1, 12)))
  1071. return (0);
  1072. if (tm->tm_hour == 12)
  1073. tm->tm_hour = 0;
  1074. break;
  1075. case 'j': /* The day of year. */
  1076. LEGAL_ALT(0);
  1077. if (!(conv_num(&bp, &i, 1, 366)))
  1078. return (0);
  1079. tm->tm_yday = i - 1;
  1080. break;
  1081. case 'M': /* The minute. */
  1082. LEGAL_ALT(ALT_O);
  1083. if (!(conv_num(&bp, &tm->tm_min, 0, 59)))
  1084. return (0);
  1085. break;
  1086. case 'm': /* The month. */
  1087. LEGAL_ALT(ALT_O);
  1088. if (!(conv_num(&bp, &i, 1, 12)))
  1089. return (0);
  1090. tm->tm_mon = i - 1;
  1091. break;
  1092. case 'p': /* The locale's equivalent of AM/PM. */
  1093. LEGAL_ALT(0);
  1094. /* AM? */
  1095. if (strcmp(am_pm[0], bp) == 0) {
  1096. if (tm->tm_hour > 11)
  1097. return (0);
  1098. bp += strlen(am_pm[0]);
  1099. break;
  1100. }
  1101. /* PM? */
  1102. else if (strcmp(am_pm[1], bp) == 0) {
  1103. if (tm->tm_hour > 11)
  1104. return (0);
  1105. tm->tm_hour += 12;
  1106. bp += strlen(am_pm[1]);
  1107. break;
  1108. }
  1109. /* Nothing matched. */
  1110. return (0);
  1111. case 'S': /* The seconds. */
  1112. LEGAL_ALT(ALT_O);
  1113. if (!(conv_num(&bp, &tm->tm_sec, 0, 61)))
  1114. return (0);
  1115. break;
  1116. case 'U': /* The week of year, beginning on sunday. */
  1117. case 'W': /* The week of year, beginning on monday. */
  1118. LEGAL_ALT(ALT_O);
  1119. /*
  1120. * XXX This is bogus, as we can not assume any valid
  1121. * information present in the tm structure at this
  1122. * point to calculate a real value, so just check the
  1123. * range for now.
  1124. */
  1125. if (!(conv_num(&bp, &i, 0, 53)))
  1126. return (0);
  1127. break;
  1128. case 'w': /* The day of week, beginning on sunday. */
  1129. LEGAL_ALT(ALT_O);
  1130. if (!(conv_num(&bp, &tm->tm_wday, 0, 6)))
  1131. return (0);
  1132. break;
  1133. case 'Y': /* The year. */
  1134. LEGAL_ALT(ALT_E);
  1135. if (!(conv_num(&bp, &i, 0, 9999)))
  1136. return (0);
  1137. tm->tm_year = i - TM_YEAR_BASE;
  1138. break;
  1139. case 'y': /* The year within 100 years of the epoch. */
  1140. LEGAL_ALT(ALT_E | ALT_O);
  1141. if (!(conv_num(&bp, &tm->tm_year, 0, 99)))
  1142. return (0);
  1143. // if (split_year) {
  1144. // tm->tm_year = ((tm->tm_year / 100) * 100) + i;
  1145. // break;
  1146. // }
  1147. // split_year = 1;
  1148. // if (i <= 68)
  1149. // tm->tm_year = i + 2000 - TM_YEAR_BASE;
  1150. // else
  1151. // tm->tm_year = i + 1900 - TM_YEAR_BASE;
  1152. // break;
  1153. /*
  1154. * Miscellaneous conversions.
  1155. */
  1156. case 'n': /* Any kind of white-space. */
  1157. case 't':
  1158. LEGAL_ALT(0);
  1159. while (ql_isspace(*bp))
  1160. bp++;
  1161. break;
  1162. default: /* Unknown/unsupported conversion. */
  1163. return (0);
  1164. }
  1165. }
  1166. /* LINTED functional specification */
  1167. return ((char *)bp);
  1168. }
  1169. int nmea_value_update(struct nmea_s *nmea, ql_gnss_data_t *gps_data)
  1170. {
  1171. int i=0;
  1172. struct nmea_gprmc_s *rmc = NULL;
  1173. struct nmea_gpgsv_s *gsv = NULL;
  1174. struct nmea_gpgga_s *gga = NULL;
  1175. struct nmea_gpgsa_s *gsa = NULL;
  1176. if(nmea == NULL || gps_data == NULL)
  1177. {
  1178. nmea_dbg_log("param invalid. \r\n");
  1179. return -1;
  1180. }
  1181. if(nmea->type == NMEA_UNKNOWN)
  1182. {
  1183. nmea_dbg_log("gps nmea type is unknown! \r\n");
  1184. return -1;
  1185. }
  1186. switch(nmea->type)
  1187. {
  1188. case NMEA_RMC:
  1189. rmc = (struct nmea_gprmc_s*)nmea->data;
  1190. if(rmc)
  1191. {
  1192. gps_data->valid = rmc->valid;
  1193. if(gps_data->valid==1)
  1194. {
  1195. //nmea_dbg_log("GNSS_FIX \r\n");
  1196. }
  1197. else
  1198. {
  1199. //nmea_dbg_log("GNSS_POSITIONING \r\n");
  1200. }
  1201. gps_data->longitude = rmc->longitude.degrees + (rmc->longitude.minutes / 60);
  1202. gps_data->longitude_cardinal = rmc->longitude.cardinal;
  1203. gps_data->latitude = rmc->latitude.degrees + (rmc->latitude.minutes / 60);
  1204. gps_data->latitude_cardinal = rmc->latitude.cardinal;
  1205. gps_data->heading = rmc->course;
  1206. gps_data->gps_speed = rmc->speed * KNOTS_CONVERSION_FACTOR;
  1207. gps_data->time.tm_year = rmc->time.tm_year;
  1208. gps_data->time.tm_mon = rmc->time.tm_mon+1;
  1209. gps_data->time.tm_mday = rmc->time.tm_mday;
  1210. gps_data->time.tm_hour = rmc->time.tm_hour;
  1211. gps_data->time.tm_min = rmc->time.tm_min;
  1212. gps_data->time.tm_sec = rmc->time.tm_sec;
  1213. }
  1214. break;
  1215. case NMEA_GSV:
  1216. gsv = (struct nmea_gpgsv_s*)nmea->data;
  1217. if(gsv)
  1218. {
  1219. unsigned int cnr_value = 0;
  1220. static unsigned int total_cnr = 0;
  1221. static unsigned int snr_num = 0;
  1222. static unsigned int max_cnr = 0;
  1223. static unsigned int min_cnr = 0;
  1224. if((prev_ms_gsv < ql_rtos_get_system_tick()) && ((tick_overflow == FALSE) || (((MAX_UINT32 - ql_rtos_get_system_tick())>10))))
  1225. {
  1226. gps_data->avg_cnr = total_cnr / snr_num;
  1227. gps_data->max_cnr=max_cnr;
  1228. gps_data->min_cnr=min_cnr;
  1229. gps_data->cnrs_index=snr_num;
  1230. total_cnr=0;
  1231. snr_num=0;
  1232. max_cnr=0;
  1233. min_cnr=0;
  1234. }
  1235. for(i = 0; i < gsv->cur_sats; i++)
  1236. {
  1237. cnr_value = gsv->sats[i].snr;
  1238. gps_data->cnrs[snr_num]=cnr_value;
  1239. max_cnr = jmax(max_cnr, cnr_value);
  1240. if(cnr_value > 0)
  1241. {
  1242. min_cnr = min_cnr > 0 ? (jmin(min_cnr, cnr_value)) : (cnr_value);
  1243. }
  1244. total_cnr += cnr_value;
  1245. if(snr_num<(QL_GSV_MAX_SATS-1))
  1246. {
  1247. snr_num ++;
  1248. }
  1249. }
  1250. prev_ms_gsv=ql_rtos_get_system_tick()+10;
  1251. if(prev_ms_gsv < 10)
  1252. {
  1253. tick_overflow = TRUE;
  1254. }
  1255. else
  1256. {
  1257. tick_overflow = FALSE;
  1258. }
  1259. }
  1260. break;
  1261. case NMEA_GGA:
  1262. gga = (struct nmea_gpgga_s*)nmea->data;
  1263. if(gga != NULL)
  1264. {
  1265. gps_data->UTC = (unsigned int)(gga->time);
  1266. gps_data->altitude = gga->altitude;
  1267. gps_data->satellites_num=gga->satellites_tracked;
  1268. }
  1269. break;
  1270. case NMEA_GSA:
  1271. gsa = (struct nmea_gpgsa_s*)nmea->data;
  1272. if(gsa != NULL)
  1273. {
  1274. gps_data->navmode = gsa->navmode;
  1275. gps_data->hdop = gsa->hdop;
  1276. gps_data->pdop = gsa->pdop;
  1277. }
  1278. break;
  1279. default:
  1280. break;
  1281. }
  1282. return 0;
  1283. }
  1284. struct nmea_s* nmea_parse(char *sentence, int length, int check_checksum)
  1285. {
  1286. int ret = -1;
  1287. nmea_type type = 0;
  1288. char *val_string = NULL;
  1289. struct nmea_s * nmea = NULL;
  1290. satellite_type sat_type = 0;
  1291. /* Validate sentence string */
  1292. if (-1 == nmea_validate(sentence, length, check_checksum))
  1293. {
  1294. nmea_dbg_log("nmea validate false! \r\n");
  1295. return NULL;
  1296. }
  1297. type = nmea_get_type(sentence);
  1298. if (NMEA_UNKNOWN == type)
  1299. {
  1300. nmea_dbg_log("nmea get type unknown! \r\n");
  1301. return NULL;
  1302. }
  1303. sat_type = nmea_satellite_check(sentence);
  1304. nmea = malloc(sizeof(struct nmea_s));
  1305. if(nmea == NULL)
  1306. {
  1307. nmea_dbg_log("nmea malloc error. \r\n");
  1308. return NULL;
  1309. }
  1310. memset(nmea, 0, sizeof(struct nmea_s));
  1311. nmea->type = type;
  1312. nmea->sat_type = sat_type;
  1313. /* Crop sentence from type word and checksum */
  1314. val_string = _crop_sentence(sentence, length);
  1315. if (NULL == val_string) {
  1316. if(nmea)
  1317. {
  1318. if(nmea->data)
  1319. {
  1320. free(nmea->data);
  1321. }
  1322. free(nmea);
  1323. nmea = NULL;
  1324. }
  1325. nmea_dbg_log("_crop_sentence failed! \r\n");
  1326. return NULL;
  1327. }
  1328. switch(type)
  1329. {
  1330. case NMEA_GGA:
  1331. {
  1332. ret = nmea_parse_gga(nmea, val_string);
  1333. if(ret)
  1334. {
  1335. nmea_dbg_log("nmea_parse_gga failed. \r\n");
  1336. goto _error;
  1337. }
  1338. }
  1339. break;
  1340. case NMEA_GSA:
  1341. {
  1342. ret = nmea_parse_gsa(nmea, val_string);
  1343. if(ret)
  1344. {
  1345. nmea_dbg_log("nmea_parse_gsa failed. \r\n");
  1346. goto _error;
  1347. }
  1348. }
  1349. break;
  1350. case NMEA_GSV:
  1351. {
  1352. ret = nmea_parse_gsv(nmea, val_string);
  1353. if(ret)
  1354. {
  1355. nmea_dbg_log("nmea_parse_gsv failed. \r\n");
  1356. goto _error;
  1357. }
  1358. }
  1359. break;
  1360. case NMEA_RMC:
  1361. {
  1362. ret = nmea_parse_rmc(nmea, val_string);
  1363. if(ret)
  1364. {
  1365. nmea_dbg_log("nmea_parse_rmc failed. \r\n");
  1366. goto _error;
  1367. }
  1368. }
  1369. break;
  1370. #if 0
  1371. case NMEA_TXT:
  1372. {
  1373. ret = nmea_parse_txt(nmea, val_string);
  1374. if(ret)
  1375. {
  1376. nmea_dbg_log("nmea_parse_txt failed. \r\n");
  1377. goto _error;
  1378. }
  1379. }
  1380. #endif
  1381. default:
  1382. break;
  1383. }
  1384. return nmea;
  1385. _error:
  1386. if(nmea)
  1387. {
  1388. if(nmea->data)
  1389. {
  1390. free(nmea->data);
  1391. }
  1392. free(nmea);
  1393. nmea = NULL;
  1394. }
  1395. return NULL;
  1396. }
  1397. int ql_get_gnss_info(ql_gnss_data_t *data)
  1398. {
  1399. if(data == NULL)
  1400. {
  1401. return -1;
  1402. }
  1403. memcpy(data, &g_gps_data, sizeof(g_gps_data));
  1404. return 0;
  1405. }