12 KiB
Backup, Restore & Settings Migration — Architecture
Note: This document describes the internals of the INAV Configurator's backup/restore and settings migration system. It is intended for Configurator developers, not end users. For user-facing documentation, see the INAV docs.
Architecture Overview
User → Firmware Flasher Tab → STM32.connect(onCliReady) → CLI mode
↓
BackupRestore.captureCliDiffAll()
↓
Save to file, prune old backups
↓
STM32 flash (DFU or serial)
↓
onFlashComplete() callback
↓
Version check → Migration check → UI overlay
↓
User confirms → Poll for FC reconnect
↓
BackupRestore.performRestore() or performRestoreWithMigration()
↓
saveAndReboot() or abortRestore()
Files
| File | Purpose |
|---|---|
js/backup_restore.js |
Core backup/restore module — CLI protocol, file I/O, auto-backup |
js/migration/migration_handler.js |
Version migration engine — profile chaining, line transformation |
js/migration/7_to_8.json |
Migration profile: INAV 7.x → 8.0 |
js/migration/8_to_9.json |
Migration profile: INAV 8.0 → 9.0 |
tabs/firmware_flasher.js |
Flash integration — auto-backup trigger, restore UI, version gating |
tabs/firmware_flasher.html |
Overlays and buttons for backup/restore/migration UI |
src/css/tabs/firmware_flasher.css |
Overlay styles |
js/protocols/stm32.js |
STM32 flash protocol — onCliReady callback, DFU timeout fix |
js/main/main.js |
Electron main process — IPC handlers for file operations |
js/main/preload.js |
IPC bridge — exposes backup API to renderer |
locale/en/messages.json |
All i18n translation keys |
Adding a New Migration Profile
When a new major INAV version is released (e.g. 9.x → 10.x), create a migration profile:
Step 1: Create the JSON profile
Create js/migration/9_to_10.json:
{
"fromVersion": "9",
"toVersion": "10",
"description": "INAV 9.x → 10.0 migration profile",
"commandRenames": {
"old_command_name": "new_command_name"
},
"settingRenames": {
"old_setting_name": "new_setting_name"
},
"valueReplacements": {
"setting_name": {
"OLD_VALUE": "NEW_VALUE"
}
},
"removed": [
"deleted_setting_1",
"deleted_setting_2"
],
"settingPatternMappings": [
{
"pattern": "^regex_matching_setting_names$",
"valueMap": { "old_numeric_id": "new_numeric_id" },
"description": "Human-readable description of remapping"
}
],
"warnings": [
"Human-readable warning about settings whose semantics changed and need manual review."
]
}
Step 2: Register the profile
In js/migration/migration_handler.js, add the import and append to the array:
import profile_9_to_10 from './9_to_10.json';
const MIGRATION_PROFILES = [
profile_7_to_8,
profile_8_to_9,
profile_9_to_10, // ← add here
];
The migration engine automatically chains profiles. A 7.x → 10.x upgrade will apply all three profiles in sequence (7→8, 8→9, 9→10).
How to determine what goes into a migration profile
Compare CLI settings between the old and new firmware version:
- Removed settings: Run
diff allon old and new firmware with default settings. Settings present in old but not in new → add toremoved - Renamed settings: Check INAV release notes and source code for renamed settings → add to
settingRenames - Renamed commands: Check for CLI command name changes (e.g.
profile→control_profile) → add tocommandRenames - Value replacements: Check for enum value name changes → add to
valueReplacements - Pattern mappings: Check for bulk ID renumbering (OSD elements, etc.) → add to
settingPatternMappings - Warnings: Check for settings where the meaning/units changed but name stayed the same → add to
warnings
Key INAV source files to check:
src/main/fc/settings.yaml— all CLI settings definitionssrc/main/fc/cli.c— CLI command implementations- Release notes on GitHub
Migration Profile Schema Reference
| Field | Type | Required | Description |
|---|---|---|---|
fromVersion |
string |
Yes | Source major version number (e.g. "9") |
toVersion |
string |
Yes | Target major version number (e.g. "10") |
description |
string |
Yes | Human-readable description |
commandRenames |
object |
Yes | Maps old CLI command names to new names. Applied to any token in the command line. E.g. "profile" → "control_profile" transforms profile 2 to control_profile 2 |
settingRenames |
object |
Yes | Maps old set setting names to new names. Only applies to set <name> = <value> lines |
valueReplacements |
object |
Yes | Maps setting names to value replacement objects { "oldval": "newval" }. Only modifies the value portion after = |
removed |
string[] |
Yes | List of setting names to remove entirely. Lines with set <name> = ... matching these are dropped |
settingPatternMappings |
array |
Yes | Array of pattern-based value remappings for settings matching a regex. Each entry has pattern (regex), valueMap (object), description (string) |
warnings |
string[] |
Yes | Warning messages about semantic changes requiring manual review. Displayed in migration preview overlay |
Existing Migration Profile Details
7_to_8.json (INAV 7.x → 8.0)
| Category | Changes |
|---|---|
| Command renames | profile → control_profile |
| Value replacements | gps_provider: UBLOX7 → UBLOX |
| Removed settings (18) | control_deadband, cpu_underclock, disarm_kill_switch, dji_workarounds, fw_iterm_limit_stick_position, gyro_anti_aliasing_lpf_type, gyro_hardware_lpf, gyro_main_lpf_type, gyro_use_dyn_lpf, inav_use_gps_no_baro, inav_use_gps_velned, ledstrip_visual_beeper, max_throttle, nav_auto_climb_rate, nav_manual_climb_rate, osd_stats_min_voltage_unit, pidsum_limit, pidsum_limit_yaw |
| Pattern mappings | osd_custom_element_N_type: IDs remapped 4→9, 5→16, 6→7, 7→10 |
| Warnings | nav_fw_wp_tracking_accuracy semantics changed: was arbitrary tracking response, now distance in meters |
8_to_9.json (INAV 8.0 → 9.0)
| Category | Changes |
|---|---|
| Command renames | controlrate_profile → use_control_profile |
| Setting renames | mixer_pid_profile_linking → mixer_control_profile_linking, osd_pan_servo_pwm2centideg → osd_pan_servo_range_decadegrees |
| Value replacements | None |
| Removed settings | None |
| Pattern mappings | None |
| Warnings | Position estimator defaults changed (w_z_baro_v, inav_w_z_gps_p, inav_w_z_gps_v). ahrs_acc_ignore_rate default changed 20→15 |
Migration Engine Internals
Profile chaining
buildMigrationChain(fromVersion, toVersion) selects all profiles where profileFrom >= fromMajor and profileTo <= toMajor, sorted by fromVersion. A 7.x → 9.x migration applies both 7→8 and 8→9 profiles in sequence.
Line processing
Each non-comment, non-empty line passes through every profile in the chain. For each profile, transformations are applied in this order:
- Command renames (any token in the line)
- Removed settings (line dropped if
set <name>matches) - Setting renames (
set <name>replacement) - Value replacements (value after
=replaced) - Setting pattern mappings (regex-matched settings with value remapping)
Missing profile detection
hasMissingProfiles() returns true when the number of profiles in the chain is fewer than the number of major version steps. The UI shows a warning but still allows restore — some settings may fail.
Edge Cases Handled
- Stale FC version after flash: Real FC version is queried via
MSP_FC_VERSIONafter connect, not the cached value - DFU mode (no MSP):
FC.CONFIGnull checks prevent crashes when connected in DFU mode - DFU timeout: UI unlock and progress label update on timeout (no permanent lock)
- Local firmware files:
localFirmwareLoadedflag prevents stale dropdown version from triggering wrong migration - Backup pruning with mixed versions: Sort by timestamp portion, not full filename
- Multi-step migration: 7.x → 9.x automatically chains 7→8 + 8→9 profiles
- Missing migration profiles: Warning shown but restore allowed — graceful degradation
- Version detection from backup: Parsed from backup header (
# Version: X.Y.Z), not from FC state
i18n Keys
All backup/restore/migration translation keys in locale/en/messages.json:
Backup status
| Key | Text |
|---|---|
backupRestoreStatusEnteringCli |
Entering CLI |
backupRestoreStatusReadingConfig |
Reading configuration via CLI |
backupRestoreStatusSavingFile |
Saving backup file... |
backupRestoreStatusExitingCli |
Exiting CLI mode |
backupRestoreBackupSaved |
Backup saved $1 |
backupRestoreAutoBackupSaved |
Auto-backup saved to $1 |
backupRestoreBackupComplete |
Backup complete |
backupRestoreBackupCancelled |
Backup cancelled |
backupRestoreBackupFailed |
Backup failed |
Restore status
| Key | Text |
|---|---|
backupRestoreStatusConnecting |
Connecting to flight controller |
backupRestoreStatusRestoringConfig |
Restoring configuration |
backupRestoreStatusRestoringProgress |
Restoring... $1 / $2 |
backupRestoreStatusSaving |
Saving configuration |
backupRestoreRestoreComplete |
Configuration restored. Flight controller is rebooting. |
backupRestoreRestoreCancelled |
Restore cancelled. |
backupRestoreRestoreFailed |
Restore failed. |
Auto-restore UI
| Key | Text |
|---|---|
backupRestoreAutoRestoreConfirm |
Restore confirmation prompt |
backupRestoreAutoRestoreWaiting |
Waiting for FC to reboot after flash |
backupRestoreAutoRestoreYes |
Yes, restore settings |
backupRestoreAutoRestoreNo |
No, keep current settings |
backupRestoreAutoRestoreWaitingPort |
Waiting for port $1 to reconnect |
backupRestoreDowngradeNoAutoRestore |
Major downgrade warning |
backupRestoreFlashCompleteBackupSaved |
Backup saved (local firmware, no restore offer) |
backupRestoreMigrationApplied |
Migration applied: $1 → $2 ($3 changes) |
backupRestoreMigrationWarningsHeader |
Migration Warnings: |
Migration preview
| Key | Text |
|---|---|
migrationPreviewTitle |
Settings Migration Required |
migrationPreviewSubtitle |
Conversion explanation |
migrationPreviewRemovedHeader |
Removed Settings: |
migrationPreviewRenamedSettingsHeader |
Renamed Settings: |
migrationPreviewRenamedCommandsHeader |
Renamed Commands: |
migrationPreviewValueReplacementsHeader |
Value Replacements: |
migrationPreviewSettingRemappingsHeader |
Setting Remappings: |
migrationPreviewContinue |
Continue with migration |
migrationPreviewCancel |
Cancel restore |
migrationMissingProfileWarning |
Missing profile warning |
Error messages
| Key | Text |
|---|---|
backupRestoreErrorTitle |
Restore Errors Detected |
backupRestoreErrorText |
Error explanation |
backupRestoreErrorAbort |
Abort |
backupRestoreErrorSave |
Save anyway |