Bash script για διερμηνεία GPS NMEA

...εφαρμογές για οτιδήποτε άλλο

Συντονιστής: konnn

Bash script για διερμηνεία GPS NMEA

Δημοσίευσηαπό George0k00 » 08 Αύγ 2018, 15:23

Πρόσφατα πειραματιζόμουν με το διαμοιρασμό του GPS ενός κινητού Android στον υπολογιστή μέσω της εφαρμογής Share GPS. Αφού κατάφερα να το δουλέψω και να ανατροφοδοτώ τις σειρές ΝΜΕΑ στον υπολογιστή (το ΝΜΕΑ είναι ένα "πρωτόκολλο" σύμφωνα με το οποίο το τσιπάκι GPS μεταδίδει τα δεδομένα του στις εφαρμογές), διαπίστωσα ότι το λογισμικό του linux (gpsd,xgps, κλπ) ήταν ιδιαίτερα προβληματικό στη συγκεκριμένη περίπτωσή μου και αποφάσισα να φτιάξω ένα σκριπτάκι σε bash (το μόνο είδος προγραμματισμού στο οποίο γνωρίζω να δημιουργήσω κάτι χρήσιμο), για να λαμβάνω τις χρήσιμες πληροφορίες που παρέχει το GPS.
Κώδικας: Επιλογή όλων
#!/bin/bash
# GPS NMEA parsing tool from file
while read -r line
do
string=$(echo $line | cut -d* -f 1)
old_IFS="$IFS"
IFS=','
read -a field <<<"$string"
IFS="$old_IFS"
if [[ "${field[0]}" =~ "GGA" ]]; then
   UTC=$(echo ${field[1]} | fold -w2 | paste -sd':' -)
   LATITUDE="${field[2]} ${field[3]}"
   LONGTITUDE="${field[4]} ${field[5]}"
   SATNUM=${field[7]}
   ALTITUDE=${field[9]}
   SEALVL=${field[11]}
   echo "Global Positioning System Fixed Data"
   echo "Fix taken at: $UTC UTC"
   echo "Number of satellites used: $SATNUM"
   echo "Coordinates: $LATITUDE $LONGTITUDE"
   echo "Altitude: $ALTITUDE meters"
   echo "Sea level: $SEALVL meters"
   echo "_____________________________________________"
elif [[ "${field[0]}" =~ "RMC" ]]; then
   UTC=$(echo ${field[1]} | fold -w2 | paste -sd':' -)
   LATITUDE="${field[3]} ${field[4]}"
   LONGTITUDE="${field[5]} ${field[6]}"
   SPEED=${field[7]}
   HDG=${field[8]} #heading of track in degrees
   MAGNETVAR="${field[10]} ${field[11]}"
   DATE=$(echo ${field[9]} | fold -w2 | paste -sd'/' -)
   echo "Recommended Minimum Specific GNSS Data"
   echo "Fix taken at: $UTC UTC, $DATE"
   echo "Coordinates: $LATITUDE $LONGTITUDE"
   echo "Ground speed: $SPEED knots, heading $HDG"
   echo "Magnetic declination: $MAGNETVAR"
   echo "_____________________________________________"
elif [[ "${field[0]}" =~ "GPGSV" ]]; then
   SATVIEW=${field[3]}
   #first satellite
   SATAID=${field[4]}
   SATAELEVATION=${field[5]}
   SATAAZIMUTH=${field[6]}
   SATASNR=${field[7]}
   #second satellite
   SATBID=${field[8]}
   SATBELEVATION=${field[9]}
   SATBAZIMUTH=${field[10]}
   SATBSNR=${field[11]}
   #third satellite
   SATCID=${field[12]}
   SATCELEVATION=${field[13]}
   SATCAZIMUTH=${field[14]}
   SATCSNR=${field[15]}
   #fourth satellite
   SATDID=${field[16]}
   SATDELEVATION=${field[17]}
   SATDAZIMUTH=${field[18]}
   SATDSNR=${field[19]}
   echo "+-------------------------------------------------------+"
   echo "| GPS satellites in view: $SATVIEW            |"
   echo "+-------------------------------------------------------+"
   echo "|Satellite ID   |$SATAID      |$SATBID   |$SATCID   |$SATDID   |"
   echo "| Elevation   |$SATAELEVATION      |$SATBELEVATION   |$SATCELEVATION   |$SATDELEVATION   |"
   echo "| Azimuth   |$SATAAZIMUTH      |$SATBAZIMUTH   |$SATCAZIMUTH   |$SATDAZIMUTH   |"
   echo "| SNR (dBHZ)   |$SATASNR      |$SATBSNR   |$SATCSNR   |$SATDSNR   |"
   echo "+-------------------------------------------------------+"
elif [[ "${field[0]}" =~ "GLGSV" ]]; then
   SATVIEW=${field[3]}
   #first satellite
   SATAID=${field[4]}
   SATAELEVATION=${field[5]}
   SATAAZIMUTH=${field[6]}
   SATASNR=${field[7]}
   #second satellite
   SATBID=${field[8]}
   SATBELEVATION=${field[9]}
   SATBAZIMUTH=${field[10]}
   SATBSNR=${field[11]}
   #third satellite
   SATCID=${field[12]}
   SATCELEVATION=${field[13]}
   SATCAZIMUTH=${field[14]}
   SATCSNR=${field[15]}
   #fourth satellite
   SATDID=${field[16]}
   SATDELEVATION=${field[17]}
   SATDAZIMUTH=${field[18]}
   SATDSNR=${field[19]}
   echo "+-------------------------------------------------------+"
   echo "| GLONASS satellites in view: $SATVIEW         |"
   echo "+-------------------------------------------------------+"
   echo "|Satellite ID   |$SATAID      |$SATBID   |$SATCID   |$SATDID   |"
   echo "| Elevation   |$SATAELEVATION      |$SATBELEVATION   |$SATCELEVATION   |$SATDELEVATION   |"
   echo "| Azimuth   |$SATAAZIMUTH      |$SATBAZIMUTH   |$SATCAZIMUTH   |$SATDAZIMUTH   |"
   echo "| SNR (dBHZ)   |$SATASNR      |$SATBSNR   |$SATCSNR   |$SATDSNR   |"
   echo "+-------------------------------------------------------+"
fi
#sleep 0
done <"$1"

Επειδή δεν είμαι έμπειρος στο αντικείμενο, μερικοί μπορεί να παρατηρήσουν ατέλειες στον κώδικα. Έψαξα στο forum αν υπάρχει θέμα στο οποίο αναρτούμε τα σκριπτάκια μας και δεν βρήκα, επομένως το έβαλα εδώ με την ελπίδα ότι κάποιος άλλος θα το βρει χρήσιμο και θα εμπνευστεί. Το χρησιμοποιώ αποθηκεύοντας την έξοδο της θύρας του gps σε ένα αρχείο, πχ:
Κώδικας: Επιλογή όλων
sudo cat /dev/rfcomm1 > out.txt

Και αυτό αποθηκέυεται ως εξής:
Κώδικας: Επιλογή όλων
$GPGGA,114601.453,5235.532,N,01258.903,E,1,12,1.0,0.0,M,0.0,M,,*6E
$GPGSA,A,3,01,02,03,04,05,06,07,08,09,10,11,12,1.0,1.0,1.0*30
$GPRMC,114601.453,A,5235.532,N,01258.903,E,77736.8,151.2,080818,000.0,W*7E
$GPGGA,114602.453,5215.081,N,01310.192,E,1,12,1.0,0.0,M,0.0,M,,*6F
$GPGSA,A,3,01,02,03,04,05,06,07,08,09,10,11,12,1.0,1.0,1.0*30
$GPRMC,114602.453,A,5215.081,N,01310.192,E,62144.8,064.4,080818,000.0,W*79
$GPGGA,114603.453,5225.703,N,01332.439,E,1,12,1.0,0.0,M,0.0,M,,*64
$GPGSA,A,3,01,02,03,04,05,06,07,08,09,10,11,12,1.0,1.0,1.0*30
$GPRMC,114603.453,A,5225.703,N,01332.439,E,52983.1,119.9,080818,000.0,W*7D
$GPGGA,114604.453,5215.636,N,01349.990,E,1,12,1.0,0.0,M,0.0,M,,*65
$GPGSA,A,3,01,02,03,04,05,06,07,08,09,10,11,12,1.0,1.0,1.0*30
$GPRMC,114604.453,A,5215.636,N,01349.990,E,52983.1,119.9,080818,000.0,W*7C

(Το συγκεκριμένα το απέκτησα από https://nmeagen.org/ για να μη δείξω την τοποθεσία μου)
Στη συνέχεια φορτώνω το αρχείο με το παραπάνω script:
Κώδικας: Επιλογή όλων
./script.sh out.txt
Recommended Minimum Specific GNSS Data
Fix taken at: 17:36:34 UTC, 07/08/18
Coordinates: xxxx.xxxxx N yyyy.yyyyy E
Ground speed: 0.0 knots, heading
Magnetic declination: 2.5 E
_____________________________________________
Global Positioning System Fixed Data
Fix taken at: 17:36:34 UTC
Number of satellites used: 06
Coordinates: xxxx.xxxxx769564 N yyyy.yyyyy E
Altitude: 80.0 meters
Sea level: 36.0 meters
_____________________________________________
+-------------------------------------------------------+
| GPS satellites in view: 12            |
+-------------------------------------------------------+
|Satellite ID   |01      |03   |09   |11   |
| Elevation   |62      |68   |25   |35   |
| Azimuth   |160      |348   |232   |181   |
| SNR (dBHZ)   |24      |16   |29   |36   |
+-------------------------------------------------------+
+-------------------------------------------------------+
| GPS satellites in view: 12            |
+-------------------------------------------------------+
|Satellite ID   |17      |18   |06   |14   |
| Elevation   |27      |34   |05   |14   |
| Azimuth   |285      |150   |317   |046   |
| SNR (dBHZ)   |16      |36   |   |   |
+-------------------------------------------------------+
+-------------------------------------------------------+
| GPS satellites in view: 12            |
+-------------------------------------------------------+
|Satellite ID   |19      |22   |23   |31   |
| Elevation   |17      |64   |58   |26   |
| Azimuth   |309      |057   |233   |057   |
| SNR (dBHZ)   |      |   |   |   |
+-------------------------------------------------------+

Αυτό που κάνει είναι να αντιστοιχεί τους αριθμούς του NMEA σε δεδομένα που μπορεί να καταλάβει άνθρωπος. Φαίνεται καλύτερα στο τερματικό, διαφορετικά δεν ξέρω να χρησιμοποιώ tab και να φτιάχνω τετραγωνάκια. Δοκίμασα να το χρησιμοποιήσω απευθείας από τη θύρα που αντιστοιχεί sτη συσκευή gps, πχ ./script.sh /dev/rfcomm1 αλλά μερικές φορές δίνει στην έξοδο μ@@@κίες. Δεν έχω κάποιο πρόβλημα αυτή τη στιγμή, αλλά μπορείτε να το τρέξετε και να προτείνεται τροποποιήσεις.

Χρήσιμες πληροφορίες:
ΝΜΕΑ 0183
Share GPS (Android App)
NMEA data
NMEA reference manual (pdf)
https://hbfs.wordpress.com/2013/05/07/p ... with-bash/
Laptop_1
Spoiler: show
1. Acer Aspire A715-71G-55KS
2. Ubuntu Budgie 18.10 4.18 | Ubuntu 18.04 4.17
3. Intel Core i5-7300HQ | 8 GB DDR4 2133 MHz | Nvidia GP107M [GeForce GTX 1050 Mobile] [10de:1c8d] / Intel HD 630
4. Qualcomm Atheros QCA6174 802.11ac [168c:003e] | RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
Laptop_2
Spoiler: show
1. Aspire E5-571-39B5
2. Ubuntu 16.04 4.15.0-36-generic | Windows 10
3. Intel Core i3-4005U │ 8 GB DDR3L 1600 MHz │Intel HD 4400
4. Qualcomm Atheros QCA9565 / AR9565 [168c:0036]│RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
Άβαταρ μέλους
George0k00
Ubuntistas
Ubuntistas
 
Δημοσιεύσεις: 178
Εγγραφή: 17 Αύγ 2014, 18:55
Τοποθεσία: Λάρισα
Launchpad: George0k00
IRC: George0k00
Εκτύπωση

Re: Bash script για διερμηνεία GPS NMEA

Δημοσίευσηαπό Tassos10 » 17 Αύγ 2018, 14:16

Πολύ ωραία δουλειά μπράβο σου! Ακόμη περισσότερο προς τιμήν σου και σε ευχαριστούμε που την μοιράζεσαι μαζί μας και έχουμε την χαρά να συζητήσουμε περί του θέματος.
Εγώ είμαι λίγο άσχετος με το GPS αλλά επίσης κάποια στιγμή είχα σκεφτεί να ασχοληθώ λιγάκι αλλά λόγο δουλειάς δεν έχω προλάβει.

Αυτό που θα ήθελα να σε ρωτήσω όμως πρώτα από όλα είναι, με ποιον τρόπο στέλνει τα δεδομένα το κινητό στον υπολογιστή σου ;
Από την επίσημη σελίδα του Share GPS, βλέπω πως υποστηρίζει διάφορους τρόπους, εσύ ποιον τρόπο προϋποθέτεις για την αποστολή των δεδομένων ;
Η αποστολή γίνεται μονάχα εφόσον το επιλέξεις εσύ ρητά μέσω της εφαρμογής «Share GPS» ;
Spoiler: show
1 Γνώσεις Linux: Πρώτα βήματα ┃ Προγραμματισμού: Πρώτα βήματα ┃ Αγγλικών: Ικανοποιητικό
2 Ubuntu 12.04 precise 3.2.0-50-generic 64bit (el_GR.UTF-8, Unity ubuntu), Ubuntu 3.2.0-49-generic
3 Intel Core2 Quad CPU Q9400 2.66GHz ‖ RAM 3954 MiB ‖ ASRock G31M-S
4 nVidia G92 [GeForce 9800 GT] [10de:0614] {nvidia}
5 eth0: Realtek RTL8101E/RTL8102E PCI Express Fast Ethernet controller [10ec:8136] (rev 02)
Tassos10
dudeTUX
dudeTUX
 
Δημοσιεύσεις: 439
Εγγραφή: 29 Μαρ 2010, 10:43
Εκτύπωση

Re: Bash script για διερμηνεία GPS NMEA

Δημοσίευσηαπό George0k00 » 18 Αύγ 2018, 14:53

Έκανα μερικές τροποποιήσεις στον κώδικα, που αφορούν την καλύτερη εμφάνιση και παροχή πληροφοριών DOP:
Κώδικας: Επιλογή όλων
#!/bin/bash
# GPS NMEA parsing tool from file
while read -r line
do
string=$(echo $line | cut -d* -f 1)
old_IFS="$IFS"
IFS=','
read -a field <<<"$string"
IFS="$old_IFS"
if [[ "${field[0]}" =~ "GGA" ]]; then
   UTC=$(echo ${field[1]} | fold -w2 | paste -sd':' -)
   LATITUDE="${field[2]} ${field[3]}"
   LONGTITUDE="${field[4]} ${field[5]}"
   SATNUM=${field[7]}
   HORDIL=${field[8]}
   ALTITUDE=${field[9]}
   SEALVL=${field[11]}
   echo "Global Positioning System Fixed Data"
   echo "Fix taken at: $UTC UTC"
   echo "Number of satellites used: $SATNUM"
   echo "Horizontal dilution of precision: $HORDIL"
   echo "Coordinates: $LATITUDE $LONGTITUDE"
   echo "Altitude: $ALTITUDE meters"
   echo "Sea level: $SEALVL meters"
   echo "_________________________________________________________"
elif [[ "${field[0]}" =~ "RMC" ]]; then
   UTC=$(echo ${field[1]} | fold -w2 | paste -sd':' -)
   LATITUDE="${field[3]} ${field[4]}"
   LONGTITUDE="${field[5]} ${field[6]}"
   SPEED=${field[7]}
   HDG=${field[8]} #heading of track in degrees
   MAGNETVAR="${field[10]} ${field[11]}"
   DATE=$(echo ${field[9]} | fold -w2 | paste -sd'/' -)
   echo "Recommended Minimum Specific GNSS Data"
   echo "Fix taken at: $UTC UTC, $DATE"
   echo "Coordinates: $LATITUDE $LONGTITUDE"
   echo "Ground speed: $SPEED knots, heading $HDG"
   echo "Magnetic declination: $MAGNETVAR"
   echo "_________________________________________________________"
elif [[ "${field[0]}" =~ "GPGSV" ]]; then
   SATVIEW=${field[3]}
   #first satellite
   SATAID=${field[4]}
   SATAELEVATION=${field[5]}
   SATAAZIMUTH=${field[6]}
   SATASNR=${field[7]}
   #second satellite
   SATBID=${field[8]}
   SATBELEVATION=${field[9]}
   SATBAZIMUTH=${field[10]}
   SATBSNR=${field[11]}
   #third satellite
   SATCID=${field[12]}
   SATCELEVATION=${field[13]}
   SATCAZIMUTH=${field[14]}
   SATCSNR=${field[15]}
   #fourth satellite
   SATDID=${field[16]}
   SATDELEVATION=${field[17]}
   SATDAZIMUTH=${field[18]}
   SATDSNR=${field[19]}
   echo "+-------------------------------------------------------+"
   echo "| GPS satellites in view: $SATVIEW            |"
   echo "+-------------------------------------------------------+"
   echo "| Satellite ID      |$SATAID   |$SATBID   |$SATCID   |$SATDID   |"
   echo "| Elevation      |$SATAELEVATION   |$SATBELEVATION   |$SATCELEVATION   |$SATDELEVATION   |"
   echo "| Azimuth      |$SATAAZIMUTH   |$SATBAZIMUTH   |$SATCAZIMUTH   |$SATDAZIMUTH   |"
   echo "| SNR (dBHz)      |$SATASNR   |$SATBSNR   |$SATCSNR   |$SATDSNR   |"
   echo "+-------------------------------------------------------+"
elif [[ "${field[0]}" =~ "GLGSV" ]]; then
   SATVIEW=${field[3]}
   #first satellite
   SATAID=${field[4]}
   SATAELEVATION=${field[5]}
   SATAAZIMUTH=${field[6]}
   SATASNR=${field[7]}
   #second satellite
   SATBID=${field[8]}
   SATBELEVATION=${field[9]}
   SATBAZIMUTH=${field[10]}
   SATBSNR=${field[11]}
   #third satellite
   SATCID=${field[12]}
   SATCELEVATION=${field[13]}
   SATCAZIMUTH=${field[14]}
   SATCSNR=${field[15]}
   #fourth satellite
   SATDID=${field[16]}
   SATDELEVATION=${field[17]}
   SATDAZIMUTH=${field[18]}
   SATDSNR=${field[19]}
   echo "+-------------------------------------------------------+"
   echo "| GLONASS satellites in view: $SATVIEW         |"
   echo "+-------------------------------------------------------+"
   echo "| Satellite ID      |$SATAID   |$SATBID   |$SATCID   |$SATDID   |"
   echo "| Elevation      |$SATAELEVATION   |$SATBELEVATION   |$SATCELEVATION   |$SATDELEVATION   |"
   echo "| Azimuth      |$SATAAZIMUTH   |$SATBAZIMUTH   |$SATCAZIMUTH   |$SATDAZIMUTH   |"
   echo "| SNR (dBHz)      |$SATASNR   |$SATBSNR   |$SATCSNR   |$SATDSNR   |"
   echo "+-------------------------------------------------------+"
fi
#sleep 0
done <"$1"


Αυτό που θα ήθελα να σε ρωτήσω όμως πρώτα από όλα είναι, με ποιον τρόπο στέλνει τα δεδομένα το κινητό στον υπολογιστή σου ;
Από την επίσημη σελίδα του Share GPS, βλέπω πως υποστηρίζει διάφορους τρόπους, εσύ ποιον τρόπο προϋποθέτεις για την αποστολή των δεδομένων ;


Το script δεν θα παραπονεθεί εφόσον το παρέχουμε δεδομένα NMEA. Εγώ χρησιμοποιώ bluetooth, αλλά και οι επιλογές για USB & TCP πρέπει να δουλεύουν, καθώς πρώτα αποθηκεύω να δεδομένα NMEA σε αρχείο και μετά διαβάζω το αρχείο με το script.

Δοκίμασα και την επιλογή για USB, χρησιμοποιώντας το netcat https://www.jillybunch.com/sharegps/netcat.html για αποθήκευση NMEA:
Κώδικας: Επιλογή όλων
nc localhost 20175 > nmea.txt

Αλλά για κάποιο λόγο τα αρχεία που δημιουργούνται από το netcat, δεν δίνουν έξοδο όταν τα διαβάζει το script, σαν να μη βρίσκει σειρές NMEA. Μόνο αν τα κάνω copy-paste σε άλλο αρχείο λειτουργεί, άρα έχει να κάνει με τον τρόπο που δουλεύει το netcat. Εδώ θα χρειαστώ βοήθεια, γιατί δεν ξέρω τι ακριβώς φταίει.

Αντίθετα όταν έχω το bluetooth, χρησιμοποιώ το cat, που είναι άψογο.
Κώδικας: Επιλογή όλων
sudo cat /dev/rfcomm1 > nmea.txt


Το γεγονός ότι πρέπει να αποθηκεύω πρώτα σε αρχείο δημιουργεί πρόβλημα όταν θέλουμε άμεση πληροφόρηση από το GPS. Αυτό είναι το δεύτερο κομμάτι που κολλάω, καθώς όπως προανέφερα χρησιμοποιώντας το script απευθείας στη θύρα του sharegps δίνει μπαρούφες (το πρόγραμμα διαβάζει μια σειρά κάθε φορά, ίσως επειδή μέχρι να διαβάσει τη μία έχει δημιουργηθεί η επόμενη από το gps, δημιουργώντας πρόβλημα στην αντιστοίχηση των μεταβλητών).

Η αποστολή γίνεται μονάχα εφόσον το επιλέξεις εσύ ρητά μέσω της εφαρμογής «Share GPS» ;

Ναι, πρέπει να ρυθμίσεις από το gps τη σύνδεση και να γράφει "Listening" για να στέλνει δεδομένα στον υπολογιστή.

Επίσης δεν μου αρέσει ότι το share gps διαθέτει premium έκδοση για πρόσθετα χαρακτηριστικά, αλλά ο δημιουργός του φρόντισε για αρκετά κατατοπιστικό οδηγό ακόμη και για linux.
Laptop_1
Spoiler: show
1. Acer Aspire A715-71G-55KS
2. Ubuntu Budgie 18.10 4.18 | Ubuntu 18.04 4.17
3. Intel Core i5-7300HQ | 8 GB DDR4 2133 MHz | Nvidia GP107M [GeForce GTX 1050 Mobile] [10de:1c8d] / Intel HD 630
4. Qualcomm Atheros QCA6174 802.11ac [168c:003e] | RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
Laptop_2
Spoiler: show
1. Aspire E5-571-39B5
2. Ubuntu 16.04 4.15.0-36-generic | Windows 10
3. Intel Core i3-4005U │ 8 GB DDR3L 1600 MHz │Intel HD 4400
4. Qualcomm Atheros QCA9565 / AR9565 [168c:0036]│RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller
Άβαταρ μέλους
George0k00
Ubuntistas
Ubuntistas
 
Δημοσιεύσεις: 178
Εγγραφή: 17 Αύγ 2014, 18:55
Τοποθεσία: Λάρισα
Launchpad: George0k00
IRC: George0k00
Εκτύπωση


Επιστροφή στο Εφαρμογές Άλλες-Διάφορες