單純的電子海圖顯示功能在實(shí)踐中是遠(yuǎn)遠(yuǎn)不夠的,需要接入諸如計(jì)程儀蝎土、羅經(jīng)视哑、AIS、GPS誊涯、雷達(dá)等數(shù)據(jù)挡毅,才能滿足基本的航海實(shí)踐需要。而不同航海電子傳感器之間數(shù)據(jù)交互主要采用NMEA 0183格式醋拧。
NMEA 0183是美國國家海洋電子協(xié)會(National Marine Electronics Association )為海用電子設(shè)備制定的標(biāo)準(zhǔn)格式慷嗜,目前已成為船舶各電子設(shè)備(如:測深儀淀弹,電羅經(jīng)丹壕,自動舵,AIS薇溃,GPS菌赖,計(jì)程儀等)之間數(shù)據(jù)傳輸?shù)臉?biāo)準(zhǔn)。該協(xié)議采用ASCII碼沐序,其串行通信默認(rèn)參數(shù)為:波特率=9600bps琉用,數(shù)據(jù)位=8bit,開始位=1bit策幼,停止位=1bit邑时,無奇偶校驗(yàn)。NEMA協(xié)議的數(shù)據(jù)結(jié)構(gòu)如下:
ASCII | 十六進(jìn)制 | 十進(jìn)制 | 描述 |
---|---|---|---|
<CR> | 0x0d | 13 | 回車 |
<LF> | 0x0a | 10 | 換行 |
! | 0x21 | 33 | 封裝語句的開始標(biāo)志 |
$ | 0x24 | 36 | 開始標(biāo)志 |
* | 0x2a | 42 | 校驗(yàn)和 |
, | 0x2c | 44 | 字段分隔標(biāo)志 |
\ | 0x5c | 92 | 標(biāo)簽塊標(biāo)志 |
^ | 0x5e | 94 | 用十六進(jìn)制表示ASCII的編碼標(biāo)志 |
~ | 0x7e | 126 | 保留 |
- 消息的最大長度為82個(gè)字符特姐,包括開始字符‘$’或‘!’和結(jié)束字符<LF>晶丘;
- 每個(gè)消息的起始字符可以是‘$’(對于常規(guī)的字段分隔消息)或'!'(對于具有特殊封裝的消息);
- 接下來的五個(gè)字符標(biāo)識設(shè)備類型TalkID(兩個(gè)字符)和報(bào)文類型(三個(gè)字符)唐含;
- 后面的所有數(shù)據(jù)字段均以逗號分隔浅浮;
- 如果沒有數(shù)據(jù),則相應(yīng)的字段保持空白(在下一個(gè)分隔符之前不包含任何字符)捷枯;
- 在最后一個(gè)數(shù)據(jù)字段字符之后的第一個(gè)字符是星號滚秩,但僅在提供校驗(yàn)和時(shí)才包括在內(nèi);
- 星號后緊跟一個(gè)校驗(yàn)和淮捆,以兩位十六進(jìn)制數(shù)表示郁油,校驗(yàn)和是‘$’和‘*’之間的所有字符的ASCII碼的按位異或本股。根據(jù)官方規(guī)范,校驗(yàn)和對于大多數(shù)數(shù)據(jù)語句是可選的桐腌,但對有些設(shè)備則是強(qiáng)制性的痊末;
- <CR> <LF>表示消息結(jié)束。
例1:$GPAAM,A,A,0.10,N,WPTNME*32
表示:常規(guī)消息(‘$’為開始符)哩掺;設(shè)備類型為:GP凿叠;消息類型:AAM;數(shù)據(jù)為:A,A,0.10,N,WPTNME嚼吞,校驗(yàn)和:32盒件。
例2:!AIVDM,1,1,,B,177KQJ5000G?tO`K>RA1wUbN0TKH,0*5C
表示:封裝消息(‘!’為開始符);設(shè)備類型為:AI舱禽;消息類型:VDM炒刁;數(shù)據(jù)為:1,1,,B,177KQJ5000G?tO`K>RA1wUbN0TKH,0,校驗(yàn)和:5C誊稚。
新建一類庫NMEAParser翔始,并添加靜態(tài)類NMEA0813Parser
去解析NMEA0813標(biāo)準(zhǔn)ASCII字符,通過識別不同的設(shè)備而采用不用的解碼器里伯。
public static class NMEA0813Parser
{
/// <summary>
/// 將NMEA數(shù)據(jù)解析城瞎,并封裝成Hashtable。
/// </summary>
/// <param name="sentence">NMEA標(biāo)準(zhǔn)的ASCII字符串</param>
/// <returns>將數(shù)據(jù)解析成Hashtable</returns>
/// <exception cref="Exception"></exception>
public static Hashtable Parse(string sentence)
{
if (IsChecksumCorrect(sentence))
{
var ss = sentence.Split('*');
switch (ss[0].Substring(0, 6))
{
//GPS數(shù)據(jù) 暫時(shí)只支持以下八種
case "$GPRMC":
case "$GPGGA":
case "$GPGSA":
case "$GPGLL":
case "$GPGST":
case "$GPGSV":
case "$GPVTG":
case "$GPZDA":
return GPSParser.ParseSentence(ss[0]);
//AIS數(shù)據(jù) 暫時(shí)只支持以下兩種
case "!AIVDM":
case "!AIVDO":
return AISParser.ParseSentence(ss[0]);
default:
break;
}
}
return null;
}
private static bool IsChecksumCorrect(string sentence)
{
if (sentence[0] != '!' && sentence[0] != '$') throw new Exception("NMEA數(shù)據(jù)開始標(biāo)志不正確");
var lastIndex = sentence.LastIndexOf('*');
if (lastIndex > 1)
{
byte checksum = 0;
for (int i = 1; i < lastIndex; i++)
{
// 使用異或
checksum ^= (byte)sentence[i];
}
// 返回十六進(jìn)制的校驗(yàn)和
return checksum.ToString("X2") == sentence.Substring(lastIndex+1, 2);
}
else //不存在校驗(yàn)和
{
return true;
}
}
}
考慮到簡單應(yīng)用疾瓮,代碼并不能完全解析NMEA0813的全部類型的數(shù)據(jù)脖镀。目前,GPS解碼器與AIS解碼器只考慮最常見的情況狼电,具體流程見后文蜒灰。