Fitz Mutch
Senior Member
I found this little USB GPS on eBay for $10 and it works perfectly to synchronize the router's clock, instead of NTP.
https://www.ebay.com/sch/i.html?_from=R40&_sacat=0&_nkw=usb gps u-blox&_sop=15&_clu=2&_fcid=1
Here's a sample script to synchronize the router clock with a GPS receiver. I verified this works on my RT-N16 router w/stock firmware. So it will likely work for all Asuswrt-Merlin routers too.
/jffs/scripts/setclock-ublox7.sh
Example usage on startup.
/jffs/scripts/init-start
I suppress all NMEA sentences except $GPZDA, so it outputs only the current date/time and hides my geographic location. These settings may be "locked down" to the flash memory of the u-blox GPS, then you don't need to set the UBX codes every time. My u-blox7 USB GPS was very inexpensive. However, there's no flash memory to "lock down" my custom settings. When left unplugged for 4 hours, it resets back to factory defaults. That's why the script must write the UBX codes to the GPS every time.
This information originally appeared in the following post.
https://www.snbforums.com/threads/ntp-daemon-for-asuswrt-merlin.28041/page-10#post-328607
https://www.ebay.com/sch/i.html?_from=R40&_sacat=0&_nkw=usb gps u-blox&_sop=15&_clu=2&_fcid=1
Here's a sample script to synchronize the router clock with a GPS receiver. I verified this works on my RT-N16 router w/stock firmware. So it will likely work for all Asuswrt-Merlin routers too.
/jffs/scripts/setclock-ublox7.sh
Code:
#!/bin/sh
GPS_DEVICE="/dev/ttyACM0"
GPS_PRODUCT="1546:01a7" # u-blox GPS receiver
NMEA_TYPE="GPZDA"
NMEA_DATA_LEN=36
# wait for device to become ready
modprobe cdc-acm
while : ; do
lsusb | grep -qi "$GPS_PRODUCT"
if [ $? -eq 0 ]; then
break
else
sleep 5
fi
done
# configure the u-blox7 GPS to report only $GPZDA
stty -F $GPS_DEVICE 9600 raw -clocal -echo icrnl
ubx_write() {
local cmdline=" $@"
local fmtline="${cmdline// /\\x}"
printf $fmtline >$GPS_DEVICE
}
ubx_write "B5 62 06 02 0A 00 01 00 00 00 00 00 00 00 00 87 9A 77" # Turn off info messages
ubx_write "B5 62 06 01 08 00 F0 00 00 00 00 00 00 00 FF 23" # Disable: NMEA GxGGA
ubx_write "B5 62 06 01 08 00 F0 01 00 00 00 00 00 00 00 2A" # Disable: NMEA GxGLL
ubx_write "B5 62 06 01 08 00 F0 02 00 00 00 00 00 00 01 31" # Disable: NMEA GxGSA
ubx_write "B5 62 06 01 08 00 F0 03 00 00 00 00 00 00 02 38" # Disable: NMEA GxGSV
ubx_write "B5 62 06 01 08 00 F0 04 00 00 00 00 00 00 03 3F" # Disable: NMEA GxRMC
ubx_write "B5 62 06 01 08 00 F0 05 00 00 00 00 00 00 04 46" # Disable: NMEA GxVTG
ubx_write "B5 62 06 01 08 00 F0 06 00 00 00 00 00 00 05 4D" # Disable: NMEA GxGRS
ubx_write "B5 62 06 01 08 00 F0 07 00 00 00 00 00 00 06 54" # Disable: NMEA GxGST
ubx_write "B5 62 06 01 08 00 F0 08 01 01 01 01 01 00 0C 6F" # Enable: NMEA GxZDA
ubx_write "B5 62 06 01 08 00 F0 09 00 00 00 00 00 00 08 62" # Disable: NMEA GxGBS
ubx_write "B5 62 06 01 08 00 F0 0A 00 00 00 00 00 00 09 69" # Disable: NMEA GxDTM
ubx_write "B5 62 06 01 08 00 F0 0D 00 00 00 00 00 00 0C 7E" # Disable: NMEA GxGNS
ubx_write "B5 62 06 01 08 00 F0 0E 00 00 00 00 00 00 0D 85" # Disable: NMEA GxTHS
ubx_write "B5 62 06 01 08 00 F0 0F 00 00 00 00 00 00 0E 8C" # Disable: NMEA GxVLW
#ubx_write "B5 62 06 09 0D 00 00 00 00 00 FF FF 00 00 00 00 00 00 01 1B A9" # Save settings to BBR (battery-backed RAM)
ubx_write "B5 62 06 09 0D 00 00 00 00 00 FF FF 00 00 00 00 00 00 03 1D AB" # Save settings to BBR,Flash
# loop until successful clock synchronization
while : ; do
# wait for NMEA sentence of type $GPZDA
READ_COUNT=0
read NMEA_DATA <$GPS_DEVICE
while [ $? -eq 0 ] && [ ${#NMEA_DATA} -ne $NMEA_DATA_LEN -o "${NMEA_DATA:0:6}" != "\$${NMEA_TYPE}" ]; do
let READ_COUNT++
if [ $READ_COUNT -gt 50 ]; then
READ_COUNT=0
sleep 5
fi
read NMEA_DATA <$GPS_DEVICE
done
# found a NMEA sentence of type $GPZDA with correct length
if [ ${#NMEA_DATA} -eq $NMEA_DATA_LEN ] && [ "${NMEA_DATA:0:6}" == "\$${NMEA_TYPE}" ]; then
# compute the NMEA checksum
L1=${#NMEA_DATA}
let L2=$L1-3
CHECKSUMHEX=${NMEA_DATA##*\*}
CHECKSUM=$(printf "%d" 0x${CHECKSUMHEX})
P=1; CHECKSUM_CALC=0
while [ $P -lt $L2 ]; do
let CHECKSUM_CALC^=$(printf '%d' "'${NMEA_DATA:$P:1}")
let P++
done
# validate the NMEA checksum
if [ $CHECKSUM_CALC -eq $CHECKSUM ]; then
# parse current date/time from NMEA sentence of type $GPZDA
if [ "$NMEA_TYPE" == "GPZDA" ]; then
# 11111111112222222222333333
# 012345678901234567890123456789012345
# $GPZDA,132727.00,07,06,2017,00,00*61
UTC="${NMEA_DATA:23:4}${NMEA_DATA:20:2}${NMEA_DATA:17:2}${NMEA_DATA:7:2}${NMEA_DATA:9:2}.${NMEA_DATA:11:2}"
else
UTC=""
fi
# set the system clock
if [ -n "$UTC" ]; then
# echo $UTC
date -u -s $UTC
if [ $? -eq 0 ]; then
nvram set ntp_ready=1
break
else
sleep 1
fi
fi
fi
fi
done
Example usage on startup.
/jffs/scripts/init-start
Code:
#!/bin/sh
# runs in background and waits indefinitely for successful clock synchronization then exits; you could do it once per day with an additional cron job
/jffs/scripts/setclock-ublox7.sh &
I suppress all NMEA sentences except $GPZDA, so it outputs only the current date/time and hides my geographic location. These settings may be "locked down" to the flash memory of the u-blox GPS, then you don't need to set the UBX codes every time. My u-blox7 USB GPS was very inexpensive. However, there's no flash memory to "lock down" my custom settings. When left unplugged for 4 hours, it resets back to factory defaults. That's why the script must write the UBX codes to the GPS every time.
This information originally appeared in the following post.
https://www.snbforums.com/threads/ntp-daemon-for-asuswrt-merlin.28041/page-10#post-328607
Last edited: