Skip to content

Instantly share code, notes, and snippets.

Last active April 7, 2023 03:10
  • Star 12 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Proof of concept AGPS data loading for PinePhone
# load_agps_data
# proof of concept loading of agps data to quectel modem via AT commands
from datetime import datetime, timezone
import requests
import serial
at_port = '/dev/ttyUSB2' # ttyUSB2 is the command port on mobian - think they renamed via udev on PmOS
agps_url = ''
agps_file = 'RAM:xtra.bin'
def sendCmd(cmdstring):
res = []
while True:
line = ser.readline()
if (line == b''):
return res
def setTime():
now = datetime.utcnow().replace(tzinfo=timezone.utc).strftime('%Y/%m/%d,%H:%M:%S')
return sendCmd(f"AT+QGPSXTRATIME=0,\"{now}\"")
# is ModemManager running? Won't work if it's already got the port
print('open serial port')
ser = serial.Serial(at_port, timeout=1)
print('Check modem will talk to us')
res = sendCmd('AT')
# FIXME - expect response OK - really ought to check this and other responses
## is GPS turned on? If so the later stuff won't work so we'll have to turn it off
print('Is GPS turned on?')
res = sendCmd('AT+QGPS?')
print('Turn off GPS')
res = sendCmd('AT+QGPSEND') # this ought to be sent only if the gps was on...
print('Is AGPS enabled?')
res = sendCmd('AT+QGPSXTRA?')
print('Precautionary enabling of AGPS')
res = sendCmd('AT+QGPSXTRA=1')
print('Is valid AGPS data already loaded?')
res = sendCmd('AT+QGPSXTRADATA?')
# FIXME: check the returned stuff
# actually this check seems unnecessary as the returned value is alway the same
# so doesn't help (and doesn't match the docs)
# fetch http://xtrapath[1-3] and upload
r = requests.get(agps_url)
#FIXME: check r.status_code before doing anything with the data
print('download status: ', r.status_code)
# precautionary delete of the target file - upload will fail if file name in use
print('delete previous AGPS data file')
res = sendCmd(f"AT+QFDEL=\"{agps_file}\"")
print('upload new AGPS data')
res = sendCmd(f"AT+QFUPL=\"{agps_file}\",{len(r.content)}")
# FIXME: check res == CONNECT and don't send if it's not
res = []
while True:
line = ser.readline()
if (line == b''):
#FIXME: calculate agps file checksum and check that it matches the response
# we'll assume here that local system time is kept accurate either by NTP or
# phone network time, so we don't need to fetch SNTP time
print('set current UTC time using local system time')
res = setTime()
print('set AGPS data to file we uploaded')
res = sendCmd(f"AT+QGPSXTRADATA=\"{agps_file}\"")
print('what does it day about data validity now?')
res = sendCmd('AT+QGPSXTRADATA?')
print('NOTE: it\'s given us the same response as before, despite having new data uploaded')
print('enable gps')
res = sendCmd('AT+QGPS=1')
print('close serial port')
if ser.is_open:
Copy link

I get an error in line 34: Traceback (most recent call last): File "/home/diederick/", line 34, in <module> ser = serial.Serial(at_port, timeout=1) AttributeError: module 'serial' has no attribute 'Serial'

I had the same issue because I installed "serial" with pip. You need to install "pyserial" (after uninstalling serial)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment