⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nmeaparser.cs

📁 嵌入式终端的gps定位程序
💻 CS
字号:

using System;
using System.Globalization;

namespace GPSPet
{
    public class NmeaParser
    {
       
        public static CultureInfo NmeaCultureInfo = new CultureInfo("en-US");
        //用来进行速度转换 1海里=1.150779英里   1英里=1.609344公里    1海里=1.852公里
        public static double KPHPerKnot = double.Parse("1.8520", NmeaCultureInfo);            
         
        #region Delegates
        //位置
        public delegate void PositionReceivedEventHandler(string latitude, string longitude);  
        //时间
        public delegate void DateTimeChangedEventHandler(System.DateTime dateTime); 
        //航向         
        public delegate void BearingReceivedEventHandler(double bearing);       
        //速度                 
        public delegate void SpeedReceivedEventHandler(double speed);    
        //限制速度,不大于55                    
        public delegate void SpeedLimitReachedEventHandler();                            
        //定位     
        public delegate void FixObtainedEventHandler();                
        //导航                       
        public delegate void FixLostEventHandler();
        //接受卫星信息(PRV号星号,仰角,方位,信噪比)
        public delegate void SatelliteReceivedEventHandler(int pseudoRandomCode, int azimuth, int elevation,int signalToNoiseRatio);
        //水平精度
        public delegate void HDOPReceivedEventHandler(double value);
        //垂直精度
        public delegate void VDOPReceivedEventHandler(double value);
        //位置精度
        public delegate void PDOPReceivedEventHandler(double value);
        //可见卫星总数目
        public delegate void SatellitesInViewReceivedEventHandler(int value);
        //使用卫星号
        public delegate void SatellitesUsedReceivedEventHandler(int value);
        //海平面高度
        public delegate void EllipsoidHeightReceivedEventHandler(double value);
        //定位模式,M-手动,A-自动
        public delegate void ModeEventHandler(string value);
        //定位状态,1-无定位,2-2D,3-3D
        public delegate void CurrentStateEventHandler(string  value);



        #endregion
        #region Events
        public event PositionReceivedEventHandler PositionReceived; //位置
        public event DateTimeChangedEventHandler DateTimeChanged; //时间
        public event BearingReceivedEventHandler BearingReceived; //航向 
        public event SpeedReceivedEventHandler SpeedReceived; //速度   
        public event SpeedLimitReachedEventHandler SpeedLimitReached;//限制速度   
        public event FixObtainedEventHandler FixObtained; //定位
        public event FixLostEventHandler FixLost; //导航
        public event SatelliteReceivedEventHandler SatelliteReceived;//接受卫星信息(PRV号星号,仰角,方位,信噪比)
        public event HDOPReceivedEventHandler HDOPReceived; //水平精度
        public event VDOPReceivedEventHandler VDOPReceived; //垂直精度
        public event PDOPReceivedEventHandler PDOPReceived; //位置精度
        public event SatellitesInViewReceivedEventHandler SatellitesInViewReceived;  //显示卫星总数目
        public event SatellitesUsedReceivedEventHandler SatellitesUsed;  //使用卫星号
        public event EllipsoidHeightReceivedEventHandler EllipsoidHeightReceived;   //海平面高度
        public event ModeEventHandler   Mode;  //定位模式
        public event CurrentStateEventHandler CurrentState;  //当前状态

        #endregion

        /// <summary>
        /// 处理从接收器接受来的信息
        /// </summary>
        /// <param name="sentence"></param>
        /// <returns></returns>
        public bool Parse(string sentence)
        {
            // 丢弃不符合序列的句子
            if (!IsValid(sentence)) return false;
            //检查句子的第一个词确定从哪种格式开始解析
            switch (GetWords(sentence)[0])
            {
                case "$GPRMC":
                    return ParseGPRMC(sentence);
                case "$GPGSV":
                    return ParseGPGSV(sentence);
                case "$GPGSA":
                    return ParseGPGSA(sentence);
                case "$GPGGA":
                    return ParseGPGGA(sentence);
                default:
                    return false; // 预示句子没通过检查
            }
        }
 
        /// <summary>
        ///  将句子切隔成词串
        /// </summary>
        /// <param name="sentence"></param>
        /// <returns></returns>
        public string[] GetWords(string sentence)
        {
            //去掉最后的 * 
            sentence = sentence.Substring(0, sentence.IndexOf("*"));
            //按逗号进行分隔
            return sentence.Split(',');
        }

        /// <summary>
        ///  解析 $GPRMC 格式的信息
        /// </summary>
        /// <param name="sentence"></param>
        /// <returns></returns>
        public bool ParseGPRMC(string sentence)
        {
            
            string[] Words = GetWords(sentence);//将句子拆分成词
            if (Words[3] != "" & Words[4] != "" & Words[5] != "" & Words[6] != "") //提取经度,纬度
            {
               
                //// Append hours
                //string Latitude = Words[3].Substring(0, 2) + "\"";
                //// Append minutes
                //Latitude = Latitude + Words[3].Substring(2) + "\"";
                //// Append the hemisphere
                //Latitude = Latitude + Words[4]; 
                //// Append hours
                //string Longitude = Words[5].Substring(0, 3) + "\"";
                //// Append minutes
                //Longitude = Longitude + Words[5].Substring(3) + "\"";
                //// Append the hemisphere
                //Longitude = Longitude + Words[6];
                // Append hours
                string Latitude = Words[3];//纬度
               
                string Longitude = Words[5];//经度
               
               
                // 将变化通知回调应用程序
                if (PositionReceived != null)
                    PositionReceived(Latitude, Longitude);
            }

            if (Words[1] != "")          //提取时,分,秒,毫秒
            {
                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; 
                if (Words[1].Length > 7)   //提取毫秒                         
                {
                    UtcMilliseconds = Convert.ToInt32(Words[1].Substring(7));         
                }
                // 用所有的值建立时间对象
                //用对象today将当前时间转换为通用时间
                System.DateTime Today = System.DateTime.Now.ToUniversalTime();     
                System.DateTime SatelliteTime = new System.DateTime(Today.Year,
                  Today.Month, Today.Day, UtcHours, UtcMinutes, UtcSeconds,
                  UtcMilliseconds);
                // 通知新时间,并调整成本地时间
                if (DateTimeChanged != null)
                    DateTimeChanged(SatelliteTime.ToLocalTime());   //将当前对象satelliteTime的值转化为本地时间
            }

            if (Words[7] != "")            //地面速度
            {
                //将速度解析并表达成 公里/小时
                double Speed = double.Parse(Words[7], NmeaCultureInfo) * KPHPerKnot;
                 
                // 通知新速度
                if (SpeedReceived != null)
                    SpeedReceived(Speed);
                // 是否超出限定速度
                if (Speed > 55)
                    if (SpeedLimitReached != null)
                        SpeedLimitReached();
            }

            if (Words[8] != "")    //航向
            {
                double Bearing = double.Parse(Words[8], NmeaCultureInfo);
                if (BearingReceived != null)
                    BearingReceived(Bearing);
            }
            //当前设备是否有satellite fix?
            if (Words[2] != "")
            {
                switch (Words[2])
                {
                    case "A":     //状态A=定位
                        if (FixObtained != null)
                            FixObtained();
                        break;
                    case "V":     //状态V=导航
                        if (FixLost != null)
                            FixLost();
                        break;
                }
            }
            return true;  //表示句子被检验完毕
        }

        /// <summary>
        /// 解析 $GPGSV 格式的信息
        /// </summary>
        /// <param name="sentence"></param>
        /// <returns></returns>
        public bool ParseGPGSV(string sentence)
        {
            int PseudoRandomCode = 0;  //卫星的PRV号星号
            int Azimuth = 0;           //方位
            int Elevation = 0;         //仰角
            int SignalToNoiseRatio = 0;//信噪比

            // 将句子分隔成词串
            string[] Words = GetWords(sentence);

            // 每句话包含四块卫星信息
            // 读每一块并报告每一块的卫星信息
            int Count = 0;
            for (Count = 1; Count <= 4; Count++)
            {
                if (Words[3] != "")         //可见卫星数目
                {
                    if (SatellitesInViewReceived != null)
                        SatellitesInViewReceived(int.Parse(Words[3]));

                }

                if ((Words.Length - 1) >= (Count * 4 + 3))
                {
                    
                    if (Words[Count * 4] != "" & Words[Count * 4 + 1] != ""
                      & Words[Count * 4 + 2] != "" & Words[Count * 4 + 3] != "")
                    {
                        PseudoRandomCode = System.Convert.ToInt32(Words[Count * 4]); //卫星的PRV号星号
                        Elevation = Convert.ToInt32(Words[Count * 4 + 1]);           //仰角
                        Azimuth = Convert.ToInt32(Words[Count * 4 + 2]);             //方位
                        SignalToNoiseRatio = Convert.ToInt32(Words[Count * 4 + 3]);  //信噪比
                        // 报告卫星信息
                        if (SatelliteReceived != null)
                            SatelliteReceived(PseudoRandomCode, Azimuth,
                            Elevation, SignalToNoiseRatio);
                    }
                }
            }
            return true; //表示句子被检验完毕
        }

        /// <summary>
        /// 解析 $GPGSA 格式的信息
        /// </summary>
        /// <param name="sentence"></param>
        /// <returns></returns>
        public bool ParseGPGSA(string sentence)
        {
            string[] Words = GetWords(sentence);

            if (Words[1] != "")   //定位模式
            {
                if (Mode != null)
                    Mode(Words[1]);
            }
            if (Words[2] != "")   //定位状态
            {
                if (CurrentState != null)
                    CurrentState(Words[2]);
            }
            if (Words[15] != "")   //位置精度
            {
                if (PDOPReceived != null)
                    PDOPReceived(double.Parse(Words[15], NmeaCultureInfo));
            }
            if (Words[16] != "")   //水平精度
            {
                if (HDOPReceived != null)
                    HDOPReceived(double.Parse(Words[16], NmeaCultureInfo));
            }
            if (Words[17] != "")  //垂直精度
            {
                if (VDOPReceived != null)
                    VDOPReceived(double.Parse(Words[17], NmeaCultureInfo));
            }
            return true;
        }

        /// <summary>
        /// 解析$GPGGA格式信息
        /// </summary>
        /// <param name="sentence"></param>
        /// <returns></returns>
        public bool ParseGPGGA(string sentence)
        {
            
            string[] Words = GetWords(sentence);
           
            if (Words[7] != "")             //使用卫星号
            {
                if (SatellitesUsed != null)
                    SatellitesUsed(int.Parse(Words[7]));   
            }
            if (Words[8] != "")
            {
                if (HDOPReceived != null)    //精度百分比
                    HDOPReceived(double.Parse(Words[8], NmeaCultureInfo));
            }

            if (Words[9] != "")             //海平面高度
            {
                if (EllipsoidHeightReceived != null)   
                    EllipsoidHeightReceived(double.Parse(Words[9]));
            }
            return true;
        }

       

        public bool IsValid(string sentence)
        {
            // Compare the characters after the asterisk to the calculation
            return sentence.Substring(sentence.IndexOf("*") + 1) ==
              GetChecksum(sentence);
        }
        // Calculates the checksum for a sentence
        public string GetChecksum(string sentence)
        {
            // Loop through all chars to get a checksum
            int Checksum = 0;
            foreach (char Character in sentence)
            {
                if (Character == '$')
                {
                    // Ignore the dollar sign
                }
                else if (Character == '*')
                {
                    // Stop processing before the asterisk
                    break;
                }
                else
                {
                    // Is this the first value for the checksum?
                    if (Checksum == 0)
                    {
                        // Yes. Set the checksum to the value
                        Checksum = Convert.ToByte(Character);
                    }
                    else
                    {
                        // No. XOR the checksum with this character's value
                        Checksum = Checksum ^ Convert.ToByte(Character);
                    }
                }
            }
            // Return the checksum formatted as a two-character hexadecimal
            return Checksum.ToString("X2");
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -