mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-25 01:05:15 +03:00
680 lines
27 KiB
JavaScript
680 lines
27 KiB
JavaScript
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(
|
|
'<span id="initialSetupArmingAllowed" i18n="initialSetupArmingAllowed" style="display: none;"></span>',
|
|
);
|
|
|
|
// 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(
|
|
`<span id="initialSetupArmingDisableFlags${i}" class="cf_tip disarm-flag" title="${i18n.getMessage(
|
|
messageKey,
|
|
)}" style="display: none;">${disarmFlagElements[i]}</span>`,
|
|
);
|
|
|
|
// The ARM_SWITCH, always the last element
|
|
} else if (i == FC.CONFIG.armingDisableCount - 1) {
|
|
arming_disable_flags_e.append(
|
|
`<span id="initialSetupArmingDisableFlags${i}" class="cf_tip disarm-flag" title="${i18n.getMessage(
|
|
"initialSetupArmingDisableFlagsTooltipARM_SWITCH",
|
|
)}" style="display: none;">ARM_SWITCH</span>`,
|
|
);
|
|
|
|
// Unknown disarm flags
|
|
} else {
|
|
arming_disable_flags_e.append(
|
|
`<span id="initialSetupArmingDisableFlags${i}" class="disarm-flag" style="display: none;">${
|
|
i + 1
|
|
}</span>`,
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
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 = `<span class="buildInfoBtn" title="${i18n.getMessage(
|
|
"initialSetupInfoBuildConfig",
|
|
)}: ${buildRoot}/json">
|
|
<a href="${buildRoot}/json" target="_blank"><strong>${i18n.getMessage(
|
|
"initialSetupInfoBuildConfig",
|
|
)}</strong></a></span>`;
|
|
const buildLog = `<span class="buildInfoBtn" title="${i18n.getMessage(
|
|
"initialSetupInfoBuildLog",
|
|
)}: ${buildRoot}/log">
|
|
<a href="${buildRoot}/log" target="_blank"><strong>${i18n.getMessage(
|
|
"initialSetupInfoBuildLog",
|
|
)}</strong></a></span>`;
|
|
build_info_e.html(`<span class="buildInfoBtn" title="${i18n.getMessage(
|
|
"initialSetupInfoBuildOptions",
|
|
)}">
|
|
<a class="buildOptions" href=#"><strong>${i18n.getMessage(
|
|
"initialSetupInfoBuildOptionList",
|
|
)}</strong></a></span>`);
|
|
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 = `<div class="dialogBuildInfoGrid-container">`;
|
|
for (const buildOptionElement of FC.CONFIG.buildOptions) {
|
|
buildOptionList += `<div class="dialogBuildInfoGrid-item">${buildOptionElement}</div>`;
|
|
}
|
|
buildOptionList += `</div>`;
|
|
|
|
build_options_e.html(`<span class="buildInfoBtn" title="${i18n.getMessage(
|
|
"initialSetupInfoBuildOptions",
|
|
)}">
|
|
<a class="buildOptions" href=#"><strong>${i18n.getMessage(
|
|
"initialSetupInfoBuildOptionList",
|
|
)}</strong></a></span>`);
|
|
|
|
const buildOptions = `<span class="buildInfoBtn" title="${i18n.getMessage(
|
|
"initialSetupInfoBuildOptionList",
|
|
)}">
|
|
<a class="buildOptions" href=#"><strong>${i18n.getMessage(
|
|
"initialSetupInfoBuildOptions",
|
|
)}</strong></a></span>`;
|
|
|
|
build_options_e.html(buildOptions);
|
|
|
|
$("a.buildOptions").on("click", async function () {
|
|
showDialogBuildInfo(
|
|
`<h3>${i18n.getMessage("initialSetupInfoBuildOptionList")}</h3>`,
|
|
buildOptionList,
|
|
);
|
|
});
|
|
} else {
|
|
// should not happen, but just in case
|
|
build_options_e.html(`${i18n.getMessage("initialSetupNoBuildInfo")}`);
|
|
}
|
|
};
|
|
|
|
function showFirmwareInfo() {
|
|
// Firmware info
|
|
msp_api_e.text(FC.CONFIG.apiVersion);
|
|
build_date_e.text(FC.CONFIG.buildInfo);
|
|
|
|
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_45)) {
|
|
build_type_e.html(
|
|
FC.CONFIG.buildKey.length === 32
|
|
? i18n.getMessage("initialSetupInfoBuildCloud")
|
|
: i18n.getMessage("initialSetupInfoBuildLocal"),
|
|
);
|
|
showBuildInfo();
|
|
showBuildOptions();
|
|
}
|
|
}
|
|
|
|
function showNetworkStatus() {
|
|
const networkStatus = ispConnected();
|
|
|
|
let statusText = "";
|
|
|
|
const type = navigator.connection.effectiveType;
|
|
const downlink = navigator.connection.downlink;
|
|
const rtt = navigator.connection.rtt;
|
|
|
|
if (!networkStatus || !navigator.onLine || type === "none") {
|
|
statusText = i18n.getMessage("initialSetupNetworkInfoStatusOffline");
|
|
} else if (type === "slow-2g" || type === "2g" || downlink < 0.115 || rtt > 1000) {
|
|
statusText = i18n.getMessage("initialSetupNetworkInfoStatusSlow");
|
|
} else {
|
|
statusText = i18n.getMessage("initialSetupNetworkInfoStatusOnline");
|
|
}
|
|
|
|
$(".network-status").text(statusText);
|
|
$(".network-type").text(navigator.connection.effectiveType);
|
|
$(".network-downlink").text(`${navigator.connection.downlink} Mbps`);
|
|
$(".network-rtt").text(navigator.connection.rtt);
|
|
}
|
|
|
|
prepareDisarmFlags();
|
|
showSensorInfo();
|
|
showFirmwareInfo();
|
|
showNetworkStatus();
|
|
|
|
// Show Sonar info box if sensor exist
|
|
if (!have_sensor(FC.CONFIG.activeSensors, "sonar")) {
|
|
$(".sonarBox").hide();
|
|
}
|
|
|
|
function get_slow_data() {
|
|
// Status info is acquired in the background using update_live_status() in serial_backend.js
|
|
|
|
$("#initialSetupArmingAllowed").toggle(FC.CONFIG.armingDisableFlags === 0);
|
|
|
|
for (let i = 0; i < FC.CONFIG.armingDisableCount; i++) {
|
|
$(`#initialSetupArmingDisableFlags${i}`).css(
|
|
"display",
|
|
(FC.CONFIG.armingDisableFlags & (1 << i)) === 0 ? "none" : "inline-block",
|
|
);
|
|
}
|
|
|
|
// System info is acquired in the background using update_live_status() in serial_backend.js
|
|
|
|
bat_voltage_e.text(i18n.getMessage("initialSetupBatteryValue", [FC.ANALOG.voltage]));
|
|
bat_mah_drawn_e.text(i18n.getMessage("initialSetupBatteryMahValue", [FC.ANALOG.mAhdrawn]));
|
|
bat_mah_drawing_e.text(i18n.getMessage("initialSetupBatteryAValue", [FC.ANALOG.amperage.toFixed(2)]));
|
|
rssi_e.text(i18n.getMessage("initialSetupRSSIValue", [((FC.ANALOG.rssi / 1023) * 100).toFixed(0)]));
|
|
|
|
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46) && FC.CONFIG.cpuTemp) {
|
|
cputemp_e.html(`${FC.CONFIG.cpuTemp.toFixed(0)} ℃`);
|
|
} else {
|
|
cputemp_e.text(i18n.getMessage("initialSetupCpuTempNotSupported"));
|
|
}
|
|
|
|
// GPS info is acquired in the background using update_live_status() in serial_backend.js
|
|
gpsFix_e.text(FC.GPS_DATA.fix ? i18n.getMessage("gpsFixTrue") : i18n.getMessage("gpsFixFalse"));
|
|
gpsFix_e.toggleClass("ready", FC.GPS_DATA.fix != 0);
|
|
gpsSats_e.text(FC.GPS_DATA.numSat);
|
|
|
|
const lat = FC.GPS_DATA.lat / 10000000;
|
|
const lon = FC.GPS_DATA.lon / 10000000;
|
|
const url = `https://maps.google.com/?q=${lat},${lon}`;
|
|
const gpsUnitText = i18n.getMessage("gpsPositionUnit");
|
|
$(".GPS_info td.latLon a")
|
|
.prop("href", url)
|
|
.text(`${lat.toFixed(4)} / ${lon.toFixed(4)} ${gpsUnitText}`);
|
|
}
|
|
|
|
function get_fast_data() {
|
|
MSP.send_message(MSPCodes.MSP_ATTITUDE, false, false, function () {
|
|
roll_e.text(i18n.getMessage("initialSetupAttitude", [FC.SENSOR_DATA.kinematics[0]]));
|
|
pitch_e.text(i18n.getMessage("initialSetupAttitude", [FC.SENSOR_DATA.kinematics[1]]));
|
|
heading_e.text(i18n.getMessage("initialSetupAttitude", [FC.SENSOR_DATA.kinematics[2]]));
|
|
|
|
self.renderModel();
|
|
self.updateInstruments();
|
|
});
|
|
// get Sonar altitude if sensor exist
|
|
if (have_sensor(FC.CONFIG.activeSensors, "sonar")) {
|
|
MSP.send_message(MSPCodes.MSP_SONAR, false, false, function () {
|
|
sonar_e.text(`${FC.SENSOR_DATA.sonar.toFixed(1)} cm`);
|
|
});
|
|
}
|
|
}
|
|
|
|
GUI.interval_add("setup_data_pull_fast", get_fast_data, 33, true); // 30 fps
|
|
GUI.interval_add("setup_data_pull_slow", get_slow_data, 250, true); // 4 fps
|
|
|
|
GUI.content_ready(callback);
|
|
}
|
|
};
|
|
|
|
setup.initializeInstruments = function () {
|
|
const options = { size: 90, showBox: false, img_directory: "images/flightindicators/" };
|
|
const attitude = $.flightIndicator("#attitude", "attitude", options);
|
|
const heading = $.flightIndicator("#heading", "heading", options);
|
|
|
|
this.updateInstruments = function () {
|
|
attitude.setRoll(FC.SENSOR_DATA.kinematics[0]);
|
|
attitude.setPitch(FC.SENSOR_DATA.kinematics[1]);
|
|
heading.setHeading(FC.SENSOR_DATA.kinematics[2]);
|
|
};
|
|
};
|
|
|
|
setup.initModel = function () {
|
|
this.model = new Model($(".model-and-info #canvas_wrapper"), $(".model-and-info #canvas"));
|
|
|
|
$(window).on("resize", $.proxy(this.model.resize, this.model));
|
|
};
|
|
|
|
setup.renderModel = function () {
|
|
const x = FC.SENSOR_DATA.kinematics[1] * -1.0 * 0.017453292519943295,
|
|
y = (FC.SENSOR_DATA.kinematics[2] * -1.0 - this.yaw_fix) * 0.017453292519943295,
|
|
z = FC.SENSOR_DATA.kinematics[0] * -1.0 * 0.017453292519943295;
|
|
|
|
this.model.rotateTo(x, y, z);
|
|
};
|
|
|
|
setup.cleanup = function (callback) {
|
|
if (this.model) {
|
|
$(window).off("resize", $.proxy(this.model.resize, this.model));
|
|
this.model.dispose();
|
|
}
|
|
|
|
if (callback) callback();
|
|
};
|
|
|
|
TABS.setup = setup;
|
|
|
|
export { setup };
|