#!/usr/bin/env python3 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  os 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  sys 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  signal 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  itertools 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  math 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  time 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  requests 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  shutil 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  subprocess 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  datetime 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  multiprocessing  import  Process ,  Event 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  typing  import  NoReturn 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  struct  import  unpack_from ,  calcsize ,  pack 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  cereal  import  log 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  cereal . messaging  as  messaging 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  openpilot . common . gpio  import  gpio_init ,  gpio_set 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . common . retry  import  retry 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  openpilot . system . hardware . tici . pins  import  GPIO 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  openpilot . common . swaglog  import  cloudlog 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  openpilot . system . qcomgpsd . modemdiag  import  ModemDiag ,  DIAG_LOG_F ,  setup_logs ,  send_recv 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  openpilot . system . qcomgpsd . structs  import  ( dict_unpacker ,  position_report ,  relist , 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              gps_measurement_report ,  gps_measurement_report_sv , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              glonass_measurement_report ,  glonass_measurement_report_sv , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              oemdre_measurement_report ,  oemdre_measurement_report_sv ,  oemdre_svpoly_report , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              LOG_GNSS_GPS_MEASUREMENT_REPORT ,  LOG_GNSS_GLONASS_MEASUREMENT_REPORT , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              LOG_GNSS_POSITION_REPORT ,  LOG_GNSS_OEMDRE_MEASUREMENT_REPORT , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              LOG_GNSS_OEMDRE_SVPOLY_REPORT ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								DEBUG  =  int ( os . getenv ( " DEBUG " ,  " 0 " ) ) == 1 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ASSIST_DATA_FILE  =  ' /tmp/xtra3grc.bin ' 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ASSIST_DATA_FILE_DOWNLOAD  =  ASSIST_DATA_FILE  +  ' .download ' 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								ASSISTANCE_URL  =  ' http://xtrapath3.izatcloud.net/xtra3grc.bin ' 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								LOG_TYPES  =  [ 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  LOG_GNSS_GPS_MEASUREMENT_REPORT , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  LOG_GNSS_GLONASS_MEASUREMENT_REPORT , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  LOG_GNSS_OEMDRE_MEASUREMENT_REPORT , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  LOG_GNSS_POSITION_REPORT , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  LOG_GNSS_OEMDRE_SVPOLY_REPORT , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								] 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								miscStatusFields  =  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " multipathEstimateIsValid " :  0 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " directionIsValid " :  1 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								measurementStatusFields  =  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " subMillisecondIsValid " :  0 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " subBitTimeIsKnown " :  1 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " satelliteTimeIsKnown " :  2 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " bitEdgeConfirmedFromSignal " :  3 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " measuredVelocity " :  4 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " fineOrCoarseVelocity " :  5 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " lockPointValid " :  6 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " lockPointPositive " :  7 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " lastUpdateFromDifference " :  9 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " lastUpdateFromVelocityDifference " :  10 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " strongIndicationOfCrossCorelation " :  11 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " tentativeMeasurement " :  12 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " measurementNotUsable " :  13 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " sirCheckIsNeeded " :  14 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " probationMode " :  15 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " multipathIndicator " :  24 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " imdJammingIndicator " :  25 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " lteB13TxJammingIndicator " :  26 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " freshMeasurementIndicator " :  27 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								measurementStatusGPSFields  =  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " gpsRoundRobinRxDiversity " :  18 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " gpsRxDiversity " :  19 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " gpsLowBandwidthRxDiversityCombined " :  20 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " gpsHighBandwidthNu4 " :  21 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " gpsHighBandwidthNu8 " :  22 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " gpsHighBandwidthUniform " :  23 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								measurementStatusGlonassFields  =  { 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " glonassMeanderBitEdgeValid " :  16 , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  " glonassTimeMarkValid " :  17 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								} 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								@retry ( attempts = 10 ,  delay = 1.0 ) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  try_setup_logs ( diag ,  logs ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  setup_logs ( diag ,  logs ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								@retry ( attempts = 3 ,  delay = 1.0 ) 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  at_cmd ( cmd :  str )  - >  str  |  None : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  return  subprocess . check_output ( f " mmcli -m any --timeout 30 --command= ' { cmd } ' " ,  shell = True ,  encoding = ' utf8 ' ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  gps_enabled ( )  - >  bool : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  return  " QGPS: 1 "  in  at_cmd ( " AT+QGPS? " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  download_assistance ( ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  try : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    response  =  requests . get ( ASSISTANCE_URL ,  timeout = 5 ,  stream = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    with  open ( ASSIST_DATA_FILE_DOWNLOAD ,  ' wb ' )  as  fp : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      for  chunk  in  response . iter_content ( chunk_size = 8192 ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fp . write ( chunk ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  fp . tell ( )  >  1e5 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          cloudlog . error ( " Qcom assistance data larger than expected " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    os . rename ( ASSIST_DATA_FILE_DOWNLOAD ,  ASSIST_DATA_FILE ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  except  requests . exceptions . RequestException : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . exception ( " Failed to download assistance file " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  downloader_loop ( event ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  os . path . exists ( ASSIST_DATA_FILE ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    os . remove ( ASSIST_DATA_FILE ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  alt_path  =  os . getenv ( " QCOM_ALT_ASSISTANCE_PATH " ,  None ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  alt_path  is  not  None  and  os . path . exists ( alt_path ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    shutil . copyfile ( alt_path ,  ASSIST_DATA_FILE ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  try : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  not  os . path . exists ( ASSIST_DATA_FILE )  and  not  event . is_set ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      download_assistance ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      event . wait ( timeout = 10 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  except  KeyboardInterrupt : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								@retry ( attempts = 5 ,  delay = 0.2 ,  ignore_failure = True ) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  inject_assistance ( ) : 
 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								  cmd  =  f " mmcli -m any --timeout 30 --location-inject-assistance-data= { ASSIST_DATA_FILE } " 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  subprocess . check_output ( cmd ,  stderr = subprocess . PIPE ,  shell = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cloudlog . info ( " successfully loaded assistance data " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								@retry ( attempts = 5 ,  delay = 1.0 ) 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  setup_quectel ( diag :  ModemDiag )  - >  bool : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ret  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # enable OEMDRE in the NV 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # TODO: it has to reboot for this to take effect 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  DIAG_NV_READ_F  =  38 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  DIAG_NV_WRITE_F  =  39 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  NV_GNSS_OEM_FEATURE_MASK  =  7165 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  send_recv ( diag ,  DIAG_NV_WRITE_F ,  pack ( ' <HI ' ,  NV_GNSS_OEM_FEATURE_MASK ,  1 ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  send_recv ( diag ,  DIAG_NV_READ_F ,  pack ( ' <H ' ,  NV_GNSS_OEM_FEATURE_MASK ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  try_setup_logs ( diag ,  LOG_TYPES ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  gps_enabled ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    at_cmd ( " AT+QGPSEND " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  " GPS_COLD_START "  in  os . environ : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # deletes all assistance 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    at_cmd ( " AT+QGPSDEL=0 " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # allow module to perform hot start 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    at_cmd ( " AT+QGPSDEL=1 " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # disable DPO power savings for more accuracy 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  at_cmd ( " AT+QGPSCFG= \" dpoenable \" ,0 " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # don't automatically turn on GNSS on powerup 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  at_cmd ( " AT+QGPSCFG= \" autogps \" ,0 " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # Do internet assistance 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  at_cmd ( " AT+QGPSXTRA=1 " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  at_cmd ( " AT+QGPSSUPLURL= \" NULL \" " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  os . path . exists ( ASSIST_DATA_FILE ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret  =  True 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    inject_assistance ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    os . remove ( ASSIST_DATA_FILE ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  #at_cmd("AT+QGPSXTRADATA?") 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  time_str  =  datetime . datetime . utcnow ( ) . strftime ( " % Y/ % m/ %d , % H: % M: % S " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  at_cmd ( f " AT+QGPSXTRATIME=0, \" { time_str } \" ,1,1,1000 " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  at_cmd ( " AT+QGPSCFG= \" outport \" , \" usbnmea \" " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  at_cmd ( " AT+QGPS=1 " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # enable OEMDRE mode 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  DIAG_SUBSYS_CMD_F  =  75 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  DIAG_SUBSYS_GPS  =  13 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  CGPS_DIAG_PDAPI_CMD  =  0x64 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  CGPS_OEM_CONTROL  =  202 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GPSDIAG_OEMFEATURE_DRE  =  1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  GPSDIAG_OEM_DRE_ON  =  1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # gpsdiag_OemControlReqType 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  send_recv ( diag ,  DIAG_SUBSYS_CMD_F ,  pack ( ' <BHBBIIII ' , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    DIAG_SUBSYS_GPS ,            # Subsystem Id 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    CGPS_DIAG_PDAPI_CMD ,        # Subsystem Command Code 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    CGPS_OEM_CONTROL ,           # CGPS Command Code 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    0 ,                          # Version 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    GPSDIAG_OEMFEATURE_DRE , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    GPSDIAG_OEM_DRE_ON , 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    0 , 0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  return  ret 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  teardown_quectel ( diag ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  at_cmd ( " AT+QGPSCFG= \" outport \" , \" none \" " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  if  gps_enabled ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    at_cmd ( " AT+QGPSEND " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  try_setup_logs ( diag ,  [ ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  wait_for_modem ( cmd = " AT+QGPS? " ) : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cloudlog . warning ( " waiting for modem to come up " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while  True : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ret  =  subprocess . call ( f " mmcli -m any --timeout 10 --command= \" { cmd } \" " ,  stdout = subprocess . DEVNULL ,  stderr = subprocess . DEVNULL ,  shell = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ret  ==  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      return 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    time . sleep ( 0.1 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  main ( )  - >  NoReturn : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  unpack_gps_meas ,  size_gps_meas  =  dict_unpacker ( gps_measurement_report ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  unpack_gps_meas_sv ,  size_gps_meas_sv  =  dict_unpacker ( gps_measurement_report_sv ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  unpack_glonass_meas ,  size_glonass_meas  =  dict_unpacker ( glonass_measurement_report ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  unpack_glonass_meas_sv ,  size_glonass_meas_sv  =  dict_unpacker ( glonass_measurement_report_sv ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  unpack_oemdre_meas ,  size_oemdre_meas  =  dict_unpacker ( oemdre_measurement_report ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  unpack_oemdre_meas_sv ,  size_oemdre_meas_sv  =  dict_unpacker ( oemdre_measurement_report_sv ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  unpack_svpoly ,  _  =  dict_unpacker ( oemdre_svpoly_report ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  unpack_position ,  _  =  dict_unpacker ( position_report ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  unpack_position ,  _  =  dict_unpacker ( position_report ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  wait_for_modem ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  stop_download_event  =  Event ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assist_fetch_proc  =  Process ( target = downloader_loop ,  args = ( stop_download_event , ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  assist_fetch_proc . start ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  def  cleanup ( sig ,  frame ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . warning ( " caught sig disabling quectel gps " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    gpio_set ( GPIO . GNSS_PWR_EN ,  False ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    teardown_quectel ( diag ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    cloudlog . warning ( " quectel cleanup done " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    stop_download_event . set ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    assist_fetch_proc . kill ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    assist_fetch_proc . join ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    sys . exit ( 0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  signal . signal ( signal . SIGINT ,  cleanup ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  signal . signal ( signal . SIGTERM ,  cleanup ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  # connect to modem 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  diag  =  ModemDiag ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  r  =  setup_quectel ( diag ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  want_assistance  =  not  r 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  cloudlog . warning ( " quectel setup done " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gpio_init ( GPIO . GNSS_PWR_EN ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  gpio_set ( GPIO . GNSS_PWR_EN ,  True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  pm  =  messaging . PubMaster ( [ ' qcomGnss ' ,  ' gpsLocation ' ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  while  1 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  os . path . exists ( ASSIST_DATA_FILE )  and  want_assistance : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      setup_quectel ( diag ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      want_assistance  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    opcode ,  payload  =  diag . recv ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  opcode  !=  DIAG_LOG_F : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . error ( f " Unhandled opcode:  { opcode } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      continue 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ( pending_msgs ,  log_outer_length ) ,  inner_log_packet  =  unpack_from ( ' <BH ' ,  payload ) ,  payload [ calcsize ( ' <BH ' ) : ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  pending_msgs  >  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      cloudlog . debug ( " have  %d  pending messages "  %  pending_msgs ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    assert  log_outer_length  ==  len ( inner_log_packet ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ( log_inner_length ,  log_type ,  log_time ) ,  log_payload  =  unpack_from ( ' <HHQ ' ,  inner_log_packet ) ,  inner_log_packet [ calcsize ( ' <HHQ ' ) : ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    assert  log_inner_length  ==  len ( inner_log_packet ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  log_type  not  in  LOG_TYPES : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      continue 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  DEBUG : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      print ( " %.4f : got log:  %x  len  %d "  %  ( time . time ( ) ,  log_type ,  len ( log_payload ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  log_type  ==  LOG_GNSS_OEMDRE_MEASUREMENT_REPORT : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      msg  =  messaging . new_message ( ' qcomGnss ' ,  valid = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gnss  =  msg . qcomGnss 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gnss . logTs  =  log_time 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gnss . init ( ' drMeasurementReport ' ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      report  =  gnss . drMeasurementReport 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dat  =  unpack_oemdre_meas ( log_payload ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  k , v  in  dat . items ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  k  in  [ " gpsTimeBias " ,  " gpsClockTimeUncertainty " ] : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          k  + =  " Ms " 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  k  ==  " version " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          assert  v  ==  2 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  k  ==  " svCount "  or  k . startswith ( " cdmaClockInfo[ " ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          # TODO: should we save cdmaClockInfo? 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          pass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  k  ==  " systemRtcValid " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          setattr ( report ,  k ,  bool ( v ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          setattr ( report ,  k ,  v ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      report . init ( ' sv ' ,  dat [ ' svCount ' ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      sats  =  log_payload [ size_oemdre_meas : ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  i  in  range ( dat [ ' svCount ' ] ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sat  =  unpack_oemdre_meas_sv ( sats [ size_oemdre_meas_sv * i : size_oemdre_meas_sv * ( i + 1 ) ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sv  =  report . sv [ i ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sv . init ( ' measurementStatus ' ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  k , v  in  sat . items ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          if  k  in  [ " unkn " ,  " measurementStatus2 " ] : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            pass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          elif  k  ==  " multipathEstimateValid " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sv . measurementStatus . multipathEstimateIsValid  =  bool ( v ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          elif  k  ==  " directionValid " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sv . measurementStatus . directionIsValid  =  bool ( v ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          elif  k  ==  " goodParity " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            setattr ( sv ,  k ,  bool ( v ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          elif  k  ==  " measurementStatus " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  kk , vv  in  measurementStatusFields . items ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              setattr ( sv . measurementStatus ,  kk ,  bool ( v  &  ( 1 << vv ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            setattr ( sv ,  k ,  v ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      pm . send ( ' qcomGnss ' ,  msg ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    elif  log_type  ==  LOG_GNSS_POSITION_REPORT : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      report  =  unpack_position ( log_payload ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  report [ " u_PosSource " ]  !=  2 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        continue 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      vNED  =  [ report [ " q_FltVelEnuMps[1] " ] ,  report [ " q_FltVelEnuMps[0] " ] ,  - report [ " q_FltVelEnuMps[2] " ] ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      vNEDsigma  =  [ report [ " q_FltVelSigmaMps[1] " ] ,  report [ " q_FltVelSigmaMps[0] " ] ,  - report [ " q_FltVelSigmaMps[2] " ] ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      msg  =  messaging . new_message ( ' gpsLocation ' ,  valid = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps  =  msg . gpsLocation 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . latitude  =  report [ " t_DblFinalPosLatLon[0] " ]  *  180 / math . pi 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . longitude  =  report [ " t_DblFinalPosLatLon[1] " ]  *  180 / math . pi 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . altitude  =  report [ " q_FltFinalPosAlt " ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . speed  =  math . sqrt ( sum ( [ x * * 2  for  x  in  vNED ] ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . bearingDeg  =  report [ " q_FltHeadingRad " ]  *  180 / math . pi 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # TODO needs update if there is another leap second, after june 2024? 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      dt_timestamp  =  ( datetime . datetime ( 1980 ,  1 ,  6 ,  0 ,  0 ,  0 ,  0 ,  datetime . UTC )  + 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      datetime . timedelta ( weeks = report [ ' w_GpsWeekNumber ' ] )  + 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      datetime . timedelta ( seconds = ( 1e-3 * report [ ' q_GpsFixTimeMs ' ]  -  18 ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . unixTimestampMillis  =  dt_timestamp . timestamp ( ) * 1e3 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . source  =  log . GpsLocationData . SensorSource . qcomdiag 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . vNED  =  vNED 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . verticalAccuracy  =  report [ " q_FltVdop " ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . bearingAccuracyDeg  =  report [ " q_FltHeadingUncRad " ]  *  180 / math . pi  if  ( report [ " q_FltHeadingUncRad " ]  !=  0 )  else  180 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gps . speedAccuracy  =  math . sqrt ( sum ( [ x * * 2  for  x  in  vNEDsigma ] ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # quectel gps verticalAccuracy is clipped to 500, set invalid if so 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      gps . hasFix  =  gps . verticalAccuracy  !=  500 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  gps . hasFix : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        want_assistance  =  False 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        stop_download_event . set ( ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      pm . send ( ' gpsLocation ' ,  msg ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    elif  log_type  ==  LOG_GNSS_OEMDRE_SVPOLY_REPORT : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      msg  =  messaging . new_message ( ' qcomGnss ' ,  valid = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dat  =  unpack_svpoly ( log_payload ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      dat  =  relist ( dat ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gnss  =  msg . qcomGnss 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gnss . logTs  =  log_time 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gnss . init ( ' drSvPoly ' ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      poly  =  gnss . drSvPoly 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  k , v  in  dat . items ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  k  ==  " version " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          assert  v  ==  2 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  k  ==  " flags " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          pass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          setattr ( poly ,  k ,  v ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ''' 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # Timestamp glonass polys with GPSTime 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      from  laika . gps_time  import  GPSTime ,  utc_to_gpst ,  get_leap_seconds 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      from  laika . helpers  import  get_prn_from_nmea_id 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      prn  =  get_prn_from_nmea_id ( poly . svId ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  prn [ 0 ]  ==  ' R ' : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        epoch  =  GPSTime ( current_gps_time . week ,  ( poly . t0  -  3 * SECS_IN_HR  +  SECS_IN_DAY )  %  ( SECS_IN_WEEK )  +  get_leap_seconds ( current_gps_time ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        epoch  =  GPSTime ( current_gps_time . week ,  poly . t0 ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      # handle week rollover 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  epoch . tow  <  SECS_IN_DAY  and  current_gps_time . tow  >  6 * SECS_IN_DAY : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        epoch . week  + =  1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      elif  epoch . tow  >  6 * SECS_IN_DAY  and  current_gps_time . tow  <  SECS_IN_DAY : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        epoch . week  - =  1 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      poly . gpsWeek  =  epoch . week 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      poly . gpsTow  =  epoch . tow 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      ''' 
   
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      pm . send ( ' qcomGnss ' ,  msg ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    elif  log_type  in  [ LOG_GNSS_GPS_MEASUREMENT_REPORT ,  LOG_GNSS_GLONASS_MEASUREMENT_REPORT ] : 
  
						 
					
						
							
								
							 
							
								
									
										 
								
							 
							
								 
							
							
								      msg  =  messaging . new_message ( ' qcomGnss ' ,  valid = True ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gnss  =  msg . qcomGnss 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gnss . logTs  =  log_time 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      gnss . init ( ' measurementReport ' ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      report  =  gnss . measurementReport 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  log_type  ==  LOG_GNSS_GPS_MEASUREMENT_REPORT : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dat  =  unpack_gps_meas ( log_payload ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sats  =  log_payload [ size_gps_meas : ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        unpack_meas_sv ,  size_meas_sv  =  unpack_gps_meas_sv ,  size_gps_meas_sv 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        report . source  =  0   # gps 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        measurement_status_fields  =  ( measurementStatusFields . items ( ) ,  measurementStatusGPSFields . items ( ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      elif  log_type  ==  LOG_GNSS_GLONASS_MEASUREMENT_REPORT : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dat  =  unpack_glonass_meas ( log_payload ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        sats  =  log_payload [ size_glonass_meas : ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        unpack_meas_sv ,  size_meas_sv  =  unpack_glonass_meas_sv ,  size_glonass_meas_sv 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        report . source  =  1   # glonass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        measurement_status_fields  =  ( measurementStatusFields . items ( ) ,  measurementStatusGlonassFields . items ( ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  RuntimeError ( f " invalid log_type:  { log_type } " ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      for  k , v  in  dat . items ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  k  ==  " version " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          assert  v  ==  0 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  k  ==  " week " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          report . gpsWeek  =  v 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  k  ==  " svCount " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          pass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          setattr ( report ,  k ,  v ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      report . init ( ' sv ' ,  dat [ ' svCount ' ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      if  dat [ ' svCount ' ]  >  0 : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        assert  len ( sats ) / / dat [ ' svCount ' ]  ==  size_meas_sv 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  i  in  range ( dat [ ' svCount ' ] ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          sv  =  report . sv [ i ] 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          sv . init ( ' measurementStatus ' ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          sat  =  unpack_meas_sv ( sats [ size_meas_sv * i : size_meas_sv * ( i + 1 ) ] ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          for  k , v  in  sat . items ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  k  ==  " parityErrorCount " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              sv . gpsParityErrorCount  =  v 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  k  ==  " frequencyIndex " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              sv . glonassFrequencyIndex  =  v 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  k  ==  " hemmingErrorCount " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              sv . glonassHemmingErrorCount  =  v 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  k  ==  " measurementStatus " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              for  kk , vv  in  itertools . chain ( * measurement_status_fields ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                setattr ( sv . measurementStatus ,  kk ,  bool ( v  &  ( 1 << vv ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  k  ==  " miscStatus " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              for  kk , vv  in  miscStatusFields . items ( ) : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                setattr ( sv . measurementStatus ,  kk ,  bool ( v  &  ( 1 << vv ) ) ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  k  ==  " pad " : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              pass 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              setattr ( sv ,  k ,  v ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								      pm . send ( ' qcomGnss ' ,  msg ) 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								if  __name__  ==  " __main__ " : 
 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								  main ( )