Refactor msp to modules (#3214)

* feat: refactor everything to modules

* fix: a lot of circular deps fixes

* feat: use vitest instead of karma
10.9-maintenance
Tomas Chmelevskij 2023-01-14 22:11:37 +01:00 committed by GitHub
parent 654dca2a19
commit c086395def
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
82 changed files with 1660 additions and 1376 deletions

View File

@ -14,7 +14,7 @@
"release:default": "NODE_ENV=production gulp release",
"release:windows": "set NODE_ENV=production&& gulp release",
"pretest": "yarn run lint",
"test": "karma start test/karma.conf.js",
"test": "vitest",
"lint": "eslint --ext .js,.vue src gulpfile.js gulp-appdmg.js",
"lint:fix": "eslint --fix src gulpfile.js gulp-appdmg.js",
"storybook": "start-storybook -p 6006"
@ -66,6 +66,7 @@
"jquery-textcomplete": "^1.8.5",
"jquery-touchswipe": "^1.6.19",
"jquery-ui-npm": "^1.12.0",
"jsdom": "^21.0.0",
"lru_map": "^0.3.3",
"marked": "^4.1.1",
"multicast-dns": "^7.2.5",
@ -92,7 +93,6 @@
"@storybook/addon-links": "^6.5.12",
"@storybook/vue": "^6.5.12",
"babel-loader": "^8.2.5",
"chai": "^4.3.6",
"command-exists": "^1.2.9",
"cordova-lib": "^11.0.0",
"del": "^6.1.1",
@ -114,17 +114,6 @@
"gulp-yarn": "^3.0.0",
"gulp-zip": "^5.1.0",
"husky": "^4.3.0",
"karma": "^6.4.1",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^3.1.1",
"karma-junit-reporter": "^2.0.1",
"karma-mocha": "^2.0.1",
"karma-rollup-preprocessor": "^7.0.8",
"karma-sinon": "^1.0.5",
"karma-sinon-chai": "^2.0.2",
"karma-spec-reporter": "^0.0.34",
"karma-tfs-reporter": "^1.0.2",
"mocha": "^10.0.0",
"nw-builder": "^3.8.6",
"os": "^0.1.2",
"postcss": "^8.4.17",
@ -133,12 +122,12 @@
"rpm-builder": "^1.2.1",
"run-script-os": "^1.1.6",
"simple-git": "^3.15.0",
"sinon": "^14.0.0",
"sinon-chai": "^3.7.0",
"targz": "^1.0.1",
"temp": "^0.9.4",
"through2": "^4.0.2",
"vinyl-source-stream": "^2.0.0",
"vite": "^4.0.4",
"vitest": "^0.27.1",
"vue-loader": "^15.9.8",
"vue-template-compiler": "^2.7.10",
"yarn": "^1.22.19"

View File

@ -1,3 +1,5 @@
import MSP from '../../js/msp.js';
class EscDshotCommandQueue
{
constructor (intervalMs)

View File

@ -3,6 +3,8 @@ import GUI from "../../js/gui.js";
import semver from "semver";
import EscDshotDirectionMotorDriver from "./EscDshotDirectionMotorDriver.js";
import DshotCommand from "../../js/utils/DshotCommand.js";
import FC from "../../js/fc.js";
import { API_VERSION_1_44 } from '../../js/data_storage.js';
class EscDshotDirectionComponent
{

View File

@ -1,5 +1,6 @@
import EscDshotCommandQueue from './EscDshotCommandQueue.js';
import DshotCommand from '../../js/utils/DshotCommand.js';
import MSPCodes from '../../js/msp/MSPCodes.js';
class EscDshotDirectionMotorDriver
{

View File

@ -2,6 +2,10 @@ import MotorOutputReorderConfig from "./MotorOutputReorderingConfig";
import MotorOutputReorderCanvas from "./MotorOutputReorderingCanvas";
import { mspHelper } from "../../js/msp/MSPHelper";
import { reinitializeConnection } from "../../js/serial_backend";
import MSP from "../../js/msp";
import MSPCodes from "../../js/msp/MSPCodes";
import FC from "../../js/fc";
import { gui_log } from "../../js/gui_log";
export default class MotorOutputReorderComponent
{
@ -94,7 +98,7 @@ export default class MotorOutputReorderComponent
function reboot()
{
GUI.log(i18n.getMessage('configurationEepromSaved'));
gui_log(i18n.getMessage('configurationEepromSaved'));
GUI.tab_switch_cleanup(() => MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection(TABS.motors)));
}

View File

@ -12,6 +12,9 @@ import BetaflightLogo from "./betaflight-logo/BetaflightLogo.vue";
import StatusBar from "./status-bar/StatusBar.vue";
import BatteryIcon from "./quad-status/BatteryIcon.vue";
import FC from '../js/fc.js';
import MSP from '../js/msp.js';
import PortUsage from '../js/port_usage.js';
import CONFIGURATOR from '../js/data_storage.js';
// Most of the global objects can go here at first.
// It's a bit of overkill for simple components,

View File

@ -1,4 +1,4 @@
import { bit_check, bit_clear, bit_set } from './serial_backend';
import { bit_check, bit_clear, bit_set } from './bit';
class Beepers {
constructor(config, supportedConditions) {

View File

@ -1,4 +1,4 @@
import GUI from "./gui";
import { gui_log } from './gui_log';
import { i18n } from "./localization";
import { get as getStorage, set as setStorage } from "./SessionStorage";
@ -21,7 +21,7 @@ export default class BuildApi {
const cachedCallback = () => {
if (cachedData) {
GUI.log(i18n.getMessage('buildServerUsingCached', [url]));
gui_log(i18n.getMessage('buildServerUsingCached', [url]));
}
onSuccess(cachedData);
@ -36,7 +36,7 @@ export default class BuildApi {
setStorage(object);
onSuccess(info);
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
gui_log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
} else {
@ -70,10 +70,10 @@ export default class BuildApi {
const url = `${this._url}${path}`;
$.get(url, function (data) {
GUI.log(i18n.getMessage('buildServerSuccess', [path]));
gui_log(i18n.getMessage('buildServerSuccess', [path]));
onSuccess(data);
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [path, `HTTP ${xhr.status}`]));
gui_log(i18n.getMessage('buildServerFailure', [path, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
}
@ -86,7 +86,7 @@ export default class BuildApi {
$.get(url, function (data) {
onSuccess(data);
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
gui_log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
}
@ -107,7 +107,7 @@ export default class BuildApi {
onSuccess(response);
},
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [`HTTP ${xhr.status}`]));
gui_log(i18n.getMessage('buildServerFailure', [`HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
}
@ -128,7 +128,7 @@ export default class BuildApi {
onSuccess(response);
},
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
gui_log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
}
@ -139,10 +139,10 @@ export default class BuildApi {
const url = `${this._url}/api/builds/${key}/status`;
$.get(url, function (data) {
GUI.log(i18n.getMessage('buildServerSuccess', [url]));
gui_log(i18n.getMessage('buildServerSuccess', [url]));
onSuccess(data);
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
gui_log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
}

View File

@ -1,4 +1,6 @@
'use strict';
import GUI from './gui';
import CONFIGURATOR from './data_storage';
import FC from './fc';
/**
* Encapsulates the AutoComplete logic
@ -575,3 +577,6 @@ CliAutoComplete._initTextcomplete = function() {
}),
]);
};
window.CliAutoComplete = CliAutoComplete;
export default CliAutoComplete;

View File

@ -1,4 +1,5 @@
'use strict';
import GUI from "./gui";
import windowWatcherUtil from "./utils/window_watchers";
const css_dark = [
'./css/dark-theme.css',
@ -63,3 +64,5 @@ DarkTheme.applyDark = function () {
DarkTheme.applyNormal = function () {
css_dark.forEach((el) => $(`link[href="${el}"]`).prop('disabled', true));
};
export default DarkTheme;

View File

@ -1,4 +1,5 @@
import { bit_check, bit_set, bit_clear } from "./serial_backend";
import { bit_check, bit_set, bit_clear } from "./bit";
import { API_VERSION_1_44 } from './data_storage';
const Features = function (config) {
const self = this;

View File

@ -1,5 +1,4 @@
'use strict';
// NOTE: this files seems to be unused anywhere
const GitHubApi = function ()
{
const self = this;
@ -25,3 +24,5 @@ GitHubApi.prototype.getFileLastCommitInfo = function (project, branch, filename,
callback(result);
});
};
export default GitHubApi;

View File

@ -1,6 +1,5 @@
'use strict';
(function () {
import { gui_log } from "./gui_log";
import { i18n } from "./localization";
/**
* Takes an ImageData object and returns an MCM symbol as an array of strings.
@ -132,7 +131,7 @@ LogoManager.init = function (font, logoStartIndex) {
const constraint = this.constraints.imageSize;
if (img.width !== constraint.expectedWidth
|| img.height !== constraint.expectedHeight) {
GUI.log(i18n.getMessage("osdSetupCustomLogoImageSizeError", {
gui_log(i18n.getMessage("osdSetupCustomLogoImageSizeError", {
width: img.width,
height: img.height,
}));
@ -158,7 +157,7 @@ LogoManager.init = function (font, logoStartIndex) {
const rgbPixel = ctx.getImageData(x, y, 1, 1).data.slice(0, 3),
colorKey = rgbPixel.join("-");
if (!this.constants.MCM_COLORMAP[colorKey]) {
GUI.log(i18n.getMessage("osdSetupCustomLogoColorMapError", {
gui_log(i18n.getMessage("osdSetupCustomLogoColorMapError", {
valueR: rgbPixel[0],
valueG: rgbPixel[1],
valueB: rgbPixel[2],
@ -288,6 +287,4 @@ LogoManager.drawPreview = function () {
}
};
window.LogoManager = LogoManager;
})();
export default LogoManager;

View File

@ -1,4 +1,5 @@
'use strict';
import FC from "./fc";
import { API_VERSION_1_43 } from "./data_storage";
const minRc = 1000;
const midRc = 1500;
@ -277,3 +278,5 @@ RateCurve.prototype.draw = function (rate, rcRate, rcExpo, superExpoActive, dead
}
}
};
export default RateCurve;

View File

@ -1,4 +1,7 @@
'use strict';
import MSP from "./msp";
import FC from "./fc";
import MSPCodes from "./msp/MSPCodes";
import { API_VERSION_1_44 } from './data_storage';
const TuningSliders = {
// Legacy Sliders
@ -824,3 +827,5 @@ TuningSliders.resetDTermFilterSlider = function() {
this.calculateNewDTermFilters();
this.updateFilterSlidersDisplay();
};
export default TuningSliders;

View File

@ -1,6 +1,8 @@
import Features from "./Features";
import { i18n } from "./localization";
import Beepers from "./Beepers";
import FC from "./fc";
import CONFIGURATOR from "./data_storage";
const VirtualFC = {
// these values are manufactured to unlock all the functionality of the configurator, they dont represent actual hardware

View File

@ -1,10 +1,16 @@
import { sensor_status, update_dataflash_global, reinitializeConnection } from "./serial_backend";
import { reinitializeConnection } from "./serial_backend";
import { update_dataflash_global } from "./update_dataflash_global";
import { sensor_status } from "./sensor_helpers.js";
import GUI from "./gui";
import Features from "./Features";
import { i18n } from "./localization";
import Beepers from "./Beepers";
import FC from "./fc";
import { mspHelper } from "./msp/MSPHelper";
import MSP from "./msp";
import MSPCodes from "./msp/MSPCodes";
import CONFIGURATOR, { API_VERSION_1_41, API_VERSION_1_45 } from "./data_storage";
import { gui_log } from './gui_log';
// code below is highly experimental, although it runs fine on latest firmware
// the data inside nested objects needs to be verified if deep copy works properly
@ -305,7 +311,7 @@ export function configuration_restore(callback) {
// validate
if (typeof configuration.generatedBy !== 'undefined' && compareVersions(configuration.generatedBy, CONFIGURATOR.BACKUP_FILE_VERSION_MIN_SUPPORTED)) {
if (!compareVersions(configuration.generatedBy, "1.14.0") && !migrate(configuration)) {
GUI.log(i18n.getMessage('backupFileUnmigratable'));
gui_log(i18n.getMessage('backupFileUnmigratable'));
return;
}
if (configuration.FEATURE_CONFIG.features._featureMask) {
@ -318,7 +324,7 @@ export function configuration_restore(callback) {
configuration_upload(configuration, callback);
} else {
GUI.log(i18n.getMessage('backupFileIncompatible'));
gui_log(i18n.getMessage('backupFileIncompatible'));
}
}
};
@ -338,7 +344,7 @@ export function configuration_restore(callback) {
function migrate(configuration) {
let appliedMigrationsCount = 0;
let migratedVersion = configuration.generatedBy;
GUI.log(i18n.getMessage('configMigrationFrom', [migratedVersion]));
gui_log(i18n.getMessage('configMigrationFrom', [migratedVersion]));
if (!compareVersions(migratedVersion, '0.59.1')) {
@ -347,7 +353,7 @@ export function configuration_restore(callback) {
configuration.MISC.rssi_aux_channel = undefined;
migratedVersion = '0.59.1';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -359,7 +365,7 @@ export function configuration_restore(callback) {
}
migratedVersion = '0.60.1';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -374,7 +380,7 @@ export function configuration_restore(callback) {
}
migratedVersion = '0.61.0';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -404,7 +410,7 @@ export function configuration_restore(callback) {
}
migratedVersion = '0.63.0';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -460,7 +466,7 @@ export function configuration_restore(callback) {
ports: ports,
};
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -480,7 +486,7 @@ export function configuration_restore(callback) {
};
}
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -520,7 +526,7 @@ export function configuration_restore(callback) {
migratedVersion = '0.66.0';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -538,7 +544,7 @@ export function configuration_restore(callback) {
configuration.profiles[profileIndex].PID.controller = newPidControllerIndex;
}
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -555,7 +561,7 @@ export function configuration_restore(callback) {
};
}
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -622,7 +628,7 @@ export function configuration_restore(callback) {
}
}
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -633,7 +639,7 @@ export function configuration_restore(callback) {
}
migratedVersion = '1.2.0';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
@ -649,12 +655,12 @@ export function configuration_restore(callback) {
migratedVersion = '1.3.1';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion]));
gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++;
}
if (appliedMigrationsCount > 0) {
GUI.log(i18n.getMessage('configMigrationSuccessful', [appliedMigrationsCount]));
gui_log(i18n.getMessage('configMigrationSuccessful', [appliedMigrationsCount]));
}
return true;
}
@ -879,7 +885,7 @@ export function configuration_restore(callback) {
}
function reboot() {
GUI.log(i18n.getMessage('eeprom_saved_ok'));
gui_log(i18n.getMessage('eeprom_saved_ok'));
GUI.tab_switch_cleanup(function() {
MSP.Promise(MSPCodes.MSP_SET_REBOOT)

11
src/js/bit.js Normal file
View File

@ -0,0 +1,11 @@
export function bit_check(num, bit) {
return (num >> bit) % 2 != 0;
}
export function bit_set(num, bit) {
return num | (1 << bit);
}
export function bit_clear(num, bit) {
return num & ~(1 << bit);
}

View File

@ -91,3 +91,5 @@ BOARD.find_board_definition = function (identifier) {
}
return DEFAULT_BOARD_DEFINITION;
};
export default BOARD;

View File

@ -1,13 +1,11 @@
'use strict';
export const API_VERSION_1_39 = '1.39.0';
export const API_VERSION_1_40 = '1.40.0';
const API_VERSION_1_39 = '1.39.0';
const API_VERSION_1_40 = '1.40.0';
const API_VERSION_1_41 = '1.41.0';
const API_VERSION_1_42 = '1.42.0';
const API_VERSION_1_43 = '1.43.0';
const API_VERSION_1_44 = '1.44.0';
const API_VERSION_1_45 = '1.45.0';
export const API_VERSION_1_41 = '1.41.0';
export const API_VERSION_1_42 = '1.42.0';
export const API_VERSION_1_43 = '1.43.0';
export const API_VERSION_1_44 = '1.44.0';
export const API_VERSION_1_45 = '1.45.0';
const CONFIGURATOR = {
// all versions are specified and compared using semantic versioning http://semver.org/
@ -38,3 +36,5 @@ const CONFIGURATOR = {
}
},
};
export default CONFIGURATOR;

View File

@ -1,6 +1,6 @@
'use strict';
import { HUFFMAN_EOF } from "./huffman";
const defaultHuffmanTree = [
export const defaultHuffmanTree = [
{ value: 0x00, codeLen: 2, code: 0x0003 }, // 11
{ value: 0x01, codeLen: 3, code: 0x0005 }, // 101
{ value: 0x02, codeLen: 4, code: 0x0009 }, // 1001
@ -260,7 +260,7 @@ const defaultHuffmanTree = [
{ value: HUFFMAN_EOF, codeLen: 12, code: 0x0000 }, // 000000000000
];
const defaultHuffmanLenIndex = function() {
export const defaultHuffmanLenIndex = function() {
const result = Array(defaultHuffmanTree.length).fill(-1);
for (let i = 0; i < defaultHuffmanTree.length; ++i) {

View File

@ -1,4 +1,5 @@
import { bit_check } from "./serial_backend";
import { bit_check } from "./bit";
import { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_44, API_VERSION_1_45 } from './data_storage';
const INITIAL_CONFIG = {
apiVersion: "0.0.0",
@ -902,6 +903,4 @@ const FC = {
},
};
// temp binding to global scope
window.FC = FC;
export default FC;

View File

@ -1,6 +1,9 @@
import { get as getConfig } from './ConfigStorage';
import MSP from './msp';
window.TABS = {}; // filled by individual tab js file
const TABS = {};
window.TABS = TABS; // filled by individual tab js file
const GUI_MODES = {
NWJS: "NW.js",
@ -242,22 +245,7 @@ class GuiControl {
return timersKilled;
}
// message = string
log(message) {
const commandLog = $('div#log');
const d = new Date();
const year = d.getFullYear();
const month = (d.getMonth() < 9) ? `0${d.getMonth() + 1}` : (d.getMonth() + 1);
const date = (d.getDate() < 10) ? `0${d.getDate()}` : d.getDate();
const hours = (d.getHours() < 10) ? `0${d.getHours()}` : d.getHours();
const minutes = (d.getMinutes() < 10) ? `0${d.getMinutes()}` : d.getMinutes();
const seconds = (d.getSeconds() < 10) ? `0${d.getSeconds()}` : d.getSeconds();
const time = `${hours}:${minutes}:${seconds}`;
const formattedDate = `${year}-${month}-${date} @${time}`;
$('div.wrapper', commandLog).append(`<p>${formattedDate} -- ${message}</p>`);
commandLog.scrollTop($('div.wrapper', commandLog).height());
}
// Method is called every time a valid tab change event is received
// callback = code to run when cleanup is finished
// default switch doesn't require callback to be set
@ -538,7 +526,7 @@ function GUI_checkOperatingSystem() {
const GUI = new GuiControl();
export { TABS };
// initialize object into GUI variable
window.GUI = GUI;
export default GUI;

21
src/js/gui_log.js Normal file
View File

@ -0,0 +1,21 @@
/**
* log to GUI
* @param {string} message message to log to GUI
*/
export function gui_log(message) {
const commandLog = $("div#log");
const d = new Date();
const year = d.getFullYear();
const month = d.getMonth() < 9 ? `0${d.getMonth() + 1}` : d.getMonth() + 1;
const date = d.getDate() < 10 ? `0${d.getDate()}` : d.getDate();
const hours = d.getHours() < 10 ? `0${d.getHours()}` : d.getHours();
const minutes = d.getMinutes() < 10 ? `0${d.getMinutes()}` : d.getMinutes();
const seconds = d.getSeconds() < 10 ? `0${d.getSeconds()}` : d.getSeconds();
const time = `${hours}:${minutes}:${seconds}`;
const formattedDate = `${year}-${month}-${date} @${time}`;
$("div.wrapper", commandLog).append(
`<p>${formattedDate} -- ${message}</p>`,
);
commandLog.scrollTop($("div.wrapper", commandLog).height());
}

View File

@ -1,6 +1,4 @@
'use strict';
const HUFFMAN_EOF = -1;
export const HUFFMAN_EOF = -1;
function huffmanDecodeBuf(inBuf, inBufCharacterCount, huffmanTree, huffmanLenIndex) {
let code = 0;
@ -57,3 +55,5 @@ function huffmanDecodeBuf(inBuf, inBufCharacterCount, huffmanTree, huffmanLenInd
return new Uint8Array(outBuf);
}
export default huffmanDecodeBuf;

View File

@ -1,6 +1,6 @@
import i18next from 'i18next';
import i18nextXHRBackend from 'i18next-xhr-backend';
import GUI from './gui.js';
import { gui_log } from './gui_log.js';
import { get as getConfig, set as setConfig } from './ConfigStorage.js';
const i18n = {};
@ -84,7 +84,7 @@ i18n.changeLanguage = function(languageSelected) {
setConfig({'userLanguageSelect': languageSelected});
i18next.changeLanguage(getValidLocale(languageSelected));
i18n.selectedLanguage = languageSelected;
GUI.log(i18n.getMessage('language_changed'));
gui_log(i18n.getMessage('language_changed'));
};
i18n.getMessage = function(messageID, parameters) {

View File

@ -1,14 +1,19 @@
import '../components/init.js';
import { gui_log } from './gui_log.js';
// same, msp seems to be everywhere used from global scope
import './msp/MSPHelper.js';
import { i18n } from './localization.js';
import GUI from './gui.js';
import { get as getConfig, set as setConfig } from './ConfigStorage.js';
import ReleaseChecker from './release_checker.js';
import { tracking, createAnalytics } from './Analytics.js';
import { initializeSerialBackend } from './serial_backend.js';
// Currently fc is everywhere, so we need to import it here
// till all is in modules
import './fc.js';
import './msp/MSPHelper.js';
import FC from './fc.js';
import CONFIGURATOR, { API_VERSION_1_42, API_VERSION_1_45 } from './data_storage.js';
import serial from './serial.js';
import CliAutoComplete from './CliAutoComplete.js';
import DarkTheme from './DarkTheme.js';
import UI_PHONES from './phones_ui.js';
$(document).ready(function () {
@ -215,8 +220,8 @@ function startProcess() {
// translate to user-selected language
i18n.localizePage();
GUI.log(i18n.getMessage('infoVersionOs', { operatingSystem: GUI.operating_system }));
GUI.log(i18n.getMessage('infoVersionConfigurator', { configuratorVersion: CONFIGURATOR.getDisplayVersion() }));
gui_log(i18n.getMessage('infoVersionOs', { operatingSystem: GUI.operating_system }));
gui_log(i18n.getMessage('infoVersionConfigurator', { configuratorVersion: CONFIGURATOR.getDisplayVersion() }));
if (GUI.isNWJS()) {
const nwWindow = GUI.nwGui.Window.get();
@ -291,12 +296,12 @@ function startProcess() {
const tabName = $(self).text();
if (tabRequiresConnection && !CONFIGURATOR.connectionValid) {
GUI.log(i18n.getMessage('tabSwitchConnectionRequired'));
gui_log(i18n.getMessage('tabSwitchConnectionRequired'));
return;
}
if (GUI.connect_lock) { // tab switching disabled while operation is in progress
GUI.log(i18n.getMessage('tabSwitchWaitForOperation'));
gui_log(i18n.getMessage('tabSwitchWaitForOperation'));
return;
}
@ -308,7 +313,7 @@ function startProcess() {
}
$('div.open_firmware_flasher a.flash').click();
} else if (GUI.allowedTabs.indexOf(tab) < 0) {
GUI.log(i18n.getMessage('tabSwitchUpgradeRequired', [tabName]));
gui_log(i18n.getMessage('tabSwitchUpgradeRequired', [tabName]));
return;
}
@ -690,7 +695,7 @@ function notifyOutdatedVersion(releaseData) {
if (semver.lt(CONFIGURATOR.version, CONFIGURATOR.latestVersion)) {
const message = i18n.getMessage('configuratorUpdateNotice', [CONFIGURATOR.latestVersion, CONFIGURATOR.latestVersionReleaseUrl]);
GUI.log(message);
gui_log(message);
const dialog = $('.dialogConfiguratorUpdate')[0];

View File

@ -1,4 +1,5 @@
'use strict';
import GUI from './gui';
import PortHandler from './port_handler';
const MDNS_INTERVAL = 10000;
const TCP_CHECK_INTERVAL = 5000;
@ -132,3 +133,5 @@ MdnsDiscovery.tcpCheck = function() {
}
}
};
export default MdnsDiscovery;

View File

@ -1,7 +1,7 @@
'use strict';
import FC from "./fc";
// generate mixer
const mixerList = [
export const mixerList = [
{ name: 'Tricopter', pos: 3, model: 'tricopter', image: 'tri', motors: 3, servos: true },
{ name: 'Quad +', pos: 2, model: 'quad_x', image: 'quad_p', motors: 4, servos: false },
{ name: 'Quad X', pos: 0, model: 'quad_x', image: 'quad_x', motors: 4, servos: false },
@ -151,3 +151,5 @@ Model.prototype.dispose = function () {
this.renderer.dispose();
}
};
export default Model;

View File

@ -1,4 +1,6 @@
'use strict';
import GUI from "./gui.js";
import CONFIGURATOR from "./data_storage.js";
import serial from "./serial.js";
const MSP = {
symbols: {
@ -407,3 +409,12 @@ const MSP = {
this.callbacks_cleanup();
},
};
MSP.SDCARD_STATE_NOT_PRESENT = 0;
MSP.SDCARD_STATE_FATAL = 1;
MSP.SDCARD_STATE_CARD_INIT = 2;
MSP.SDCARD_STATE_FS_INIT = 3;
MSP.SDCARD_STATE_READY = 4;
window.MSP = MSP;
export default MSP;

View File

@ -1,5 +1,3 @@
'use strict';
//MSPCodes needs to be re-integrated inside MSP object
const MSPCodes = {
MSP_API_VERSION: 1,
@ -205,3 +203,5 @@ const MSPCodes = {
PID_PROFILE_NAME: 3,
RATE_PROFILE_NAME: 4,
};
export default MSPCodes;

View File

@ -1,5 +1,13 @@
import MspHelper from "./MSPHelper";
import { read_serial } from "../serial_backend";
import { i18n } from "../localization";
import GUI from "../gui";
import MSP from "../msp";
import FC from "../fc";
import MSPCodes from "./MSPCodes";
import CONFIGURATOR from "../data_storage";
import serial from "../serial";
import { gui_log } from "../gui_log";
const MSPConnectorImpl = function () {
this.baud = undefined;
@ -37,7 +45,7 @@ MSPConnectorImpl.prototype.connect = function (port, baud, onConnectCallback, on
// disconnect after 10 seconds with error if we don't get IDENT data
GUI.timeout_add('msp_connector', function () {
if (!CONFIGURATOR.connectionValid) {
GUI.log(i18n.getMessage('noConfigurationReceived'));
gui_log(i18n.getMessage('noConfigurationReceived'));
disconnectAndCleanup();
}
@ -57,7 +65,7 @@ MSPConnectorImpl.prototype.connect = function (port, baud, onConnectCallback, on
self.onConnectCallback();
});
} else {
GUI.log(i18n.getMessage('serialPortOpenFail'));
gui_log(i18n.getMessage('serialPortOpenFail'));
self.onFailureCallback();
}
});

View File

@ -1,10 +1,17 @@
// NOTE: this is a circular dependency, needs investigating
import { bit_check, sensor_status, bit_set, update_dataflash_global } from "../serial_backend";
import { update_dataflash_global } from "../update_dataflash_global";
import { sensor_status } from "../sensor_helpers";
import { bit_check, bit_set } from "../bit";
import { i18n } from "../localization";
import GUI from "../gui";
import { gui_log } from "../gui_log";
import FC from "../fc";
import semver from 'semver';
import vtxDeviceStatusFactory from "../utils/VtxDeviceStatus/VtxDeviceStatusFactory";
import MSP from "../msp";
import MSPCodes from "./MSPCodes";
import { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_44, API_VERSION_1_45 } from '../data_storage';
import EscProtocols from "../utils/EscProtocols";
import huffmanDecodeBuf from "../huffman";
import { defaultHuffmanTree, defaultHuffmanLenIndex } from "../default_huffman_tree";
// Used for LED_STRIP
const ledDirectionLetters = ['n', 'e', 's', 'w', 'u', 'd']; // in LSB bit order
@ -2610,14 +2617,14 @@ MspHelper.prototype.setArmingEnabled = function(doEnable, disableRunawayTakeoffP
MSP.send_message(MSPCodes.MSP_ARMING_DISABLE, mspHelper.crunch(MSPCodes.MSP_ARMING_DISABLE), false, function () {
if (doEnable) {
GUI.log(i18n.getMessage('armingEnabled'));
gui_log(i18n.getMessage('armingEnabled'));
if (disableRunawayTakeoffPrevention) {
GUI.log(i18n.getMessage('runawayTakeoffPreventionDisabled'));
gui_log(i18n.getMessage('runawayTakeoffPreventionDisabled'));
} else {
GUI.log(i18n.getMessage('runawayTakeoffPreventionEnabled'));
gui_log(i18n.getMessage('runawayTakeoffPreventionEnabled'));
}
} else {
GUI.log(i18n.getMessage('armingDisabled'));
gui_log(i18n.getMessage('armingDisabled'));
}
if (onCompleteCallback) {
@ -2641,11 +2648,6 @@ MspHelper.prototype.sendSerialConfig = function(callback) {
MSP.send_message(mspCode, mspHelper.crunch(mspCode), false, callback);
};
MSP.SDCARD_STATE_NOT_PRESENT = 0; //TODO, move these to better place
MSP.SDCARD_STATE_FATAL = 1;
MSP.SDCARD_STATE_CARD_INIT = 2;
MSP.SDCARD_STATE_FS_INIT = 3;
MSP.SDCARD_STATE_READY = 4;
let mspHelper;
// This is temporary, till things are moved

View File

@ -1,4 +1,5 @@
'use strict';
import { i18n } from "./localization";
import FC from "./fc";
// return true if user has choose a special peripheral
function isPeripheralSelected(peripheralName) {
@ -30,3 +31,5 @@ function adjustBoxNameIfPeripheralWithModeID(modeId, defaultName) {
return defaultName;
}
export default adjustBoxNameIfPeripheralWithModeID;

View File

@ -1,4 +1,4 @@
'use strict';
import GUI from "./gui";
const UI_PHONES = {
background: '#background',
@ -85,3 +85,5 @@ const UI_PHONES = {
$(this.headerbar).removeClass('expand2 expand');
},
};
export default UI_PHONES;

View File

@ -1,8 +1,14 @@
'use strict';
import GUI from "./gui";
import FC from "./fc";
import { i18n } from "./localization";
import { generateVirtualApiVersions } from './utils/common';
import { get as getConfig } from "./ConfigStorage";
import serial from "./serial";
import MdnsDiscovery from "./mdns_discovery";
const TIMEOUT_CHECK = 500 ; // With 250 it seems that it produces a memory leak and slowdown in some versions, reason unknown
const usbDevices = { filters: [
export const usbDevices = { filters: [
{'vendorId': 1155, 'productId': 57105}, // STM Device in DFU Mode || Digital Radio in USB mode
{'vendorId': 10473, 'productId': 393}, // GD32 DFU Bootloader
] };
@ -36,8 +42,8 @@ PortHandler.reinitialize = function () {
if (this.usbCheckLoop) {
clearTimeout(this.usbCheckLoop);
}
this.showVirtualMode = ConfigStorage.get('showVirtualMode').showVirtualMode;
this.showAllSerialDevices = ConfigStorage.get('showAllSerialDevices').showAllSerialDevices;
this.showVirtualMode = getConfig('showVirtualMode').showVirtualMode;
this.showAllSerialDevices = getConfig('showAllSerialDevices').showAllSerialDevices;
this.check(); // start listening, check after TIMEOUT_CHECK ms
};
@ -420,3 +426,7 @@ PortHandler.flush_callbacks = function () {
return killed;
};
// temp workaround till everything is in modules
window.PortHandler = PortHandler;
export default PortHandler;

View File

@ -1,4 +1,4 @@
'use strict';
import serial from "./serial";
const PortUsage = {
previous_received: 0,
@ -36,3 +36,7 @@ const PortUsage = {
this.port_usage_up = 0;
},
};
// drop these after all is in modules
window.PortUsage = PortUsage;
export default PortUsage;

View File

@ -6,7 +6,18 @@
popular choices - 921600, 460800, 256000, 230400, 153600, 128000, 115200, 57600, 38400, 28800, 19200
*/
import MSPConnectorImpl from "../msp/MSPConnector";
import { bit_check } from "../serial_backend";
import GUI from "../gui";
import { i18n } from "../localization";
import MSP from "../msp";
import FC from "../fc";
import { bit_check } from "../bit";
import { gui_log } from "../gui_log";
import MSPCodes from "../msp/MSPCodes";
import PortUsage from "../port_usage";
import PortHandler, { usbDevices } from "../port_handler";
import { API_VERSION_1_42 } from "../data_storage";
import serial from "../serial";
import STM32DFU from "./stm32usbdfu";
const STM32_protocol = function () {
this.baud = null;
@ -85,7 +96,7 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
self.initialize();
} else {
GUI.log(i18n.getMessage('serialPortOpenFail'));
gui_log(i18n.getMessage('serialPortOpenFail'));
}
});
} else {
@ -106,7 +117,7 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
self.initialize();
} else {
GUI.connect_lock = false;
GUI.log(i18n.getMessage('serialPortOpenFail'));
gui_log(i18n.getMessage('serialPortOpenFail'));
}
});
}
@ -127,7 +138,7 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
if (failedAttempts > 100) {
clearInterval(dfuWaitInterval);
console.log(`failed to get DFU connection, gave up after 10 seconds`);
GUI.log(i18n.getMessage('serialPortOpenFail'));
gui_log(i18n.getMessage('serialPortOpenFail'));
GUI.connect_lock = false;
}
}
@ -144,7 +155,7 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
serial.connect(self.port, {bitrate: self.options.reboot_baud}, function (openInfo) {
if (!openInfo) {
GUI.connect_lock = false;
GUI.log(i18n.getMessage('serialPortOpenFail'));
gui_log(i18n.getMessage('serialPortOpenFail'));
return;
}
@ -164,7 +175,7 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
const onConnectHandler = function () {
GUI.log(i18n.getMessage('apiVersionReceived', [FC.CONFIG.apiVersion]));
gui_log(i18n.getMessage('apiVersionReceived', [FC.CONFIG.apiVersion]));
if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_42)) {
self.msp_connector.disconnect(function (disconnectionResult) {
@ -178,11 +189,11 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
MSP.send_message(MSPCodes.MSP_BOARD_INFO, false, false, () => {
if (bit_check(FC.CONFIG.targetCapabilities, FC.TARGET_CAPABILITIES_FLAGS.HAS_FLASH_BOOTLOADER)) {
// Board has flash bootloader
GUI.log(i18n.getMessage('deviceRebooting_flashBootloader'));
gui_log(i18n.getMessage('deviceRebooting_flashBootloader'));
console.log('flash bootloader detected');
rebootMode = 4; // MSP_REBOOT_BOOTLOADER_FLASH
} else {
GUI.log(i18n.getMessage('deviceRebooting_romBootloader'));
gui_log(i18n.getMessage('deviceRebooting_romBootloader'));
console.log('no flash bootloader detected');
rebootMode = 1; // MSP_REBOOT_BOOTLOADER_ROM;
}

View File

@ -10,7 +10,9 @@
that being said, it seems that certain level of CLRSTATUS is required before running another type of operation for
example switching from DNLOAD to UPLOAD, etc, clearning the state so device is in dfuIDLE is highly recommended.
*/
'use strict';
import GUI from "../gui";
import { i18n } from "../localization";
import { gui_log } from "../gui_log";
// Task for the brave ones. There are quite a few shadow variables which clash when
// const or let are used. So need to run thorough tests when chaning `var`
@ -100,7 +102,7 @@ STM32DFU_protocol.prototype.connect = function (device, hex, options, callback)
self.openDevice(result[0]);
} else {
console.log('USB DFU not found');
GUI.log(i18n.getMessage('stm32UsbDfuNotFound'));
gui_log(i18n.getMessage('stm32UsbDfuNotFound'));
}
});
};
@ -111,16 +113,16 @@ STM32DFU_protocol.prototype.openDevice = function (device) {
chrome.usb.openDevice(device, function (handle) {
if (checkChromeRuntimeError()) {
console.log('Failed to open USB device!');
GUI.log(i18n.getMessage('usbDeviceOpenFail'));
gui_log(i18n.getMessage('usbDeviceOpenFail'));
if (GUI.operating_system === 'Linux') {
GUI.log(i18n.getMessage('usbDeviceUdevNotice'));
gui_log(i18n.getMessage('usbDeviceUdevNotice'));
}
return;
}
self.handle = handle;
GUI.log(i18n.getMessage('usbDeviceOpened', handle.handle.toString()));
gui_log(i18n.getMessage('usbDeviceOpened', handle.handle.toString()));
console.log(`Device opened with Handle ID: ${handle.handle}`);
self.claimInterface(0);
});
@ -132,9 +134,9 @@ STM32DFU_protocol.prototype.closeDevice = function () {
chrome.usb.closeDevice(self.handle, function closed() {
if (checkChromeRuntimeError()) {
console.log('Failed to close USB device!');
GUI.log(i18n.getMessage('usbDeviceCloseFail'));
gui_log(i18n.getMessage('usbDeviceCloseFail'));
} else {
GUI.log(i18n.getMessage('usbDeviceClosed'));
gui_log(i18n.getMessage('usbDeviceClosed'));
console.log(`Device closed with Handle ID: ${self.handle.handle}`);
}
@ -634,7 +636,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
}
if (typeof nextAction !== "undefined") {
GUI.log(i18n.getMessage('dfu_device_flash_info', (self.flash_layout.total_size / 1024).toString()));
gui_log(i18n.getMessage('dfu_device_flash_info', (self.flash_layout.total_size / 1024).toString()));
// verify all addresses in the hex are writable.
@ -648,7 +650,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
}
if (unusableBlocks.length > 0) {
GUI.log(i18n.getMessage('dfu_hex_address_errors'));
gui_log(i18n.getMessage('dfu_hex_address_errors'));
TABS.firmware_flasher.flashingMessage(i18n.getMessage('dfu_hex_address_errors'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID);
self.leave();
} else {
@ -673,7 +675,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
var unprotect = function() {
console.log('Initiate read unprotect');
let messageReadProtected = i18n.getMessage('stm32ReadProtected');
GUI.log(messageReadProtected);
gui_log(messageReadProtected);
TABS.firmware_flasher.flashingMessage(messageReadProtected, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.ACTION);
self.controlTransfer('out', self.request.DNLOAD, 0, 0, 0, [0x92], function () { // 0x92 initiates read unprotect
@ -695,10 +697,10 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
self.controlTransfer('in', self.request.GETSTATUS, 0, 0, 6, 0, function (data, error) { // should stall/disconnect
if (error) { // we encounter an error, but this is expected. should be a stall.
console.log('Unprotect memory command ran successfully. Unplug flight controller. Connect again in DFU mode and try flashing again.');
GUI.log(i18n.getMessage('stm32UnprotectSuccessful'));
gui_log(i18n.getMessage('stm32UnprotectSuccessful'));
let messageUnprotectUnplug = i18n.getMessage('stm32UnprotectUnplug');
GUI.log(messageUnprotectUnplug);
gui_log(messageUnprotectUnplug);
TABS.firmware_flasher.flashingMessage(messageUnprotectUnplug, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.ACTION)
.flashProgress(0);
@ -706,7 +708,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
} else { // unprotecting the flight controller did not work. It did not reboot.
console.log('Failed to execute unprotect memory command');
GUI.log(i18n.getMessage('stm32UnprotectFailed'));
gui_log(i18n.getMessage('stm32UnprotectFailed'));
TABS.firmware_flasher.flashingMessage(i18n.getMessage('stm32UnprotectFailed'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID);
console.log(data);
self.cleanup();
@ -716,7 +718,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
} else {
console.log('Failed to initiate unprotect memory command');
let messageUnprotectInitFailed = i18n.getMessage('stm32UnprotectInitFailed');
GUI.log(messageUnprotectInitFailed);
gui_log(messageUnprotectInitFailed);
TABS.firmware_flasher.flashingMessage(messageUnprotectInitFailed, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID);
self.cleanup();
}
@ -736,7 +738,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
if (data[4] === self.state.dfuUPLOAD_IDLE && ob_data.length === self.chipInfo.option_bytes.total_size) {
console.log('Option bytes read successfully');
console.log('Chip does not appear read protected');
GUI.log(i18n.getMessage('stm32NotReadProtected'));
gui_log(i18n.getMessage('stm32NotReadProtected'));
// it is pretty safe to continue to erase flash
self.clearStatus(function() {
self.upload_procedure(2);
@ -785,14 +787,14 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
// if address load fails with this specific error though, it is very likely bc of read protection
if (loadAddressResponse[4] === self.state.dfuERROR && loadAddressResponse[0] === self.status.errVENDOR) {
// read protected
GUI.log(i18n.getMessage('stm32AddressLoadFailed'));
gui_log(i18n.getMessage('stm32AddressLoadFailed'));
self.clearStatus(unprotect);
return;
} else if (loadAddressResponse[4] === self.state.dfuDNLOAD_IDLE) {
console.log('Address load for option bytes sector succeeded.');
self.clearStatus(tryReadOB);
} else {
GUI.log(i18n.getMessage('stm32AddressLoadUnknown'));
gui_log(i18n.getMessage('stm32AddressLoadUnknown'));
self.cleanup();
}
};
@ -852,7 +854,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
if (page === erase_pages.length) {
console.log("Erase: complete");
GUI.log(i18n.getMessage('dfu_erased_kilobytes', (total_erased / 1024).toString()));
gui_log(i18n.getMessage('dfu_erased_kilobytes', (total_erased / 1024).toString()));
self.upload_procedure(4);
} else {
erase_page();
@ -1124,3 +1126,5 @@ STM32DFU_protocol.prototype.cleanup = function () {
// initialize object
const STM32DFU = new STM32DFU_protocol();
export default STM32DFU;

View File

@ -1,4 +1,4 @@
import GUI from "./gui";
import { gui_log } from "./gui_log";
import { i18n } from "./localization";
import { get as getStorage, set as setStorage } from "./SessionStorage";
@ -20,7 +20,7 @@ ReleaseChecker.prototype.loadReleaseData = function (processFunction) {
if (!cacheReleaseData || !cachedReleaseLastUpdate || releaseDataTimestamp - cachedReleaseLastUpdate > 3600 * 1000) {
$.get(self._releaseUrl, function (releaseData) {
GUI.log(i18n.getMessage('releaseCheckLoaded',[self._releaseName]));
gui_log(i18n.getMessage('releaseCheckLoaded',[self._releaseName]));
const data = {};
data[self._releaseDataTag] = releaseData;
@ -33,13 +33,13 @@ ReleaseChecker.prototype.loadReleaseData = function (processFunction) {
if (data['responseJSON']) {
message = data['responseJSON'].message;
}
GUI.log(i18n.getMessage('releaseCheckFailed',[self._releaseName,message]));
gui_log(i18n.getMessage('releaseCheckFailed',[self._releaseName,message]));
self._processReleaseData(cacheReleaseData, processFunction);
});
} else {
if (cacheReleaseData) {
GUI.log(i18n.getMessage('releaseCheckCached',[self._releaseName]));
gui_log(i18n.getMessage('releaseCheckCached',[self._releaseName]));
}
self._processReleaseData(cacheReleaseData, processFunction);
@ -51,7 +51,7 @@ ReleaseChecker.prototype._processReleaseData = function (releaseData, processFun
if (releaseData) {
processFunction(releaseData);
} else {
GUI.log(i18n.getMessage('releaseCheckNoInfo',[self._releaseName]));
gui_log(i18n.getMessage('releaseCheckNoInfo',[self._releaseName]));
processFunction();
}

88
src/js/sensor_helpers.js Normal file
View File

@ -0,0 +1,88 @@
import FC from './fc';
import { bit_check } from './bit';
export function have_sensor(sensors_detected, sensor_code) {
switch(sensor_code) {
case 'acc':
return bit_check(sensors_detected, 0);
case 'baro':
return bit_check(sensors_detected, 1);
case 'mag':
return bit_check(sensors_detected, 2);
case 'gps':
return bit_check(sensors_detected, 3);
case 'sonar':
return bit_check(sensors_detected, 4);
case 'gyro':
return bit_check(sensors_detected, 5);
}
return false;
}
export function sensor_status(sensors_detected) {
// initialize variable (if it wasn't)
if (!sensor_status.previous_sensors_detected) {
sensor_status.previous_sensors_detected = -1; // Otherwise first iteration will not be run if sensors_detected == 0
}
// update UI (if necessary)
if (sensor_status.previous_sensors_detected == sensors_detected) {
return;
}
// set current value
sensor_status.previous_sensors_detected = sensors_detected;
const eSensorStatus = $("div#sensor-status");
if (have_sensor(sensors_detected, "acc")) {
$(".accel", eSensorStatus).addClass("on");
$(".accicon", eSensorStatus).addClass("active");
} else {
$(".accel", eSensorStatus).removeClass("on");
$(".accicon", eSensorStatus).removeClass("active");
}
if (
(FC.CONFIG.boardType == 0 || FC.CONFIG.boardType == 2) &&
have_sensor(sensors_detected, "gyro")
) {
$(".gyro", eSensorStatus).addClass("on");
$(".gyroicon", eSensorStatus).addClass("active");
} else {
$(".gyro", eSensorStatus).removeClass("on");
$(".gyroicon", eSensorStatus).removeClass("active");
}
if (have_sensor(sensors_detected, "baro")) {
$(".baro", eSensorStatus).addClass("on");
$(".baroicon", eSensorStatus).addClass("active");
} else {
$(".baro", eSensorStatus).removeClass("on");
$(".baroicon", eSensorStatus).removeClass("active");
}
if (have_sensor(sensors_detected, "mag")) {
$(".mag", eSensorStatus).addClass("on");
$(".magicon", eSensorStatus).addClass("active");
} else {
$(".mag", eSensorStatus).removeClass("on");
$(".magicon", eSensorStatus).removeClass("active");
}
if (have_sensor(sensors_detected, "gps")) {
$(".gps", eSensorStatus).addClass("on");
$(".gpsicon", eSensorStatus).addClass("active");
} else {
$(".gps", eSensorStatus).removeClass("on");
$(".gpsicon", eSensorStatus).removeClass("active");
}
if (have_sensor(sensors_detected, "sonar")) {
$(".sonar", eSensorStatus).addClass("on");
$(".sonaricon", eSensorStatus).addClass("active");
} else {
$(".sonar", eSensorStatus).removeClass("on");
$(".sonaricon", eSensorStatus).removeClass("active");
}
}

View File

@ -1,4 +1,8 @@
'use strict';
import GUI from "./gui";
import { i18n } from "./localization";
import FC from "./fc";
import CONFIGURATOR from "./data_storage";
import { gui_log } from "./gui_log";
const serial = {
connected: false,
@ -64,7 +68,7 @@ const serial = {
self.failed = 0;
} else {
console.log(`${self.connectionType}: connection did not recover from last onReceiveError, disconnecting`);
GUI.log(i18n.getMessage('serialUnrecoverable'));
gui_log(i18n.getMessage('serialUnrecoverable'));
self.errorHandler(getInfo.error, 'receive');
}
} else {
@ -85,7 +89,7 @@ const serial = {
if (_info.paused) {
// assume unrecoverable, disconnect
console.log(`${self.connectionType}: connection did not recover from ${self.error} condition, disconnecting`);
GUI.log(i18n.getMessage('serialUnrecoverable'));
gui_log(i18n.getMessage('serialUnrecoverable'));
self.errorHandler(_info.error, 'receive');
}
else {
@ -104,7 +108,7 @@ const serial = {
case 'frame_error':
case 'parity_error':
GUI.log(i18n.getMessage(`serialError${inflection.camelize(info.error)}`));
gui_log(i18n.getMessage(`serialError${inflection.camelize(info.error)}`));
self.errorHandler(info.error, 'receive');
break;
case 'break': // This seems to be the error that is thrown under NW.js in Windows when the device reboots after typing 'exit' in CLI
@ -461,3 +465,5 @@ const serial = {
}
},
};
export default serial;

View File

@ -6,6 +6,18 @@ import Features from "./Features";
import VirtualFC from "./VirtualFC";
import Beepers from "./Beepers";
import FC from "./fc";
import MSP from "./msp";
import MSPCodes from "./msp/MSPCodes";
import PortUsage from "./port_usage";
import PortHandler from "./port_handler";
import CONFIGURATOR, { API_VERSION_1_45 } from "./data_storage";
import serial from "./serial";
import MdnsDiscovery from "./mdns_discovery";
import UI_PHONES from "./phones_ui";
import { bit_check } from './bit.js';
import { sensor_status, have_sensor } from "./sensor_helpers";
import { update_dataflash_global } from "./update_dataflash_global";
import { gui_log } from "./gui_log";
let mspHelper;
let connectionTimestamp;
@ -211,7 +223,7 @@ function setConnectionTimeout() {
// disconnect after 10 seconds with error if we don't get IDENT data
GUI.timeout_add('connecting', function () {
if (!CONFIGURATOR.connectionValid) {
GUI.log(i18n.getMessage('noConfigurationReceived'));
gui_log(i18n.getMessage('noConfigurationReceived'));
$('div.connect_controls a.connect').click(); // disconnect
}
@ -227,7 +239,7 @@ function onOpen(openInfo) {
// reset connecting_to
GUI.connecting_to = false;
GUI.log(i18n.getMessage('serialPortOpened', serial.connectionType === 'serial' ? [serial.connectionId] : [openInfo.socketId]));
gui_log(i18n.getMessage('serialPortOpened', serial.connectionType === 'serial' ? [serial.connectionId] : [openInfo.socketId]));
// save selected port with chrome.storage if the port differs
let result = ConfigStorage.get('last_used_port');
@ -258,7 +270,7 @@ function onOpen(openInfo) {
MSP.send_message(MSPCodes.MSP_API_VERSION, false, false, function () {
tracking.setFlightControllerData(tracking.DATA.API_VERSION, FC.CONFIG.apiVersion);
GUI.log(i18n.getMessage('apiVersionReceived', [FC.CONFIG.apiVersion]));
gui_log(i18n.getMessage('apiVersionReceived', [FC.CONFIG.apiVersion]));
if (semver.gte(FC.CONFIG.apiVersion, CONFIGURATOR.API_VERSION_ACCEPTED)) {
@ -268,11 +280,11 @@ function onOpen(openInfo) {
MSP.send_message(MSPCodes.MSP_FC_VERSION, false, false, function () {
tracking.setFlightControllerData(tracking.DATA.FIRMWARE_VERSION, FC.CONFIG.flightControllerVersion);
GUI.log(i18n.getMessage('fcInfoReceived', [FC.CONFIG.flightControllerIdentifier, FC.CONFIG.flightControllerVersion]));
gui_log(i18n.getMessage('fcInfoReceived', [FC.CONFIG.flightControllerIdentifier, FC.CONFIG.flightControllerVersion]));
MSP.send_message(MSPCodes.MSP_BUILD_INFO, false, false, function () {
GUI.log(i18n.getMessage('buildInfoReceived', [FC.CONFIG.buildInfo]));
gui_log(i18n.getMessage('buildInfoReceived', [FC.CONFIG.buildInfo]));
MSP.send_message(MSPCodes.MSP_BOARD_INFO, false, false, processBoardInfo);
});
@ -313,7 +325,7 @@ function onOpen(openInfo) {
tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'SerialPortFailed');
console.log('Failed to open serial port');
GUI.log(i18n.getMessage('serialPortOpenFail'));
gui_log(i18n.getMessage('serialPortOpenFail'));
abortConnect();
}
@ -354,7 +366,7 @@ function processBoardInfo() {
tracking.setFlightControllerData(tracking.DATA.MANUFACTURER_ID, FC.CONFIG.manufacturerId);
tracking.setFlightControllerData(tracking.DATA.MCU_TYPE, FC.getMcuType());
GUI.log(i18n.getMessage('boardInfoReceived', [FC.getHardwareName(), FC.CONFIG.boardVersion]));
gui_log(i18n.getMessage('boardInfoReceived', [FC.getHardwareName(), FC.CONFIG.boardVersion]));
if (bit_check(FC.CONFIG.targetCapabilities, FC.TARGET_CAPABILITIES_FLAGS.SUPPORTS_CUSTOM_DEFAULTS) && bit_check(FC.CONFIG.targetCapabilities, FC.TARGET_CAPABILITIES_FLAGS.HAS_CUSTOM_DEFAULTS) && FC.CONFIG.configurationState === FC.CONFIGURATION_STATES.DEFAULTS_BARE) {
const dialog = $('#dialogResetToCustomDefaults')[0];
@ -450,7 +462,7 @@ function processUid() {
tracking.setFlightControllerData(tracking.DATA.MCU_ID, objectHash.sha1(deviceIdentifier));
tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'Connected');
connectionTimestamp = Date.now();
GUI.log(i18n.getMessage('uniqueDeviceIdReceived', [deviceIdentifier]));
gui_log(i18n.getMessage('uniqueDeviceIdReceived', [deviceIdentifier]));
processCraftName();
});
@ -463,7 +475,7 @@ async function processCraftName() {
await MSP.promise(MSPCodes.MSP_NAME);
}
GUI.log(i18n.getMessage('craftNameReceived', semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_45) ? [FC.CONFIG.craftName] : [FC.CONFIG.name]));
gui_log(i18n.getMessage('craftNameReceived', semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_45) ? [FC.CONFIG.craftName] : [FC.CONFIG.name]));
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_45)) {
await MSP.promise(MSPCodes.MSP2_GET_TEXT, mspHelper.crunch(MSPCodes.MSP2_GET_TEXT, MSPCodes.PILOT_NAME));
@ -564,9 +576,9 @@ function onConnect() {
function onClosed(result) {
if (result) { // All went as expected
GUI.log(i18n.getMessage('serialPortClosedOk'));
gui_log(i18n.getMessage('serialPortClosedOk'));
} else { // Something went wrong
GUI.log(i18n.getMessage('serialPortClosedFail'));
gui_log(i18n.getMessage('serialPortClosedFail'));
}
$('#tabs ul.mode-connected').hide();
@ -606,90 +618,6 @@ export function read_serial(info) {
}
}
export function sensor_status(sensors_detected) {
// initialize variable (if it wasn't)
if (!sensor_status.previous_sensors_detected) {
sensor_status.previous_sensors_detected = -1; // Otherwise first iteration will not be run if sensors_detected == 0
}
// update UI (if necessary)
if (sensor_status.previous_sensors_detected == sensors_detected) {
return;
}
// set current value
sensor_status.previous_sensors_detected = sensors_detected;
const eSensorStatus = $('div#sensor-status');
if (have_sensor(sensors_detected, 'acc')) {
$('.accel', eSensorStatus).addClass('on');
$('.accicon', eSensorStatus).addClass('active');
} else {
$('.accel', eSensorStatus).removeClass('on');
$('.accicon', eSensorStatus).removeClass('active');
}
if ((FC.CONFIG.boardType == 0 || FC.CONFIG.boardType == 2) && have_sensor(sensors_detected, 'gyro')) {
$('.gyro', eSensorStatus).addClass('on');
$('.gyroicon', eSensorStatus).addClass('active');
} else {
$('.gyro', eSensorStatus).removeClass('on');
$('.gyroicon', eSensorStatus).removeClass('active');
}
if (have_sensor(sensors_detected, 'baro')) {
$('.baro', eSensorStatus).addClass('on');
$('.baroicon', eSensorStatus).addClass('active');
} else {
$('.baro', eSensorStatus).removeClass('on');
$('.baroicon', eSensorStatus).removeClass('active');
}
if (have_sensor(sensors_detected, 'mag')) {
$('.mag', eSensorStatus).addClass('on');
$('.magicon', eSensorStatus).addClass('active');
} else {
$('.mag', eSensorStatus).removeClass('on');
$('.magicon', eSensorStatus).removeClass('active');
}
if (have_sensor(sensors_detected, 'gps')) {
$('.gps', eSensorStatus).addClass('on');
$('.gpsicon', eSensorStatus).addClass('active');
} else {
$('.gps', eSensorStatus).removeClass('on');
$('.gpsicon', eSensorStatus).removeClass('active');
}
if (have_sensor(sensors_detected, 'sonar')) {
$('.sonar', eSensorStatus).addClass('on');
$('.sonaricon', eSensorStatus).addClass('active');
} else {
$('.sonar', eSensorStatus).removeClass('on');
$('.sonaricon', eSensorStatus).removeClass('active');
}
}
export function have_sensor(sensors_detected, sensor_code) {
switch(sensor_code) {
case 'acc':
return bit_check(sensors_detected, 0);
case 'baro':
return bit_check(sensors_detected, 1);
case 'mag':
return bit_check(sensors_detected, 2);
case 'gps':
return bit_check(sensors_detected, 3);
case 'sonar':
return bit_check(sensors_detected, 4);
case 'gyro':
return bit_check(sensors_detected, 5);
}
return false;
}
function startLiveDataRefreshTimer() {
// live data refresh
GUI.timeout_add('data_refresh', update_live_status, 100);
@ -753,61 +681,6 @@ async function update_live_status() {
}
}
export function bit_check(num, bit) {
return ((num >> bit) % 2 != 0);
}
export function bit_set(num, bit) {
return num | 1 << bit;
}
export function bit_clear(num, bit) {
return num & ~(1 << bit);
}
export function update_dataflash_global() {
function formatFilesize(bytes) {
if (bytes < 1024) {
return `${bytes}B`;
}
const kilobytes = bytes / 1024;
if (kilobytes < 1024) {
return `${Math.round(kilobytes)}kB`;
}
const megabytes = kilobytes / 1024;
return `${megabytes.toFixed(1)}MB`;
}
const supportsDataflash = FC.DATAFLASH.totalSize > 0;
if (supportsDataflash){
$(".noflash_global").css({
display: 'none',
});
$(".dataflash-contents_global").css({
display: 'block',
});
$(".dataflash-free_global").css({
width: `${100-(FC.DATAFLASH.totalSize - FC.DATAFLASH.usedSize) / FC.DATAFLASH.totalSize * 100}%`,
display: 'block',
});
$(".dataflash-free_global div").text(`Dataflash: free ${formatFilesize(FC.DATAFLASH.totalSize - FC.DATAFLASH.usedSize)}`);
} else {
$(".noflash_global").css({
display: 'block',
});
$(".dataflash-contents_global").css({
display: 'none',
});
}
}
export function reinitializeConnection(callback) {
// Close connection gracefully if it still exists.
@ -821,7 +694,7 @@ export function reinitializeConnection(callback) {
}
}
GUI.log(i18n.getMessage('deviceRebooting'));
gui_log(i18n.getMessage('deviceRebooting'));
let attempts = 0;
const reconnect = setInterval(waitforSerial, 100);
@ -831,7 +704,7 @@ export function reinitializeConnection(callback) {
console.log(`Serial connection available after ${attempts / 10} seconds`);
clearInterval(reconnect);
getStatus();
GUI.log(i18n.getMessage('deviceReady'));
gui_log(i18n.getMessage('deviceReady'));
if (callback === typeof('function')) {
callback();
}
@ -840,7 +713,7 @@ export function reinitializeConnection(callback) {
if (attempts > 100) {
clearInterval(reconnect);
console.log(`failed to get serial connection, gave up after 10 seconds`);
GUI.log(i18n.getMessage('serialPortOpenFail'));
gui_log(i18n.getMessage('serialPortOpenFail'));
}
}
}

View File

@ -1,6 +1,11 @@
import { i18n } from '../localization';
import GUI from '../gui';
import { mspHelper } from '../msp/MSPHelper';
import MSP from '../msp';
import FC from '../fc';
import MSPCodes from '../msp/MSPCodes';
import { API_VERSION_1_42 } from '../data_storage';
import { gui_log } from '../gui_log';
const adjustments = {};
@ -232,7 +237,7 @@ adjustments.initialize = function (callback) {
function save_to_eeprom() {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () {
GUI.log(i18n.getMessage('adjustmentsEepromSaved'));
gui_log(i18n.getMessage('adjustmentsEepromSaved'));
});
}

View File

@ -1,8 +1,13 @@
import { i18n } from '../localization';
import GUI from '../gui';
import { get as getConfig, set as setConfig } from '../ConfigStorage';
import { bit_check } from '../serial_backend';
import { bit_check } from '../bit';
import { mspHelper } from '../msp/MSPHelper';
import FC from '../fc';
import MSP from '../msp';
import MSPCodes from '../msp/MSPCodes';
import adjustBoxNameIfPeripheralWithModeID from '../peripherals';
import { gui_log } from '../gui_log';
const auxiliary = {};
@ -392,7 +397,7 @@ auxiliary.initialize = function (callback) {
function save_to_eeprom() {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () {
GUI.log(i18n.getMessage('auxiliaryEepromSaved'));
gui_log(i18n.getMessage('auxiliaryEepromSaved'));
});
}
});
@ -561,7 +566,6 @@ auxiliary.cleanup = function (callback) {
if (callback) callback();
};
window.TABS.auxiliary = auxiliary;
export {
auxiliary,
};

View File

@ -4,6 +4,11 @@ import GUI from '../gui';
import BuildApi from '../BuildApi';
import { tracking } from '../Analytics';
import { reinitializeConnection } from "../serial_backend";
import CONFIGURATOR from "../data_storage";
import serial from "../serial";
import CliAutoComplete from "../CliAutoComplete";
import UI_PHONES from "../phones_ui";
import { gui_log } from "../gui_log";
const cli = {
lineDelayMs: 15,
@ -503,7 +508,7 @@ cli.read = function (readInfo) {
if (this.cliBuffer === 'Rebooting') {
CONFIGURATOR.cliActive = false;
CONFIGURATOR.cliValid = false;
GUI.log(i18n.getMessage('cliReboot'));
gui_log(i18n.getMessage('cliReboot'));
reinitializeConnection();
}
@ -512,7 +517,7 @@ cli.read = function (readInfo) {
this.lastArrival = new Date().getTime();
if (!CONFIGURATOR.cliValid && validateText.indexOf('CLI') !== -1) {
GUI.log(i18n.getMessage('cliEnter'));
gui_log(i18n.getMessage('cliEnter'));
CONFIGURATOR.cliValid = true;
// begin output history with the prompt (last line of welcome message)
// this is to match the content of the history with what the user sees on this tab

View File

@ -4,6 +4,11 @@ import GUI from '../gui';
import { tracking } from "../Analytics";
import { reinitializeConnection } from '../serial_backend';
import { mspHelper } from '../msp/MSPHelper';
import FC from '../fc';
import MSP from '../msp';
import MSPCodes from '../msp/MSPCodes';
import { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_45 } from '../data_storage';
import { gui_log } from '../gui_log';
const configuration = {
analyticsChanges: {},
@ -549,7 +554,7 @@ configuration.initialize = function (callback) {
}
function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved'));
gui_log(i18n.getMessage('configurationEepromSaved'));
GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection);

View File

@ -2,7 +2,12 @@ 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 = {};
@ -366,7 +371,7 @@ failsafe.initialize = function (callback) {
}
function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved'));
gui_log(i18n.getMessage('configurationEepromSaved'));
GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection);

View File

@ -8,6 +8,13 @@ import { tracking } from "../Analytics";
import MspHelper from '../msp/MSPHelper';
import STM32 from '../protocols/stm32';
import FC from '../fc';
import MSP from '../msp';
import MSPCodes from '../msp/MSPCodes';
import PortHandler, { usbDevices } from '../port_handler';
import CONFIGURATOR, { API_VERSION_1_39 } from '../data_storage';
import serial from '../serial';
import STM32DFU from '../protocols/stm32usbdfu';
import { gui_log } from '../gui_log';
const firmware_flasher = {
targets: null,
@ -449,7 +456,7 @@ firmware_flasher.initialize = function (callback) {
if (!inComment && input.charCodeAt(i) > 255) {
self.flashingMessage(i18n.getMessage('firmwareFlasherConfigCorrupted'), self.FLASH_MESSAGE_TYPES.INVALID);
GUI.log(i18n.getMessage('firmwareFlasherConfigCorruptedLogMessage'));
gui_log(i18n.getMessage('firmwareFlasherConfigCorruptedLogMessage'));
return null;
}
@ -494,7 +501,7 @@ firmware_flasher.initialize = function (callback) {
STM32.connect(port, baud, firmware, options);
} else {
console.log('Please select valid serial port');
GUI.log(i18n.getMessage('firmwareFlasherNoValidPort'));
gui_log(i18n.getMessage('firmwareFlasherNoValidPort'));
}
} else {
tracking.sendEvent(tracking.EVENT_CATEGORIES.FLASHING, 'Flashing', self.fileName || null);
@ -532,10 +539,10 @@ firmware_flasher.initialize = function (callback) {
if (board !== target) {
boardSelect.val(board).trigger('change');
}
GUI.log(i18n.getMessage(targetAvailable ? 'firmwareFlasherBoardVerificationSuccess' : 'firmwareFlasherBoardVerficationTargetNotAvailable',
gui_log(i18n.getMessage(targetAvailable ? 'firmwareFlasherBoardVerificationSuccess' : 'firmwareFlasherBoardVerficationTargetNotAvailable',
{ boardName: board }));
} else {
GUI.log(i18n.getMessage('firmwareFlasherBoardVerificationFail'));
gui_log(i18n.getMessage('firmwareFlasherBoardVerificationFail'));
}
onClose();
}
@ -565,7 +572,7 @@ firmware_flasher.initialize = function (callback) {
MSP.listen(mspHelper.process_data.bind(mspHelper));
getBoard();
} else {
GUI.log(i18n.getMessage('serialPortOpenFail'));
gui_log(i18n.getMessage('serialPortOpenFail'));
}
}
@ -578,7 +585,7 @@ firmware_flasher.initialize = function (callback) {
baud = parseInt($('#flash_manual_baud_rate').val());
}
GUI.log(i18n.getMessage('firmwareFlasherDetectBoardQuery'));
gui_log(i18n.getMessage('firmwareFlasherDetectBoardQuery'));
const isLoaded = self.targets ? Object.keys(self.targets).length > 0 : false;
@ -593,7 +600,7 @@ firmware_flasher.initialize = function (callback) {
console.log('Releases not loaded yet');
}
} else {
GUI.log(i18n.getMessage('firmwareFlasherNoValidPort'));
gui_log(i18n.getMessage('firmwareFlasherNoValidPort'));
}
}
}
@ -789,7 +796,7 @@ firmware_flasher.initialize = function (callback) {
tracking.setFirmwareData(tracking.DATA.FIRMWARE_SOURCE, 'http');
if ($('select[name="firmware_version"]').val() === "0") {
GUI.log(i18n.getMessage('firmwareFlasherNoFirmwareSelected'));
gui_log(i18n.getMessage('firmwareFlasherNoFirmwareSelected'));
return;
}
@ -1090,7 +1097,7 @@ firmware_flasher.initialize = function (callback) {
});
} else {
console.log('You don\'t have write permissions for this file, sorry.');
GUI.log(i18n.getMessage('firmwareFlasherWritePermissions'));
gui_log(i18n.getMessage('firmwareFlasherWritePermissions'));
}
});
});
@ -1106,7 +1113,7 @@ firmware_flasher.initialize = function (callback) {
const port = resultPort[0];
if (!GUI.connect_lock) {
GUI.log(i18n.getMessage('firmwareFlasherFlashTrigger', [port]));
gui_log(i18n.getMessage('firmwareFlasherFlashTrigger', [port]));
console.log(`Detected: ${port} - triggering flash on connect`);
// Trigger regular Flashing sequence
@ -1114,7 +1121,7 @@ firmware_flasher.initialize = function (callback) {
$('a.flash_firmware').click();
}, 100); // timeout so bus have time to initialize after being detected by the system
} else {
GUI.log(i18n.getMessage('firmwareFlasherPreviousDevice', [port]));
gui_log(i18n.getMessage('firmwareFlasherPreviousDevice', [port]));
}
// Since current port_detected request was consumed, create new one

View File

@ -1,7 +1,9 @@
import { i18n } from "../localization";
import GUI from '../gui';
import { have_sensor } from "../serial_backend";
import { have_sensor } from "../sensor_helpers";
import FC from '../fc';
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
const gps = {};
gps.initialize = function (callback) {

View File

@ -2,6 +2,9 @@ import { i18n } from "../localization";
import GUI from '../gui';
import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import { gui_log } from "../gui_log";
const led_strip = {
wireMode: false,
@ -579,7 +582,7 @@ led_strip.initialize = function (callback, scrollPosition) {
function save_to_eeprom() {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function() {
GUI.log(i18n.getMessage('ledStripEepromSaved'));
gui_log(i18n.getMessage('ledStripEepromSaved'));
});
}
});

View File

@ -3,6 +3,10 @@ import GUI from '../gui';
import { i18n } from '../localization';
import { get as getConfig, set as setConfig } from '../ConfigStorage';
import FC from '../fc.js';
import MSP from '../msp.js';
import MSPCodes from '../msp/MSPCodes.js';
import CONFIGURATOR from '../data_storage.js';
import { gui_log } from '../gui_log.js';
const logging = {};
logging.initialize = function (callback) {
@ -86,7 +90,7 @@ logging.initialize = function (callback) {
$(this).text(i18n.getMessage('loggingStop'));
$(this).data("clicks", clicks !== true);
} else {
GUI.log(i18n.getMessage('loggingErrorOneProperty'));
gui_log(i18n.getMessage('loggingErrorOneProperty'));
}
} else {
GUI.interval_kill_all();
@ -96,10 +100,10 @@ logging.initialize = function (callback) {
$(this).data("clicks", !clicks);
}
} else {
GUI.log(i18n.getMessage('loggingErrorLogFile'));
gui_log(i18n.getMessage('loggingErrorLogFile'));
}
} else {
GUI.log(i18n.getMessage('loggingErrorNotConnected'));
gui_log(i18n.getMessage('loggingErrorNotConnected'));
}
});
@ -297,7 +301,7 @@ logging.initialize = function (callback) {
if (retaining) {
chrome.fileSystem.getDisplayPath(fileEntry, function (path) {
GUI.log(i18n.getMessage('loggingAutomaticallyRetained', [path]));
gui_log(i18n.getMessage('loggingAutomaticallyRetained', [path]));
});
}

View File

@ -6,9 +6,16 @@ import MotorOutputReorderComponent from "../../components/MotorOutputReordering/
import EscDshotDirectionComponent from "../../components/EscDshotDirection/EscDshotDirectionComponent";
import DshotCommand from "../../js/utils/DshotCommand.js";
import { tracking } from "../Analytics";
import { bit_check, reinitializeConnection } from "../serial_backend";
import { reinitializeConnection } from "../serial_backend";
import { bit_check } from "../bit";
import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc";
import MSP from "../msp";
import { mixerList } from "../model";
import MSPCodes from "../msp/MSPCodes";
import { API_VERSION_1_42, API_VERSION_1_44 } from "../data_storage";
import EscProtocols from "../utils/EscProtocols";
import { gui_log } from "../gui_log";
const motors = {
previousDshotBidir: null,
@ -1173,7 +1180,7 @@ motors.initialize = async function (callback) {
}
function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved'));
gui_log(i18n.getMessage('configurationEepromSaved'));
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection);
}

View File

@ -4,6 +4,10 @@ import { tracking } from "../Analytics";
import { reinitializeConnection } from "../serial_backend";
import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import CONFIGURATOR, { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_44, API_VERSION_1_45 } from "../data_storage";
import { gui_log } from "../gui_log";
let sdcardTimer;
@ -55,7 +59,7 @@ onboard_logging.initialize = function (callback) {
}
function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved'));
gui_log(i18n.getMessage('configurationEepromSaved'));
GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection);
@ -574,7 +578,7 @@ onboard_logging.initialize = function (callback) {
accepts: [{description: `${suffix.toUpperCase()} files`, extensions: [suffix]}]}, function(fileEntry) {
if (checkChromeRuntimeError()) {
if (chrome.runtime.lastError.message !== "User cancelled") {
GUI.log(i18n.getMessage('dataflashFileWriteFailed'));
gui_log(i18n.getMessage('dataflashFileWriteFailed'));
}
return;
}
@ -586,7 +590,7 @@ onboard_logging.initialize = function (callback) {
fileEntry.createWriter(function (fileWriter) {
fileWriter.onerror = function (e) {
GUI.log(`<strong><span class="message-negative">${i18n.getMessage('error', { errorMessage: e.target.error.message })}</span class="message-negative></strong>`);
gui_log(`<strong><span class="message-negative">${i18n.getMessage('error', { errorMessage: e.target.error.message })}</span class="message-negative></strong>`);
console.error(e);
@ -598,7 +602,7 @@ onboard_logging.initialize = function (callback) {
}, function (e) {
// File is not readable or does not exist!
console.error(e);
GUI.log(i18n.getMessage('dataflashFileWriteFailed'));
gui_log(i18n.getMessage('dataflashFileWriteFailed'));
});
});
}

View File

@ -1,6 +1,9 @@
import { i18n } from '../localization';
import GUI from '../gui';
import { get as getConfig, set as setConfig } from '../ConfigStorage';
import PortHandler from '../port_handler';
import CliAutoComplete from '../CliAutoComplete';
import DarkTheme from '../DarkTheme';
const options = {};
options.initialize = function (callback) {

View File

@ -1,9 +1,15 @@
import { i18n } from "../localization";
import GUI from '../gui';
import { tracking } from "../Analytics";
import { bit_check } from "../serial_backend";
import { bit_check } from "../bit";
import VirtualFC from "../VirtualFC";
import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import PortHandler from "../port_handler";
import CONFIGURATOR, { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_44, API_VERSION_1_45 } from "../data_storage";
import LogoManager from "../LogoManager";
import { gui_log } from "../gui_log";
const FONT = {};
const SYM = {};
@ -250,7 +256,7 @@ FONT.upload = function($progress) {
.then(function() {
console.log(`Uploaded all ${FONT.data.characters.length} characters`);
GUI.log(i18n.getMessage('osdSetupUploadingFontEnd', {length: FONT.data.characters.length}));
gui_log(i18n.getMessage('osdSetupUploadingFontEnd', {length: FONT.data.characters.length}));
OSD.GUI.fontManager.close();
@ -3245,7 +3251,7 @@ osd.initialize = function(callback) {
$('a.save').click(function() {
MSP.promise(MSPCodes.MSP_EEPROM_WRITE);
GUI.log(i18n.getMessage('osdSettingsSaved'));
gui_log(i18n.getMessage('osdSettingsSaved'));
const oldText = $(this).html();
$(this).html(i18n.getMessage('osdButtonSaved'));
setTimeout(() => {
@ -3365,7 +3371,7 @@ osd.initialize = function(callback) {
});
} else {
console.log('You don\'t have write permissions for this file, sorry.');
GUI.log(i18n.getMessage('osdWritePermissions'));
gui_log(i18n.getMessage('osdWritePermissions'));
}
});
});

View File

@ -2,9 +2,16 @@ import { i18n } from "../localization";
import { colorTables, getColorForPercentage } from '../utils/css.js';
import GUI from '../gui';
import { tracking } from "../Analytics";
import { have_sensor } from "../serial_backend";
import { have_sensor } from "../sensor_helpers";
import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc";
import MSP from "../msp";
import TuningSliders from "../TuningSliders";
import Model from "../model";
import RateCurve from "../RateCurve";
import MSPCodes from "../msp/MSPCodes";
import { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_44, API_VERSION_1_45 } from "../data_storage";
import { gui_log } from "../gui_log";
const pid_tuning = {
RATE_PROFILE_MASK: 128,
@ -1454,7 +1461,7 @@ pid_tuning.initialize = function (callback) {
self.refresh(function () {
self.updating = false;
GUI.log(i18n.getMessage('pidTuningPidProfileReset'));
gui_log(i18n.getMessage('pidTuningPidProfileReset'));
});
});
});
@ -1470,7 +1477,7 @@ pid_tuning.initialize = function (callback) {
$('.tab-pid_tuning select[name="profile"]').prop('disabled', 'false');
FC.CONFIG.profile = self.currentProfile;
GUI.log(i18n.getMessage('pidTuningLoadedProfile', [self.currentProfile + 1]));
gui_log(i18n.getMessage('pidTuningLoadedProfile', [self.currentProfile + 1]));
});
});
});
@ -1487,7 +1494,7 @@ pid_tuning.initialize = function (callback) {
FC.CONFIG.rateProfile = self.currentRateProfile;
self.currentRates = self.rateCurve.getCurrentRates();
GUI.log(i18n.getMessage('pidTuningLoadedRateProfile', [self.currentRateProfile + 1]));
gui_log(i18n.getMessage('pidTuningLoadedRateProfile', [self.currentRateProfile + 1]));
});
});
});
@ -1801,7 +1808,7 @@ pid_tuning.initialize = function (callback) {
$('a.refresh').click(function () {
self.refresh(function () {
GUI.log(i18n.getMessage('pidTuningDataRefreshed'));
gui_log(i18n.getMessage('pidTuningDataRefreshed'));
});
});
@ -2263,7 +2270,7 @@ pid_tuning.initialize = function (callback) {
self.setDirty(false);
GUI.log(i18n.getMessage('pidTuningEepromSaved'));
gui_log(i18n.getMessage('pidTuningEepromSaved'));
self.refresh();
});
@ -2429,12 +2436,12 @@ pid_tuning.checkUpdateProfile = function (updateRateProfile) {
self.refresh(function () {
self.updating = false;
if (changedProfile) {
GUI.log(i18n.getMessage('pidTuningReceivedProfile', [FC.CONFIG.profile + 1]));
gui_log(i18n.getMessage('pidTuningReceivedProfile', [FC.CONFIG.profile + 1]));
FC.CONFIG.profile = self.currentProfile;
}
if (changedRateProfile) {
GUI.log(i18n.getMessage('pidTuningReceivedRateProfile', [FC.CONFIG.rateProfile + 1]));
gui_log(i18n.getMessage('pidTuningReceivedRateProfile', [FC.CONFIG.rateProfile + 1]));
FC.CONFIG.rateProfile = self.currentRateProfile;
}
});

View File

@ -5,6 +5,11 @@ import { tracking } from "../Analytics";
import { reinitializeConnection } from '../serial_backend';
import { mspHelper } from '../msp/MSPHelper';
import FC from '../fc';
import MSP from '../msp';
import MSPCodes from '../msp/MSPCodes';
import { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_45 } from '../data_storage';
import BOARD from '../boards';
import { gui_log } from '../gui_log';
const ports = {
analyticsChanges: {},
@ -487,7 +492,7 @@ ports.initialize = function (callback) {
}
function on_saved_handler() {
GUI.log(i18n.getMessage('configurationEepromSaved'));
gui_log(i18n.getMessage('configurationEepromSaved'));
GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection);

View File

@ -3,6 +3,9 @@ import GUI from '../gui';
import { tracking } from "../Analytics";
import { mspHelper } from '../msp/MSPHelper';
import FC from '../fc';
import MSP from '../msp';
import MSPCodes from '../msp/MSPCodes';
import { gui_log } from '../gui_log';
const power = {
supported: false,
@ -500,7 +503,7 @@ power.initialize = function (callback) {
}
function save_completed() {
GUI.log(i18n.getMessage('configurationEepromSaved'));
gui_log(i18n.getMessage('configurationEepromSaved'));
TABS.power.initialize();
}

View File

@ -2,9 +2,18 @@ import { i18n } from "../localization";
import GUI from '../gui';
import { get as getConfig, set as setConfig } from '../ConfigStorage';
import { tracking } from "../Analytics";
import { bit_check, reinitializeConnection } from "../serial_backend";
import { reinitializeConnection } from "../serial_backend";
import { bit_check } from "../bit";
import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc";
import MSP from "../msp";
import Model from "../model";
import RateCurve from "../RateCurve";
import MSPCodes from "../msp/MSPCodes";
import windowWatcherUtil from "../utils/window_watchers";
import CONFIGURATOR, { API_VERSION_1_42, API_VERSION_1_43, API_VERSION_1_44, API_VERSION_1_45 } from "../data_storage";
import DarkTheme from "../DarkTheme";
import { gui_log } from "../gui_log";
import CryptoES from 'crypto-es';
@ -417,7 +426,7 @@ receiver.initialize = function (callback) {
$('a.refresh').click(function () {
tab.refresh(function () {
GUI.log(i18n.getMessage('receiverDataRefreshed'));
gui_log(i18n.getMessage('receiverDataRefreshed'));
});
});
@ -489,7 +498,7 @@ receiver.initialize = function (callback) {
}
function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved'));
gui_log(i18n.getMessage('configurationEepromSaved'));
if (boot) {
GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection);
@ -549,7 +558,7 @@ receiver.initialize = function (callback) {
$("a.bind").click(function() {
MSP.send_message(MSPCodes.MSP2_BETAFLIGHT_BIND);
GUI.log(i18n.getMessage('receiverButtonBindMessage'));
gui_log(i18n.getMessage('receiverButtonBindMessage'));
});
}
$(".bind_btn").toggle(showBindButton);

View File

@ -1,4 +1,5 @@
"use strict";
import windowWatcherUtil from "../utils/window_watchers";
import { i18n } from "../localization";
const css_dark = [
'/css/dark-theme.css',
@ -42,8 +43,9 @@ let gimbalElems;
let sliderElems;
let enableTX = false;
// NOTE: import should be enough right?
// This is a hack to get the i18n var of the parent, but the localizePage not works
const i18n = opener.i18n;
// const i18n = opener.i18n;
const watchers = {
darkTheme: (val) => {

View File

@ -1,8 +1,11 @@
import { i18n } from "../localization";
import GUI from '../gui';
import { get as getConfig, set as setConfig } from '../ConfigStorage';
import { have_sensor } from "../serial_backend";
import { have_sensor } from "../sensor_helpers";
import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import serial from "../serial";
const sensors = {};
sensors.initialize = function (callback) {

View File

@ -2,6 +2,9 @@ import { i18n } from "../localization";
import GUI from '../gui';
import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import { gui_log } from "../gui_log";
const servos = {};
servos.initialize = function (callback) {
@ -137,7 +140,7 @@ servos.initialize = function (callback) {
function save_to_eeprom() {
if (save_configuration_to_eeprom) {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () {
GUI.log(i18n.getMessage('servosEepromSave'));
gui_log(i18n.getMessage('servosEepromSave'));
});
}
}

View File

@ -1,9 +1,14 @@
import { i18n } from '../localization';
import GUI from '../gui';
import { configuration_backup, configuration_restore } from '../backup_restore';
import { have_sensor } from '../serial_backend';
import { have_sensor } from '../sensor_helpers';
import { mspHelper } from '../msp/MSPHelper';
import FC from '../fc';
import MSP from '../msp';
import Model from '../model';
import MSPCodes from '../msp/MSPCodes';
import CONFIGURATOR, { API_VERSION_1_42, API_VERSION_1_43 } from '../data_storage';
import { gui_log } from '../gui_log';
const setup = {
yaw_fix: 0.0,
@ -34,13 +39,13 @@ setup.initialize = function (callback) {
const backupButton = $('#content .backup');
const restoreButton = $('#content .restore');
backupButton.on('click', () => configuration_backup(() => GUI.log(i18n.getMessage('initialSetupBackupSuccess'))));
backupButton.on('click', () => configuration_backup(() => gui_log(i18n.getMessage('initialSetupBackupSuccess'))));
restoreButton.on('click', () => configuration_restore(() => {
// get latest settings
TABS.setup.initialize();
GUI.log(i18n.getMessage('initialSetupRestoreSuccess'));
gui_log(i18n.getMessage('initialSetupRestoreSuccess'));
}));
if (CONFIGURATOR.virtualMode) {
@ -109,7 +114,7 @@ setup.initialize = function (callback) {
// until this operation finishes, sending more commands through data_poll() will result in serial buffer overflow
GUI.interval_pause('setup_data_pull');
MSP.send_message(MSPCodes.MSP_ACC_CALIBRATION, false, false, function () {
GUI.log(i18n.getMessage('initialSetupAccelCalibStarted'));
gui_log(i18n.getMessage('initialSetupAccelCalibStarted'));
$('#accel_calib_running').show();
$('#accel_calib_rest').hide();
});
@ -117,7 +122,7 @@ setup.initialize = function (callback) {
GUI.timeout_add('button_reset', function () {
GUI.interval_resume('setup_data_pull');
GUI.log(i18n.getMessage('initialSetupAccelCalibEnded'));
gui_log(i18n.getMessage('initialSetupAccelCalibEnded'));
_self.removeClass('calibrating');
$('#accel_calib_running').hide();
$('#accel_calib_rest').show();
@ -132,13 +137,13 @@ setup.initialize = function (callback) {
_self.addClass('calibrating');
MSP.send_message(MSPCodes.MSP_MAG_CALIBRATION, false, false, function () {
GUI.log(i18n.getMessage('initialSetupMagCalibStarted'));
gui_log(i18n.getMessage('initialSetupMagCalibStarted'));
$('#mag_calib_running').show();
$('#mag_calib_rest').hide();
});
GUI.timeout_add('button_reset', function () {
GUI.log(i18n.getMessage('initialSetupMagCalibEnded'));
gui_log(i18n.getMessage('initialSetupMagCalibEnded'));
_self.removeClass('calibrating');
$('#mag_calib_running').hide();
$('#mag_calib_rest').show();
@ -159,7 +164,7 @@ setup.initialize = function (callback) {
$('.dialogConfirmReset-confirmbtn').click(function() {
dialogConfirmReset.close();
MSP.send_message(MSPCodes.MSP_RESET_CONF, false, false, function () {
GUI.log(i18n.getMessage('initialSetupSettingsRestored'));
gui_log(i18n.getMessage('initialSetupSettingsRestored'));
GUI.tab_switch_cleanup(function () {
TABS.setup.initialize();

View File

@ -1,5 +1,8 @@
import { i18n } from "../localization";
import GUI from '../gui';
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import { gui_log } from "../gui_log";
const setup_osd = {
};
@ -35,7 +38,7 @@ setup_osd.initialize = function (callback) {
$('a.resetSettings').click(function () {
MSP.send_message(MSPCodes.MSP_RESET_CONF, false, false, function () {
GUI.log(i18n.getMessage('initialSetupSettingsRestored'));
gui_log(i18n.getMessage('initialSetupSettingsRestored'));
GUI.tab_switch_cleanup(function () {
TABS.setup_osd.initialize();

View File

@ -3,6 +3,9 @@ import GUI from '../gui';
import { reinitializeConnection } from "../serial_backend";
import { mspHelper } from '../msp/MSPHelper';
import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import { gui_log } from "../gui_log";
const transponder = {
available: false,
@ -300,7 +303,7 @@ transponder.initialize = function(callback) {
function save_to_eeprom() {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function() {
GUI.log(i18n.getMessage('transponderEepromSaved'));
gui_log(i18n.getMessage('transponderEepromSaved'));
if ( $(_this).hasClass('reboot') ) {
GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection);
@ -312,7 +315,7 @@ transponder.initialize = function(callback) {
if (FC.TRANSPONDER.provider !== "0" && FC.TRANSPONDER.data.length !== FC.TRANSPONDER.providers.find(function(provider) {
return provider.id == FC.TRANSPONDER.provider;
}).dataLength ) {
GUI.log(i18n.getMessage('transponderDataInvalid'));
gui_log(i18n.getMessage('transponderDataInvalid'));
} else {
save_transponder_data();
}

View File

@ -5,6 +5,11 @@ import { tracking } from "../Analytics";
import { mspHelper } from "../msp/MSPHelper";
import FC from '../fc';
import { VtxDeviceTypes } from '../utils/VtxDeviceStatus/VtxDeviceStatus';
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import { API_VERSION_1_42, API_VERSION_1_44 } from '../data_storage';
import UI_PHONES from "../phones_ui";
import { gui_log } from "../gui_log";
const vtx = {
supported: false,
@ -639,7 +644,7 @@ vtx.initialize = function (callback) {
writer.onerror = function(){
console.error('Failed to write VTX table lua file');
GUI.log(i18n.getMessage('vtxSavedLuaFileKo'));
gui_log(i18n.getMessage('vtxSavedLuaFileKo'));
};
writer.onwriteend = function() {
@ -652,7 +657,7 @@ vtx.initialize = function (callback) {
writer.onwriteend = function() {
tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'VtxTableLuaSave', text.length);
console.log('Write VTX table lua file end');
GUI.log(i18n.getMessage('vtxSavedLuaFileOk'));
gui_log(i18n.getMessage('vtxSavedLuaFileOk'));
};
writer.write(data);
@ -662,7 +667,7 @@ vtx.initialize = function (callback) {
}, function (){
console.error('Failed to get VTX table lua file writer');
GUI.log(i18n.getMessage('vtxSavedLuaFileKo'));
gui_log(i18n.getMessage('vtxSavedLuaFileKo'));
});
});
}
@ -690,7 +695,7 @@ vtx.initialize = function (callback) {
writer.onerror = function(){
console.error('Failed to write VTX file');
GUI.log(i18n.getMessage('vtxSavedFileKo'));
gui_log(i18n.getMessage('vtxSavedFileKo'));
};
writer.onwriteend = function() {
@ -704,7 +709,7 @@ vtx.initialize = function (callback) {
tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'VtxTableSave', text.length);
console.log(vtxConfig);
console.log('Write VTX file end');
GUI.log(i18n.getMessage('vtxSavedFileOk'));
gui_log(i18n.getMessage('vtxSavedFileOk'));
};
writer.write(data);
@ -714,7 +719,7 @@ vtx.initialize = function (callback) {
}, function (){
console.error('Failed to get VTX file writer');
GUI.log(i18n.getMessage('vtxSavedFileKo'));
gui_log(i18n.getMessage('vtxSavedFileKo'));
});
});
}
@ -756,20 +761,20 @@ vtx.initialize = function (callback) {
self.analyticsChanges['VtxTableLoadFromFile'] = file.name;
console.log('Load VTX file end');
GUI.log(i18n.getMessage('vtxLoadFileOk'));
gui_log(i18n.getMessage('vtxLoadFileOk'));
},
function() {
// JSON is NOT valid
console.error('VTX Config from file failed validation against schema');
GUI.log(i18n.getMessage('vtxLoadFileKo'));
gui_log(i18n.getMessage('vtxLoadFileKo'));
},
);
} catch (err) {
console.error('Failed loading VTX file config');
GUI.log(i18n.getMessage('vtxLoadFileKo'));
gui_log(i18n.getMessage('vtxLoadFileKo'));
}
};
@ -777,7 +782,7 @@ vtx.initialize = function (callback) {
}, function() {
console.error('Failed to get VTX file reader');
GUI.log(i18n.getMessage('vtxLoadFileKo'));
gui_log(i18n.getMessage('vtxLoadFileKo'));
});
});
}
@ -806,25 +811,25 @@ vtx.initialize = function (callback) {
self.analyticsChanges['VtxTableLoadFromClipboard'] = text.length;
console.log('Load VTX clipboard end');
GUI.log(i18n.getMessage('vtxLoadClipboardOk'));
gui_log(i18n.getMessage('vtxLoadClipboardOk'));
},
function() {
// JSON is NOT valid
GUI.log(i18n.getMessage('vtxLoadClipboardKo'));
gui_log(i18n.getMessage('vtxLoadClipboardKo'));
console.error('VTX Config from clipboard failed validation against schema');
},
);
}, function(err) {
GUI.log(i18n.getMessage('vtxLoadClipboardKo'));
gui_log(i18n.getMessage('vtxLoadClipboardKo'));
console.error('Failed to read clipboard contents: ', err);
},
);
} catch (err) {
console.error(`Failed loading VTX file config: ${err}`);
GUI.log(i18n.getMessage('vtxLoadClipboardKo'));
gui_log(i18n.getMessage('vtxLoadClipboardKo'));
}
}
@ -887,7 +892,7 @@ vtx.initialize = function (callback) {
}
function save_completed() {
GUI.log(i18n.getMessage('configurationEepromSaved'));
gui_log(i18n.getMessage('configurationEepromSaved'));
TABS.vtx.vtxTableSavePending = false;

View File

@ -0,0 +1,44 @@
import FC from "./fc";
export function update_dataflash_global() {
function formatFilesize(bytes) {
if (bytes < 1024) {
return `${bytes}B`;
}
const kilobytes = bytes / 1024;
if (kilobytes < 1024) {
return `${Math.round(kilobytes)}kB`;
}
const megabytes = kilobytes / 1024;
return `${megabytes.toFixed(1)}MB`;
}
const supportsDataflash = FC.DATAFLASH.totalSize > 0;
if (supportsDataflash){
$(".noflash_global").css({
display: 'none',
});
$(".dataflash-contents_global").css({
display: 'block',
});
$(".dataflash-free_global").css({
width: `${100-(FC.DATAFLASH.totalSize - FC.DATAFLASH.usedSize) / FC.DATAFLASH.totalSize * 100}%`,
display: 'block',
});
$(".dataflash-free_global div").text(`Dataflash: free ${formatFilesize(FC.DATAFLASH.totalSize - FC.DATAFLASH.usedSize)}`);
} else {
$(".noflash_global").css({
display: 'block',
});
$(".dataflash-contents_global").css({
display: 'none',
});
}
}

View File

@ -1,4 +1,4 @@
'use strict';
import { API_VERSION_1_42, API_VERSION_1_43 } from '../data_storage';
class EscProtocols
{
@ -71,3 +71,5 @@ class EscProtocols
}
export default EscProtocols;

View File

@ -1,3 +1,5 @@
import VtxDeviceStatus from './VtxDeviceStatus';
const vtxDeviceStatusFactory = {
_vtxDeviceStatusClasses: [],

View File

@ -1,4 +1,6 @@
import semver from "semver";
import { mixerList } from "../model";
import CONFIGURATOR from "../data_storage";
export function millitime() {
return new Date().getTime();

View File

@ -1,5 +1,3 @@
'use strict';
/*
This utility is intended to communicate between chrome windows.
One window could watch passed values from another window and react to them.
@ -57,3 +55,5 @@ windowWatcherUtil.passValue = function(windows, key, val) {
applyBinding(windows, key, val);
}
};
export default windowWatcherUtil;

View File

@ -78,34 +78,11 @@
<script type="text/javascript" src="./node_modules/bluebird/js/browser/bluebird.min.js"></script>
<script type="text/javascript" src="./js/libraries/jquery.ba-throttle-debounce.min.js"></script>
<script type="text/javascript" src="./node_modules/inflection/lib/inflection.js"></script>
<script type="text/javascript" src="./js/libraries/analytics.js"></script>
<script type="text/javascript" src="./js/utils/window_watchers.js"></script>
<script type="text/javascript" src="./js/data_storage.js"></script>
<script type="text/javascript" src="./js/port_handler.js"></script>
<script type="text/javascript" src="./js/port_usage.js"></script>
<script type="text/javascript" src="./js/serial.js"></script>
<script type="text/javascript" src="./js/mdns_discovery.js"></script>
<script type="text/javascript" src="./js/huffman.js"></script>
<script type="text/javascript" src="./js/default_huffman_tree.js"></script>
<script type="text/javascript" src="./js/model.js"></script>
<script type="text/javascript" src="./js/msp/MSPCodes.js"></script>
<script type="text/javascript" src="./js/msp.js"></script>
<script type="text/javascript" src="./js/peripherals.js"></script>
<script type="text/javascript" src="./js/protocols/stm32usbdfu.js"></script>
<script type="text/javascript" src="./js/boards.js"></script>
<script type="text/javascript" src="./js/RateCurve.js"></script>
<script type="text/javascript" src="./js/GitHubApi.js"></script>
<script type="module" src="./js/main.js"></script>
<script type="text/javascript" src="./js/LogoManager.js"></script>
<script type="text/javascript" src="./node_modules/jquery-textcomplete/dist/jquery.textcomplete.min.js"></script>
<script type="text/javascript" src="./js/CliAutoComplete.js"></script>
<script type="text/javascript" src="./js/DarkTheme.js"></script>
<script type="text/javascript" src="./js/TuningSliders.js"></script>
<script type="text/javascript" src="./js/phones_ui.js"></script>
<script type="text/javascript" src="./node_modules/jquery-touchswipe/jquery.touchSwipe.min.js"></script>
<script type="text/javascript" src="./node_modules/select2/dist/js/select2.min.js"></script>
<script type="text/javascript" src="./node_modules/multiple-select/dist/multiple-select.min.js"></script>
<script type="text/javascript" src="./js/utils/EscProtocols.js"></script>
<script type="module" src="./js/main.js"></script>
<title></title>
</head>

View File

@ -1,5 +1,8 @@
import GUI from "../../js/gui";
import { i18n } from "../../js/localization";
import CONFIGURATOR from "../../js/data_storage";
import serial from "../../js/serial";
import { gui_log } from "../../js/gui_log";
export default class CliEngine
{
@ -208,13 +211,13 @@ export default class CliEngine
if (this.cliBuffer === 'Rebooting' && CliEngine.s_backspaceCode !== charCode) {
CONFIGURATOR.cliEngineActive = false;
CONFIGURATOR.cliEngineValid = false;
GUI.log(i18n.getMessage('cliReboot'));
gui_log(i18n.getMessage('cliReboot'));
reinitializeConnection(this._currentTab);
}
}
if (!CONFIGURATOR.cliEngineValid && validateText.indexOf('CLI') !== -1) {
GUI.log(i18n.getMessage('cliEnter'));
gui_log(i18n.getMessage('cliEnter'));
CONFIGURATOR.cliEngineValid = true;
}
}

View File

@ -2,6 +2,7 @@ import GUI from "../../../js/gui";
import { i18n } from "../../../js/localization";
import PickedPreset from "../PickedPreset";
import PresetTitlePanel from "../TitlePanel/PresetTitlePanel";
import FC from "../../../js/fc";
export default class PresetsDetailedDialog {
constructor(domDialog, pickedPresetList, onPresetPickedCallback, favoritePresets) {

View File

@ -1,6 +1,9 @@
import GUI from '../../js/gui';
import { get as getConfig, set as setConfig } from '../../js/ConfigStorage';
import { i18n } from '../../js/localization';
import FC from '../../js/fc';
import CONFIGURATOR from '../../js/data_storage';
import UI_PHONES from '../../js/phones_ui';
import { favoritePresets } from './FavoritePresets';
import CliEngine from './CliEngine';

View File

@ -1,60 +0,0 @@
const commonjs = require("@rollup/plugin-commonjs");
const resolve = require("@rollup/plugin-node-resolve").default;
const rollupReplace = require("@rollup/plugin-replace");
const NODE_ENV = process.env.NODE_ENV || 'test';
module.exports = function(config) {
config.set({
reporters: ['tfs', 'spec','junit'],
basePath: '../',
frameworks: ['mocha', 'chai', 'sinon-chai'],
files: [
'./node_modules/jquery/dist/jquery.min.js',
'./node_modules/jquery-textcomplete/dist/jquery.textcomplete.min.js',
'./node_modules/bluebird/js/browser/bluebird.min.js',
'./node_modules/jbox/dist/jBox.min.js',
'./src/js/msp.js',
'./src/js/serial.js',
'./src/js/data_storage.js',
{ pattern: './src/js/localization.js', type: 'module', watched: false },
{ pattern: './src/js/gui.js', type: 'module', watched: false },
'./src/js/CliAutoComplete.js',
{ pattern: './src/js/tabs/cli.js', type: 'module', watched: false },
'./src/js/phones_ui.js',
'./test/**/*.js',
],
browsers: ['ChromeHeadlessNoSandbox'],
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: 'ChromeHeadless',
flags: ['--no-sandbox'],
},
},
tfsReporter: {
outputDir: 'testresults',
outputFile: 'test_results.xml',
},
junitReporter: {
outputDir: 'test-results-junit',
},
singleRun: true,
preprocessors: {
'./src/js/localization.js': ['rollup'],
'./src/js/tabs/cli.js': ['rollup'],
'./src/js/gui.js': ['rollup'],
},
rollupPreprocessor: {
plugins: [
rollupReplace({
'process.env.NODE_ENV': JSON.stringify(NODE_ENV),
}),
resolve(),
commonjs(),
],
output: {
format: 'esm',
},
},
});
};

26
test/setup.js Normal file
View File

@ -0,0 +1,26 @@
import "bluebird";
import { JSDOM } from "jsdom";
import $ from "jquery";
import { vi } from "vitest";
import jBox from "jbox";
// Note: this can go away once jquery is used as module everywhere
const { window } = new JSDOM("");
$(window);
globalThis.$ = $;
globalThis.jQuery = $;
globalThis.jBox = jBox;
Object.defineProperty(window, "matchMedia", {
writable: true,
value: vi.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: vi.fn(), // deprecated
removeListener: vi.fn(), // deprecated
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
dispatchEvent: vi.fn(),
})),
});

View File

@ -1,279 +0,0 @@
class MockAnalytics {
EVENT_CATEGORIES = {};
sendEvent() {
// Empty
}
}
let tracking;
describe('TABS.cli', () => {
function toArrayBuffer(string) {
const bufferOut = new ArrayBuffer(string.length);
const bufView = new Uint8Array(bufferOut);
for (let i = 0; i < string.length; i++) {
bufView[i] = string.charCodeAt(i);
}
return bufferOut;
}
describe('output', () => {
const cliTab = $('<div>').addClass('tab-cli');
const cliOutput = $('<div>').addClass('wrapper');
const cliPrompt = $('<textarea name="commands">');
cliTab.append($('<div>').addClass('window').append(cliOutput));
cliTab.append(cliPrompt);
CliAutoComplete.setEnabled(false); // not testing the client-side autocomplete
before(() => {
tracking = new MockAnalytics();
$('body').append(cliTab);
CONFIGURATOR.cliValid = true;
TABS.cli.GUI.windowWrapper = cliOutput;
});
after(() => cliTab.remove());
beforeEach(() => {
cliOutput.empty();
cliPrompt.val('');
TABS.cli.cliBuffer = "";
});
it('ambiguous auto-complete results', () => {
TABS.cli.cliBuffer = 'se';
TABS.cli.read({
data: toArrayBuffer('\r\033[Kserialpassthrough\tservo\r\n# ser'),
});
// Ambigous auto-complete from firmware is preceded with an \r carriage return
// which only renders a line break on Mac
const expectedValue = GUI.operating_system !== "Windows" ?
'se<br>serialpassthrough\tservo<br>' :
'seserialpassthrough\tservo<br>';
expect(cliOutput.html()).to.equal(expectedValue);
expect(cliPrompt.val()).to.equal('ser');
});
it('unambiguous auto-complete result', () => {
TABS.cli.read({
data: toArrayBuffer('serialpassthrough'),
});
expect(cliOutput.html()).to.equal('');
expect(cliPrompt.val()).to.equal('serialpassthrough');
});
it('unambiguous auto-complete result with partial buffer', () => {
TABS.cli.cliBuffer = 'serial';
TABS.cli.read({
data: toArrayBuffer('passthrough'),
});
expect(cliOutput.html()).to.equal('');
expect(cliPrompt.val()).to.equal('serialpassthrough');
});
it("escape characters are skipped", () => {
TABS.cli.read({
data: toArrayBuffer('\033[K'),
});
expect(cliOutput.html()).to.equal('');
expect(cliPrompt.val()).to.equal('');
});
});
function triggerEnterKey(input) {
const enterKeycode = 13;
const event = $.Event("keypress");
event.which = enterKeycode;
input.trigger(event);
}
function triggerTabKey(input) {
const tabKeycode = 9;
const event = $.Event("keydown");
event.which = tabKeycode;
input.trigger(event);
}
const backspaceCode = String.fromCharCode(127);
describe('input', () => {
const content = $('<div>').attr('id', 'content');
const cliTab = $('<div>').addClass('tab-cli');
const cliPrompt = $('<textarea name="commands">');
cliTab.append(cliPrompt);
beforeEach(() => {
$('body')
.append(content);
// Stub loading of template.
sinon.stub($.fn, 'load').callsFake((file, callback) => {
content.append(cliTab);
callback();
});
sinon.stub(TABS.cli, 'send');
sinon.stub(Promise, 'reduce').callsFake((items, cb) => {
items.forEach((line, idx) => cb(0, line, idx));
});
sinon.stub(window, 'Promise').callsFake(resolve => resolve(0));
sinon.stub(GUI, 'timeout_add').withArgs('CLI_send_slowly')
.callsFake((name, cb) => {
cb();
});
TABS.cli.cliBuffer = "";
});
afterEach(() => {
content.remove();
$.fn.load.restore();
TABS.cli.send.restore();
Promise.reduce.restore();
Promise.restore();
GUI.timeout_add.restore();
});
beforeEach(() => {
cliPrompt.val('');
content.empty();
});
it('tab key triggers serial message with appended tab char', done => {
TABS.cli.initialize(() => {
cliPrompt.val('serial');
triggerTabKey(cliPrompt);
expect(TABS.cli.send).to.have.been.calledOnce;
expect(TABS.cli.send).to.have.been.calledWith('serial\t');
done();
});
});
it('second auto complete in row', done => {
TABS.cli.initialize(() => {
TABS.cli.cliBuffer = '# ser';
cliPrompt.val('seri');
triggerTabKey(cliPrompt);
expect(TABS.cli.send).to.have.been.calledOnce;
expect(TABS.cli.send).to.have.been.calledWith('i\t');
done();
});
});
it('auto-complete command with trailing space', done => {
TABS.cli.initialize(() => {
TABS.cli.cliBuffer = '# get ';
cliPrompt.val('get r');
triggerTabKey(cliPrompt);
expect(TABS.cli.send).to.have.been.calledOnce;
expect(TABS.cli.send).to.have.been.calledWith('r\t');
done();
});
});
it('auto-complete after delete characters', done => {
TABS.cli.initialize(() => {
TABS.cli.cliBuffer = '# serial';
cliPrompt.val('ser');
triggerTabKey(cliPrompt);
expect(TABS.cli.send).to.have.been.calledOnce;
expect(TABS.cli.send).to.have.been.calledWith(backspaceCode.repeat(3) + '\t');
done();
});
});
it('enter after autocomplete', done => {
TABS.cli.initialize(() => {
TABS.cli.cliBuffer = '# servo';
cliPrompt.val('servo');
triggerEnterKey(cliPrompt);
expect(TABS.cli.send).to.have.been.calledOnce;
expect(TABS.cli.send).to.have.been.calledWith('\n');
done();
});
});
it('enter after autocomplete', done => {
TABS.cli.initialize(() => {
TABS.cli.cliBuffer = '# ser';
cliPrompt.val('servo');
triggerEnterKey(cliPrompt);
expect(TABS.cli.send).to.have.been.calledOnce;
expect(TABS.cli.send).to.have.been.calledWith('vo\n');
done();
});
});
it('enter after deleting characters', done => {
TABS.cli.initialize(() => {
TABS.cli.cliBuffer = '# serial';
cliPrompt.val('ser');
triggerEnterKey(cliPrompt);
expect(TABS.cli.send).to.have.been.calledOnce;
expect(TABS.cli.send).to.have.been.calledWith(backspaceCode.repeat(3) + '\n');
done();
});
});
it('cliBuffer is cleared on startup', done => {
TABS.cli.cliBuffer = '# serial';
TABS.cli.initialize(() => {
expect(TABS.cli.cliBuffer).to.equal('');
done();
});
});
it('exit upon cleanup clears cliBuffer first', done => {
CONFIGURATOR.connectionValid = true;
TABS.cli.cliValid = true;
TABS.cli.initialize(() => {
const commandInBuffer = 'resource';
TABS.cli.cliBuffer = `# ${commandInBuffer}`;
TABS.cli.cleanup();
expect(TABS.cli.send).to.have.been.calledOnce;
expect(TABS.cli.send).to.have.been.calledWith(backspaceCode.repeat(commandInBuffer.length) + 'exit\r');
done();
});
});
});
});

303
test/tabs/cli.test.js Normal file
View File

@ -0,0 +1,303 @@
import { Promise } from "bluebird";
import {
describe,
it,
expect,
beforeAll,
afterAll,
afterEach,
beforeEach,
vi,
} from "vitest";
import CliAutoComplete from "../../src/js/CliAutoComplete";
import { cli } from "../../src/js/tabs/cli";
import "jquery-textcomplete";
import $ from "jquery";
import CONFIGURATOR from "../../src/js/data_storage";
import GUI from "../../src/js/gui";
class MockAnalytics {
sendEvent() {
// Empty
}
}
MockAnalytics.prototype.EVENT_CATEGORIES = {};
function toArrayBuffer(string) {
const bufferOut = new ArrayBuffer(string.length);
const bufView = new Uint8Array(bufferOut);
for (let i = 0; i < string.length; i++) {
bufView[i] = string.charCodeAt(i);
}
return bufferOut;
}
function triggerEnterKey(input) {
const enterKeycode = 13;
const event = $.Event("keypress");
event.which = enterKeycode;
input.trigger(event);
}
function triggerTabKey(input) {
const tabKeycode = 9;
const event = $.Event("keydown");
event.which = tabKeycode;
input.trigger(event);
}
const backspaceCode = String.fromCharCode(127);
beforeAll(() => {
window.tracking = new MockAnalytics();
});
describe("cli", () => {
describe("output", () => {
let cliTab;
let cliOutput;
let cliPrompt;
beforeAll(() => {
cliTab = $("<div>").addClass("tab-cli");
cliOutput = $("<div>").addClass("wrapper");
cliPrompt = $('<textarea name="commands">');
cliTab.append($("<div>").addClass("window").append(cliOutput));
cliTab.append(cliPrompt);
CliAutoComplete.setEnabled(false); // not testing the client-side autocomplete
$("body").append(cliTab);
CONFIGURATOR.cliValid = true;
cli.GUI.windowWrapper = cliOutput;
});
afterAll(() => {
cliTab.remove();
});
beforeEach(() => {
cliOutput.empty();
cliPrompt.val("");
cli.cliBuffer = "";
});
it("ambiguous auto-complete results", () => {
cli.cliBuffer = "se";
cli.read({
data: toArrayBuffer(
"\r\x1B[Kserialpassthrough\tservo\r\n# ser"
),
});
// Ambigous auto-complete from firmware is preceded with an \r carriage return
// which only renders a line break on Mac
const expectedValue =
GUI.operating_system !== "Windows"
? "se<br>serialpassthrough\tservo<br>"
: "seserialpassthrough\tservo<br>";
expect(cliOutput.html()).toEqual(expectedValue);
expect(cliPrompt.val()).toEqual("ser");
});
it("unambiguous auto-complete result", () => {
cli.read({
data: toArrayBuffer("serialpassthrough"),
});
expect(cliOutput.html()).toEqual("");
expect(cliPrompt.val()).toEqual("serialpassthrough");
});
it("unambiguous auto-complete result with partial buffer", () => {
cli.cliBuffer = "serial";
cli.read({
data: toArrayBuffer("passthrough"),
});
expect(cliOutput.html()).toEqual("");
expect(cliPrompt.val()).toEqual("serialpassthrough");
});
it("escape characters are skipped", () => {
cli.read({
data: toArrayBuffer("\x1B[K"),
});
expect(cliOutput.html()).toEqual("");
expect(cliPrompt.val()).toEqual("");
});
});
describe("input", () => {
let content;
let cliTab;
let cliPrompt;
beforeAll(() => {
content = $("<div>").attr("id", "content");
cliTab = $("<div>").addClass("tab-cli");
cliPrompt = $('<textarea name="commands">');
cliTab.append(cliPrompt);
$("body").append(content);
vi.spyOn($.fn, "load").mockImplementation((file, callback) => {
content.append(cliTab);
// callback();
});
vi.mock("../src/js/tabs/cli", async (importOriginal) => {
const mod = await importOriginal();
return {
...mod,
send: () => {},
};
});
vi.spyOn(Promise, "reduce").mockImplementation((items, cb) => {
items.forEach((line, idx) => cb(0, line, idx));
});
vi.spyOn(Promise, "Promise").mockResolvedValue(0);
vi.spyOn(GUI, "timeout_add").mockImplementation((name, cb) => {
cb();
});
cli.cliBuffer = "";
});
afterEach(() => {
content.remove();
vi.resetAllMocks();
});
beforeEach(() => {
cliPrompt.val("");
content.empty("");
});
it("tab key triggers serial message with appended tab char", (done) => {
cli.initialize(() => {
cliPrompt.val("serial");
triggerTabKey(cliPrompt);
expect(cli.send).toHaveBeenCalledOnce();
expect(cli.send).toHaveBeenCalledWith("serial\t");
done();
});
});
it("second auto complete in row", (done) => {
cli.initialize(() => {
cli.cliBuffer = "# ser";
cliPrompt.val("seri");
triggerTabKey(cliPrompt);
expect(cli.send).toHaveBeenCalledOnce();
expect(cli.send).toHaveBeenCalledWith("i\t");
done();
});
});
it("auto-complete command with trailing space", (done) => {
cli.initialize(() => {
cli.cliBuffer = "# get ";
cliPrompt.val("get r");
triggerTabKey(cliPrompt);
expect(cli.send).toHaveBeenCalledOnce();
expect(cli.send).toHaveBeenCalledWith("r\t");
done();
});
});
it("auto-complete after delete characters", (done) => {
cli.initialize(() => {
cli.cliBuffer = "# serial";
cliPrompt.val("ser");
triggerTabKey(cliPrompt);
expect(cli.send).toHaveBeenCalledOnce();
expect(cli.send).toHaveBeenCalledWith(
`${backspaceCode.repeat(3)}\t`
);
done();
});
});
it("enter after autocomplete", (done) => {
cli.initialize(() => {
cli.cliBuffer = "# servo";
cliPrompt.val("servo");
triggerEnterKey(cliPrompt);
expect(cli.send).toHaveBeenCalledOnce();
expect(cli.send).toHaveBeenCalledWith("\n");
done();
});
});
it("enter after autocomplete", (done) => {
cli.initialize(() => {
cli.cliBuffer = "# ser";
cliPrompt.val("servo");
triggerEnterKey(cliPrompt);
expect(cli.send).toHaveBeenCalledOnce();
expect(cli.send).toHaveBeenCalledWith("vo\n");
done();
});
});
it("enter after deleting characters", (done) => {
cli.initialize(() => {
cli.cliBuffer = "# serial";
cliPrompt.val("ser");
triggerEnterKey(cliPrompt);
expect(cli.send).toHaveBeenCalledOnce();
expect(cli.send).toHaveBeenCalledWith(
`${backspaceCode.repeat(3)}\n`
);
done();
});
});
it("cliBuffer is cleared on startup", (done) => {
cli.cliBuffer = "# serial";
cli.initialize(() => {
expect(cli.cliBuffer).to.equal("");
done();
});
});
it("exit upon cleanup clears cliBuffer first", (done) => {
CONFIGURATOR.connectionValid = true;
cli.cliValid = true;
cli.initialize(() => {
const commandInBuffer = "resource";
cli.cliBuffer = `# ${commandInBuffer}`;
cli.cleanup();
expect(cli.send).toHaveBeenCalledOnce();
expect(cli.send).toHaveBeenCalledWith(
`${backspaceCode.repeat(commandInBuffer.length)}exit\r`,
);
done();
});
});
});
});

13
vite.config.js Normal file
View File

@ -0,0 +1,13 @@
/// <reference types="vitest" />
import { defineConfig } from 'vite';
export default defineConfig({
test: {
// NOTE: this is a replacement location for karma tests.
// moving forward we should colocate tests with the
// code they test.
include: ['test/**/*.test.{js,mjs,cjs}'],
environment: 'jsdom',
setupFiles: ['test/setup.js'],
},
});

1274
yarn.lock

File diff suppressed because it is too large Load Diff