luat_lib_libgnss.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. /*
  2. @module libgnss
  3. @summary NMEA数据处理
  4. @version 1.0
  5. @date 2020.07.03
  6. @demo libgnss
  7. @tag LUAT_USE_LIBGNSS
  8. @usage
  9. -- 提醒: 本库输出的坐标,均为 WGS84 坐标系
  10. -- 如需要在国内地图使用, 要转换成对应地图的坐标系, 例如 GCJ02 BD09
  11. -- 相关链接: https://lbsyun.baidu.com/index.php?title=coordinate
  12. -- 方案1, 经lua层进行数据中转
  13. uart.setup(2, 115200)
  14. uart.on(2, "recv", function(id, len)
  15. while 1 do
  16. local data = uart.read(id, 1024)
  17. if data and #data > 1 then
  18. libgnss.parse(data)
  19. else
  20. break
  21. end
  22. end
  23. end)
  24. -- 方案2, 适合2022.12.26之后编译固件,效率更高一些
  25. uart.setup(2, 115200)
  26. libgnss.bind(2)
  27. -- 可选调试模式
  28. -- libgnss.debug(true)
  29. sys.subscribe("GNSS_STATE", function(event, ticks)
  30. -- event取值有
  31. -- FIXED 定位成功
  32. -- LOSE 定位丢失
  33. -- ticks是事件发生的时间,一般可以忽略
  34. log.info("gnss", "state", event, ticks)
  35. end)
  36. */
  37. #include "luat_base.h"
  38. #include "luat_msgbus.h"
  39. #include "luat_malloc.h"
  40. #include "luat_uart.h"
  41. #include "luat_mcu.h"
  42. #include "luat_rtc.h"
  43. #define LUAT_LOG_TAG "gnss"
  44. #include "luat_log.h"
  45. #include "minmea.h"
  46. extern luat_libgnss_t *libgnss_gnss;
  47. // extern luat_libgnss_t *libgnss_gnsstmp;
  48. extern char* libgnss_recvbuff;
  49. extern int libgnss_route_uart_id;
  50. extern int gnss_debug;
  51. void luat_uart_set_app_recv(int id, luat_uart_recv_callback_t cb);
  52. static inline void push_gnss_value(lua_State *L, struct minmea_float *f, int mode) {
  53. if (f->value == 0) {
  54. lua_pushinteger(L, 0);
  55. return;
  56. }
  57. switch (mode)
  58. {
  59. case 0:
  60. lua_pushnumber(L, minmea_tofloat(f));
  61. break;
  62. case 1:
  63. lua_pushinteger(L, minmea_tocoord2(f));
  64. break;
  65. case 2:
  66. lua_pushnumber(L, minmea_tocoord(f));
  67. break;
  68. default:
  69. lua_pushnumber(L, minmea_tocoord(f));
  70. break;
  71. }
  72. }
  73. static int luat_libgnss_state_handler(lua_State *L, void* ptr) {
  74. (void)ptr;
  75. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  76. lua_getglobal(L, "sys_pub");
  77. if (!lua_isfunction(L, -1)) {
  78. return 0;
  79. }
  80. /*
  81. @sys_pub libgnss
  82. GNSS状态变化
  83. GNSS_STATE
  84. @usage
  85. sys.subscribe("GNSS_STATE", function(event, ticks)
  86. -- event取值有
  87. -- FIXED 定位成功
  88. -- LOSE 定位丢失
  89. -- ticks是事件发生的时间,一般可以忽略
  90. log.info("gnss", "state", event, ticks)
  91. end)
  92. */
  93. lua_pushliteral(L, "GNSS_STATE");
  94. switch (msg->arg1)
  95. {
  96. case GNSS_STATE_FIXED:
  97. lua_pushliteral(L, "FIXED");
  98. break;
  99. case GNSS_STATE_LOSE:
  100. lua_pushliteral(L, "LOSE");
  101. break;
  102. case GNSS_STATE_OPEN:
  103. lua_pushliteral(L, "OPEN");
  104. break;
  105. case GNSS_STATE_CLOSE:
  106. lua_pushliteral(L, "CLOSE");
  107. break;
  108. default:
  109. return 0;
  110. }
  111. lua_pushinteger(L, msg->arg2);
  112. lua_call(L, 3, 0);
  113. return 0;
  114. }
  115. int luat_libgnss_state_onchanged(int state) {
  116. rtos_msg_t msg = {0};
  117. msg.handler = luat_libgnss_state_handler;
  118. msg.arg1 = state;
  119. #ifdef LUAT_USE_MCU
  120. msg.arg2 = luat_mcu_ticks();
  121. #endif
  122. luat_msgbus_put(&msg, 0);
  123. return 0;
  124. }
  125. static void put_datetime(lua_State*L, struct tm* rtime) {
  126. lua_pushliteral(L, "year");
  127. lua_pushinteger(L, rtime->tm_year);
  128. lua_settable(L, -3);
  129. lua_pushliteral(L, "month");
  130. lua_pushinteger(L, rtime->tm_mon + 1); // 比较纠结, 要不要兼容老的呢?
  131. lua_settable(L, -3);
  132. lua_pushliteral(L, "day");
  133. lua_pushinteger(L, rtime->tm_mday);
  134. lua_settable(L, -3);
  135. lua_pushliteral(L, "hour");
  136. lua_pushinteger(L, rtime->tm_hour);
  137. lua_settable(L, -3);
  138. lua_pushliteral(L, "min");
  139. lua_pushinteger(L, rtime->tm_min);
  140. lua_settable(L, -3);
  141. lua_pushliteral(L, "sec");
  142. lua_pushinteger(L, rtime->tm_sec);
  143. lua_settable(L, -3);
  144. }
  145. static int32_t l_gnss_callback(lua_State *L, void* ptr){
  146. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  147. luat_libgnss_uart_recv_cb(msg->arg1, msg->arg2);
  148. return 0;
  149. }
  150. static void l_libgnss_uart_recv_cb(int uart_id, uint32_t data_len)
  151. {
  152. rtos_msg_t msg = {0};
  153. msg.handler = l_gnss_callback;
  154. msg.arg1 = uart_id;
  155. msg.arg2 = data_len;
  156. luat_msgbus_put(&msg, 0);
  157. }
  158. /**
  159. 处理nmea数据
  160. @api libgnss.parse(str)
  161. @string 原始nmea数据
  162. @usage
  163. -- 解析nmea数据
  164. libgnss.parse(indata)
  165. log.info("nmea", json.encode(libgnss.getRmc(), "11g"))
  166. */
  167. static int l_libgnss_parse(lua_State *L) {
  168. size_t len = 0;
  169. const char* str = luaL_checklstring(L, 1, &len);
  170. if (len > 0) {
  171. luat_libgnss_parse_data(str, len);
  172. }
  173. return 0;
  174. }
  175. /**
  176. 当前是否已经定位成功
  177. @api libgnss.isFix()
  178. @return boolean 定位成功与否
  179. @usage
  180. log.info("nmea", "isFix", libgnss.isFix())
  181. */
  182. static int l_libgnss_is_fix(lua_State *L) {
  183. if (libgnss_gnss == NULL) {
  184. lua_pushboolean(L, 0);
  185. }
  186. else
  187. lua_pushboolean(L, libgnss_gnss->frame_rmc.valid != 0 ? 1 : 0);
  188. return 1;
  189. }
  190. /**
  191. 获取位置信息
  192. @api libgnss.getIntLocation()
  193. @return int lat数据, 格式为 ddddddddd
  194. @return int lng数据, 格式为 ddddddddd
  195. @return int speed数据
  196. @usage
  197. -- 建议用libgnss.getRmc(1)
  198. log.info("nmea", "loc", libgnss.getIntLocation())
  199. */
  200. static int l_libgnss_get_int_location(lua_State *L) {
  201. if (libgnss_gnss != NULL && libgnss_gnss->frame_rmc.valid) {
  202. lua_pushinteger(L, libgnss_gnss->frame_rmc.latitude.value);
  203. lua_pushinteger(L, libgnss_gnss->frame_rmc.longitude.value);
  204. // lua_pushinteger(L, libgnss_gnss->frame_rmc.speed.value);
  205. push_gnss_value(L, &libgnss_gnss->frame_rmc.speed, 1);
  206. } else {
  207. lua_pushinteger(L, 0);
  208. lua_pushinteger(L, 0);
  209. lua_pushinteger(L, 0);
  210. }
  211. return 3;
  212. }
  213. /**
  214. 获取原始RMC位置信息
  215. @api libgnss.getRmc(data_mode)
  216. @int 坐标类数据的格式, 0-DDMM.MMM格式, 1-DDDDDDD格式, 2-DD.DDDDD格式
  217. @return table 原始rmc数据
  218. @usage
  219. -- 解析nmea
  220. log.info("nmea", "rmc", json.encode(libgnss.getRmc(2)))
  221. -- 实例输出
  222. --[[
  223. {
  224. "course":0,
  225. "valid":true, // true定位成功,false定位丢失
  226. "lat":23.4067, // 纬度, 正数为北纬, 负数为南纬
  227. "lng":113.231, // 经度, 正数为东经, 负数为西经
  228. "variation":0, // 地面航向,单位为度,从北向起顺时针计算
  229. "speed":0 // 地面速度, 单位为"节"
  230. "year":2023, // 年份
  231. "month":1, // 月份, 1-12
  232. "day":5, // 月份天, 1-31
  233. "hour":7, // 小时,0-23
  234. "min":23, // 分钟,0-59
  235. "sec":20, // 秒,0-59
  236. }
  237. ]]
  238. */
  239. static int l_libgnss_get_rmc(lua_State *L) {
  240. int mode = luaL_optinteger(L, 1, 0);
  241. lua_settop(L, 0);
  242. lua_createtable(L, 0, 12);
  243. struct tm rtime = {0};
  244. if (libgnss_gnss != NULL) {
  245. lua_pushboolean(L, libgnss_gnss->frame_rmc.valid);
  246. lua_setfield(L, -2, "valid");
  247. if (libgnss_gnss->frame_rmc.valid) {
  248. push_gnss_value(L, &(libgnss_gnss->frame_rmc.latitude), mode);
  249. }
  250. else
  251. lua_pushinteger(L, 0);
  252. lua_setfield(L, -2, "lat");
  253. if (libgnss_gnss->frame_rmc.valid) {
  254. push_gnss_value(L, &(libgnss_gnss->frame_rmc.longitude), mode);
  255. }
  256. else
  257. lua_pushinteger(L, 0);
  258. lua_setfield(L, -2, "lng");
  259. if (libgnss_gnss->frame_rmc.valid) {
  260. push_gnss_value(L, &(libgnss_gnss->frame_rmc.speed), 0);
  261. }
  262. else
  263. lua_pushinteger(L, 0);
  264. lua_setfield(L, -2, "speed");
  265. if (libgnss_gnss->frame_rmc.valid) {
  266. push_gnss_value(L, &(libgnss_gnss->frame_rmc.course), 0);
  267. }
  268. else
  269. lua_pushinteger(L, 0);
  270. lua_setfield(L, -2, "course");
  271. if (libgnss_gnss->frame_rmc.valid) {
  272. push_gnss_value(L, &(libgnss_gnss->frame_rmc.variation), 0);
  273. }
  274. else
  275. lua_pushinteger(L, 0);
  276. lua_setfield(L, -2, "variation");
  277. // 时间类
  278. minmea_getdatetime(&rtime, &libgnss_gnss->frame_rmc.date, &libgnss_gnss->frame_rmc.time);
  279. put_datetime(L, &rtime);
  280. }
  281. return 1;
  282. }
  283. static void add_gsv(lua_State*L, struct minmea_sentence_gsv* gsvs, size_t *count, int tp) {
  284. for (size_t i = 0; i < FRAME_GSV_MAX; i++)
  285. {
  286. for (size_t j = 0; j < 4; j++)
  287. {
  288. //LLOGD("nr %d snr %d", gnss->frame_gsv[i].sats[j].nr, gnss->frame_gsv[i].sats[j].snr);
  289. if (gsvs[i].sats[j].nr) {
  290. lua_pushinteger(L, *count);
  291. lua_createtable(L, 0, 4);
  292. lua_pushliteral(L, "nr");
  293. lua_pushinteger(L, gsvs[i].sats[j].nr);
  294. lua_settable(L, -3);
  295. lua_pushliteral(L, "snr");
  296. lua_pushinteger(L, gsvs[i].sats[j].snr);
  297. lua_settable(L, -3);
  298. lua_pushliteral(L, "elevation");
  299. lua_pushinteger(L, gsvs[i].sats[j].elevation);
  300. lua_settable(L, -3);
  301. lua_pushliteral(L, "azimuth");
  302. lua_pushinteger(L, gsvs[i].sats[j].azimuth);
  303. lua_settable(L, -3);
  304. lua_pushliteral(L, "tp");
  305. lua_pushinteger(L, tp);
  306. lua_settable(L, -3);
  307. lua_settable(L, -3);
  308. *count = *count + 1;
  309. }
  310. }
  311. }
  312. }
  313. /**
  314. 获取原始GSV信息
  315. @api libgnss.getGsv()
  316. @return table 原始GSV数据
  317. @usage
  318. -- 解析nmea
  319. log.info("nmea", "gsv", json.encode(libgnss.getGsv()))
  320. --[[实例输出
  321. {
  322. "total_sats":24, // 总可见卫星数量
  323. "sats":[
  324. {
  325. "snr":27, // 信噪比
  326. "azimuth":278, // 方向角
  327. "elevation":59, // 仰角
  328. "tp":0, // 0 - GPS/SASS/QSZZ, 1 - BD
  329. "nr":4 // 卫星编号
  330. },
  331. // 这里忽略了22个卫星的信息
  332. {
  333. "snr":0,
  334. "azimuth":107,
  335. "elevation":19,
  336. "tp":1,
  337. "nr":31
  338. }
  339. ]
  340. }
  341. ]]
  342. */
  343. static int l_libgnss_get_gsv(lua_State *L) {
  344. lua_createtable(L, 0, 2);
  345. if (libgnss_gnss == NULL)
  346. return 1;
  347. size_t count = 1;
  348. lua_createtable(L, 12, 0);
  349. if (libgnss_gnss->frame_gsv_gp->total_sats > 0) {
  350. add_gsv(L, libgnss_gnss->frame_gsv_gp, &count, 0);
  351. }
  352. if (libgnss_gnss->frame_gsv_gb->total_sats > 0) {
  353. add_gsv(L, libgnss_gnss->frame_gsv_gb, &count, 1);
  354. }
  355. // if (libgnss_gnss->frame_gsv_gl->total_sats > 0) {
  356. // add_gsv(L, libgnss_gnss->frame_gsv_gl, &count);
  357. // }
  358. // if (libgnss_gnss->frame_gsv_ga->total_sats > 0) {
  359. // add_gsv(L, libgnss_gnss->frame_gsv_ga, &count);
  360. // }
  361. lua_setfield(L, -2, "sats");
  362. lua_pushliteral(L, "total_sats");
  363. lua_pushinteger(L, count - 1);
  364. lua_settable(L, -3);
  365. return 1;
  366. }
  367. /**
  368. 获取原始GSA信息
  369. @api libgnss.getGsa(data_mode)
  370. @int 坐标类数据的格式, 0-DDMM.MMM格式, 1-DDDDDDD格式, 2-DD.DDDDD格式
  371. @return table 原始GSA数据
  372. @usage
  373. -- 获取
  374. log.info("nmea", "gsa", json.encode(libgnss.getGsa(), "11g"))
  375. -- 示例数据
  376. --[[
  377. {
  378. "sats":[ // 正在使用的卫星编号
  379. 9,
  380. 6,
  381. 16,
  382. 16,
  383. 26,
  384. 21,
  385. 27,
  386. 27,
  387. 4,
  388. 36,
  389. 3,
  390. 7,
  391. 8,
  392. 194
  393. ],
  394. "vdop":0.03083333, // 垂直精度因子,0.00 - 99.99,不定位时值为 99.99
  395. "pdop":0.0455, // 水平精度因子,0.00 - 99.99,不定位时值为 99.99
  396. "fix_type":3, // 定位模式, 1-未定位, 2-2D定位, 3-3D定位
  397. "hdop":0.0335 // 位置精度因子,0.00 - 99.99,不定位时值为 99.99
  398. }
  399. ]]
  400. */
  401. static int l_libgnss_get_gsa(lua_State *L) {
  402. int mode = luaL_optinteger(L, 1, 0);
  403. lua_settop(L, 0);
  404. if (libgnss_gnss == NULL)
  405. return 0;
  406. lua_createtable(L, 0, 10);
  407. //lua_pushliteral(L, "mode");
  408. //lua_pushlstring(L, gnss ? &(gnss->frame_gsa.mode) : "N", 1);
  409. //lua_settable(L, -3);
  410. lua_pushliteral(L, "fix_type");
  411. lua_pushinteger(L, libgnss_gnss->frame_gsa[0].fix_type);
  412. lua_settable(L, -3);
  413. lua_pushliteral(L, "pdop");
  414. push_gnss_value(L, &(libgnss_gnss->frame_gsa[0].pdop), 0);
  415. lua_settable(L, -3);
  416. lua_pushliteral(L, "hdop");
  417. push_gnss_value(L, &(libgnss_gnss->frame_gsa[0].hdop), 0);
  418. lua_settable(L, -3);
  419. lua_pushliteral(L, "vdop");
  420. push_gnss_value(L, &(libgnss_gnss->frame_gsa[0].vdop), 0);
  421. lua_settable(L, -3);
  422. lua_pushliteral(L, "sats");
  423. lua_createtable(L, 12, 0);
  424. size_t pos = 1;
  425. for (size_t i = 0; i < 12; i++) {
  426. for (size_t j = 0; j < 3; j++)
  427. {
  428. if (libgnss_gnss->frame_gsa[j].sats[i] == 0)
  429. continue;
  430. lua_pushinteger(L, libgnss_gnss->frame_gsa[j].sats[i]);
  431. lua_seti(L, -2, pos);
  432. pos ++;
  433. }
  434. }
  435. lua_settable(L, -3);
  436. return 1;
  437. }
  438. /**
  439. 获取VTA速度信息
  440. @api libgnss.getVtg(data_mode)
  441. @int 可选, 3-原始字符串, 不传或者传其他值, 则返回浮点值
  442. @return table 原始VTA数据
  443. @usage
  444. -- 解析nmea
  445. log.info("nmea", "vtg", json.encode(libgnss.getVtg()))
  446. -- 示例
  447. --[[
  448. {
  449. "speed_knots":0, // 速度, 英里/小时
  450. "true_track_degrees":0, // 真北方向角
  451. "magnetic_track_degrees":0, // 磁北方向角
  452. "speed_kph":0 // 速度, 千米/小时
  453. }
  454. ]]
  455. */
  456. static int l_libgnss_get_vtg(lua_State *L) {
  457. int mode = luaL_optinteger(L, 1, 0);
  458. lua_settop(L, 0);
  459. if (libgnss_gnss == NULL)
  460. return 0;
  461. if (mode == 3) {
  462. lua_pushstring(L, libgnss_gnss->vtg);
  463. return 1;
  464. }
  465. lua_createtable(L, 0, 10);
  466. struct minmea_sentence_vtg frame_vtg = {0};
  467. minmea_parse_vtg(&frame_vtg, libgnss_gnss->vtg);
  468. // lua_pushliteral(L, "faa_mode");
  469. // lua_pushlstring(L, libgnss_gnss->frame_vtg.faa_mode, 1);
  470. // lua_settable(L, -3);
  471. lua_pushliteral(L, "true_track_degrees");
  472. push_gnss_value(L, &(frame_vtg.true_track_degrees), 0);
  473. lua_settable(L, -3);
  474. lua_pushliteral(L, "magnetic_track_degrees");
  475. push_gnss_value(L, &(frame_vtg.magnetic_track_degrees), 0);
  476. lua_settable(L, -3);
  477. lua_pushliteral(L, "speed_knots");
  478. push_gnss_value(L, &(frame_vtg.speed_knots), 0);
  479. lua_settable(L, -3);
  480. lua_pushliteral(L, "speed_kph");
  481. push_gnss_value(L, &(frame_vtg.speed_kph), 0);
  482. lua_settable(L, -3);
  483. return 1;
  484. }
  485. /**
  486. 获取原始ZDA时间和日期信息
  487. @api libgnss.getZda()
  488. @return table 原始zda数据
  489. @usage
  490. log.info("nmea", "zda", json.encode(libgnss.getZda()))
  491. -- 实例输出
  492. --[[
  493. {
  494. "minute_offset":0, // 本地时区的分钟, 一般固定输出0
  495. "hour_offset":0, // 本地时区的小时, 一般固定输出0
  496. "year":2023 // UTC 年,四位数字
  497. "month":1, // UTC 月,两位,01 ~ 12
  498. "day":5, // UTC 日,两位数字,01 ~ 31
  499. "hour":7, // 小时
  500. "min":50, // 分
  501. "sec":14, // 秒
  502. }
  503. ]]
  504. */
  505. static int l_libgnss_get_zda(lua_State *L) {
  506. lua_createtable(L, 0, 9);
  507. struct tm rtime = {0};
  508. if (libgnss_gnss != NULL) {
  509. struct minmea_sentence_zda frame_zda = {0};
  510. minmea_parse_zda(&frame_zda, libgnss_gnss->zda);
  511. lua_pushliteral(L, "hour_offset");
  512. lua_pushinteger(L, frame_zda.hour_offset);
  513. lua_settable(L, -3);
  514. lua_pushliteral(L, "minute_offset");
  515. lua_pushinteger(L, frame_zda.minute_offset);
  516. lua_settable(L, -3);
  517. // 时间相关
  518. minmea_getdatetime(&rtime, &frame_zda.date, &frame_zda.time);
  519. put_datetime(L, &rtime);
  520. }
  521. return 1;
  522. }
  523. /**
  524. 设置调试模式
  525. @api libgnss.debug(mode)
  526. @bool true开启调试,false关闭调试,默认为false
  527. @usage
  528. -- 开启调试, 会输出GNSS原始数据到日志中
  529. libgnss.debug(true)
  530. -- 关闭调试
  531. libgnss.debug(false)
  532. */
  533. static int l_libgnss_debug(lua_State *L) {
  534. if (libgnss_gnss == NULL && luat_libgnss_init(0)) {
  535. return 0;
  536. }
  537. if (lua_isboolean(L, 1) && lua_toboolean(L, 1)) {
  538. LLOGD("Debug ON");
  539. gnss_debug = 1;
  540. }
  541. else
  542. {
  543. LLOGD("Debug OFF");
  544. gnss_debug = 0;
  545. }
  546. return 0;
  547. }
  548. /*
  549. 获取GGA数据
  550. @api libgnss.getGga(data_mode)
  551. @int 坐标类数据的格式, 0-DDMM.MMM格式, 1-DDDDDDD格式, 2-DD.DDDDD格式, 3-原始字符串
  552. @return table GGA数据, 若如不存在会返回nil
  553. @usage
  554. local gga = libgnss.getGga(2)
  555. if gga then
  556. log.info("GGA", json.encode(gga, "11g"))
  557. end
  558. --实例输出
  559. --[[
  560. {
  561. "dgps_age":0, // 差分校正时延,单位为秒
  562. "fix_quality":1, // 定位状态标识 0 - 无效,1 - 单点定位,2 - 差分定位
  563. "satellites_tracked":14, // 参与定位的卫星数量
  564. "altitude":0.255, // 海平面分离度
  565. "hdop":0.0335, // 水平精度因子,0.00 - 99.99,不定位时值为 99.99
  566. "longitude":113.231, // 经度, 正数为东经, 负数为西经
  567. "latitude":23.4067, // 纬度, 正数为北纬, 负数为南纬
  568. "height":0 // 椭球高,固定输出 1 位小数
  569. }
  570. ]]
  571. */
  572. static int l_libgnss_get_gga(lua_State* L) {
  573. int mode = luaL_optinteger(L, 1, 0);
  574. lua_settop(L, 0);
  575. if (libgnss_gnss == NULL)
  576. return 0;
  577. if (mode == 3) {
  578. lua_pushstring(L, libgnss_gnss->gga);
  579. return 1;
  580. }
  581. lua_newtable(L);
  582. struct minmea_sentence_gga frame_gga = {0};
  583. minmea_parse_gga(&frame_gga, libgnss_gnss->gga);
  584. lua_pushstring(L, "altitude");
  585. push_gnss_value(L, &(frame_gga.altitude), 0);
  586. lua_settable(L, -3);
  587. lua_pushstring(L, "latitude");
  588. push_gnss_value(L, &(frame_gga.latitude), mode);
  589. lua_settable(L, -3);
  590. lua_pushstring(L, "longitude");
  591. push_gnss_value(L, &(frame_gga.longitude), mode);
  592. lua_settable(L, -3);
  593. lua_pushstring(L, "fix_quality");
  594. lua_pushinteger(L, frame_gga.fix_quality);
  595. lua_settable(L, -3);
  596. lua_pushstring(L, "satellites_tracked");
  597. lua_pushinteger(L, frame_gga.satellites_tracked);
  598. lua_settable(L, -3);
  599. lua_pushstring(L, "hdop");
  600. push_gnss_value(L, &(frame_gga.hdop), 0);
  601. lua_settable(L, -3);
  602. lua_pushstring(L, "height");
  603. push_gnss_value(L, &(frame_gga.height), 0);
  604. lua_settable(L, -3);
  605. lua_pushstring(L, "dgps_age");
  606. push_gnss_value(L, &(frame_gga.dgps_age), 0);
  607. lua_settable(L, -3);
  608. return 1;
  609. }
  610. /*
  611. 获取GLL数据
  612. @api libgnss.getGll(data_mode)
  613. @int 坐标类数据的格式, 0-DDMM.MMM格式, 1-DDDDDDD格式, 2-DD.DDDDD格式
  614. @return table GLL数据, 若如不存在会返回nil
  615. @usage
  616. local gll = libgnss.getGll(2)
  617. if gll then
  618. log.info("GLL", json.encode(gll, "11g"))
  619. end
  620. -- 实例数据
  621. --[[
  622. {
  623. "status":"A", // 定位状态, A有效, B无效
  624. "mode":"A", // 定位模式, V无效, A单点解, D差分解
  625. "sec":20, // 秒, UTC时间为准
  626. "min":23, // 分钟, UTC时间为准
  627. "hour":7, // 小时, UTC时间为准
  628. "longitude":113.231, // 经度, 正数为东经, 负数为西经
  629. "latitude":23.4067, // 纬度, 正数为北纬, 负数为南纬
  630. "us":0 // 微妙数, 通常为0
  631. }
  632. ]]
  633. */
  634. static int l_libgnss_get_gll(lua_State* L) {
  635. int mode = luaL_optinteger(L, 1, 0);
  636. lua_settop(L, 0);
  637. if (libgnss_gnss == NULL)
  638. return 0;
  639. if (mode == 3) {
  640. lua_pushstring(L, libgnss_gnss->vtg);
  641. return 1;
  642. }
  643. lua_newtable(L);
  644. struct minmea_sentence_gll frame_gll = {0};
  645. minmea_parse_gll(&frame_gll, libgnss_gnss->gll);
  646. lua_pushstring(L, "latitude");
  647. push_gnss_value(L, &(frame_gll.latitude), mode);
  648. lua_settable(L, -3);
  649. lua_pushstring(L, "longitude");
  650. push_gnss_value(L, &(frame_gll.longitude), mode);
  651. lua_settable(L, -3);
  652. lua_pushstring(L, "mode");
  653. lua_pushfstring(L, "%c", frame_gll.mode);
  654. lua_settable(L, -3);
  655. lua_pushstring(L, "status");
  656. lua_pushfstring(L, "%c", frame_gll.status);
  657. lua_settable(L, -3);
  658. lua_pushstring(L, "hour");
  659. lua_pushinteger(L, frame_gll.time.hours);
  660. lua_settable(L, -3);
  661. lua_pushstring(L, "us");
  662. lua_pushinteger(L, frame_gll.time.microseconds);
  663. lua_settable(L, -3);
  664. lua_pushstring(L, "min");
  665. lua_pushinteger(L, frame_gll.time.minutes);
  666. lua_settable(L, -3);
  667. lua_pushstring(L, "sec");
  668. lua_pushinteger(L, frame_gll.time.seconds);
  669. lua_settable(L, -3);
  670. return 1;
  671. }
  672. /**
  673. 清除历史定位数据
  674. @api libgnss.clear()
  675. @return nil 无返回值
  676. @usage
  677. -- 该操作会清除所有定位数据
  678. */
  679. static int l_libgnss_clear(lua_State*L) {
  680. (void)L;
  681. if (libgnss_gnss == NULL && luat_libgnss_init(1))
  682. return 0;
  683. memset(libgnss_gnss, 0, sizeof(luat_libgnss_t));
  684. return 0;
  685. }
  686. /*
  687. 绑定uart端口进行GNSS数据读取
  688. @api libgnss.bind(id, next_id)
  689. @int uart端口号
  690. @int 转发到uart的id, 例如虚拟uart.VUART_0
  691. @usage
  692. -- 配置串口信息, 通常为 115200 8N1
  693. uart.setup(2, 115200)
  694. -- 绑定uart, 马上开始解析GNSS数据
  695. libgnss.bind(2)
  696. -- 无需再调用uart.on然后调用libgnss.parse
  697. -- 开发期可打开调试日志
  698. libgnss.debug(true)
  699. -- 2023-01-02之后编译的固件有效
  700. -- 从uart2读取并解析, 同时转发到虚拟串口0
  701. libgnss.bind(2, uart.VUART_0)
  702. */
  703. static int l_libgnss_bind(lua_State* L) {
  704. int uart_id = luaL_checkinteger(L, 1);
  705. l_libgnss_clear(L);
  706. if (libgnss_recvbuff == NULL) {
  707. libgnss_recvbuff = luat_heap_malloc(RECV_BUFF_SIZE);
  708. }
  709. if (luat_uart_exist(uart_id)) {
  710. //uart_app_recvs[uart_id] = nmea_uart_recv_cb;
  711. luat_uart_set_app_recv(uart_id, l_libgnss_uart_recv_cb);
  712. }
  713. if (lua_isinteger(L, 2)) {
  714. libgnss_route_uart_id = luaL_checkinteger(L, 2);
  715. }
  716. return 0;
  717. }
  718. /**
  719. 获取位置字符串
  720. @api libgnss.locStr(mode)
  721. @int 字符串模式. 0- Air780EG所需的格式
  722. @return 指定模式的字符串
  723. @usage
  724. -- 仅推荐在定位成功后调用
  725. */
  726. static int l_libgnss_locStr(lua_State *L) {
  727. int mode = luaL_optinteger(L, 1, 0);
  728. char buff[64] = {0};
  729. float lat_f = minmea_tofloat(&libgnss_gnss->frame_rmc.latitude);
  730. float lng_f = minmea_tofloat(&libgnss_gnss->frame_rmc.longitude);
  731. switch (mode)
  732. {
  733. case 0:
  734. snprintf_(buff, 63, "%.7g,%c,%.7g,%c,1.0",
  735. fabs(lat_f), lat_f > 0 ? 'N' : 'S',
  736. fabs(lng_f), lng_f > 0 ? 'E' : 'W');
  737. break;
  738. case 1:
  739. snprintf_(buff, 63, "%d,%d", libgnss_gnss->frame_rmc.latitude.value, libgnss_gnss->frame_rmc.longitude.value);
  740. break;
  741. default:
  742. break;
  743. }
  744. lua_pushstring(L, buff);
  745. return 1;
  746. }
  747. /**
  748. 定位成功后自动设置RTC
  749. @api libgnss.rtcAuto(enable)
  750. @bool 开启与否, 默认是false关闭
  751. @usage
  752. -- 开启自动设置RTC
  753. libgnss.rtcAuto(true)
  754. */
  755. static int l_libgnss_rtc_auto(lua_State *L) {
  756. if (libgnss_gnss == NULL)
  757. return 0;
  758. if (lua_isboolean(L, 1) && lua_toboolean(L, 1)) {
  759. libgnss_gnss->rtc_auto = 1;
  760. LLOGD("GNSS->RTC Auto-Set now is ON");
  761. }
  762. else {
  763. libgnss_gnss->rtc_auto = 0;
  764. LLOGD("GNSS->RTC Auto-Set now is OFF");
  765. }
  766. return 0;
  767. }
  768. //临时处理, 当前GNSS处理均在lua线程
  769. // static lua_State *gnss_L;
  770. static int gnss_raw_cb = 0;
  771. int luat_libgnss_rawdata_cb(lua_State *L, void* ptr) {
  772. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  773. // lua_getglobal(L, "sys_pub");
  774. lua_geti(L, LUA_REGISTRYINDEX, gnss_raw_cb);
  775. if (lua_isfunction(L, -1)) {
  776. // lua_pushliteral(gnss_L, "GNSS_RAW_DATA");
  777. lua_pushlstring(L, ptr, msg->arg1);
  778. luat_heap_free(ptr);
  779. ptr = NULL;
  780. lua_call(L, 1, 0);
  781. }
  782. else {
  783. luat_heap_free(ptr);
  784. }
  785. return 0;
  786. }
  787. int luat_libgnss_on_rawdata(const char* data, size_t len) {
  788. if (gnss_raw_cb == 0)
  789. return 0;
  790. char* ptr = luat_heap_malloc(len);
  791. if (ptr == NULL)
  792. return 0;
  793. memcpy(ptr, data, len);
  794. rtos_msg_t msg = {
  795. .handler = luat_libgnss_rawdata_cb,
  796. .arg1 = len,
  797. .ptr = ptr
  798. };
  799. luat_msgbus_put(&msg, 0);
  800. return 0;
  801. }
  802. /**
  803. 底层事件回调
  804. @api libgnss.on(tp, fn)
  805. @string 事件类型,当前支持"raw"
  806. @usage
  807. -- 本函数一般用于调试, 用于获取底层实际收到的数据
  808. libgnss.on("raw", function(data)
  809. log.info("GNSS", data)
  810. end)
  811. */
  812. static int l_libgnss_on(lua_State *L) {
  813. size_t len = 0;
  814. const char* tp = luaL_checklstring(L, 1, &len);
  815. if (!strcmp("raw", tp)) {
  816. if (gnss_raw_cb != 0) {
  817. luaL_unref(L, LUA_REGISTRYINDEX, gnss_raw_cb);
  818. gnss_raw_cb = 0;
  819. }
  820. if (lua_isfunction(L, 2)) {
  821. lua_pushvalue(L, 2);
  822. gnss_raw_cb = luaL_ref(L, LUA_REGISTRYINDEX);
  823. }
  824. }
  825. return 0;
  826. }
  827. /**
  828. 获取非标的GPTXT数据
  829. @api libgnss.getTxt()
  830. @return GPTXT所携带的字符串
  831. @usage
  832. -- 本函数于2023.6.6 添加
  833. log.info("gnss", "txt", libgnss.getTxt())
  834. -- 测试语句
  835. libgnss.parse("$GPTXT,01,01,01,ANTENNA SHORT*63\r\n")
  836. log.info("GNSS", libgnss.getTxt())
  837. libgnss.parse("$GPTXT,01,01,01,ANTENNA OPEN*25\r\n")
  838. log.info("GNSS", libgnss.getTxt())
  839. libgnss.parse("$GPTXT,01,01,01,ANTENNA OK*35\r\n")
  840. log.info("GNSS", libgnss.getTxt())
  841. */
  842. static int l_libgnss_get_txt(lua_State *L) {
  843. if (libgnss_gnss == NULL) {
  844. lua_pushliteral(L, "");
  845. return 1;
  846. }
  847. libgnss_gnss->txt.txt[FRAME_TXT_MAX_LEN] = 0x00;
  848. lua_pushstring(L, libgnss_gnss->txt.txt);
  849. return 1;
  850. }
  851. #include "rotable2.h"
  852. static const rotable_Reg_t reg_libgnss[] =
  853. {
  854. { "parse", ROREG_FUNC(l_libgnss_parse)},
  855. { "isFix", ROREG_FUNC(l_libgnss_is_fix)},
  856. { "getIntLocation", ROREG_FUNC(l_libgnss_get_int_location)},
  857. { "getRmc", ROREG_FUNC(l_libgnss_get_rmc)},
  858. { "getGsv", ROREG_FUNC(l_libgnss_get_gsv)},
  859. { "getGsa", ROREG_FUNC(l_libgnss_get_gsa)},
  860. { "getVtg", ROREG_FUNC(l_libgnss_get_vtg)},
  861. { "getGga", ROREG_FUNC(l_libgnss_get_gga)},
  862. { "getGll", ROREG_FUNC(l_libgnss_get_gll)},
  863. { "getZda", ROREG_FUNC(l_libgnss_get_zda)},
  864. { "locStr", ROREG_FUNC(l_libgnss_locStr)},
  865. { "rtcAuto",ROREG_FUNC(l_libgnss_rtc_auto)},
  866. { "on", ROREG_FUNC(l_libgnss_on)},
  867. { "debug", ROREG_FUNC(l_libgnss_debug)},
  868. { "clear", ROREG_FUNC(l_libgnss_clear)},
  869. { "bind", ROREG_FUNC(l_libgnss_bind)},
  870. { "getTxt", ROREG_FUNC(l_libgnss_get_txt)},
  871. { NULL, ROREG_INT(0)}
  872. };
  873. LUAMOD_API int luaopen_libgnss( lua_State *L ) {
  874. luat_newlib2(L, reg_libgnss);
  875. return 1;
  876. }