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