27560


Visual Studio 2010 C# / .Net Framework 4.0 にて、 Windows Form
アプリケーションの開発を行っています。

アプリケーションの実行環境は Windows 8.1 タブレットをターゲットとしており、  
機能としてはタブレットに内臓されている GPS より現在位置情報の取得を行っています。

下記 `LocationInfo` クラスの Get()
にて緯度経度を返しているのですが、Wifiに接続されているときと、接続されていない場合で取得値に差異があります。  
※ WiFi 接続時は現在地とは全く違う場所を返してきている様です。

  1. Windows 8 標準アプリの「地図」ではオンラインオフラインいずれの場合も正常な位置を取得できているようなのですが、`Windows.Device` より取得できる値と `Windows.System.Device` から取得できる値には違いがあるのでしょうか？
  2. また WiFi 接続時に全く違う場所が返されていることの原因としては、位置情報データベース（どこのサービス？）に登録されているアクセスポイントと経度緯度座標の情報がおかしいと考えればよいのでしょうか？これを解決する術はありますか？
  3. Wifi 接続時であっても GPS センサーの値（衛星値）のみを取得する方法はないでしょうか？  
デバイスに COMポートから直接アクセスを試みましたが、デバイスマネージャの COMポートのツリーには GPS
デバイスは表示されておらず、センサーのツリーに表示されていました。

[code]

    public class LocationInfo
    {
        private static System.Device.Location.GeoCoordinateWatcher _wtc;
        private static double _latitude = double.MinValue;
        private static double _longitude = double.MinValue;
        private static bool _changed;
    
        public static void Get(ref double latitude, ref double longitude)
        {
            _changed = false;
    
            System.Threading.Thread _proc = new System.Threading.Thread(WatcherStart);
            _proc.Start();
    
            while(true)
            {
                if(_changed)
                {
                    latitude = _latitude;
                    longitude = _longitude;                    
                    return;
                }
    
                System.Threading.Thread.Sleep(100);
            }
        }
    
        private static void WatcherStart()
        {
            _wtc = new System.Device.Location.GeoCoordinateWatcher(System.Device.Location.GeoPositionAccuracy.Default);
            _wtc.PositionChanged += new EventHandler<System.Device.Location.GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate>>(PositionChanged);
            _wtc.Start();
        }
    
        private static void PositionChanged(object sender, System.Device.Location.GeoPositionChangedEventArgs<System.Device.Location.GeoCoordinate> e)
        {
            _latitude = e.Position.Location.Latitude;
            _longitude = e.Position.Location.Longitude;            
            _changed = true;
        }
    }
    
[/code]

やりたいことは、常に GPS の衛星情報のみを使用できるようにしたいと考えています。  
（電波をつかめていないときはエラー応答で構わない）

上記質問内容の方法以外にも対応方法等がありましたらご教示ください。


CC BY-SA 3.0
2015-01-27T05:38:28.470
5403
2016-07-12T07:23:57.330
2016-07-12T07:23:57.330
7854
7854
question
c# .net gps windows-8.1
.Net 4.0 C# フォームアプリからのGPS情報取得について


以下、投稿者自己解決による回答です。

Windows API Code
Pack(Microsoft.WindowsAPICodePack.Sensors)を使用することでGPSセンサーからの情報のみを取得することができるようになりました。  
ただしマイクロソフト公式のWindows Api Code
Packソースコード配布サイトは閉じられており、NugetよりDLL(マイクロソフト公式配布ではない)をインストールしています。

ざっとですが対応内容を記載します。初回のデータ取得に時間がかかっているため、起動時にStartRead()しておき、必要な時にプロパティより緯度経度を取得しています。  
※実際のコードにはエラーハンドリング、処理状態の制御などを入れてますので、このままでは動作しないかもしれません。とりあえず必要そうな部分だけ抜き出しています。

またDataReportのValue取得位置のIndexですが、今回は固定のハードウェア構成となっており、出現位置が同じでしたので固定で取得しています。本来はSensorのサポートプロパティリストの配列位置のIndexと同じ位置であるものを取得する必要があるようです。

（参考）<https://msdn.microsoft.com/en-us/library/dd318981(v=vs.85).aspx>

[code]

    /// <summary>
    /// GPS位置情報取得クラス
    /// </summary>
    public class LocationGpsInfo2
    {
        /// <summary>
        /// センサータイプ
        /// </summary>
        private static Guid SENSOR_TYPE_LOCATION_GPS = new Guid("ED4CA589-327A-4FF9-A560-91DA4B48275E");
    
        /// <summary>
        /// データタイプ
        /// </summary>
        private static Guid SENSOR_DATA_TYPE_LOCATION_GUID = new Guid("055C74D8-CA6F-47D6-95C6-1ED3637A0FF4");
    
        /// <summary>
        /// 位置情報センサ
        /// </summary>
        private static Sensor GeolocationSensor;
    
        /// <summary>
        /// インスタンス
        /// </summary>
        private static LocationGpsInfo2 _locationGpsInfo = new LocationGpsInfo2();
    
        /// <summary>
        /// 緯度
        /// </summary>
        private static double _latitude = 0;
        public static double Latitude
        {
            get { return _latitude; }
        }
    
        /// <summary>
        /// 経度
        /// </summary>
        private static double _longitude = 0;
        public static double Longitude
        {
            get { return _longitude; }
        }
    
        private LocationGpsInfo2()
        {
            // センサの取得
            SensorList<Sensor> list = SensorManager.GetSensorsByTypeId(SensorTypes.LocationGps);
    
            GeolocationSensor = list[0];
        }
    
        private static void DataReportChanged(Sensor sender, EventArgs e)
        {
            foreach (Guid formatId in sender.DataReport.Values.Keys)
            {
                if (formatId == SENSOR_DATA_TYPE_LOCATION_GUID)
                {
                    // 位置情報を更新
                    _latitude = (double)sender.DataReport.Values[formatId][0];
                    _longitude = (double)sender.DataReport.Values[formatId][1];
                }
            }
        }
    
        public static void StartRead()
        {
            GeolocationSensor.DataReportChanged += DataReportChanged;
        }
    
        public static void StopRead()
        {
            GeolocationSensor.DataReportChanged -= DataReportChanged;
        }
    }
    
[/code]


CC BY-SA 3.0
2016-07-12T07:21:57.003
27560
2016-07-12T07:21:57.003
7854
5403
answer