import { i18n } from "../localization"; import GUI from '../gui'; import { reinitializeConnection } from "../serial_backend"; import { mspHelper } from "../msp/MSPHelper"; import MSP from "../msp"; import FC from "../fc"; import MSPCodes from "../msp/MSPCodes"; import adjustBoxNameIfPeripheralWithModeID from "../peripherals"; import { API_VERSION_1_43, API_VERSION_1_44, API_VERSION_1_45 } from "../data_storage"; import { gui_log } from "../gui_log"; const failsafe = {}; failsafe.initialize = function (callback) { if (GUI.active_tab != 'failsafe') { GUI.active_tab = 'failsafe'; } function load_rx_config() { MSP.send_message(MSPCodes.MSP_RX_CONFIG, false, false, load_failssafe_config); } function load_failssafe_config() { MSP.send_message(MSPCodes.MSP_FAILSAFE_CONFIG, false, false, load_rxfail_config); } function load_rxfail_config() { MSP.send_message(MSPCodes.MSP_RXFAIL_CONFIG, false, false, load_gps_rescue); } function load_gps_rescue() { MSP.send_message(MSPCodes.MSP_GPS_RESCUE, false, false, get_box_names); } function get_box_names() { MSP.send_message(MSPCodes.MSP_BOXNAMES, false, false, get_mode_ranges); } function get_mode_ranges() { MSP.send_message(MSPCodes.MSP_MODE_RANGES, false, false, get_box_ids); } function get_box_ids() { MSP.send_message(MSPCodes.MSP_BOXIDS, false, false, get_ports_config); } function get_ports_config() { mspHelper.loadSerialConfig(get_rc_data); } function get_rc_data() { MSP.send_message(MSPCodes.MSP_RC, false, false, get_rssi_config); } function get_rssi_config() { MSP.send_message(MSPCodes.MSP_RSSI_CONFIG, false, false, load_feature_config); } function load_feature_config() { MSP.send_message(MSPCodes.MSP_FEATURE_CONFIG, false, false, load_motor_config); } function load_motor_config() { MSP.send_message(MSPCodes.MSP_MOTOR_CONFIG, false, false, load_gps_config); } function load_gps_config() { MSP.send_message(MSPCodes.MSP_GPS_CONFIG, false, false, load_html); } function load_html() { $('#content').load("./tabs/failsafe.html", process_html); } load_rx_config(); function process_html() { // fill stage 2 fields function toggleStage2(doShow) { if (doShow) { $('div.stage2').show(); } else { $('div.stage2').hide(); } } // FIXME cleanup oldpane html and css const oldPane = $('div.oldpane'); oldPane.prop("disabled", true); oldPane.hide(); // generate labels for assigned aux modes const auxAssignment = []; let element; for (let channelIndex = 0; channelIndex < FC.RC.active_channels - 4; channelIndex++) { auxAssignment.push(""); } if (typeof FC.RSSI_CONFIG.channel !== 'undefined') { auxAssignment[FC.RSSI_CONFIG.channel - 5] += "" + "RSSI" + ""; // Aux channels start at 5 in backend so we have to substract 5 } for (let modeIndex = 0; modeIndex < FC.AUX_CONFIG.length; modeIndex++) { const modeId = FC.AUX_CONFIG_IDS[modeIndex]; // scan mode ranges to find assignments for (let modeRangeIndex = 0; modeRangeIndex < FC.MODE_RANGES.length; modeRangeIndex++) { const modeRange = FC.MODE_RANGES[modeRangeIndex]; if (modeRange.id != modeId) { continue; } const range = modeRange.range; if (range.start >= range.end) { continue; // invalid! } // Search for the real name if it belongs to a peripheral let modeName = FC.AUX_CONFIG[modeIndex]; modeName = adjustBoxNameIfPeripheralWithModeID(modeId, modeName); auxAssignment[modeRange.auxChannelIndex] += `${modeName}`; } } // generate full channel list const channelNames = [ i18n.getMessage('controlAxisRoll'), i18n.getMessage('controlAxisPitch'), i18n.getMessage('controlAxisYaw'), i18n.getMessage('controlAxisThrottle'), ], fullChannels_e = $('div.activechannellist'); let aux_index = 1, aux_assignment_index = 0; for (let i = 0; i < FC.RXFAIL_CONFIG.length; i++) { if (i < channelNames.length) { fullChannels_e.append(`\
\
\ ${channelNames[i]}\
\
\ \
\
\
\ `); } else { const messageKey = `controlAxisAux${aux_index++}`; fullChannels_e.append(`\
\
\ ${i18n.getMessage(messageKey)}\ ${auxAssignment[aux_assignment_index++]}\
\
\ \
\
\
\ `); } } const channel_mode_array = []; $('.number', fullChannels_e).each(function () { channel_mode_array.push($('select.aux_set' , this)); }); const channel_value_array = []; $('.number', fullChannels_e).each(function () { channel_value_array.push($('input[name="aux_value"]' , this)); }); const channelMode = $('select.aux_set'); const channelValue = $('input[name="aux_value"]'); // UI hooks channelMode.change(function () { const currentMode = parseInt($(this).val()); const i = parseInt($(this).prop("id")); FC.RXFAIL_CONFIG[i].mode = currentMode; if (currentMode == 2) { channel_value_array[i].prop("disabled", false); channel_value_array[i].show(); } else { channel_value_array[i].prop("disabled", true); channel_value_array[i].hide(); } }); // UI hooks channelValue.change(function () { const i = parseInt($(this).prop("id")); FC.RXFAIL_CONFIG[i].value = parseInt($(this).val()); }); // fill stage 1 Valid Pulse Range Settings $('input[name="rx_min_usec"]').val(FC.RX_CONFIG.rx_min_usec); $('input[name="rx_max_usec"]').val(FC.RX_CONFIG.rx_max_usec); // fill fallback settings (mode and value) for all channels for (let i = 0; i < FC.RXFAIL_CONFIG.length; i++) { channel_value_array[i].val(FC.RXFAIL_CONFIG[i].value); channel_mode_array[i].val(FC.RXFAIL_CONFIG[i].mode); channel_mode_array[i].change(); } FC.FEATURE_CONFIG.features.generateElements($('.tab-failsafe .featuresNew')); $('tbody.rxFailsafe').hide(); toggleStage2(true); $('input[name="failsafe_throttle"]').val(FC.FAILSAFE_CONFIG.failsafe_throttle); $('input[name="failsafe_off_delay"]').val((FC.FAILSAFE_CONFIG.failsafe_off_delay / 10.0).toFixed(1)); $('input[name="failsafe_throttle_low_delay"]').val((FC.FAILSAFE_CONFIG.failsafe_throttle_low_delay / 10.0).toFixed(1)); $('input[name="failsafe_delay"]').val((FC.FAILSAFE_CONFIG.failsafe_delay / 10.0).toFixed(1)); // set stage 2 failsafe procedure $('input[type="radio"].procedure').change(function () { // Disable all the settings $('.proceduresettings :input').attr('disabled',true); // Enable only selected $(this).parent().parent().find(':input').attr('disabled',false); }); switch(FC.FAILSAFE_CONFIG.failsafe_procedure) { case 0: element = $('input[id="land"]') ; element.prop('checked', true); element.change(); break; case 1: element = $('input[id="drop"]'); element.prop('checked', true); element.change(); break; case 2: element = $('input[id="gps_rescue"]'); element.prop('checked', true); element.change(); break; } // Sort the element, if need to group, do it by lexical sort, ie. by naming of (the translated) selection text $('#failsafeSwitchSelect').sortSelect(); // `failsafe_kill_switch` has been renamed to `failsafe_switch_mode`. // It is backwards compatible with `failsafe_kill_switch` $('select[name="failsafe_switch_mode"]').val(FC.FAILSAFE_CONFIG.failsafe_switch_mode); $('div.kill_switch').hide(); // The GPS Rescue tab is only available for 1.40 or later, and the parameters for 1.41 // Load GPS Rescue parameters $('input[name="gps_rescue_angle"]').val(FC.GPS_RESCUE.angle); $('input[name="gps_rescue_initial_altitude"]').val(FC.GPS_RESCUE.initialAltitudeM); $('input[name="gps_rescue_descent_distance"]').val(FC.GPS_RESCUE.descentDistanceM); $('input[name="gps_rescue_ground_speed"]').val((FC.GPS_RESCUE.rescueGroundspeed / 100).toFixed(2)); $('input[name="gps_rescue_throttle_min"]').val(FC.GPS_RESCUE.throttleMin); $('input[name="gps_rescue_throttle_max"]').val(FC.GPS_RESCUE.throttleMax); $('input[name="gps_rescue_throttle_hover"]').val(FC.GPS_RESCUE.throttleHover); $('input[name="gps_rescue_min_sats"]').val(FC.GPS_RESCUE.minSats); // Sort the element, if need to group, do it by lexical sort, ie. by naming of (the translated) selection text $('#failsafeGpsRescueItemSanitySelect').sortSelect(); $('select[name="gps_rescue_sanity_checks"]').val(FC.GPS_RESCUE.sanityChecks); // Sort the element, if need to group, do it by lexical sort, ie. by naming of (the translated) selection text $('#failsafeGpsRescueItemAltitudeSelect').sortSelect(); if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_43)) { $('input[name="gps_rescue_ascend_rate"]').val((FC.GPS_RESCUE.ascendRate / 100).toFixed(2)); $('input[name="gps_rescue_descend_rate"]').val((FC.GPS_RESCUE.descendRate / 100).toFixed(2)); $('input[name="gps_rescue_allow_arming_without_fix"]').prop('checked', FC.GPS_RESCUE.allowArmingWithoutFix > 0); $('select[name="gps_rescue_altitude_mode"]').val(FC.GPS_RESCUE.altitudeMode); } else { $('input[name="gps_rescue_ascend_rate"]').closest('.number').hide(); $('input[name="gps_rescue_descend_rate"]').closest('.number').hide(); $('input[name="gps_rescue_allow_arming_without_fix"]').closest('.number').hide(); $('select[name="gps_rescue_altitude_mode"]').closest('.number').hide(); } if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) { $('input[name="gps_rescue_min_dth"]').val(FC.GPS_RESCUE.minRescueDth); } else { $('input[name="gps_rescue_min_dth"]').closest('.number').hide(); } if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_45)) { $('input[name="gps_rescue_min_dth"]').attr("min", 20); } $('a.save').click(function () { // gather data that doesn't have automatic change event bound FC.FEATURE_CONFIG.features.updateData($('input[name="FAILSAFE"]')); FC.RX_CONFIG.rx_min_usec = parseInt($('input[name="rx_min_usec"]').val()); FC.RX_CONFIG.rx_max_usec = parseInt($('input[name="rx_max_usec"]').val()); FC.FAILSAFE_CONFIG.failsafe_throttle = parseInt($('input[name="failsafe_throttle"]').val()); FC.FAILSAFE_CONFIG.failsafe_off_delay = Math.round(10.0 * parseFloat($('input[name="failsafe_off_delay"]').val())); FC.FAILSAFE_CONFIG.failsafe_throttle_low_delay = Math.round(10.0 * parseFloat($('input[name="failsafe_throttle_low_delay"]').val())); FC.FAILSAFE_CONFIG.failsafe_delay = Math.round(10.0 * parseFloat($('input[name="failsafe_delay"]').val())); if( $('input[id="land"]').is(':checked')) { FC.FAILSAFE_CONFIG.failsafe_procedure = 0; } else if( $('input[id="drop"]').is(':checked')) { FC.FAILSAFE_CONFIG.failsafe_procedure = 1; } else if( $('input[id="gps_rescue"]').is(':checked')) { FC.FAILSAFE_CONFIG.failsafe_procedure = 2; } FC.FAILSAFE_CONFIG.failsafe_switch_mode = $('select[name="failsafe_switch_mode"]').val(); // Load GPS Rescue parameters FC.GPS_RESCUE.angle = $('input[name="gps_rescue_angle"]').val(); FC.GPS_RESCUE.initialAltitudeM = $('input[name="gps_rescue_initial_altitude"]').val(); FC.GPS_RESCUE.descentDistanceM = $('input[name="gps_rescue_descent_distance"]').val(); FC.GPS_RESCUE.rescueGroundspeed = $('input[name="gps_rescue_ground_speed"]').val() * 100; FC.GPS_RESCUE.throttleMin = $('input[name="gps_rescue_throttle_min"]').val(); FC.GPS_RESCUE.throttleMax = $('input[name="gps_rescue_throttle_max"]').val(); FC.GPS_RESCUE.throttleHover = $('input[name="gps_rescue_throttle_hover"]').val(); FC.GPS_RESCUE.minSats = $('input[name="gps_rescue_min_sats"]').val(); FC.GPS_RESCUE.sanityChecks = $('select[name="gps_rescue_sanity_checks"]').val(); if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_43)) { FC.GPS_RESCUE.ascendRate = $('input[name="gps_rescue_ascend_rate"]').val() * 100; FC.GPS_RESCUE.descendRate = $('input[name="gps_rescue_descend_rate"]').val() * 100; FC.GPS_RESCUE.allowArmingWithoutFix = $('input[name="gps_rescue_allow_arming_without_fix"]').prop('checked') ? 1 : 0; FC.GPS_RESCUE.altitudeMode = parseInt($('select[name="gps_rescue_altitude_mode"]').val()); } if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) { FC.GPS_RESCUE.minRescueDth = $('input[name="gps_rescue_min_dth"]').val(); } function save_failssafe_config() { MSP.send_message(MSPCodes.MSP_SET_FAILSAFE_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_FAILSAFE_CONFIG), false, save_rxfail_config); } function save_rxfail_config() { mspHelper.sendRxFailConfig(save_feature_config); } function save_feature_config() { MSP.send_message(MSPCodes.MSP_SET_FEATURE_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_FEATURE_CONFIG), false, save_gps_rescue); } function save_gps_rescue() { MSP.send_message(MSPCodes.MSP_SET_GPS_RESCUE, mspHelper.crunch(MSPCodes.MSP_SET_GPS_RESCUE), false, save_to_eeprom); } function save_to_eeprom() { MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, reboot); } function reboot() { gui_log(i18n.getMessage('configurationEepromSaved')); GUI.tab_switch_cleanup(function() { MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection); }); } MSP.send_message(MSPCodes.MSP_SET_RX_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_RX_CONFIG), false, save_failssafe_config); }); // translate to user-selected language i18n.localizePage(); // status data pulled via separate timer with static speed GUI.interval_add('status_pull', function status_pull() { MSP.send_message(MSPCodes.MSP_STATUS); }, 250, true); GUI.content_ready(callback); } }; failsafe.cleanup = function (callback) { if (callback) callback(); }; window.TABS.failsafe = failsafe; export { failsafe, };