【问题标题】:GPS returns incorrect time stamp on Windows Mobile CE 5.2GPS 在 Windows Mobile CE 5.2 上返回不正确的时间戳
【发布时间】:2016-08-29 16:30:18
【问题描述】:

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

我收到了正确的日期,但时间差了 3 小时...我是东部时区,设备设置了正确的时区,现在设备上的时间是上午 11:56(关闭我知道),GPS 返回下午 4:15...

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

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;          
        }

【问题讨论】:

    标签: c# windows-mobile compact-framework windows-ce


    【解决方案1】:

    如果 GPSposition.validField 表明时间有效,则 GPS 时间应该很好。

    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(取决于一年中的哪一天)。

    【讨论】:

    • 非常感谢您的回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-18
    • 2013-10-16
    • 1970-01-01
    • 2012-04-23
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多