GPS returns Windows Mobile CE 5.2 上的时间戳不正确

GPS returns incorrect time stamp on Windows Mobile CE 5.2

我有一台运行 CE OS 5.2 的摩托罗拉 MC65 设备。我想获得设备的有效时间;我的印象是,因为我从卫星接收到这些数据,所以它会知道该位置的正确时间...

我收到正确的日期,但时间有 3 小时偏差...我是东部时区,设备设置了正确的时区,设备上的时间现在是 11:56am(我知道它关闭了),GPS returns 4:15PM...

这是我当前通过 GPS 获取时间的代码,我使用了 Microsoft (https://msdn.microsoft.com/en-us/library/bb202128.aspx) 的 GPS 中间驱动程序:

public DateTime GetGPSTime()
    {
        Boolean satsInView = false;
        Gps g = new Gps();
        g.DeviceStateChanged += new DeviceStateChangedEventHandler(g_DeviceStateChanged);
        g.Open();
        Thread.Sleep(4000);  

        if (g.Opened)
        {
            if (deviceState.ServiceState == GpsServiceState.On)
            {
                GpsPosition pos = g.GetPosition(TimeSpan.Zero); //No Delay in time
                if (pos != null)
                {
                    //First check that we have sats visible for good GPS signal.
                    if (pos.SatellitesInViewCountValid)
                    {
                        if (pos.SatellitesInViewCount >= 1)
                            satsInView = true;
                        else
                            satsInView = false;
                    }

                    if (pos.TimeValid && satsInView)
                    {
                        g.Close();
                        g.DeviceStateChanged -= g_DeviceStateChanged;
                        return pos.Time; //Returned time obtained from GPS Obj
                    }
                }
                g.Close();
                g.DeviceStateChanged -= g_DeviceStateChanged;
                return Helper.GetSystemTimeToNow(); //If GPS obj is null, return current system time.
            }
        }

        g.Close();
        g.DeviceStateChanged -= g_DeviceStateChanged;
        return Helper.GetSystemTimeToNow(); //If GPS obj is null, return current system time.
    }

此外,这里是来自官方Microsoft Intermediate GPS代码示例的方法。这个方法被我上面的代码调用,GpsPosition pos = g.GetPosition(TimeSpan.Zero);

 /// <summary>
        /// Get the position reported by the GPS receiver that is no older than
        /// the maxAge passed in
        /// </summary>
        /// <param name="maxAge">Max age of the gps position data that you want back. 
        /// If there is no data within the required age, null is returned.  
        /// if maxAge == TimeSpan.Zero, then the age of the data is ignored</param>
        /// <returns>GpsPosition class with all the position details</returns>
        public GpsPosition GetPosition(TimeSpan maxAge)
        {
            GpsPosition gpsPosition = null;
            if (Opened)
            {
                // allocate the necessary memory on the native side.  We have a class (GpsPosition) that 
                // has the same memory layout as its native counterpart
                IntPtr ptr = Utils.LocalAlloc(Marshal.SizeOf(typeof(GpsPosition)));

                // fill in the required fields 
                gpsPosition = new GpsPosition();
                gpsPosition.dwVersion = 1;
                gpsPosition.dwSize = Marshal.SizeOf(typeof(GpsPosition));

                // Marshal our data to the native pointer we allocated.
                Marshal.StructureToPtr(gpsPosition, ptr, false);

                // call native method passing in our native buffer
                int result = GPSGetPosition(gpsHandle, ptr, 500000, 0);
                if (result == 0)
                {
                    // native call succeeded, marshal native data to our managed data
                    gpsPosition = (GpsPosition)Marshal.PtrToStructure(ptr, typeof(GpsPosition));

                    if (maxAge != TimeSpan.Zero)
                    {
                        // check to see if the data is recent enough.
                        if (!gpsPosition.TimeValid || DateTime.Now - maxAge > gpsPosition.Time)
                        {
                            gpsPosition = null;
                        }
                    }
                }
                else if (result == 87) // ERROR_INVALID_PARAMETER)
                {
                    // 
                    // TEMPORARY HACK
                    // 
                    //  http://blogs.msdn.com/cenet/archive/2007/12/06/gpsid-problem-workaround-on-recent-wm6-release.aspx
                    // 

                    Utils.LocalFree(ptr);

                    // allocate the necessary memory on the native side.  We have a class (GpsPosition) that 
                    // has the same memory layout as its native counterpart
                    ptr = Utils.LocalAlloc(376);

                    // fill in the required fields 
                    gpsPosition = new GpsPosition();
                    gpsPosition.dwVersion = 1;
                    gpsPosition.dwSize = 376;

                    // Marshal our data to the native pointer we allocated.
                    Marshal.StructureToPtr(gpsPosition, ptr, false);

                    // call native method passing in our native buffer
                    result = GPSGetPosition(gpsHandle, ptr, 500000, 0);

                    if (result == 0)
                    {
                        // native call succeeded, marshal native data to our managed data
                        gpsPosition = (GpsPosition)Marshal.PtrToStructure(ptr, typeof(GpsPosition));

                        if (maxAge != TimeSpan.Zero)
                        {
                            // check to see if the data is recent enough.
                            if (!gpsPosition.TimeValid || DateTime.Now - maxAge > gpsPosition.Time)
                            {
                                gpsPosition = null;
                            }
                        }
                    }
                }

                // free our native memory
                Utils.LocalFree(ptr);
            }

            return gpsPosition;          
        }

GPS时间应该是好的,如果GPSposition.validField说时间是有效的。

GPS 时间始终为 UTC。设置系统时间是唯一的方法,系统时间也始终是 UTC。由于将系统时间设置为从 DST 时间跨度内部到外部 DST 时间跨度,反之亦然,系统时间应始终设置两次!详情见我的博客...

    private void SetTimeToGPS(DateTime UTCtime)
    {
        if (m_SetTime)
        {
            // Get the local time zone and a base Coordinated Universal 
            // Time (UTC).
            TimeZone localZone = TimeZone.CurrentTimeZone;
            DateTime baseUTC = UTCtime; // new DateTime(2000, 1, 1);

            System.Diagnostics.Debug.WriteLine("\nLocal time: {0}\n",
                localZone.StandardName);

            // Calculate the local time and UTC offset.
            DateTime localTime = localZone.ToLocalTime(baseUTC);
            TimeSpan localOffset =
                localZone.GetUtcOffset(localTime);

            System.Diagnostics.Debug.WriteLine(string.Format("{0,-20:yyyy-MM-dd HH:mm}" +
                "{1,-20:yyyy-MM-dd HH:mm}{2,-12}{3}",
                baseUTC, localTime, localOffset,
                localZone.IsDaylightSavingTime(localTime)));
            //adjust the clock
            //localTime += localOffset;
            PInvokeLibrary.SystemTimeLib.SetTime(localTime);
            m_SetTime = false;
        }
    }

代码是我在 https://github.com/hjgode/win-mobile-code/blob/master/gps8/Gps8/GPS_Sample8/GPSForm1.cs

的 GpsSample8 演示

使用时间进行测试时,请注意您从 GPS (UTC) 获取的时间以及您的设备在将 SystemTime 设置为 GPS 时间两次后对 SystemTime 和 LocalTime 的说明。

顺便说一句:EST 比 UTC 晚 5 小时,而不是 3 小时。应用偏移量后,是否应用 DST(取决于一年中的哪一天)。