10 -- 提醒: 本库输出的坐标,均为 WGS84 坐标系
11 -- 如需要在国内地图使用, 要转换成对应地图的坐标系, 例如 GCJ02 BD09
12 -- 相关链接: https://lbsyun.baidu.com/index.php?title=coordinate
13 -- 相关链接: https://www.openluat.com/GPS-Offset.html
15 -- 提醒: GPS功能, GNSS功能, NMEA解析功能,均为当前库的子功能
16 -- 本库的主要功能就是解析NMEA协议, 支持内置GNSS也支持外置GNSS
21 uart.on(2, "recv", function(id, len)
23 local data = uart.read(id, 1024)
24 if data and #data > 1 then
31 -- 方案2, 适合2022.12.26之后编译固件,效率更高一些
36 -- libgnss.debug(true)
38 sys.subscribe("GNSS_STATE", function(event, ticks)
42 -- ticks是事件发生的时间,一般可以忽略
43 log.info("gnss", "state", event, ticks)
46 #include "luat_base.h"
47 #include "luat_msgbus.h"
49 #include "luat_uart.h"
53 #define LUAT_LOG_TAG "gnss"
58 extern luat_libgnss_t gnssctx
;
59 // extern luat_libgnss_t *libgnss_gnsstmp;
60 extern char* libgnss_recvbuff
;
61 extern int libgnss_route_uart_id
;
62 extern int gnss_debug
;
64 void luat_uart_set_app_recv(int id
, luat_uart_recv_callback_t cb
);
66 static inline void push_gnss_value(lua_State
*L
, struct minmea_float
*f
, int mode
) {
68 lua_pushinteger(L
, 0);
74 lua_pushnumber(L
, minmea_tofloat(f
));
77 lua_pushinteger(L
, minmea_tocoord2(f
));
80 lua_pushnumber(L
, minmea_tocoord(f
));
83 lua_pushnumber(L
, minmea_tocoord(f
));
88 static int luat_libgnss_state_handler(lua_State
*L
, void* ptr
) {
90 rtos_msg_t
* msg
= (rtos_msg_t
*)lua_topointer(L
, -1);
91 lua_getglobal(L
, "sys_pub");
92 if (!lua_isfunction(L
, -1)) {
100 sys.subscribe("GNSS_STATE", function(event, ticks)
104 -- ticks是事件发生的时间,一般可以忽略
105 log.info("gnss", "state", event, ticks)
108 lua_pushliteral(L
, "GNSS_STATE");
111 case GNSS_STATE_FIXED
:
112 lua_pushliteral(L
, "FIXED");
114 case GNSS_STATE_LOSE
:
115 lua_pushliteral(L
, "LOSE");
117 case GNSS_STATE_OPEN
:
118 lua_pushliteral(L
, "OPEN");
120 case GNSS_STATE_CLOSE
:
121 lua_pushliteral(L
, "CLOSE");
126 lua_pushinteger(L
, msg
->arg2
);
131 int luat_libgnss_state_onchanged(int state
) {
132 rtos_msg_t msg
= {0};
133 msg
.handler
= luat_libgnss_state_handler
;
136 msg
.arg2
= luat_mcu_ticks();
138 luat_msgbus_put(&msg
, 0);
142 static void put_datetime(lua_State
*L
, struct tm
* rtime
) {
143 lua_pushliteral(L
, "year");
144 lua_pushinteger(L
, rtime
->tm_year
);
147 lua_pushliteral(L
, "month");
148 lua_pushinteger(L
, rtime
->tm_mon
+ 1); // 比较纠结, 要不要兼容老的呢?
151 lua_pushliteral(L
, "day");
152 lua_pushinteger(L
, rtime
->tm_mday
);
155 lua_pushliteral(L
, "hour");
156 lua_pushinteger(L
, rtime
->tm_hour
);
159 lua_pushliteral(L
, "min");
160 lua_pushinteger(L
, rtime
->tm_min
);
163 lua_pushliteral(L
, "sec");
164 lua_pushinteger(L
, rtime
->tm_sec
);
168 static int l_gnss_callback(lua_State
*L
, void* ptr
){
170 rtos_msg_t
* msg
= (rtos_msg_t
*)lua_topointer(L
, -1);
171 luat_libgnss_uart_recv_cb(msg
->arg1
, msg
->arg2
);
175 static void l_libgnss_uart_recv_cb(int uart_id
, uint32_t data_len
)
177 rtos_msg_t msg
= {0};
178 msg
.handler
= l_gnss_callback
;
181 luat_msgbus_put(&msg
, 0);
186 @api libgnss.parse(str)
190 libgnss.parse(indata)
191 log.info("nmea", json.encode(libgnss.getRmc(), "11g"))
193 static int l_libgnss_parse(lua_State
*L
) {
195 const char* str
= luaL_checklstring(L
, 1, &len
);
197 luat_libgnss_parse_data(str
, len
);
205 @return boolean 定位成功与否
207 log.info("nmea", "isFix", libgnss.isFix())
209 static int l_libgnss_is_fix(lua_State
*L
) {
210 lua_pushboolean(L
, gnssctx
.frame_rmc
.valid
!= 0 ? 1 : 0);
216 @api libgnss.getIntLocation(speed_type)
218 @return int lat数据, 格式为 ddddddddd
219 @return int lng数据, 格式为 ddddddddd
220 @return int speed数据, 单位米. 于2023.9.26修正
222 -- 建议用libgnss.getRmc(1)
223 log.info("nmea", "loc", libgnss.getIntLocation())
225 -- 2023.12.11 新增speed_type参数
228 0 - m/h 米/小时, 默认值, 整型
234 log.info("nmea", "loc", libgnss.getIntLocation())
236 log.info("nmea", "loc", libgnss.getIntLocation(1))
238 log.info("nmea", "loc", libgnss.getIntLocation(2))
240 log.info("nmea", "loc", libgnss.getIntLocation(3))
242 static int l_libgnss_get_int_location(lua_State
*L
) {
243 if (gnssctx
.frame_rmc
.valid
) {
244 lua_pushinteger(L
, gnssctx
.frame_rmc
.latitude
.value
);
245 lua_pushinteger(L
, gnssctx
.frame_rmc
.longitude
.value
);
246 int speed_type
= luaL_optinteger(L
, 1, 0);
250 lua_pushnumber(L
, (minmea_tofloat(&(gnssctx
.frame_rmc
.speed
)) * 1852 / 3600));
253 lua_pushnumber(L
, (minmea_tofloat(&(gnssctx
.frame_rmc
.speed
)) * 1.852));
256 lua_pushnumber(L
, minmea_tofloat(&(gnssctx
.frame_rmc
.speed
)));
259 lua_pushinteger(L
, (int32_t)(minmea_tofloat(&(gnssctx
.frame_rmc
.speed
)) * 1852));
264 lua_pushinteger(L
, 0);
265 lua_pushinteger(L
, 0);
266 lua_pushinteger(L
, 0);
273 @api libgnss.getRmc(data_mode)
274 @int 坐标类数据的格式, 0-DDMM.MMM格式, 1-DDDDDDD格式, 2-DD.DDDDD格式
275 @return table 原始rmc数据
278 log.info("nmea", "rmc", json.encode(libgnss.getRmc(2)))
283 "valid":true, // true定位成功,false定位丢失
284 "lat":23.4067, // 纬度, 正数为北纬, 负数为南纬
285 "lng":113.231, // 经度, 正数为东经, 负数为西经
286 "variation":0, // 地面航向,单位为度,从北向起顺时针计算
287 "speed":0 // 地面速度, 单位为"节"
289 "month":1, // 月份, 1-12
290 "day":5, // 月份天, 1-31
297 static int l_libgnss_get_rmc(lua_State
*L
) {
298 int mode
= luaL_optinteger(L
, 1, 0);
300 lua_createtable(L
, 0, 12);
302 struct tm rtime
= {0};
305 lua_pushboolean(L
, gnssctx
.frame_rmc
.valid
);
306 lua_setfield(L
, -2, "valid");
308 if (gnssctx
.frame_rmc
.valid
) {
309 push_gnss_value(L
, &(gnssctx
.frame_rmc
.latitude
), mode
);
312 lua_pushinteger(L
, 0);
313 lua_setfield(L
, -2, "lat");
315 if (gnssctx
.frame_rmc
.valid
) {
316 push_gnss_value(L
, &(gnssctx
.frame_rmc
.longitude
), mode
);
319 lua_pushinteger(L
, 0);
320 lua_setfield(L
, -2, "lng");
322 if (gnssctx
.frame_rmc
.valid
) {
323 push_gnss_value(L
, &(gnssctx
.frame_rmc
.speed
), 0);
326 lua_pushinteger(L
, 0);
327 lua_setfield(L
, -2, "speed");
329 if (gnssctx
.frame_rmc
.valid
) {
330 push_gnss_value(L
, &(gnssctx
.frame_rmc
.course
), 0);
333 lua_pushinteger(L
, 0);
334 lua_setfield(L
, -2, "course");
336 if (gnssctx
.frame_rmc
.valid
) {
337 push_gnss_value(L
, &(gnssctx
.frame_rmc
.variation
), 0);
340 lua_pushinteger(L
, 0);
341 lua_setfield(L
, -2, "variation");
344 minmea_getdatetime(&rtime
, &gnssctx
.frame_rmc
.date
, &gnssctx
.frame_rmc
.time
);
345 put_datetime(L
, &rtime
);
353 @api libgnss.getGsv()
354 @return table 原始GSV数据
357 log.info("nmea", "gsv", json.encode(libgnss.getGsv()))
360 "total_sats":24, // 总可见卫星数量
364 "azimuth":278, // 方向角
365 "elevation":59, // 仰角
366 "tp":0, // 0 - GPS, 1 - BD
381 static int l_libgnss_get_gsv(lua_State
*L
) {
382 lua_createtable(L
, 0, 2);
384 uint64_t tnow
= luat_mcu_tick64_ms();
385 struct minmea_sentence_gsv frame_gsv
= {0};
386 lua_createtable(L
, FRAME_GSV_MAX
, 0);
387 for (size_t i
= 0; i
< FRAME_GSV_MAX
; i
++)
389 if (!luat_libgnss_data_check(gnssctx
.gsv
[i
], 3500, tnow
) || !minmea_parse_gsv(&frame_gsv
, gnssctx
.gsv
[i
]->data
)) {
393 for (size_t j
= 0; j
< 4; j
++)
395 if (!frame_gsv
.sats
[j
].nr
) {
398 lua_pushinteger(L
, count
);
399 lua_createtable(L
, 0, 4);
401 lua_pushliteral(L
, "nr");
402 lua_pushinteger(L
, frame_gsv
.sats
[j
].nr
);
405 lua_pushliteral(L
, "snr");
406 lua_pushinteger(L
, frame_gsv
.sats
[j
].snr
);
409 lua_pushliteral(L
, "elevation");
410 lua_pushinteger(L
, frame_gsv
.sats
[j
].elevation
);
413 lua_pushliteral(L
, "azimuth");
414 lua_pushinteger(L
, frame_gsv
.sats
[j
].azimuth
);
418 // https://receiverhelp.trimble.com/alloy-gnss/en-us/NMEA-0183messages_GSA.html
419 lua_pushliteral(L
, "tp");
420 if (memcmp(gnssctx
.gsv
[i
], "$GP", 3) == 0) {
421 lua_pushinteger(L
, 0);
423 else if (memcmp(gnssctx
.gsv
[i
], "$GL", 3) == 0) {
424 lua_pushinteger(L
, 2);
426 else if (memcmp(gnssctx
.gsv
[i
], "$GA", 3) == 0) {
427 lua_pushinteger(L
, 3);
429 else if (memcmp(gnssctx
.gsv
[i
], "$BD", 3) == 0 || memcmp(gnssctx
.gsv
[i
], "$GB", 3) == 0) {
430 lua_pushinteger(L
, 1);
432 else if (memcmp(gnssctx
.gsv
[i
], "$QZ", 3) == 0) {
433 lua_pushinteger(L
, 4);
436 lua_pushinteger(L
, 0);
440 // 新增一个类型, 字符串的, 实在是各种变化无法应对
441 lua_pushliteral(L
, "tpstr");
442 lua_pushlstring(L
, gnssctx
.gsv
[i
]->data
+ 1, 2);
449 lua_setfield(L
, -2, "sats");
451 lua_pushliteral(L
, "total_sats");
452 lua_pushinteger(L
, count
- 1);
461 @api libgnss.getGsa(data_mode)
463 @return table 原始GSA数据
466 log.info("nmea", "gsa", json.encode(libgnss.getGsa(), "11g"))
467 -- 示例数据(模式0, 也就是默认模式)
470 "sats":[ // 正在使用的卫星编号
486 "vdop":0.03083333, // 垂直精度因子,0.00 - 99.99,不定位时值为 99.99
487 "pdop":0.0455, // 水平精度因子,0.00 - 99.99,不定位时值为 99.99
488 "fix_type":3, // 定位模式, 1-未定位, 2-2D定位, 3-3D定位
489 "hdop":0.0335 // 位置精度因子,0.00 - 99.99,不定位时值为 99.99
493 -- 示例数据(模式1), 2024.5.26新增
495 {"pdop":7.8299999,"sats":[13,15,18,23],"vdop":3.2400000,"hdop":7.1300001,"fix_type":3},
496 {"pdop":7.8299999,"sats":[20,35,8,13],"vdop":3.2400000,"hdop":7.1300001,"fix_type":3}
500 static int l_libgnss_get_gsa_mode0(lua_State
*L
) {
501 struct minmea_sentence_gsa frame_gsa
= {0};
502 uint64_t tnow
= luat_mcu_tick64_ms();
503 lua_createtable(L
, 0, 12);
505 for (size_t i
= 0; i
< FRAME_GSA_MAX
; i
++)
507 if (!luat_libgnss_data_check(gnssctx
.gsa
[i
], 1500, tnow
) || minmea_parse_gsa(&frame_gsa
, gnssctx
.gsa
[i
]->data
) != 1)
511 lua_pushliteral(L
, "fix_type");
512 lua_pushinteger(L
, frame_gsa
.fix_type
);
515 lua_pushliteral(L
, "pdop");
516 push_gnss_value(L
, &(frame_gsa
.pdop
), 0);
519 lua_pushliteral(L
, "hdop");
520 push_gnss_value(L
, &(frame_gsa
.hdop
), 0);
523 lua_pushliteral(L
, "vdop");
524 push_gnss_value(L
, &(frame_gsa
.vdop
), 0);
529 lua_pushliteral(L
, "sats");
530 lua_createtable(L
, FRAME_GSA_MAX
, 0);
532 for (size_t i
= 0; i
< FRAME_GSA_MAX
; i
++) {
533 if (gnssctx
.gsa
[i
] == NULL
|| minmea_parse_gsa(&frame_gsa
, gnssctx
.gsa
[i
]->data
) != 1)
537 if (tnow
- gnssctx
.gsa
[i
]->tm
> 1000) {
540 // LLOGD("GSA: %s", gnssctx.gsa[i]->data);
541 for (size_t j
= 0; j
< 12; j
++)
543 if (frame_gsa
.sats
[j
] == 0)
546 lua_pushinteger(L
, frame_gsa
.sats
[j
]);
547 lua_seti(L
, -2, pos
);
555 static int l_libgnss_get_gsa_mode1(lua_State
*L
) {
556 struct minmea_sentence_gsa frame_gsa
= {0};
557 uint64_t tnow
= luat_mcu_tick64_ms();
559 lua_createtable(L
, FRAME_GSA_MAX
, 0);
561 for (size_t i
= 0; i
< FRAME_GSA_MAX
; i
++) {
562 if (gnssctx
.gsa
[i
] == NULL
|| minmea_parse_gsa(&frame_gsa
, gnssctx
.gsa
[i
]->data
) != 1)
566 if (tnow
- gnssctx
.gsa
[i
]->tm
> 1000) {
570 lua_createtable(L
, 0, 12);
571 lua_pushliteral(L
, "fix_type");
572 lua_pushinteger(L
, frame_gsa
.fix_type
);
575 lua_pushliteral(L
, "pdop");
576 push_gnss_value(L
, &(frame_gsa
.pdop
), 0);
579 lua_pushliteral(L
, "hdop");
580 push_gnss_value(L
, &(frame_gsa
.hdop
), 0);
583 lua_pushliteral(L
, "vdop");
584 push_gnss_value(L
, &(frame_gsa
.vdop
), 0);
587 lua_pushliteral(L
, "sats");
588 lua_createtable(L
, 12, 0);
590 for (size_t j
= 0; j
< 12; j
++)
592 if (frame_gsa
.sats
[j
] == 0)
595 lua_pushinteger(L
, frame_gsa
.sats
[j
]);
596 lua_seti(L
, -2, pos
);
600 lua_seti(L
, -2, count
);
604 static int l_libgnss_get_gsa(lua_State
*L
) {
605 int mode
= luaL_optinteger(L
, 1, 0);
608 return l_libgnss_get_gsa_mode1(L
);
611 return l_libgnss_get_gsa_mode0(L
);
618 @api libgnss.getVtg(data_mode)
619 @int 可选, 3-原始字符串, 不传或者传其他值, 则返回浮点值
620 @return table 原始VTA数据
623 log.info("nmea", "vtg", json.encode(libgnss.getVtg()))
627 "speed_knots":0, // 速度, 英里/小时
628 "true_track_degrees":0, // 真北方向角
629 "magnetic_track_degrees":0, // 磁北方向角
630 "speed_kph":0 // 速度, 千米/小时
632 -- 提醒: Air780EG和Air510U,在速度<5km/h时, 不会返回方向角
635 static int l_libgnss_get_vtg(lua_State
*L
) {
636 int mode
= luaL_optinteger(L
, 1, 0);
638 if (gnssctx
.vtg
== NULL
)
641 lua_pushstring(L
, gnssctx
.vtg
->data
);
644 lua_createtable(L
, 0, 10);
645 struct minmea_sentence_vtg frame_vtg
= {0};
646 minmea_parse_vtg(&frame_vtg
, gnssctx
.vtg
->data
);
648 // lua_pushliteral(L, "faa_mode");
649 // lua_pushlstring(L, gnssctx.frame_vtg.faa_mode, 1);
650 // lua_settable(L, -3);
652 lua_pushliteral(L
, "true_track_degrees");
653 push_gnss_value(L
, &(frame_vtg
.true_track_degrees
), 0);
656 lua_pushliteral(L
, "magnetic_track_degrees");
657 push_gnss_value(L
, &(frame_vtg
.magnetic_track_degrees
), 0);
660 lua_pushliteral(L
, "speed_knots");
661 push_gnss_value(L
, &(frame_vtg
.speed_knots
), 0);
664 lua_pushliteral(L
, "speed_kph");
665 push_gnss_value(L
, &(frame_vtg
.speed_kph
), 0);
673 @api libgnss.getZda()
674 @return table 原始zda数据
676 log.info("nmea", "zda", json.encode(libgnss.getZda()))
680 "minute_offset":0, // 本地时区的分钟, 一般固定输出0
681 "hour_offset":0, // 本地时区的小时, 一般固定输出0
682 "year":2023 // UTC 年,四位数字
683 "month":1, // UTC 月,两位,01 ~ 12
684 "day":5, // UTC 日,两位数字,01 ~ 31
691 static int l_libgnss_get_zda(lua_State
*L
) {
692 lua_createtable(L
, 0, 9);
693 struct tm rtime
= {0};
694 if (gnssctx
.zda
!= NULL
) {
695 struct minmea_sentence_zda frame_zda
= {0};
696 minmea_parse_zda(&frame_zda
, gnssctx
.zda
->data
);
698 lua_pushliteral(L
, "hour_offset");
699 lua_pushinteger(L
, frame_zda
.hour_offset
);
702 lua_pushliteral(L
, "minute_offset");
703 lua_pushinteger(L
, frame_zda
.minute_offset
);
707 minmea_getdatetime(&rtime
, &frame_zda
.date
, &frame_zda
.time
);
708 put_datetime(L
, &rtime
);
716 @api libgnss.debug(mode)
717 @bool true开启调试,false关闭调试,默认为false
719 -- 开启调试, 会输出GNSS原始数据到日志中
724 static int l_libgnss_debug(lua_State
*L
) {
725 if (lua_isboolean(L
, 1) && lua_toboolean(L
, 1)) {
739 @api libgnss.getGga(data_mode)
740 @int 坐标类数据的格式, 0-DDMM.MMM格式, 1-DDDDDDD格式, 2-DD.DDDDD格式, 3-原始字符串
741 @return table GGA数据, 若如不存在会返回nil
743 local gga = libgnss.getGga(2)
745 log.info("GGA", json.encode(gga, "11g"))
750 "dgps_age":0, // 差分校正时延,单位为秒
751 "fix_quality":1, // 定位状态标识 0 - 无效,1 - 单点定位,2 - 差分定位
752 "satellites_tracked":14, // 参与定位的卫星数量
753 "altitude":0.255, // 海平面分离度, 或者成为海拔, 单位是米,
754 "hdop":0.0335, // 水平精度因子,0.00 - 99.99,不定位时值为 99.99
755 "longitude":113.231, // 经度, 正数为东经, 负数为西经
756 "latitude":23.4067, // 纬度, 正数为北纬, 负数为南纬
757 "height":0 // 椭球高,固定输出 1 位小数
761 static int l_libgnss_get_gga(lua_State
* L
) {
762 int mode
= luaL_optinteger(L
, 1, 0);
764 if (gnssctx
.gga
== NULL
)
767 lua_pushstring(L
, gnssctx
.gga
->data
);
771 struct minmea_sentence_gga frame_gga
= {0};
772 minmea_parse_gga(&frame_gga
, gnssctx
.gga
->data
);
774 lua_pushstring(L
, "altitude");
775 push_gnss_value(L
, &(frame_gga
.altitude
), 0);
778 lua_pushstring(L
, "latitude");
779 push_gnss_value(L
, &(frame_gga
.latitude
), mode
);
782 lua_pushstring(L
, "longitude");
783 push_gnss_value(L
, &(frame_gga
.longitude
), mode
);
786 lua_pushstring(L
, "fix_quality");
787 lua_pushinteger(L
, frame_gga
.fix_quality
);
790 lua_pushstring(L
, "satellites_tracked");
791 lua_pushinteger(L
, frame_gga
.satellites_tracked
);
794 lua_pushstring(L
, "hdop");
795 push_gnss_value(L
, &(frame_gga
.hdop
), 0);
798 lua_pushstring(L
, "height");
799 push_gnss_value(L
, &(frame_gga
.height
), 0);
802 lua_pushstring(L
, "dgps_age");
803 push_gnss_value(L
, &(frame_gga
.dgps_age
), 0);
811 @api libgnss.getGll(data_mode)
812 @int 坐标类数据的格式, 0-DDMM.MMM格式, 1-DDDDDDD格式, 2-DD.DDDDD格式
813 @return table GLL数据, 若如不存在会返回nil
815 local gll = libgnss.getGll(2)
817 log.info("GLL", json.encode(gll, "11g"))
822 "status":"A", // 定位状态, A有效, B无效
823 "mode":"A", // 定位模式, V无效, A单点解, D差分解
824 "sec":20, // 秒, UTC时间为准
825 "min":23, // 分钟, UTC时间为准
826 "hour":7, // 小时, UTC时间为准
827 "longitude":113.231, // 经度, 正数为东经, 负数为西经
828 "latitude":23.4067, // 纬度, 正数为北纬, 负数为南纬
833 static int l_libgnss_get_gll(lua_State
* L
) {
834 int mode
= luaL_optinteger(L
, 1, 0);
836 if (gnssctx
.gll
== NULL
)
839 lua_pushstring(L
, gnssctx
.vtg
->data
);
843 struct minmea_sentence_gll frame_gll
= {0};
844 minmea_parse_gll(&frame_gll
, gnssctx
.gll
->data
);
846 lua_pushstring(L
, "latitude");
847 push_gnss_value(L
, &(frame_gll
.latitude
), mode
);
850 lua_pushstring(L
, "longitude");
851 push_gnss_value(L
, &(frame_gll
.longitude
), mode
);
854 lua_pushstring(L
, "mode");
855 lua_pushfstring(L
, "%c", frame_gll
.mode
);
858 lua_pushstring(L
, "status");
859 lua_pushfstring(L
, "%c", frame_gll
.status
);
862 lua_pushstring(L
, "hour");
863 lua_pushinteger(L
, frame_gll
.time
.hours
);
865 lua_pushstring(L
, "us");
866 lua_pushinteger(L
, frame_gll
.time
.microseconds
);
868 lua_pushstring(L
, "min");
869 lua_pushinteger(L
, frame_gll
.time
.minutes
);
871 lua_pushstring(L
, "sec");
872 lua_pushinteger(L
, frame_gll
.time
.seconds
);
885 static int l_libgnss_clear(lua_State
*L
) {
887 memset(&gnssctx
.frame_rmc
, 0, sizeof(struct minmea_sentence_rmc
));
893 @api libgnss.bind(id, next_id)
895 @int 转发到uart的id, 例如虚拟uart.VUART_0
897 -- 配置串口信息, 通常为 115200 8N1
898 uart.setup(2, 115200)
899 -- 绑定uart, 马上开始解析GNSS数据
901 -- 无需再调用uart.on然后调用libgnss.parse
905 -- 2023-01-02之后编译的固件有效
906 -- 从uart2读取并解析, 同时转发到虚拟串口0
907 libgnss.bind(2, uart.VUART_0)
909 static int l_libgnss_bind(lua_State
* L
) {
910 int uart_id
= luaL_checkinteger(L
, 1);
912 if (libgnss_recvbuff
== NULL
) {
913 libgnss_recvbuff
= luat_heap_malloc(RECV_BUFF_SIZE
);
915 if (luat_uart_exist(uart_id
)) {
916 //uart_app_recvs[uart_id] = nmea_uart_recv_cb;
917 luat_uart_set_app_recv(uart_id
, l_libgnss_uart_recv_cb
);
919 if (lua_isinteger(L
, 2)) {
920 libgnss_route_uart_id
= luaL_checkinteger(L
, 2);
928 @api libgnss.locStr(mode)
929 @int 字符串模式. 0- Air780EG所需的格式
934 static int l_libgnss_locStr(lua_State
*L
) {
935 int mode
= luaL_optinteger(L
, 1, 0);
937 float lat_f
= minmea_tofloat(&gnssctx
.frame_rmc
.latitude
);
938 float lng_f
= minmea_tofloat(&gnssctx
.frame_rmc
.longitude
);
942 snprintf_(buff
, 63, "%.7g,%c,%.7g,%c,1.0",
943 fabs(lat_f
), lat_f
> 0 ? 'N' : 'S',
944 fabs(lng_f
), lng_f
> 0 ? 'E' : 'W');
947 snprintf_(buff
, 63, "%d,%d", gnssctx
.frame_rmc
.latitude
.value
, gnssctx
.frame_rmc
.longitude
.value
);
952 lua_pushstring(L
, buff
);
958 @api libgnss.rtcAuto(enable)
959 @bool 开启与否, 默认是false关闭
962 libgnss.rtcAuto(true)
964 static int l_libgnss_rtc_auto(lua_State
*L
) {
965 if (lua_isboolean(L
, 1) && lua_toboolean(L
, 1)) {
966 gnssctx
.rtc_auto
= 1;
967 LLOGD("GNSS->RTC Auto-Set now is ON");
970 gnssctx
.rtc_auto
= 0;
971 LLOGD("GNSS->RTC Auto-Set now is OFF");
976 //临时处理, 当前GNSS处理均在lua线程
977 // static lua_State *gnss_L;
978 static int gnss_raw_cb
= 0;
980 int luat_libgnss_rawdata_cb(lua_State
*L
, void* ptr
) {
981 rtos_msg_t
* msg
= (rtos_msg_t
*)lua_topointer(L
, -1);
982 // lua_getglobal(L, "sys_pub");
983 lua_geti(L
, LUA_REGISTRYINDEX
, gnss_raw_cb
);
984 if (lua_isfunction(L
, -1)) {
985 // lua_pushliteral(gnss_L, "GNSS_RAW_DATA");
986 lua_pushlstring(L
, ptr
, msg
->arg1
);
997 int luat_libgnss_on_rawdata(const char* data
, size_t len
) {
998 if (gnss_raw_cb
== 0)
1000 char* ptr
= luat_heap_malloc(len
);
1003 memcpy(ptr
, data
, len
);
1005 .handler
= luat_libgnss_rawdata_cb
,
1009 luat_msgbus_put(&msg
, 0);
1015 @api libgnss.on(tp, fn)
1016 @string 事件类型,当前支持"raw"
1018 -- 本函数一般用于调试, 用于获取底层实际收到的数据
1019 libgnss.on("raw", function(data)
1020 log.info("GNSS", data)
1023 static int l_libgnss_on(lua_State
*L
) {
1025 const char* tp
= luaL_checklstring(L
, 1, &len
);
1026 if (!strcmp("raw", tp
)) {
1027 if (gnss_raw_cb
!= 0) {
1028 luaL_unref(L
, LUA_REGISTRYINDEX
, gnss_raw_cb
);
1031 if (lua_isfunction(L
, 2)) {
1032 lua_pushvalue(L
, 2);
1033 gnss_raw_cb
= luaL_ref(L
, LUA_REGISTRYINDEX
);
1041 @api libgnss.getTxt()
1042 @return GPTXT所携带的字符串
1045 log.info("gnss", "txt", libgnss.getTxt())
1048 libgnss.parse("$GPTXT,01,01,01,ANTENNA SHORT*63\r\n")
1049 log.info("GNSS", libgnss.getTxt())
1050 libgnss.parse("$GPTXT,01,01,01,ANTENNA OPEN*25\r\n")
1051 log.info("GNSS", libgnss.getTxt())
1052 libgnss.parse("$GPTXT,01,01,01,ANTENNA OK*35\r\n")
1053 log.info("GNSS", libgnss.getTxt())
1055 static int l_libgnss_get_txt(lua_State
*L
) {
1056 if (gnssctx
.txt
== NULL
) {
1057 lua_pushliteral(L
, "");
1060 struct minmea_sentence_txt txt
= {0};
1061 minmea_parse_txt(&txt
, gnssctx
.txt
->data
);
1062 txt
.txt
[FRAME_TXT_MAX_LEN
] = 0x00;
1063 lua_pushstring(L
, txt
.txt
);
1069 @api libgnss.casic_aid(dt, loc)
1072 @return string 辅助定位数据
1074 -- 本函数适合CASIC系列GNSS模块的辅助定位信息的合成
1075 -- 本函数 2023.11.14 新增
1078 -- 时间来源很多, 一般建议socket.sntp()时间同步后的系统时间
1079 local dt = os.date("!*t")
1083 -- 1. 从历史定位数据得到, 例如之前定位成功后保存到本地文件系统了
1084 -- 2. 通过基站定位或者wifi定位获取到
1086 -- 坐标系是WGS84, 但鉴于是辅助定位,精度不是关键因素
1092 local aid = libgnss.casic_aid(dt, lla)
1094 #include "luat_casic_gnss.h"
1095 double strtod(const char *s
,char **ptr
);
1096 static int l_libgnss_casic_aid(lua_State
* L
) {
1097 DATETIME_STR dt
= {0};
1098 POS_LLA_STR lla
= {0};
1099 const char* data
= "";
1101 if (lua_istable(L
, 1)) {
1102 if (LUA_TNUMBER
== lua_getfield(L
, 1, "day")) {
1103 dt
.day
= lua_tointeger(L
, -1);
1106 // 这里兼容month和mon两种, os.date 和 rtc.get
1107 if (LUA_TNUMBER
== lua_getfield(L
, 1, "month")) {
1108 dt
.month
= lua_tointeger(L
, -1);
1111 if (LUA_TNUMBER
== lua_getfield(L
, 1, "mon")) {
1112 dt
.month
= lua_tointeger(L
, -1);
1116 if (LUA_TNUMBER
== lua_getfield(L
, 1, "year")) {
1117 dt
.year
= lua_tointeger(L
, -1);
1122 if (LUA_TNUMBER
== lua_getfield(L
, 1, "hour")) {
1123 dt
.hour
= lua_tointeger(L
, -1);
1126 if (LUA_TNUMBER
== lua_getfield(L
, 1, "min")) {
1127 dt
.minute
= lua_tointeger(L
, -1);
1130 if (LUA_TNUMBER
== lua_getfield(L
, 1, "sec")) {
1131 dt
.second
= lua_tointeger(L
, -1);
1135 if (lua_istable(L
, 2)) {
1136 lua_getfield(L
, 2, "lat");
1137 if (LUA_TNUMBER
== lua_type(L
, -1)) {
1138 lla
.lat
= lua_tonumber(L
, -1);
1140 else if (LUA_TSTRING
== lua_type(L
, -1)) {
1141 data
= luaL_checkstring(L
, -1);
1142 lla
.lat
= strtod(data
, NULL
);
1146 lua_getfield(L
, 2, "lng");
1147 if (LUA_TNUMBER
== lua_type(L
, -1)) {
1148 lla
.lon
= lua_tonumber(L
, -1);
1150 else if (LUA_TSTRING
== lua_type(L
, -1)) {
1151 data
= luaL_checkstring(L
, -1);
1152 lla
.lon
= strtod(data
, NULL
);
1155 if (LUA_TNUMBER
== lua_getfield(L
, 2, "alt")) {
1156 lla
.alt
= lua_tonumber(L
, -1);
1159 if (lla
.lat
> 0.001 || lla
.lat
< -0.01)
1160 if (lla
.lon
> 0.001 || lla
.lon
< -0.01)
1164 casicAgnssAidIni(&dt
, &lla
, tmp
);
1165 lua_pushlstring(L
, tmp
, 66);
1169 #include "rotable2.h"
1170 static const rotable_Reg_t reg_libgnss
[] =
1172 { "parse", ROREG_FUNC(l_libgnss_parse
)},
1173 { "isFix", ROREG_FUNC(l_libgnss_is_fix
)},
1174 { "getIntLocation", ROREG_FUNC(l_libgnss_get_int_location
)},
1175 { "getRmc", ROREG_FUNC(l_libgnss_get_rmc
)},
1176 { "getGsv", ROREG_FUNC(l_libgnss_get_gsv
)},
1177 { "getGsa", ROREG_FUNC(l_libgnss_get_gsa
)},
1178 { "getVtg", ROREG_FUNC(l_libgnss_get_vtg
)},
1179 { "getGga", ROREG_FUNC(l_libgnss_get_gga
)},
1180 { "getGll", ROREG_FUNC(l_libgnss_get_gll
)},
1181 { "getZda", ROREG_FUNC(l_libgnss_get_zda
)},
1182 { "locStr", ROREG_FUNC(l_libgnss_locStr
)},
1183 { "rtcAuto",ROREG_FUNC(l_libgnss_rtc_auto
)},
1184 { "on", ROREG_FUNC(l_libgnss_on
)},
1186 { "debug", ROREG_FUNC(l_libgnss_debug
)},
1187 { "clear", ROREG_FUNC(l_libgnss_clear
)},
1188 { "bind", ROREG_FUNC(l_libgnss_bind
)},
1190 { "getTxt", ROREG_FUNC(l_libgnss_get_txt
)},
1191 { "casic_aid", ROREG_FUNC(l_libgnss_casic_aid
)},
1193 { NULL
, ROREG_INT(0)}
1196 LUAMOD_API
int luaopen_libgnss( lua_State
*L
) {
1197 luat_newlib2(L
, reg_libgnss
);