in Backend/src/System.Device/Location/GeoCoordinateWatcherInternal.cs [388:502]
private void HandleLocationChangedEvent(ILocationReport locationReport)
{
const double KnotsToMetersPerSec = 463.0 / 900.0;
GeoCoordinate coordinate = GeoCoordinate.Unknown;
CivicAddress address = CivicAddress.Unknown;
DateTimeOffset timestamp = DateTimeOffset.Now;
SYSTEMTIME systime;
if (0 == locationReport.GetTimestamp(out systime))
{
timestamp = new DateTimeOffset(systime.wYear, systime.wMonth, systime.wDay, systime.wHour,
systime.wMinute, systime.wSecond, systime.wMilliseconds, TimeSpan.Zero);
}
//
// If we are listening for latlong reports and this is one,
// extract the coordinate properties
//
if (m_latLongStatus != ReportStatus.NotSupported)
{
ILatLongReport latLongReport = locationReport as ILatLongReport;
if (latLongReport != null)
{
double latitude, longitude, errorRadius, altitude, altitudeError;
if ((latLongReport.GetLatitude(out latitude) == 0) &&
(latLongReport.GetLongitude(out longitude) == 0))
{
latLongReport.GetErrorRadius(out errorRadius);
latLongReport.GetAltitude(out altitude);
latLongReport.GetAltitudeError(out altitudeError);
double speed = GetDoubleProperty(locationReport, LocationPropertyKey.Speed) * KnotsToMetersPerSec;
double course = GetDoubleProperty(locationReport, LocationPropertyKey.Heading);
coordinate = new GeoCoordinate(latitude, longitude, altitude, errorRadius, altitudeError, speed, course);
}
}
}
//
// Now see if there is civic address data in the report. We do this for both latlong and civic address
// reports to handle the case of one sensor providing both types of data. Only generate a report if
// countryRegion and at least one other string is present. For Win 7 a country string is always present
// because the native location provider API defaults to UserGeoID if no sensor provides one.
//
string countryRegion = GetStringProperty(locationReport, LocationPropertyKey.CountryRegion);
if (countryRegion != String.Empty)
{
string address1 = GetStringProperty(locationReport, LocationPropertyKey.AddressLine1);
string address2 = GetStringProperty(locationReport, LocationPropertyKey.AddressLine2);
string city = GetStringProperty(locationReport, LocationPropertyKey.City);
string postalCode = GetStringProperty(locationReport, LocationPropertyKey.PostalCode);
string stateProvince = GetStringProperty(locationReport, LocationPropertyKey.StateProvince);
if (address1 != String.Empty || address2 != String.Empty || city != String.Empty ||
postalCode != String.Empty || stateProvince != String.Empty)
{
address = new CivicAddress(address1, address2, String.Empty, city, countryRegion, String.Empty, postalCode, stateProvince);
}
}
//
// if we have either coordinate or civic address report data, continue the processing
//
if (!coordinate.IsUnknown || !address.IsUnknown)
{
GeoPositionStatus prevStatus = Status;
//
// Combine with civic address if there is one available
//
if (!coordinate.IsUnknown && (!address.IsUnknown))
{
coordinate.m_address = address;
}
m_position = new GeoPosition<GeoCoordinate>(timestamp, coordinate);
if (IsStarted)
{
//
// Send a location change event if we are reporting a ready status. Otherwise, set
// an event pending flag which will cause the event to be sent when the status
// does switch to ready.
//
if (GeoPositionStatus.Ready == Status)
{
//
// The reported status may have changed because of the received data. If it
// has then generate a status change event.
//
if (Status != prevStatus)
{
OnPositionStatusChanged(new GeoPositionStatusChangedEventArgs(m_curStatus));
}
OnPositionChanged(new GeoPositionChangedEventArgs<GeoCoordinate>(m_position));
}
else
{
m_eventPending = true;
}
}
else
{
//
// Fire Ready event when location is available in case Start() hasn't been called
//
if (GeoPositionStatus.Ready == m_curStatus)
{
OnPositionStatusChanged(new GeoPositionStatusChangedEventArgs(m_curStatus));
}
}
}
}