import { i18n } from "../localization"; import semver from "semver"; import { isExpertModeEnabled } from "../utils/isExportModeEnabled"; import GUI, { TABS } from "../gui"; import { have_sensor } from "../sensor_helpers"; import { mspHelper } from "../msp/MSPHelper"; import FC from "../fc"; import MSP from "../msp"; import Model from "../model"; import MSPCodes from "../msp/MSPCodes"; import { API_VERSION_1_45, API_VERSION_1_46, API_VERSION_1_47 } from "../data_storage"; import { gui_log } from "../gui_log"; import $ from "jquery"; import { ispConnected } from "../utils/connection"; const setup = { yaw_fix: 0.0, }; setup.initialize = function (callback) { const self = this; if (GUI.active_tab != "setup") { GUI.active_tab = "setup"; } function load_status() { MSP.send_message(MSPCodes.MSP_STATUS_EX, false, false, load_mixer_config); } function load_mixer_config() { MSP.send_message(MSPCodes.MSP_MIXER_CONFIG, false, false, load_html); } function load_html() { $("#content").load("./tabs/setup.html", process_html); } MSP.send_message(MSPCodes.MSP_ACC_TRIM, false, false, load_status); function process_html() { // translate to user-selected language i18n.localizePage(); // initialize 3D Model self.initModel(); // set roll in interactive block $("span.roll").text(i18n.getMessage("initialSetupAttitude", [0])); // set pitch in interactive block $("span.pitch").text(i18n.getMessage("initialSetupAttitude", [0])); // set heading in interactive block $("span.heading").text(i18n.getMessage("initialSetupAttitude", [0])); // check if we have accelerometer and magnetometer if (!have_sensor(FC.CONFIG.activeSensors, "acc")) { $("a.calibrateAccel").addClass("disabled"); $("default_btn").addClass("disabled"); } if (!have_sensor(FC.CONFIG.activeSensors, "mag")) { $("a.calibrateMag").addClass("disabled"); $("default_btn").addClass("disabled"); } self.initializeInstruments(); $("#arming-disable-flag").attr("title", i18n.getMessage("initialSetupArmingDisableFlagsTooltip")); if (isExpertModeEnabled()) { $(".initialSetupRebootBootloader").show(); } else { $(".initialSetupRebootBootloader").hide(); } $("a.rebootBootloader").click(function () { const buffer = []; buffer.push( FC.boardHasFlashBootloader() ? mspHelper.REBOOT_TYPES.BOOTLOADER_FLASH : mspHelper.REBOOT_TYPES.BOOTLOADER, ); MSP.send_message(MSPCodes.MSP_SET_REBOOT, buffer, false); }); // UI Hooks $("a.calibrateAccel").click(function () { const _self = $(this); if (!_self.hasClass("calibrating")) { _self.addClass("calibrating"); // During this period MCU won't be able to process any serial commands because its locked in a for/while loop // until this operation finishes, sending more commands through data_poll() will result in serial buffer overflow GUI.interval_pause("setup_data_pull"); MSP.send_message(MSPCodes.MSP_ACC_CALIBRATION, false, false, function () { gui_log(i18n.getMessage("initialSetupAccelCalibStarted")); $("#accel_calib_running").show(); $("#accel_calib_rest").hide(); }); GUI.timeout_add( "button_reset", function () { GUI.interval_resume("setup_data_pull"); gui_log(i18n.getMessage("initialSetupAccelCalibEnded")); _self.removeClass("calibrating"); $("#accel_calib_running").hide(); $("#accel_calib_rest").show(); }, 2000, ); } }); $("a.calibrateMag").click(function () { const _self = $(this); if (!_self.hasClass("calibrating") && !_self.hasClass("disabled")) { _self.addClass("calibrating"); MSP.send_message(MSPCodes.MSP_MAG_CALIBRATION, false, false, function () { gui_log(i18n.getMessage("initialSetupMagCalibStarted")); $("#mag_calib_running").show(); $("#mag_calib_rest").hide(); }); function magCalibResetButton() { gui_log(i18n.getMessage("initialSetupMagCalibEnded")); _self.removeClass("calibrating"); $("#mag_calib_running").hide(); $("#mag_calib_rest").show(); } if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) { let cycle = 0; const cycleMax = 45; const interval = 1000; const intervalId = setInterval(function () { if (cycle >= cycleMax || (FC.CONFIG.armingDisableFlags & (1 << 12)) === 0) { clearInterval(intervalId); magCalibResetButton(); } cycle++; }, interval); } else { GUI.timeout_add("button_reset", magCalibResetButton, 30000); } } }); const dialogConfirmReset = $(".dialogConfirmReset")[0]; $("a.resetSettings").click(function () { dialogConfirmReset.showModal(); }); $(".dialogConfirmReset-cancelbtn").click(function () { dialogConfirmReset.close(); }); $(".dialogConfirmReset-confirmbtn").click(function () { dialogConfirmReset.close(); MSP.send_message(MSPCodes.MSP_RESET_CONF, false, false, function () { gui_log(i18n.getMessage("initialSetupSettingsRestored")); GUI.tab_switch_cleanup(function () { TABS.setup.initialize(); }); }); }); // display current yaw fix value (important during tab re-initialization) $("div#interactive_block > a.reset").text(i18n.getMessage("initialSetupButtonResetZaxisValue", [self.yaw_fix])); // reset yaw button hook $("div#interactive_block > a.reset").click(function () { self.yaw_fix = FC.SENSOR_DATA.kinematics[2] * -1.0; $(this).text(i18n.getMessage("initialSetupButtonResetZaxisValue", [self.yaw_fix])); console.log(`YAW reset to 0 deg, fix: ${self.yaw_fix} deg`); }); // cached elements const bat_voltage_e = $(".bat-voltage"), bat_mah_drawn_e = $(".bat-mah-drawn"), bat_mah_drawing_e = $(".bat-mah-drawing"), rssi_e = $(".rssi"), cputemp_e = $(".cpu-temp"), arming_disable_flags_e = $(".arming-disable-flags"), gpsFix_e = $(".GPS_info span.colorToggle"), gpsSats_e = $(".gpsSats"), roll_e = $("dd.roll"), pitch_e = $("dd.pitch"), heading_e = $("dd.heading"), sonar_e = $(".sonarAltitude"), // Sensor info sensor_gyro_e = $(".sensor_gyro_hw"), sensor_acc_e = $(".sensor_acc_hw"), sensor_mag_e = $(".sensor_mag_hw"), sensor_baro_e = $(".sensor_baro_hw"), sensor_sonar_e = $(".sensor_sonar_hw"), // Firmware info msp_api_e = $(".api-version"), build_date_e = $(".build-date"), build_type_e = $(".build-type"), build_info_e = $(".build-info"), build_options_e = $(".build-options"); // DISARM FLAGS // We add all the arming/disarming flags available, and show/hide them if needed. // align with betaflight runtime_config.h armingDisableFlags_e const prepareDisarmFlags = function () { let disarmFlagElements = [ "NO_GYRO", "FAILSAFE", "RX_FAILSAFE", "NOT_DISARMED", "BOXFAILSAFE", "RUNAWAY_TAKEOFF", "CRASH_DETECTED", "THROTTLE", "ANGLE", "BOOT_GRACE_TIME", "NOPREARM", "LOAD", "CALIBRATING", "CLI", "CMS_MENU", "BST", "MSP", "PARALYZE", "GPS", "RESC", "RPMFILTER", // Introduced in 1.42 "REBOOT_REQUIRED", "DSHOT_BITBANG", // Introduced in 1.43 "ACC_CALIBRATION", "MOTOR_PROTOCOL", // 'ARM_SWITCH', // Needs to be the last element, since it's always activated if one of the others is active when arming ]; if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) { disarmFlagElements.splice(disarmFlagElements.indexOf("RPMFILTER"), 1, "DSHOT_TELEM"); } if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) { disarmFlagElements.splice(disarmFlagElements.indexOf("MOTOR_PROTOCOL"), 0, "CRASHFLIP"); } // Arming allowed flag arming_disable_flags_e.append( '', ); // Arming disabled flags for (let i = 0; i < FC.CONFIG.armingDisableCount; i++) { // All the known elements but the ARM_SWITCH (it must be always the last element) if (i < disarmFlagElements.length - 1) { const messageKey = `initialSetupArmingDisableFlagsTooltip${disarmFlagElements[i]}`; arming_disable_flags_e.append( ` ${i18n.getMessage( "initialSetupInfoBuildConfig", )}`; const buildLog = ` ${i18n.getMessage( "initialSetupInfoBuildLog", )}`; build_info_e.html(` ${i18n.getMessage( "initialSetupInfoBuildOptionList", )}`); build_info_e.html(`${buildConfig} ${buildLog}`); } else { build_info_e.html( supported ? i18n.getMessage("initialSetupNotOnline") : i18n.getMessage("initialSetupNoBuildInfo"), ); } }; const showBuildOptions = function () { const supported = ((semver.eq(FC.CONFIG.apiVersion, API_VERSION_1_45) && ispConnected()) || semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) && FC.CONFIG.buildOptions.length; if (supported) { let buildOptionList = `
`, ); // The ARM_SWITCH, always the last element } else if (i == FC.CONFIG.armingDisableCount - 1) { arming_disable_flags_e.append( ` `, ); // Unknown disarm flags } else { arming_disable_flags_e.append( ` `, ); } } }; const showSensorInfo = function () { const gyroElements = [ "AUTO", "NONE", "MPU6050", "L3G4200D", "MPU3050", "L3GD20", "MPU6000", "MPU6500", "MPU9250", "ICM20601", "ICM20602", "ICM20608G", "ICM20649", "ICM20689", "ICM42605", "ICM42688P", "BMI160", "BMI270", "LSM6DSO", "LSM6DSV16X", "VIRTUAL", ]; const accElements = [ "AUTO", "NONE", "ADXL345", "MPU6050", "MMA8452", "BMA280", "LSM303DLHC", "MPU6000", "MPU6500", "MPU9250", "ICM20601", "ICM20602", "ICM20608G", "ICM20649", "ICM20689", "ICM42605", "ICM42688P", "BMI160", "BMI270", "LSM6DSO", "LSM6DSV16X", "VIRTUAL", ]; const magElements = [ "DEFAULT", "NONE", "HMC5883", "AK8975", "AK8963", "QMC5883", "LIS2MDL", "LIS3MDL", "MPU925X_AK8963", "IST8310", ]; const baroElements = [ "DEFAULT", "NONE", "BMP085", "MS5611", "BMP280", "LPS", "QMP6988", "BMP388", "DPS310", "2SMPB_02B", "VIRTUAL", ]; const sonarElements = ["NONE", "HCSR04", "TFMINI", "TF02"]; // remove deprecated sensors or add new ones if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) { gyroElements.splice(gyroElements.indexOf("L3G4200D"), 1); gyroElements.splice(gyroElements.indexOf("MPU3050"), 1); gyroElements.splice(gyroElements.indexOf("LSM6DSV16X") + 1, 0, "IIM42653"); accElements.splice(accElements.indexOf("ADXL345"), 1); accElements.splice(accElements.indexOf("MMA8452"), 1); accElements.splice(accElements.indexOf("BMA280"), 1); accElements.splice(accElements.indexOf("LSM303DLHC"), 1); accElements.splice(accElements.indexOf("LSM6DSV16X") + 1, 0, "IIM42653"); } if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) { MSP.send_message(MSPCodes.MSP2_SENSOR_CONFIG_ACTIVE, false, false, function () { // Sensor info const textNA = i18n.getMessage("initialSetupNotInBuild"); const textDisabled = i18n.getMessage("initialSetupNotDetected"); if (FC.SENSOR_CONFIG_ACTIVE.gyro_hardware == 0xff) { sensor_gyro_e.text(textNA); } else if ( have_sensor(FC.CONFIG.activeSensors, "gyro") && FC.SENSOR_CONFIG_ACTIVE.gyro_hardware > 1 ) { sensor_gyro_e.text(gyroElements[FC.SENSOR_CONFIG_ACTIVE.gyro_hardware]); } else { sensor_gyro_e.text(textDisabled); } if (FC.SENSOR_CONFIG_ACTIVE.acc_hardware == 0xff) { sensor_acc_e.text(textNA); } else if ( have_sensor(FC.CONFIG.activeSensors, "acc") && FC.SENSOR_CONFIG_ACTIVE.acc_hardware > 1 ) { sensor_acc_e.text(accElements[FC.SENSOR_CONFIG_ACTIVE.acc_hardware]); } else { sensor_acc_e.text(textDisabled); } if (FC.SENSOR_CONFIG_ACTIVE.baro_hardware == 0xff) { sensor_baro_e.text(textNA); } else if ( have_sensor(FC.CONFIG.activeSensors, "baro") && FC.SENSOR_CONFIG_ACTIVE.baro_hardware > 1 ) { sensor_baro_e.text(baroElements[FC.SENSOR_CONFIG_ACTIVE.baro_hardware]); } else { sensor_baro_e.text(textDisabled); } if (FC.SENSOR_CONFIG_ACTIVE.mag_hardware == 0xff) { sensor_mag_e.text(textNA); } else if ( have_sensor(FC.CONFIG.activeSensors, "mag") && FC.SENSOR_CONFIG_ACTIVE.mag_hardware > 1 ) { sensor_mag_e.text(magElements[FC.SENSOR_CONFIG_ACTIVE.mag_hardware]); } else { sensor_mag_e.text(textDisabled); } if (FC.SENSOR_CONFIG_ACTIVE.sonar_hardware == 0xff) { sensor_sonar_e.text(textNA); } else if ( have_sensor(FC.CONFIG.activeSensors, "sonar") && FC.SENSOR_CONFIG_ACTIVE.sonar_hardware > 0 ) { sensor_sonar_e.text(sonarElements[FC.SENSOR_CONFIG_ACTIVE.sonar_hardware]); } else { sensor_sonar_e.text(textDisabled); } }); } }; function showDialogBuildInfo(title, message) { const dialog = $(".dialogBuildInfo")[0]; $(".dialogBuildInfo-title").html(title); $(".dialogBuildInfo-content").html(message); if (!dialog.hasAttribute("open")) { dialog.showModal(); $(".dialogBuildInfo-closebtn").on("click", function () { dialog.close(); }); } } const showBuildInfo = function () { const supported = FC.CONFIG.buildKey.length === 32; if (supported && ispConnected()) { const buildRoot = `https://build.betaflight.com/api/builds/${FC.CONFIG.buildKey}`; const buildConfig = `