diff --git a/core/ContextBase.cpp b/core/ContextBase.cpp index 22ac849c..74345909 100644 --- a/core/ContextBase.cpp +++ b/core/ContextBase.cpp @@ -70,7 +70,8 @@ const loc_param_s_type ContextBase::mGps_conf_table[] = {"XTRA_SERVER_1", &mGps_conf.XTRA_SERVER_1, NULL, 's'}, {"XTRA_SERVER_2", &mGps_conf.XTRA_SERVER_2, NULL, 's'}, {"XTRA_SERVER_3", &mGps_conf.XTRA_SERVER_3, NULL, 's'}, - {"USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL", &mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL, NULL, 'n'}, + {"USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL", + &mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL, NULL, 'n'}, {"AGPS_CONFIG_INJECT", &mGps_conf.AGPS_CONFIG_INJECT, NULL, 'n'}, {"EXTERNAL_DR_ENABLED", &mGps_conf.EXTERNAL_DR_ENABLED, NULL, 'n'}, {"SUPL_HOST", &mGps_conf.SUPL_HOST, NULL, 's'}, @@ -78,13 +79,19 @@ const loc_param_s_type ContextBase::mGps_conf_table[] = {"MODEM_TYPE", &mGps_conf.MODEM_TYPE, NULL, 'n' }, {"MO_SUPL_HOST", &mGps_conf.MO_SUPL_HOST, NULL, 's' }, {"MO_SUPL_PORT", &mGps_conf.MO_SUPL_PORT, NULL, 'n' }, - {"CONSTRAINED_TIME_UNCERTAINTY_ENABLED", &mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED, NULL, 'n'}, - {"CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD", &mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD, NULL, 'f'}, - {"CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET", &mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET, NULL, 'n'}, - {"POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED", &mGps_conf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED, NULL, 'n'}, + {"CONSTRAINED_TIME_UNCERTAINTY_ENABLED", + &mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENABLED, NULL, 'n'}, + {"CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD", + &mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_THRESHOLD, NULL, 'f'}, + {"CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET", + &mGps_conf.CONSTRAINED_TIME_UNCERTAINTY_ENERGY_BUDGET, NULL, 'n'}, + {"POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED", + &mGps_conf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED, NULL, 'n'}, {"PROXY_APP_PACKAGE_NAME", &mGps_conf.PROXY_APP_PACKAGE_NAME, NULL, 's' }, {"CP_MTLR_ES", &mGps_conf.CP_MTLR_ES, NULL, 'n' }, {"GNSS_DEPLOYMENT", &mGps_conf.GNSS_DEPLOYMENT, NULL, 'n'}, + {"CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED", + &mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED, NULL, 'n'}, }; const loc_param_s_type ContextBase::mSap_conf_table[] = @@ -183,6 +190,7 @@ void ContextBase::readConfig() mGps_conf.POSITION_ASSISTED_CLOCK_ESTIMATOR_ENABLED = 0; /* default configuration QTI GNSS H/W */ mGps_conf.GNSS_DEPLOYMENT = 0; + mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED = 0; UTIL_READ_CONF(LOC_PATH_GPS_CONF, mGps_conf_table); UTIL_READ_CONF(LOC_PATH_SAP_CONF, mSap_conf_table); diff --git a/core/ContextBase.h b/core/ContextBase.h index 5da76e26..6701600e 100644 --- a/core/ContextBase.h +++ b/core/ContextBase.h @@ -74,6 +74,7 @@ typedef struct loc_gps_cfg_s char PROXY_APP_PACKAGE_NAME[LOC_MAX_PARAM_STRING]; uint32_t CP_MTLR_ES; uint32_t GNSS_DEPLOYMENT; + uint32_t CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED; } loc_gps_cfg_s_type; /* NOTE: the implementaiton of the parser casts number diff --git a/etc/gps.conf b/etc/gps.conf index 63547653..47aa8efb 100644 --- a/etc/gps.conf +++ b/etc/gps.conf @@ -99,6 +99,31 @@ DATUM_TYPE = 0 ################################ # NMEA provider (1=Modem Processor, 0=Application Processor) NMEA_PROVIDER=0 + +# Customized NMEA GGA fix quality that can be used to tell +# whether SENSOR contributed to the fix. +# +# When this configuration item is not enabled (set to any value that is not 1), +# GGA fix quality conforms to NMEA standard spec as below: +# PPP/DGNSS/SBAS correction fix w/ or w/o sensor: 2 +# RTK fixed fix w/ or w/o sensor: 4 +# RTK float fix w/ or w/o sensor: 5 +# SPE fix w/ or w/o sensor: 1 +# Sensor dead reckoning fix: 6 +# +# When this configuration is enabled (set to 1), GGA fix quality +# will be output as below: +# PPP fix w/o sensor: 59, w/ sensor: 69 +# DGNSS/SBAS correction fix w/o sensor: 2, w/ sensor: 62 +# RTK fixed fix w/o sensor: 4, w/ sensor: 64 +# RTK float fix w/o sensor: 5, w/ sensor: 65, +# SPE fix w/o sensor: 1, and w/ sensor: 61 +# Sensor dead reckoning fix: 6 +# +# any value that is not 1 - disabled +# 1 - enabled +CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED = 0 + # Mark if it is a SGLTE target (1=SGLTE, 0=nonSGLTE) SGLTE_TARGET=0 diff --git a/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp index 43fb63bf..980d4895 100644 --- a/gnss/GnssAdapter.cpp +++ b/gnss/GnssAdapter.cpp @@ -3272,9 +3272,10 @@ GnssAdapter::reportPosition(const UlpLocation& ulpLocation, (0 == ulpLocation.gpsLocation.longitude) && (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability)); uint8_t generate_nmea = (reportToGnssClient && status != LOC_SESS_FAILURE && !blank_fix); + bool custom_nmea_gga = (1 == ContextBase::mGps_conf.CUSTOM_NMEA_GGA_FIX_QUALITY_ENABLED); std::vector nmeaArraystr; loc_nmea_generate_pos(ulpLocation, locationExtended, mLocSystemInfo, - generate_nmea, nmeaArraystr); + generate_nmea, custom_nmea_gga, nmeaArraystr); stringstream ss; for (auto itor = nmeaArraystr.begin(); itor != nmeaArraystr.end(); ++itor) { ss << *itor; diff --git a/utils/loc_nmea.cpp b/utils/loc_nmea.cpp index d5e4b57a..24197ff0 100644 --- a/utils/loc_nmea.cpp +++ b/utils/loc_nmea.cpp @@ -1033,47 +1033,56 @@ SIDE EFFECTS ===========================================================================*/ static void loc_nmea_get_fix_quality(const UlpLocation & location, const GpsLocationExtended & locationExtended, - char & ggaGpsQuality, + bool custom_gga_fix_quality, + char ggaGpsQuality[3], char & rmcModeIndicator, char & vtgModeIndicator) { - ggaGpsQuality = '0'; - rmcModeIndicator = 'N'; - vtgModeIndicator = 'N'; + ggaGpsQuality[0] = '0'; // 0 means no fix + rmcModeIndicator = 'N'; // N means no fix + vtgModeIndicator = 'N'; // N means no fix do { + // GGA fix quality is defined in NMEA spec as below: + // https://www.trimble.com/OEM_ReceiverHelp/V4.44/en/NMEA-0183messages_GGA.html + // Fix quality: 0 = invalid + // 1 = GPS fix (SPS) + // 2 = DGPS fix + // 3 = PPS fix + // 4 = Real Time Kinematic + // 5 = Float RTK + // 6 = estimated (dead reckoning) (2.3 feature) + // 7 = Manual input mode + // 8 = Simulation mode if (!(location.gpsLocation.flags & LOC_GPS_LOCATION_HAS_LAT_LONG)){ - ggaGpsQuality = '0'; // 0 means no fix - rmcModeIndicator = 'N'; - vtgModeIndicator = 'N'; break; } // NOTE: Order of the check is important if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK) { if (LOC_NAV_MASK_PPP_CORRECTION & locationExtended.navSolutionMask) { - ggaGpsQuality = '2'; // 2 means DGPS fix + ggaGpsQuality[0] = '2'; // 2 means DGPS fix rmcModeIndicator = 'P'; // P means precise vtgModeIndicator = 'P'; // P means precise break; } else if (LOC_NAV_MASK_RTK_FIXED_CORRECTION & locationExtended.navSolutionMask){ - ggaGpsQuality = '4'; // 4 means RTK Fixed fix + ggaGpsQuality[0] = '4'; // 4 means RTK Fixed fix rmcModeIndicator = 'R'; // use R (RTK fixed) vtgModeIndicator = 'D'; // use D (differential) as // no RTK fixed defined for VTG in NMEA 183 spec break; } else if (LOC_NAV_MASK_RTK_CORRECTION & locationExtended.navSolutionMask){ - ggaGpsQuality = '5'; // 5 means RTK float fix + ggaGpsQuality[0] = '5'; // 5 means RTK float fix rmcModeIndicator = 'F'; // F means RTK float fix vtgModeIndicator = 'D'; // use D (differential) as // no RTK float defined for VTG in NMEA 183 spec break; } else if (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask){ - ggaGpsQuality = '2'; // 2 means DGPS fix + ggaGpsQuality[0] = '2'; // 2 means DGPS fix rmcModeIndicator = 'D'; // D means differential vtgModeIndicator = 'D'; // D means differential break; } else if (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask){ - ggaGpsQuality = '2'; // 2 means DGPS fix + ggaGpsQuality[0] = '2'; // 2 means DGPS fix rmcModeIndicator = 'D'; // D means differential vtgModeIndicator = 'D'; // D means differential break; @@ -1082,12 +1091,12 @@ static void loc_nmea_get_fix_quality(const UlpLocation & location, // NOTE: Order of the check is important if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK) { if (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask){ - ggaGpsQuality = '1'; // 1 means GPS + ggaGpsQuality[0] = '1'; // 1 means GPS rmcModeIndicator = 'A'; // A means autonomous vtgModeIndicator = 'A'; // A means autonomous break; } else if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask){ - ggaGpsQuality = '6'; // 6 means estimated (dead reckoning) + ggaGpsQuality[0] = '6'; // 6 means estimated (dead reckoning) rmcModeIndicator = 'E'; // E means estimated (dead reckoning) vtgModeIndicator = 'E'; // E means estimated (dead reckoning) break; @@ -1095,7 +1104,54 @@ static void loc_nmea_get_fix_quality(const UlpLocation & location, } } while (0); - LOC_LOGv("gps quality: %c, rmc mode indicator: %c, vtg mode indicator: %c", + do { + // check for customized nmea enabled or not + // with customized GGA quality enabled + // PPP fix w/o sensor: 59, PPP fix w/ sensor: 69 + // DGNSS/SBAS correction fix w/o sensor: 2, w/ sensor: 62 + // RTK fixed fix w/o sensor: 4, w/ sensor: 64 + // RTK float fix w/o sensor: 5, w/ sensor: 65 + // SPE fix w/o sensor: 1, and w/ sensor: 61 + // Sensor dead reckoning fix: 6 + if (true == custom_gga_fix_quality) { + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_NAV_SOLUTION_MASK) { + // PPP fix w/o sensor: fix quality will now be 59 + // PPP fix w sensor: fix quality will now be 69 + if (LOC_NAV_MASK_PPP_CORRECTION & locationExtended.navSolutionMask) { + if ((locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK) && + (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask)) { + ggaGpsQuality[0] = '6'; + ggaGpsQuality[1] = '9'; + } else { + ggaGpsQuality[0] = '5'; + ggaGpsQuality[1] = '9'; + } + break; + } + } + + if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_POS_TECH_MASK) { + if (LOC_POS_TECH_MASK_SENSORS & locationExtended.tech_mask){ + char ggaQuality_copy = ggaGpsQuality[0]; + ggaGpsQuality[0] = '6'; // 6 sensor assisted + // RTK fixed fix w/ sensor: fix quality will now be 64 + // RTK float fix w/ sensor: 65 + // DGNSS and/or SBAS correction fix and w/ sensor: 62 + // GPS fix without correction and w/ sensor: 61 + if ((LOC_NAV_MASK_RTK_FIXED_CORRECTION & locationExtended.navSolutionMask)|| + (LOC_NAV_MASK_RTK_CORRECTION & locationExtended.navSolutionMask)|| + (LOC_NAV_MASK_DGNSS_CORRECTION & locationExtended.navSolutionMask)|| + (LOC_NAV_MASK_SBAS_CORRECTION_IONO & locationExtended.navSolutionMask)|| + (LOC_POS_TECH_MASK_SATELLITE & locationExtended.tech_mask)) { + ggaGpsQuality[1] = ggaQuality_copy; + break; + } + } + } + } + } while (0); + + LOC_LOGv("gps quality: %s, rmc mode indicator: %c, vtg mode indicator: %c", ggaGpsQuality, rmcModeIndicator, vtgModeIndicator); } @@ -1127,6 +1183,7 @@ void loc_nmea_generate_pos(const UlpLocation &location, const GpsLocationExtended &locationExtended, const LocationSystemInfo &systemInfo, unsigned char generate_nmea, + bool custom_gga_fix_quality, std::vector &nmeaArraystr) { ENTRY_LOG(); @@ -1270,10 +1327,10 @@ void loc_nmea_generate_pos(const UlpLocation &location, talker[1] = sv_meta.talker[1]; } - char ggaGpsQuality = '0'; + char ggaGpsQuality[3] = {'0', '\0', '\0'}; char rmcModeIndicator = 'N'; char vtgModeIndicator = 'N'; - loc_nmea_get_fix_quality(location, locationExtended, + loc_nmea_get_fix_quality(location, locationExtended, custom_gga_fix_quality, ggaGpsQuality, rmcModeIndicator, vtgModeIndicator); // ------------------- @@ -1772,12 +1829,12 @@ void loc_nmea_generate_pos(const UlpLocation &location, svUsedCount = MAX_SATELLITES_IN_USE; if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_DOP) { - length = snprintf(pMarker, lengthRemaining, "%c,%02d,%.1f,", + length = snprintf(pMarker, lengthRemaining, "%s,%02d,%.1f,", ggaGpsQuality, svUsedCount, locationExtended.hdop); } else { // no hdop - length = snprintf(pMarker, lengthRemaining, "%c,%02d,,", + length = snprintf(pMarker, lengthRemaining, "%s,%02d,,", ggaGpsQuality, svUsedCount); } diff --git a/utils/loc_nmea.h b/utils/loc_nmea.h index c6c83db4..a9cafb76 100644 --- a/utils/loc_nmea.h +++ b/utils/loc_nmea.h @@ -79,6 +79,7 @@ void loc_nmea_generate_pos(const UlpLocation &location, const GpsLocationExtended &locationExtended, const LocationSystemInfo &systemInfo, unsigned char generate_nmea, + bool custom_gga_fix_quality, std::vector &nmeaArraystr); #define DEBUG_NMEA_MINSIZE 6