'use strict';
TABS.servos = {};
TABS.servos.initialize = function (callback) {
if (GUI.active_tab !== 'servos') {
GUI.active_tab = 'servos';
}
function get_servo_configurations() {
MSP.send_message(MSPCodes.MSP_SERVO_CONFIGURATIONS, false, false, get_servo_mix_rules);
}
function get_servo_mix_rules() {
MSP.send_message(MSPCodes.MSP_SERVO_MIX_RULES, false, false, get_rc_data);
}
function get_rc_data() {
MSP.send_message(MSPCodes.MSP_RC, false, false, get_boxnames_data);
}
function get_boxnames_data() {
MSP.send_message(MSPCodes.MSP_BOXNAMES, false, false, load_html);
}
function load_html() {
$('#content').load("./tabs/servos.html", process_html);
}
get_servo_configurations();
function update_ui() {
if (semver.lt(FC.CONFIG.apiVersion, "1.12.0") || FC.SERVO_CONFIG.length === 0) {
$(".tab-servos").removeClass("supported");
return;
}
$(".tab-servos").addClass("supported");
let servoCheckbox = '';
let servoHeader = '';
for (let i = 0; i < FC.RC.active_channels-4; i++) {
servoHeader += `
A${(i+1)} | `;
}
servoHeader += ' | ';
for (let i = 0; i < FC.RC.active_channels; i++) {
servoCheckbox += ` | `;
}
$('div.tab-servos table.fields tr.main').append(servoHeader);
/*
* function: void process_servos(string, object)
*/
function process_servos(name, obj) {
$('div.supported_wrapper').show();
const subElement = `${name}`;
element += `${subElement}${FC.SERVO_CONFIG[obj].middle}" /> | `;
element += `${subElement}${FC.SERVO_CONFIG[obj].min}" /> | `;
element += `${subElement}${FC.SERVO_CONFIG[obj].max}" /> | `;
element += `${servoCheckbox} | `;
$('div.tab-servos table.fields').append(element);
if (FC.SERVO_CONFIG[obj].indexOfChannelToForward >= 0) {
$('div.tab-servos table.fields tr:last td.channel input').eq(FC.SERVO_CONFIG[obj].indexOfChannelToForward).prop('checked', true);
}
// adding select box and generating options
$('div.tab-servos table.fields tr:last td.direction').append('');
const select = $('div.tab-servos table.fields tr:last td.direction select');
for (let i = 100; i > -101; i--) {
select.append(``);
}
// select current rate
select.val(FC.SERVO_CONFIG[obj].rate);
$('div.tab-servos table.fields tr:last').data('info', {'obj': obj});
// UI hooks
// only one checkbox for indicating a channel to forward can be selected at a time, perhaps a radio group would be best here.
$('div.tab-servos table.fields tr:last td.channel input').click(function () {
if($(this).is(':checked')) {
$(this).parent().parent().find('.channel input').not($(this)).prop('checked', false);
}
});
}
/*
* function: void servos_update(boolean)
*/
function servos_update(save_configuration_to_eeprom) {
$('div.tab-servos table.fields tr:not(".main")').each(function () {
const info = $(this).data('info');
const selection = $('.channel input', this);
let channelIndex = parseInt(selection.index(selection.filter(':checked')));
if (channelIndex === -1) {
channelIndex = undefined;
}
FC.SERVO_CONFIG[info.obj].indexOfChannelToForward = channelIndex;
FC.SERVO_CONFIG[info.obj].middle = parseInt($('.middle input', this).val());
FC.SERVO_CONFIG[info.obj].min = parseInt($('.min input', this).val());
FC.SERVO_CONFIG[info.obj].max = parseInt($('.max input', this).val());
const val = parseInt($('.direction select', this).val());
FC.SERVO_CONFIG[info.obj].rate = val;
});
//
// send data to FC
//
mspHelper.sendServoConfigurations(send_servo_mixer_rules);
function send_servo_mixer_rules() {
mspHelper.sendServoConfigurations(save_to_eeprom);
}
function save_to_eeprom() {
if (save_configuration_to_eeprom) {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () {
GUI.log(i18n.getMessage('servosEepromSave'));
});
}
}
}
// drop previous table
$('div.tab-servos table.fields tr:not(:first)').remove();
// let's reflect CLI here to number servo's 1-8 instead of 0-7
for (let servoIndex = 0; servoIndex < 8; servoIndex++) {
process_servos(`Servo ${servoIndex+1}`, servoIndex);
}
const servosWrapper = $('.servos .bar-wrapper');
for (let i = 0; i < 8; i++) {
servosWrapper.append(`\
\
`);
}
const rangeMin = 1000;
const rangeMax = 2000;
$('div.values li:not(:last)').text(rangeMin);
/*
* void test_update(void);
*/
function test_update() {
const blockHeight = 100;
const fullBlockScale = rangeMax - rangeMin;
for (let i = 0; i < FC.SERVO_DATA.length; i++) {
const servoValue = FC.SERVO_DATA[i];
const barHeight = servoValue - rangeMin;
const marginTop = blockHeight - (barHeight * (blockHeight / fullBlockScale)).clamp(0, blockHeight);
const height = (barHeight * (blockHeight / fullBlockScale)).clamp(0, blockHeight);
const color = parseInt(barHeight * 0.009);
$(`.servo-${i} .label`, servosWrapper).text(servoValue);
$(`.servo-${i} .indicator`, servosWrapper).css({
'margin-top' : `${marginTop}px`,
'height' : `${height}px`,
'background-color' : `rgba(255,187,0,1${color})`,
});
}
}
function get_servo_data() {
MSP.send_message(MSPCodes.MSP_SERVO, false, false, test_update);
}
// UI hooks for dynamically generated elements
GUI.interval_add('servo_data_pull_and_test_update', get_servo_data, 50);
$('table.directions select, table.directions input, table.fields select, table.fields input').change(function () {
if ($('div.live input').is(':checked')) {
// apply small delay as there seems to be some funky update business going wrong
GUI.timeout_add('servos_update', servos_update, 10);
}
});
$('a.update').click(function () {
servos_update(true);
});
}
function process_html() {
update_ui();
// translate to user-selected language
i18n.localizePage();
// status data pulled via separate timer with static speed
GUI.interval_add('status_pull', function () {
MSP.send_message(MSPCodes.MSP_STATUS);
}, 250, true);
GUI.content_ready(callback);
}
};
TABS.servos.cleanup = function (callback) {
if (callback) {
callback();
}
};