Click here to Skip to main content
15,878,814 members
Articles / Mobile Apps / Windows Mobile

Track your position using a Windows Mobile 6 device

Rate me:
Please Sign up or sign in to vote.
4.59/5 (23 votes)
29 Dec 2008CPOL5 min read 130.5K   3.2K   111  
Track your geographical position using a Windows Mobile 6 device and some Google Map programming.
using System;
using System.Runtime.InteropServices;
using System.Collections;

namespace PositionSenderMobile.GPS
{
    #region Internal Native Structures
    [StructLayout(LayoutKind.Sequential)]
    internal struct SystemTime
    {
        internal short year;
        internal short month;
        internal short dayOfWeek;
        internal short day;
        internal short hour;
        internal short minute;
        internal short second;
        internal short millisecond;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct SatelliteArray
    {
        int a, b, c, d, e, f, g, h, i, j, k, l;

        public int Count
        {
            get { return 12; }
        }

        public int this[int value]
        {
            get
            {
                if (value == 0) return a;
                else if (value == 1) return b;
                else if (value == 2) return c;
                else if (value == 3) return d;
                else if (value == 4) return e;
                else if (value == 5) return f;
                else if (value == 6) return g;
                else if (value == 7) return h;
                else if (value == 8) return i;
                else if (value == 9) return j;
                else if (value == 10) return k;
                else if (value == 11) return l;
                else throw new ArgumentOutOfRangeException("value must be 0 - 11");
            }
        }
    }
    #endregion
    
    enum FixQuality : int
    {
        Unknown = 0,
        Gps,
        DGps
    }
    enum FixType : int
    {
        Unknown = 0,
        XyD,
        XyzD
    }

    enum FixSelection : int
    {
        Unknown = 0,
        Auto,
        Manual
    }

    public class Satellite
    {
        public Satellite() { }
        public Satellite(int id, int elevation, int azimuth, int signalStrength)
        {
            this.id = id;
            this.elevation = elevation;
            this.azimuth = azimuth;
            this.signalStrength = signalStrength;
        }

        int id;
        /// <summary>
        /// Id of the satellite
        /// </summary>
        public int Id
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }


        int elevation;
        /// <summary>
        /// Elevation of the satellite
        /// </summary>
        public int Elevation
        {
            get
            {
                return elevation;
            }
            set
            {
                elevation = value;
            }
        }


        int azimuth;
        /// <summary>
        /// Azimuth of the satellite
        /// </summary>
        public int Azimuth
        {
            get
            {
                return azimuth;
            }
            set
            {
                azimuth = value;
            }
        }


        int signalStrength;
        /// <summary>
        /// SignalStrenth of the satellite
        /// </summary>
        public int SignalStrength
        {
            get
            {
                return signalStrength;
            }
            set
            {
                signalStrength = value;
            }
        }

    }

    [StructLayout(LayoutKind.Sequential)]
    public class GpsPosition
    {
        internal GpsPosition() { }
        internal static int GPS_VALID_UTC_TIME = 0x00000001;
        internal static int GPS_VALID_LATITUDE = 0x00000002;
        internal static int GPS_VALID_LONGITUDE = 0x00000004;
        internal static int GPS_VALID_SPEED = 0x00000008;
        internal static int GPS_VALID_HEADING = 0x00000010;
        internal static int GPS_VALID_MAGNETIC_VARIATION = 0x00000020;
        internal static int GPS_VALID_ALTITUDE_WRT_SEA_LEVEL = 0x00000040;
        internal static int GPS_VALID_ALTITUDE_WRT_ELLIPSOID = 0x00000080;
        internal static int GPS_VALID_POSITION_DILUTION_OF_PRECISION = 0x00000100;
        internal static int GPS_VALID_HORIZONTAL_DILUTION_OF_PRECISION = 0x00000200;
        internal static int GPS_VALID_VERTICAL_DILUTION_OF_PRECISION = 0x00000400;
        internal static int GPS_VALID_SATELLITE_COUNT = 0x00000800;
        internal static int GPS_VALID_SATELLITES_USED_PRNS = 0x00001000;
        internal static int GPS_VALID_SATELLITES_IN_VIEW = 0x00002000;
        internal static int GPS_VALID_SATELLITES_IN_VIEW_PRNS = 0x00004000;
        internal static int GPS_VALID_SATELLITES_IN_VIEW_ELEVATION = 0x00008000;
        internal static int GPS_VALID_SATELLITES_IN_VIEW_AZIMUTH = 0x00010000;
        internal static int GPS_VALID_SATELLITES_IN_VIEW_SIGNAL_TO_NOISE_RATIO = 0x00020000;


        internal int dwVersion = 1;             // Current version of GPSID client is using.
        internal int dwSize = 0;                // sizeof(_GPS_POSITION)

        // Not all fields in the structure below are guaranteed to be valid.  
        // Which fields are valid depend on GPS device being used, how stale the API allows
        // the data to be, and current signal.
        // Valid fields are specified in dwValidFields, based on GPS_VALID_XXX flags.
        internal int dwValidFields = 0;

        // Additional information about this location structure (GPS_DATA_FLAGS_XXX)
        internal int dwFlags = 0;

        //** Time related
        internal SystemTime stUTCTime = new SystemTime(); 	//  UTC according to GPS clock.

        //** Position + heading related
        internal double dblLatitude = 0.0;            // Degrees latitude.  North is positive
        internal double dblLongitude = 0.0;           // Degrees longitude.  East is positive
        internal float flSpeed = 0.0f;                // Speed in knots
        internal float flHeading = 0.0f;              // Degrees heading (course made good).  True North=0
        internal double dblMagneticVariation = 0.0;   // Magnetic variation.  East is positive
        internal float flAltitudeWRTSeaLevel = 0.0f;  // Altitute with regards to sea level, in meters
        internal float flAltitudeWRTEllipsoid = 0.0f; // Altitude with regards to ellipsoid, in meters

        //** Quality of this fix
        // Where did we get fix from?
        internal FixQuality fixQuality = FixQuality.Unknown;        
        // Is this 2d or 3d fix?
        internal FixType fixType = FixType.Unknown;      
        // Auto or manual selection between 2d or 3d mode
        internal FixSelection selectionType = FixSelection.Unknown;     
        // Position Dilution Of Precision
        internal float flPositionDilutionOfPrecision = 0.0f;
        // Horizontal Dilution Of Precision
        internal float flHorizontalDilutionOfPrecision = 0.0f; 
        // Vertical Dilution Of Precision
        internal float flVerticalDilutionOfPrecision = 0.0f;   

        //** Satellite information
        // Number of satellites used in solution
        internal int dwSatelliteCount = 0;               
        // PRN numbers of satellites used in the solution
        internal SatelliteArray rgdwSatellitesUsedPRNs = new SatelliteArray();
        // Number of satellites in view.  From 0-GPS_MAX_SATELLITES
        internal int dwSatellitesInView = 0;                      	                   
        // PRN numbers of satellites in view
        internal SatelliteArray rgdwSatellitesInViewPRNs = new SatelliteArray();                
        // Elevation of each satellite in view
        internal SatelliteArray rgdwSatellitesInViewElevation = new SatelliteArray();           
        // Azimuth of each satellite in view
        internal SatelliteArray rgdwSatellitesInViewAzimuth = new SatelliteArray();             
        // Signal to noise ratio of each satellite in view
        internal SatelliteArray rgdwSatellitesInViewSignalToNoiseRatio = new SatelliteArray();  

        /// <summary>
        /// UTC according to GPS clock.
        /// </summary>
        public DateTime Time
        {
            get
            {
                DateTime time = new DateTime(stUTCTime.year, stUTCTime.month, stUTCTime.day, stUTCTime.hour, stUTCTime.minute, stUTCTime.second, stUTCTime.millisecond);
                return time;
            }

        }
        /// <summary>
        /// True if the Time property is valid, false if invalid
        /// </summary>
        public bool TimeValid
        {
            get { return (dwValidFields & GPS_VALID_UTC_TIME) != 0; }
        }


        /// <summary>
        /// Satellites used in the solution
        /// </summary>
        /// <returns>Array of Satellites</returns>
        public Satellite[] GetSatellitesInSolution()
        {
            Satellite[] inViewSatellites = GetSatellitesInView();
            ArrayList list = new ArrayList();
            for (int index = 0; index < dwSatelliteCount; index++)
            {
                Satellite found = null;
                for (int viewIndex = 0; viewIndex < inViewSatellites.Length && found == null; viewIndex++)
                {
                    if (rgdwSatellitesUsedPRNs[index] == inViewSatellites[viewIndex].Id)
                    {
                        found = inViewSatellites[viewIndex];
                        list.Add(found);
                    }
                }
            }

            return (Satellite[])list.ToArray(typeof(Satellite));
        }
        /// <summary>
        /// True if the SatellitesInSolution property is valid, false if invalid
        /// </summary>
        public bool SatellitesInSolutionValid
        {
            get { return (dwValidFields & GPS_VALID_SATELLITES_USED_PRNS) != 0; }
        }



        /// <summary>
        /// Satellites in view
        /// </summary>
        /// <returns>Array of Satellites</returns>
        public Satellite[] GetSatellitesInView()
        {
            Satellite[] satellites = null;
            if (dwSatellitesInView != 0)
            {
                satellites = new Satellite[dwSatellitesInView];
                for (int index = 0; index < satellites.Length; index++)
                {
                    satellites[index] = new Satellite();
                    satellites[index].Azimuth = rgdwSatellitesInViewAzimuth[index];
                    satellites[index].Elevation = rgdwSatellitesInViewElevation[index];
                    satellites[index].Id = rgdwSatellitesInViewPRNs[index];
                    satellites[index].SignalStrength = rgdwSatellitesInViewSignalToNoiseRatio[index];
                }
            }

            return satellites;
        }
        /// <summary>
        /// True if the SatellitesInView property is valid, false if invalid
        /// </summary>
        public bool SatellitesInViewValid
        {
            get { return (dwValidFields & GPS_VALID_SATELLITES_IN_VIEW) != 0; }
        }


        /// <summary>
        /// Number of satellites used in solution
        /// </summary>
        public int SatelliteCount
        {
            get { return dwSatelliteCount; }
        }
        /// <summary>
        /// True if the SatelliteCount property is valid, false if invalid
        /// </summary>
        public bool SatelliteCountValid
        {
            get { return (dwValidFields & GPS_VALID_SATELLITE_COUNT) != 0; }
        }

        /// <summary>
        /// Number of satellites in view.  
        /// </summary>
        public int SatellitesInViewCount
        {
            get { return dwSatellitesInView; }
        }
        /// <summary>
        /// True if the SatellitesInViewCount property is valid, false if invalid
        /// </summary>
        public bool SatellitesInViewCountValid
        {
            get { return (dwValidFields & GPS_VALID_SATELLITES_IN_VIEW) != 0; }
        }

        /// <summary>
        /// Speed in knots
        /// </summary>
        public float Speed
        {
            get { return flSpeed; }
        }
        /// <summary>
        /// True if the Speed property is valid, false if invalid
        /// </summary>
        public bool SpeedValid
        {
            get { return (dwValidFields & GPS_VALID_SPEED) != 0; }
        }

        /// <summary>
        /// Altitude with regards to ellipsoid, in meters
        /// </summary>
        public float EllipsoidAltitude
        {
            get { return flAltitudeWRTEllipsoid; }
        }
        /// <summary>
        /// True if the EllipsoidAltitude property is valid, false if invalid
        /// </summary>
        public bool EllipsoidAltitudeValid
        {
            get { return (dwValidFields & GPS_VALID_ALTITUDE_WRT_ELLIPSOID) != 0; }
        }

        /// <summary>
        /// Altitute with regards to sea level, in meters
        /// </summary>
        public float SeaLevelAltitude
        {
            get { return flAltitudeWRTSeaLevel; }
        }
        /// <summary>
        /// True if the SeaLevelAltitude property is valid, false if invalid
        /// </summary>
        public bool SeaLevelAltitudeValid
        {
            get { return (dwValidFields & GPS_VALID_ALTITUDE_WRT_SEA_LEVEL) != 0; }
        }

        /// <summary>
        /// Latitude in decimal degrees.  North is positive
        /// </summary>
        public double Latitude
        {
            get { return dblLatitude; }
        }
        /// <summary>
        /// Latitude in degrees, minutes, seconds.  North is positive
        /// </summary>
        public DegreesMinutesSeconds LatitudeInDegreesMinutesSeconds
        {
            get { return new DegreesMinutesSeconds(dblLatitude); }
        }

        /// <summary>
        /// True if the Latitude property is valid, false if invalid
        /// </summary>
        public bool LatitudeValid
        {
            get { return (dwValidFields & GPS_VALID_LATITUDE) != 0; }
        }

        /// <summary>
        /// Longitude in decimal degrees.  East is positive
        /// </summary>
        public double Longitude
        {
            get { return dblLongitude; }
        }

        /// <summary>
        /// Longitude in degrees, minutes, seconds.  East is positive
        /// </summary>
        public DegreesMinutesSeconds LongitudeInDegreesMinutesSeconds
        {
            get { return new DegreesMinutesSeconds(dblLongitude); }
        }
        /// <summary>
        /// True if the Longitude property is valid, false if invalid
        /// </summary>
        public bool LongitudeValid
        {
            get { return (dwValidFields & GPS_VALID_LONGITUDE) != 0; }
        }

        /// <summary>
        /// Degrees heading (course made good).  True North=0
        /// </summary>
        public float Heading
        {
            get { return flHeading; }
        }
        /// <summary>
        /// True if the Heading property is valid, false if invalid
        /// </summary>
        public bool HeadingValid
        {
            get { return (dwValidFields & GPS_VALID_HEADING) != 0; }
        }

        /// <summary>
        /// Position Dilution Of Precision
        /// </summary>
        public float PositionDilutionOfPrecision
        {
            get { return flPositionDilutionOfPrecision; }
        }
        /// <summary>
        /// True if the PositionDilutionOfPrecision property is valid, false if invalid
        /// </summary>
        public bool PositionDilutionOfPrecisionValid
        {
            get { return (dwValidFields & GPS_VALID_POSITION_DILUTION_OF_PRECISION) != 0; }
        }

        /// <summary>
        /// Horizontal Dilution Of Precision
        /// </summary>
        public float HorizontalDilutionOfPrecision
        {
            get { return flHorizontalDilutionOfPrecision; }
        }
        /// <summary>
        /// True if the HorizontalDilutionOfPrecision property is valid, false if invalid
        /// </summary>
        public bool HorizontalDilutionOfPrecisionValid
        {
            get { return (dwValidFields & GPS_VALID_HORIZONTAL_DILUTION_OF_PRECISION) != 0; }
        }

        /// <summary>
        /// Vertical Dilution Of Precision
        /// </summary>
        public float VerticalDilutionOfPrecision
        {
            get { return flVerticalDilutionOfPrecision; }
        }
        /// <summary>
        /// True if the VerticalDilutionOfPrecision property is valid, false if invalid
        /// </summary>
        public bool VerticalDilutionOfPrecisionValid
        {
            get { return (dwValidFields & GPS_VALID_VERTICAL_DILUTION_OF_PRECISION) != 0; }
        }
    }

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Netherlands Netherlands
I'm a software engineer, working in this field since May 1989. Currently doing C# .NET development and project management using SCRUM.

Comments and Discussions