1 คะแนน โดย GN⁺ 2 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • หลังจาก Mozilla ยุติบริการ GPS location service การระบุตำแหน่งบน Linux ที่อิงกับ GeoClue ก็มีความแม่นยำน้อยลง โดย where-am-i ระบุตำแหน่งใกล้ Toronto ด้วย GeoIP ที่มีความแม่นยำ 25km
  • ผู้เขียนอาศัยข้อเท็จจริงที่ว่าโฮมเซิร์ฟเวอร์แบบติดตั้งประจำที่ไม่ได้เคลื่อนที่ จึงตั้งค่าให้ส่งออก พิกัด GPS ที่ต้องการภายในเครือข่ายบ้านแบบโลคัล
  • GeoClue เปิดใช้ network-nmea ไว้เป็นค่าเริ่มต้นใน /etc/geoclue/geoclue.conf และจะค้นหา บริการ mDNS _nmea-0183._tcp เพื่อรับข้อมูล GPS
  • nmea-static-gps-server จะส่งข้อความ GPS แบบ NMEA 0183 ผ่าน TCP ทุกหนึ่งวินาที และลงทะเบียนบริการ _nmea-0183._tcp ด้วย Avahi
  • หลังรีสตาร์ต GeoClue ไคลเอนต์ก็รับพิกัดจากเซิร์ฟเวอร์ได้ทันที โดยผลลัพธ์แสดงคำอธิบาย GPS GGA+RMC และความแม่นยำ 0 meters ส่วน Gnome Maps ก็แสดงตำแหน่งที่ถูกต้องได้ทันที

การตั้งค่า GeoClue และ NMEA

  • หลังจาก Mozilla ยุติ GPS location service ความแม่นยำของตำแหน่งบน Linux ก็ลดลง และ GeoClue ซึ่ง Firefox และ Gnome Maps ใช้บนหลายระบบ Linux ก็อาศัย GeoIP จึงระบุตำแหน่งใกล้ Toronto ด้วยความแม่นยำ 25km เมื่อทดสอบด้วย where-am-i
  • เดโม where-am-i สามารถติดตั้งได้จากแพ็กเกจของแต่ละดิสโทร
    # Fedora  
      sudo dnf install geoclue2-demos  
    
    # Debian family  
      sudo apt install geoclue-2-demo  
    
  • ผู้เขียนอาศัยข้อเท็จจริงที่ว่าโฮมเซิร์ฟเวอร์แบบติดตั้งประจำที่ไม่ได้เคลื่อนที่ จึงตั้งค่าให้ส่งออก พิกัด GPS ที่ต้องการจากภายในเครือข่ายบ้านแบบโลคัล
  • โปรโตคอลที่ใช้คือ NMEA 0183 ซึ่งเป็นชุดข้อกำหนดสำหรับอุปกรณ์อิเล็กทรอนิกส์ทางเรือ โดยสามารถส่งข้อความผ่านพอร์ตอนุกรมหรือ TCP socket ได้
  • ตัวอย่างข้อความ GPS ประกอบด้วยบรรทัด GPRMC และ GPGGA
    $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 เปิดใช้ network-nmea ไว้เป็นค่าเริ่มต้นใน /etc/geoclue/geoclue.conf
    # Network NMEA source configuration options  
      [network-nmea]  
    # Fetch location from NMEA sources on local network?  
      enable=true  
    
  • GeoClue จะค้นหา บริการ mDNS ชื่อ _nmea-0183._tcp และเมื่อพบเรคอร์ดก็จะเชื่อมต่อไปยังที่อยู่นั้นเพื่อรับข้อมูล GPS

การทำเซิร์ฟเวอร์และการตรวจสอบการทำงาน

  • nmea-static-gps-server เป็นเซิร์ฟเวอร์ TCP ที่ส่งข้อมูล GPS ทุกหนึ่งวินาที และลงทะเบียนบริการ _nmea-0183._tcp ผ่าน Avahi
  • Avahi คือ implementation มาตรฐานของ mDNS บน Linux ส่วนบน 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 ก็สามารถทดสอบตัวเซิร์ฟเวอร์ TCP ได้ง่าย ๆ ด้วย telnet node05.local 10110
  • เมื่อรีสตาร์ต 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⁺ 2 시간 전
ความคิดเห็นจาก Lobste.rs
  • ไม่เคยรู้มาก่อนเลยว่ามีมาตรฐาน บริการ mDNS สำหรับประกาศ GNSS บน LAN ซึ่งมันแก้ปัญหาที่ผม/ฉันครุ่นคิดเป็นพัก ๆ มาราว 6 เดือนได้ตรงจุดทันที

    • พอจะแชร์ได้ไหมว่าคุณกำลังทำอะไรอยู่? โปรเจ็กต์เล็ก ๆ ของผม/ฉันแก้ปัญหาเฉพาะอย่างหนึ่ง แต่ก็สงสัยว่ามันจะมีการใช้งานที่กว้างกว่านี้ไหม
  • การสปูฟตำแหน่ง GPS เป็นไอเดียที่ดี แต่ถ้าจะทำจริงก็ดูเหมือนจะมีงานพอสมควร
    ถ้าในตั้งค่า Android หรือในส่วนขยาย Firefox มีตัวเลือกง่าย ๆ อย่าง “ใช้ตำแหน่งจริง / ใช้ตำแหน่งที่กำหนดเอง” ก็น่าจะดี
    แต่ก็สงสัยเหมือนกันว่าเวลามันขัดกับปัจจัยอื่นอย่าง IP หรือ locale แล้ว ตำแหน่ง GPS จะถูกให้น้ำหนักมากแค่ไหน
    เพิ่มเติมคือผม/ฉันตกใจอยู่แวบหนึ่งตอนเห็นรูป Jeff Geerling ตรงท้ายหน้า ก่อนจะมารู้ทีหลังว่าเขาไม่ได้เป็นผู้เขียน แค่กดไลก์ไว้เท่านั้น
    ถ้าเป็นไปได้ ปกติผม/ฉันจะเลี่ยงงานของเขา

    • ที่บอกว่า “ถ้าเป็นไปได้ ปกติผม/ฉันจะเลี่ยงงานของเขา” นี่เพราะอะไรเหรอ?
    • เหมือนว่า Android จะมีฟีเจอร์แบบนั้นอยู่นะ เป็นฟีเจอร์สำหรับนักพัฒนาชื่อ Mock Locations
      ผม/ฉันเคยใช้ตัวรับสัญญาณ GNSS ของ Trimble จำไม่ได้แล้วว่าเป็น USB OTG หรือ BLE แต่แอปของ Trimble สามารถทำหน้าที่เป็นแหล่ง Mock Locations เพื่อให้แอป Android ใด ๆ ก็ได้ รับพิกัดความแม่นยำสูงจากไม้สตาฟสำรวจ แทนที่จะใช้พิกัดความแม่นยำค่อนข้างต่ำของตัวโทรศัพท์เอง ประมาณ 2 ซม.
  • น่าสนใจดี แต่ก็น่าจะทำเองได้ แล้วก็เขียนสคริปต์ให้ 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