luat_lib_libgnss.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  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. -- 相关链接: https://www.openluat.com/GPS-Offset.html
  13. -- 提醒: GPS功能, GNSS功能, NMEA解析功能,均为当前库的子功能
  14. -- 本库的主要功能就是解析NMEA协议, 支持内置GNSS也支持外置GNSS
  15. -- 以下是使用本libgnss的示例代码
  16. -- 方案1, 经lua层进行数据中转
  17. uart.setup(2, 115200)
  18. uart.on(2, "recv", function(id, len)
  19. while 1 do
  20. local data = uart.read(id, 1024)
  21. if data and #data > 1 then
  22. libgnss.parse(data)
  23. else
  24. break
  25. end
  26. end
  27. end)
  28. -- 方案2, 适合2022.12.26之后编译固件,效率更高一些
  29. uart.setup(2, 115200)
  30. libgnss.bind(2)
  31. -- 可选调试模式
  32. -- libgnss.debug(true)
  33. sys.subscribe("GNSS_STATE", function(event, ticks)
  34. -- event取值有
  35. -- FIXED 定位成功
  36. -- LOSE 定位丢失
  37. -- ticks是事件发生的时间,一般可以忽略
  38. log.info("gnss", "state", event, ticks)
  39. end)
  40. */
  41. #include "luat_base.h"
  42. #include "luat_msgbus.h"
  43. #include "luat_mem.h"
  44. #include "luat_uart.h"
  45. #include "luat_mcu.h"
  46. #include "luat_rtc.h"
  47. #include "luat_zbuff.h"
  48. #define LUAT_LOG_TAG "gnss"
  49. #include "luat_log.h"
  50. #include "minmea.h"
  51. extern luat_libgnss_t gnssctx;
  52. // extern luat_libgnss_t *libgnss_gnsstmp;
  53. extern char* libgnss_recvbuff;
  54. extern int libgnss_route_uart_id;
  55. extern int gnss_debug;
  56. static int gnss_raw_cb = 0;
  57. static int gnss_txt_cb = 0;
  58. // static int gnss_rmc_cb = 0;
  59. static int gnss_other_cb = 0;
  60. void luat_uart_set_app_recv(int id, luat_uart_recv_callback_t cb);
  61. static inline void push_gnss_value(lua_State *L, struct minmea_float *f, int mode) {
  62. if (f->value == 0) {
  63. lua_pushinteger(L, 0);
  64. return;
  65. }
  66. switch (mode)
  67. {
  68. case 0:
  69. lua_pushnumber(L, minmea_tofloat(f));
  70. break;
  71. case 1:
  72. lua_pushinteger(L, minmea_tocoord2(f));
  73. break;
  74. case 2:
  75. lua_pushnumber(L, minmea_tocoord(f));
  76. break;
  77. default:
  78. lua_pushnumber(L, minmea_tocoord(f));
  79. break;
  80. }
  81. }
  82. static int luat_libgnss_state_handler(lua_State *L, void* ptr) {
  83. (void)ptr;
  84. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  85. lua_getglobal(L, "sys_pub");
  86. if (!lua_isfunction(L, -1)) {
  87. return 0;
  88. }
  89. /*
  90. @sys_pub libgnss
  91. GNSS状态变化
  92. GNSS_STATE
  93. @usage
  94. sys.subscribe("GNSS_STATE", function(event, ticks)
  95. -- event取值有
  96. -- FIXED 定位成功
  97. -- LOSE 定位丢失
  98. -- ticks是事件发生的时间,一般可以忽略
  99. log.info("gnss", "state", event, ticks)
  100. end)
  101. */
  102. lua_pushliteral(L, "GNSS_STATE");
  103. switch (msg->arg1)
  104. {
  105. case GNSS_STATE_FIXED:
  106. lua_pushliteral(L, "FIXED");
  107. break;
  108. case GNSS_STATE_LOSE:
  109. lua_pushliteral(L, "LOSE");
  110. break;
  111. case GNSS_STATE_OPEN:
  112. lua_pushliteral(L, "OPEN");
  113. break;
  114. case GNSS_STATE_CLOSE:
  115. lua_pushliteral(L, "CLOSE");
  116. break;
  117. default:
  118. return 0;
  119. }
  120. lua_pushinteger(L, msg->arg2);
  121. lua_call(L, 3, 0);
  122. return 0;
  123. }
  124. int luat_libgnss_state_onchanged(int state) {
  125. rtos_msg_t msg = {0};
  126. msg.handler = luat_libgnss_state_handler;
  127. msg.arg1 = state;
  128. #ifdef LUAT_USE_MCU
  129. msg.arg2 = luat_mcu_ticks();
  130. #endif
  131. luat_msgbus_put(&msg, 0);
  132. return 0;
  133. }
  134. static void put_datetime(lua_State*L, struct tm* rtime) {
  135. lua_pushliteral(L, "year");
  136. lua_pushinteger(L, rtime->tm_year);
  137. lua_settable(L, -3);
  138. lua_pushliteral(L, "month");
  139. lua_pushinteger(L, rtime->tm_mon + 1); // 比较纠结, 要不要兼容老的呢?
  140. lua_settable(L, -3);
  141. lua_pushliteral(L, "day");
  142. lua_pushinteger(L, rtime->tm_mday);
  143. lua_settable(L, -3);
  144. lua_pushliteral(L, "hour");
  145. lua_pushinteger(L, rtime->tm_hour);
  146. lua_settable(L, -3);
  147. lua_pushliteral(L, "min");
  148. lua_pushinteger(L, rtime->tm_min);
  149. lua_settable(L, -3);
  150. lua_pushliteral(L, "sec");
  151. lua_pushinteger(L, rtime->tm_sec);
  152. lua_settable(L, -3);
  153. }
  154. static int l_gnss_callback(lua_State *L, void* ptr){
  155. (void)ptr;
  156. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  157. luat_libgnss_uart_recv_cb(msg->arg1, msg->arg2);
  158. return 0;
  159. }
  160. static void l_libgnss_uart_recv_cb(int uart_id, uint32_t data_len)
  161. {
  162. rtos_msg_t msg = {0};
  163. msg.handler = l_gnss_callback;
  164. msg.arg1 = uart_id;
  165. msg.arg2 = data_len;
  166. luat_msgbus_put(&msg, 0);
  167. }
  168. /**
  169. 处理nmea数据
  170. @api libgnss.parse(str)
  171. @string 原始nmea数据
  172. @usage
  173. -- 解析nmea数据
  174. libgnss.parse(indata)
  175. log.info("nmea", json.encode(libgnss.getRmc(), "11g"))
  176. */
  177. static int l_libgnss_parse(lua_State *L) {
  178. size_t len = 0;
  179. const char* str = NULL;
  180. luat_zbuff_t* zbuff = NULL;
  181. if (lua_type(L, 1) == LUA_TSTRING) {
  182. str = luaL_checklstring(L, 1, &len);
  183. }
  184. else if (lua_isuserdata(L, 1)) {
  185. zbuff = tozbuff(L);
  186. str = (const char*)zbuff->addr;
  187. len = zbuff->used;
  188. }
  189. else {
  190. return 0;
  191. }
  192. if (len > 0) {
  193. luat_libgnss_parse_data(str, len);
  194. }
  195. return 0;
  196. }
  197. /**
  198. 当前是否已经定位成功
  199. @api libgnss.isFix()
  200. @return boolean 定位成功与否
  201. @usage
  202. log.info("nmea", "isFix", libgnss.isFix())
  203. */
  204. static int l_libgnss_is_fix(lua_State *L) {
  205. lua_pushboolean(L, gnssctx.frame_rmc.valid != 0 ? 1 : 0);
  206. return 1;
  207. }
  208. /**
  209. 获取位置信息
  210. @api libgnss.getIntLocation(speed_type)
  211. @int 速度单位,默认是m/h
  212. @return int lat数据, 格式为 ddddddddd
  213. @return int lng数据, 格式为 ddddddddd
  214. @return int speed数据, 单位米. 于2023.9.26修正
  215. @usage
  216. -- 建议用libgnss.getRmc(1)
  217. log.info("nmea", "loc", libgnss.getIntLocation())
  218. -- 2023.12.11 新增speed_type参数
  219. --[[
  220. 速度单位可选值
  221. 0 - m/h 米/小时, 默认值, 整型
  222. 1 - m/s 米/秒, 浮点数
  223. 2 - km/h 千米/小时, 浮点数
  224. 3 - kn/h 英里/小时, 浮点数
  225. ]]
  226. -- 默认 米/小时
  227. log.info("nmea", "loc", libgnss.getIntLocation())
  228. -- 米/秒
  229. log.info("nmea", "loc", libgnss.getIntLocation(1))
  230. -- 千米/小时
  231. log.info("nmea", "loc", libgnss.getIntLocation(2))
  232. -- 英里/小时
  233. log.info("nmea", "loc", libgnss.getIntLocation(3))
  234. */
  235. static int l_libgnss_get_int_location(lua_State *L) {
  236. if (gnssctx.frame_rmc.valid) {
  237. lua_pushinteger(L, gnssctx.frame_rmc.latitude.value);
  238. lua_pushinteger(L, gnssctx.frame_rmc.longitude.value);
  239. int speed_type = luaL_optinteger(L, 1, 0);
  240. switch (speed_type)
  241. {
  242. case 1: // 米/秒
  243. lua_pushnumber(L, (minmea_tofloat(&(gnssctx.frame_rmc.speed)) * 1852 / 3600));
  244. break;
  245. case 2: // 千米/小时
  246. lua_pushnumber(L, (minmea_tofloat(&(gnssctx.frame_rmc.speed)) * 1.852));
  247. break;
  248. case 3: // 英里/小时
  249. lua_pushnumber(L, minmea_tofloat(&(gnssctx.frame_rmc.speed)));
  250. break;
  251. default: // 米/小时
  252. lua_pushinteger(L, (int32_t)(minmea_tofloat(&(gnssctx.frame_rmc.speed)) * 1852));
  253. break;
  254. }
  255. } else {
  256. lua_pushinteger(L, 0);
  257. lua_pushinteger(L, 0);
  258. lua_pushinteger(L, 0);
  259. }
  260. return 3;
  261. }
  262. /**
  263. 获取原始RMC位置信息
  264. @api libgnss.getRmc(data_mode)
  265. @int 坐标类数据的格式, 0-DDMM.MMM格式, 1-DDDDDDD格式, 2-DD.DDDDD格式, 3-原始RMC字符串
  266. @return table 原始rmc数据
  267. @usage
  268. -- 解析nmea
  269. log.info("nmea", "rmc", json.encode(libgnss.getRmc(2)))
  270. -- 实例输出
  271. --[[
  272. {
  273. "course":0,
  274. "valid":true, // true定位成功,false定位丢失
  275. "lat":23.4067, // 纬度, 正数为北纬, 负数为南纬
  276. "lng":113.231, // 经度, 正数为东经, 负数为西经
  277. "variation":0, // 地面航向,单位为度,从北向起顺时针计算
  278. "speed":0 // 地面速度, 单位为"节"
  279. "year":2023, // 年份
  280. "month":1, // 月份, 1-12
  281. "day":5, // 月份天, 1-31
  282. "hour":7, // 小时,0-23
  283. "min":23, // 分钟,0-59
  284. "sec":20, // 秒,0-59
  285. }
  286. ]]
  287. */
  288. static int l_libgnss_get_rmc(lua_State *L) {
  289. int mode = luaL_optinteger(L, 1, 0);
  290. lua_settop(L, 0);
  291. lua_createtable(L, 0, 12);
  292. struct tm rtime = {0};
  293. if (mode == 3) {
  294. if (gnssctx.rmc == NULL)
  295. return 0;
  296. lua_pushstring(L, gnssctx.rmc->data);
  297. return 1;
  298. }
  299. if (1) {
  300. lua_pushboolean(L, gnssctx.frame_rmc.valid);
  301. lua_setfield(L, -2, "valid");
  302. if (gnssctx.frame_rmc.valid) {
  303. push_gnss_value(L, &(gnssctx.frame_rmc.latitude), mode);
  304. }
  305. else
  306. lua_pushinteger(L, 0);
  307. lua_setfield(L, -2, "lat");
  308. if (gnssctx.frame_rmc.valid) {
  309. push_gnss_value(L, &(gnssctx.frame_rmc.longitude), mode);
  310. }
  311. else
  312. lua_pushinteger(L, 0);
  313. lua_setfield(L, -2, "lng");
  314. if (gnssctx.frame_rmc.valid) {
  315. push_gnss_value(L, &(gnssctx.frame_rmc.speed), 0);
  316. }
  317. else
  318. lua_pushinteger(L, 0);
  319. lua_setfield(L, -2, "speed");
  320. if (gnssctx.frame_rmc.valid) {
  321. push_gnss_value(L, &(gnssctx.frame_rmc.course), 0);
  322. }
  323. else
  324. lua_pushinteger(L, 0);
  325. lua_setfield(L, -2, "course");
  326. if (gnssctx.frame_rmc.valid) {
  327. push_gnss_value(L, &(gnssctx.frame_rmc.variation), 0);
  328. }
  329. else
  330. lua_pushinteger(L, 0);
  331. lua_setfield(L, -2, "variation");
  332. // 时间类
  333. minmea_getdatetime(&rtime, &gnssctx.frame_rmc.date, &gnssctx.frame_rmc.time);
  334. put_datetime(L, &rtime);
  335. }
  336. return 1;
  337. }
  338. /**
  339. 获取原始GSV信息
  340. @api libgnss.getGsv()
  341. @return table 原始GSV数据
  342. @usage
  343. -- 解析nmea
  344. log.info("nmea", "gsv", json.encode(libgnss.getGsv()))
  345. --[[实例输出
  346. {
  347. "total_sats":24, // 总可见卫星数量
  348. "sats":[
  349. {
  350. "snr":27, // 信噪比
  351. "azimuth":278, // 方向角
  352. "elevation":59, // 仰角
  353. "tp":0, // 0 - GPS, 1 - BD
  354. "nr":4 // 卫星编号
  355. },
  356. // 这里忽略了22个卫星的信息
  357. {
  358. "snr":0,
  359. "azimuth":107,
  360. "elevation":19,
  361. "tp":1,
  362. "nr":31
  363. }
  364. ]
  365. }
  366. ]]
  367. */
  368. static int l_libgnss_get_gsv(lua_State *L) {
  369. lua_createtable(L, 0, 2);
  370. size_t count = 1;
  371. uint64_t tnow = luat_mcu_tick64_ms();
  372. struct minmea_sentence_gsv frame_gsv = {0};
  373. lua_createtable(L, FRAME_GSV_MAX, 0);
  374. for (size_t i = 0; i < FRAME_GSV_MAX; i++)
  375. {
  376. if (!luat_libgnss_data_check(gnssctx.gsv[i], 3500, tnow) || !minmea_parse_gsv(&frame_gsv, gnssctx.gsv[i]->data)) {
  377. continue;
  378. }
  379. for (size_t j = 0; j < 4; j++)
  380. {
  381. if (!frame_gsv.sats[j].nr) {
  382. continue;
  383. }
  384. lua_pushinteger(L, count);
  385. lua_createtable(L, 0, 4);
  386. lua_pushliteral(L, "nr");
  387. lua_pushinteger(L, frame_gsv.sats[j].nr);
  388. lua_settable(L, -3);
  389. lua_pushliteral(L, "snr");
  390. lua_pushinteger(L, frame_gsv.sats[j].snr);
  391. lua_settable(L, -3);
  392. lua_pushliteral(L, "elevation");
  393. lua_pushinteger(L, frame_gsv.sats[j].elevation);
  394. lua_settable(L, -3);
  395. lua_pushliteral(L, "azimuth");
  396. lua_pushinteger(L, frame_gsv.sats[j].azimuth);
  397. lua_settable(L, -3);
  398. // 区分不同的卫星系统
  399. // https://receiverhelp.trimble.com/alloy-gnss/en-us/NMEA-0183messages_GSA.html
  400. lua_pushliteral(L, "tp");
  401. if (memcmp(gnssctx.gsv[i], "$GP", 3) == 0) {
  402. lua_pushinteger(L, 0);
  403. }
  404. else if (memcmp(gnssctx.gsv[i], "$GL", 3) == 0) {
  405. lua_pushinteger(L, 2);
  406. }
  407. else if (memcmp(gnssctx.gsv[i], "$GA", 3) == 0) {
  408. lua_pushinteger(L, 3);
  409. }
  410. else if (memcmp(gnssctx.gsv[i], "$BD", 3) == 0 || memcmp(gnssctx.gsv[i], "$GB", 3) == 0) {
  411. lua_pushinteger(L, 1);
  412. }
  413. else if (memcmp(gnssctx.gsv[i], "$QZ", 3) == 0) {
  414. lua_pushinteger(L, 4);
  415. }
  416. else {
  417. lua_pushinteger(L, 0);
  418. }
  419. lua_settable(L, -3);
  420. // 新增一个类型, 字符串的, 实在是各种变化无法应对
  421. lua_pushliteral(L, "tpstr");
  422. lua_pushlstring(L, gnssctx.gsv[i]->data + 1, 2);
  423. lua_settable(L, -3);
  424. lua_settable(L, -3);
  425. count = count + 1;
  426. }
  427. }
  428. lua_setfield(L, -2, "sats");
  429. lua_pushliteral(L, "total_sats");
  430. lua_pushinteger(L, count - 1);
  431. lua_settable(L, -3);
  432. return 1;
  433. }
  434. /**
  435. 获取原始GSA信息
  436. @api libgnss.getGsa(data_mode)
  437. @int 模式
  438. @return table 原始GSA数据
  439. @usage
  440. -- 获取
  441. log.info("nmea", "gsa", json.encode(libgnss.getGsa(), "11g"))
  442. -- 示例数据(模式0, 也就是默认模式)
  443. --[[
  444. {
  445. "sats":[ // 正在使用的卫星编号
  446. 9,
  447. 6,
  448. 16,
  449. 16,
  450. 26,
  451. 21,
  452. 27,
  453. 27,
  454. 4,
  455. 36,
  456. 3,
  457. 7,
  458. 8,
  459. 194
  460. ],
  461. "vdop":0.03083333, // 垂直精度因子,0.00 - 99.99,不定位时值为 99.99
  462. "pdop":0.0455, // 水平精度因子,0.00 - 99.99,不定位时值为 99.99
  463. "fix_type":3, // 定位模式, 1-未定位, 2-2D定位, 3-3D定位
  464. "hdop":0.0335 // 位置精度因子,0.00 - 99.99,不定位时值为 99.99
  465. }
  466. ]]
  467. -- 示例数据(模式1), 2024.5.26新增
  468. [
  469. {"pdop":7.8299999,"sats":[13,15,18,23],"vdop":3.2400000,"hdop":7.1300001,"fix_type":3},
  470. {"pdop":7.8299999,"sats":[20,35,8,13],"vdop":3.2400000,"hdop":7.1300001,"fix_type":3}
  471. ]
  472. */
  473. static int l_libgnss_get_gsa_mode0(lua_State *L) {
  474. struct minmea_sentence_gsa frame_gsa = {0};
  475. uint64_t tnow = luat_mcu_tick64_ms();
  476. lua_createtable(L, 0, 12);
  477. for (size_t i = 0; i < FRAME_GSA_MAX; i++)
  478. {
  479. if (!luat_libgnss_data_check(gnssctx.gsa[i], 1500, tnow) || minmea_parse_gsa(&frame_gsa, gnssctx.gsa[i]->data) != 1)
  480. {
  481. continue;
  482. }
  483. lua_pushliteral(L, "fix_type");
  484. lua_pushinteger(L, frame_gsa.fix_type);
  485. lua_settable(L, -3);
  486. lua_pushliteral(L, "pdop");
  487. push_gnss_value(L, &(frame_gsa.pdop), 0);
  488. lua_settable(L, -3);
  489. lua_pushliteral(L, "hdop");
  490. push_gnss_value(L, &(frame_gsa.hdop), 0);
  491. lua_settable(L, -3);
  492. lua_pushliteral(L, "vdop");
  493. push_gnss_value(L, &(frame_gsa.vdop), 0);
  494. lua_settable(L, -3);
  495. lua_pushliteral(L, "sysid");
  496. lua_pushinteger(L, frame_gsa.sysid);
  497. lua_settable(L, -3);
  498. break;
  499. }
  500. lua_pushliteral(L, "sats");
  501. lua_createtable(L, FRAME_GSA_MAX, 0);
  502. size_t pos = 1;
  503. for (size_t i = 0; i < FRAME_GSA_MAX; i++) {
  504. if (gnssctx.gsa[i] == NULL || minmea_parse_gsa(&frame_gsa, gnssctx.gsa[i]->data) != 1)
  505. {
  506. continue;
  507. }
  508. if (tnow - gnssctx.gsa[i]->tm > 1000) {
  509. continue;
  510. }
  511. // LLOGD("GSA: %s", gnssctx.gsa[i]->data);
  512. for (size_t j = 0; j < 12; j++)
  513. {
  514. if (frame_gsa.sats[j] == 0)
  515. continue;
  516. lua_pushinteger(L, frame_gsa.sats[j]);
  517. lua_seti(L, -2, pos);
  518. pos ++;
  519. }
  520. }
  521. lua_settable(L, -3);
  522. return 1;
  523. }
  524. static int l_libgnss_get_gsa_mode1(lua_State *L) {
  525. struct minmea_sentence_gsa frame_gsa = {0};
  526. uint64_t tnow = luat_mcu_tick64_ms();
  527. lua_createtable(L, FRAME_GSA_MAX, 0);
  528. size_t count = 0;
  529. for (size_t i = 0; i < FRAME_GSA_MAX; i++) {
  530. if (gnssctx.gsa[i] == NULL || minmea_parse_gsa(&frame_gsa, gnssctx.gsa[i]->data) != 1)
  531. {
  532. continue;
  533. }
  534. if (tnow - gnssctx.gsa[i]->tm > 1000) {
  535. continue;
  536. }
  537. count ++;
  538. lua_createtable(L, 0, 12);
  539. lua_pushliteral(L, "fix_type");
  540. lua_pushinteger(L, frame_gsa.fix_type);
  541. lua_settable(L, -3);
  542. lua_pushliteral(L, "pdop");
  543. push_gnss_value(L, &(frame_gsa.pdop), 0);
  544. lua_settable(L, -3);
  545. lua_pushliteral(L, "hdop");
  546. push_gnss_value(L, &(frame_gsa.hdop), 0);
  547. lua_settable(L, -3);
  548. lua_pushliteral(L, "vdop");
  549. push_gnss_value(L, &(frame_gsa.vdop), 0);
  550. lua_settable(L, -3);
  551. lua_pushliteral(L, "sysid");
  552. lua_pushinteger(L, frame_gsa.sysid);
  553. lua_settable(L, -3);
  554. lua_pushliteral(L, "sats");
  555. lua_createtable(L, 12, 0);
  556. size_t pos = 1;
  557. for (size_t j = 0; j < 12; j++)
  558. {
  559. if (frame_gsa.sats[j] == 0)
  560. continue;
  561. lua_pushinteger(L, frame_gsa.sats[j]);
  562. lua_seti(L, -2, pos);
  563. pos ++;
  564. }
  565. lua_settable(L, -3);
  566. lua_seti(L, -2, count);
  567. }
  568. return 1;
  569. }
  570. static int l_libgnss_get_gsa(lua_State *L) {
  571. int mode = luaL_optinteger(L, 1, 0);
  572. lua_settop(L, 0);
  573. if (1 == mode) {
  574. return l_libgnss_get_gsa_mode1(L);
  575. }
  576. else {
  577. return l_libgnss_get_gsa_mode0(L);
  578. }
  579. }
  580. /**
  581. 获取VTA速度信息
  582. @api libgnss.getVtg(data_mode)
  583. @int 可选, 3-原始字符串, 不传或者传其他值, 则返回浮点值
  584. @return table 原始VTA数据
  585. @usage
  586. -- 解析nmea
  587. log.info("nmea", "vtg", json.encode(libgnss.getVtg()))
  588. -- 示例
  589. --[[
  590. {
  591. "speed_knots":0, // 速度, 英里/小时
  592. "true_track_degrees":0, // 真北方向角
  593. "magnetic_track_degrees":0, // 磁北方向角
  594. "speed_kph":0 // 速度, 千米/小时
  595. }
  596. -- 提醒: Air780EG和Air510U,在速度<5km/h时, 不会返回方向角
  597. ]]
  598. */
  599. static int l_libgnss_get_vtg(lua_State *L) {
  600. int mode = luaL_optinteger(L, 1, 0);
  601. lua_settop(L, 0);
  602. if (gnssctx.vtg == NULL)
  603. return 0;
  604. if (mode == 3) {
  605. lua_pushstring(L, gnssctx.vtg->data);
  606. return 1;
  607. }
  608. lua_createtable(L, 0, 10);
  609. struct minmea_sentence_vtg frame_vtg = {0};
  610. minmea_parse_vtg(&frame_vtg, gnssctx.vtg->data);
  611. // lua_pushliteral(L, "faa_mode");
  612. // lua_pushlstring(L, gnssctx.frame_vtg.faa_mode, 1);
  613. // lua_settable(L, -3);
  614. lua_pushliteral(L, "true_track_degrees");
  615. push_gnss_value(L, &(frame_vtg.true_track_degrees), 0);
  616. lua_settable(L, -3);
  617. lua_pushliteral(L, "magnetic_track_degrees");
  618. push_gnss_value(L, &(frame_vtg.magnetic_track_degrees), 0);
  619. lua_settable(L, -3);
  620. lua_pushliteral(L, "speed_knots");
  621. push_gnss_value(L, &(frame_vtg.speed_knots), 0);
  622. lua_settable(L, -3);
  623. lua_pushliteral(L, "speed_kph");
  624. push_gnss_value(L, &(frame_vtg.speed_kph), 0);
  625. lua_settable(L, -3);
  626. return 1;
  627. }
  628. /**
  629. 获取原始ZDA时间和日期信息
  630. @api libgnss.getZda()
  631. @return table 原始zda数据
  632. @usage
  633. log.info("nmea", "zda", json.encode(libgnss.getZda()))
  634. -- 实例输出
  635. --[[
  636. {
  637. "minute_offset":0, // 本地时区的分钟, 一般固定输出0
  638. "hour_offset":0, // 本地时区的小时, 一般固定输出0
  639. "year":2023 // UTC 年,四位数字
  640. "month":1, // UTC 月,两位,01 ~ 12
  641. "day":5, // UTC 日,两位数字,01 ~ 31
  642. "hour":7, // 小时
  643. "min":50, // 分
  644. "sec":14, // 秒
  645. }
  646. ]]
  647. */
  648. static int l_libgnss_get_zda(lua_State *L) {
  649. lua_createtable(L, 0, 9);
  650. struct tm rtime = {0};
  651. if (gnssctx.zda != NULL) {
  652. struct minmea_sentence_zda frame_zda = {0};
  653. minmea_parse_zda(&frame_zda, gnssctx.zda->data);
  654. lua_pushliteral(L, "hour_offset");
  655. lua_pushinteger(L, frame_zda.hour_offset);
  656. lua_settable(L, -3);
  657. lua_pushliteral(L, "minute_offset");
  658. lua_pushinteger(L, frame_zda.minute_offset);
  659. lua_settable(L, -3);
  660. // 时间相关
  661. minmea_getdatetime(&rtime, &frame_zda.date, &frame_zda.time);
  662. put_datetime(L, &rtime);
  663. }
  664. return 1;
  665. }
  666. /**
  667. 设置调试模式
  668. @api libgnss.debug(mode)
  669. @bool true开启调试,false关闭调试,默认为false
  670. @usage
  671. -- 开启调试, 会输出GNSS原始数据到日志中
  672. libgnss.debug(true)
  673. -- 关闭调试
  674. libgnss.debug(false)
  675. */
  676. static int l_libgnss_debug(lua_State *L) {
  677. if (lua_isboolean(L, 1) && lua_toboolean(L, 1)) {
  678. LLOGD("Debug ON");
  679. gnss_debug = 1;
  680. }
  681. else
  682. {
  683. LLOGD("Debug OFF");
  684. gnss_debug = 0;
  685. }
  686. return 0;
  687. }
  688. /*
  689. 获取GGA数据
  690. @api libgnss.getGga(data_mode)
  691. @int 坐标类数据的格式, 0-DDMM.MMM格式, 1-DDDDDDD格式, 2-DD.DDDDD格式, 3-原始字符串
  692. @return table GGA数据, 若如不存在会返回nil
  693. @usage
  694. local gga = libgnss.getGga(2)
  695. if gga then
  696. log.info("GGA", json.encode(gga, "11g"))
  697. end
  698. --实例输出
  699. --[[
  700. {
  701. "dgps_age":0, // 差分校正时延,单位为秒
  702. "fix_quality":1, // 定位状态标识 0 - 无效,1 - 单点定位,2 - 差分定位
  703. "satellites_tracked":14, // 参与定位的卫星数量
  704. "altitude":0.255, // 海平面分离度, 或者成为海拔, 单位是米,
  705. "hdop":0.0335, // 水平精度因子,0.00 - 99.99,不定位时值为 99.99
  706. "longitude":113.231, // 经度, 正数为东经, 负数为西经
  707. "latitude":23.4067, // 纬度, 正数为北纬, 负数为南纬
  708. "height":0 // 椭球高,固定输出 1 位小数
  709. }
  710. ]]
  711. */
  712. static int l_libgnss_get_gga(lua_State* L) {
  713. int mode = luaL_optinteger(L, 1, 0);
  714. lua_settop(L, 0);
  715. if (gnssctx.gga == NULL)
  716. return 0;
  717. if (mode == 3) {
  718. lua_pushstring(L, gnssctx.gga->data);
  719. return 1;
  720. }
  721. lua_newtable(L);
  722. struct minmea_sentence_gga frame_gga = {0};
  723. minmea_parse_gga(&frame_gga, gnssctx.gga->data);
  724. lua_pushstring(L, "altitude");
  725. push_gnss_value(L, &(frame_gga.altitude), 0);
  726. lua_settable(L, -3);
  727. lua_pushstring(L, "latitude");
  728. push_gnss_value(L, &(frame_gga.latitude), mode);
  729. lua_settable(L, -3);
  730. lua_pushstring(L, "longitude");
  731. push_gnss_value(L, &(frame_gga.longitude), mode);
  732. lua_settable(L, -3);
  733. lua_pushstring(L, "fix_quality");
  734. lua_pushinteger(L, frame_gga.fix_quality);
  735. lua_settable(L, -3);
  736. lua_pushstring(L, "satellites_tracked");
  737. lua_pushinteger(L, frame_gga.satellites_tracked);
  738. lua_settable(L, -3);
  739. lua_pushstring(L, "hdop");
  740. push_gnss_value(L, &(frame_gga.hdop), 0);
  741. lua_settable(L, -3);
  742. lua_pushstring(L, "height");
  743. push_gnss_value(L, &(frame_gga.height), 0);
  744. lua_settable(L, -3);
  745. lua_pushstring(L, "dgps_age");
  746. push_gnss_value(L, &(frame_gga.dgps_age), 0);
  747. lua_settable(L, -3);
  748. return 1;
  749. }
  750. /*
  751. 获取GLL数据
  752. @api libgnss.getGll(data_mode)
  753. @int 坐标类数据的格式, 0-DDMM.MMM格式, 1-DDDDDDD格式, 2-DD.DDDDD格式
  754. @return table GLL数据, 若如不存在会返回nil
  755. @usage
  756. local gll = libgnss.getGll(2)
  757. if gll then
  758. log.info("GLL", json.encode(gll, "11g"))
  759. end
  760. -- 实例数据
  761. --[[
  762. {
  763. "status":"A", // 定位状态, A有效, B无效
  764. "mode":"A", // 定位模式, V无效, A单点解, D差分解
  765. "sec":20, // 秒, UTC时间为准
  766. "min":23, // 分钟, UTC时间为准
  767. "hour":7, // 小时, UTC时间为准
  768. "longitude":113.231, // 经度, 正数为东经, 负数为西经
  769. "latitude":23.4067, // 纬度, 正数为北纬, 负数为南纬
  770. "us":0 // 微妙数, 通常为0
  771. }
  772. ]]
  773. */
  774. static int l_libgnss_get_gll(lua_State* L) {
  775. int mode = luaL_optinteger(L, 1, 0);
  776. lua_settop(L, 0);
  777. if (gnssctx.gll == NULL)
  778. return 0;
  779. if (mode == 3) {
  780. lua_pushstring(L, gnssctx.vtg->data);
  781. return 1;
  782. }
  783. lua_newtable(L);
  784. struct minmea_sentence_gll frame_gll = {0};
  785. minmea_parse_gll(&frame_gll, gnssctx.gll->data);
  786. lua_pushstring(L, "latitude");
  787. push_gnss_value(L, &(frame_gll.latitude), mode);
  788. lua_settable(L, -3);
  789. lua_pushstring(L, "longitude");
  790. push_gnss_value(L, &(frame_gll.longitude), mode);
  791. lua_settable(L, -3);
  792. lua_pushstring(L, "mode");
  793. lua_pushfstring(L, "%c", frame_gll.mode);
  794. lua_settable(L, -3);
  795. lua_pushstring(L, "status");
  796. lua_pushfstring(L, "%c", frame_gll.status);
  797. lua_settable(L, -3);
  798. lua_pushstring(L, "hour");
  799. lua_pushinteger(L, frame_gll.time.hours);
  800. lua_settable(L, -3);
  801. lua_pushstring(L, "us");
  802. lua_pushinteger(L, frame_gll.time.microseconds);
  803. lua_settable(L, -3);
  804. lua_pushstring(L, "min");
  805. lua_pushinteger(L, frame_gll.time.minutes);
  806. lua_settable(L, -3);
  807. lua_pushstring(L, "sec");
  808. lua_pushinteger(L, frame_gll.time.seconds);
  809. lua_settable(L, -3);
  810. return 1;
  811. }
  812. /**
  813. 清除历史定位数据
  814. @api libgnss.clear()
  815. @return nil 无返回值
  816. @usage
  817. -- 该操作会清除所有定位数据
  818. */
  819. static int l_libgnss_clear(lua_State*L) {
  820. (void)L;
  821. luat_libgnss_init(true);
  822. return 0;
  823. }
  824. /*
  825. 绑定uart端口进行GNSS数据读取
  826. @api libgnss.bind(id, next_id)
  827. @int uart端口号
  828. @int 转发到uart的id, 例如虚拟uart.VUART_0
  829. @usage
  830. -- 配置串口信息, 通常为 115200 8N1
  831. uart.setup(2, 115200)
  832. -- 绑定uart, 马上开始解析GNSS数据
  833. libgnss.bind(2)
  834. -- 无需再调用uart.on然后调用libgnss.parse
  835. -- 开发期可打开调试日志
  836. libgnss.debug(true)
  837. -- 2023-01-02之后编译的固件有效
  838. -- 从uart2读取并解析, 同时转发到虚拟串口0
  839. libgnss.bind(2, uart.VUART_0)
  840. */
  841. static int l_libgnss_bind(lua_State* L) {
  842. int uart_id = luaL_checkinteger(L, 1);
  843. int next_uart_id = 0;
  844. l_libgnss_clear(L);
  845. if (libgnss_recvbuff == NULL) {
  846. libgnss_recvbuff = luat_heap_malloc(RECV_BUFF_SIZE);
  847. }
  848. luat_uart_set_app_recv(uart_id, l_libgnss_uart_recv_cb);
  849. if (lua_isinteger(L, 2)) {
  850. next_uart_id = luaL_checkinteger(L, 2);
  851. if (uart_id == libgnss_route_uart_id) {
  852. LLOGW("id == next_id , is NOT allow. %d", uart_id);
  853. return 0;
  854. }
  855. libgnss_route_uart_id = next_uart_id;
  856. }
  857. return 0;
  858. }
  859. /**
  860. 获取位置字符串
  861. @api libgnss.locStr(mode)
  862. @int 字符串模式. 0- Air780EG所需的格式
  863. @return 指定模式的字符串
  864. @usage
  865. -- 仅推荐在定位成功后调用
  866. */
  867. static int l_libgnss_locStr(lua_State *L) {
  868. int mode = luaL_optinteger(L, 1, 0);
  869. char buff[64] = {0};
  870. float lat_f = minmea_tofloat(&gnssctx.frame_rmc.latitude);
  871. float lng_f = minmea_tofloat(&gnssctx.frame_rmc.longitude);
  872. switch (mode)
  873. {
  874. case 0:
  875. snprintf_(buff, 63, "%.7g,%c,%.7g,%c,1.0",
  876. fabs(lat_f), lat_f > 0 ? 'N' : 'S',
  877. fabs(lng_f), lng_f > 0 ? 'E' : 'W');
  878. break;
  879. case 1:
  880. snprintf_(buff, 63, "%ld,%ld", gnssctx.frame_rmc.latitude.value, gnssctx.frame_rmc.longitude.value);
  881. break;
  882. default:
  883. break;
  884. }
  885. lua_pushstring(L, buff);
  886. return 1;
  887. }
  888. /**
  889. 定位成功后自动设置RTC
  890. @api libgnss.rtcAuto(enable)
  891. @bool 开启与否, 默认是false关闭
  892. @usage
  893. -- 开启自动设置RTC
  894. libgnss.rtcAuto(true)
  895. */
  896. static int l_libgnss_rtc_auto(lua_State *L) {
  897. if (lua_isboolean(L, 1) && lua_toboolean(L, 1)) {
  898. gnssctx.rtc_auto = 1;
  899. LLOGD("GNSS->RTC Auto-Set now is ON");
  900. }
  901. else {
  902. gnssctx.rtc_auto = 0;
  903. LLOGD("GNSS->RTC Auto-Set now is OFF");
  904. }
  905. return 0;
  906. }
  907. static int l_libgnss_data_cb(lua_State *L, void* ptr) {
  908. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  909. // lua_getglobal(L, "sys_pub");
  910. lua_geti(L, LUA_REGISTRYINDEX, msg->arg2);
  911. if (lua_isfunction(L, -1)) {
  912. // lua_pushliteral(gnss_L, "GNSS_RAW_DATA");
  913. lua_pushlstring(L, ptr, msg->arg1);
  914. luat_heap_free(ptr);
  915. ptr = NULL;
  916. lua_call(L, 1, 0);
  917. }
  918. else {
  919. luat_heap_free(ptr);
  920. }
  921. return 0;
  922. }
  923. int luat_libgnss_on_rawdata(const char* data, size_t len, int type) {
  924. int cb = 0;
  925. if (type == 0) {
  926. if (gnss_raw_cb == 0)
  927. return 0;
  928. cb = gnss_raw_cb;
  929. }
  930. else if (type == 1) {
  931. if (gnss_txt_cb == 0)
  932. return 0;
  933. cb = gnss_txt_cb;
  934. }
  935. else if (type == 2) {
  936. if (gnss_other_cb == 0)
  937. return 0;
  938. cb = gnss_other_cb;
  939. }
  940. else {
  941. return 0;
  942. }
  943. char* ptr = luat_heap_malloc(len);
  944. if (ptr == NULL)
  945. return 0;
  946. memcpy(ptr, data, len);
  947. rtos_msg_t msg = {
  948. .handler = l_libgnss_data_cb,
  949. .arg1 = len,
  950. .arg2 = cb,
  951. .ptr = ptr
  952. };
  953. luat_msgbus_put(&msg, 0);
  954. return 0;
  955. }
  956. /**
  957. 底层事件回调
  958. @api libgnss.on(tp, fn)
  959. @string 事件类型,当前支持"raw"
  960. @usage
  961. -- 本函数一般用于调试, 用于获取底层实际收到的数据
  962. libgnss.on("raw", function(data)
  963. log.info("GNSS", data)
  964. end)
  965. */
  966. static int l_libgnss_on(lua_State *L) {
  967. size_t len = 0;
  968. const char* tp = luaL_checklstring(L, 1, &len);
  969. if (!strcmp("raw", tp)) {
  970. if (gnss_raw_cb != 0) {
  971. luaL_unref(L, LUA_REGISTRYINDEX, gnss_raw_cb);
  972. gnss_raw_cb = 0;
  973. }
  974. if (lua_isfunction(L, 2)) {
  975. lua_pushvalue(L, 2);
  976. gnss_raw_cb = luaL_ref(L, LUA_REGISTRYINDEX);
  977. }
  978. }
  979. else if (!strcmp("txt", tp)) {
  980. if (gnss_txt_cb != 0) {
  981. luaL_unref(L, LUA_REGISTRYINDEX, gnss_txt_cb);
  982. gnss_txt_cb = 0;
  983. }
  984. if (lua_isfunction(L, 2)) {
  985. lua_pushvalue(L, 2);
  986. gnss_txt_cb = luaL_ref(L, LUA_REGISTRYINDEX);
  987. }
  988. }
  989. else if (!strcmp("other", tp)) {
  990. if (gnss_other_cb != 0) {
  991. luaL_unref(L, LUA_REGISTRYINDEX, gnss_other_cb);
  992. gnss_other_cb = 0;
  993. }
  994. if (lua_isfunction(L, 2)) {
  995. lua_pushvalue(L, 2);
  996. gnss_other_cb = luaL_ref(L, LUA_REGISTRYINDEX);
  997. }
  998. }
  999. return 0;
  1000. }
  1001. /**
  1002. 获取非标的GPTXT数据
  1003. @api libgnss.getTxt()
  1004. @return GPTXT所携带的字符串
  1005. @usage
  1006. -- 本函数于2023.6.6 添加
  1007. log.info("gnss", "txt", libgnss.getTxt())
  1008. -- 测试语句
  1009. libgnss.parse("$GPTXT,01,01,01,ANTENNA SHORT*63\r\n")
  1010. log.info("GNSS", libgnss.getTxt())
  1011. libgnss.parse("$GPTXT,01,01,01,ANTENNA OPEN*25\r\n")
  1012. log.info("GNSS", libgnss.getTxt())
  1013. libgnss.parse("$GPTXT,01,01,01,ANTENNA OK*35\r\n")
  1014. log.info("GNSS", libgnss.getTxt())
  1015. */
  1016. static int l_libgnss_get_txt(lua_State *L) {
  1017. if (gnssctx.txt == NULL) {
  1018. lua_pushliteral(L, "");
  1019. return 1;
  1020. }
  1021. struct minmea_sentence_txt txt = {0};
  1022. minmea_parse_txt(&txt, gnssctx.txt->data);
  1023. txt.txt[FRAME_TXT_MAX_LEN] = 0x00;
  1024. lua_pushstring(L, txt.txt);
  1025. return 1;
  1026. }
  1027. /*
  1028. 合成Air530Z所需要的辅助定位数据
  1029. @api libgnss.casic_aid(dt, loc)
  1030. @table 时间信息
  1031. @table 经纬度及海拔
  1032. @return string 辅助定位数据
  1033. @usage
  1034. -- 本函数适合CASIC系列GNSS模块的辅助定位信息的合成
  1035. -- 本函数 2023.11.14 新增
  1036. -- 首先是时间信息,注意是UTC时间
  1037. -- 时间来源很多, 一般建议socket.sntp()时间同步后的系统时间
  1038. local dt = os.date("!*t")
  1039. -- 然后是辅助定位坐标
  1040. -- 来源有很多方式:
  1041. -- 1. 从历史定位数据得到, 例如之前定位成功后保存到本地文件系统了
  1042. -- 2. 通过基站定位或者wifi定位获取到
  1043. -- 3. 通过IP定位获取到大概坐标
  1044. -- 坐标系是WGS84, 但鉴于是辅助定位,精度不是关键因素
  1045. local lla = {
  1046. lat = 23.12,
  1047. lng = 114.12
  1048. }
  1049. local aid = libgnss.casic_aid(dt, lla)
  1050. */
  1051. #include "luat_casic_gnss.h"
  1052. double strtod(const char *s,char **ptr);
  1053. static int l_libgnss_casic_aid(lua_State* L) {
  1054. DATETIME_STR dt = {0};
  1055. POS_LLA_STR lla = {0};
  1056. const char* data = "";
  1057. if (lua_istable(L, 1)) {
  1058. if (LUA_TNUMBER == lua_getfield(L, 1, "day")) {
  1059. dt.day = lua_tointeger(L, -1);
  1060. };
  1061. lua_pop(L, 1);
  1062. // 这里兼容month和mon两种, os.date 和 rtc.get
  1063. if (LUA_TNUMBER == lua_getfield(L, 1, "month")) {
  1064. dt.month = lua_tointeger(L, -1);
  1065. };
  1066. lua_pop(L, 1);
  1067. if (LUA_TNUMBER == lua_getfield(L, 1, "mon")) {
  1068. dt.month = lua_tointeger(L, -1);
  1069. };
  1070. lua_pop(L, 1);
  1071. if (LUA_TNUMBER == lua_getfield(L, 1, "year")) {
  1072. dt.year = lua_tointeger(L, -1);
  1073. if (dt.year > 2022)
  1074. dt.valid = 1;
  1075. };
  1076. lua_pop(L, 1);
  1077. if (LUA_TNUMBER == lua_getfield(L, 1, "hour")) {
  1078. dt.hour = lua_tointeger(L, -1);
  1079. };
  1080. lua_pop(L, 1);
  1081. if (LUA_TNUMBER == lua_getfield(L, 1, "min")) {
  1082. dt.minute = lua_tointeger(L, -1);
  1083. };
  1084. lua_pop(L, 1);
  1085. if (LUA_TNUMBER == lua_getfield(L, 1, "sec")) {
  1086. dt.second = lua_tointeger(L, -1);
  1087. };
  1088. lua_pop(L, 1);
  1089. }
  1090. if (lua_istable(L, 2)) {
  1091. lua_getfield(L, 2, "lat");
  1092. if (LUA_TNUMBER == lua_type(L, -1)) {
  1093. lla.lat = lua_tonumber(L, -1);
  1094. }
  1095. else if (LUA_TSTRING == lua_type(L, -1)) {
  1096. data = luaL_checkstring(L, -1);
  1097. lla.lat = strtod(data, NULL);
  1098. }
  1099. lua_pop(L, 1);
  1100. lua_getfield(L, 2, "lng");
  1101. if (LUA_TNUMBER == lua_type(L, -1)) {
  1102. lla.lon = lua_tonumber(L, -1);
  1103. }
  1104. else if (LUA_TSTRING == lua_type(L, -1)) {
  1105. data = luaL_checkstring(L, -1);
  1106. lla.lon = strtod(data, NULL);
  1107. }
  1108. lua_pop(L, 1);
  1109. if (LUA_TNUMBER == lua_getfield(L, 2, "alt")) {
  1110. lla.alt = lua_tonumber(L, -1);
  1111. };
  1112. if (lla.lat > 0.001 || lla.lat < -0.01)
  1113. if (lla.lon > 0.001 || lla.lon < -0.01)
  1114. lla.valid = 1;
  1115. }
  1116. char tmp[66] = {0};
  1117. casicAgnssAidIni(&dt, &lla, tmp);
  1118. lua_pushlstring(L, tmp, 66);
  1119. return 1;
  1120. };
  1121. #include "rotable2.h"
  1122. static const rotable_Reg_t reg_libgnss[] =
  1123. {
  1124. { "parse", ROREG_FUNC(l_libgnss_parse)},
  1125. { "isFix", ROREG_FUNC(l_libgnss_is_fix)},
  1126. { "getIntLocation", ROREG_FUNC(l_libgnss_get_int_location)},
  1127. { "getRmc", ROREG_FUNC(l_libgnss_get_rmc)},
  1128. { "getGsv", ROREG_FUNC(l_libgnss_get_gsv)},
  1129. { "getGsa", ROREG_FUNC(l_libgnss_get_gsa)},
  1130. { "getVtg", ROREG_FUNC(l_libgnss_get_vtg)},
  1131. { "getGga", ROREG_FUNC(l_libgnss_get_gga)},
  1132. { "getGll", ROREG_FUNC(l_libgnss_get_gll)},
  1133. { "getZda", ROREG_FUNC(l_libgnss_get_zda)},
  1134. { "locStr", ROREG_FUNC(l_libgnss_locStr)},
  1135. { "rtcAuto",ROREG_FUNC(l_libgnss_rtc_auto)},
  1136. { "on", ROREG_FUNC(l_libgnss_on)},
  1137. { "debug", ROREG_FUNC(l_libgnss_debug)},
  1138. { "clear", ROREG_FUNC(l_libgnss_clear)},
  1139. { "bind", ROREG_FUNC(l_libgnss_bind)},
  1140. { "getTxt", ROREG_FUNC(l_libgnss_get_txt)},
  1141. { "casic_aid", ROREG_FUNC(l_libgnss_casic_aid)},
  1142. { NULL, ROREG_INT(0)}
  1143. };
  1144. LUAMOD_API int luaopen_libgnss( lua_State *L ) {
  1145. luat_newlib2(L, reg_libgnss);
  1146. return 1;
  1147. }