luat_lib_libgnss.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*
  2. @module libgnss
  3. @summary NMEA数据处理
  4. @version 1.0
  5. @date 2020.07.03
  6. */
  7. #include "luat_base.h"
  8. #include "luat_msgbus.h"
  9. #include "luat_malloc.h"
  10. #include "luat_uart.h"
  11. #define LUAT_LOG_TAG "luat.gnss"
  12. #include "luat_log.h"
  13. #include "minmea.h"
  14. typedef struct luat_libgnss
  15. {
  16. uint8_t debug;
  17. uint8_t prev_fixed;
  18. // int lua_ref;
  19. struct minmea_sentence_rmc frame_rmc;
  20. struct minmea_sentence_gga frame_gga;
  21. struct minmea_sentence_gsv frame_gsv[3];
  22. struct minmea_sentence_vtg frame_vtg;
  23. struct minmea_sentence_gsa frame_gsa;
  24. } luat_libgnss_t;
  25. static luat_libgnss_t *gnss = NULL;
  26. static luat_libgnss_t *gnsstmp = NULL;
  27. static int luat_libgnss_init(lua_State *L) {
  28. if (gnss == NULL) {
  29. gnss = luat_heap_malloc(sizeof(luat_libgnss_t));
  30. if (gnss == NULL) {
  31. LLOGW("out of memory for libgnss data parse");
  32. return 0;
  33. }
  34. gnsstmp = luat_heap_malloc(sizeof(luat_libgnss_t));
  35. if (gnsstmp == NULL) {
  36. luat_heap_free(gnss);
  37. LLOGW("out of memory for libgnss data parse");
  38. return 0;
  39. }
  40. // gnss->lua_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  41. memset(gnss, 0, sizeof(luat_libgnss_t));
  42. memset(gnsstmp, 0, sizeof(luat_libgnss_t));
  43. }
  44. lua_pushboolean(L, 1);
  45. return 1;
  46. }
  47. static int parse_nmea(const char* line, lua_State *L) {
  48. // $GNRMC,080313.00,A,2324.40756,N,11313.86184,E,0.284,,010720,,,A*68
  49. //if (gnss != NULL && gnss->debug)
  50. // LLOGD("GNSS [%s]", line);
  51. if (gnss == NULL && luat_libgnss_init(L)) {
  52. return 0;
  53. }
  54. switch (minmea_sentence_id(line, false)) {
  55. case MINMEA_SENTENCE_RMC: {
  56. if (minmea_parse_rmc(&(gnsstmp->frame_rmc), line)) {
  57. if (gnsstmp->frame_rmc.valid) {
  58. memcpy(&(gnss->frame_rmc), &gnsstmp->frame_rmc, sizeof(struct minmea_sentence_rmc));
  59. }
  60. else {
  61. gnss->frame_rmc.valid = 0;
  62. if (gnsstmp->frame_rmc.date.year > 0) {
  63. memcpy(&(gnss->frame_rmc.date), &(gnsstmp->frame_rmc.date), sizeof(struct minmea_date));
  64. }
  65. if (gnsstmp->frame_rmc.time.hours > 0) {
  66. memcpy(&(gnss->frame_rmc.time), &(gnsstmp->frame_rmc.time), sizeof(struct minmea_time));
  67. }
  68. }
  69. //memcpy(&(gnss->frame_rmc), &frame_rmc, sizeof(struct minmea_sentence_rmc));
  70. //LLOGD("RMC %s", line);
  71. //LLOGD("RMC isFix(%d) Lat(%ld) Lng(%ld)", gnss->frame_rmc.valid, gnss->frame_rmc.latitude.value, gnss->frame_rmc.longitude.value);
  72. // if (prev_gnss_fixed != gnss->frame_rmc.valid) {
  73. // lua_getglobal(L, "sys_pub");
  74. // if (lua_isfunction(L, -1)) {
  75. // lua_pushliteral(L, "GPS_STATE");
  76. // lua_pushstring(L, gnss->frame_rmc.valid ? "LOCATION_SUCCESS" : "LOCATION_FAIL");
  77. // lua_call(L, 2, 0);
  78. // }
  79. // else {
  80. // lua_pop(L, 1);
  81. // }
  82. // prev_gnss_fixed = gnss->frame_rmc.valid;
  83. // }
  84. }
  85. } break;
  86. case MINMEA_SENTENCE_GGA: {
  87. //struct minmea_sentence_gga frame_gga;
  88. if (minmea_parse_gga(&gnsstmp->frame_gga, line)) {
  89. memcpy(&(gnss->frame_gga), &gnsstmp->frame_gga, sizeof(struct minmea_sentence_gga));
  90. //LLOGD("$GGA: fix quality: %d", frame_gga.fix_quality);
  91. }
  92. } break;
  93. case MINMEA_SENTENCE_GSV: {
  94. if (minmea_parse_gsv(&gnsstmp->frame_gsv[0], line)) {
  95. switch (gnsstmp->frame_gsv[0].msg_nr)
  96. {
  97. case 1:
  98. memset(&(gnss->frame_gsv), 0, sizeof(struct minmea_sentence_gsv) * 3);
  99. case 2:
  100. case 3:
  101. memcpy(&(gnss->frame_gsv[gnsstmp->frame_gsv[0].msg_nr - 1]), &gnsstmp->frame_gsv, sizeof(struct minmea_sentence_gsv));
  102. break;
  103. default:
  104. break;
  105. }
  106. // LLOGD("$GSV: message %d of %d", frame_gsv.msg_nr, frame_gsv.total_msgs);
  107. // LLOGD("$GSV: sattelites in view: %d", frame_gsv.total_sats);
  108. // for (int i = 0; i < 4; i++)
  109. // LLOGD("$GSV: sat nr %d, elevation: %d, azimuth: %d, snr: %d dbm",
  110. // frame_gsv.sats[i].nr,
  111. // frame_gsv.sats[i].elevation,
  112. // frame_gsv.sats[i].azimuth,
  113. // frame_gsv.sats[i].snr);
  114. }
  115. } break;
  116. case MINMEA_SENTENCE_GSA: {
  117. //struct minmea_sentence_gsa frame_gsa;
  118. if (minmea_parse_gsa(&(gnss->frame_gsa), line)) {
  119. //memcpy(&(gnss->frame_gsa), &frame_gsa, sizeof(struct minmea_sentence_gsa));
  120. }
  121. } break;
  122. case MINMEA_SENTENCE_VTG: {
  123. //struct minmea_sentence_vtg frame_vtg;
  124. if (minmea_parse_vtg(&(gnsstmp->frame_vtg), line)) {
  125. memcpy(&(gnss->frame_vtg), &gnsstmp->frame_vtg, sizeof(struct minmea_sentence_vtg));
  126. //--------------------------------------
  127. // 暂时不发GPS_MSG_REPORT
  128. // lua_getglobal(L, "sys_pub");
  129. // if (lua_isfunction(L, -1)) {
  130. // lua_pushstring(L, "GPS_MSG_REPORT");
  131. // lua_call(L, 1, 0);
  132. // }
  133. // else {
  134. // lua_pop(L, 1);
  135. // }
  136. //--------------------------------------
  137. }
  138. } break;
  139. default:
  140. break;
  141. }
  142. return 0;
  143. }
  144. /**
  145. 处理nmea数据
  146. @api libgnss.parse(str)
  147. @string 原始nmea数据
  148. @usage
  149. -- 解析nmea
  150. libgnss.parse(indata)
  151. log.info("nmea", json.encode(libgnss.getRmc()))
  152. */
  153. static int l_libgnss_parse(lua_State *L) {
  154. size_t len = 0;
  155. const char* str = luaL_checklstring(L, 1, &len);
  156. if (len == 0) {
  157. return 0;
  158. }
  159. char buff[85] = {0}; // nmea 最大长度82,含换行符
  160. char *ptr = (char*)str;
  161. size_t prev = 0;
  162. for (size_t i = 1; i < len; i++)
  163. {
  164. if (*(ptr + i) == 0x0A) {
  165. if (i - prev > 10 && i - prev < 82) {
  166. memcpy(buff, ptr + prev, i - prev - 1);
  167. if (buff[0] == '$') {
  168. buff[i - prev - 1] = 0; // 确保结束符存在
  169. parse_nmea((const char*)buff, L);
  170. }
  171. }
  172. i ++;
  173. prev = i;
  174. }
  175. }
  176. return 0;
  177. }
  178. /**
  179. 当前是否已经定位成功
  180. @api libgnss.isFix()
  181. @return boolean 定位成功与否
  182. @usage
  183. -- 解析nmea
  184. libgnss.parse(indata)
  185. log.info("nmea", "isFix", libgnss.isFix())
  186. */
  187. static int l_libgnss_is_fix(lua_State *L) {
  188. if (gnss == NULL) {
  189. lua_pushboolean(L, 0);
  190. }
  191. else
  192. lua_pushboolean(L, gnss->frame_rmc.valid != 0 ? 1 : 0);
  193. return 1;
  194. }
  195. /**
  196. 获取位置信息
  197. @api libgnss.getIntLocation()
  198. @return int lat数据, 格式为 ddmmmmmmm
  199. @return int lng数据, 格式为 ddmmmmmmm
  200. @return int speed数据
  201. @usage
  202. -- 解析nmea
  203. libgnss.parse(indata)
  204. log.info("nmea", "loc", libgnss.getIntLocation())
  205. */
  206. static int l_libgnss_get_int_location(lua_State *L) {
  207. if (gnss != NULL && gnss->frame_rmc.valid) {
  208. lua_pushinteger(L, gnss->frame_rmc.latitude.value);
  209. lua_pushinteger(L, gnss->frame_rmc.longitude.value);
  210. lua_pushinteger(L, gnss->frame_rmc.speed.value);
  211. } else {
  212. lua_pushinteger(L, 0);
  213. lua_pushinteger(L, 0);
  214. lua_pushinteger(L, 0);
  215. }
  216. return 3;
  217. }
  218. /**
  219. 获取原始RMC位置信息
  220. @api libgnss.getRmc()
  221. @return table 原始rmc数据
  222. @usage
  223. -- 解析nmea
  224. libgnss.parse(indata)
  225. log.info("nmea", "rmc", json.encode(libgnss.getRmc()))
  226. */
  227. static int l_libgnss_get_rmc(lua_State *L) {
  228. lua_createtable(L, 0, 12);
  229. if (gnss != NULL) {
  230. lua_pushliteral(L, "valid");
  231. lua_pushboolean(L, gnss->frame_rmc.valid);
  232. lua_settable(L, -3);
  233. lua_pushliteral(L, "lat");
  234. lua_pushinteger(L, gnss->frame_rmc.latitude.value);
  235. lua_settable(L, -3);
  236. lua_pushliteral(L, "lng");
  237. lua_pushinteger(L, gnss->frame_rmc.longitude.value);
  238. lua_settable(L, -3);
  239. lua_pushliteral(L, "speed");
  240. lua_pushinteger(L, gnss->frame_rmc.speed.value);
  241. lua_settable(L, -3);
  242. lua_pushliteral(L, "course");
  243. lua_pushinteger(L, gnss->frame_rmc.course.value);
  244. lua_settable(L, -3);
  245. lua_pushliteral(L, "variation");
  246. lua_pushinteger(L, gnss->frame_rmc.variation.value);
  247. lua_settable(L, -3);
  248. lua_pushliteral(L, "year");
  249. lua_pushinteger(L, gnss->frame_rmc.date.year + 2000);
  250. lua_settable(L, -3);
  251. lua_pushliteral(L, "month");
  252. lua_pushinteger(L, gnss->frame_rmc.date.month);
  253. lua_settable(L, -3);
  254. lua_pushliteral(L, "day");
  255. lua_pushinteger(L, gnss->frame_rmc.date.day);
  256. lua_settable(L, -3);
  257. lua_pushliteral(L, "hour");
  258. lua_pushinteger(L, gnss->frame_rmc.time.hours);
  259. lua_settable(L, -3);
  260. lua_pushliteral(L, "min");
  261. lua_pushinteger(L, gnss->frame_rmc.time.minutes);
  262. lua_settable(L, -3);
  263. lua_pushliteral(L, "sec");
  264. lua_pushinteger(L, gnss->frame_rmc.time.seconds);
  265. lua_settable(L, -3);
  266. }
  267. return 1;
  268. }
  269. /**
  270. 获取原始GSV信息
  271. @api libgnss.getGsv()
  272. @return table 原始GSV数据
  273. @usage
  274. -- 解析nmea
  275. libgnss.parse(indata)
  276. log.info("nmea", "gsv", json.encode(libgnss.getGsv()))
  277. */
  278. static int l_libgnss_get_gsv(lua_State *L) {
  279. lua_createtable(L, 0, 2);
  280. if (gnss != NULL) {
  281. int count = 1;
  282. lua_pushliteral(L, "total_sats");
  283. lua_pushinteger(L, gnss->frame_gsv[0].total_sats);
  284. lua_settable(L, -3);
  285. lua_pushliteral(L, "sats");
  286. lua_createtable(L, 12, 0);
  287. for (size_t i = 0; i < gnss->frame_gsv[0].msg_nr; i++)
  288. {
  289. for (size_t j = 0; j < 4; j++)
  290. {
  291. if (gnss->frame_gsv[i].sats[j].snr) {
  292. lua_pushinteger(L, count++);
  293. lua_createtable(L, 0, 3);
  294. lua_pushliteral(L, "snr");
  295. lua_pushinteger(L, gnss->frame_gsv[i].sats[j].snr);
  296. lua_settable(L, -3);
  297. lua_pushliteral(L, "elevation");
  298. lua_pushinteger(L, gnss->frame_gsv[i].sats[j].elevation);
  299. lua_settable(L, -3);
  300. lua_pushliteral(L, "azimuth");
  301. lua_pushinteger(L, gnss->frame_gsv[i].sats[j].azimuth);
  302. lua_settable(L, -3);
  303. lua_settable(L, -3);
  304. }
  305. }
  306. }
  307. lua_settable(L, -3);
  308. }
  309. return 1;
  310. }
  311. /**
  312. 获取原始GSA信息
  313. @api libgnss.getGsa()
  314. @return table 原始GSA数据
  315. @usage
  316. -- 解析nmea
  317. libgnss.parse(indata)
  318. log.info("nmea", "gsa", json.encode(libgnss.getGsa()))
  319. */
  320. static int l_libgnss_get_gsa(lua_State *L) {
  321. lua_createtable(L, 0, 10);
  322. //lua_pushliteral(L, "mode");
  323. //lua_pushlstring(L, gnss ? &(gnss->frame_gsa.mode) : "N", 1);
  324. //lua_settable(L, -3);
  325. lua_pushliteral(L, "fix_type");
  326. lua_pushinteger(L, gnss ? gnss->frame_gsa.fix_type : 0);
  327. lua_settable(L, -3);
  328. lua_pushliteral(L, "pdop");
  329. lua_pushinteger(L, gnss ? gnss->frame_gsa.pdop.value : 0);
  330. lua_settable(L, -3);
  331. lua_pushliteral(L, "hdop");
  332. lua_pushinteger(L, gnss ? gnss->frame_gsa.hdop.value : 0);
  333. lua_settable(L, -3);
  334. lua_pushliteral(L, "vdop");
  335. lua_pushinteger(L, gnss ? gnss->frame_gsa.vdop.value : 0);
  336. lua_settable(L, -3);
  337. lua_pushliteral(L, "sats");
  338. lua_createtable(L, 12, 0);
  339. if (gnss != NULL) {
  340. for (size_t i = 0; i < 12; i++) {
  341. if (gnss->frame_gsa.sats[i] == 0) break;
  342. lua_pushinteger(L, i + 1);
  343. lua_pushinteger(L, gnss->frame_gsa.sats[i]);
  344. lua_settable(L, -3);
  345. }
  346. }
  347. {
  348. //if (gnss != NULL && gnss->frame_gsa.sats[i]) {
  349. // lua_pushinteger(L, i + 1);
  350. // lua_pushinteger(L, gnss->frame_gsa.sats[i]);
  351. // lua_settable(L, -3);
  352. //}
  353. //else {
  354. // break;
  355. //}
  356. }
  357. lua_settable(L, -3);
  358. return 1;
  359. }
  360. /**
  361. 获取原始VTA位置信息
  362. @api libgnss.getVtg()
  363. @return table 原始VTA数据
  364. @usage
  365. -- 解析nmea
  366. libgnss.parse(indata)
  367. log.info("nmea", "vtg", json.encode(libgnss.getVtg()))
  368. */
  369. static int l_libgnss_get_vtg(lua_State *L) {
  370. lua_createtable(L, 0, 10);
  371. //lua_pushliteral(L, "faa_mode");
  372. //lua_pushlstring(L, gnss ? &(gnss->frame_vtg.faa_mode) : 'N', 1);
  373. //lua_settable(L, -3);
  374. lua_pushliteral(L, "true_track_degrees");
  375. lua_pushinteger(L, gnss ? gnss->frame_vtg.true_track_degrees.value : 0);
  376. lua_settable(L, -3);
  377. lua_pushliteral(L, "magnetic_track_degrees");
  378. lua_pushinteger(L, gnss ? gnss->frame_vtg.magnetic_track_degrees.value : 0);
  379. lua_settable(L, -3);
  380. lua_pushliteral(L, "speed_knots");
  381. lua_pushinteger(L, gnss ? gnss->frame_vtg.speed_knots.value : 0);
  382. lua_settable(L, -3);
  383. lua_pushliteral(L, "speed_kph");
  384. lua_pushinteger(L, gnss ? gnss->frame_vtg.speed_kph.value : 0);
  385. lua_settable(L, -3);
  386. return 1;
  387. }
  388. static int l_libgnss_debug(lua_State *L) {
  389. if (gnss == NULL && luat_libgnss_init(L)) {
  390. return 0;
  391. }
  392. if (lua_isboolean(L, 1) && lua_toboolean(L, 1)) {
  393. gnss->debug = 1;
  394. }
  395. else
  396. {
  397. gnss->debug = 0;
  398. }
  399. return 0;
  400. }
  401. //-----------------------------------------------------
  402. // For Air530Z
  403. //-----------------------------------------------------
  404. uint8_t air530z_uart_id = 2;
  405. static int l_libgnss_air530_setup(lua_State *L) {
  406. air530z_uart_id = luaL_checkinteger(L, 1);
  407. return 0;
  408. }
  409. static int l_libgnss_air530_saveconf(lua_State *L) {
  410. luat_uart_write(air530z_uart_id, "$PCAS00*01\r\n", strlen("$PCAS00*01\r\n"));
  411. return 0;
  412. }
  413. static int l_libgnss_air530_setbandrate(lua_State *L) {
  414. /*
  415. 0=4800bps
  416. 1=9600bps
  417. 2=19200bps
  418. 3=38400bps
  419. 4=57600bps
  420. 5=115200bps
  421. */
  422. int bandrate = luaL_checkinteger(L, 1);
  423. switch (bandrate)
  424. {
  425. case 4800:
  426. luat_uart_write(air530z_uart_id, "$PCAS01,0*1C\r\n", strlen("$PCAS01,0*1C\r\n"));
  427. break;
  428. case 9600:
  429. luat_uart_write(air530z_uart_id, "$PCAS01,1*1D\r\n", strlen("$PCAS01,1*1D\r\n"));
  430. break;
  431. case 19200:
  432. luat_uart_write(air530z_uart_id, "$PCAS01,2*1E\r\n", strlen("$PCAS01,2*1E\r\n"));
  433. break;
  434. case 38400:
  435. luat_uart_write(air530z_uart_id, "$PCAS01,3*1F\r\n", strlen("$PCAS01,3*1F\r\n"));
  436. break;
  437. case 57600:
  438. luat_uart_write(air530z_uart_id, "$PCAS01,4*18\r\n", strlen("$PCAS01,4*18\r\n"));
  439. break;
  440. case 115200:
  441. luat_uart_write(air530z_uart_id, "$PCAS01,5*19\r\n", strlen("$PCAS01,5*19\r\n"));
  442. break;
  443. default:
  444. LLOGD("fallback to default 9600");
  445. luat_uart_write(air530z_uart_id, "$PCAS01,1*1D\r\n", strlen("$PCAS01,1*1D\r\n"));
  446. break;
  447. }
  448. return 0;
  449. }
  450. static int l_libgnss_get_gga(lua_State* L) {
  451. if (gnss == NULL)
  452. return 0;
  453. lua_newtable(L);
  454. lua_pushstring(L, "altitude");
  455. lua_pushinteger(L, gnss->frame_gga.altitude.value);
  456. lua_settable(L, -3);
  457. lua_pushstring(L, "latitude");
  458. lua_pushinteger(L, gnss->frame_gga.latitude.value);
  459. lua_settable(L, -3);
  460. lua_pushstring(L, "longitude");
  461. lua_pushinteger(L, gnss->frame_gga.longitude.value);
  462. lua_settable(L, -3);
  463. lua_pushstring(L, "fix_quality");
  464. lua_pushinteger(L, gnss->frame_gga.fix_quality);
  465. lua_settable(L, -3);
  466. lua_pushstring(L, "satellites_tracked");
  467. lua_pushinteger(L, gnss->frame_gga.satellites_tracked);
  468. lua_settable(L, -3);
  469. lua_pushstring(L, "hdop");
  470. lua_pushinteger(L, gnss->frame_gga.hdop.value);
  471. lua_settable(L, -3);
  472. lua_pushstring(L, "height");
  473. lua_pushinteger(L, gnss->frame_gga.height.value);
  474. lua_settable(L, -3);
  475. lua_pushstring(L, "dgps_age");
  476. lua_pushinteger(L, gnss->frame_gga.dgps_age.value);
  477. lua_settable(L, -3);
  478. return 1;
  479. }
  480. #include "rotable2.h"
  481. static const rotable_Reg_t reg_libgnss[] =
  482. {
  483. { "parse", ROREG_FUNC(l_libgnss_parse)},
  484. { "isFix", ROREG_FUNC(l_libgnss_is_fix)},
  485. { "getIntLocation", ROREG_FUNC(l_libgnss_get_int_location)},
  486. { "getRmc", ROREG_FUNC(l_libgnss_get_rmc)},
  487. { "getGsv", ROREG_FUNC(l_libgnss_get_gsv)},
  488. { "getGsa", ROREG_FUNC(l_libgnss_get_gsa)},
  489. { "getVtg", ROREG_FUNC(l_libgnss_get_vtg)},
  490. { "getGga", ROREG_FUNC(l_libgnss_get_gga)},
  491. { "debug", ROREG_FUNC(l_libgnss_debug)},
  492. //-----------------------------------------
  493. // { "air530z_setup", ROREG_FUNC(l_libgnss_air530_setup)},
  494. // { "air530z_saveconf", ROREG_FUNC(l_libgnss_air530_saveconf)},
  495. // { "air530z_setbandrate", ROREG_FUNC(l_libgnss_air530_setbandrate)},
  496. { NULL, NULL , 0}
  497. };
  498. LUAMOD_API int luaopen_libgnss( lua_State *L ) {
  499. luat_newlib2(L, reg_libgnss);
  500. return 1;
  501. }