1 ポイント 投稿者 GN⁺ 1 시간 전 | 1件のコメント | WhatsAppで共有
  • MozillaのGPS location service終了後、LinuxのGeoClueベースの位置特定の精度が低下し、where-am-iはGeoIPでToronto近辺を25km精度で示していた
  • 固定されたホームサーバーは動かないことを利用し、自宅ネットワーク内で任意のGPS座標をローカルに配信するよう構成した
  • GeoClueは/etc/geoclue/geoclue.confnetwork-nmeaがデフォルトで有効になっており、_nmea-0183._tcp mDNSサービスを見つけてGPS情報を受け取っていた
  • nmea-static-gps-serverは1秒に1回 NMEA 0183 GPSメッセージをTCPで配信し、Avahiで_nmea-0183._tcpサービスを登録する
  • GeoClueを再起動するとクライアントがすぐにサーバーの座標を取得し、結果としてGPS GGA+RMCという説明と0 metersの精度が返され、Gnome Mapsは即座に正しい位置を表示した

GeoClueとNMEAの設定

  • MozillaのGPS location service終了以降、Linuxでは位置精度が低下し、複数のLinuxシステムでFirefoxやGnome Mapsが利用するGeoClueは、where-am-iベースでGeoIPによりToronto近辺を25km精度で示していた
  • where-am-iデモはディストリビューションごとのパッケージとしてインストールできる
    # Fedora  
      sudo dnf install geoclue2-demos  
    
    # Debian family  
      sudo apt install geoclue-2-demo  
    
  • 固定されたホームサーバーは動かないことを利用して、自宅ネットワーク内では任意のGPS座標をローカルで配信するよう構成した
  • 使用したプロトコルはNMEA 0183で、船舶用電子機器向けの仕様群であり、メッセージはシリアルポートまたはTCPソケットで送ることができる
  • 例のGPSメッセージはGPRMCGPGGAの行で構成される
    $GPRMC,204049.000,A,5308.3999,N,00601.9266,E,0.000,0.000,030526,,*02  
    $GPGGA,204049.000,5308.3999,N,00601.9266,E,1,08,1.0,119.0,M,0.0,M,,*6F  
    
  • GeoClueでは/etc/geoclue/geoclue.confnetwork-nmeaがデフォルトで有効になっていた
    # Network NMEA source configuration options  
      [network-nmea]  
    # Fetch location from NMEA sources on local network?  
      enable=true  
    
  • GeoClueは_nmea-0183._tcpというmDNSサービスを探し、レコードを見つけるとそのアドレスへ接続してGPS情報を受け取る

サーバー実装と動作確認

  • nmea-static-gps-serverは1秒ごとにGPS情報を配信するTCPサーバーで、Avahiによって_nmea-0183._tcpサービスを登録する
  • AvahiはLinuxの標準的なmDNS実装で、MacではBonjourが同じ役割を担い、mDNSはローカルネットワーク上の.localアドレスやプリンター・テレビのような機器の検出にも使われる
  • リポジトリには次のようなAvahiサービス設定が含まれている
    <?xml version="1.0" standalone='no'?>  
    <!DOCTYPE service-group SYSTEM "avahi-service.dtd">  
    <service-group>  
      <name replace-wildcards="yes">NMEA GPS (%h)</name>  
      <service>  
        <type>_nmea-0183._tcp</type>  
        <port>10110</port>  
      </service>  
    </service-group>  
    
  • このファイルを/etc/avahi/services/nmea-statis-gpc.serviceにコピーした後、別のマシンでavahi-browseを使ってサービス検出を確認できる
    $ avahi-browse  _nmea-0183._tcp -r -t  
    + wlp192s0 IPv6 NMEA GPS (node05)                             _nmea-0183._tcp      local  
    + wlp192s0 IPv4 NMEA GPS (node05)                             _nmea-0183._tcp      local  
    = wlp192s0 IPv6 NMEA GPS (node05)                             _nmea-0183._tcp      local  
       hostname = [node05.local]  
       address = [fe80::a8c2:15de:9af:19b]  
       port = [10110]  
       txt = []  
    = wlp192s0 IPv4 NMEA GPS (node05)                             _nmea-0183._tcp      local  
       hostname = [node05.local]  
       address = [192.168.2.205]  
       port = [10110]  
       txt = []  
    
  • サービスがnode05.localで動作している場合、telnet node05.local 10110でTCPサーバー自体も簡単にテストできる
  • クライアントでGeoClueを再起動すると、すぐにサーバーの座標を取得した
    $ sudo systemctl restart geoclue  
    $ /usr/libexec/geoclue-2.0/demos/where-am-i  
    
  • 結果はサーバーの正確な座標とGPS GGA+RMCという説明を返し、精度は0 metersと表示された
    Client object: /org/freedesktop/GeoClue2/Client/3  
    
    New location:  
    Latitude:    43.645758°  
    Longitude:   -79.410510°  
    Accuracy:    0 meters  
    Altitude:    119.000000 meters  
    Speed:       0.000000 meters/second  
    Description: GPS GGA+RMC  
    Timestamp:   Sun 03 May 2026 04:58:58 PM (1777841938 seconds since the Epoch)  
    
  • Gnome Mapsはすぐに正しい位置を表示し、Firefoxは再起動が必要だった
  • MacのApple MapsでもLocation Servicesをオフにした状態で動作しているように見えたが、地図上に正確な点は表示されず、おおよその地域だけが合っていた
  • この方法により、自宅にいる間はLinuxマシンが遅く不正確なGPS検索を待たずに正しい位置を即座に取得でき、Linuxを使うゲストや同僚に対して誤った位置をスプーフィングする用途にも使える
  • https://github.com/evert/nmea-static-gps-server

1件のコメント

 
GN⁺ 1 시간 전
Lobste.rs の意見
  • LAN 上で GNSS をアドバタイズできる標準の mDNS サービスがあるなんてまったく知らなかったが、これでここ半年ほど断続的に悩んでいた問題が一発で解決した

    • 何を作っているのか共有してもらえる? 自分の小さなプロジェクトは特定の1つの問題を解決するものだけど、もっと広い使い道があるのか気になった
  • GPS 位置情報のスプーフィングは良いアイデアだが、実際に実装するとなると比較的かなり手間がかかりそう
    Android の設定や Firefox 拡張機能に「実際の位置を使う / カスタム位置を使う」みたいな単純なオプションがあればいいのにと思う
    ただ、IP やロケールのような他の要素と衝突したときに、GPS 位置情報にどれくらい大きな重みが与えられるのかも気になる
    追記すると、ページ最下部で Jeff Geerling の写真を見て一瞬驚いたが、著者ではなく「いいね」を押しただけだと後から気づいた
    できれば彼の仕事は普段あまり見ないようにしている

    • 「できれば彼の仕事は普段あまり見ない」というのは、なぜ?
    • Android にはそういう機能がある気がする。開発者向け機能の Mock Locations
      以前 Trimble の GNSS 受信機を使っていたが、USB OTG だったのか BLE だったのかは覚えていないものの、Trimble アプリが Mock Locations のソースになって、任意の Android アプリがスマホ本体の比較的低精度な位置情報ではなく、測量ポールの高精度な座標、約 2cm レベルを受け取れるようになっていた
  • 面白いが、自分で実装して、ホームネットワークにいるときに Android 端末からこれを配信するスクリプトを作ることもできそう
    まだ本当に必要かどうかまでは完全には確信できていない :p

  • NMEA 0183 が海洋電子機器向けの仕様群だというのは初めて知った
    NMEA が何の略か調べるほど気にしたことはなかったが、ModemManager と Qualcomm モデム経由で名前自体は知っていた

    $ qmicli -d qrtr://0 --loc-get-nmea-types  
    Successfully retrieved NMEA types: gga, gsv, gsa  
    $ mmcli -m any --location-status  
      Location | capabilities: 3gpp-lac-ci, gps-raw, gps-nmea, agps-msa, agps-msb