天天看点

在Windows Mobile和Wince(Windows Embedded CE)下使用.NET Compact Framework进行GPS NMEA data数据分析的开发

 转:http://www.cnblogs.com/procoder/archive/2009/05/05/1450219.html

提供GPS功能的Wince和Windows Mobile都需要一个GPS接收器(GPS Receiver)。GPS receiver就像一个收音机,他从太空中各个GPS卫星(Satellites)接收信号,通过自身的算法(一般在Firmware里面)计算出位置等信息,然后以NMEA data的格式输出。GPS receiver就是接收卫星信号转换成NMEA data的设备。

进行GPS的开发需要从GPS receiver取出NMEA data,分析出关心的数据。关心的数据包括经度(Longitude),维度(Latitude)和海拔(Altitude)等等。在Windows Mobile 5以上MS提供了GPS Intermediate Driver,开发人员不再需要自己分析NMEA data了。但是Wince5以及以下版本不提供GPS Intermediate Driver,还是需要自己分析NMEA data来取出关心的信息。本文讲述如何使用C#进行NMEA data的分析。第一眼看,分析NMEA有自己做轮子之嫌,其实了解NMEA的分析也是有好处的,由于各个生产GPS receiver的厂商在硬件工艺和算法的不一样,各个厂商都提供自己扩展的NMEA data,这些数据GPS Intermediate Driver是不支持的,需要自己分析。

NMEA 全称NMEA 0183,是电子与数据的通信规范,也就是协议。实现该协议的设备输出这种规范的数据,其他应用就可以基于这协议分析出相关的数据。NMEA开始用在航海设备上,现在广泛用在GPS设备上,这就是为什么NMEA的原始速度使用Knot(海里/小时)表示。下面是一段GPS NMEA data的范例

$GPRMC, 000006 ,A, 3754.6240 ,S, 14509.7720 ,E, 010.8 , 313.1 , 010108 , 011.8 ,E * 6A

$GPGGA, 201033 , 3754.6240 ,S, 14509.7720 ,E, 1 , 05 , 1.7 , 91.1 ,M, - 1.1 ,M,, * 75

$GPGSA,A, 3 ,, 05 , 10 ,,,, 21 ,, 29 , 30 ,,, 2.9 , 1.7 , 1.3 * 32

$GPGSV, 3 , 3 , 12 , 29 , 74 , 163 , 41 , 30 , 53 , 337 , 40 , 31 , 09 , 266 , 00 , 37 , 00 , 000 , 00 * 78

$PGRME, 6.3 ,M, 11.9 ,M, 13.5 ,M * 25

$PGRMB, 0.0 , 200 ,,,,K,,N,W * 28

$PGRMM,WGS  84 * 06 复制代码

GPS NMEA data有以下特点:

* 每一条NMEA data的数据都是以dollar符号开头。

* 从第二个字符开始的前2个字符表示发送者(talker)和接着3个字符表示数据(message)。其中上面的talker中,GP表示通用的GPS NMEA data,而PG为特定厂商的NMEA data。

* 所有数据字段(data fields)都是使用逗号隔开(comma-delimited)。

* 最后一个数据段接着一个星号(asterisk)。

* 星号后面是两位数字的校正码(checksum),checksum的计算方法是或计算在 '$' 和 '*'之间的所有字符。

* 最后以回车换行(<CR><LF>)结尾。

有了上述规范,开发NMEA的分析器就变得十分简单,分析流程是:先接收一条NMEA语句(NMEA sentence),然后检查语句格式,检查checksum,然后再根据talker和message进行分发,使用不同的算法进行分析。下面为核心分析流程。

         public   bool  Parse( string  sentence)

        {

             string  rawData  =  sentence;

             try

            {

                 if  ( ! IsValid(sentence))

                {

                     return   false ;

                }

                sentence  =  sentence.Substring( 1 , sentence.IndexOf( ' * ' )  -   1 );

                 string [] Words  =  Getwords(sentence);

                 switch  (Words[ 0 ])

                {

                     case   " GPRMC " :

                         return  ParseGPRMC(Words);

                     case   " GPGGA " :

                         return  ParseGPGGA(Words);

                     case   " GPGSA " :

                         return  ParseGPGSA(Words);

                     case   " GPGSV " :

                         return  ParseGPGSV(Words);

                     default :

                         return   false ;

                }

            }

             catch  (Exception e)

            {

                Console.WriteLine(e.Message  +  rawData);

                 return   false ;

            }

        } 复制代码

代码1

Parse为分析接口,所有从GPS Receiver接收到NMEA data全部调用这个接口进行分析。

IsValid检验该NMEA sentence是否有效。

Checksum进行Checksum运算,检验校验码是否有效。

接下来,讲述关键语句的分析。进行语句的分析,需要一个NMEA的规范手册,这个手册可以从GPS厂商下载,例如从Garmin下载 NMEA手册

在该手册的第24页可以看到GPRMC的协议定义。

在Windows Mobile和Wince(Windows Embedded CE)下使用.NET Compact Framework进行GPS NMEA data数据分析的开发

图1

根据手册的规范定义,抽取想要的信息。如下代码:

         private   bool  ParseGPRMC( string [] Words)

        {

             if  (Words[ 1 ].Length  >   0   &  Words[ 9 ].Length  >   0 )

            {

                 int  UtcHours  =  Convert.ToInt32(Words[ 1 ].Substring( 0 ,  2 ));

                 int  UtcMinutes  =  Convert.ToInt32(Words[ 1 ].Substring( 2 ,  2 ));

                 int  UtcSeconds  =  Convert.ToInt32(Words[ 1 ].Substring( 4 ,  2 ));

                 int  UtcMilliseconds  =   0 ;

                 //  Extract milliseconds if it is available

                 if  (Words[ 1 ].Length  >   7 )

                {

                    UtcMilliseconds  =  Convert.ToInt32(Words[ 1 ].Substring( 7 ));

                }

                 int  UtcDay  =  Convert.ToInt32(Words[ 9 ].Substring( 0 ,  2 ));

                 int  UtcMonth  =  Convert.ToInt32(Words[ 9 ].Substring( 2 ,  2 ));

                 //  available for this century

                 int  UtcYear  =  Convert.ToInt32(Words[ 9 ].Substring( 4 ,  2 ))  +   2000 ;

                utcDateTime  =   new  DateTime(UtcYear, UtcMonth, UtcDay, UtcHours, UtcMinutes, UtcSeconds, UtcMilliseconds);

            }

            fixStatus  =  (Words[ 2 ][ 0 ]  ==   ' A ' )  ?  FixStatus.Obtained : FixStatus.Lost;

             if  (Words[ 3 ].Length  >   0   &  Words[ 4 ].Length  ==   1   &  Words[ 5 ].Length  >   0   &  Words[ 6 ].Length  ==   1 )

            {

                latitude.Hours  =   int .Parse(Words[ 3 ].Substring( 0 ,  2 ));

                latitude.Minutes  =   int .Parse(Words[ 3 ].Substring( 2 ,  2 ));

                latitude.Seconds  =  Math.Round( double .Parse(Words[ 3 ].Substring( 5 ,  4 ))  *   6   /   1000.0 ,  3 );

                 if  ( " S "   ==  Words[ 4 ])

                {

                    latitude.Hours  =   - latitude.Hours;

                }

                longitude.Hours  =   int .Parse(Words[ 5 ].Substring( 0 ,  3 ));

                longitude.Minutes  =   int .Parse(Words[ 5 ].Substring( 3 ,  2 ));

                longitude.Seconds  =  Math.Round( double .Parse(Words[ 5 ].Substring( 6 ,  4 ))  *   6   /   1000.0 ,  3 );

                 if  ( " W "   ==  Words[ 6 ])

                {

                    longitude.Hours  =   - longitude.Hours;

                }

            }

             if  (Words[ 8 ].Length  >   0 )

            {

                azimuth  =   decimal .Parse(Words[ 8 ], NmeaCultureInfo);

            }

             if  (Words[ 7 ].Length  >   0 )

            {

                velocity  =   decimal .Parse(Words[ 7 ], NmeaCultureInfo)  *  KMpHPerKnot;

            }

             return   true ;

        } 复制代码

代码2

从ParseGPRMC看,传递的参数是一个string的数组,分析要做的事情就是把数组的元素根据手册翻译成需要的信息,例如字段1为UTC的日期信息,字段9为UTC的时间信息。字段2为fix信息,就是GPS是否完成了初始化的信息。字段3,4为经度,字段5,6为维度。字段7为速度。字段8为角度。

         private   bool  ParseGPGGA( string [] Words)

        {

             if  (Words[ 6 ].Length  >   0 )

            {

                 switch  (Convert.ToInt32(Words[ 6 ]))

                {

                     case   0 :

                        differentialGpsType  =  DifferentialGpsType.NotSet;

                         break ;

                     case   1 :

                        differentialGpsType  =  DifferentialGpsType.SPS;

                         break ;

                     case   2 :

                        differentialGpsType  =  DifferentialGpsType.DSPS;

                         break ;

                     case   3 :

                        differentialGpsType  =  DifferentialGpsType.PPS;

                         break ;

                     case   4 :

                        differentialGpsType  =  DifferentialGpsType.RTK;

                         break ;

                     default :

                        differentialGpsType  =  DifferentialGpsType.NotSet;

                         break ;

                }

            }

             if  (Words[ 7 ].Length  >   0 )

            {

                satellitesInUsed  =  Convert.ToInt32(Words[ 7 ]);

            }

             if  (Words[ 8 ].Length  >   0 )

            {

                horizontalDilutionOfPrecision  =  Convert.ToDecimal(Words[ 8 ]);

            }

             if  (Words[ 9 ].Length  >   0 )

            {

                altitude  =  Convert.ToDecimal(Words[ 9 ]);

            }

             return   true ;

        } 复制代码

代码3

分析ParseGPGGA和分析ParseGPRMC一样,从数组抽取信息,字段6为fix类型,这个参数表示使用了那些辅佐卫星或者地面信号站来提高GPS的精度。SPS为普通类型,DSPS使用了DGPS 地面信号站fix,DSPS使用了WAAS位置卫星fix(只是用在美国),PPS使用了EGNOS位置卫星fix(只是用在欧洲),RTK使用了MSAS位置卫星fix(只是用在亚洲)。字段7为使用卫星的数量。字段8为水平精度。字段9为海拔。

         private   bool  ParseGPGSA( string [] Words)

        {

             if  (Words[ 1 ].Length  >   0 )

            {

                fixMode  =  Words[ 1 ][ 0 ]  ==   ' A '   ?  FixMode.Auto : FixMode.Manual;

            }

             if  (Words[ 2 ].Length  >   0 )

            {

                 switch  (Convert.ToInt32(Words[ 2 ]))

                {

                     case   1 :

                        fixMethod  =  FixMethod.NotSet;

                         break ;

                     case   2 :

                        fixMethod  =  FixMethod.Fix2D;

                         break ;

                     case   3 :

                        fixMethod  =  FixMethod.Fix3D;

                         break ;

                     default :

                        fixMethod  =  FixMethod.NotSet;

                         break ;

                }

            }

             foreach  (GpsSatellite s  in  satellites.Values)

            {

                s.InUsed  =   false ;

            }

            satellitesInUsed  =   0 ;

             for  ( int  i  =   0 ; i  <   12 ;  ++ i)

            {

                 string  id  =  Words[ 3   +  i];

                 if  (id.Length  >   0 )

                {

                     int  nId  =  Convert.ToInt32(id);

                     if  ( ! satellites.ContainsKey(nId))

                    {

                        satellites[nId]  =   new  GpsSatellite();

                        satellites[nId].PRC  =  nId;

                    }

                    satellites[nId].InUsed  =   true ;

                     ++ satellitesInUsed;

                }

            }

             if  (Words[ 15 ].Length  >   0 )

            {

                positionDilutionOfPrecision  =  Convert.ToDecimal(Words[ 15 ]);

            }

             if  (Words[ 16 ].Length  >   0 )

            {

                horizontalDilutionOfPrecision  =  Convert.ToDecimal(Words[ 16 ]);

            }

             if  (Words[ 17 ].Length  >   0 )

            {

                verticalDilutionOfPrecision  =  Convert.ToDecimal(Words[ 17 ]);

            }

             return   true ;

        } 复制代码

代码4

从ParseGPGSA看,字段1为fix的状态,手工fix或者自动fix。字段2为fix的方法,2D或者3D。字段3到14共12个字段分别为在使用卫星的信息。字段15为位置精度信息。字段16为水平精度信息。字段17为垂直精度信息。

         private   bool  ParseGPGSV( string [] Words)

        {

             int  messageNumber  =   0 ;

             if  (Words[ 2 ].Length  >   0 )

            {

                messageNumber  =  Convert.ToInt32(Words[ 2 ]);

            }

             if  (Words[ 3 ].Length  >   0 )

            {

                satellitesInView  =  Convert.ToInt32(Words[ 3 ]);

            }

             if  (messageNumber  ==   0   ||  satellitesInView  ==   0 )

            {

                 return   false ;

            }

             for  ( int  i  =   1 ; i  <=   4 ;  ++ i)

            {

                 if  ((Words.Length  -   1 )  >=  (i  *   4   +   3 ))

                {

                     int  nId  =   0 ;

                     if  (Words[i  *   4 ].Length  >   0 )

                    {

                         string  id  =  Words[i  *   4 ];

                        nId  =  Convert.ToInt32(id);

                         if  ( ! satellites.ContainsKey(nId))

                        {

                            satellites[nId]  =   new  GpsSatellite();

                            satellites[nId].PRC  =  nId;

                        }

                        satellites[nId].InView  =   true ;

                    }

                     if  (Words[i  *   4   +   1 ].Length  >   0 )

                    {

                        satellites[nId].Elevation  =  Convert.ToInt32(Words[i  *   4   +   1 ]);

                    }

                     if  (Words[i  *   4   +   2 ].Length  >   0 )

                    {

                        satellites[nId].Azimuth  =  Convert.ToInt32(Words[i  *   4   +   2 ]);

                    }

                     if  (Words[i  *   4   +   3 ].Length  >   0 )

                    {

                        satellites[nId].SNR  =  Convert.ToInt32(Words[i  *   4   +   3 ]);

                        satellites[nId].NotTracking  =   false ;

                    }

                     else

                    {

                        satellites[nId].NotTracking  =   true ;

                    }

                }

            }

             return   true ;

        } 复制代码

代码5

从ParseGPGSA看,这个比较特别,他把在使用的卫星信息分开多条语句output。如下:

$GPGSV, 3 , 1 , 12 , 03 , 43 , 246 , 46 , 06 , 57 , 263 , 52 , 09 , 10 , 090 , 00 , 14 , 29 , 357 , 41 * 71

$GPGSV, 3 , 2 , 12 , 15 , 12 , 140 , 00 , 16 , 10 , 307 , 00 , 18 , 59 , 140 , 00 , 19 , 20 , 224 , 00 * 75

$GPGSV, 3 , 3 , 12 , 21 , 48 , 089 , 00 , 22 , 69 , 265 , 36 , 24 , 09 , 076 , 00 , 34 , 00 , 000 , 00 * 76

复制代码

字段1为一共分开多少条语句。字段2为当前语句的序号。字段3为在使用的卫星的数量。后面字段分别表示三个不同卫星的信息,取其中一个卫星来解释,字段4为卫星的ID,字段5为太空海拔,字段6为角度,字段7为信号强弱。

对于厂商的私有NMEA data也是同样的方法进行分析,根据文档的描述进行分析。下面为整个类的代码。

在Windows Mobile和Wince(Windows Embedded CE)下使用.NET Compact Framework进行GPS NMEA data数据分析的开发
在Windows Mobile和Wince(Windows Embedded CE)下使用.NET Compact Framework进行GPS NMEA data数据分析的开发

NmeaParser

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)

http://www.CodeHighlighter.com/

-->    public class NmeaParser

    {

        public struct Coordinate

        {

            public int Hours;

            public int Minutes;

            public double Seconds;

        }

        public enum FixStatus

        {

            NotSet,

            Obtained, //A

            Lost //V

        }

        public enum FixMode

        {

            Auto,   //A

            Manual

        }

        public enum FixMethod

        {

            NotSet,

            Fix2D,

            Fix3D

        }

        public enum DifferentialGpsType

        {

            NotSet, 

            SPS,    

            DSPS,   

            PPS,    

            RTK     

        }

        public class GpsSatellite

        {

            public int PRC { get; set; }

            public int Elevation { get; set; }

            public int Azimuth { get; set; }

            public int SNR { get; set; }

            public bool InUsed { get; set; }

            public bool InView { get; set; }

            public bool NotTracking { get; set; }

        }

        private static readonly CultureInfo NmeaCultureInfo = new CultureInfo("en-US");

        private static readonly decimal KMpHPerKnot = decimal.Parse("1.852", NmeaCultureInfo);

        private Coordinate latitude;

        private Coordinate longitude;

        private decimal altitude = 0;

        private DateTime utcDateTime;

        private decimal velocity = 0;

        private decimal azimuth = 0;

        private FixStatus fixStatus;

        private DifferentialGpsType differentialGpsType;

        private FixMode fixMode;

        private FixMethod fixMethod;

        private int satellitesInView;

        private int satellitesInUsed;

        private readonly Dictionary<int, GpsSatellite> satellites;

        private decimal horizontalDilutionOfPrecision = 50;

        private decimal positionDilutionOfPrecision = 50;

        private decimal verticalDilutionOfPrecision = 50;

        public NmeaParser()

        {

            satellites = new Dictionary<int, GpsSatellite>();

        }

        public bool Parse(string sentence)

        {

            string rawData = sentence;

            try

            {

                if (!IsValid(sentence))

                {

                    return false;

                }

                sentence = sentence.Substring(1, sentence.IndexOf('*') - 1);

                string[] Words = Getwords(sentence);

                switch (Words[0])

                {

                    case "GPRMC":

                        return ParseGPRMC(Words);

                    case "GPGGA":

                        return ParseGPGGA(Words);

                    case "GPGSA":

                        return ParseGPGSA(Words);

                    case "GPGSV":

                        return ParseGPGSV(Words);

                    default:

                        return false;

                }

            }

            catch (Exception e)

            {

                Console.WriteLine(e.Message + rawData);

                return false;

            }

        }

        private bool IsValid(string sentence)

        {

            // GPS data can't be zero length

            if (sentence.Length == 0)

            {

                return false;

            }

            // first character must be a $

            if (sentence[0] != '$')

            {

                return false;

            }

            // GPS data can't be longer than 82 character

            if (sentence.Length > 82)

            {

                return false;

            }

            try

            {

                string checksum = sentence.Substring(sentence.IndexOf('*') + 1);

                return Checksum(sentence, checksum);

            }

            catch (Exception e)

            {

                Console.WriteLine("Checksum failure. " + e.Message);

                return false;

            }

        }

        private bool Checksum(string sentence, string checksumStr)

        {

            int checksum = 0;

            int length = sentence.IndexOf('*') - 1;

            // go from first character upto last *

            for (int i = 1; i <= length; ++i)

            {

                checksum = checksum ^ Convert.ToByte(sentence[i]);

            }

            return (checksum.ToString("X2") == checksumStr);

        }

        // Divides a sentence into individual Words

        private static string[] Getwords(string sentence)

        {

            return sentence.Split(',');

        }

        private bool ParseGPRMC(string[] Words)

        {

            if (Words[1].Length > 0 & Words[9].Length > 0)

            {

                int UtcHours = Convert.ToInt32(Words[1].Substring(0, 2));

                int UtcMinutes = Convert.ToInt32(Words[1].Substring(2, 2));

                int UtcSeconds = Convert.ToInt32(Words[1].Substring(4, 2));

                int UtcMilliseconds = 0;

                // Extract milliseconds if it is available

                if (Words[1].Length > 7)

                {

                    UtcMilliseconds = Convert.ToInt32(Words[1].Substring(7));

                }

                int UtcDay = Convert.ToInt32(Words[9].Substring(0, 2));

                int UtcMonth = Convert.ToInt32(Words[9].Substring(2, 2));

                // available for this century

                int UtcYear = Convert.ToInt32(Words[9].Substring(4, 2)) + 2000;

                utcDateTime = new DateTime(UtcYear, UtcMonth, UtcDay, UtcHours, UtcMinutes, UtcSeconds, UtcMilliseconds);

            }

            fixStatus = (Words[2][0] == 'A') ? FixStatus.Obtained : FixStatus.Lost;

            if (Words[3].Length > 0 & Words[4].Length == 1 & Words[5].Length > 0 & Words[6].Length == 1)

            {

                latitude.Hours = int.Parse(Words[3].Substring(0, 2));

                latitude.Minutes = int.Parse(Words[3].Substring(2, 2));

                latitude.Seconds = Math.Round(double.Parse(Words[3].Substring(5, 4)) * 6 / 1000.0, 3);

                if ("S" == Words[4])

                {

                    latitude.Hours = -latitude.Hours;

                }

                longitude.Hours = int.Parse(Words[5].Substring(0, 3));

                longitude.Minutes = int.Parse(Words[5].Substring(3, 2));

                longitude.Seconds = Math.Round(double.Parse(Words[5].Substring(6, 4)) * 6 / 1000.0, 3);

                if ("W" == Words[6])

                {

                    longitude.Hours = -longitude.Hours;

                }

            }

            if (Words[8].Length > 0)

            {

                azimuth = decimal.Parse(Words[8], NmeaCultureInfo);

            }

            if (Words[7].Length > 0)

            {

                velocity = decimal.Parse(Words[7], NmeaCultureInfo) * KMpHPerKnot;

            }

            return true;

        }

        private bool ParseGPGGA(string[] Words)

        {

            if (Words[6].Length > 0)

            {

                switch (Convert.ToInt32(Words[6]))

                {

                    case 0:

                        differentialGpsType = DifferentialGpsType.NotSet;

                        break;

                    case 1:

                        differentialGpsType = DifferentialGpsType.SPS;

                        break;

                    case 2:

                        differentialGpsType = DifferentialGpsType.DSPS;

                        break;

                    case 3:

                        differentialGpsType = DifferentialGpsType.PPS;

                        break;

                    case 4:

                        differentialGpsType = DifferentialGpsType.RTK;

                        break;

                    default:

                        differentialGpsType = DifferentialGpsType.NotSet;

                        break;

                }

            }

            if (Words[7].Length > 0)

            {

                satellitesInUsed = Convert.ToInt32(Words[7]);

            }

            if (Words[8].Length > 0)

            {

                horizontalDilutionOfPrecision = Convert.ToDecimal(Words[8]);

            }

            if (Words[9].Length > 0)

            {

                altitude = Convert.ToDecimal(Words[9]);

            }

            return true;

        }

        private bool ParseGPGSA(string[] Words)

        {

            if (Words[1].Length > 0)

            {

                fixMode = Words[1][0] == 'A' ? FixMode.Auto : FixMode.Manual;

            }

            if (Words[2].Length > 0)

            {

                switch (Convert.ToInt32(Words[2]))

                {

                    case 1:

                        fixMethod = FixMethod.NotSet;

                        break;

                    case 2:

                        fixMethod = FixMethod.Fix2D;

                        break;

                    case 3:

                        fixMethod = FixMethod.Fix3D;

                        break;

                    default:

                        fixMethod = FixMethod.NotSet;

                        break;

                }

            }

            foreach (GpsSatellite s in satellites.Values)

            {

                s.InUsed = false;

            }

            satellitesInUsed = 0;

            for (int i = 0; i < 12; ++i)

            {

                string id = Words[3 + i];

                if (id.Length > 0)

                {

                    int nId = Convert.ToInt32(id);

                    if (!satellites.ContainsKey(nId))

                    {

                        satellites[nId] = new GpsSatellite();

                        satellites[nId].PRC = nId;

                    }

                    satellites[nId].InUsed = true;

                    ++satellitesInUsed;

                }

            }

            if (Words[15].Length > 0)

            {

                positionDilutionOfPrecision = Convert.ToDecimal(Words[15]);

            }

            if (Words[16].Length > 0)

            {

                horizontalDilutionOfPrecision = Convert.ToDecimal(Words[16]);

            }

            if (Words[17].Length > 0)

            {

                verticalDilutionOfPrecision = Convert.ToDecimal(Words[17]);

            }

            return true;

        }

        private bool ParseGPGSV(string[] Words)

        {

            int messageNumber = 0;

            if (Words[2].Length > 0)

            {

                messageNumber = Convert.ToInt32(Words[2]);

            }

            if (Words[3].Length > 0)

            {

                satellitesInView = Convert.ToInt32(Words[3]);

            }

            if (messageNumber == 0 || satellitesInView == 0)

            {

                return false;

            }

            for (int i = 1; i <= 4; ++i)

            {

                if ((Words.Length - 1) >= (i * 4 + 3))

                {

                    int nId = 0;

                    if (Words[i * 4].Length > 0)

                    {

                        string id = Words[i * 4];

                        nId = Convert.ToInt32(id);

                        if (!satellites.ContainsKey(nId))

                        {

                            satellites[nId] = new GpsSatellite();

                            satellites[nId].PRC = nId;

                        }

                        satellites[nId].InView = true;

                    }

                    if (Words[i * 4 + 1].Length > 0)

                    {

                        satellites[nId].Elevation = Convert.ToInt32(Words[i * 4 + 1]);

                    }

                    if (Words[i * 4 + 2].Length > 0)

                    {

                        satellites[nId].Azimuth = Convert.ToInt32(Words[i * 4 + 2]);

                    }

                    if (Words[i * 4 + 3].Length > 0)

                    {

                        satellites[nId].SNR = Convert.ToInt32(Words[i * 4 + 3]);

                        satellites[nId].NotTracking = false;

                    }

                    else

                    {

                        satellites[nId].NotTracking = true;

                    }

                }

            }

            return true;

        }

    }

继续阅读