1
0
Fork 0
mirror of https://github.com/iNavFlight/inav-configurator.git synced 2025-07-13 03:19:54 +03:00
inav-configurator/tabs/sitl.js
2024-04-21 20:46:16 -03:00

527 lines
No EOL
16 KiB
JavaScript

'use strict'
const path = require('path');
const { GUI, TABS } = require('./../js/gui');
const i18n = require('./../js/localization');
const { Ser2TCP, SITLProcess } = 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] X-Plane",
sim: "X-Plane",
eepromFileName: "standard-x-plane.bin",
isStdProfile: true,
simEnabeld: true,
port: 49001,
ip: "127.0.0.1",
useImu: false,
channelMap: [ 1, 15, 13, 16],
useSerialTcp: true,
comPort: "",
tcpPort: 5762,
serialProtocol: "SBus",
baudrate: false,
stopbits: false,
parity: false
},
{
name: "[Standard] RealFlight Flying Wing",
sim: "RealFlight",
eepromFileName: "standard-realflight.bin",
isStdProfile: true,
simEnabeld: true,
port: 49001,
ip: "127.0.0.1",
useImu: false,
channelMap: [ 1, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0],
useSerialTcp: true,
comPort: "",
tcpPort: 5762,
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 os = GUI.operating_system;
if (os != 'Windows' && os != 'Linux') {
$('.content_wrapper').find('*').remove();
$('.content_wrapper').append(`<h2>${i18n.getMessage('sitlOSNotSupported')}</h2>`);
GUI.content_ready(callback);
return;
}
var currentSim, currentProfile, profiles;
var mapping = new Array(28).fill(0);
var serialProtocolls = Ser2TCP.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 serialTcpEnable = $('#serialTcpEnable')
var tcpPort_e = $('#serialTCPPort');
var protocollPreset_e = $('#serialProtocoll');
var baudRate_e = $('#sitlBaud');
var stopBits_e = $('#serialStopbits');
var parity_e = $('#serialParity');
var serialTcpEable_e = $('#serialTcpEnable');
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);
Ser2TCP.resetPortsList();
Ser2TCP.pollSerialPorts(ports => {
serialPorts_e.find('*').remove();
ports.forEach(port => {
serialPorts_e.append(`<option value="${port}">${port}</option>`)
});
});
enableSim_e.on('change', () => {
currentProfile.simEnabeld = enableSim_e.is(':checked');
});
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;
var selectedProtocoll = protocollPreset_e.find(':selected').val();
if (selectedProtocoll == "manual") {
serialOptions = {
protocollName: "manual",
bitrate: currentProfile.baudrate,
stopBits: currentProfile.stopBits,
parityBit: currentProfile.parity
}
} else {;
serialOptions = {
protocollName: selectedProtocoll
}
}
SITLProcess.start(currentProfile.eepromFileName, sim, useImu_e.is(':checked'), simIp, simPort, channelMap, result => {
appendLog(result);
if (serialTcpEnable.is(':checked') && result == `[SIM] Connection with ${currentProfile.sim} successfully established.\n`) {
Ser2TCP.start(serialPorts_e.val(), serialOptions, currentProfile.ip, currentProfile.tcpPort, result => {
appendLog(`[Serial2TCP] ${result}`);
});
}
});
});
$('.sitlStop').on('click', ()=> {
$('.sitlStop').addClass('disabled');
$('.sitlStart').removeClass('disabled');
Ser2TCP.stop();
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 })) {
alert(i18n.getMessage('sitlProfileExists'))
return;
}
var eerpromName = name.replace(/[^a-z0-9]/gi, '_').toLowerCase() + ".bin";
var profile = {
name: name,
sim: "RealFlight",
isStdProfile: false,
simEnabeld: true,
eepromFileName: eerpromName,
port: 49001,
ip: "127.0.0.1",
useImu: false,
channelMap: [ 1, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0],
useSerialTcp: true,
tcpPort: 5762,
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) {
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();
});
serialTcpEable_e.on('change', () => {
currentProfile.useSerialTcp = serialTcpEable_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);
} else {
baudRate_e.prop('disabled', false);
baudRate_e.val('');
stopBits_e.prop('disabled', false);
stopBits_e.val('');
parity_e.prop('disabled', false);
parity_e.val('');
}
currentProfile.serialProtocol = selectedProtocoll;
});
serialPorts_e.on('change', () => {
currentProfile.comPort = serialPorts_e.val();
});
tcpPort_e.on('change', () => {
currentProfile.tcpPort = parseInt(tcpPort_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) {
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);
}
port_e.prop('disabled', simulator.isPortFixed);
renderChanMapTable();
return;
}
});
}
function updateCurrentProfile() {
var selected = profiles_e.find(':selected').val();
var selectedIndex = profiles.findIndex(element => {
return element.name == selected;
});
currentProfile = profiles[selectedIndex];
if (currentProfile.isStdProfile) {
currentProfile = structuredClone(stdProfiles.find((profile) => {
return profile.sim == currentProfile.sim;
}));
}
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);
} 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);
}
if (currentProfile.comPort != "")
serialPorts_e.val(currentProfile.comPort);
enableSim_e.prop('checked', currentProfile.simEnabeld).trigger('change');
serialTcpEable_e.prop('checked', currentProfile.useSerialTcp).trigger('change');
tcpPort_e.val(currentProfile.tcpPort);
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) => {
Ser2TCP.stopPollSerialPorts();
if (callback)
callback();
};