ardupilot-methodic-configurator 2.6.1__py3-none-any.whl → 2.7.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ardupilot-methodic-configurator might be problematic. Click here for more details.

Files changed (107) hide show
  1. ardupilot_methodic_configurator/__init__.py +2 -2
  2. ardupilot_methodic_configurator/__main__.py +34 -1
  3. ardupilot_methodic_configurator/annotate_params.py +49 -14
  4. ardupilot_methodic_configurator/argparse_check_range.py +1 -1
  5. ardupilot_methodic_configurator/backend_filesystem.py +7 -3
  6. ardupilot_methodic_configurator/backend_filesystem_configuration_steps.py +53 -6
  7. ardupilot_methodic_configurator/backend_filesystem_freedesktop.py +275 -0
  8. ardupilot_methodic_configurator/backend_filesystem_json_with_schema.py +3 -3
  9. ardupilot_methodic_configurator/backend_filesystem_program_settings.py +26 -8
  10. ardupilot_methodic_configurator/backend_filesystem_vehicle_components.py +3 -3
  11. ardupilot_methodic_configurator/backend_flightcontroller.py +37 -20
  12. ardupilot_methodic_configurator/backend_flightcontroller_info.py +1 -1
  13. ardupilot_methodic_configurator/backend_internet.py +1 -1
  14. ardupilot_methodic_configurator/backend_mavftp.py +1 -1
  15. ardupilot_methodic_configurator/battery_cell_voltages.py +1 -1
  16. ardupilot_methodic_configurator/common_arguments.py +1 -1
  17. ardupilot_methodic_configurator/configuration_manager.py +561 -121
  18. ardupilot_methodic_configurator/configuration_steps_ArduCopter.json +7 -5
  19. ardupilot_methodic_configurator/configuration_steps_ArduPlane.json +3 -1
  20. ardupilot_methodic_configurator/configuration_steps_Heli.json +3 -1
  21. ardupilot_methodic_configurator/configuration_steps_Rover.json +3 -1
  22. ardupilot_methodic_configurator/configuration_steps_strings.py +5 -3
  23. ardupilot_methodic_configurator/data_model_ardupilot_parameter.py +55 -2
  24. ardupilot_methodic_configurator/data_model_configuration_step.py +96 -46
  25. ardupilot_methodic_configurator/data_model_fc_ids.py +16 -7
  26. ardupilot_methodic_configurator/data_model_motor_test.py +1 -1
  27. ardupilot_methodic_configurator/data_model_par_dict.py +25 -11
  28. ardupilot_methodic_configurator/data_model_software_updates.py +1 -1
  29. ardupilot_methodic_configurator/data_model_template_overview.py +1 -1
  30. ardupilot_methodic_configurator/data_model_vehicle_components.py +1 -1
  31. ardupilot_methodic_configurator/data_model_vehicle_components_base.py +3 -2
  32. ardupilot_methodic_configurator/data_model_vehicle_components_display.py +1 -1
  33. ardupilot_methodic_configurator/data_model_vehicle_components_import.py +2 -1
  34. ardupilot_methodic_configurator/data_model_vehicle_components_json_schema.py +1 -1
  35. ardupilot_methodic_configurator/data_model_vehicle_components_templates.py +1 -1
  36. ardupilot_methodic_configurator/data_model_vehicle_components_validation.py +41 -1
  37. ardupilot_methodic_configurator/data_model_vehicle_project.py +1 -1
  38. ardupilot_methodic_configurator/data_model_vehicle_project_creator.py +1 -1
  39. ardupilot_methodic_configurator/data_model_vehicle_project_opener.py +1 -1
  40. ardupilot_methodic_configurator/extract_param_defaults.py +1 -1
  41. ardupilot_methodic_configurator/frontend_tkinter_autoresize_combobox.py +1 -1
  42. ardupilot_methodic_configurator/frontend_tkinter_base_window.py +6 -2
  43. ardupilot_methodic_configurator/frontend_tkinter_component_editor.py +56 -29
  44. ardupilot_methodic_configurator/frontend_tkinter_component_editor_base.py +18 -13
  45. ardupilot_methodic_configurator/frontend_tkinter_component_template_manager.py +1 -1
  46. ardupilot_methodic_configurator/frontend_tkinter_connection_selection.py +1 -1
  47. ardupilot_methodic_configurator/frontend_tkinter_directory_selection.py +1 -1
  48. ardupilot_methodic_configurator/frontend_tkinter_entry_dynamic.py +1 -1
  49. ardupilot_methodic_configurator/frontend_tkinter_flightcontroller_info.py +1 -1
  50. ardupilot_methodic_configurator/frontend_tkinter_font.py +1 -1
  51. ardupilot_methodic_configurator/frontend_tkinter_motor_test.py +1 -1
  52. ardupilot_methodic_configurator/frontend_tkinter_pair_tuple_combobox.py +7 -1
  53. ardupilot_methodic_configurator/frontend_tkinter_parameter_editor.py +107 -156
  54. ardupilot_methodic_configurator/frontend_tkinter_parameter_editor_documentation_frame.py +24 -58
  55. ardupilot_methodic_configurator/frontend_tkinter_parameter_editor_table.py +24 -56
  56. ardupilot_methodic_configurator/frontend_tkinter_progress_window.py +1 -1
  57. ardupilot_methodic_configurator/frontend_tkinter_project_creator.py +1 -1
  58. ardupilot_methodic_configurator/frontend_tkinter_project_opener.py +1 -1
  59. ardupilot_methodic_configurator/frontend_tkinter_rich_text.py +1 -1
  60. ardupilot_methodic_configurator/frontend_tkinter_scroll_frame.py +1 -1
  61. ardupilot_methodic_configurator/frontend_tkinter_show.py +3 -3
  62. ardupilot_methodic_configurator/frontend_tkinter_software_update.py +1 -1
  63. ardupilot_methodic_configurator/frontend_tkinter_stage_progress.py +19 -29
  64. ardupilot_methodic_configurator/frontend_tkinter_template_overview.py +1 -1
  65. ardupilot_methodic_configurator/frontend_tkinter_usage_popup_window.py +1 -1
  66. ardupilot_methodic_configurator/internationalization.py +1 -1
  67. ardupilot_methodic_configurator/param_pid_adjustment_update.py +43 -39
  68. ardupilot_methodic_configurator/tempcal_imu.py +1 -1
  69. ardupilot_methodic_configurator/vehicle_components.py +1 -1
  70. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/AirCar_v1/14_logging.param +3 -3
  71. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/Big_Owl/14_logging.param +3 -3
  72. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/Chimera7/14_logging.param +3 -3
  73. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/FETtec-5/14_logging.param +3 -3
  74. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/GazeboIrisWithTargetFollow/14_logging.param +3 -3
  75. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/Holybro_X500/14_logging.param +3 -3
  76. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/Holybro_X500_V2/14_logging.param +3 -3
  77. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/Holybro_X650_LTE/14_logging.param +3 -3
  78. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/Hoverit_X11+/14_logging.param +3 -3
  79. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/Hoverit_X13/14_logging.param +3 -3
  80. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/Marmotte5v2/14_logging.param +3 -3
  81. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/ReadyToSkyZD550/14_logging.param +3 -3
  82. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/TarotFY680Hexacopter/05_remote_controller.param +1 -1
  83. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/TarotFY680Hexacopter/14_logging.param +3 -3
  84. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/TarotFY680Hexacopter/47_position_controller.param +2 -2
  85. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/Tarot_X4/14_logging.param +3 -3
  86. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/X11_plus/14_logging.param +3 -3
  87. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/diatone_taycan_mxc/4.3.8-params/14_logging.param +3 -3
  88. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/diatone_taycan_mxc/4.4.4-params/14_logging.param +3 -3
  89. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/diatone_taycan_mxc/4.5.x-params/14_logging.param +3 -3
  90. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/diatone_taycan_mxc/4.6.x-params/14_logging.param +3 -3
  91. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/empty_4.5.x/10_gnss.param +1 -1
  92. ardupilot_methodic_configurator/vehicle_templates/ArduCopter/empty_4.6.x/10_gnss.param +1 -1
  93. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/METADATA +12 -7
  94. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/RECORD +107 -106
  95. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/licenses/credits/CREDITS.md +1 -0
  96. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/WHEEL +0 -0
  97. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/entry_points.txt +0 -0
  98. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/licenses/LICENSE.md +0 -0
  99. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/licenses/LICENSES/Apache-2.0.txt +0 -0
  100. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/licenses/LICENSES/BSD-3-Clause.txt +0 -0
  101. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/licenses/LICENSES/GPL-3.0-or-later.txt +0 -0
  102. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/licenses/LICENSES/LGPL-3.0-or-later.txt +0 -0
  103. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/licenses/LICENSES/MIT-CMU.txt +0 -0
  104. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/licenses/LICENSES/MIT.txt +0 -0
  105. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/licenses/LICENSES/MPL-2.0.txt +0 -0
  106. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/licenses/LICENSES/PSF-2.0.txt +0 -0
  107. {ardupilot_methodic_configurator-2.6.1.dist-info → ardupilot_methodic_configurator-2.7.1.dist-info}/top_level.txt +0 -0
@@ -69,7 +69,9 @@
69
69
  "mandatory_text": "100% mandatory (0% optional)",
70
70
  "auto_changed_by": "",
71
71
  "derived_parameters": {
72
- "RC_PROTOCOLS": { "New Value": "vehicle_components['RC Receiver']['FC Connection']['Protocol']", "Change Reason": "Selected in the component editor" }
72
+ "RC_PROTOCOLS": { "New Value": "vehicle_components['RC Receiver']['FC Connection']['Protocol']", "Change Reason": "Selected in the component editor" },
73
+ "RC5_OPTION": { "New Value": "1 if vehicle_components['RC Receiver']['FC Connection']['Protocol'] == 'ExpressLRS' else fc_parameters.get('RC5_OPTION', 0)", "Change Reason": "ExpressLRS requires RC5 to be used for arming (Arm/Disarm function)" },
74
+ "FLTMODE_CH": { "New Value": "6 if vehicle_components['RC Receiver']['FC Connection']['Protocol'] == 'ExpressLRS' else fc_parameters.get('FLTMODE_CH', 5)", "Change Reason": "ExpressLRS requires FLTMODE_CH != 5" }
73
75
  },
74
76
  "rename_connection": "vehicle_components['RC Receiver']['FC Connection']['Type']",
75
77
  "old_filenames": []
@@ -212,7 +214,7 @@
212
214
  "wiki_text": "Follow the blog instructions and use Mission Planner instead of this tool to configure the mandatory hardware parameters.",
213
215
  "wiki_url": "",
214
216
  "external_tool_text": "Mission Planner",
215
- "external_tool_url": "https://github.com/ArduPilot/MethodicConfigurator/blob/latest/TUNING_GUIDE_ArduCopter.md#212-configure-mandatory-hardware-parameters-17",
217
+ "external_tool_url": "https://ardupilot.org/copter/docs/configuring-hardware.html",
216
218
  "mandatory_text": "100% mandatory (0% optional)",
217
219
  "auto_changed_by": "Mission Planner. If you have not done this step in Mission Planner yet, close this application and use Mission Planner",
218
220
  "old_filenames": ["11_mp_setup_mandatory_hardware.param"]
@@ -250,9 +252,9 @@
250
252
  "LOG_FILE_DSRMROT": { "New Value": 1, "Change Reason": "One .bin log file per flight, not per battery/reboot" }
251
253
  },
252
254
  "derived_parameters": {
253
- "INS_LOG_BAT_MASK": { "New Value": "1 if 'F4' in vehicle_components['Flight Controller']['Specifications']['MCU Series'] or vehicle_components['Propellers']['Specifications']['Diameter_inches'] < 16 else 0", "Change Reason": "Use acc and gyro batch logging on F4 processors, gyro raw logging on others" },
254
- "INS_LOG_BAT_OPT": { "New Value": "4 if 'F4' in vehicle_components['Flight Controller']['Specifications']['MCU Series'] or vehicle_components['Propellers']['Specifications']['Diameter_inches'] < 16 else 0", "Change Reason": "Use pre and post filters acc and gyro batch logging on F4 processors, pre-post gyro raw logging on others" },
255
- "INS_RAW_LOG_OPT": { "New Value": "0 if 'F4' in vehicle_components['Flight Controller']['Specifications']['MCU Series'] or vehicle_components['Propellers']['Specifications']['Diameter_inches'] < 16 else 9", "Change Reason": "Use pre and post filters acc and gyro batch logging on F4 processors, pre-post gyro raw logging on others" }
255
+ "INS_LOG_BAT_MASK": { "New Value": "1 if 'F4' in vehicle_components['Flight Controller']['Specifications']['MCU Series'] or vehicle_components['Propellers']['Specifications']['Diameter_inches'] > 16 else 0", "Change Reason": "Use acc and gyro batch logging on F4 processors or big props, gyro raw logging on others" },
256
+ "INS_LOG_BAT_OPT": { "New Value": "4 if 'F4' in vehicle_components['Flight Controller']['Specifications']['MCU Series'] or vehicle_components['Propellers']['Specifications']['Diameter_inches'] > 16 else 0", "Change Reason": "Use pre and post filters acc and gyro batch logging on F4 processors or big props, pre-post gyro raw logging on others" },
257
+ "INS_RAW_LOG_OPT": { "New Value": "0 if 'F4' in vehicle_components['Flight Controller']['Specifications']['MCU Series'] or vehicle_components['Propellers']['Specifications']['Diameter_inches'] > 16 else 9", "Change Reason": "Use pre and post filters acc and gyro batch logging on F4 processors or big props, pre-post gyro raw logging on others" }
256
258
  },
257
259
  "old_filenames": ["13_logging.param"]
258
260
  },
@@ -69,7 +69,9 @@
69
69
  "mandatory_text": "100% mandatory (0% optional)",
70
70
  "auto_changed_by": "",
71
71
  "derived_parameters": {
72
- "RC_PROTOCOLS": { "New Value": "vehicle_components['RC Receiver']['FC Connection']['Protocol']", "Change Reason": "Selected in the component editor" }
72
+ "RC_PROTOCOLS": { "New Value": "vehicle_components['RC Receiver']['FC Connection']['Protocol']", "Change Reason": "Selected in the component editor" },
73
+ "RC5_OPTION": { "New Value": "1 if vehicle_components['RC Receiver']['FC Connection']['Protocol'] == 'ExpressLRS' else fc_parameters.get('RC5_OPTION', 0)", "Change Reason": "ExpressLRS requires RC5 to be used for arming (Arm/Disarm function)" },
74
+ "FLTMODE_CH": { "New Value": "6 if vehicle_components['RC Receiver']['FC Connection']['Protocol'] == 'ExpressLRS' else fc_parameters.get('FLTMODE_CH', 5)", "Change Reason": "ExpressLRS requires FLTMODE_CH != 5" }
73
75
  },
74
76
  "rename_connection": "vehicle_components['RC Receiver']['FC Connection']['Type']",
75
77
  "old_filenames": []
@@ -69,7 +69,9 @@
69
69
  "mandatory_text": "100% mandatory (0% optional)",
70
70
  "auto_changed_by": "",
71
71
  "derived_parameters": {
72
- "RC_PROTOCOLS": { "New Value": "vehicle_components['RC Receiver']['FC Connection']['Protocol']", "Change Reason": "Selected in the component editor" }
72
+ "RC_PROTOCOLS": { "New Value": "vehicle_components['RC Receiver']['FC Connection']['Protocol']", "Change Reason": "Selected in the component editor" },
73
+ "RC5_OPTION": { "New Value": "1 if vehicle_components['RC Receiver']['FC Connection']['Protocol'] == 'ExpressLRS' else fc_parameters.get('RC5_OPTION', 0)", "Change Reason": "ExpressLRS requires RC5 to be used for arming (Arm/Disarm function)" },
74
+ "FLTMODE_CH": { "New Value": "6 if vehicle_components['RC Receiver']['FC Connection']['Protocol'] == 'ExpressLRS' else fc_parameters.get('FLTMODE_CH', 5)", "Change Reason": "ExpressLRS requires FLTMODE_CH != 5" }
73
75
  },
74
76
  "rename_connection": "vehicle_components['RC Receiver']['FC Connection']['Type']",
75
77
  "old_filenames": []
@@ -69,7 +69,9 @@
69
69
  "mandatory_text": "100% mandatory (0% optional)",
70
70
  "auto_changed_by": "",
71
71
  "derived_parameters": {
72
- "RC_PROTOCOLS": { "New Value": "vehicle_components['RC Receiver']['FC Connection']['Protocol']", "Change Reason": "Selected in the component editor" }
72
+ "RC_PROTOCOLS": { "New Value": "vehicle_components['RC Receiver']['FC Connection']['Protocol']", "Change Reason": "Selected in the component editor" },
73
+ "RC5_OPTION": { "New Value": "1 if vehicle_components['RC Receiver']['FC Connection']['Protocol'] == 'ExpressLRS' else fc_parameters.get('RC5_OPTION', 0)", "Change Reason": "ExpressLRS requires RC5 to be used for arming (Arm/Disarm function)" },
74
+ "FLTMODE_CH": { "New Value": "6 if vehicle_components['RC Receiver']['FC Connection']['Protocol'] == 'ExpressLRS' else fc_parameters.get('FLTMODE_CH', 5)", "Change Reason": "ExpressLRS requires FLTMODE_CH != 5" }
73
75
  },
74
76
  "rename_connection": "vehicle_components['RC Receiver']['FC Connection']['Type']",
75
77
  "old_filenames": []
@@ -1,7 +1,7 @@
1
1
  """
2
2
  Auto-generated by the update_configuration_steps_translation.py. Do not edit, ALL CHANGES WILL BE LOST.
3
3
 
4
- This file is part of Ardupilot methodic configurator. https://github.com/ArduPilot/MethodicConfigurator
4
+ This file is part of ArduPilot Methodic Configurator. https://github.com/ArduPilot/MethodicConfigurator
5
5
 
6
6
  SPDX-FileCopyrightText: 2024-2025 Amilcar Lucas
7
7
 
@@ -253,6 +253,8 @@ Jump to '47_position_controller.param' file?""")
253
253
  _config_steps_strings = _("Derived from vehicle component editor propeller size")
254
254
  _config_steps_strings = _("Disable fast harmonic notch logging")
255
255
  _config_steps_strings = _("Do not allow arming below this voltage")
256
+ _config_steps_strings = _("ExpressLRS requires FLTMODE_CH != 5")
257
+ _config_steps_strings = _("ExpressLRS requires RC5 to be used for arming (Arm/Disarm function)")
256
258
  _config_steps_strings = _("Gather data for the offline IMU temperature calibration while the FC is disarmed")
257
259
  _config_steps_strings = _("Gyro raw logging no longer required, notch filter setup is complete, this reduces processor load and log file size")
258
260
  _config_steps_strings = _("Hover learn will improve this initial guess")
@@ -287,9 +289,9 @@ Jump to '47_position_controller.param' file?""")
287
289
  _config_steps_strings = _("Use INS_GYRO_FILTER / 4 as a first guess")
288
290
  _config_steps_strings = _("Use MOT_THST_HOVER assuming MOT_THST_HOVER has been correctly learned")
289
291
  _config_steps_strings = _("Use VTOL-Quicktune lua script to estimate a good PID starting values")
290
- _config_steps_strings = _("Use acc and gyro batch logging on F4 processors, gyro raw logging on others")
292
+ _config_steps_strings = _("Use acc and gyro batch logging on F4 processors or big props, gyro raw logging on others")
291
293
  _config_steps_strings = _("Use lua scripting for VTOL-Quicktune, MagFit automation and wind speed estimation automation")
292
- _config_steps_strings = _("Use pre and post filters acc and gyro batch logging on F4 processors, pre-post gyro raw logging on others")
294
+ _config_steps_strings = _("Use pre and post filters acc and gyro batch logging on F4 processors or big props, pre-post gyro raw logging on others")
293
295
  _config_steps_strings = _("Use the first notch filter to filter the noise created by the motors/propellers")
294
296
  _config_steps_strings = _("Value for the first couple of flights will be changed later once MOT_THST_HOVER is learned")
295
297
  _config_steps_strings = _("allow post flight tuning with Replay")
@@ -1,7 +1,7 @@
1
1
  """
2
2
  ArduPilot parameter domain model.
3
3
 
4
- This file is part of Ardupilot methodic configurator. https://github.com/ArduPilot/MethodicConfigurator
4
+ This file is part of ArduPilot Methodic Configurator. https://github.com/ArduPilot/MethodicConfigurator
5
5
 
6
6
  SPDX-FileCopyrightText: 2024-2025 Amilcar do Carmo Lucas <amilcar.lucas@iav.de>
7
7
 
@@ -185,7 +185,7 @@ class ArduPilotParameter: # pylint: disable=too-many-instance-attributes, too-m
185
185
  value_dirty = (
186
186
  self._new_value != self._value_on_file
187
187
  if self.is_bitmask or self.is_multiple_choice
188
- else is_within_tolerance(self._new_value, self._value_on_file)
188
+ else not is_within_tolerance(self._new_value, self._value_on_file)
189
189
  )
190
190
  return value_dirty or self._change_reason != self._change_reason_on_file
191
191
 
@@ -259,6 +259,10 @@ class ArduPilotParameter: # pylint: disable=too-many-instance-attributes, too-m
259
259
  """Return the change reason string for this parameter."""
260
260
  return self._change_reason
261
261
 
262
+ def get_new_value(self) -> float:
263
+ """Return the new value for this parameter (to be saved to file or uploaded to FC)."""
264
+ return self._new_value
265
+
262
266
  def get_selected_value_from_dict(self) -> Optional[str]:
263
267
  """Return the string representation from the values dictionary for the new value."""
264
268
  if self.is_in_values_dict:
@@ -430,6 +434,55 @@ class ArduPilotParameter: # pylint: disable=too-many-instance-attributes, too-m
430
434
  self._change_reason = change_reason
431
435
  return True
432
436
 
437
+ def set_forced_or_derived_value(self, value: float) -> None:
438
+ """
439
+ Set the value for a forced or derived parameter.
440
+
441
+ This method bypasses normal validation and is intended for use only
442
+ when applying forced or derived parameter values after parameter creation.
443
+
444
+ Args:
445
+ value: The new value to set
446
+
447
+ Raises:
448
+ ValueError: If this parameter is not forced or derived
449
+
450
+ """
451
+ if not (self._is_forced or self._is_derived):
452
+ raise ValueError(_("This method is only for forced or derived parameters."))
453
+
454
+ if self.is_readonly:
455
+ raise ValueError(_("Readonly parameters cannot be forced or derived."))
456
+
457
+ self._new_value = value
458
+
459
+ def set_forced_or_derived_change_reason(self, change_reason: str) -> None:
460
+ """
461
+ Set the change reason for a forced or derived parameter.
462
+
463
+ This method bypasses normal validation and is intended for use only
464
+ when applying forced or derived parameter change reasons after parameter creation.
465
+
466
+ Args:
467
+ change_reason: The new change reason to set
468
+
469
+ Raises:
470
+ ValueError: If this parameter is not forced or derived
471
+
472
+ """
473
+ if not (self._is_forced or self._is_derived):
474
+ raise ValueError(_("This method is only for forced or derived parameters."))
475
+
476
+ if self.is_readonly:
477
+ raise ValueError(_("Readonly parameters cannot be forced or derived."))
478
+
479
+ self._change_reason = change_reason
480
+
481
+ def copy_new_value_to_file(self) -> None:
482
+ """Copy the new value to the value on file, marking it as saved, resetting the is_dirty property."""
483
+ self._value_on_file = self._new_value
484
+ self._change_reason_on_file = self._change_reason
485
+
433
486
 
434
487
  class BitmaskHelper:
435
488
  """Helper class for working with ArduPilot parameter bitmasks."""
@@ -4,7 +4,7 @@ Configuration step data model for parameter processing and domain model creation
4
4
  This file contains business logic for processing configuration steps, including parameter
5
5
  computation, domain model creation, and connection renaming operations.
6
6
 
7
- This file is part of Ardupilot methodic configurator. https://github.com/ArduPilot/MethodicConfigurator
7
+ This file is part of ArduPilot Methodic Configurator. https://github.com/ArduPilot/MethodicConfigurator
8
8
 
9
9
  SPDX-FileCopyrightText: 2024-2025 Amilcar do Carmo Lucas <amilcar.lucas@iav.de>
10
10
 
@@ -28,6 +28,11 @@ class ConfigurationStepProcessor:
28
28
  including parameter computation, domain model creation, and connection renaming.
29
29
  """
30
30
 
31
+ # Bits indicating ExpressLRS in RC_OPTIONS parameter
32
+ # 9: Suppress CRSF mode/rate message for ELRS systems
33
+ # 13: Use 420kbaud for ELRS protocol
34
+ ELRS_RC_OPTIONS_BITS = (9, 13)
35
+
31
36
  def __init__(self, local_filesystem: LocalFilesystem) -> None:
32
37
  """
33
38
  Initialize the configuration step processor.
@@ -42,11 +47,18 @@ class ConfigurationStepProcessor:
42
47
  # These variables are used by the forced_parameters and derived_parameters in configuration_steps_*.json files
43
48
  self.variables = self.local_filesystem.get_eval_variables()
44
49
 
45
- def process_configuration_step(
50
+ def process_configuration_step( # pylint: disable=too-many-locals
46
51
  self,
47
52
  selected_file: str,
48
53
  fc_parameters: dict[str, float],
49
- ) -> tuple[dict[str, ArduPilotParameter], bool, list[tuple[str, str]], list[tuple[str, str]]]:
54
+ ) -> tuple[
55
+ dict[str, ArduPilotParameter],
56
+ list[tuple[str, str]],
57
+ list[tuple[str, str]],
58
+ set[str],
59
+ list[tuple[str, str]],
60
+ ParDict,
61
+ ]:
50
62
  """
51
63
  Process a configuration step including parameter computation and domain model creation.
52
64
 
@@ -57,67 +69,103 @@ class ConfigurationStepProcessor:
57
69
  Returns:
58
70
  Tuple containing:
59
71
  - Dictionary of ArduPilotParameter domain model objects
60
- - Boolean indicating if at least one parameter was edited
61
72
  - List of (title, message) tuples for UI error feedback
62
73
  - List of (title, message) tuples for UI info feedback
74
+ - Set of parameter names to remove (duplicates from rename operations)
75
+ - List of (old_name, new_name) pairs to rename
76
+ - ParDict of derived parameters to apply to domain model
63
77
 
64
78
  """
65
- at_least_one_param_edited = False
66
79
  ui_errors: list[tuple[str, str]] = []
67
80
  ui_infos: list[tuple[str, str]] = []
81
+ duplicates_to_remove: set[str] = set()
82
+ renames_to_apply: list[tuple[str, str]] = []
83
+ derived_params_to_apply: ParDict = ParDict()
68
84
 
69
85
  # Process configuration step operations if configuration steps exist
70
86
  if self.local_filesystem.configuration_steps and selected_file in self.local_filesystem.configuration_steps:
71
87
  variables = self.variables
72
88
  variables["fc_parameters"] = fc_parameters
73
89
 
74
- # Compute derived parameters
90
+ # Compute derived parameters (does NOT mutate filesystem.file_parameters)
75
91
  error_msg = self.local_filesystem.compute_parameters(
76
92
  selected_file, self.local_filesystem.configuration_steps[selected_file], "derived", variables
77
93
  )
78
94
  if error_msg:
79
95
  ui_errors.append((_("Error in derived parameters"), error_msg))
80
- # Merge derived parameter values
81
- elif self.local_filesystem.merge_forced_or_derived_parameters(
82
- selected_file, self.local_filesystem.derived_parameters, list(fc_parameters.keys())
83
- ):
84
- at_least_one_param_edited = True
85
-
86
- # Handle connection renaming
87
- connection_edited, ui_infos = self._handle_connection_renaming(selected_file, variables)
88
- if connection_edited:
89
- at_least_one_param_edited = True
96
+ # Collect derived parameter values to apply later in domain model
97
+ elif selected_file in self.local_filesystem.derived_parameters:
98
+ # Filter derived parameters that exist in FC (if fc_parameters provided)
99
+ fc_param_names = set(fc_parameters.keys()) if fc_parameters else set()
100
+ for param_name, param in self.local_filesystem.derived_parameters[selected_file].items():
101
+ # Only include if no FC filter OR parameter exists in FC
102
+ if not fc_param_names or param_name in fc_param_names:
103
+ derived_params_to_apply[param_name] = param
104
+
105
+ # Populate new_connection_prefix from rename_connection configuration step
106
+ if "rename_connection" in self.local_filesystem.configuration_steps.get(selected_file, {}):
107
+ variables["new_connection_prefix"] = self.local_filesystem.configuration_steps[selected_file][
108
+ "rename_connection"
109
+ ]
110
+
111
+ # Calculate connection rename operations (does NOT mutate filesystem.file_parameters)
112
+ rename_ui_infos, duplicates_to_remove, renames_to_apply = self._handle_connection_renaming(
113
+ selected_file, variables
114
+ )
115
+ ui_infos.extend(rename_ui_infos)
90
116
 
91
117
  # Create domain model parameters
92
- parameters = self._create_domain_model_parameters(selected_file, fc_parameters)
93
-
94
- return parameters, at_least_one_param_edited, ui_errors, ui_infos
95
-
96
- def _handle_connection_renaming(self, selected_file: str, variables: dict) -> tuple[bool, list[tuple[str, str]]]:
118
+ current_step_parameters = self._create_domain_model_parameters(selected_file, fc_parameters)
119
+
120
+ # Check for ExpressLRS and add FLTMODE_CH warning
121
+ if current_step_parameters.get("RC_OPTIONS") is not None or current_step_parameters.get("FLTMODE_CH") is not None:
122
+ rc_options = int(fc_parameters.get("RC_OPTIONS", 32))
123
+ if (rc_options & (1 << self.ELRS_RC_OPTIONS_BITS[0])) or (rc_options & (1 << self.ELRS_RC_OPTIONS_BITS[1])):
124
+ fltmode_ch = fc_parameters.get("FLTMODE_CH", 5)
125
+ if fltmode_ch == 5:
126
+ ui_infos.append(
127
+ (
128
+ _("ExpressLRS Configuration Warning"),
129
+ _(
130
+ "FLTMODE_CH must be set to a channel other than 5 (currently set to 5).\n"
131
+ "Please change FLTMODE_CH to a different channel (e.g., 6, 7, 8, etc.)\n"
132
+ "to avoid conflicts with the required RC5 arming channel."
133
+ ),
134
+ )
135
+ )
136
+
137
+ return current_step_parameters, ui_errors, ui_infos, duplicates_to_remove, renames_to_apply, derived_params_to_apply
138
+
139
+ def _handle_connection_renaming(
140
+ self, selected_file: str, variables: dict
141
+ ) -> tuple[list[tuple[str, str]], set[str], list[tuple[str, str]]]:
97
142
  """
98
- Handle connection renaming operations for the selected file.
143
+ Calculate connection renaming operations for the selected file.
144
+
145
+ This method calculates what renames should happen but does NOT modify
146
+ filesystem.file_parameters. The operations are returned for the caller
147
+ to apply to the domain model.
99
148
 
100
149
  Args:
101
150
  selected_file: The name of the selected parameter file
102
- variables: Variables dictionary for evaluation
151
+ variables: Dictionary of variables for parameter evaluation
103
152
 
104
153
  Returns:
105
154
  Tuple containing:
106
- - True if parameters were modified, False otherwise
107
155
  - List of (title, message) tuples for UI info feedback
156
+ - Set of parameter names to remove (duplicates)
157
+ - List of (old_name, new_name) pairs to rename
108
158
 
109
159
  """
110
- if "rename_connection" not in self.local_filesystem.configuration_steps[selected_file]:
111
- return False, []
160
+ new_connection_prefix = variables.get("new_connection_prefix")
161
+ if not new_connection_prefix:
162
+ return [], set(), []
112
163
 
113
- new_connection_prefix = self.local_filesystem.configuration_steps[selected_file]["rename_connection"]
114
-
115
- # Apply renames to the parameters dictionary
116
- duplicated_parameters, renamed_pairs = self._apply_connection_renames(
164
+ # Calculate rename operations WITHOUT mutating file_parameters
165
+ duplicated_parameters, renamed_pairs = self._calculate_connection_rename_operations(
117
166
  self.local_filesystem.file_parameters[selected_file], new_connection_prefix, variables
118
167
  )
119
168
 
120
- at_least_one_param_edited = False
121
169
  ui_infos: list[tuple[str, str]] = []
122
170
 
123
171
  # Handle duplicated parameters
@@ -125,7 +173,6 @@ class ConfigurationStepProcessor:
125
173
  logging_info(_("Removing duplicate parameter %s"), old_name)
126
174
  info_msg = _("The parameter '{old_name}' was removed due to duplication.")
127
175
  ui_infos.append((_("Parameter Removed"), info_msg.format(**locals())))
128
- at_least_one_param_edited = True
129
176
 
130
177
  # Handle renamed parameters
131
178
  for old_name, new_name in renamed_pairs:
@@ -135,9 +182,8 @@ class ConfigurationStepProcessor:
135
182
  "to obey the flight controller connection defined in the component editor window."
136
183
  )
137
184
  ui_infos.append((_("Parameter Renamed"), info_msg.format(**locals())))
138
- at_least_one_param_edited = True
139
185
 
140
- return at_least_one_param_edited, ui_infos
186
+ return ui_infos, duplicated_parameters, renamed_pairs
141
187
 
142
188
  def _create_domain_model_parameters(
143
189
  self, selected_file: str, fc_parameters: dict[str, float]
@@ -225,21 +271,25 @@ class ConfigurationStepProcessor:
225
271
  return renames
226
272
 
227
273
  @staticmethod
228
- def _apply_connection_renames(
229
- parameters: dict[str, Any], new_connection_prefix: str, variables: Optional[dict[str, Any]] = None
274
+ def _calculate_connection_rename_operations(
275
+ parameters: ParDict, new_connection_prefix: str, variables: Optional[dict[str, Any]] = None
230
276
  ) -> tuple[set[str], list[tuple[str, str]]]:
231
277
  """
232
- Apply connection prefix renames to a parameter dictionary.
278
+ Calculate connection prefix rename operations without mutating the parameters dictionary.
279
+
280
+ This method determines which parameters should be renamed and which are duplicates,
281
+ but does NOT modify the input dictionary. The caller is responsible for applying
282
+ the operations to their domain model.
233
283
 
234
284
  Args:
235
- parameters: Dictionary of parameter objects to rename, it will modify it
285
+ parameters: Dictionary of parameter objects to analyze (NOT modified)
236
286
  new_connection_prefix: The new prefix to apply
237
287
  variables: Optional dictionary of variables for evaluation
238
288
 
239
289
  Returns:
240
290
  Tuple containing:
241
- - Set of duplicated parameter names that got removed
242
- - List of (old_name, new_name) pairs that were renamed
291
+ - Set of parameter names that should be removed (duplicates)
292
+ - List of (old_name, new_name) pairs that should be renamed
243
293
 
244
294
  """
245
295
  if variables:
@@ -249,18 +299,18 @@ class ConfigurationStepProcessor:
249
299
  # Generate the rename mapping
250
300
  renames = ConfigurationStepProcessor._generate_connection_renames(list(parameters.keys()), new_connection_prefix)
251
301
 
252
- # Track unique new names and actual renames performed
253
- new_names = set()
254
- duplicates = set()
302
+ # Track unique new names and actual renames to perform
303
+ # Initialize with all existing parameter names to prevent conflicts
304
+ new_names = set(parameters.keys())
305
+ duplicates: set[str] = set()
255
306
  renamed_pairs = []
256
307
  for old_name, new_name in renames.items():
257
308
  if new_name in new_names:
258
- parameters.pop(old_name)
259
- duplicates.add(old_name)
309
+ # Do not perform rename due to conflict, let the user handle it
310
+ pass
260
311
  else:
261
312
  new_names.add(new_name)
262
313
  if new_name != old_name:
263
- parameters[new_name] = parameters.pop(old_name)
264
314
  renamed_pairs.append((old_name, new_name))
265
315
 
266
316
  return duplicates, renamed_pairs
@@ -26,7 +26,7 @@ VID_VENDOR_DICT: dict[int, list[str]] = {
26
26
  # Maps USB VID,PID tuple to product name(s)
27
27
  VID_PID_PRODUCT_DICT: dict[tuple[int, int], list[str]] = {
28
28
  (0x26AC, 0x1124): ["CZOEMrevG"],
29
- (0x1209, 0x5741): ["AcctonGodwit_GA1", "ACNS-CM4Pilot", "ACNS-F405AIO", "AEDROXH7", "AeroCogito-H7Digital", "AEROFOX-H7", "AET-H743-Basic", "airbotf4", "AIRLink", "Airvolute-DCS2", "AnyleafH7", "Aocoda-RC-H743Dual", "AR-F407SmartBat", "ARK_CANNODE", "ARK_FPV", "ARK_PI6X", "ARKV6X", "AtomRCF405NAVI", "ATOMRCF405NAVI-Deluxe", "BeastF7", "BeastF7v2", "BeastH7", "BeastH7v2", "BETAFPV-F405", "BirdCANdy", "BlitzF745", "BlitzF745AIO", "BlitzH743Pro", "BlitzMiniF745", "BlitzWingH743", "BotBloxDroneNet", "BOTWINGF405", "BrahmaF4", "BROTHERHOBBYF405v3", "BROTHERHOBBYH743", "C-RTK2-HP", "CarbonixF405", "CBU-H7-LC-Stamp", "CBU-H7-Stamp", "CORVON405V2_1", "CORVON743V1", "CrazyF405", "crazyflie2", "CSKY405", "CUAV-7-Nano", "CUAV-Nora", "CUAV-Pixhack-v3", "CUAV-V6X-v2", "CUAV-X25-EVO", "CUAV-X7", "CUAVv5", "CUAVv5Nano", "CubeNode", "CubeRedSecondary", "CubeRedSecondary-IO", "CubeSolo", "DAKEFPVF405", "DAKEFPVH743", "DAKEFPVH743Pro", "DevEBoxH7v2", "DroneerF405", "DrotekP3Pro", "F35Lightning", "F4BY_H743", "FlyingMoonF407", "FlyingMoonF427", "FlyingMoonH743", "FlywooF405HD-AIOv2", "FlywooF405Pro", "FlywooF405S-AIO", "FlywooF745", "FlywooF745Nano", "FlywooH743Pro", "fmuv2", "fmuv3", "fmuv5", "FoxeerF405v2", "FoxeerH743v1", "FreeflyRTK", "GEPRC_TAKER_H743", "GEPRCF745BTHD", "UltraBlue", "%BOARD%", "HEEWING-F405", "HEEWING-F405v2", "Here4AP", "Here4FC", "HolybroF4_PMU", "IFLIGHT_2RAW_H7", "JFB100", "JFB-110", "JHEM_JHEF405", "JHEMCU-GSF405A", "JHEMCU-GSF405A-RX2", "JHEMCU-H743HD", "JHEMCUF405PRO", "JHEMCUF405WING", "KakuteF4", "KakuteF4-Wing", "KakuteF4Mini", "KakuteF7", "KakuteF7Mini", "KakuteH7", "KakuteH7-Wing", "KakuteH7Mini", "KakuteH7Mini-Nand", "KakuteH7v2", "LongBowF405WING", "LumenierLUXF765-NDAA", "luminousbee4", "luminousbee5", "MambaF405-2022", "MambaF405v2", "MambaH743v4", "MatekF405", "MatekF405-CAN", "MatekF405-STD", "MatekF405-TE", "MatekF405-Wing", "MatekF765-SE", "MatekF765-Wing", "MatekH743", "MatekH7A3", "MazzyStarDrone", "MFE_POS3_CAN", "MFT-SEMA100", "MicoAir405Mini", "MicoAir405v2", "MicoAir743", "MicoAir743-AIO", "MicoAir743v2", "mindpx-v2", "mini-pix", "modalai_fc-v1", "mRoControlZeroClassic", "mRoControlZeroF7", "mRoControlZeroH7", "mRoControlZeroOEMH7", "mRoCZeroOEMH7", "mRoNexus", "mRoPixracerPro", "mRoX21", "mRoX21-777", "MUPilot", "NarinFC-H5", "NarinFC-H7", "Nucleo-L476", "Nucleo-L496", "NucleoH743", "NucleoH755", "NxtPX4v2", "omnibusf4", "omnibusf4pro", "omnibusf4pro-one", "omnibusf4v6", "OMNIBUSF7V2", "OmnibusNanoV6", "ORBITH743", "OrqaF405Pro", "OrqaH7QuadCore", "PH4-mini", "PixC4-Jetson", "PixFlamingo", "Pixhawk1", "Pixhawk1-1M", "Pixhawk4", "Pixhawk6X", "Pixhawk6X-PPPGW", "PixPilot-C3", "PixPilot-V3", "PixPilot-V6", "PixPilot-V6PRO", "Pixracer", "PixSurveyA1", "PixSurveyA1-IND", "PixSurveyA2-IND", "QioTekAdeptF407", "QioTekZealotF427", "QioTekZealotH743", "R9Pilot", "RadiolinkF405", "RadiolinkPIX6", "RADIX2HD", "ReaperF745", "revo-mini", "revo-mini-i2c", "revo-mini-sd", "rFCU", "SDMODELH7V1", "SDMODELH7V2", "SequreH743", "Sierra-F405", "Sierra-F412", "Sierra-F9P", "Sierra-PrecisionPoint", "SIYI_N7", "SkySakuraH743", "SkystarsF405v2", "SkystarsH7HD", "SkystarsH7HDv2", "skyviper-f412-rev1", "skyviper-journey", "skyviper-v2450", "sparky2", "SPEDIXF405", "SPEDIXH743", "speedybeef4", "SpeedyBeeF405AIO", "SpeedyBeeF405Mini", "SpeedyBeeF405WING", "speedybeef4v3", "speedybeef4v4", "SPRacingH7", "SPRacingH7RF", "StellarF4", "StellarF4V2", "StellarH7V2", "SuccexF4", "SULILGH7-P1-P2", "SVehicle-E2", "sw-boom-f407", "sw-nav-f405", "sw-spar-f407", "Swan-K1", "TBS-Colibri-F7", "TBS_LUCID_H7", "TBS_LUCID_H7_WING", "TBS_LUCID_PRO", "TMotorH743", "uav-dev-fc-um982", "VUAV-V7pro", "X-MAV-AP-H743v2", "YARIV6X", "YJUAV_A6", "YJUAV_A6SE", "YJUAV_A6SE_H743", "YJUAV_A6Ultra", "ZeroOneX6", "ZeroOneX6_Air"],
29
+ (0x1209, 0x5741): ["AcctonGodwit_GA1", "ACNS-CM4Pilot", "ACNS-F405AIO", "AEDROXH7", "AeroCogito-H7Digital", "AEROFOX-H7", "AET-H743-Basic", "airbotf4", "AIRLink", "Airvolute-DCS2", "AnyleafH7", "Aocoda-RC-H743Dual", "AR-F407SmartBat", "ARK_CANNODE", "ARK_FPV", "ARK_PI6X", "ARKV6X", "AtomRCF405NAVI", "ATOMRCF405NAVI-Deluxe", "BeastF7", "BeastF7v2", "BeastH7", "BeastH7v2", "BETAFPV-F405", "BirdCANdy", "BlitzF745", "BlitzF745AIO", "BlitzH743Pro", "BlitzMiniF745", "BlitzWingH743", "BotBloxDroneNet", "BOTWINGF405", "BrahmaF4", "BROTHERHOBBYF405v3", "BROTHERHOBBYH743", "C-RTK2-HP", "CarbonixF405", "CBU-H7-LC-Stamp", "CBU-H7-Stamp", "CORVON405V2_1", "CORVON743V1", "CrazyF405", "crazyflie2", "CSKY405", "CUAV-7-Nano", "CUAV-Nora", "CUAV-Pixhack-v3", "CUAV-V6X-v2", "CUAV-X25-EVO", "CUAV-X7", "CUAVv5", "CUAVv5Nano", "CubeNode", "CubeRedSecondary", "CubeRedSecondary-IO", "CubeSolo", "DAKEFPVF405", "DAKEFPVH743", "DAKEFPVH743Pro", "DevEBoxH7v2", "DroneerF405", "DrotekP3Pro", "F35Lightning", "F4BY_H743", "FlyingMoonF407", "FlyingMoonF427", "FlyingMoonH743", "FlysparkF4", "FlywooF405HD-AIOv2", "FlywooF405Pro", "FlywooF405S-AIO", "FlywooF745", "FlywooF745Nano", "FlywooH743Pro", "fmuv2", "fmuv3", "fmuv5", "FoxeerF405v2", "FoxeerH743v1", "FreeflyRTK", "GEPRC_TAKER_H743", "GEPRCF745BTHD", "UltraBlue", "%BOARD%", "HEEWING-F405", "HEEWING-F405v2", "Here4AP", "Here4FC", "HolybroF4_PMU", "IFLIGHT_2RAW_H7", "JFB100", "JFB-110", "JHEM_JHEF405", "JHEMCU-GSF405A", "JHEMCU-GSF405A-RX2", "JHEMCU-H743HD", "JHEMCUF405PRO", "JHEMCUF405WING", "KakuteF4", "KakuteF4-Wing", "KakuteF4Mini", "KakuteF7", "KakuteF7Mini", "KakuteH7", "KakuteH7-Wing", "KakuteH7Mini", "KakuteH7Mini-Nand", "KakuteH7v2", "LongBowF405WING", "LumenierLUXF765-NDAA", "luminousbee4", "luminousbee5", "MambaF405-2022", "MambaF405v2", "MambaH743v4", "MatekF405", "MatekF405-CAN", "MatekF405-STD", "MatekF405-TE", "MatekF405-Wing", "MatekF765-SE", "MatekF765-Wing", "MatekH743", "MatekH7A3", "MazzyStarDrone", "MFE_POS3_CAN", "MFT-SEMA100", "MicoAir405Mini", "MicoAir405v2", "MicoAir743", "MicoAir743-AIO", "MicoAir743v2", "mindpx-v2", "mini-pix", "modalai_fc-v1", "mRoControlZeroClassic", "mRoControlZeroF7", "mRoControlZeroH7", "mRoControlZeroOEMH7", "mRoCZeroOEMH7", "mRoNexus", "mRoPixracerPro", "mRoX21", "mRoX21-777", "MUPilot", "NarinFC-H5", "NarinFC-H7", "NarinFC-X3", "Nucleo-L476", "Nucleo-L496", "NucleoH743", "NucleoH755", "NxtPX4v2", "omnibusf4", "omnibusf4pro", "omnibusf4pro-one", "omnibusf4v6", "OMNIBUSF7V2", "OmnibusNanoV6", "ORBITH743", "OrqaF405Pro", "OrqaH7QuadCore", "PH4-mini", "PixC4-Jetson", "PixFlamingo", "Pixhawk1", "Pixhawk1-1M", "Pixhawk4", "Pixhawk6X", "Pixhawk6X-PPPGW", "PixPilot-C3", "PixPilot-V3", "PixPilot-V6", "PixPilot-V6PRO", "Pixracer", "PixSurveyA1", "PixSurveyA1-IND", "PixSurveyA2-IND", "QioTekAdeptF407", "QioTekZealotF427", "QioTekZealotH743", "R9Pilot", "RadiolinkF405", "RadiolinkPIX6", "RADIX2HD", "ReaperF745", "revo-mini", "revo-mini-i2c", "revo-mini-sd", "rFCU", "SDMODELH7V1", "SDMODELH7V2", "SequreH743", "Sierra-F405", "Sierra-F412", "Sierra-F9P", "Sierra-PrecisionPoint", "SIYI_N7", "SkySakuraH743", "SkystarsF405v2", "SkystarsH7HD", "SkystarsH7HDv2", "skyviper-f412-rev1", "skyviper-journey", "skyviper-v2450", "sparky2", "SPEDIXF405", "SPEDIXH743", "speedybeef4", "SpeedyBeeF405AIO", "SpeedyBeeF405Mini", "SpeedyBeeF405WING", "speedybeef4v3", "speedybeef4v4", "SPRacingH7", "SPRacingH7RF", "StellarF4", "StellarF4V2", "StellarH7V2", "SuccexF4", "SULILGH7-P1-P2", "SVehicle-E2", "sw-boom-f407", "sw-nav-f405", "sw-spar-f407", "Swan-K1", "TBS-Colibri-F7", "TBS_LUCID_H7", "TBS_LUCID_H7_WING", "TBS_LUCID_H7_WING_AIO", "TBS_LUCID_PRO", "TMotorH743", "uav-dev-fc-um982", "VUAV-V7pro", "X-MAV-AP-H743v2", "YARIV6X", "YJUAV_A6", "YJUAV_A6SE", "YJUAV_A6SE_H743", "YJUAV_A6Ultra", "ZeroOneX6", "ZeroOneX6_Air"],
30
30
  (0x2DAE, 0x1011): ["CubeBlack", "CubeGreen-solo"],
31
31
  (0x2DAE, 0x1101): ["CubeBlack+"],
32
32
  (0x2DAE, 0x1016): ["CubeOrange"],
@@ -49,7 +49,7 @@ VID_PID_PRODUCT_DICT: dict[tuple[int, int], list[str]] = {
49
49
  (0x27AC, 0x1351): ["VRUBrain-v51"],
50
50
  }
51
51
 
52
- # Maps 16-bit APJ board ID to board name(s) for 266 supported boards
52
+ # Maps 16-bit APJ board ID to board name(s) for 269 supported boards
53
53
  APJ_BOARD_ID_NAME_DICT: dict[int, list[str]] = {
54
54
  1124: ["3DRControlZeroG"],
55
55
  7120: ["AcctonGodwit_GA1"],
@@ -126,6 +126,7 @@ APJ_BOARD_ID_NAME_DICT: dict[int, list[str]] = {
126
126
  1067: ["FlyingMoonF407"],
127
127
  1068: ["FlyingMoonF427"],
128
128
  1112: ["FlyingMoonH743"],
129
+ 1361: ["FlysparkF4"],
129
130
  1180: ["FlywooF405HD-AIOv2"],
130
131
  1137: ["FlywooF405Pro"],
131
132
  1099: ["FlywooF405S-AIO"],
@@ -194,6 +195,7 @@ APJ_BOARD_ID_NAME_DICT: dict[int, list[str]] = {
194
195
  1222: ["MUPilot"],
195
196
  1188: ["NarinFC-H5"],
196
197
  1183: ["NarinFC-H7"],
198
+ 1199: ["NarinFC-X3"],
197
199
  1051: ["Nucleo-L476"],
198
200
  1047: ["Nucleo-L496"],
199
201
  1159: ["NxtPX4v2"],
@@ -262,6 +264,7 @@ APJ_BOARD_ID_NAME_DICT: dict[int, list[str]] = {
262
264
  6000: ["sw-spar-f407"],
263
265
  5250: ["TBS_LUCID_H7"],
264
266
  5253: ["TBS_LUCID_H7_WING"],
267
+ 5254: ["TBS_LUCID_H7_WING_AIO"],
265
268
  5251: ["TBS_LUCID_PRO"],
266
269
  212: ["thepeach-k1"],
267
270
  213: ["thepeach-r1"],
@@ -282,7 +285,7 @@ APJ_BOARD_ID_NAME_DICT: dict[int, list[str]] = {
282
285
  5600: ["ZeroOneX6", "ZeroOneX6_Air"],
283
286
  }
284
287
 
285
- # Maps 16-bit APJ board ID to board vendor for 266 supported boards
288
+ # Maps 16-bit APJ board ID to board vendor for 269 supported boards
286
289
  APJ_BOARD_ID_VENDOR_DICT: dict[int, list[str]] = {
287
290
  1124: ["3DR"], # 3DRControlZeroG
288
291
  7120: ["ArduPilot"], # AcctonGodwit_GA1
@@ -359,6 +362,7 @@ APJ_BOARD_ID_VENDOR_DICT: dict[int, list[str]] = {
359
362
  1067: ["ArduPilot"], # FlyingMoonF407
360
363
  1068: ["ArduPilot"], # FlyingMoonF427
361
364
  1112: ["ArduPilot"], # FlyingMoonH743
365
+ 1361: ["ArduPilot"], # FlysparkF4
362
366
  1180: ["ArduPilot"], # FlywooF405HD-AIOv2
363
367
  1137: ["ArduPilot"], # FlywooF405Pro
364
368
  1099: ["ArduPilot"], # FlywooF405S-AIO
@@ -427,6 +431,7 @@ APJ_BOARD_ID_VENDOR_DICT: dict[int, list[str]] = {
427
431
  1222: ["ArduPilot"], # MUPilot
428
432
  1188: ["ArduPilot"], # NarinFC-H5
429
433
  1183: ["ArduPilot"], # NarinFC-H7
434
+ 1199: ["ArduPilot"], # NarinFC-X3
430
435
  1051: ["ArduPilot"], # Nucleo-L476
431
436
  1047: ["ArduPilot"], # Nucleo-L496
432
437
  1159: ["ArduPilot"], # NxtPX4v2
@@ -495,6 +500,7 @@ APJ_BOARD_ID_VENDOR_DICT: dict[int, list[str]] = {
495
500
  6000: ["ArduPilot"], # sw-spar-f407
496
501
  5250: ["ArduPilot"], # TBS_LUCID_H7
497
502
  5253: ["ArduPilot"], # TBS_LUCID_H7_WING
503
+ 5254: ["ArduPilot"], # TBS_LUCID_H7_WING_AIO
498
504
  5251: ["ArduPilot"], # TBS_LUCID_PRO
499
505
  212: ["ThePeach"], # thepeach-k1
500
506
  213: ["ThePeach"], # thepeach-r1
@@ -515,7 +521,7 @@ APJ_BOARD_ID_VENDOR_DICT: dict[int, list[str]] = {
515
521
  5600: ["ArduPilot"], # ZeroOneX6, ZeroOneX6_Air
516
522
  }
517
523
 
518
- # Maps 16-bit APJ board ID to MCU series for 266 supported boards
524
+ # Maps 16-bit APJ board ID to MCU series for 269 supported boards
519
525
  APJ_BOARD_ID_MCU_SERIES_DICT: dict[int, list[str]] = {
520
526
  1124: ["STM32H7xx"], # 3DRControlZeroG
521
527
  7120: ["STM32H7xx"], # AcctonGodwit_GA1
@@ -592,6 +598,7 @@ APJ_BOARD_ID_MCU_SERIES_DICT: dict[int, list[str]] = {
592
598
  1067: ["STM32F4xx"], # FlyingMoonF407
593
599
  1068: ["STM32F4xx"], # FlyingMoonF427
594
600
  1112: ["STM32H7xx"], # FlyingMoonH743
601
+ 1361: ["STM32F4xx"], # FlysparkF4
595
602
  1180: ["STM32F4xx"], # FlywooF405HD-AIOv2
596
603
  1137: ["STM32F4xx"], # FlywooF405Pro
597
604
  1099: ["STM32F4xx"], # FlywooF405S-AIO
@@ -660,6 +667,7 @@ APJ_BOARD_ID_MCU_SERIES_DICT: dict[int, list[str]] = {
660
667
  1222: ["STM32F7xx"], # MUPilot
661
668
  1188: ["STM32H7xx"], # NarinFC-H5
662
669
  1183: ["STM32H7xx"], # NarinFC-H7
670
+ 1199: ["STM32H7xx"], # NarinFC-X3
663
671
  1051: ["STM32L476"], # Nucleo-L476
664
672
  1047: ["STM32L496"], # Nucleo-L496
665
673
  1159: ["STM32H7xx"], # NxtPX4v2
@@ -728,6 +736,7 @@ APJ_BOARD_ID_MCU_SERIES_DICT: dict[int, list[str]] = {
728
736
  6000: ["STM32F4xx"], # sw-spar-f407
729
737
  5250: ["STM32H7xx"], # TBS_LUCID_H7
730
738
  5253: ["STM32H7xx"], # TBS_LUCID_H7_WING
739
+ 5254: ["STM32H7xx"], # TBS_LUCID_H7_WING_AIO
731
740
  5251: ["STM32F4xx"], # TBS_LUCID_PRO
732
741
  212: ["STM32F4xx"], # thepeach-k1
733
742
  213: ["STM32F4xx"], # thepeach-r1
@@ -748,12 +757,12 @@ APJ_BOARD_ID_MCU_SERIES_DICT: dict[int, list[str]] = {
748
757
  5600: ["STM32H7xx"], # ZeroOneX6, ZeroOneX6_Air
749
758
  }
750
759
 
751
- # Maps MCU series to 16-bit APJ board ID for 266 supported boards
760
+ # Maps MCU series to 16-bit APJ board ID for 269 supported boards
752
761
  MCU_SERIES_APJ_BOARD_ID_DICT: dict[str, list[int]] = {
753
762
  "CKS32F4xx": [1134, 1065], # AR-F407SmartBat, QioTekAdeptF407
754
- "STM32F4xx": [1115, 1116, 128, 83, 1078, 1143, 1125, 1044, 2501, 1184, 5811, 1085, 1064, 1187, 1177, 12, 1158, 9, 1003, 1190, 5800, 13, 135, 20, 1530, 1067, 1068, 1180, 1137, 1099, 1157, 1119, 5401, 1081, 1059, 1412, 1169, 122, 5406, 1030, 1422, 11, 1038, 1019, 125, 1014, 1054, 127, 6101, 1161, 1150, 88, 3, 1002, 131, 137, 133, 1155, 1140, 1096, 1076, 1107, 1021, 1417, 124, 1052, 1055, 1034, 1095, 1201, 130, 1197, 134, 5271, 1135, 1106, 1082, 1136, 1500, 1504, 1011, 6001, 6002, 6000, 5251, 212, 213, 1151, 1152, 1154, 1910, 1351], # ACNS-CM4Pilot, ACNS-F405AIO, airbotf4, ARK_CANNODE, AtomRCF405NAVI, ATOMRCF405NAVI-Deluxe, BETAFPV-F405, BirdCANdy, BOTWINGF405, BrahmaF4, BROTHERHOBBYF405v3, C-RTK2-HP, CarbonixF405, CORVON405V2_1, CrazyF405, crazyflie2, CSKY405, CUAV-Pixhack-v3, CubeBlack, CubeGreen-solo, CubePurple, CubeSolo, fmuv2, fmuv3, mRoX21, Pixhawk1, Pixhawk1-1M, skyviper-f412-rev1, skyviper-journey, skyviper-v2450, CubeBlack+, DAKEFPVF405, DroneerF405, DrotekP3Pro, F35Lightning, F4BY, F4BY_F427, FlyingMoonF407, FlyingMoonF427, FlywooF405HD-AIOv2, FlywooF405Pro, FlywooF405S-AIO, FoxeerF405v2, HEEWING-F405, HEEWING-F405v2, HolybroF4_PMU, JHEM_JHEF405, JHEMCU-GSF405A, JHEMCU-GSF405A-RX2, JHEMCUF405PRO, JHEMCUF405WING, KakuteF4, KakuteF4-Wing, KakuteF4Mini, LongBowF405WING, luminousbee4, Pixracer, MambaF405-2022, MambaF405v2, MatekF405, MatekF405-STD, MatekF405-CAN, MatekF405-TE, MatekF405-Wing, MFE_POS3_CAN, MicoAir405Mini, MicoAir405v2, mindpx-v2, mini-pix, omnibusf4, omnibusf4pro, omnibusf4pro-one, omnibusf4v6, OmnibusNanoV6, OrqaF405Pro, PixPilot-C3, PixPilot-V3, PixSurveyA1, PixSurveyA1-IND, QioTekZealotF427, RadiolinkF405, revo-mini, revo-mini-i2c, revo-mini-sd, Sierra-F405, Sierra-F412, Sierra-F9P, Sierra-PrecisionPoint, SkystarsF405v2, sparky2, SPEDIXF405, speedybeef4, SpeedyBeeF405AIO, SpeedyBeeF405Mini, SpeedyBeeF405WING, speedybeef4v3, speedybeef4v4, StellarF4, StellarF4V2, SuccexF4, sw-boom-f407, sw-nav-f405, sw-spar-f407, TBS_LUCID_PRO, thepeach-k1, thepeach-r1, VRBrain-v51, VRBrain-v52, VRBrain-v54, VRCore-v10, VRUBrain-v51
763
+ "STM32F4xx": [1115, 1116, 128, 83, 1078, 1143, 1125, 1044, 2501, 1184, 5811, 1085, 1064, 1187, 1177, 12, 1158, 9, 1003, 1190, 5800, 13, 135, 20, 1530, 1067, 1068, 1361, 1180, 1137, 1099, 1157, 1119, 5401, 1081, 1059, 1412, 1169, 122, 5406, 1030, 1422, 11, 1038, 1019, 125, 1014, 1054, 127, 6101, 1161, 1150, 88, 3, 1002, 131, 137, 133, 1155, 1140, 1096, 1076, 1107, 1021, 1417, 124, 1052, 1055, 1034, 1095, 1201, 130, 1197, 134, 5271, 1135, 1106, 1082, 1136, 1500, 1504, 1011, 6001, 6002, 6000, 5251, 212, 213, 1151, 1152, 1154, 1910, 1351], # ACNS-CM4Pilot, ACNS-F405AIO, airbotf4, ARK_CANNODE, AtomRCF405NAVI, ATOMRCF405NAVI-Deluxe, BETAFPV-F405, BirdCANdy, BOTWINGF405, BrahmaF4, BROTHERHOBBYF405v3, C-RTK2-HP, CarbonixF405, CORVON405V2_1, CrazyF405, crazyflie2, CSKY405, CUAV-Pixhack-v3, CubeBlack, CubeGreen-solo, CubePurple, CubeSolo, fmuv2, fmuv3, mRoX21, Pixhawk1, Pixhawk1-1M, skyviper-f412-rev1, skyviper-journey, skyviper-v2450, CubeBlack+, DAKEFPVF405, DroneerF405, DrotekP3Pro, F35Lightning, F4BY, F4BY_F427, FlyingMoonF407, FlyingMoonF427, FlysparkF4, FlywooF405HD-AIOv2, FlywooF405Pro, FlywooF405S-AIO, FoxeerF405v2, HEEWING-F405, HEEWING-F405v2, HolybroF4_PMU, JHEM_JHEF405, JHEMCU-GSF405A, JHEMCU-GSF405A-RX2, JHEMCUF405PRO, JHEMCUF405WING, KakuteF4, KakuteF4-Wing, KakuteF4Mini, LongBowF405WING, luminousbee4, Pixracer, MambaF405-2022, MambaF405v2, MatekF405, MatekF405-STD, MatekF405-CAN, MatekF405-TE, MatekF405-Wing, MFE_POS3_CAN, MicoAir405Mini, MicoAir405v2, mindpx-v2, mini-pix, omnibusf4, omnibusf4pro, omnibusf4pro-one, omnibusf4v6, OmnibusNanoV6, OrqaF405Pro, PixPilot-C3, PixPilot-V3, PixSurveyA1, PixSurveyA1-IND, QioTekZealotF427, RadiolinkF405, revo-mini, revo-mini-i2c, revo-mini-sd, Sierra-F405, Sierra-F412, Sierra-F9P, Sierra-PrecisionPoint, SkystarsF405v2, sparky2, SPEDIXF405, speedybeef4, SpeedyBeeF405AIO, SpeedyBeeF405Mini, SpeedyBeeF405WING, speedybeef4v3, speedybeef4v4, StellarF4, StellarF4V2, SuccexF4, sw-boom-f407, sw-nav-f405, sw-spar-f407, TBS_LUCID_PRO, thepeach-k1, thepeach-r1, VRBrain-v51, VRBrain-v52, VRBrain-v54, VRCore-v10, VRUBrain-v51
755
764
  "STM32F7xx": [55, 1026, 1057, 1164, 1117, 1163, 50, 120, 1027, 1042, 1028, 1501, 1084, 123, 145, 4500, 143, 188, 41775, 141, 136, 1222, 121, 1131, 51, 1008, 1410, 1074], # AIRLink, BeastF7, BeastF7v2, BlitzF745, BlitzF745AIO, BlitzMiniF745, CUAVv5, CUAVv5Nano, fmuv5, PH4-mini, Pix32v5, Pixhawk4, Swan-K1, TBS-Colibri-F7, CubeYellow, FlywooF745, FlywooF745Nano, FreeflyRTK, GEPRCF745BTHD, JFB100, KakuteF7, KakuteF7Mini, LumenierLUXF765-NDAA, MatekF765-SE, MatekF765-Wing, MazzyStarDrone, modalai_fc-v1, mRoControlZeroF7, mRoX21-777, MUPilot, OMNIBUSF7V2, PixFlamingo-F767, Pixhawk5X, R9Pilot, RadiolinkPIX6, ReaperF745
756
- "STM32H7xx": [1124, 7120, 1198, 4300, 7110, 2024, 5200, 1146, 5210, 59, 58, 57, 1025, 1056, 1162, 1168, 1148, 5810, 1182, 1156, 1189, 7000, 1009, 7001, 7002, 1010, 1079, 140, 1033, 1063, 1069, 1409, 1070, 1193, 1194, 1061, 139, 1531, 1112, 1181, 1089, 1502, 1071, 146, 1043, 1173, 1110, 1411, 1048, 1105, 1058, 1315, 1029, 1073, 1013, 1149, 2000, 1166, 1176, 1179, 1022, 1023, 1024, 1015, 1017, 1188, 1183, 1159, 1191, 1204, 1032, 56, 53, 1408, 1083, 1160, 6104, 1036, 1118, 1102, 1111, 1167, 1195, 1123, 2714, 1075, 1196, 1060, 1108, 1503, 2005, 6110, 5250, 5253, 1138, 5230, 7100, 1174, 1234, 1113, 1127, 1141, 1144, 5600], # 3DRControlZeroG, AcctonGodwit_GA1, AEDROXH7, AeroCogito-H7Digital, AEROFOX-H7, AET-H743-Basic, Airvolute-DCS2, AnyleafH7, Aocoda-RC-H743Dual, ARK_FPV, ARK_PI6X, ARKV6X, BeastH7, BeastH7v2, BlitzH743Pro, BlitzWingH743, BotBloxDroneNet, BROTHERHOBBYH743, CBU-H7-LC-Stamp, CBU-H7-Stamp, CORVON743V1, CUAV-7-Nano, CUAV-Nora, CUAV-V6X-v2, CUAV-X25-EVO, CUAV-X7, CubeNode, CubeOrange, CubeOrange-joey, CubeOrangePlus, CubeRedPrimary, CubeRedPrimary-PPPGW, CubeRedSecondary, CubeRedSecondary-IO, DAKEFPVH743, DAKEFPVH743Pro, DevEBoxH7v2, Durandal, NucleoH743, NucleoH755, F4BY_H743, FlyingMoonH743, FlywooH743Pro, FoxeerH743v1, GEPRC_TAKER_H743, GreenSightUltraBlue, H757I_EVAL, H757I_EVAL_intf, Here4AP, Here4FC, IFLIGHT_2RAW_H7, JFB110, JHEMCU-H743HD, KakuteH7, KakuteH7v2, KakuteH7-Wing, KakuteH7Mini, KakuteH7Mini-Nand, kha_eth, luminousbee5, MambaH743v4, MatekH743, MatekH7A3, MFT-SEMA100, MicoAir743, MicoAir743-AIO, MicoAir743v2, mRoControlZeroClassic, mRoControlZeroH7, mRoControlZeroOEMH7, mRoCZeroOEMH7, mRoNexus, mRoPixracerPro, NarinFC-H5, NarinFC-H7, NxtPX4v2, ORBITH743, OrqaH7QuadCore, PixC4-Jetson, Pixhawk6C, Pixhawk6X, Pixhawk6X-PPPGW, PixPilot-V6, PixPilot-V6PRO, PixSurveyA2-IND, QioTekZealotH743, RADIX2HD, rFCU, SDMODELH7V1, SDMODELH7V2, SequreH743, SIYI_N7, SkySakuraH743, SkystarsH7HD, SkystarsH7HDv2, SPEDIXH743, SPRacingH7, SPRacingH7RF, StellarH7V2, SULILGH7-P1-P2, SVehicle-E2, TBS_LUCID_H7, TBS_LUCID_H7_WING, TMotorH743, uav-dev-fc-um982, VUAV-V7pro, X-MAV-AP-H743v2, YARIV6X, YJUAV_A6, YJUAV_A6SE, YJUAV_A6SE_H743, YJUAV_A6Ultra, ZeroOneX6, ZeroOneX6_Air
765
+ "STM32H7xx": [1124, 7120, 1198, 4300, 7110, 2024, 5200, 1146, 5210, 59, 58, 57, 1025, 1056, 1162, 1168, 1148, 5810, 1182, 1156, 1189, 7000, 1009, 7001, 7002, 1010, 1079, 140, 1033, 1063, 1069, 1409, 1070, 1193, 1194, 1061, 139, 1531, 1112, 1181, 1089, 1502, 1071, 146, 1043, 1173, 1110, 1411, 1048, 1105, 1058, 1315, 1029, 1073, 1013, 1149, 2000, 1166, 1176, 1179, 1022, 1023, 1024, 1015, 1017, 1188, 1183, 1199, 1159, 1191, 1204, 1032, 56, 53, 1408, 1083, 1160, 6104, 1036, 1118, 1102, 1111, 1167, 1195, 1123, 2714, 1075, 1196, 1060, 1108, 1503, 2005, 6110, 5250, 5253, 5254, 1138, 5230, 7100, 1174, 1234, 1113, 1127, 1141, 1144, 5600], # 3DRControlZeroG, AcctonGodwit_GA1, AEDROXH7, AeroCogito-H7Digital, AEROFOX-H7, AET-H743-Basic, Airvolute-DCS2, AnyleafH7, Aocoda-RC-H743Dual, ARK_FPV, ARK_PI6X, ARKV6X, BeastH7, BeastH7v2, BlitzH743Pro, BlitzWingH743, BotBloxDroneNet, BROTHERHOBBYH743, CBU-H7-LC-Stamp, CBU-H7-Stamp, CORVON743V1, CUAV-7-Nano, CUAV-Nora, CUAV-V6X-v2, CUAV-X25-EVO, CUAV-X7, CubeNode, CubeOrange, CubeOrange-joey, CubeOrangePlus, CubeRedPrimary, CubeRedPrimary-PPPGW, CubeRedSecondary, CubeRedSecondary-IO, DAKEFPVH743, DAKEFPVH743Pro, DevEBoxH7v2, Durandal, NucleoH743, NucleoH755, F4BY_H743, FlyingMoonH743, FlywooH743Pro, FoxeerH743v1, GEPRC_TAKER_H743, GreenSightUltraBlue, H757I_EVAL, H757I_EVAL_intf, Here4AP, Here4FC, IFLIGHT_2RAW_H7, JFB110, JHEMCU-H743HD, KakuteH7, KakuteH7v2, KakuteH7-Wing, KakuteH7Mini, KakuteH7Mini-Nand, kha_eth, luminousbee5, MambaH743v4, MatekH743, MatekH7A3, MFT-SEMA100, MicoAir743, MicoAir743-AIO, MicoAir743v2, mRoControlZeroClassic, mRoControlZeroH7, mRoControlZeroOEMH7, mRoCZeroOEMH7, mRoNexus, mRoPixracerPro, NarinFC-H5, NarinFC-H7, NarinFC-X3, NxtPX4v2, ORBITH743, OrqaH7QuadCore, PixC4-Jetson, Pixhawk6C, Pixhawk6X, Pixhawk6X-PPPGW, PixPilot-V6, PixPilot-V6PRO, PixSurveyA2-IND, QioTekZealotH743, RADIX2HD, rFCU, SDMODELH7V1, SDMODELH7V2, SequreH743, SIYI_N7, SkySakuraH743, SkystarsH7HD, SkystarsH7HDv2, SPEDIXH743, SPRacingH7, SPRacingH7RF, StellarH7V2, SULILGH7-P1-P2, SVehicle-E2, TBS_LUCID_H7, TBS_LUCID_H7_WING, TBS_LUCID_H7_WING_AIO, TMotorH743, uav-dev-fc-um982, VUAV-V7pro, X-MAV-AP-H743v2, YARIV6X, YJUAV_A6, YJUAV_A6SE, YJUAV_A6SE_H743, YJUAV_A6Ultra, ZeroOneX6, ZeroOneX6_Air
757
766
  "STM32L476": [1051], # Nucleo-L476
758
767
  "STM32L496": [1047], # Nucleo-L496
759
768
  "STM32L4xx": [1090], # PixFlamingo
@@ -1,7 +1,7 @@
1
1
  """
2
2
  Data model for motor test functionality.
3
3
 
4
- This file is part of Ardupilot methodic configurator. https://github.com/ArduPilot/MethodicConfigurator
4
+ This file is part of ArduPilot Methodic Configurator. https://github.com/ArduPilot/MethodicConfigurator
5
5
 
6
6
  SPDX-FileCopyrightText: 2024-2025 Amilcar do Carmo Lucas <amilcar.lucas@iav.de>
7
7