#!/bin/bash ###AUTHOR### #Harry Dove-Robinson 5/8/2017 #harry@doverobinson.me #https://gist.github.com/hdoverobinson #https://github.com/hdoverobinson ###USAGE### #This is a script used to configure u-blox GPS/GNSS modules from a text file generated by u-center. #This allows for the possibility of simple in-situ u-blox receiver configuration on a Linux host. (u-center is Windows-only software.) #It has been tested on the NEO-M8T and EVK-M8T modules with u-center 8.24 and should work with any GPS receiver on the u-blox 8/M8 firmware. #The script takes its first argument as the path to a GPS device file and the second argument as the path to a .txt file used to configure the GPS. #Example: ./ubxconfig.sh /dev/ttyACM0 NEO-M8T_10HZ_GNSS_SBAS.txt #The receiver is first reset to factory defaults before it is configured from the text file. The configuration is then saved to all available flash. #The configuration text file used should be one that is outputted from u-center (Tools -> GNSS Configuration...). #The packages "dos2unix" and "bc" are required for this script to run. ###NOTES### #The script will not run unless there is an exact match between the MON-VER string of the text file and the MON-VER output of the GPS receiver. #The MON-VER response is the longest parsed by the script, and it may take a few tries before the full message is able to be parsed. #All other messages are sent up to 10 times before being permanently declared "NOT ACKNOWLEDGED". Note that this does not mean that it was explicitly rejected. #If "ERROR - MESSAGE NOT ACKNOWLEDGED" is shown after 10 retries, then there is likely a problem with the contents of the configuration file or communication with the GPS receiver. #It is expected behavior for some UBX messages to be rejected by the receiver. Try running the configuration file within u-center to see which ones. #The STTY variable holds the stty configuration message that sets up the serial line for this script. It assumes a USB device able to run at 921600 baud. #Other stty configuration messages can be loaded in with the output of "stty -F /dev/GPS0 -g" where "GPS0" is the character device file of the GPS. #Currently this script cannot handle changes in the baudrate when used over an analog serial line. The GPS receiver should be connected to the host via USB. export GPS=$1 export CONFIG=$2 export STTY="406:0:18b7:8a30:3:1c:7f:8:4:2:64:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0" export RETRY_COUNT="10" export TIMEOUT=".25s" export UBX_ACK_ACK="b5620501" export UBX_ACK_NAK="b5620500" export UBX_PREAMBLE="B5 62" export UBX_MON_VER_POLL="0A 04 00 00" export UBX_CFG_CFG_REVERTDEFAULT="06 09 0D 00 FF FF 00 00 00 00 00 00 FF FF 00 00 17" export UBX_CFG_CFG_SAVE="06 09 0D 00 00 00 00 00 FF FF 00 00 00 00 00 00 17" #counts number of sent messages up to the set number of retries #anything sent into the counter should fail with exit code 1 and pass with exit code 0 send_counter () { SENT_COUNTER=0 until [ $SENT_COUNTER == $RETRY_COUNT ] && echo "$(tput setaf 1)ERROR - MESSAGE NOT ACKNOWLEDGED$(tput sgr0)" && let ERROR_COUNTER=ERROR_COUNTER+1 || "$@" do let SENT_COUNTER=SENT_COUNTER+1 echo "NOT ACKNOWLEDGED" if [ $SENT_COUNTER -ge 1 ] && [ $SENT_COUNTER -le $(expr $RETRY_COUNT - 1) ] then echo "RETRYING" fi done } #these needed to be functions so that ver_check can loop multiple times if it fails file_mon_ver () { #pulls MON-VER string from configuration file, finds only the hex and reformats for comparison grep "MON-VER" $1 | sed 's/^.*-\s//' | xxd -r -p | xxd -p | tr -d '\n' } dev_mon_ver () { #sends the MON-VER polling message, has larger timeout and set byte range because we expect a long response echo "`ubx_chksum "$UBX_MON_VER_POLL"`" | xxd -r -p > $GPS && timeout 5s cat $GPS | xxd -p -l50000 | grep -m1 -a -A 10 "b5620a04" | tr -d '\n' } ver_check () { if [[ `dev_mon_ver` =~ .*`file_mon_ver $1`.* ]] then echo "Version match!" else return 1 fi } send_ubx () { echo "Sending UBX message: "$@"" #timeout is allowed in case no response is received ubx_response=`timeout $TIMEOUT cat $GPS | xxd -p | grep -m1 -a -e "$UBX_ACK_ACK" -e "$UBX_ACK_NAK" & echo $2 | xxd -r -p > $GPS` if [[ $ubx_response == *$UBX_ACK_ACK* ]] then echo "$(tput setaf 2)ACKNOWLEDGED$(tput sgr0)" && let ACK_COUNTER=ACK_COUNTER+1 elif [[ $ubx_response == *$UBX_ACK_NAK* ]] then echo "$(tput setaf 3)REJECTED$(tput sgr0)" && let NAK_COUNTER=NAK_COUNTER+1 else return 1 fi } ubx_chksum () ############################################################################################################################# ###Fletcher checksum calculator adapted from: http://www.aeronetworks.ca/2014/07/fletcher-checksum-calculator-in-bash.html### ############################################################################################################################# { SUM=0 FLETCHER=0 j=0 printf "$UBX_PREAMBLE " for i in $1 do j=$(echo "ibase=16;$i" | bc) printf "%02X " "$j" SUM=$(echo "$SUM + $j" | bc) SUM=$(echo "$SUM%256" | bc) FLETCHER=$(echo "$FLETCHER + $SUM" | bc) FLETCHER=$(echo "$FLETCHER%256" | bc) done printf "%02X " "$SUM" printf "%02X\n" "$FLETCHER" } main () { #validate the GPS device and .txt file if [[ -c $GPS ]] && [[ -f $CONFIG && -s $CONFIG && $CONFIG == *.txt ]] then #prepare serial port stty -F $GPS $STTY #remove windows carriage returns from config file dos2unix $CONFIG #version compatibility loop echo "Checking compatibility..." until ver_check $1 do echo "Version mismatch! Checking again..." done ACK_COUNTER=0 NAK_COUNTER=0 ERROR_COUNTER=0 #configuration start echo "Configuring u-blox GPS at $GPS from $1..." echo "Resetting to factory defaults..." send_counter send_ubx "UBX-CFG-CFG-REVERTDEFAULT" "$(ubx_chksum "$UBX_CFG_CFG_REVERTDEFAULT")" echo "Restoring configuration from file..." #loop through config file after MON-VER line and pass through ubx_chksum, send_ubx, and send_counter while read -r line do send_counter send_ubx "`echo $line | sed 's/\s.*$//'`" "`ubx_chksum "$(echo $line | sed 's/^.*-\s//')"`" done < <(tail -n+2 $1) echo "Saving configuration to flash..." send_counter send_ubx "UBX-CFG-CFG-SAVE" "$(ubx_chksum "$UBX_CFG_CFG_SAVE")" echo -en "\n" echo "Done!" #print message stats TOTAL=$(($ACK_COUNTER+$NAK_COUNTER+$ERROR_COUNTER)) echo -en "\n" echo "----------------------------------------" echo -en "\n" echo "UBX MESSAGE STATISTICS:" echo "$(tput setaf 2)ACKNOWLEDGED:$(tput sgr0) $ACK_COUNTER ($(echo "scale=2; $ACK_COUNTER / $TOTAL * 100" | bc | sed s/\\.[0-9]\\+//)%)" echo "$(tput setaf 3)REJECTED:$(tput sgr0) $NAK_COUNTER ($(echo "scale=2; $NAK_COUNTER / $TOTAL * 100" | bc | sed s/\\.[0-9]\\+//)%)" echo "$(tput setaf 1)ERRORS:$(tput sgr0) $ERROR_COUNTER ($(echo "scale=2; $ERROR_COUNTER / $TOTAL * 100" | bc | sed s/\\.[0-9]\\+//)%)" echo "TOTAL SENT: $TOTAL" echo -en "\n" else echo "Provide the GPS device as first argument and .txt file as second!" return 1 fi } #check for dos2unix if ! command -v dos2unix > /dev/null 2>&1 then echo "Please install dos2unix!" exit 2 fi #check for bc if ! command -v bc > /dev/null 2>&1 then echo "Please install bc!" exit 2 fi #run main $CONFIG exit $ERROR_COUNTER