Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions js/msp/MSPHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ var mspHelper = (function () {
FC.GPS_DATA.hdop = data.getUint16(14, true);
FC.GPS_DATA.eph = data.getUint16(16, true);
FC.GPS_DATA.epv = data.getUint16(18, true);
// Check if hwVersion field exists (firmware with extended MSP_GPSSTATISTICS)
if (data.byteLength >= 24) {
FC.GPS_DATA.hwVersion = data.getUint32(20, true);
} else {
FC.GPS_DATA.hwVersion = 0; // Unknown for older firmware
}
break;
case MSPCodes.MSP2_ADSB_VEHICLE_LIST:
var byteOffsetCounter = 0;
Expand Down
18 changes: 18 additions & 0 deletions locale/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,24 @@
"configurationGPSUseGlonass": {
"message": "Gps use Glonass Satellites (RU)"
},
"gpsPresetMode": {
"message": "GPS Configuration Preset"
},
"gpsPresetModeHelp": {
"message": "Choose a preset optimized for your GPS module, or use Manual for custom configuration. Auto-detect will identify your GPS module if connected."
},
"gpsUpdateRate": {
"message": "GPS Update Rate (Hz)"
},
"gpsUpdateRateHelp": {
"message": "How often the GPS module sends position updates. Higher rates provide lower latency but may reduce accuracy with multiple constellations on M10 modules."
},
"gpsAutoDetectFailed": {
"message": "Could not auto-detect GPS module. Please connect flight controller or select manual preset."
},
"gpsAutoDetectSuccess": {
"message": "GPS module detected:"
},
"tzOffset": {
"message": "Timezone Offset"
},
Expand Down
41 changes: 38 additions & 3 deletions tabs/gps.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,51 @@
<input type="number" id="mag_declination" name="mag_declination" step="0.1" min="-180" max="180" />
<label for="mag_declination"><span data-i18n="configurationMagDeclination"></span></label>
</div>
<!-- GPS Optimization Preset -->
<div class="select">
<select id="gps_preset_mode">
<option value="auto">Auto-detect GPS Type</option>
<option value="manual" selected>Manual Settings</option>
<option value="m8">u-blox M8</option>
<option value="m9-precision">u-blox M9 (Precision Mode)</option>
<option value="m9-sport">u-blox M9 (Sport Mode)</option>
<option value="m10">u-blox M10</option>
<option value="m10-highperf">u-blox M10 (High-Performance)</option>
</select>
<label for="gps_preset_mode">
<span data-i18n="gpsPresetMode">GPS Configuration Preset</span>
</label>
<div for="gps_preset_mode" class="helpicon cf_tip" data-i18n_title="gpsPresetModeHelp"></div>
</div>
<!-- Hardware detection status -->
<div id="gps_hardware_status" style="display: none; padding: 5px; margin: 5px 0; font-size: 12px; color: #28a745;">
<span style="margin-right: 5px;">✓</span>
<span id="gps_hardware_name"></span>
<a href="#" id="gps_apply_optimal" style="margin-left: 10px; color: #007bff; text-decoration: none;">[Use optimal settings]</a>
</div>
<!-- GPS Preset Info (shown when preset selected) -->
<div class="preset-info" id="preset_info" style="display: none; padding: 5px; margin: 5px 0; background: #f0f0f0; border-radius: 3px;">
<strong><span id="preset_name"></span></strong>
<ul id="preset_details" style="margin: 5px 0; padding-left: 20px;"></ul>
</div>
<!-- GPS Update Rate -->
<div class="number">
<input type="number" id="gps_ublox_nav_hz" data-setting="gps_ublox_nav_hz" step="1" min="5" max="20" />
<label for="gps_ublox_nav_hz">
<span data-i18n="gpsUpdateRate">GPS Update Rate (Hz)</span>
</label>
<div for="gps_ublox_nav_hz" class="helpicon cf_tip" data-i18n_title="gpsUpdateRateHelp"></div>
</div>
<div class="checkbox">
<input type="checkbox" class="toggle update_preview" data-setting="gps_ublox_use_galileo" data-live="true">
<input type="checkbox" id="gps_use_galileo" class="toggle update_preview preset-controlled" data-setting="gps_ublox_use_galileo">
<label for="gps_use_galileo"><span data-i18n="configurationGPSUseGalileo"></span></label>
</div>
<div class="checkbox">
<input type="checkbox" class="toggle update_preview" data-setting="gps_ublox_use_beidou" data-live="true">
<input type="checkbox" id="gps_use_beidou" class="toggle update_preview preset-controlled" data-setting="gps_ublox_use_beidou">
<label for="gps_use_beidou"><span data-i18n="configurationGPSUseBeidou"></span></label>
</div>
<div class="checkbox">
<input type="checkbox" class="toggle update_preview" data-setting="gps_ublox_use_glonass" data-live="true">
<input type="checkbox" id="gps_use_glonass" class="toggle update_preview preset-controlled" data-setting="gps_ublox_use_glonass">
<label for="gps_use_glonass"><span data-i18n="configurationGPSUseGlonass"></span></label>
</div>
<div class="number">
Expand Down
181 changes: 176 additions & 5 deletions tabs/gps.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,13 @@ TABS.gps.initialize = function (callback) {
let vehiclesCursorInitialized = false;
let arrowIcon;

function process_html() {
async function process_html(settingsPromise) {
// Wait for settings to finish loading to avoid race conditions
// where user changes are overwritten by background setting loads
if (settingsPromise) {
await settingsPromise;
}

i18n.localize();

var fcFeatures = FC.getFeatures();
Expand Down Expand Up @@ -200,6 +206,163 @@ TABS.gps.initialize = function (callback) {

gps_ubx_sbas_e.val(FC.MISC.gps_ubx_sbas);

// GPS Preset Configuration
const GPS_PRESETS = {
m8: {
name: "u-blox M8",
galileo: true,
glonass: true,
beidou: true,
rate: 8,
description: [
"4 GNSS constellations for maximum accuracy",
"8Hz update rate (conservative for M8)",
"Best for: Navigation, position hold, slower aircraft"
]
},
'm9-precision': {
name: "u-blox M9 (Precision Mode)",
galileo: true,
glonass: false,
beidou: true,
rate: 5,
description: [
"3 GNSS constellations (GPS+Galileo+Beidou) → 32 satellites",
"5Hz update rate, HDOP ~1.0-1.3",
"Best for: Long-range cruise, position hold, navigation missions"
]
},
'm9-sport': {
name: "u-blox M9 (Sport Mode)",
galileo: true,
glonass: false,
beidou: true,
rate: 10,
description: [
"3 GNSS constellations (GPS+Galileo+Beidou) → 16 satellites",
"10Hz update rate (hardware limit), HDOP ~2.0-2.5",
"Best for: Fast flying, racing, acrobatics, quick response"
]
},
m10: {
name: "u-blox M10",
galileo: true,
glonass: false,
beidou: true,
rate: 8,
description: [
"3 GNSS constellations (GPS+Galileo+Beidou)",
"8Hz update rate (safe for M10 default CPU clock)",
"Best for: General use, balanced performance"
]
},
'm10-highperf': {
name: "u-blox M10 (High-Performance)",
galileo: true,
glonass: true,
beidou: true,
rate: 10,
description: [
"4 GNSS constellations for maximum satellites",
"10Hz update rate (requires high-performance CPU clock)",
"Only use if you KNOW your M10 has high-performance clock enabled"
]
},
manual: {
name: "Manual Settings",
description: [
"Full control over constellation selection and update rate",
"For advanced users and special requirements"
]
}
};

function detectGPSPreset(hwVersion) {
switch(hwVersion) {
case 800: return 'm8';
case 900: return 'm9-precision'; // Default to precision mode for better accuracy
case 1000: return 'm10';
default: return 'manual';
}
}

function applyGPSPreset(presetId) {
// Handle special cases first (before checking GPS_PRESETS)
if (presetId === 'manual') {
// Enable all controls
$('.preset-controlled').prop('disabled', false);
$('#gps_ublox_nav_hz').prop('disabled', false);
$('#preset_info').hide();
return;
}

if (presetId === 'auto') {
// Try to auto-detect from FC
if (FC.GPS_DATA && FC.GPS_DATA.hwVersion) {
const detectedPreset = detectGPSPreset(FC.GPS_DATA.hwVersion);
applyGPSPreset(detectedPreset);
$('#gps_preset_mode').val(detectedPreset);
GUI.log(i18n.getMessage('gpsAutoDetectSuccess') + ' ' + GPS_PRESETS[detectedPreset].name);
} else {
// Fall back to manual if can't detect
applyGPSPreset('manual');
$('#gps_preset_mode').val('manual');
GUI.log(i18n.getMessage('gpsAutoDetectFailed'));
}
return;
}

// Normal preset application
const preset = GPS_PRESETS[presetId];
if (!preset) return;

// Apply preset values (user can still adjust after applying)
$('#gps_use_galileo').prop('checked', preset.galileo);
$('#gps_use_glonass').prop('checked', preset.glonass);
$('#gps_use_beidou').prop('checked', preset.beidou);
$('#gps_ublox_nav_hz').val(preset.rate);

// Show preset info
$('#preset_name').text(preset.name);
$('#preset_details').html(preset.description.map(d => `<li>${d}</li>`).join(''));
$('#preset_info').show();
}

// Set up preset mode handler (namespaced to prevent memory leaks)
$('#gps_preset_mode').on('change.gpsTab', function() {
applyGPSPreset($(this).val());
});

// Hardware detection status indicator
function updateHardwareStatus() {
if (FC.GPS_DATA && FC.GPS_DATA.hwVersion && FC.GPS_DATA.hwVersion > 0) {
const detectedPreset = detectGPSPreset(FC.GPS_DATA.hwVersion);
if (detectedPreset && detectedPreset !== 'manual' && GPS_PRESETS[detectedPreset]) {
$('#gps_hardware_name').text(GPS_PRESETS[detectedPreset].name + ' detected');
$('#gps_hardware_status').show();
}
}
}

// Handler for "Use optimal settings" link (namespaced)
$('#gps_apply_optimal').on('click.gpsTab', function(e) {
e.preventDefault();
if (FC.GPS_DATA && FC.GPS_DATA.hwVersion) {
const detectedPreset = detectGPSPreset(FC.GPS_DATA.hwVersion);
if (detectedPreset && detectedPreset !== 'manual') {
$('#gps_preset_mode').val(detectedPreset).trigger('change');
GUI.log('Applied recommended settings for ' + GPS_PRESETS[detectedPreset].name);
}
}
});

// Initialize - default to manual mode to preserve user's existing settings
// User can explicitly select a preset or use "Auto-detect" if desired
applyGPSPreset('manual');

// Check for hardware detection after a short delay to allow GPS data to arrive
setTimeout(updateHardwareStatus, 500);

let mapView = new View({
center: [0, 0],
zoom: 15
Expand Down Expand Up @@ -240,7 +403,7 @@ TABS.gps.initialize = function (callback) {
}));
}

$("#center_button").on('click', function () {
$("#center_button").on('click.gpsTab', function () {
let lat = FC.GPS_DATA.lat / 10000000;
let lon = FC.GPS_DATA.lon / 10000000;
let center = fromLonLat([lon, lat]);
Expand Down Expand Up @@ -466,7 +629,7 @@ TABS.gps.initialize = function (callback) {
});
}

$('a.save').on('click', function () {
$('a.save').on('click.gpsTab', function () {
serialPortHelper.set($port.val(), 'GPS', $baud.val());
features.reset();
features.fromUI($('.tab-gps'));
Expand Down Expand Up @@ -517,15 +680,15 @@ TABS.gps.initialize = function (callback) {
}
}

$('a.loadAssistnowOnline').on('click', function () {
$('a.loadAssistnowOnline').on('click.gpsTab', function () {
if(globalSettings.assistnowApiKey != null && globalSettings.assistnowApiKey != '') {
ublox.loadAssistnowOnline(processUbloxData);
} else {
dialog.alert("Assistnow Token not set!");
}
});

$('a.loadAssistnowOffline').on('click', function () {
$('a.loadAssistnowOffline').on('click.gpsTab', function () {
if(globalSettings.assistnowApiKey != null && globalSettings.assistnowApiKey != '') {
ublox.loadAssistnowOffline(processUbloxData);
} else {
Expand All @@ -539,6 +702,14 @@ TABS.gps.initialize = function (callback) {
};

TABS.gps.cleanup = function (callback) {
// Remove all namespaced event handlers to prevent memory leaks
$('#gps_preset_mode').off('.gpsTab');
$('#gps_apply_optimal').off('.gpsTab');
$('#center_button').off('.gpsTab');
$('a.save').off('.gpsTab');
$('a.loadAssistnowOnline').off('.gpsTab');
$('a.loadAssistnowOffline').off('.gpsTab');

if (callback) callback();
if (TABS.gps.toolboxAdsbVehicle){
TABS.gps.toolboxAdsbVehicle.close();
Expand Down
Loading