Σελίδα 1 από 1

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

ΔημοσίευσηΔημοσιεύτηκε: 08 Αύγ 2018, 15:23
από George0k00
Πρόσφατα πειραματιζόμουν με το διαμοιρασμό του 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/

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

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

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

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

ΔημοσίευσηΔημοσιεύτηκε: 18 Αύγ 2018, 14:53
από George0k00
Έκανα μερικές τροποποιήσεις στον κώδικα, που αφορούν την καλύτερη εμφάνιση και παροχή πληροφοριών 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.