You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
inav-configurator/tabs/sitl.js

533 lines
17 KiB
JavaScript

'use strict'
const path = require('path');
const { GUI, TABS } = require('./../js/gui');
const i18n = require('./../js/localization');
const { SITLProcess, SitlSerialPortUtils } = require('./../js/sitl');
const Store = require('electron-store');
const store = new Store();
const localhost = "127.0.0.1"
const simulators = [
{
name: "X-Plane",
port: 49001,
isPortFixed: false,
inputChannels: 4,
fixedChanMap: ["Throttle", "Roll", "Pitch", "Yaw" ]
},
{
name: "RealFlight",
port: 18083,
isPortFixed: true,
inputChannels: 12,
fixedChanMap: false
}
];
const stdProfiles = [
{
name: "[Standard] Confgurator",
sim: "X-Plane",
eepromFileName: "standard-configurator.bin",
isStdProfile: true,
simEnabled: false,
port: 49001,
ip: "127.0.0.1",
useImu: false,
channelMap: [ 1, 15, 13, 16],
useSerialReceiver: true,
serialPort: "",
serialUart: 3,
serialProtocol: "SBus",
baudRate: false,
stopBits: false,
parity: false
},
{
name: "[Standard] X-Plane",
sim: "X-Plane",
eepromFileName: "standard-x-plane.bin",
isStdProfile: true,
simEnabled: true,
port: 49001,
ip: "127.0.0.1",
useImu: false,
channelMap: [ 1, 15, 13, 16],
useSerialReceiver: true,
serialPort: "",
serialUart: 3,
serialProtocol: "SBus",
baudRate: false,
stopBits: false,
parity: false
},
{
name: "[Standard] RealFlight Flying Wing",
sim: "RealFlight",
eepromFileName: "standard-realflight.bin",
isStdProfile: true,
simEnabled: true,
port: 49001,
ip: "127.0.0.1",
useImu: false,
channelMap: [ 1, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0],
useSerialReceiver: true,
serialPort: "",
serialUart: 3,
serialProtocol: "SBus",
baudRate: false,
stopBits: false,
parity: false
}
];
var SITL_LOG = "";
TABS.sitl = {};
TABS.sitl.initialize = (callback) => {
if (GUI.active_tab != 'sitl') {
GUI.active_tab = 'sitl';
}
GUI.load(path.join(__dirname, "sitl.html"), function () {
i18n.localize();
var currentSim, currentProfile, profiles;
var mapping = new Array(28).fill(0);
var serialProtocolls = SitlSerialPortUtils.getProtocolls();
var sim_e = $('#simulator');
var enableSim_e = $('#sitlEnableSim');
var port_e = $('#simPort');
var simIp_e = $('#simIP');
var useImu_e = $('#sitlUseImu');
var profiles_e = $('#sitlProfile');
var profileSaveBtn_e = $('#sitlProfileSave');
var profileNewBtn_e = $('#sitlProfileNew');
var profileDeleteBtn_e = $('#sitlProfileDelete');
var serialPorts_e = $('#sitlSerialPort');
var serialReceiverEnable_e = $('#serialReceiverEnable');
var serialUart_e = $('#sitlSerialUART');
var protocollPreset_e = $('#serialProtocoll');
var baudRate_e = $('#sitlBaud');
var stopBits_e = $('#serialStopbits');
var parity_e = $('#serialParity');
if (SITLProcess.isRunning) {
$('.sitlStart').addClass('disabled');
$('.sitlStop').removeClass('disabled');
} else {
$('.sitlStop').addClass('disabled');
$('.sitlStart').removeClass('disabled');
}
var $sitlLog = $('#sitlLog');
$sitlLog.val(SITL_LOG);
if ($sitlLog && $sitlLog.length == 1) {
$sitlLog.val(SITL_LOG);
$sitlLog.animate({scrollTop: $sitlLog[0].scrollHeight - $sitlLog.height()}, "fast");
}
profiles = stdProfiles.slice(0);
var sitlProfiles = store.get('sitlProfiles', false);
if (sitlProfiles) {
profiles.push(...sitlProfiles);
}
initElements(true);
SitlSerialPortUtils.resetPortsList();
SitlSerialPortUtils.pollSerialPorts(ports => {
serialPorts_e.find('*').remove();
ports.forEach(port => {
serialPorts_e.append(`<option value="${port}">${port}</option>`)
});
});
enableSim_e.on('change', () => {
currentProfile.simEnabled = enableSim_e.is(':checked');
updateSim();
});
sim_e.on('change', () => {
updateSim();
});
profiles_e.on('change', () => {
updateCurrentProfile();
});
port_e.on('change', () => {
if (!currentSim.isPortFixed) {
var port = parseInt(port_e.val());
if (port != NaN)
currentProfile.port = parseInt(port_e.val());
}
});
simIp_e.on('change', () => {
currentProfile.ip = simIp_e.val();
});
useImu_e.on('change', () => {
currentProfile.useImu = useImu_e.is(':checked');
});
$('.sitlStart').on('click', ()=> {
$('.sitlStart').addClass('disabled');
$('.sitlStop').removeClass('disabled');
var sim, simPort, simIp, channelMap = "";
if (enableSim_e.is(':checked')) {
switch(currentSim.name) {
case 'X-Plane':
sim = 'xp';
break;
case 'RealFlight':
sim = 'rf'
break;
}
}
if (port_e.val() !== "") {
simPort = port_e.val();
}
if (simIp_e.val() !== "") {
simIp = simIp_e.val();
}
const zeroPad = (num, places) => String(num).padStart(places, '0');
for (let i = 0; i < currentSim.inputChannels; i++) {
var inavChan = mapping[i];
if (inavChan == 0) {
continue;
} else if (inavChan < 13) {
channelMap += `M${zeroPad(inavChan, 2)}-${zeroPad(i + 1, 2)},`;
} else {
channelMap += `S${zeroPad(inavChan - 12, 2)}-${zeroPad(i + 1, 2)},`;
}
}
channelMap = channelMap.substring(0, channelMap.length - 1);
var serialOptions = null;
if ( serialReceiverEnable_e.is(':checked') && !!serialPorts_e.val()) {
var selectedProtocoll = protocollPreset_e.find(':selected').val();
if (selectedProtocoll == "manual") {
serialOptions = {
protocollName: "manual",
baudRate: baudRate_e.val() || currentProfile.baudRate || "115200",
stopBits: stopBits_e.val() || currentProfile.stopBits || "One",
parity: parity_e.val() || currentProfile.parity || "None",
serialPort: serialPorts_e.val() || currentProfile.serialPort || "",
serialUart: serialUart_e.val() || currentProfile.serialUart || -1
}
} else {;
serialOptions = {
protocollName: selectedProtocoll || "SBus",
serialPort: serialPorts_e.val() || currentProfile.serialPort || "" ,
serialUart: serialUart_e.val() || currentProfile.serialUart || -1
}
}
}
appendLog("\n");
SITLProcess.start(currentProfile.eepromFileName, sim, useImu_e.is(':checked'), simIp, simPort, channelMap, serialOptions,result => {
appendLog(result);
});
});
$('.sitlStop').on('click', ()=> {
$('.sitlStop').addClass('disabled');
$('.sitlStart').removeClass('disabled');
SITLProcess.stop();
appendLog(i18n.getMessage('sitlStopped'));
});
profileSaveBtn_e.on('click', function () {
saveProfiles();
});
profileNewBtn_e.on('click', function () {
var name = prompt(i18n.getMessage('sitlNewProfile'), i18n.getMessage('sitlEnterName'));
if (!name)
return;
if (profiles.find(e => { return e.name == name })) {
GUI.alert(i18n.getMessage('sitlProfileExists'))
return;
}
var eerpromName = name.replace(/[^a-z0-9]/gi, '_').toLowerCase() + ".bin";
var profile = {
name: name,
sim: "RealFlight",
isStdProfile: false,
simEnabled: false,
eepromFileName: eerpromName,
port: 49001,
ip: "127.0.0.1",
useImu: false,
channelMap: [ 1, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0],
useSerialReceiver: true,
serialPort: serialPorts_e.val(),
serialUart: 3,
serialProtocol: "SBus",
baudRate: false,
stopBits: false,
parity: false
}
profiles.push(profile);
profiles_e.append(`<option value="${name}">${name}</option>`)
profiles_e.val(name);
updateCurrentProfile();
saveProfiles();
});
profileDeleteBtn_e.on('click', function () {
if (currentProfile.isStdProfile) {
GUI.alert(i18n.getMessage('sitlStdProfileCantDeleted'));
return;
}
var selected = profiles_e.find(':selected').val();
profiles = profiles.filter(profile => {
return profile.name != selected;
});
SITLProcess.deleteEepromFile(currentProfile.eepromFileName);
profiles_e.find('*').remove();
initElements(false);
saveProfiles();
});
serialReceiverEnable_e.on('change', () => {
currentProfile.useSerialReceiver = serialReceiverEnable_e.is(':checked');
});
protocollPreset_e.on('change', () => {
var selectedProtocoll = protocollPreset_e.find(':selected').val();
var protocoll = serialProtocolls.find(protocoll => {
return protocoll.name == selectedProtocoll;
});
if (selectedProtocoll != 'manual'){
baudRate_e.prop('disabled', true);
baudRate_e.val(protocoll.baudRate);
stopBits_e.prop('disabled', true);
stopBits_e.val(protocoll.stopBits);
parity_e.prop('disabled', true);
parity_e.val(protocoll.parity);
serialUart_e.prop('disabled', selectedProtocoll == "Flight Controller Proxy");
} else {
baudRate_e.prop('disabled', false);
stopBits_e.prop('disabled', false);
parity_e.prop('disabled', false);
serialUart_e.prop('disabled', false);
}
currentProfile.serialProtocol = selectedProtocoll;
});
serialPorts_e.on('change', () => {
currentProfile.serialPort = serialPorts_e.val();
});
serialUart_e.on('change', () => {
currentProfile.serialUart = parseInt(serialUart_e.val());
});
baudRate_e.on('change', () => {
var baud = parseInt(baudRate_e.val());
if (baud != NaN)
currentProfile.baudRate = baud
});
stopBits_e.on('change', () => {
currentProfile.stopBits = stopBits_e.val();
});
parity_e.on('change', () => {
currentProfile.parity = parity_e.val();
});
function initElements(init)
{
profiles.forEach(profile => {
profiles_e.append(`<option value="${profile.name}">${profile.name}</option>`)
});
if (init) {
simulators.forEach(simulator => {
sim_e.append(`<option value="${simulator.name}">${simulator.name}</option>`)
});
protocollPreset_e.append('<option value="manual">Manual</option>');
serialProtocolls.forEach(protocoll => {
protocollPreset_e.append(`<option value="${protocoll.name}">${protocoll.name}</option>`);
});
var sitlLastProfile = store.get('sitlLastProfile', false);
if (sitlLastProfile) {
var element = profiles.find(profile => {
return profile.name == sitlLastProfile;
});
if (element)
profiles_e.val(element.name).trigger('change');
}
}
updateCurrentProfile();
}
function saveProfiles() {
if (currentProfile.isStdProfile) {
GUI.alert(i18n.getMessage('sitlStdProfileCantOverwritten'));
return;
}
var profilesToSave = [];
profiles.forEach(profile => {
if (!profile.isStdProfile)
profilesToSave.push(profile);
});
store.set('sitlProfiles', profilesToSave);
}
function updateSim() {
simulators.forEach(simulator => {
if (simulator.name == sim_e.find(':selected').text()) {
currentSim = simulator;
currentProfile.sim = currentSim.name;
if (currentSim.isPortFixed) {
port_e.val(currentSim.port).trigger('change');
} else {
port_e.val(currentProfile.port);
}
sim_e.prop('disabled', !currentProfile.simEnabled);
simIp_e.prop('disabled', !currentProfile.simEnabled);
port_e.prop('disabled', simulator.isPortFixed || !currentProfile.simEnabled);
useImu_e.prop('disabled', !currentProfile.simEnabled);
renderChanMapTable();
return;
}
});
}
function updateCurrentProfile() {
var selected = profiles_e.find(':selected').val();
var selectedIndex = profiles.findIndex(element => {
return element.name == selected;
});
currentProfile = profiles[selectedIndex];
protocollPreset_e.val(currentProfile.serialProtocol);
if (currentProfile.serialProtocol == "manual")
{
baudRate_e.val(currentProfile.baudRate);
baudRate_e.prop('disabled', false);
stopBits_e.val(currentProfile.stopBits);
stopBits_e.prop('disabled', false);
parity_e.val(currentProfile.parity);
parity_e.prop('disabled', false);
serialUart_e.prop('disabled', false);
} else {
var protocoll = serialProtocolls.find(protocoll => {
return protocoll.name == currentProfile.serialProtocol;
});
baudRate_e.prop('disabled', true);
baudRate_e.val(protocoll.baudRate);
stopBits_e.prop('disabled', true);
stopBits_e.val(protocoll.stopBits);
parity_e.prop('disabled', true);
parity_e.val(protocoll.parity);
serialUart_e.prop('disabled', currentProfile.serialProtocol == "Flight Controller Proxy");
}
if (currentProfile.serialPort != "")
serialPorts_e.val(currentProfile.serialPort);
enableSim_e.prop('checked', currentProfile.simEnabled).trigger('change');
serialReceiverEnable_e.prop('checked', currentProfile.useSerialReceiver).trigger('change');
serialUart_e.val(currentProfile.serialUart);
mapping = currentProfile.channelMap;
sim_e.val(currentProfile.sim);
updateSim();
simIp_e.val(currentProfile.ip).trigger('change');
useImu_e.prop('checked', currentProfile.useImu).trigger('change');
store.set('sitlLastProfile', selected);
}
function renderChanMapTable()
{
var mapTableBody = $('.mapTableBody');
mapTableBody.find('*').remove();
for (let i = 0; i < currentSim.inputChannels; i++) {
var output;
if (currentSim.fixedChanMap) {
output = currentSim.fixedChanMap[i];
} else {
output = i + 1;
}
mapTableBody.append("<tr><td>" + output + "</td><td><select data-out=\"" + i + "\" class=\"inavChannel\"\"></select></td></td>");
const row = mapTableBody.find('tr:last');
GUI.fillSelect(row.find(".inavChannel"), getInavChannels(), mapping[i]);
row.find(".inavChannel").val(mapping[i]).on('change', (sender) => {
mapping[$(sender.target).data('out')] = parseInt($(sender.target).val());
store.set('sitlMapping', mapping);
});
}
}
function getInavChannels() {
var channels = [];
for (var i = 0; i <= 12; i++) {
if (i == 0)
channels.push("None");
else
channels.push("Motor " + i);
}
for (var i = 1; i <= 16; i++) {
if (i == 0)
channels.push("None");
else
channels.push("Servo " + i);
}
return channels;
}
function appendLog(message){
SITL_LOG += message;
var $sitlLog = $('#sitlLog');
if ($sitlLog && $sitlLog.length == 1) {
$sitlLog.val(SITL_LOG);
$sitlLog.animate({scrollTop: $sitlLog[0].scrollHeight - $sitlLog.height()}, "fast");
}
}
GUI.content_ready(callback);
});
};
TABS.sitl.cleanup = (callback) => {
SitlSerialPortUtils.stopPollSerialPorts();
if (callback)
callback();
};