/*global $,helper,mspHelper,MSP,GUI,SERVO_RULES,MOTOR_RULES,MIXER_CONFIG,googleAnalytics,LOGIC_CONDITIONS,TABS,ServoMixRule*/ 'use strict'; TABS.mixer = {}; TABS.mixer.initialize = function (callback, scrollPosition) { let loadChainer = new MSPChainerClass(), saveChainer = new MSPChainerClass(), currentPlatform, currentMixerPreset, $servoMixTable, $servoMixTableBody, $motorMixTable, $motorMixTableBody, modal, motorWizardModal; if (GUI.active_tab != 'mixer') { GUI.active_tab = 'mixer'; googleAnalytics.sendAppView('Mixer'); } loadChainer.setChain([ mspHelper.loadMixerConfig, mspHelper.loadMotors, mspHelper.loadServoMixRules, mspHelper.loadMotorMixRules, mspHelper.loadOutputMapping, mspHelper.loadLogicConditions ]); loadChainer.setExitPoint(loadHtml); loadChainer.execute(); saveChainer.setChain([ mspHelper.saveMixerConfig, mspHelper.sendServoMixer, mspHelper.sendMotorMixer, mspHelper.saveToEeprom ]); saveChainer.setExitPoint(reboot); function reboot() { //noinspection JSUnresolvedVariable GUI.log(chrome.i18n.getMessage('configurationEepromSaved')); GUI.tab_switch_cleanup(function() { MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitialize); }); } function reinitialize() { //noinspection JSUnresolvedVariable GUI.log(chrome.i18n.getMessage('deviceRebooting')); GUI.handleReconnect($('.tab_mixer a')); } function loadHtml() { GUI.load("./tabs/mixer.html", processHtml); } function renderOutputTable() { let outputCount = OUTPUT_MAPPING.getOutputCount(), $outputRow = $('#output-row'), $functionRow = $('#function-row'); $outputRow.append(''); $functionRow.append(''); for (let i = 1; i <= outputCount; i++) { $outputRow.append('S' + i + ''); $functionRow.append('-'); } $outputRow.find('td').css('width', 100 / (outputCount + 1) + '%'); } function renderOutputMapping() { let outputMap = OUTPUT_MAPPING.getOutputTable( MIXER_CONFIG.platformType == PLATFORM_MULTIROTOR || MIXER_CONFIG.platformType == PLATFORM_TRICOPTER, MOTOR_RULES.getNumberOfConfiguredMotors(), SERVO_RULES.getUsedServoIndexes() ); for (let i = 1; i <= OUTPUT_MAPPING.getOutputCount(); i++) { $('#function-' + i).html(outputMap[i - 1]); } } function renderServoMixRules() { /* * Process servo mix table UI */ let rules = SERVO_RULES.get(); $servoMixTableBody.find("*").remove(); for (let servoRuleIndex in rules) { if (rules.hasOwnProperty(servoRuleIndex)) { const servoRule = rules[servoRuleIndex]; $servoMixTableBody.append('\ \ \ \ \ \ \ \ \ \ '); const $row = $servoMixTableBody.find('tr:last'); GUI.renderLogicConditionSelect( $row.find('.mixer-table__condition'), LOGIC_CONDITIONS, servoRule.getConditionId(), function () { servoRule.setConditionId($(this).val()); }, true ); GUI.fillSelect($row.find(".mix-rule-input"), FC.getServoMixInputNames(), servoRule.getInput()); $row.find(".mix-rule-input").val(servoRule.getInput()).change(function () { servoRule.setInput($(this).val()); updateFixedValueVisibility($row, $(this)); }); $row.find(".mix-rule-servo").val(servoRule.getTarget()).change(function () { servoRule.setTarget($(this).val()); }); $row.find(".mix-rule-rate").val(servoRule.getRate()).change(function () { servoRule.setRate($(this).val()); $row.find(".mix-rule-fixed-value").val(mapServoWeightToFixedValue($(this).val())); }); $row.find(".mix-rule-fixed-value").val(mapServoWeightToFixedValue($row.find(".mix-rule-rate").val())); $row.find(".mix-rule-speed").val(servoRule.getSpeed()).change(function () { servoRule.setSpeed($(this).val()); }); $row.find("[data-role='role-servo-delete']").attr("data-index", servoRuleIndex); updateFixedValueVisibility($row, $row.find(".mix-rule-input")); } } let rate_inputs = $('.mix-rule-rate'); rate_inputs.attr("min", -1000); rate_inputs.attr("max", 1000); localize(); } function updateFixedValueVisibility(row, $mixRuleInput) { // Show the fixed value input box if "MAX" input was selected for this servo const $fixedValueCalcInput = row.find(".mix-rule-fixed-value"); if (FC.getServoMixInputNames()[$mixRuleInput.val()] === 'MAX') { $fixedValueCalcInput.show(); row.find(".mix-rule-speed").prop('disabled', true); } else { $fixedValueCalcInput.hide(); row.find(".mix-rule-speed").prop('disabled', false); } // Show the Fixed Value column if at least one servo has the "MAX" input assigned const $fixedValueCol = $("#servo-mix-table").find(".mixer-fixed-value-col"); const rules = SERVO_RULES.get(); for (let servoRuleIndex in rules) { if (rules.hasOwnProperty(servoRuleIndex)) { if (FC.getServoMixInputNames()[rules[servoRuleIndex].getInput()] === 'MAX') { $fixedValueCol.show(); return; } } } $fixedValueCol.hide(); } function mapServoWeightToFixedValue(weight) { return (parseInt(weight) + 100) * 1000 / 200 + 1000; } function renderMotorMixRules() { /* * Process motor mix table UI */ var rules = MOTOR_RULES.get(); $motorMixTableBody.find("*").remove(); let index = 0; for (const i in rules) { if (rules.hasOwnProperty(i)) { const rule = rules[i]; index++; $motorMixTableBody.append('\ \ \ \ \ \ \ \ \ '); const $row = $motorMixTableBody.find('tr:last'); $row.find('.mix-rule-motor').html(index); $row.find('.mix-rule-throttle').val(rule.getThrottle()).change(function () { rule.setThrottle($(this).val()); }); $row.find('.mix-rule-roll').val(rule.getRoll()).change(function () { rule.setRoll($(this).val()); }); $row.find('.mix-rule-pitch').val(rule.getPitch()).change(function () { rule.setPitch($(this).val()); }); $row.find('.mix-rule-yaw').val(rule.getYaw()).change(function () { rule.setYaw($(this).val()); }); $row.find("[data-role='role-motor-delete']").attr("data-index", i); } } localize(); } function saveAndReboot() { /* * Send tracking */ googleAnalytics.sendEvent('Mixer', 'Platform type', helper.platform.getById(MIXER_CONFIG.platformType).name); googleAnalytics.sendEvent('Mixer', 'Mixer preset', helper.mixer.getById(MIXER_CONFIG.appliedMixerPreset).name); /* * Send mixer rules */ SERVO_RULES.cleanup(); SERVO_RULES.inflate(); MOTOR_RULES.cleanup(); MOTOR_RULES.inflate(); saveChainer.execute(); } function processHtml() { $servoMixTable = $('#servo-mix-table'); $servoMixTableBody = $servoMixTable.find('tbody'); $motorMixTable = $('#motor-mix-table'); $motorMixTableBody = $motorMixTable.find('tbody'); function fillMixerPreset() { let mixers = helper.mixer.getByPlatform(MIXER_CONFIG.platformType); $mixerPreset.find("*").remove(); for (i in mixers) { if (mixers.hasOwnProperty(i)) { let m = mixers[i]; $mixerPreset.append(''); } } } let $platformSelect = $('#platform-type'), platforms = helper.platform.getList(), $hasFlapsWrapper = $('#has-flaps-wrapper'), $hasFlaps = $('#has-flaps'), $mixerPreset = $('#mixer-preset'), $wizardButton = $("#mixer-wizard"); motorWizardModal = new jBox('Modal', { width: 480, height: 410, closeButton: 'title', animation: false, attach: $wizardButton, title: chrome.i18n.getMessage("mixerWizardModalTitle"), content: $('#mixerWizardContent') }); function validateMixerWizard() { let errorCount = 0; for (let i = 0; i < 4; i++) { const $elements = $('[data-motor] option:selected[id=' + i + ']'), assignedRulesCount = $elements.length; if (assignedRulesCount != 1) { errorCount++; $elements.closest('tr').addClass("red-background"); } else { $elements.closest('tr').removeClass("red-background"); } } return (errorCount == 0); } $(".wizard-motor-select").change(validateMixerWizard); $("#wizard-execute-button").click(function () { // Validate mixer settings if (!validateMixerWizard()) { return; } MOTOR_RULES.flush(); for (let i = 0; i < 4; i++) { const $selects = $(".wizard-motor-select"); let rule = -1; $selects.each(function () { if (parseInt($(this).find(":selected").attr("id"), 10) == i) { rule = parseInt($(this).attr("data-motor"), 10); } }); const r = currentMixerPreset.motorMixer[rule]; MOTOR_RULES.put( new MotorMixRule( r.getThrottle(), r.getRoll(), r.getPitch(), r.getYaw() ) ); } renderMotorMixRules(); renderOutputMapping(); motorWizardModal.close(); }); $platformSelect.find("*").remove(); for (let i in platforms) { if (platforms.hasOwnProperty(i)) { let p = platforms[i]; $platformSelect.append(''); } } $hasFlaps.prop("checked", MIXER_CONFIG.hasFlaps); $hasFlaps.change(function () { if ($(this).is(":checked")) { MIXER_CONFIG.hasFlaps = 1; } else { MIXER_CONFIG.hasFlaps = 0; } }); $hasFlaps.change(); $platformSelect.change(function () { MIXER_CONFIG.platformType = parseInt($platformSelect.val(), 10); currentPlatform = helper.platform.getById(MIXER_CONFIG.platformType); var $platformSelectParent = $platformSelect.parent('.select'); if (currentPlatform.flapsPossible) { $hasFlapsWrapper.removeClass('is-hidden'); $platformSelectParent.removeClass('no-bottom-border'); } else { $hasFlapsWrapper.addClass('is-hidden'); $platformSelectParent.addClass('no-bottom-border'); } fillMixerPreset(); $mixerPreset.change(); }); currentPlatform = helper.platform.getById(MIXER_CONFIG.platformType); $platformSelect.val(MIXER_CONFIG.platformType).change(); $mixerPreset.change(function () { const presetId = parseInt($mixerPreset.val(), 10); currentMixerPreset = helper.mixer.getById(presetId); MIXER_CONFIG.appliedMixerPreset = presetId; if (currentMixerPreset.id == 3) { $wizardButton.parent().removeClass("is-hidden"); } else { $wizardButton.parent().addClass("is-hidden"); } $('.mixerPreview img').attr('src', './resources/motor_order/' + currentMixerPreset.image + '.svg'); }); if (MIXER_CONFIG.appliedMixerPreset > -1) { $mixerPreset.val(MIXER_CONFIG.appliedMixerPreset).change(); } else { $mixerPreset.change(); } modal = new jBox('Modal', { width: 480, height: 240, closeButton: 'title', animation: false, attach: $('#load-and-apply-mixer-button'), title: chrome.i18n.getMessage("mixerApplyModalTitle"), content: $('#mixerApplyContent') }); $('#execute-button').click(function () { helper.mixer.loadServoRules(currentMixerPreset); helper.mixer.loadMotorRules(currentMixerPreset); renderServoMixRules(); renderMotorMixRules(); renderOutputMapping(); modal.close(); saveAndReboot(); }); $('#load-mixer-button').click(function () { helper.mixer.loadServoRules(currentMixerPreset); helper.mixer.loadMotorRules(currentMixerPreset); renderServoMixRules(); renderMotorMixRules(); renderOutputMapping(); }); $servoMixTableBody.on('click', "[data-role='role-servo-delete']", function (event) { SERVO_RULES.drop($(event.currentTarget).attr("data-index")); renderServoMixRules(); renderOutputMapping(); }); $motorMixTableBody.on('click', "[data-role='role-motor-delete']", function (event) { MOTOR_RULES.drop($(event.currentTarget).attr("data-index")); renderMotorMixRules(); renderOutputMapping(); }); $servoMixTableBody.on('change', "input", function (event) { renderOutputMapping(); }); $("[data-role='role-servo-add']").click(function () { if (SERVO_RULES.hasFreeSlots()) { SERVO_RULES.put(new ServoMixRule(0, 0, 100, 0)); renderServoMixRules(); renderOutputMapping(); } }); $("[data-role='role-motor-add']").click(function () { if (MOTOR_RULES.hasFreeSlots()) { MOTOR_RULES.put(new MotorMixRule(1, 0, 0, 0)); renderMotorMixRules(); renderOutputMapping(); } }); $("[data-role='role-logic-conditions-open']").click(function () { LOGIC_CONDITIONS.open(); }); $('#save-button').click(saveAndReboot); renderServoMixRules(); renderMotorMixRules(); renderOutputTable(); renderOutputMapping(); LOGIC_CONDITIONS.init($('#logic-wrapper')); localize(); helper.mspBalancedInterval.add('logic_conditions_pull', 350, 1, getLogicConditionsStatus); GUI.content_ready(callback); } function getLogicConditionsStatus() { mspHelper.loadLogicConditionsStatus(onStatusPullDone); } function onStatusPullDone() { LOGIC_CONDITIONS.update(LOGIC_CONDITIONS_STATUS); } }; TABS.mixer.cleanup = function (callback) { delete modal; delete motorWizardModal; $('.jBox-wrapper').remove(); if (callback) callback(); };