1 điểm bởi GN⁺ 2 giờ trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Sau khi Mozilla ngừng dịch vụ định vị GPS, việc xác định vị trí dựa trên GeoClue trên Linux trở nên kém chính xác; where-am-i dùng GeoIP và xác định gần Toronto với độ chính xác 25km
  • Tận dụng việc máy chủ gia đình cố định không di chuyển, tác giả cấu hình để phát ra tọa độ GPS mong muốn ngay trong mạng nội bộ
  • Trong GeoClue, network-nmea được bật mặc định trong /etc/geoclue/geoclue.conf, và nó tìm dịch vụ mDNS _nmea-0183._tcp để nhận thông tin GPS
  • nmea-static-gps-server phát các bản tin GPS NMEA 0183 qua TCP mỗi giây một lần, đồng thời đăng ký dịch vụ _nmea-0183._tcp bằng Avahi
  • Sau khi khởi động lại GeoClue, máy khách lập tức nhận đúng tọa độ từ máy chủ; kết quả trả về mô tả GPS GGA+RMC cùng độ chính xác 0 mét, và Gnome Maps hiển thị đúng vị trí ngay lập tức

Cấu hình GeoClue và NMEA

  • Sau khi Mozilla ngừng dịch vụ định vị GPS, độ chính xác vị trí trên Linux giảm xuống; trên nhiều hệ thống Linux, GeoClue mà Firefox và Gnome Maps sử dụng đã xác định where-am-i bằng GeoIP gần Toronto với độ chính xác 25km
  • Có thể cài bản demo where-am-i bằng gói tương ứng theo từng bản phân phối
    # Fedora  
      sudo dnf install geoclue2-demos  
    
    # Debian family  
      sudo apt install geoclue-2-demo  
    
  • Tận dụng việc máy chủ gia đình cố định không di chuyển, tác giả cấu hình để phát tọa độ GPS mong muốn ngay trong mạng nội bộ
  • Giao thức được dùng là NMEA 0183, một bộ đặc tả dành cho thiết bị điện tử hàng hải; bản tin có thể được gửi qua cổng nối tiếp hoặc socket TCP
  • Ví dụ bản tin GPS gồm các dòng 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  
    
  • Trong /etc/geoclue/geoclue.conf, network-nmea được bật mặc định
    # Network NMEA source configuration options  
      [network-nmea]  
    # Fetch location from NMEA sources on local network?  
      enable=true  
    
  • GeoClue tìm dịch vụ mDNS có tên _nmea-0183._tcp; khi phát hiện bản ghi, nó kết nối tới địa chỉ đó để nhận thông tin GPS

Triển khai máy chủ và kiểm tra hoạt động

  • nmea-static-gps-server là một máy chủ TCP phát thông tin GPS mỗi giây một lần, đồng thời đăng ký dịch vụ _nmea-0183._tcp bằng Avahi
  • Avahi là triển khai mDNS tiêu chuẩn trên Linux; trên Mac, Bonjour đảm nhiệm vai trò tương tự, và mDNS cũng được dùng để tìm địa chỉ .local hoặc phát hiện các thiết bị như máy in và TV trong mạng cục bộ
  • Kho lưu trữ có kèm cấu hình dịch vụ Avahi như sau
    <?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>  
    
  • Sau khi chép tệp này vào /etc/avahi/services/nmea-statis-gpc.service, có thể dùng avahi-browse trên máy khác để xác nhận dịch vụ đã được công bố
    $ 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 = []  
    
  • Khi dịch vụ đang chạy trên node05.local, cũng có thể dễ dàng kiểm tra chính máy chủ TCP bằng telnet node05.local 10110
  • Sau khi khởi động lại GeoClue trên máy khách, nó lập tức nhận đúng tọa độ từ máy chủ
    $ sudo systemctl restart geoclue  
    $ /usr/libexec/geoclue-2.0/demos/where-am-i  
    
  • Kết quả trả về đúng tọa độ của máy chủ cùng mô tả GPS GGA+RMC, và độ chính xác được hiển thị là 0 mét
    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 hiển thị đúng vị trí ngay lập tức, còn Firefox cần khởi động lại
  • Trên Apple Maps của Mac, cách này có vẻ cũng hoạt động khi tắt Location Services, nhưng bản đồ không hiển thị điểm chính xác mà chỉ đúng khu vực tương đối
  • Cách làm này giúp các máy Linux trong nhà xác định đúng vị trí ngay lập tức mà không phải chờ truy vấn GPS chậm và kém chính xác; nó cũng có thể được dùng để giả vị trí sai cho khách hoặc đồng nghiệp dùng Linux
  • https://github.com/evert/nmea-static-gps-server

1 bình luận

 
Ý kiến trên Lobste.rs
  • Tôi hoàn toàn không biết là có một dịch vụ mDNS tiêu chuẩn để quảng bá GNSS trên LAN, và nó đã giải quyết ngay một vấn đề mà tôi thỉnh thoảng suy nghĩ suốt khoảng 6 tháng qua

    • Bạn có thể chia sẻ mình đang làm gì không? Dự án nhỏ của tôi chỉ giải quyết một vấn đề cụ thể, nhưng tôi tò mò liệu có ứng dụng rộng hơn không
  • Giả mạo vị trí GPS là một ý tưởng hay, nhưng để triển khai thực tế thì có vẻ vẫn khá nhiều việc
    Sẽ thật tuyệt nếu trong phần cài đặt Android hoặc một tiện ích mở rộng Firefox có tùy chọn đơn giản như “dùng vị trí thật / dùng vị trí tùy chỉnh”
    Dù vậy, tôi cũng thắc mắc GPS location được ưu tiên đến mức nào khi xung đột với các yếu tố khác như IP hay locale
    Nhân tiện, tôi đã hơi giật mình khi thấy ảnh Jeff Geerling ở cuối trang, rồi mới nhận ra là ông ấy chỉ bấm thích chứ không phải tác giả
    Nếu có thể thì tôi thường tránh các sản phẩm của ông ấy

    • “Nếu có thể thì tôi thường tránh các sản phẩm của ông ấy” là vì sao?
    • Hình như Android có tính năng đó. Đó là Mock Locations dành cho nhà phát triển
      Tôi từng dùng bộ thu GNSS của Trimble, không nhớ là qua USB OTG hay BLE, nhưng ứng dụng Trimble có thể làm nguồn Mock Locations để bất kỳ ứng dụng Android nào cũng nhận được tọa độ độ chính xác cao từ cây sào đo đạc, khoảng 2 cm, thay vì độ chính xác tương đối thấp của chính điện thoại
  • Khá thú vị, nhưng tôi cũng có thể tự triển khai và viết một script để phát thứ này từ thiết bị Android khi ở trong mạng gia đình
    Tôi vẫn chưa hoàn toàn chắc mình có thực sự cần nó hay không :p

  • Tôi mới biết NMEA 0183 là một bộ đặc tả dành cho thiết bị điện tử hàng hải
    Tôi chưa từng đủ tò mò để tra xem NMEA nghĩa là gì, nhưng tôi biết tên này thông qua ModemManager và modem 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