修改nmeaLib库增加北斗(BD)和格洛纳斯(GNSS)解析
修改nmeaLib库增加北斗(BD)和格洛纳斯(GNSS)解析
- 一、nmealib库下载
- 二、NMEA协议介绍
- 1. 概述
- 2. 版本
- 3. 数据格式
- 4. 常见消息类型
- 5. 通信方式
- 6. 优势
- 7. 应用示例
- 三、修改nmealib库
- 1、修改sentence.h及sentence.c文件
- 2、修改info.h文件
- 3、修改parse.c .h文件
- 4 、修改paser.c文件
- 四、测试
- 五、完成工程加源码下载
一、nmealib库下载
点击链接nmeaLib跳转:
点击下载
二、NMEA协议介绍
NMEA消息头分为三种
1.GP代表GPS系统单独定位
2.BD代表BD2系统单独定位
3.GN代表GPS与DB2系统混合定位
1. 概述
- 全称:National Marine Electronics Association(国家海洋电子协会)协议
- 目的:标准化海上电子设备之间的数据通信
- 应用领域:航海、航空、汽车导航等
NMEA(National Marine Electronics Association)协议是用于海洋电子设备之间通信的标准协议。它广泛应用于GPS接收器、航海仪器等设备中。NMEA数据以ASCII字符串形式传输,通常以“$”开头,以“*”和校验和结束。以下是NMEA数据解析的基本方法:
2. 版本
- 常见版本:0183 和 4.00
- 最新版本:NMEA 4.00(2019年发布)
3. 数据格式
- 基本结构:每条消息以
$
开头,以*
结束 - 校验和:消息中包含校验和,用于验证数据完整性
4. 常见消息类型
- GGA:全球定位系统固定数据
- RMC:推荐最小定位信息
- VTG:航向和地面速度
- GLL:地理定位
- ZDA:时间与日期
5. 通信方式
- 波特率:通常为 4800 bps,也可设置为更高
- 接口:串行接口(RS-232、RS-422、RS-485)
- 网络支持:通过 NMEA 2000 协议支持网络通信
6. 优势
- 标准化:确保不同制造商设备的兼容性
- 简单易用:文本格式,易于解析
- 广泛支持:多数导航设备和软件都支持 NMEA
7. 应用示例
- 航海:GPS接收器与自动驾驶仪通信
- 航空:飞行管理计算机与导航系统通信
- 汽车:车载导航系统与传感器通信
三、修改nmealib库
1、修改sentence.h及sentence.c文件
新增支持的协议名
enum nmeaPACKTYPE
{GPNON = 0x0000, /**< Unknown packet type. */GPGGA = 0x0001, /**< GGA - Essential fix data which provide 3D location and accuracy data. */BDGGA = 0x0010, /**< GGA - Essential fix data which provide 3D location and accuracy data. */GNGGA = 0x0100, /**< GGA - Essential fix data which provide 3D location and accuracy data. */GPGSA = 0x0002, /**< GSA - GPS receiver operating mode, SVs used for navigation, and DOP values. */BDGSA = 0x0020, /**< GSA - GPS receiver operating mode, SVs used for navigation, and DOP values. */GNGSA = 0x0200, /**< GSA - GPS receiver operating mode, SVs used for navigation, and DOP values. */GPGSV = 0x0004, /**< GSV - Number of SVs in view, PRN numbers, elevation, azimuth & SNR values. */BDGSV = 0x0040, /**< GSV - Number of SVs in view, PRN numbers, elevation, azimuth & SNR values. */GNGSV = 0x0400, /**< GSV - Number of SVs in view, PRN numbers, elevation, azimuth & SNR values. */GPRMC = 0x0008, /**< RMC - Recommended Minimum Specific GPS/TRANSIT Data. */BDRMC = 0x0080, /**< RMC - Recommended Minimum Specific GPS/TRANSIT Data. */GNRMC = 0x0800, /**< RMC - Recommended Minimum Specific GPS/TRANSIT Data. */GPVTG = 0x1000, /**< VTG - Actual track made good and speed over ground. */BDVTG = 0x2000, /**< VTG - Actual track made good and speed over ground. */GNVTG = 0x4000 /**< VTG - Actual track made good and speed over ground. */
};
每个类型都需要增加相关结构体,BD和GP、GN只是前面的标识不一样,数据都是一样的
typedef struct _nmeaGPGGA
{nmeaTIME utc; /**< UTC of position (just time) */double lat; /**< Latitude in NDEG - [degree][min].[sec/60] */char ns; /**< [N]orth or [S]outh */double lon; /**< Longitude in NDEG - [degree][min].[sec/60] */char ew; /**< [E]ast or [W]est */int sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */int satinuse; /**< Number of satellites in use (not those in view) */double HDOP; /**< Horizontal dilution of precision */double elv; /**< Antenna altitude above/below mean sea level (geoid) */char elv_units; /**< [M]eters (Antenna height unit) */double diff; /**< Geoidal separation (Diff. between WGS-84 earth ellipsoid and mean sea level. '-' = geoid is below WGS-84 ellipsoid) */char diff_units; /**< [M]eters (Units of geoidal separation) */double dgps_age; /**< Time in seconds since last DGPS update */int dgps_sid; /**< DGPS station ID number */} nmeaGPGGA, nmeaBDGGA, nmeaGNGGA;
/*** GSA packet information structure (Satellite status)*/
typedef struct _nmeaGPGSA
{char fix_mode; /**< Mode (M = Manual, forced to operate in 2D or 3D; A = Automatic, 3D/2D) */int fix_type; /**< Type, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */int sat_prn[NMEA_MAXSAT]; /**< PRNs of satellites used in position fix (null for unused fields) */double PDOP; /**< Dilution of precision */double HDOP; /**< Horizontal dilution of precision */double VDOP; /**< Vertical dilution of precision */} nmeaGPGSA, nmeaBDGSA, nmeaGNGSA;/*** GSV packet information structure (Satellites in view)*/
typedef struct _nmeaGPGSV
{int pack_count; /**< Total number of messages of this type in this cycle */int pack_index; /**< Message number */int sat_count; /**< Total number of satellites in view */nmeaSATELLITE sat_data[NMEA_SATINPACK];} nmeaGPGSV, nmeaBDGSV, nmeaGNGSV;
/*** RMC packet information structure (Recommended Minimum sentence C)*/
typedef struct _nmeaGPRMC
{nmeaTIME utc; /**< UTC of position */char status; /**< Status (A = active or V = void) */double lat; /**< Latitude in NDEG - [degree][min].[sec/60] */char ns; /**< [N]orth or [S]outh */double lon; /**< Longitude in NDEG - [degree][min].[sec/60] */char ew; /**< [E]ast or [W]est */double speed; /**< Speed over the ground in knots */double direction; /**< Track angle in degrees True */double declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */char declin_ew; /**< [E]ast or [W]est */char mode; /**< Mode indicator of fix type (A = autonomous, D = differential, E = estimated, N = not valid, S = simulator) */} nmeaGPRMC, nmeaBDRMC, nmeaGNRMC;/*** VTG packet information structure (Track made good and ground speed)*/
typedef struct _nmeaGPVTG
{double dir; /**< True track made good (degrees) */char dir_t; /**< Fixed text 'T' indicates that track made good is relative to true north */double dec; /**< Magnetic track made good */char dec_m; /**< Fixed text 'M' */double spn; /**< Ground speed, knots */char spn_n; /**< Fixed text 'N' indicates that speed over ground is in knots */double spk; /**< Ground speed, kilometers per hour */char spk_k; /**< Fixed text 'K' indicates that speed over ground is in kilometers/hour */} nmeaGPVTG, nmeaBDVTG, nmeaGNVTG;
2、修改info.h文件
/*** NMEA library* URL: http://nmea.sourceforge.net* Author: Tim (xtimor@gmail.com)* Licence: http://www.gnu.org/licenses/lgpl.html* $Id: info.h 10 2007-11-15 14:50:15Z xtimor $**//*! \file */#ifndef __NMEA_INFO_H__
#define __NMEA_INFO_H__#include "time.h"#define NMEA_SIG_BAD (0)
#define NMEA_SIG_LOW (1)
#define NMEA_SIG_MID (2)
#define NMEA_SIG_HIGH (3)#define NMEA_FIX_BAD (1)
#define NMEA_FIX_2D (2)
#define NMEA_FIX_3D (3)#define NMEA_MAXSAT (12)
#define NMEA_SATINPACK (4)
#define NMEA_NSATPACKS (NMEA_MAXSAT / NMEA_SATINPACK)#define NMEA_DEF_LAT (5001.2621)
#define NMEA_DEF_LON (3613.0595)#ifdef __cplusplus
extern "C" {
#endif/*** Position data in fractional degrees or radians*/
typedef struct _nmeaPOS
{double lat; /**< Latitude */double lon; /**< Longitude */} nmeaPOS;/*** Information about satellite* @see nmeaSATINFO* @see nmeaGPGSV*/
typedef struct _nmeaSATELLITE
{int id; /**< Satellite PRN number */int in_use; /**< Used in position fix */int elv; /**< Elevation in degrees, 90 maximum */int azimuth; /**< Azimuth, degrees from true north, 000 to 359 */int sig; /**< Signal, 00-99 dB */} nmeaSATELLITE;typedef struct _nmeaGenerNumber
{unsigned int sum;unsigned int GP;unsigned int BD;unsigned int GN;
} nmeaGenerNumber;
/*** Information about all satellites in view* @see nmeaINFO* @see nmeaGPGSV*/
typedef struct _nmeaSATINFO
{int inuse; /**< Number of satellites in use (not those in view) */int inuseGP; /**< Number of satellites in use (not those in view) */int inuseBD; /**< Number of satellites in use (not those in view) */int inuseGN; /**< Number of satellites in use (not those in view) */int inview; /**< Total number of satellites in view */int inviewGP; /**< Total number of satellites in view */int inviewBD; /**< Total number of satellites in view */int inviewGN; /**< Total number of satellites in view */int sat_prnGP[NMEA_MAXSAT]; /*存储GP包中使用的卫星id*/int sat_prnBD[NMEA_MAXSAT]; /*存储BD包中使用的卫星id*/int sat_prnGN[NMEA_MAXSAT]; /*存储GN包中使用的卫星id*/nmeaSATELLITE sat[NMEA_MAXSAT]; /**< Satellites information */nmeaSATELLITE satGP[NMEA_MAXSAT]; /**< Satellites information */nmeaSATELLITE satBD[NMEA_MAXSAT]; /**< Satellites information */nmeaSATELLITE satGN[NMEA_MAXSAT]; /**< Satellites information */nmeaGenerNumber insig_greater35;nmeaGenerNumber insig_32to35;
} nmeaSATINFO;/*** Summary GPS information from all parsed packets,* used also for generating NMEA stream* @see nmea_parse* @see nmea_GPGGA2info, nmea_...2info*/
typedef struct _nmeaINFO
{int smask; /**< Mask specifying types of packages from which data have been obtained */nmeaTIME utc; /**< UTC of position */int sig; /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */int fix; /**< Operating mode, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */double PDOP; /**< Position Dilution Of Precision */double HDOP; /**< Horizontal Dilution Of Precision */double VDOP; /**< Vertical Dilution Of Precision */double lat; /**< Latitude in NDEG - +/-[degree][min].[sec/60] */double lon; /**< Longitude in NDEG - +/-[degree][min].[sec/60] */double elv; /**< Antenna altitude above/below mean sea level (geoid) in meters */double speed; /**< Speed over the ground in kilometers/hour */double direction; /**< Track angle in degrees True */double declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */nmeaSATINFO satinfo; /**< Satellites information */} nmeaINFO;void nmea_zero_INFO(nmeaINFO *info);#ifdef __cplusplus
}
#endif#endif /* __NMEA_INFO_H__ */
3、修改parse.c .h文件
对所有的nmea_parse_*方法 增加BD与GN的解析
对所有的name_*2info方法 增加BD与GN的解析
parse.h
/*** NMEA library* URL: http://nmea.sourceforge.net* Author: Tim (xtimor@gmail.com)* Licence: http://www.gnu.org/licenses/lgpl.html* $Id: parse.h 4 2007-08-27 13:11:03Z xtimor $**/#ifndef __NMEA_PARSE_H__
#define __NMEA_PARSE_H__#include "sentence.h"#ifdef __cplusplus
extern "C" {
#endifint nmea_pack_type(const char *buff, int buff_sz);
int nmea_find_tail(const char *buff, int buff_sz, int *res_crc);int nmea_parse_GPGGA(const char *buff, int buff_sz, nmeaGPGGA *pack);
int nmea_parse_BDGGA(const char* buff, int buff_sz, nmeaBDGGA* pack);
int nmea_parse_GNGGA(const char* buff, int buff_sz, nmeaGNGGA* pack);int nmea_parse_GPGSA(const char *buff, int buff_sz, nmeaGPGSA *pack);
int nmea_parse_BDGSA(const char* buff, int buff_sz, nmeaBDGSA* pack);
int nmea_parse_GNGSA(const char* buff, int buff_sz, nmeaGNGSA* pack);int nmea_parse_GPGSV(const char *buff, int buff_sz, nmeaGPGSV *pack);
int nmea_parse_BDGSV(const char* buff, int buff_sz, nmeaBDGSV* pack);
int nmea_parse_GNGSV(const char* buff, int buff_sz, nmeaGNGSV* pack);int nmea_parse_GPRMC(const char *buff, int buff_sz, nmeaGPRMC *pack);
int nmea_parse_BDRMC(const char* buff, int buff_sz, nmeaBDRMC* pack);
int nmea_parse_GNRMC(const char* buff, int buff_sz, nmeaGNRMC* pack);int nmea_parse_GPVTG(const char *buff, int buff_sz, nmeaGPVTG *pack);
int nmea_parse_BDVTG(const char* buff, int buff_sz, nmeaBDVTG* pack);
int nmea_parse_GNVTG(const char* buff, int buff_sz, nmeaGNVTG* pack);void nmea_GPGGA2info(nmeaGPGGA *pack, nmeaINFO *info);
void nmea_BDGGA2info(nmeaBDGGA* pack, nmeaINFO* info);
void nmea_GNGGA2info(nmeaGNGGA* pack, nmeaINFO* info);void nmea_GPGSA2info(nmeaGPGSA *pack, nmeaINFO *info);
void nmea_BDGSA2info(nmeaBDGSA* pack, nmeaINFO* info);
void nmea_GNGSA2info(nmeaGNGSA* pack, nmeaINFO* info);void nmea_GPGSV2info(nmeaGPGSV *pack, nmeaINFO *info);
void nmea_BDGSV2info(nmeaBDGSV* pack, nmeaINFO* info);
void nmea_GNGSV2info(nmeaGNGSV* pack, nmeaINFO* info);void nmea_GPRMC2info(nmeaGPRMC *pack, nmeaINFO *info);
void nmea_BDRMC2info(nmeaBDRMC* pack, nmeaINFO* info);
void nmea_GNRMC2info(nmeaGNRMC* pack, nmeaINFO* info);void nmea_GPVTG2info(nmeaGPVTG *pack, nmeaINFO *info);
void nmea_BDVTG2info(nmeaBDVTG* pack, nmeaINFO* info);
void nmea_GNVTG2info(nmeaGNVTG* pack, nmeaINFO* info);#ifdef __cplusplus
}
#endif#endif /* __NMEA_PARSE_H__ */
parse.c
/*** NMEA library* URL: http://nmea.sourceforge.net* Author: Tim (xtimor@gmail.com)* Licence: http://www.gnu.org/licenses/lgpl.html* $Id: parse.c 17 2008-03-11 11:56:11Z xtimor $**//*** \file parse.h* \brief Functions of a low level for analysis of* packages of NMEA stream.** \code* ...* ptype = nmea_pack_type(* (const char *)parser->buffer + nparsed + 1,* parser->buff_use - nparsed - 1);* * if(0 == (node = malloc(sizeof(nmeaParserNODE))))* goto mem_fail;* * node->pack = 0;* * switch(ptype)* {* case GPGGA:* if(0 == (node->pack = malloc(sizeof(nmeaGPGGA))))* goto mem_fail;* node->packType = GPGGA;* if(!nmea_parse_GPGGA(* (const char *)parser->buffer + nparsed,* sen_sz, (nmeaGPGGA *)node->pack))* {* free(node);* node = 0;* }* break;* case GPGSA:* if(0 == (node->pack = malloc(sizeof(nmeaGPGSA))))* goto mem_fail;* node->packType = GPGSA;* if(!nmea_parse_GPGSA(* (const char *)parser->buffer + nparsed,* sen_sz, (nmeaGPGSA *)node->pack))* {* free(node);* node = 0;* }* break;* ...* \endcode*/#include "tok.h"
#include "parse.h"
#include "context.h"
#include "gmath.h"
#include "units.h"#include <string.h>
#include <stdio.h>int _nmea_parse_time(const char *buff, int buff_sz, nmeaTIME *res)
{int success = 0;switch(buff_sz){case sizeof("hhmmss") - 1:success = (3 == nmea_scanf(buff, buff_sz,"%2d%2d%2d", &(res->hour), &(res->min), &(res->sec)));break;case sizeof("hhmmss.s") - 1:case sizeof("hhmmss.ss") - 1:case sizeof("hhmmss.sss") - 1:success = (4 == nmea_scanf(buff, buff_sz,"%2d%2d%2d.%d", &(res->hour), &(res->min), &(res->sec), &(res->hsec)));break;default:nmea_error("Parse of time error (format error)!");success = 0;break;}return (success?0:-1);
}/*** \brief Define packet type by header (nmeaPACKTYPE).* @param buff a constant character pointer of packet buffer.* @param buff_sz buffer size.* @return The defined packet type* @see nmeaPACKTYPE*/
int nmea_pack_type(const char *buff, int buff_sz)
{
#if 0static const char *pheads[] = {"GPGGA","BDGGA","GNGGA","GPGSA","BDGSA","GNGSA","GPGSV","BDGSV","GNGSV","GPRMC","BDRMC","GNRMC","GPVTG","BDVTG","GNVTG",};
#endifNMEA_ASSERT(buff);if(buff_sz < 5)return GPNON;else if(0 == memcmp((buff), "GPGGA", 5))return GPGGA;else if (0 == memcmp((buff), "BDGGA", 5))return BDGGA;else if (0 == memcmp((buff), "GNGGA", 5))return GNGGA;else if(0 == memcmp((buff), "GPGSA", 5))return GPGSA;else if (0 == memcmp((buff), "BDGSA", 5))return BDGSA;else if (0 == memcmp((buff), "GNGSA", 5))return GNGSA;else if(0 == memcmp((buff), "GPGSV", 5))return GPGSV;else if (0 == memcmp((buff), "BDGSV", 5))return BDGSV;else if (0 == memcmp((buff), "GNGSV", 5))return GNGSV;else if(0 == memcmp((buff), "GPRMC", 5))return GPRMC;else if (0 == memcmp((buff), "BDRMC", 5))return BDRMC;else if (0 == memcmp((buff), "GNRMC", 5))return GNRMC;else if(0 == memcmp((buff), "GPVTG", 5))return GPVTG;else if (0 == memcmp((buff), "BDVTG", 5))return BDVTG;else if (0 == memcmp((buff), "GNVTG", 5))return GNVTG;return GPNON;
}/*** \brief Find tail of packet ("\r\n") in buffer and check control sum (CRC).* @param buff a constant character pointer of packets buffer.* @param buff_sz buffer size.* @param res_crc a integer pointer for return CRC of packet (must be defined).* @return Number of bytes to packet tail.*/
int nmea_find_tail(const char *buff, int buff_sz, int *res_crc)
{static const int tail_sz = 3 /* *[CRC] */ + 2 /* \r\n */;const char *end_buff = buff + buff_sz;int nread = 0;int crc = 0;NMEA_ASSERT(buff && res_crc);*res_crc = -1;for(;buff < end_buff; ++buff, ++nread){if(('$' == *buff) && nread){buff = 0;break;}else if('*' == *buff){if(buff + tail_sz <= end_buff && '\r' == buff[3] && '\n' == buff[4]){*res_crc = nmea_atoi(buff + 1, 2, 16);nread = buff_sz - (int)(end_buff - (buff + tail_sz));if(*res_crc != crc){*res_crc = -1;buff = 0;}}break;}else if(nread)crc ^= (int)*buff;}if(*res_crc < 0 && buff)nread = 0;return nread;
}/*** \brief Parse GGA packet from buffer.* @param buff a constant character pointer of packet buffer.* @param buff_sz buffer size.* @param pack a pointer of packet which will filled by function.* @return 1 (true) - if parsed successfully or 0 (false) - if fail.*/
int nmea_parse_GGA(const char* buff, int buff_sz,const char* sysType, nmeaGPGGA* pack)
{char time_buff[NMEA_TIMEPARSE_BUF];char nmeaSysID[3] = { 0 };NMEA_ASSERT(buff && pack);memset(pack, 0, sizeof(nmeaGPGGA));nmea_trace_buff(buff, buff_sz);if (15 != nmea_scanf(buff, buff_sz,"$%2sGGA,%s,%f,%C,%f,%C,%d,%d,%f,%f,%C,%f,%C,%f,%d*",&(nmeaSysID[0]),&(time_buff[0]),&(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew),&(pack->sig), &(pack->satinuse), &(pack->HDOP), &(pack->elv), &(pack->elv_units),&(pack->diff), &(pack->diff_units), &(pack->dgps_age), &(pack->dgps_sid))){nmea_error("%sGGA parse error!",sysType);return 0;}if (0 != memcmp(nmeaSysID, sysType, 2)) {nmea_error("%sGGA sys type error parse[%s]!", sysType, nmeaSysID);return 0;}if (0 != _nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc))){nmea_error("%sGGA time parse error!",sysType);return 0;}return 1;
}
int nmea_parse_GPGGA(const char *buff, int buff_sz, nmeaGPGGA *pack)
{return nmea_parse_GGA(buff, buff_sz, NMEA_SYSTEM_TYPE_GP, (nmeaGPGGA*)pack);
}
int nmea_parse_BDGGA(const char* buff, int buff_sz, nmeaBDGGA* pack)
{return nmea_parse_GGA(buff, buff_sz, NMEA_SYSTEM_TYPE_BD, (nmeaGPGGA*)pack);
}
int nmea_parse_GNGGA(const char* buff, int buff_sz, nmeaGNGGA* pack)
{return nmea_parse_GGA(buff, buff_sz, NMEA_SYSTEM_TYPE_GN, (nmeaGPGGA*)pack);
}/*** \brief Parse GSA packet from buffer.* @param buff a constant character pointer of packet buffer.* @param buff_sz buffer size.* @param pack a pointer of packet which will filled by function.* @return 1 (true) - if parsed successfully or 0 (false) - if fail.*/
int name_parse_GSA(const char* buff, int buff_sz,const char* sysType, nmeaGPGSA* pack) {NMEA_ASSERT(buff && pack);char nmeaSysID[3] = { 0 };memset(pack, 0, sizeof(nmeaGPGSA));nmea_trace_buff(buff, buff_sz);if (18 != nmea_scanf(buff, buff_sz,"$%2sGSA,%C,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%f*",&(nmeaSysID[0]),&(pack->fix_mode), &(pack->fix_type),&(pack->sat_prn[0]), &(pack->sat_prn[1]), &(pack->sat_prn[2]), &(pack->sat_prn[3]), &(pack->sat_prn[4]), &(pack->sat_prn[5]),&(pack->sat_prn[6]), &(pack->sat_prn[7]), &(pack->sat_prn[8]), &(pack->sat_prn[9]), &(pack->sat_prn[10]), &(pack->sat_prn[11]),&(pack->PDOP), &(pack->HDOP), &(pack->VDOP))){nmea_error("%sGSA parse error!", sysType);return 0;}if (0 != memcmp(nmeaSysID, sysType, 2)) {nmea_error("%sGSA sys type error parse[%s]!", sysType, nmeaSysID);return 0;}return 1;
}int nmea_parse_GPGSA(const char *buff, int buff_sz, nmeaGPGSA *pack)
{return name_parse_GSA(buff,buff_sz, NMEA_SYSTEM_TYPE_GP,(nmeaGPGSA*)pack);
}
int nmea_parse_BDGSA(const char* buff, int buff_sz, nmeaBDGSA* pack)
{return name_parse_GSA(buff, buff_sz, NMEA_SYSTEM_TYPE_BD, (nmeaGPGSA*)pack);
}
int nmea_parse_GNGSA(const char* buff, int buff_sz, nmeaGNGSA* pack)
{return name_parse_GSA(buff, buff_sz, NMEA_SYSTEM_TYPE_GN, (nmeaGPGSA*)pack);
}/*** \brief Parse GSV packet from buffer.* @param buff a constant character pointer of packet buffer.* @param buff_sz buffer size.* @param pack a pointer of packet which will filled by function.* @return 1 (true) - if parsed successfully or 0 (false) - if fail.*/
int nmea_parse_GSV(const char* buff, int buff_sz, const char* sysType, nmeaGPGSV* pack)
{int nsen, nsat;char nmeaSysID[3] = { 0 };NMEA_ASSERT(buff && pack);memset(pack, 0, sizeof(nmeaGPGSV));nmea_trace_buff(buff, buff_sz);nsen = nmea_scanf(buff, buff_sz,"$%2sGSV,%d,%d,%d,""%d,%d,%d,%d,""%d,%d,%d,%d,""%d,%d,%d,%d,""%d,%d,%d,%d*",&(nmeaSysID[0]),&(pack->pack_count), &(pack->pack_index), &(pack->sat_count),&(pack->sat_data[0].id), &(pack->sat_data[0].elv), &(pack->sat_data[0].azimuth), &(pack->sat_data[0].sig),&(pack->sat_data[1].id), &(pack->sat_data[1].elv), &(pack->sat_data[1].azimuth), &(pack->sat_data[1].sig),&(pack->sat_data[2].id), &(pack->sat_data[2].elv), &(pack->sat_data[2].azimuth), &(pack->sat_data[2].sig),&(pack->sat_data[3].id), &(pack->sat_data[3].elv), &(pack->sat_data[3].azimuth), &(pack->sat_data[3].sig));if (0 != memcmp(nmeaSysID, sysType, 2)) {nmea_error("%sGSV sys type error parse[%s]!", sysType, nmeaSysID);return 0;}nsen--; //因为相比原库多解析了一个系统类型 所以需要减去nsat = (pack->pack_index - 1) * NMEA_SATINPACK;nsat = (nsat + NMEA_SATINPACK > pack->sat_count) ? pack->sat_count - nsat : NMEA_SATINPACK;nsat = nsat * 4 + 3 /* first three sentence`s */;if (nsen < nsat || nsen >(NMEA_SATINPACK * 4 + 3)){nmea_error("GPGSV parse error!");return 0;}return 1;
}
int nmea_parse_GPGSV(const char* buff, int buff_sz, nmeaGPGSV* pack)
{return nmea_parse_GSV(buff, buff_sz, NMEA_SYSTEM_TYPE_GP, (nmeaGPGSV*)pack);
}
int nmea_parse_BDGSV(const char* buff, int buff_sz, nmeaBDGSV* pack)
{return nmea_parse_GSV(buff, buff_sz, NMEA_SYSTEM_TYPE_BD, (nmeaGPGSV*)pack);
}
int nmea_parse_GNGSV(const char* buff, int buff_sz, nmeaGNGSV* pack)
{return nmea_parse_GSV(buff, buff_sz, NMEA_SYSTEM_TYPE_GN, (nmeaGPGSV*)pack);
}/*** \brief Parse RMC packet from buffer.* @param buff a constant character pointer of packet buffer.* @param buff_sz buffer size.* @param pack a pointer of packet which will filled by function.* @return 1 (true) - if parsed successfully or 0 (false) - if fail.*/
int nmea_parse_RMC(const char *buff, int buff_sz, const char* sysType, nmeaGPRMC *pack)
{int nsen;char time_buff[NMEA_TIMEPARSE_BUF];char nmeaSysID[3] = { 0 };NMEA_ASSERT(buff && pack);memset(pack, 0, sizeof(nmeaGPRMC));nmea_trace_buff(buff, buff_sz);nsen = nmea_scanf(buff, buff_sz,"$%2sRMC,%s,%C,%f,%C,%f,%C,%f,%f,%2d%2d%2d,%f,%C,%C*",&(nmeaSysID[0]),&(time_buff[0]),&(pack->status), &(pack->lat), &(pack->ns), &(pack->lon), &(pack->ew),&(pack->speed), &(pack->direction),&(pack->utc.day), &(pack->utc.mon), &(pack->utc.year),&(pack->declination), &(pack->declin_ew), &(pack->mode));if(nsen != 14 && nsen != 15){nmea_error("%sRMC parse error!", sysType);return 0;} if (0 != memcmp(nmeaSysID, sysType, 2)) {nmea_error("%sRMC sys type error parse[%s]!", sysType, nmeaSysID);return 0;}if(0 != _nmea_parse_time(&time_buff[0], (int)strlen(&time_buff[0]), &(pack->utc))){nmea_error("%sRMC time parse error!", sysType);return 0;}if(pack->utc.year < 90)pack->utc.year += 100;pack->utc.mon -= 1;return 1;
}
int nmea_parse_GPRMC(const char* buff, int buff_sz, nmeaGPRMC* pack)
{return nmea_parse_RMC(buff, buff_sz, NMEA_SYSTEM_TYPE_GP, (nmeaGPRMC*)pack);
}
int nmea_parse_BDRMC(const char* buff, int buff_sz, nmeaBDRMC* pack)
{return nmea_parse_RMC(buff, buff_sz, NMEA_SYSTEM_TYPE_BD, (nmeaGPRMC*)pack);
}
int nmea_parse_GNRMC(const char* buff, int buff_sz, nmeaGNRMC* pack)
{return nmea_parse_RMC(buff, buff_sz, NMEA_SYSTEM_TYPE_GN, (nmeaGPRMC*)pack);
}/*** \brief Parse VTG packet from buffer.* @param buff a constant character pointer of packet buffer.* @param buff_sz buffer size.* @param pack a pointer of packet which will filled by function.* @return 1 (true) - if parsed successfully or 0 (false) - if fail.*/
int nmea_parse_VTG(const char *buff, int buff_sz, const char* sysType, nmeaGPVTG *pack)
{char nmeaSysID[3] = { 0 };NMEA_ASSERT(buff && pack);memset(pack, 0, sizeof(nmeaGPVTG));nmea_trace_buff(buff, buff_sz);if(9 != nmea_scanf(buff, buff_sz,"$%2sVTG,%f,%C,%f,%C,%f,%C,%f,%C*",&(nmeaSysID[0]),&(pack->dir), &(pack->dir_t),&(pack->dec), &(pack->dec_m),&(pack->spn), &(pack->spn_n),&(pack->spk), &(pack->spk_k))){nmea_error("%sVTG parse error!", sysType);return 0;}if (0 != memcmp(nmeaSysID, sysType, 2)) {nmea_error("%sRMC sys type error parse[%s]!", sysType, nmeaSysID);return 0;}if( pack->dir_t != 'T' ||pack->dec_m != 'M' ||pack->spn_n != 'N' ||pack->spk_k != 'K'){nmea_error("%sVTG parse error (format error)!", sysType);return 0;}return 1;
}
int nmea_parse_GPVTG(const char* buff, int buff_sz, nmeaGPVTG* pack)
{return nmea_parse_VTG(buff, buff_sz, NMEA_SYSTEM_TYPE_GP, (nmeaGPVTG*)pack);
}
int nmea_parse_BDVTG(const char* buff, int buff_sz, nmeaBDVTG* pack)
{return nmea_parse_VTG(buff, buff_sz, NMEA_SYSTEM_TYPE_BD, (nmeaGPVTG*)pack);
}
int nmea_parse_GNVTG(const char* buff, int buff_sz, nmeaGNVTG* pack)
{return nmea_parse_VTG(buff, buff_sz, NMEA_SYSTEM_TYPE_GN, (nmeaGPVTG*)pack);
}/*** \brief Fill nmeaINFO structure by GGA packet data.* @param pack a pointer of packet structure.* @param info a pointer of summary information structure.*/
void nmea_GGA2info(nmeaGPGGA* pack, nmeaINFO* info,int type)
{NMEA_ASSERT(pack && info);info->utc.hour = pack->utc.hour;info->utc.min = pack->utc.min;info->utc.sec = pack->utc.sec;info->utc.hsec = pack->utc.hsec;info->sig = pack->sig;info->HDOP = pack->HDOP;info->elv = pack->elv;info->lat = ((pack->ns == 'N') ? pack->lat : -(pack->lat));info->lon = ((pack->ew == 'E') ? pack->lon : -(pack->lon));info->smask |= type;
}
void nmea_GPGGA2info(nmeaGPGGA *pack, nmeaINFO *info)
{nmea_GGA2info(pack, info, GPGGA);
}
void nmea_BDGGA2info(nmeaBDGGA* pack, nmeaINFO* info)
{nmea_GGA2info(pack, info, BDGGA);
}
void nmea_GNGGA2info(nmeaGNGGA* pack, nmeaINFO* info)
{nmea_GGA2info(pack, info, GNGGA);
}/*** \brief Fill nmeaINFO structure by GSA packet data.* @param pack a pointer of packet structure.* @param info a pointer of summary information structure.*/
void nmea_GPGSA2info(nmeaGPGSA *pack, nmeaINFO *info)
{int i, j, nuse = 0;NMEA_ASSERT(pack && info);info->fix = pack->fix_type;info->PDOP = pack->PDOP;info->HDOP = pack->HDOP;info->VDOP = pack->VDOP;for(i = 0; i < NMEA_MAXSAT; ++i){info->satinfo.sat_prnGP[i] = pack->sat_prn[i];
#if 0for(j = 0; j < info->satinfo.inview; ++j){if(pack->sat_prn[i] && pack->sat_prn[i] == info->satinfo.satGP[j].id){info->satinfo.satGP[j].in_use = 1;nuse++;}}
#endif}
#if 0info->satinfo.inuseGP = nuse;info->satinfo.inuse = info->satinfo.inuseGP+ info->satinfo.inuseBD+ info->satinfo.inuseGN;
#endifinfo->smask |= GPGSA;
}
void nmea_BDGSA2info(nmeaBDGSA* pack, nmeaINFO* info)
{int i, j, nuse = 0;NMEA_ASSERT(pack && info);info->fix = pack->fix_type;info->PDOP = pack->PDOP;info->HDOP = pack->HDOP;info->VDOP = pack->VDOP;for (i = 0; i < NMEA_MAXSAT; ++i){info->satinfo.sat_prnBD[i] = pack->sat_prn[i];
#if 0for (j = 0; j < info->satinfo.inview; ++j){if (pack->sat_prn[i] && pack->sat_prn[i] == info->satinfo.satBD[j].id){info->satinfo.satBD[j].in_use = 1;nuse++;}}
#endif}
#if 0info->satinfo.inuseBD = nuse;info->satinfo.inuse = info->satinfo.inuseGP + info->satinfo.inuseBD + info->satinfo.inuseGN;
#endifinfo->smask |= BDGSA;
}
void nmea_GNGSA2info(nmeaGNGSA* pack, nmeaINFO* info)
{int i, j, nuse = 0;NMEA_ASSERT(pack && info);info->fix = pack->fix_type;info->PDOP = pack->PDOP;info->HDOP = pack->HDOP;info->VDOP = pack->VDOP;for (i = 0; i < NMEA_MAXSAT; ++i){info->satinfo.sat_prnGN[i] = pack->sat_prn[i];
#if 0for (j = 0; j < info->satinfo.inview; ++j){if (pack->sat_prn[i] && pack->sat_prn[i] == info->satinfo.satGN[j].id){info->satinfo.satGN[j].in_use = 1;nuse++;}}
#endif}
#if 0info->satinfo.inuseGN = nuse;info->satinfo.inuse = info->satinfo.inuseGP + info->satinfo.inuseBD + info->satinfo.inuseGN;
#endifinfo->smask |= GNGSA;
}/*** \brief Fill nmeaINFO structure by GSV packet data.* @param pack a pointer of packet structure.* @param info a pointer of summary information structure.*/
void nmea_GPGSV2info(nmeaGPGSV *pack, nmeaINFO *info)
{int isat, isi, nsat;NMEA_ASSERT(pack && info);if(pack->pack_index > pack->pack_count ||pack->pack_index * NMEA_SATINPACK > NMEA_MAXSAT)return;if(pack->pack_index < 1)pack->pack_index = 1;if (pack->pack_index == 1) {info->satinfo.inuseGP = 0;info->satinfo.insig_greater35.GP = 0;info->satinfo.insig_32to35.GP = 0;}info->satinfo.inviewGP = pack->sat_count;info->satinfo.inview = info->satinfo.inviewGP + info->satinfo.inviewBD +info->satinfo.inviewGP;nsat = (pack->pack_index - 1) * NMEA_SATINPACK;nsat = (nsat + NMEA_SATINPACK > pack->sat_count)?pack->sat_count - nsat:NMEA_SATINPACK;for(isat = 0; isat < nsat; ++isat){isi = (pack->pack_index - 1) * NMEA_SATINPACK + isat;info->satinfo.satGP[isi].id = pack->sat_data[isat].id;info->satinfo.satGP[isi].elv = pack->sat_data[isat].elv;info->satinfo.satGP[isi].azimuth = pack->sat_data[isat].azimuth;info->satinfo.satGP[isi].sig = pack->sat_data[isat].sig;info->satinfo.satGP[isi].in_use = 0;for (int j = 0; j < NMEA_MAXSAT; ++j){if (info->satinfo.sat_prnGP[j] && (info->satinfo.sat_prnGP[j] == info->satinfo.satGP[isi].id)){info->satinfo.satGP[isi].in_use = 1;info->satinfo.inuseGP++;if (info->satinfo.satGP[isi].sig > 35) {info->satinfo.insig_greater35.GP++;}else if (info->satinfo.satGP[isi].sig > 32) {info->satinfo.insig_32to35.GP++;}break;}}}info->satinfo.insig_greater35.sum = info->satinfo.insig_greater35.GP + info->satinfo.insig_greater35.BD + info->satinfo.insig_greater35.GN;info->satinfo.insig_32to35.sum = info->satinfo.insig_32to35.GP + info->satinfo.insig_32to35.BD + info->satinfo.insig_32to35.GN;info->satinfo.inuse = info->satinfo.inuseGP + info->satinfo.inuseBD + info->satinfo.inuseGN;info->smask |= GPGSV;
}
void nmea_BDGSV2info(nmeaBDGSV* pack, nmeaINFO* info)
{int isat, isi, nsat;NMEA_ASSERT(pack && info);if (pack->pack_index > pack->pack_count ||pack->pack_index * NMEA_SATINPACK > NMEA_MAXSAT)return;if (pack->pack_index < 1)pack->pack_index = 1;if (pack->pack_index == 1) {info->satinfo.inuseBD = 0;info->satinfo.insig_greater35.BD = 0;info->satinfo.insig_32to35.BD = 0;}info->satinfo.inviewBD = pack->sat_count;info->satinfo.inview = info->satinfo.inviewGP + info->satinfo.inviewBD + info->satinfo.inviewGN;nsat = (pack->pack_index - 1) * NMEA_SATINPACK;nsat = (nsat + NMEA_SATINPACK > pack->sat_count) ? pack->sat_count - nsat : NMEA_SATINPACK;for (isat = 0; isat < nsat; ++isat){isi = (pack->pack_index - 1) * NMEA_SATINPACK + isat;info->satinfo.satBD[isi].id = pack->sat_data[isat].id;info->satinfo.satBD[isi].elv = pack->sat_data[isat].elv;info->satinfo.satBD[isi].azimuth = pack->sat_data[isat].azimuth;info->satinfo.satBD[isi].sig = pack->sat_data[isat].sig;info->satinfo.satBD[isi].in_use = 0;for (int j = 0; j < NMEA_MAXSAT; ++j){if (info->satinfo.sat_prnBD[j] && (info->satinfo.sat_prnBD[j] == info->satinfo.satBD[isi].id)){info->satinfo.satBD[isi].in_use = 1;info->satinfo.inuseBD++;if (info->satinfo.satBD[isi].sig > 35) {info->satinfo.insig_greater35.BD++;}else if (info->satinfo.satBD[isi].sig > 32) {info->satinfo.insig_32to35.BD++;}break;}}}info->satinfo.insig_greater35.sum = info->satinfo.insig_greater35.GP + info->satinfo.insig_greater35.BD + info->satinfo.insig_greater35.GN;info->satinfo.insig_32to35.sum = info->satinfo.insig_32to35.GP + info->satinfo.insig_32to35.BD + info->satinfo.insig_32to35.GN;info->satinfo.inuse = info->satinfo.inuseGP + info->satinfo.inuseBD + info->satinfo.inuseGN;info->smask |= BDGSV;
}
void nmea_GNGSV2info(nmeaGNGSV* pack, nmeaINFO* info)
{int isat, isi, nsat;NMEA_ASSERT(pack && info);if (pack->pack_index > pack->pack_count ||pack->pack_index * NMEA_SATINPACK > NMEA_MAXSAT)return;if (pack->pack_index < 1)pack->pack_index = 1;if (pack->pack_index == 1) {info->satinfo.inuseGN = 0;info->satinfo.insig_greater35.GN = 0;info->satinfo.insig_32to35.GN = 0;}info->satinfo.inviewGN = pack->sat_count;info->satinfo.inview = info->satinfo.inviewGP + info->satinfo.inviewBD + info->satinfo.inviewGN;nsat = (pack->pack_index - 1) * NMEA_SATINPACK;nsat = (nsat + NMEA_SATINPACK > pack->sat_count) ? pack->sat_count - nsat : NMEA_SATINPACK;for (isat = 0; isat < nsat; ++isat){isi = (pack->pack_index - 1) * NMEA_SATINPACK + isat;info->satinfo.satGN[isi].id = pack->sat_data[isat].id;info->satinfo.satGN[isi].elv = pack->sat_data[isat].elv;info->satinfo.satGN[isi].azimuth = pack->sat_data[isat].azimuth;info->satinfo.satGN[isi].sig = pack->sat_data[isat].sig;info->satinfo.satGN[isi].in_use = 0;for (int j = 0; j < NMEA_MAXSAT; ++j){if (info->satinfo.sat_prnGN[j] && (info->satinfo.sat_prnGN[j] == info->satinfo.satGN[isi].id)){info->satinfo.satGN[isi].in_use = 1;info->satinfo.inuseGN++;if (info->satinfo.satGN[isi].sig > 35) {info->satinfo.insig_greater35.GN++;}else if (info->satinfo.satGN[isi].sig > 32) {info->satinfo.insig_32to35.GN++;}break;}}}info->satinfo.insig_greater35.sum = info->satinfo.insig_greater35.GP + info->satinfo.insig_greater35.BD + info->satinfo.insig_greater35.GN;info->satinfo.insig_32to35.sum = info->satinfo.insig_32to35.GP + info->satinfo.insig_32to35.BD + info->satinfo.insig_32to35.GN;info->satinfo.inuse = info->satinfo.inuseGP + info->satinfo.inuseBD + info->satinfo.inuseGN;info->smask |= GNGSV;
}/*** \brief Fill nmeaINFO structure by RMC packet data.* @param pack a pointer of packet structure.* @param info a pointer of summary information structure.*/
void nmea_RMC2info(nmeaGPRMC *pack, nmeaINFO *info, int type)
{NMEA_ASSERT(pack && info);if('A' == pack->status){if(NMEA_SIG_BAD == info->sig)info->sig = NMEA_SIG_MID;if(NMEA_FIX_BAD == info->fix)info->fix = NMEA_FIX_2D;}else if('V' == pack->status){info->sig = NMEA_SIG_BAD;info->fix = NMEA_FIX_BAD;}info->utc = pack->utc;info->lat = ((pack->ns == 'N')?pack->lat:-(pack->lat));info->lon = ((pack->ew == 'E')?pack->lon:-(pack->lon));info->speed = pack->speed * NMEA_TUD_KNOTS;info->direction = pack->direction;info->smask |= type;
}
void nmea_GPRMC2info(nmeaGPRMC* pack, nmeaINFO* info)
{nmea_RMC2info(pack, info, GPRMC);
}
void nmea_BDRMC2info(nmeaBDRMC* pack, nmeaINFO* info)
{nmea_RMC2info(pack, info, BDRMC);
}
void nmea_GNRMC2info(nmeaGNRMC* pack, nmeaINFO* info)
{nmea_RMC2info(pack, info, GNRMC);
}/*** \brief Fill nmeaINFO structure by VTG packet data.* @param pack a pointer of packet structure.* @param info a pointer of summary information structure.*/
void nmea_VTG2info(nmeaGPVTG *pack, nmeaINFO *info, int type)
{NMEA_ASSERT(pack && info);info->direction = pack->dir;info->declination = pack->dec;info->speed = pack->spk;info->smask |= type;
}
void nmea_GPVTG2info(nmeaGPVTG* pack, nmeaINFO* info)
{nmea_VTG2info(pack, info, GPVTG);
}
void nmea_BDVTG2info(nmeaBDVTG* pack, nmeaINFO* info)
{nmea_VTG2info(pack, info, BDVTG);
}
void nmea_GNVTG2info(nmeaGNVTG* pack, nmeaINFO* info)
{nmea_VTG2info(pack, info, GNVTG);
}
4 、修改paser.c文件
/*** NMEA library* URL: http://nmea.sourceforge.net* Author: Tim (xtimor@gmail.com)* Licence: http://www.gnu.org/licenses/lgpl.html* $Id: parser.c 17 2008-03-11 11:56:11Z xtimor $**//*** \file parser.h*/#include "tok.h"
#include "parse.h"
#include "parser.h"
#include "context.h"#include <string.h>
#include <stdlib.h>typedef struct _nmeaParserNODE
{int packType;void *pack;struct _nmeaParserNODE *next_node;} nmeaParserNODE;/** high level*//*** \brief Initialization of parser object* @return true (1) - success or false (0) - fail*/
int nmea_parser_init(nmeaPARSER *parser)
{int resv = 0;int buff_size = nmea_property()->parse_buff_size;NMEA_ASSERT(parser);if(buff_size < NMEA_MIN_PARSEBUFF)buff_size = NMEA_MIN_PARSEBUFF;memset(parser, 0, sizeof(nmeaPARSER));if(0 == (parser->buffer = malloc(buff_size)))nmea_error("Insufficient memory!");else{parser->buff_size = buff_size;resv = 1;} return resv;
}/*** \brief Destroy parser object*/
void nmea_parser_destroy(nmeaPARSER *parser)
{NMEA_ASSERT(parser && parser->buffer);free(parser->buffer);nmea_parser_queue_clear(parser);memset(parser, 0, sizeof(nmeaPARSER));
}/*** \brief Analysis of buffer and put results to information structure* @return Number of packets wos parsed*/
int nmea_parse( nmeaPARSER *parser,const char *buff, int buff_sz,nmeaINFO *info)
{int ptype, nread = 0;void *pack = 0;NMEA_ASSERT(parser && parser->buffer);nmea_parser_push(parser, buff, buff_sz);while(GPNON != (ptype = nmea_parser_pop(parser, &pack))){nread++;switch(ptype){case GPGGA:nmea_GPGGA2info((nmeaGPGGA *)pack, info);break;case BDGGA:nmea_BDGGA2info((nmeaBDGGA*)pack, info);break;case GNGGA:nmea_GNGGA2info((nmeaGNGGA*)pack, info);break;case GPGSA:nmea_GPGSA2info((nmeaGPGSA *)pack, info);break;case BDGSA:nmea_BDGSA2info((nmeaBDGSA*)pack, info);break;case GNGSA:nmea_GNGSA2info((nmeaGNGSA*)pack, info);break;case GPGSV:nmea_GPGSV2info((nmeaGPGSV *)pack, info);break;case BDGSV:nmea_BDGSV2info((nmeaBDGSV*)pack, info);break;case GNGSV:nmea_GNGSV2info((nmeaGNGSV*)pack, info);break;case GPRMC:nmea_GPRMC2info((nmeaGPRMC *)pack, info);break;case BDRMC:nmea_BDRMC2info((nmeaBDRMC*)pack, info);break;case GNRMC:nmea_GNRMC2info((nmeaGNRMC*)pack, info);break;case GPVTG:nmea_GPVTG2info((nmeaGPVTG *)pack, info);break;case BDVTG:nmea_BDVTG2info((nmeaBDVTG*)pack, info);break;case GNVTG:nmea_GNVTG2info((nmeaGNVTG*)pack, info);break;};free(pack);}return nread;
}/** low level*/int nmea_parser_real_push(nmeaPARSER *parser, const char *buff, int buff_sz)
{int nparsed = 0, crc, sen_sz, ptype;nmeaParserNODE *node = 0;NMEA_ASSERT(parser && parser->buffer);/* clear unuse buffer (for debug) *//*memset(parser->buffer + parser->buff_use, 0,parser->buff_size - parser->buff_use);*//* add */if(parser->buff_use + buff_sz >= parser->buff_size)nmea_parser_buff_clear(parser);memcpy(parser->buffer + parser->buff_use, buff, buff_sz);parser->buff_use += buff_sz;/* parse */for(;;node = 0){sen_sz = nmea_find_tail((const char *)parser->buffer + nparsed,(int)parser->buff_use - nparsed, &crc);if(!sen_sz){if(nparsed)memcpy(parser->buffer,parser->buffer + nparsed,parser->buff_use -= nparsed);break;}else if(crc >= 0){ptype = nmea_pack_type((const char *)parser->buffer + nparsed + 1,parser->buff_use - nparsed - 1);if(0 == (node = malloc(sizeof(nmeaParserNODE))))goto mem_fail;node->pack = 0;switch(ptype){case GPGGA:if(0 == (node->pack = malloc(sizeof(nmeaGPGGA))))goto mem_fail;node->packType = GPGGA;if(!nmea_parse_GPGGA((const char *)parser->buffer + nparsed,sen_sz, (nmeaGPGGA *)node->pack)){free(node);node = 0;}break;case BDGGA:if (0 == (node->pack = malloc(sizeof(nmeaBDGGA))))goto mem_fail;node->packType = BDGGA;if (!nmea_parse_BDGGA((const char*)parser->buffer + nparsed,sen_sz, (nmeaBDGGA*)node->pack)){free(node);node = 0;}break;case GNGGA:if (0 == (node->pack = malloc(sizeof(nmeaGNGGA))))goto mem_fail;node->packType = GNGGA;if (!nmea_parse_GNGGA((const char*)parser->buffer + nparsed,sen_sz, (nmeaGNGGA*)node->pack)){free(node);node = 0;}break;case GPGSA:if(0 == (node->pack = malloc(sizeof(nmeaGPGSA))))goto mem_fail;node->packType = GPGSA;if(!nmea_parse_GPGSA((const char *)parser->buffer + nparsed,sen_sz, (nmeaGPGSA *)node->pack)){free(node);node = 0;}break;case BDGSA:if (0 == (node->pack = malloc(sizeof(nmeaBDGSA))))goto mem_fail;node->packType = BDGSA;if (!nmea_parse_BDGSA((const char*)parser->buffer + nparsed,sen_sz, (nmeaBDGSA*)node->pack)){free(node);node = 0;}break;case GNGSA:if (0 == (node->pack = malloc(sizeof(nmeaGNGSA))))goto mem_fail;node->packType = GNGSA;if (!nmea_parse_GNGSA((const char*)parser->buffer + nparsed,sen_sz, (nmeaGNGSA*)node->pack)){free(node);node = 0;}break;case GPGSV:if(0 == (node->pack = malloc(sizeof(nmeaGPGSV))))goto mem_fail;node->packType = GPGSV;if(!nmea_parse_GPGSV((const char *)parser->buffer + nparsed,sen_sz, (nmeaGPGSV *)node->pack)){free(node);node = 0;}break;case BDGSV:if (0 == (node->pack = malloc(sizeof(nmeaBDGSV))))goto mem_fail;node->packType = BDGSV;if (!nmea_parse_BDGSV((const char*)parser->buffer + nparsed,sen_sz, (nmeaBDGSV*)node->pack)){free(node);node = 0;}break;case GNGSV:if (0 == (node->pack = malloc(sizeof(nmeaGNGSV))))goto mem_fail;node->packType = GNGSV;if (!nmea_parse_GNGSV((const char*)parser->buffer + nparsed,sen_sz, (nmeaGNGSV*)node->pack)){free(node);node = 0;}break;case GPRMC:if(0 == (node->pack = malloc(sizeof(nmeaGPRMC))))goto mem_fail;node->packType = GPRMC;if(!nmea_parse_GPRMC((const char *)parser->buffer + nparsed,sen_sz, (nmeaGPRMC *)node->pack)){free(node);node = 0;}break;case BDRMC:if (0 == (node->pack = malloc(sizeof(nmeaBDRMC))))goto mem_fail;node->packType = BDRMC;if (!nmea_parse_BDRMC((const char*)parser->buffer + nparsed,sen_sz, (nmeaBDRMC*)node->pack)){free(node);node = 0;}break;case GNRMC:if (0 == (node->pack = malloc(sizeof(nmeaGNRMC))))goto mem_fail;node->packType = GNRMC;if (!nmea_parse_GNRMC((const char*)parser->buffer + nparsed,sen_sz, (nmeaGNRMC*)node->pack)){free(node);node = 0;}break;case GPVTG:if(0 == (node->pack = malloc(sizeof(nmeaGPVTG))))goto mem_fail;node->packType = GPVTG;if(!nmea_parse_GPVTG((const char *)parser->buffer + nparsed,sen_sz, (nmeaGPVTG *)node->pack)){free(node);node = 0;}break;case BDVTG:if (0 == (node->pack = malloc(sizeof(nmeaBDVTG))))goto mem_fail;node->packType = BDVTG;if (!nmea_parse_BDVTG((const char*)parser->buffer + nparsed,sen_sz, (nmeaBDVTG*)node->pack)){free(node);node = 0;}break;case GNVTG:if (0 == (node->pack = malloc(sizeof(nmeaGNVTG))))goto mem_fail;node->packType = GNVTG;if (!nmea_parse_GNVTG((const char*)parser->buffer + nparsed,sen_sz, (nmeaGNVTG*)node->pack)){free(node);node = 0;}break;default:free(node);node = 0;break;};if(node){if(parser->end_node)((nmeaParserNODE *)parser->end_node)->next_node = node;parser->end_node = node;if(!parser->top_node)parser->top_node = node;node->next_node = 0;}}nparsed += sen_sz;}return nparsed;mem_fail:if(node)free(node);nmea_error("Insufficient memory!");return -1;
}/*** \brief Analysis of buffer and keep results into parser* @return Number of bytes wos parsed from buffer*/
int nmea_parser_push(nmeaPARSER *parser, const char *buff, int buff_sz)
{int nparse, nparsed = 0;do{if(buff_sz > parser->buff_size)nparse = parser->buff_size;elsenparse = buff_sz;nparsed += nmea_parser_real_push(parser, buff, nparse);buff_sz -= nparse;} while(buff_sz);return nparsed;
}/*** \brief Get type of top packet keeped into parser* @return Type of packet* @see nmeaPACKTYPE*/
int nmea_parser_top(nmeaPARSER *parser)
{int retval = GPNON;nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;NMEA_ASSERT(parser && parser->buffer);if(node)retval = node->packType;return retval;
}/*** \brief Withdraw top packet from parser* @return Received packet type* @see nmeaPACKTYPE*/
int nmea_parser_pop(nmeaPARSER *parser, void **pack_ptr)
{int retval = GPNON;nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;NMEA_ASSERT(parser && parser->buffer);if(node){*pack_ptr = node->pack;retval = node->packType;parser->top_node = node->next_node;if(!parser->top_node)parser->end_node = 0;free(node);}return retval;
}/*** \brief Get top packet from parser without withdraw* @return Received packet type* @see nmeaPACKTYPE*/
int nmea_parser_peek(nmeaPARSER *parser, void **pack_ptr)
{int retval = GPNON;nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;NMEA_ASSERT(parser && parser->buffer);if(node){*pack_ptr = node->pack;retval = node->packType;}return retval;
}/*** \brief Delete top packet from parser* @return Deleted packet type* @see nmeaPACKTYPE*/
int nmea_parser_drop(nmeaPARSER *parser)
{int retval = GPNON;nmeaParserNODE *node = (nmeaParserNODE *)parser->top_node;NMEA_ASSERT(parser && parser->buffer);if(node){if(node->pack)free(node->pack);retval = node->packType;parser->top_node = node->next_node;if(!parser->top_node)parser->end_node = 0;free(node);}return retval;
}/*** \brief Clear cache of parser* @return true (1) - success*/
int nmea_parser_buff_clear(nmeaPARSER *parser)
{NMEA_ASSERT(parser && parser->buffer);parser->buff_use = 0;return 1;
}/*** \brief Clear packets queue into parser* @return true (1) - success*/
int nmea_parser_queue_clear(nmeaPARSER *parser)
{NMEA_ASSERT(parser);while(parser->top_node)nmea_parser_drop(parser);return 1;
}
四、测试
#include <iostream>
#include "nmea.h"using namespace std;static void trace(const char* str, int str_size)
{printf("nmea trace:");for (int i = 0; i < str_size; i++)printf("%c", str[i]);
}static void error(const char* str, int str_size)
{printf("\nnmea error:");for (int i = 0; i < str_size; i++)printf("%c", str[i]);printf("\n");
}int main()
{nmeaINFO info; //GPS解码后得到的信息nmeaPARSER parser; //解码时使用的数据结构char ss[128]; //打印字符串bufferdouble deg_lat; //转换成[degree].[degree]格式的纬度double deg_lon; //转换成[degree].[degree]格式的经度nmea_property()->trace_func = &trace;nmea_property()->error_func = &error;nmea_zero_INFO(&info);nmea_parser_init(&parser);const char gps_rx_data[] = """$GPRMC,183729,A,3907.356,N,12102.482,W,000.0,360.0,080301,015.5,E*6F\r\n""$GPRMB,A,,,,,,,,,,,,V*71\r\n""$GPGGA,183730,3907.356,N,12102.482,W,1,05,1.6,646.4,M,-24.1,M,,*75\r\n""$GPGSA,A,3,02,,,07,,09,24,26,,,,,1.6,1.6,1.0*3D\r\n""$GPGSV,2,1,08,02,43,088,38,04,42,145,00,05,11,291,00,07,60,043,35*71\r\n""$GPGSV,2,2,08,08,02,145,00,09,46,303,47,24,16,178,32,26,18,231,43*77\r\n""$PGRME,22.0,M,52.9,M,51.0,M*14\r\n""$GPGLL,3907.360,N,12102.481,W,183730,A*33\r\n""$PGRMZ,2062,f,3*2D\r\n""$PGRMM,WGS84*06\r\n""$GPBOD,,T,,M,,*47\r\n""$GPRTE,1,1,c,0*07\r\n""$GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67\r\n""$GPRMB,A,,,,,,,,,,,,V*71\r\n""$BDGSV,3,1,09,209,70,350,,225,56,177,,224,53,65,,206,50,304,*59\r\n""$BDGSV,3,2,09,201,38,143,,202,37,221,,210,22,185,,216,22,291,*6B\r\n""$BDGSV,3,3,09,213,12,201,*61\r\n""$BDGSV,3,1,09,209,70,350,,225,56,177,,224,53,65,,206,50,304,*59\r\n""$BDGSV,3,2,09,201,38,143,,202,37,221,,210,22,185,,216,22,291,*6B\r\n";int len = nmea_parse(&parser, (const char*)&gps_rx_data[0], strlen(gps_rx_data), &info);if (len > 0){printf("len = %d\n",len);//info.lat lon中的格式为[degree][min].[sec/60],使用以下函数转换成[degree].[degree]格式deg_lat = nmea_ndeg2degree(info.lat);deg_lon = nmea_ndeg2degree(info.lon);printf("utc_time:%d-%02d-%02d,%d:%d:%d \n", info.utc.year + 1900, info.utc.mon + 1, info.utc.day,info.utc.hour, info.utc.min, info.utc.sec);//因为LOG_D不支持浮点数,所以此处使用snprintf进行打印,再用LOG_D输出snprintf(ss, 128, "wd:%f,jd:%f\n", deg_lat, deg_lon);printf(ss);snprintf(ss, 128, "high:%f m\n", info.elv);printf(ss);snprintf(ss, 128, "v:%f km/h\n", info.speed);printf(ss);snprintf(ss, 128, "hangxiang:%f du\n", info.direction);printf(ss);snprintf(ss, 128, "used GPS:%d,show GPS:%d\n", info.satinfo.inuse, info.satinfo.inview);printf(ss);snprintf(ss, 128, "PDOP:%f,HDOP:%f,VDOP:%f\n", info.PDOP, info.HDOP, info.VDOP);printf(ss);}return 0;
}
运行结果
五、完成工程加源码下载
点击链接跳转:资源下载