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:default": "NODE_ENV=production gulp release",
"release:windows": "set NODE_ENV=production&& gulp release", "release:windows": "set NODE_ENV=production&& gulp release",
"pretest": "yarn run lint", "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": "eslint --ext .js,.vue src gulpfile.js gulp-appdmg.js",
"lint:fix": "eslint --fix src gulpfile.js gulp-appdmg.js", "lint:fix": "eslint --fix src gulpfile.js gulp-appdmg.js",
"storybook": "start-storybook -p 6006" "storybook": "start-storybook -p 6006"
@ -66,6 +66,7 @@
"jquery-textcomplete": "^1.8.5", "jquery-textcomplete": "^1.8.5",
"jquery-touchswipe": "^1.6.19", "jquery-touchswipe": "^1.6.19",
"jquery-ui-npm": "^1.12.0", "jquery-ui-npm": "^1.12.0",
"jsdom": "^21.0.0",
"lru_map": "^0.3.3", "lru_map": "^0.3.3",
"marked": "^4.1.1", "marked": "^4.1.1",
"multicast-dns": "^7.2.5", "multicast-dns": "^7.2.5",
@ -92,7 +93,6 @@
"@storybook/addon-links": "^6.5.12", "@storybook/addon-links": "^6.5.12",
"@storybook/vue": "^6.5.12", "@storybook/vue": "^6.5.12",
"babel-loader": "^8.2.5", "babel-loader": "^8.2.5",
"chai": "^4.3.6",
"command-exists": "^1.2.9", "command-exists": "^1.2.9",
"cordova-lib": "^11.0.0", "cordova-lib": "^11.0.0",
"del": "^6.1.1", "del": "^6.1.1",
@ -114,17 +114,6 @@
"gulp-yarn": "^3.0.0", "gulp-yarn": "^3.0.0",
"gulp-zip": "^5.1.0", "gulp-zip": "^5.1.0",
"husky": "^4.3.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", "nw-builder": "^3.8.6",
"os": "^0.1.2", "os": "^0.1.2",
"postcss": "^8.4.17", "postcss": "^8.4.17",
@ -133,12 +122,12 @@
"rpm-builder": "^1.2.1", "rpm-builder": "^1.2.1",
"run-script-os": "^1.1.6", "run-script-os": "^1.1.6",
"simple-git": "^3.15.0", "simple-git": "^3.15.0",
"sinon": "^14.0.0",
"sinon-chai": "^3.7.0",
"targz": "^1.0.1", "targz": "^1.0.1",
"temp": "^0.9.4", "temp": "^0.9.4",
"through2": "^4.0.2", "through2": "^4.0.2",
"vinyl-source-stream": "^2.0.0", "vinyl-source-stream": "^2.0.0",
"vite": "^4.0.4",
"vitest": "^0.27.1",
"vue-loader": "^15.9.8", "vue-loader": "^15.9.8",
"vue-template-compiler": "^2.7.10", "vue-template-compiler": "^2.7.10",
"yarn": "^1.22.19" "yarn": "^1.22.19"

View File

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

View File

@ -3,6 +3,8 @@ import GUI from "../../js/gui.js";
import semver from "semver"; import semver from "semver";
import EscDshotDirectionMotorDriver from "./EscDshotDirectionMotorDriver.js"; import EscDshotDirectionMotorDriver from "./EscDshotDirectionMotorDriver.js";
import DshotCommand from "../../js/utils/DshotCommand.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 class EscDshotDirectionComponent
{ {

View File

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

View File

@ -2,6 +2,10 @@ import MotorOutputReorderConfig from "./MotorOutputReorderingConfig";
import MotorOutputReorderCanvas from "./MotorOutputReorderingCanvas"; import MotorOutputReorderCanvas from "./MotorOutputReorderingCanvas";
import { mspHelper } from "../../js/msp/MSPHelper"; import { mspHelper } from "../../js/msp/MSPHelper";
import { reinitializeConnection } from "../../js/serial_backend"; 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 export default class MotorOutputReorderComponent
{ {
@ -94,7 +98,7 @@ export default class MotorOutputReorderComponent
function reboot() 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))); 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 StatusBar from "./status-bar/StatusBar.vue";
import BatteryIcon from "./quad-status/BatteryIcon.vue"; import BatteryIcon from "./quad-status/BatteryIcon.vue";
import FC from '../js/fc.js'; 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. // Most of the global objects can go here at first.
// It's a bit of overkill for simple components, // 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 { class Beepers {
constructor(config, supportedConditions) { constructor(config, supportedConditions) {

View File

@ -1,4 +1,4 @@
import GUI from "./gui"; import { gui_log } from './gui_log';
import { i18n } from "./localization"; import { i18n } from "./localization";
import { get as getStorage, set as setStorage } from "./SessionStorage"; import { get as getStorage, set as setStorage } from "./SessionStorage";
@ -21,7 +21,7 @@ export default class BuildApi {
const cachedCallback = () => { const cachedCallback = () => {
if (cachedData) { if (cachedData) {
GUI.log(i18n.getMessage('buildServerUsingCached', [url])); gui_log(i18n.getMessage('buildServerUsingCached', [url]));
} }
onSuccess(cachedData); onSuccess(cachedData);
@ -36,7 +36,7 @@ export default class BuildApi {
setStorage(object); setStorage(object);
onSuccess(info); onSuccess(info);
}).fail(xhr => { }).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`])); gui_log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) { if (onFailure !== undefined) {
onFailure(); onFailure();
} else { } else {
@ -70,10 +70,10 @@ export default class BuildApi {
const url = `${this._url}${path}`; const url = `${this._url}${path}`;
$.get(url, function (data) { $.get(url, function (data) {
GUI.log(i18n.getMessage('buildServerSuccess', [path])); gui_log(i18n.getMessage('buildServerSuccess', [path]));
onSuccess(data); onSuccess(data);
}).fail(xhr => { }).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [path, `HTTP ${xhr.status}`])); gui_log(i18n.getMessage('buildServerFailure', [path, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) { if (onFailure !== undefined) {
onFailure(); onFailure();
} }
@ -86,7 +86,7 @@ export default class BuildApi {
$.get(url, function (data) { $.get(url, function (data) {
onSuccess(data); onSuccess(data);
}).fail(xhr => { }).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`])); gui_log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) { if (onFailure !== undefined) {
onFailure(); onFailure();
} }
@ -107,7 +107,7 @@ export default class BuildApi {
onSuccess(response); onSuccess(response);
}, },
}).fail(xhr => { }).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [`HTTP ${xhr.status}`])); gui_log(i18n.getMessage('buildServerFailure', [`HTTP ${xhr.status}`]));
if (onFailure !== undefined) { if (onFailure !== undefined) {
onFailure(); onFailure();
} }
@ -128,7 +128,7 @@ export default class BuildApi {
onSuccess(response); onSuccess(response);
}, },
}).fail(xhr => { }).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`])); gui_log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) { if (onFailure !== undefined) {
onFailure(); onFailure();
} }
@ -139,10 +139,10 @@ export default class BuildApi {
const url = `${this._url}/api/builds/${key}/status`; const url = `${this._url}/api/builds/${key}/status`;
$.get(url, function (data) { $.get(url, function (data) {
GUI.log(i18n.getMessage('buildServerSuccess', [url])); gui_log(i18n.getMessage('buildServerSuccess', [url]));
onSuccess(data); onSuccess(data);
}).fail(xhr => { }).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`])); gui_log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) { if (onFailure !== undefined) {
onFailure(); 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 * 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 = [ const css_dark = [
'./css/dark-theme.css', './css/dark-theme.css',
@ -63,3 +64,5 @@ DarkTheme.applyDark = function () {
DarkTheme.applyNormal = function () { DarkTheme.applyNormal = function () {
css_dark.forEach((el) => $(`link[href="${el}"]`).prop('disabled', true)); 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 Features = function (config) {
const self = this; const self = this;

View File

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

View File

@ -1,6 +1,5 @@
'use strict'; import { gui_log } from "./gui_log";
import { i18n } from "./localization";
(function () {
/** /**
* Takes an ImageData object and returns an MCM symbol as an array of strings. * 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; const constraint = this.constraints.imageSize;
if (img.width !== constraint.expectedWidth if (img.width !== constraint.expectedWidth
|| img.height !== constraint.expectedHeight) { || img.height !== constraint.expectedHeight) {
GUI.log(i18n.getMessage("osdSetupCustomLogoImageSizeError", { gui_log(i18n.getMessage("osdSetupCustomLogoImageSizeError", {
width: img.width, width: img.width,
height: img.height, height: img.height,
})); }));
@ -158,7 +157,7 @@ LogoManager.init = function (font, logoStartIndex) {
const rgbPixel = ctx.getImageData(x, y, 1, 1).data.slice(0, 3), const rgbPixel = ctx.getImageData(x, y, 1, 1).data.slice(0, 3),
colorKey = rgbPixel.join("-"); colorKey = rgbPixel.join("-");
if (!this.constants.MCM_COLORMAP[colorKey]) { if (!this.constants.MCM_COLORMAP[colorKey]) {
GUI.log(i18n.getMessage("osdSetupCustomLogoColorMapError", { gui_log(i18n.getMessage("osdSetupCustomLogoColorMapError", {
valueR: rgbPixel[0], valueR: rgbPixel[0],
valueG: rgbPixel[1], valueG: rgbPixel[1],
valueB: rgbPixel[2], 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 minRc = 1000;
const midRc = 1500; 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 = { const TuningSliders = {
// Legacy Sliders // Legacy Sliders
@ -824,3 +827,5 @@ TuningSliders.resetDTermFilterSlider = function() {
this.calculateNewDTermFilters(); this.calculateNewDTermFilters();
this.updateFilterSlidersDisplay(); this.updateFilterSlidersDisplay();
}; };
export default TuningSliders;

View File

@ -1,6 +1,8 @@
import Features from "./Features"; import Features from "./Features";
import { i18n } from "./localization";
import Beepers from "./Beepers"; import Beepers from "./Beepers";
import FC from "./fc"; import FC from "./fc";
import CONFIGURATOR from "./data_storage";
const VirtualFC = { const VirtualFC = {
// these values are manufactured to unlock all the functionality of the configurator, they dont represent actual hardware // 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 GUI from "./gui";
import Features from "./Features"; import Features from "./Features";
import { i18n } from "./localization"; import { i18n } from "./localization";
import Beepers from "./Beepers"; import Beepers from "./Beepers";
import FC from "./fc"; import FC from "./fc";
import { mspHelper } from "./msp/MSPHelper"; 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 // 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 // the data inside nested objects needs to be verified if deep copy works properly
@ -305,7 +311,7 @@ export function configuration_restore(callback) {
// validate // validate
if (typeof configuration.generatedBy !== 'undefined' && compareVersions(configuration.generatedBy, CONFIGURATOR.BACKUP_FILE_VERSION_MIN_SUPPORTED)) { if (typeof configuration.generatedBy !== 'undefined' && compareVersions(configuration.generatedBy, CONFIGURATOR.BACKUP_FILE_VERSION_MIN_SUPPORTED)) {
if (!compareVersions(configuration.generatedBy, "1.14.0") && !migrate(configuration)) { if (!compareVersions(configuration.generatedBy, "1.14.0") && !migrate(configuration)) {
GUI.log(i18n.getMessage('backupFileUnmigratable')); gui_log(i18n.getMessage('backupFileUnmigratable'));
return; return;
} }
if (configuration.FEATURE_CONFIG.features._featureMask) { if (configuration.FEATURE_CONFIG.features._featureMask) {
@ -318,7 +324,7 @@ export function configuration_restore(callback) {
configuration_upload(configuration, callback); configuration_upload(configuration, callback);
} else { } else {
GUI.log(i18n.getMessage('backupFileIncompatible')); gui_log(i18n.getMessage('backupFileIncompatible'));
} }
} }
}; };
@ -338,7 +344,7 @@ export function configuration_restore(callback) {
function migrate(configuration) { function migrate(configuration) {
let appliedMigrationsCount = 0; let appliedMigrationsCount = 0;
let migratedVersion = configuration.generatedBy; let migratedVersion = configuration.generatedBy;
GUI.log(i18n.getMessage('configMigrationFrom', [migratedVersion])); gui_log(i18n.getMessage('configMigrationFrom', [migratedVersion]));
if (!compareVersions(migratedVersion, '0.59.1')) { if (!compareVersions(migratedVersion, '0.59.1')) {
@ -347,7 +353,7 @@ export function configuration_restore(callback) {
configuration.MISC.rssi_aux_channel = undefined; configuration.MISC.rssi_aux_channel = undefined;
migratedVersion = '0.59.1'; migratedVersion = '0.59.1';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -359,7 +365,7 @@ export function configuration_restore(callback) {
} }
migratedVersion = '0.60.1'; migratedVersion = '0.60.1';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -374,7 +380,7 @@ export function configuration_restore(callback) {
} }
migratedVersion = '0.61.0'; migratedVersion = '0.61.0';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -404,7 +410,7 @@ export function configuration_restore(callback) {
} }
migratedVersion = '0.63.0'; migratedVersion = '0.63.0';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -460,7 +466,7 @@ export function configuration_restore(callback) {
ports: ports, ports: ports,
}; };
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -480,7 +486,7 @@ export function configuration_restore(callback) {
}; };
} }
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -520,7 +526,7 @@ export function configuration_restore(callback) {
migratedVersion = '0.66.0'; migratedVersion = '0.66.0';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -538,7 +544,7 @@ export function configuration_restore(callback) {
configuration.profiles[profileIndex].PID.controller = newPidControllerIndex; configuration.profiles[profileIndex].PID.controller = newPidControllerIndex;
} }
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -555,7 +561,7 @@ export function configuration_restore(callback) {
}; };
} }
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -622,7 +628,7 @@ export function configuration_restore(callback) {
} }
} }
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -633,7 +639,7 @@ export function configuration_restore(callback) {
} }
migratedVersion = '1.2.0'; migratedVersion = '1.2.0';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
@ -649,12 +655,12 @@ export function configuration_restore(callback) {
migratedVersion = '1.3.1'; migratedVersion = '1.3.1';
GUI.log(i18n.getMessage('configMigratedTo', [migratedVersion])); gui_log(i18n.getMessage('configMigratedTo', [migratedVersion]));
appliedMigrationsCount++; appliedMigrationsCount++;
} }
if (appliedMigrationsCount > 0) { if (appliedMigrationsCount > 0) {
GUI.log(i18n.getMessage('configMigrationSuccessful', [appliedMigrationsCount])); gui_log(i18n.getMessage('configMigrationSuccessful', [appliedMigrationsCount]));
} }
return true; return true;
} }
@ -879,7 +885,7 @@ export function configuration_restore(callback) {
} }
function reboot() { function reboot() {
GUI.log(i18n.getMessage('eeprom_saved_ok')); gui_log(i18n.getMessage('eeprom_saved_ok'));
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
MSP.Promise(MSPCodes.MSP_SET_REBOOT) 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; 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'; export const API_VERSION_1_41 = '1.41.0';
const API_VERSION_1_40 = '1.40.0'; export const API_VERSION_1_42 = '1.42.0';
export const API_VERSION_1_43 = '1.43.0';
const API_VERSION_1_41 = '1.41.0'; export const API_VERSION_1_44 = '1.44.0';
const API_VERSION_1_42 = '1.42.0'; export const API_VERSION_1_45 = '1.45.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';
const CONFIGURATOR = { const CONFIGURATOR = {
// all versions are specified and compared using semantic versioning http://semver.org/ // 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: 0x00, codeLen: 2, code: 0x0003 }, // 11
{ value: 0x01, codeLen: 3, code: 0x0005 }, // 101 { value: 0x01, codeLen: 3, code: 0x0005 }, // 101
{ value: 0x02, codeLen: 4, code: 0x0009 }, // 1001 { value: 0x02, codeLen: 4, code: 0x0009 }, // 1001
@ -260,7 +260,7 @@ const defaultHuffmanTree = [
{ value: HUFFMAN_EOF, codeLen: 12, code: 0x0000 }, // 000000000000 { value: HUFFMAN_EOF, codeLen: 12, code: 0x0000 }, // 000000000000
]; ];
const defaultHuffmanLenIndex = function() { export const defaultHuffmanLenIndex = function() {
const result = Array(defaultHuffmanTree.length).fill(-1); const result = Array(defaultHuffmanTree.length).fill(-1);
for (let i = 0; i < defaultHuffmanTree.length; ++i) { 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 = { const INITIAL_CONFIG = {
apiVersion: "0.0.0", apiVersion: "0.0.0",
@ -902,6 +903,4 @@ const FC = {
}, },
}; };
// temp binding to global scope
window.FC = FC;
export default FC; export default FC;

View File

@ -1,6 +1,9 @@
import { get as getConfig } from './ConfigStorage'; 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 = { const GUI_MODES = {
NWJS: "NW.js", NWJS: "NW.js",
@ -242,22 +245,7 @@ class GuiControl {
return timersKilled; 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 // Method is called every time a valid tab change event is received
// callback = code to run when cleanup is finished // callback = code to run when cleanup is finished
// default switch doesn't require callback to be set // default switch doesn't require callback to be set
@ -538,7 +526,7 @@ function GUI_checkOperatingSystem() {
const GUI = new GuiControl(); const GUI = new GuiControl();
export { TABS };
// initialize object into GUI variable // initialize object into GUI variable
window.GUI = GUI; window.GUI = GUI;
export default 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'; export const HUFFMAN_EOF = -1;
const HUFFMAN_EOF = -1;
function huffmanDecodeBuf(inBuf, inBufCharacterCount, huffmanTree, huffmanLenIndex) { function huffmanDecodeBuf(inBuf, inBufCharacterCount, huffmanTree, huffmanLenIndex) {
let code = 0; let code = 0;
@ -57,3 +55,5 @@ function huffmanDecodeBuf(inBuf, inBufCharacterCount, huffmanTree, huffmanLenInd
return new Uint8Array(outBuf); return new Uint8Array(outBuf);
} }
export default huffmanDecodeBuf;

View File

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

View File

@ -1,14 +1,19 @@
import '../components/init.js'; 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 { i18n } from './localization.js';
import GUI from './gui.js'; import GUI from './gui.js';
import { get as getConfig, set as setConfig } from './ConfigStorage.js'; import { get as getConfig, set as setConfig } from './ConfigStorage.js';
import ReleaseChecker from './release_checker.js'; import ReleaseChecker from './release_checker.js';
import { tracking, createAnalytics } from './Analytics.js'; import { tracking, createAnalytics } from './Analytics.js';
import { initializeSerialBackend } from './serial_backend.js'; import { initializeSerialBackend } from './serial_backend.js';
// Currently fc is everywhere, so we need to import it here import FC from './fc.js';
// till all is in modules import CONFIGURATOR, { API_VERSION_1_42, API_VERSION_1_45 } from './data_storage.js';
import './fc.js'; import serial from './serial.js';
import './msp/MSPHelper.js'; import CliAutoComplete from './CliAutoComplete.js';
import DarkTheme from './DarkTheme.js';
import UI_PHONES from './phones_ui.js';
$(document).ready(function () { $(document).ready(function () {
@ -215,8 +220,8 @@ function startProcess() {
// translate to user-selected language // translate to user-selected language
i18n.localizePage(); i18n.localizePage();
GUI.log(i18n.getMessage('infoVersionOs', { operatingSystem: GUI.operating_system })); gui_log(i18n.getMessage('infoVersionOs', { operatingSystem: GUI.operating_system }));
GUI.log(i18n.getMessage('infoVersionConfigurator', { configuratorVersion: CONFIGURATOR.getDisplayVersion() })); gui_log(i18n.getMessage('infoVersionConfigurator', { configuratorVersion: CONFIGURATOR.getDisplayVersion() }));
if (GUI.isNWJS()) { if (GUI.isNWJS()) {
const nwWindow = GUI.nwGui.Window.get(); const nwWindow = GUI.nwGui.Window.get();
@ -291,12 +296,12 @@ function startProcess() {
const tabName = $(self).text(); const tabName = $(self).text();
if (tabRequiresConnection && !CONFIGURATOR.connectionValid) { if (tabRequiresConnection && !CONFIGURATOR.connectionValid) {
GUI.log(i18n.getMessage('tabSwitchConnectionRequired')); gui_log(i18n.getMessage('tabSwitchConnectionRequired'));
return; return;
} }
if (GUI.connect_lock) { // tab switching disabled while operation is in progress if (GUI.connect_lock) { // tab switching disabled while operation is in progress
GUI.log(i18n.getMessage('tabSwitchWaitForOperation')); gui_log(i18n.getMessage('tabSwitchWaitForOperation'));
return; return;
} }
@ -308,7 +313,7 @@ function startProcess() {
} }
$('div.open_firmware_flasher a.flash').click(); $('div.open_firmware_flasher a.flash').click();
} else if (GUI.allowedTabs.indexOf(tab) < 0) { } else if (GUI.allowedTabs.indexOf(tab) < 0) {
GUI.log(i18n.getMessage('tabSwitchUpgradeRequired', [tabName])); gui_log(i18n.getMessage('tabSwitchUpgradeRequired', [tabName]));
return; return;
} }
@ -690,7 +695,7 @@ function notifyOutdatedVersion(releaseData) {
if (semver.lt(CONFIGURATOR.version, CONFIGURATOR.latestVersion)) { if (semver.lt(CONFIGURATOR.version, CONFIGURATOR.latestVersion)) {
const message = i18n.getMessage('configuratorUpdateNotice', [CONFIGURATOR.latestVersion, CONFIGURATOR.latestVersionReleaseUrl]); const message = i18n.getMessage('configuratorUpdateNotice', [CONFIGURATOR.latestVersion, CONFIGURATOR.latestVersionReleaseUrl]);
GUI.log(message); gui_log(message);
const dialog = $('.dialogConfiguratorUpdate')[0]; 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 MDNS_INTERVAL = 10000;
const TCP_CHECK_INTERVAL = 5000; 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 // generate mixer
const mixerList = [ export const mixerList = [
{ name: 'Tricopter', pos: 3, model: 'tricopter', image: 'tri', motors: 3, servos: true }, { 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 +', 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 }, { 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(); 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 = { const MSP = {
symbols: { symbols: {
@ -407,3 +409,12 @@ const MSP = {
this.callbacks_cleanup(); 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 //MSPCodes needs to be re-integrated inside MSP object
const MSPCodes = { const MSPCodes = {
MSP_API_VERSION: 1, MSP_API_VERSION: 1,
@ -205,3 +203,5 @@ const MSPCodes = {
PID_PROFILE_NAME: 3, PID_PROFILE_NAME: 3,
RATE_PROFILE_NAME: 4, RATE_PROFILE_NAME: 4,
}; };
export default MSPCodes;

View File

@ -1,5 +1,13 @@
import MspHelper from "./MSPHelper"; import MspHelper from "./MSPHelper";
import { read_serial } from "../serial_backend"; 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 () { const MSPConnectorImpl = function () {
this.baud = undefined; 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 // disconnect after 10 seconds with error if we don't get IDENT data
GUI.timeout_add('msp_connector', function () { GUI.timeout_add('msp_connector', function () {
if (!CONFIGURATOR.connectionValid) { if (!CONFIGURATOR.connectionValid) {
GUI.log(i18n.getMessage('noConfigurationReceived')); gui_log(i18n.getMessage('noConfigurationReceived'));
disconnectAndCleanup(); disconnectAndCleanup();
} }
@ -57,7 +65,7 @@ MSPConnectorImpl.prototype.connect = function (port, baud, onConnectCallback, on
self.onConnectCallback(); self.onConnectCallback();
}); });
} else { } else {
GUI.log(i18n.getMessage('serialPortOpenFail')); gui_log(i18n.getMessage('serialPortOpenFail'));
self.onFailureCallback(); self.onFailureCallback();
} }
}); });

View File

@ -1,10 +1,17 @@
// NOTE: this is a circular dependency, needs investigating import { update_dataflash_global } from "../update_dataflash_global";
import { bit_check, sensor_status, bit_set, update_dataflash_global } from "../serial_backend"; import { sensor_status } from "../sensor_helpers";
import { bit_check, bit_set } from "../bit";
import { i18n } from "../localization"; import { i18n } from "../localization";
import GUI from "../gui"; import { gui_log } from "../gui_log";
import FC from "../fc"; import FC from "../fc";
import semver from 'semver'; import semver from 'semver';
import vtxDeviceStatusFactory from "../utils/VtxDeviceStatus/VtxDeviceStatusFactory"; 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 // Used for LED_STRIP
const ledDirectionLetters = ['n', 'e', 's', 'w', 'u', 'd']; // in LSB bit order 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 () { MSP.send_message(MSPCodes.MSP_ARMING_DISABLE, mspHelper.crunch(MSPCodes.MSP_ARMING_DISABLE), false, function () {
if (doEnable) { if (doEnable) {
GUI.log(i18n.getMessage('armingEnabled')); gui_log(i18n.getMessage('armingEnabled'));
if (disableRunawayTakeoffPrevention) { if (disableRunawayTakeoffPrevention) {
GUI.log(i18n.getMessage('runawayTakeoffPreventionDisabled')); gui_log(i18n.getMessage('runawayTakeoffPreventionDisabled'));
} else { } else {
GUI.log(i18n.getMessage('runawayTakeoffPreventionEnabled')); gui_log(i18n.getMessage('runawayTakeoffPreventionEnabled'));
} }
} else { } else {
GUI.log(i18n.getMessage('armingDisabled')); gui_log(i18n.getMessage('armingDisabled'));
} }
if (onCompleteCallback) { if (onCompleteCallback) {
@ -2641,11 +2648,6 @@ MspHelper.prototype.sendSerialConfig = function(callback) {
MSP.send_message(mspCode, mspHelper.crunch(mspCode), false, 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; let mspHelper;
// This is temporary, till things are moved // 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 // return true if user has choose a special peripheral
function isPeripheralSelected(peripheralName) { function isPeripheralSelected(peripheralName) {
@ -30,3 +31,5 @@ function adjustBoxNameIfPeripheralWithModeID(modeId, defaultName) {
return defaultName; return defaultName;
} }
export default adjustBoxNameIfPeripheralWithModeID;

View File

@ -1,4 +1,4 @@
'use strict'; import GUI from "./gui";
const UI_PHONES = { const UI_PHONES = {
background: '#background', background: '#background',
@ -85,3 +85,5 @@ const UI_PHONES = {
$(this.headerbar).removeClass('expand2 expand'); $(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 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': 1155, 'productId': 57105}, // STM Device in DFU Mode || Digital Radio in USB mode
{'vendorId': 10473, 'productId': 393}, // GD32 DFU Bootloader {'vendorId': 10473, 'productId': 393}, // GD32 DFU Bootloader
] }; ] };
@ -36,8 +42,8 @@ PortHandler.reinitialize = function () {
if (this.usbCheckLoop) { if (this.usbCheckLoop) {
clearTimeout(this.usbCheckLoop); clearTimeout(this.usbCheckLoop);
} }
this.showVirtualMode = ConfigStorage.get('showVirtualMode').showVirtualMode; this.showVirtualMode = getConfig('showVirtualMode').showVirtualMode;
this.showAllSerialDevices = ConfigStorage.get('showAllSerialDevices').showAllSerialDevices; this.showAllSerialDevices = getConfig('showAllSerialDevices').showAllSerialDevices;
this.check(); // start listening, check after TIMEOUT_CHECK ms this.check(); // start listening, check after TIMEOUT_CHECK ms
}; };
@ -420,3 +426,7 @@ PortHandler.flush_callbacks = function () {
return killed; 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 = { const PortUsage = {
previous_received: 0, previous_received: 0,
@ -36,3 +36,7 @@ const PortUsage = {
this.port_usage_up = 0; 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 popular choices - 921600, 460800, 256000, 230400, 153600, 128000, 115200, 57600, 38400, 28800, 19200
*/ */
import MSPConnectorImpl from "../msp/MSPConnector"; 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 () { const STM32_protocol = function () {
this.baud = null; this.baud = null;
@ -85,7 +96,7 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
self.initialize(); self.initialize();
} else { } else {
GUI.log(i18n.getMessage('serialPortOpenFail')); gui_log(i18n.getMessage('serialPortOpenFail'));
} }
}); });
} else { } else {
@ -106,7 +117,7 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
self.initialize(); self.initialize();
} else { } else {
GUI.connect_lock = false; 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) { if (failedAttempts > 100) {
clearInterval(dfuWaitInterval); clearInterval(dfuWaitInterval);
console.log(`failed to get DFU connection, gave up after 10 seconds`); 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; 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) { serial.connect(self.port, {bitrate: self.options.reboot_baud}, function (openInfo) {
if (!openInfo) { if (!openInfo) {
GUI.connect_lock = false; GUI.connect_lock = false;
GUI.log(i18n.getMessage('serialPortOpenFail')); gui_log(i18n.getMessage('serialPortOpenFail'));
return; return;
} }
@ -164,7 +175,7 @@ STM32_protocol.prototype.connect = function (port, baud, hex, options, callback)
const onConnectHandler = function () { 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)) { if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_42)) {
self.msp_connector.disconnect(function (disconnectionResult) { 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, () => { MSP.send_message(MSPCodes.MSP_BOARD_INFO, false, false, () => {
if (bit_check(FC.CONFIG.targetCapabilities, FC.TARGET_CAPABILITIES_FLAGS.HAS_FLASH_BOOTLOADER)) { if (bit_check(FC.CONFIG.targetCapabilities, FC.TARGET_CAPABILITIES_FLAGS.HAS_FLASH_BOOTLOADER)) {
// Board has flash bootloader // Board has flash bootloader
GUI.log(i18n.getMessage('deviceRebooting_flashBootloader')); gui_log(i18n.getMessage('deviceRebooting_flashBootloader'));
console.log('flash bootloader detected'); console.log('flash bootloader detected');
rebootMode = 4; // MSP_REBOOT_BOOTLOADER_FLASH rebootMode = 4; // MSP_REBOOT_BOOTLOADER_FLASH
} else { } else {
GUI.log(i18n.getMessage('deviceRebooting_romBootloader')); gui_log(i18n.getMessage('deviceRebooting_romBootloader'));
console.log('no flash bootloader detected'); console.log('no flash bootloader detected');
rebootMode = 1; // MSP_REBOOT_BOOTLOADER_ROM; 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 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. 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 // 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` // 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]); self.openDevice(result[0]);
} else { } else {
console.log('USB DFU not found'); 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) { chrome.usb.openDevice(device, function (handle) {
if (checkChromeRuntimeError()) { if (checkChromeRuntimeError()) {
console.log('Failed to open USB device!'); console.log('Failed to open USB device!');
GUI.log(i18n.getMessage('usbDeviceOpenFail')); gui_log(i18n.getMessage('usbDeviceOpenFail'));
if (GUI.operating_system === 'Linux') { if (GUI.operating_system === 'Linux') {
GUI.log(i18n.getMessage('usbDeviceUdevNotice')); gui_log(i18n.getMessage('usbDeviceUdevNotice'));
} }
return; return;
} }
self.handle = handle; 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}`); console.log(`Device opened with Handle ID: ${handle.handle}`);
self.claimInterface(0); self.claimInterface(0);
}); });
@ -132,9 +134,9 @@ STM32DFU_protocol.prototype.closeDevice = function () {
chrome.usb.closeDevice(self.handle, function closed() { chrome.usb.closeDevice(self.handle, function closed() {
if (checkChromeRuntimeError()) { if (checkChromeRuntimeError()) {
console.log('Failed to close USB device!'); console.log('Failed to close USB device!');
GUI.log(i18n.getMessage('usbDeviceCloseFail')); gui_log(i18n.getMessage('usbDeviceCloseFail'));
} else { } else {
GUI.log(i18n.getMessage('usbDeviceClosed')); gui_log(i18n.getMessage('usbDeviceClosed'));
console.log(`Device closed with Handle ID: ${self.handle.handle}`); 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") { 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. // verify all addresses in the hex are writable.
@ -648,7 +650,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
} }
if (unusableBlocks.length > 0) { 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); TABS.firmware_flasher.flashingMessage(i18n.getMessage('dfu_hex_address_errors'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID);
self.leave(); self.leave();
} else { } else {
@ -673,7 +675,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
var unprotect = function() { var unprotect = function() {
console.log('Initiate read unprotect'); console.log('Initiate read unprotect');
let messageReadProtected = i18n.getMessage('stm32ReadProtected'); let messageReadProtected = i18n.getMessage('stm32ReadProtected');
GUI.log(messageReadProtected); gui_log(messageReadProtected);
TABS.firmware_flasher.flashingMessage(messageReadProtected, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.ACTION); 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 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 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. 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.'); 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'); let messageUnprotectUnplug = i18n.getMessage('stm32UnprotectUnplug');
GUI.log(messageUnprotectUnplug); gui_log(messageUnprotectUnplug);
TABS.firmware_flasher.flashingMessage(messageUnprotectUnplug, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.ACTION) TABS.firmware_flasher.flashingMessage(messageUnprotectUnplug, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.ACTION)
.flashProgress(0); .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. } else { // unprotecting the flight controller did not work. It did not reboot.
console.log('Failed to execute unprotect memory command'); 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); TABS.firmware_flasher.flashingMessage(i18n.getMessage('stm32UnprotectFailed'), TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID);
console.log(data); console.log(data);
self.cleanup(); self.cleanup();
@ -716,7 +718,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
} else { } else {
console.log('Failed to initiate unprotect memory command'); console.log('Failed to initiate unprotect memory command');
let messageUnprotectInitFailed = i18n.getMessage('stm32UnprotectInitFailed'); let messageUnprotectInitFailed = i18n.getMessage('stm32UnprotectInitFailed');
GUI.log(messageUnprotectInitFailed); gui_log(messageUnprotectInitFailed);
TABS.firmware_flasher.flashingMessage(messageUnprotectInitFailed, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID); TABS.firmware_flasher.flashingMessage(messageUnprotectInitFailed, TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID);
self.cleanup(); 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) { if (data[4] === self.state.dfuUPLOAD_IDLE && ob_data.length === self.chipInfo.option_bytes.total_size) {
console.log('Option bytes read successfully'); console.log('Option bytes read successfully');
console.log('Chip does not appear read protected'); 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 // it is pretty safe to continue to erase flash
self.clearStatus(function() { self.clearStatus(function() {
self.upload_procedure(2); 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 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) { if (loadAddressResponse[4] === self.state.dfuERROR && loadAddressResponse[0] === self.status.errVENDOR) {
// read protected // read protected
GUI.log(i18n.getMessage('stm32AddressLoadFailed')); gui_log(i18n.getMessage('stm32AddressLoadFailed'));
self.clearStatus(unprotect); self.clearStatus(unprotect);
return; return;
} else if (loadAddressResponse[4] === self.state.dfuDNLOAD_IDLE) { } else if (loadAddressResponse[4] === self.state.dfuDNLOAD_IDLE) {
console.log('Address load for option bytes sector succeeded.'); console.log('Address load for option bytes sector succeeded.');
self.clearStatus(tryReadOB); self.clearStatus(tryReadOB);
} else { } else {
GUI.log(i18n.getMessage('stm32AddressLoadUnknown')); gui_log(i18n.getMessage('stm32AddressLoadUnknown'));
self.cleanup(); self.cleanup();
} }
}; };
@ -852,7 +854,7 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
if (page === erase_pages.length) { if (page === erase_pages.length) {
console.log("Erase: complete"); 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); self.upload_procedure(4);
} else { } else {
erase_page(); erase_page();
@ -1124,3 +1126,5 @@ STM32DFU_protocol.prototype.cleanup = function () {
// initialize object // initialize object
const STM32DFU = new STM32DFU_protocol(); 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 { i18n } from "./localization";
import { get as getStorage, set as setStorage } from "./SessionStorage"; 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) { if (!cacheReleaseData || !cachedReleaseLastUpdate || releaseDataTimestamp - cachedReleaseLastUpdate > 3600 * 1000) {
$.get(self._releaseUrl, function (releaseData) { $.get(self._releaseUrl, function (releaseData) {
GUI.log(i18n.getMessage('releaseCheckLoaded',[self._releaseName])); gui_log(i18n.getMessage('releaseCheckLoaded',[self._releaseName]));
const data = {}; const data = {};
data[self._releaseDataTag] = releaseData; data[self._releaseDataTag] = releaseData;
@ -33,13 +33,13 @@ ReleaseChecker.prototype.loadReleaseData = function (processFunction) {
if (data['responseJSON']) { if (data['responseJSON']) {
message = data['responseJSON'].message; message = data['responseJSON'].message;
} }
GUI.log(i18n.getMessage('releaseCheckFailed',[self._releaseName,message])); gui_log(i18n.getMessage('releaseCheckFailed',[self._releaseName,message]));
self._processReleaseData(cacheReleaseData, processFunction); self._processReleaseData(cacheReleaseData, processFunction);
}); });
} else { } else {
if (cacheReleaseData) { if (cacheReleaseData) {
GUI.log(i18n.getMessage('releaseCheckCached',[self._releaseName])); gui_log(i18n.getMessage('releaseCheckCached',[self._releaseName]));
} }
self._processReleaseData(cacheReleaseData, processFunction); self._processReleaseData(cacheReleaseData, processFunction);
@ -51,7 +51,7 @@ ReleaseChecker.prototype._processReleaseData = function (releaseData, processFun
if (releaseData) { if (releaseData) {
processFunction(releaseData); processFunction(releaseData);
} else { } else {
GUI.log(i18n.getMessage('releaseCheckNoInfo',[self._releaseName])); gui_log(i18n.getMessage('releaseCheckNoInfo',[self._releaseName]));
processFunction(); 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 = { const serial = {
connected: false, connected: false,
@ -64,7 +68,7 @@ const serial = {
self.failed = 0; self.failed = 0;
} else { } else {
console.log(`${self.connectionType}: connection did not recover from last onReceiveError, disconnecting`); 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'); self.errorHandler(getInfo.error, 'receive');
} }
} else { } else {
@ -85,7 +89,7 @@ const serial = {
if (_info.paused) { if (_info.paused) {
// assume unrecoverable, disconnect // assume unrecoverable, disconnect
console.log(`${self.connectionType}: connection did not recover from ${self.error} condition, disconnecting`); 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'); self.errorHandler(_info.error, 'receive');
} }
else { else {
@ -104,7 +108,7 @@ const serial = {
case 'frame_error': case 'frame_error':
case 'parity_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'); self.errorHandler(info.error, 'receive');
break; 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 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 VirtualFC from "./VirtualFC";
import Beepers from "./Beepers"; import Beepers from "./Beepers";
import FC from "./fc"; 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 mspHelper;
let connectionTimestamp; let connectionTimestamp;
@ -211,7 +223,7 @@ function setConnectionTimeout() {
// disconnect after 10 seconds with error if we don't get IDENT data // disconnect after 10 seconds with error if we don't get IDENT data
GUI.timeout_add('connecting', function () { GUI.timeout_add('connecting', function () {
if (!CONFIGURATOR.connectionValid) { if (!CONFIGURATOR.connectionValid) {
GUI.log(i18n.getMessage('noConfigurationReceived')); gui_log(i18n.getMessage('noConfigurationReceived'));
$('div.connect_controls a.connect').click(); // disconnect $('div.connect_controls a.connect').click(); // disconnect
} }
@ -227,7 +239,7 @@ function onOpen(openInfo) {
// reset connecting_to // reset connecting_to
GUI.connecting_to = false; 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 // save selected port with chrome.storage if the port differs
let result = ConfigStorage.get('last_used_port'); let result = ConfigStorage.get('last_used_port');
@ -258,7 +270,7 @@ function onOpen(openInfo) {
MSP.send_message(MSPCodes.MSP_API_VERSION, false, false, function () { MSP.send_message(MSPCodes.MSP_API_VERSION, false, false, function () {
tracking.setFlightControllerData(tracking.DATA.API_VERSION, FC.CONFIG.apiVersion); 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)) { 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 () { MSP.send_message(MSPCodes.MSP_FC_VERSION, false, false, function () {
tracking.setFlightControllerData(tracking.DATA.FIRMWARE_VERSION, FC.CONFIG.flightControllerVersion); 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 () { 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); 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'); tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'SerialPortFailed');
console.log('Failed to open serial port'); console.log('Failed to open serial port');
GUI.log(i18n.getMessage('serialPortOpenFail')); gui_log(i18n.getMessage('serialPortOpenFail'));
abortConnect(); abortConnect();
} }
@ -354,7 +366,7 @@ function processBoardInfo() {
tracking.setFlightControllerData(tracking.DATA.MANUFACTURER_ID, FC.CONFIG.manufacturerId); tracking.setFlightControllerData(tracking.DATA.MANUFACTURER_ID, FC.CONFIG.manufacturerId);
tracking.setFlightControllerData(tracking.DATA.MCU_TYPE, FC.getMcuType()); 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) { 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]; const dialog = $('#dialogResetToCustomDefaults')[0];
@ -450,7 +462,7 @@ function processUid() {
tracking.setFlightControllerData(tracking.DATA.MCU_ID, objectHash.sha1(deviceIdentifier)); tracking.setFlightControllerData(tracking.DATA.MCU_ID, objectHash.sha1(deviceIdentifier));
tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'Connected'); tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'Connected');
connectionTimestamp = Date.now(); connectionTimestamp = Date.now();
GUI.log(i18n.getMessage('uniqueDeviceIdReceived', [deviceIdentifier])); gui_log(i18n.getMessage('uniqueDeviceIdReceived', [deviceIdentifier]));
processCraftName(); processCraftName();
}); });
@ -463,7 +475,7 @@ async function processCraftName() {
await MSP.promise(MSPCodes.MSP_NAME); 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)) { 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)); 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) { function onClosed(result) {
if (result) { // All went as expected if (result) { // All went as expected
GUI.log(i18n.getMessage('serialPortClosedOk')); gui_log(i18n.getMessage('serialPortClosedOk'));
} else { // Something went wrong } else { // Something went wrong
GUI.log(i18n.getMessage('serialPortClosedFail')); gui_log(i18n.getMessage('serialPortClosedFail'));
} }
$('#tabs ul.mode-connected').hide(); $('#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() { function startLiveDataRefreshTimer() {
// live data refresh // live data refresh
GUI.timeout_add('data_refresh', update_live_status, 100); 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) { export function reinitializeConnection(callback) {
// Close connection gracefully if it still exists. // 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; let attempts = 0;
const reconnect = setInterval(waitforSerial, 100); const reconnect = setInterval(waitforSerial, 100);
@ -831,7 +704,7 @@ export function reinitializeConnection(callback) {
console.log(`Serial connection available after ${attempts / 10} seconds`); console.log(`Serial connection available after ${attempts / 10} seconds`);
clearInterval(reconnect); clearInterval(reconnect);
getStatus(); getStatus();
GUI.log(i18n.getMessage('deviceReady')); gui_log(i18n.getMessage('deviceReady'));
if (callback === typeof('function')) { if (callback === typeof('function')) {
callback(); callback();
} }
@ -840,7 +713,7 @@ export function reinitializeConnection(callback) {
if (attempts > 100) { if (attempts > 100) {
clearInterval(reconnect); clearInterval(reconnect);
console.log(`failed to get serial connection, gave up after 10 seconds`); 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 { i18n } from '../localization';
import GUI from '../gui'; import GUI from '../gui';
import { mspHelper } from '../msp/MSPHelper'; 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 = {}; const adjustments = {};
@ -232,7 +237,7 @@ adjustments.initialize = function (callback) {
function save_to_eeprom() { function save_to_eeprom() {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () { 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 { i18n } from '../localization';
import GUI from '../gui'; import GUI from '../gui';
import { get as getConfig, set as setConfig } from '../ConfigStorage'; 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 { 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 = {}; const auxiliary = {};
@ -392,7 +397,7 @@ auxiliary.initialize = function (callback) {
function save_to_eeprom() { function save_to_eeprom() {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () { 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(); if (callback) callback();
}; };
window.TABS.auxiliary = auxiliary;
export { export {
auxiliary, auxiliary,
}; };

View File

@ -4,6 +4,11 @@ import GUI from '../gui';
import BuildApi from '../BuildApi'; import BuildApi from '../BuildApi';
import { tracking } from '../Analytics'; import { tracking } from '../Analytics';
import { reinitializeConnection } from "../serial_backend"; 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 = { const cli = {
lineDelayMs: 15, lineDelayMs: 15,
@ -503,7 +508,7 @@ cli.read = function (readInfo) {
if (this.cliBuffer === 'Rebooting') { if (this.cliBuffer === 'Rebooting') {
CONFIGURATOR.cliActive = false; CONFIGURATOR.cliActive = false;
CONFIGURATOR.cliValid = false; CONFIGURATOR.cliValid = false;
GUI.log(i18n.getMessage('cliReboot')); gui_log(i18n.getMessage('cliReboot'));
reinitializeConnection(); reinitializeConnection();
} }
@ -512,7 +517,7 @@ cli.read = function (readInfo) {
this.lastArrival = new Date().getTime(); this.lastArrival = new Date().getTime();
if (!CONFIGURATOR.cliValid && validateText.indexOf('CLI') !== -1) { if (!CONFIGURATOR.cliValid && validateText.indexOf('CLI') !== -1) {
GUI.log(i18n.getMessage('cliEnter')); gui_log(i18n.getMessage('cliEnter'));
CONFIGURATOR.cliValid = true; CONFIGURATOR.cliValid = true;
// begin output history with the prompt (last line of welcome message) // 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 // 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 { tracking } from "../Analytics";
import { reinitializeConnection } from '../serial_backend'; import { reinitializeConnection } from '../serial_backend';
import { mspHelper } from '../msp/MSPHelper'; 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 = { const configuration = {
analyticsChanges: {}, analyticsChanges: {},
@ -549,7 +554,7 @@ configuration.initialize = function (callback) {
} }
function reboot() { function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved')); gui_log(i18n.getMessage('configurationEepromSaved'));
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection); 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 GUI from '../gui';
import { reinitializeConnection } from "../serial_backend"; import { reinitializeConnection } from "../serial_backend";
import { mspHelper } from "../msp/MSPHelper"; 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 = {}; const failsafe = {};
@ -366,7 +371,7 @@ failsafe.initialize = function (callback) {
} }
function reboot() { function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved')); gui_log(i18n.getMessage('configurationEepromSaved'));
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection); 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 MspHelper from '../msp/MSPHelper';
import STM32 from '../protocols/stm32'; import STM32 from '../protocols/stm32';
import FC from '../fc'; 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 = { const firmware_flasher = {
targets: null, targets: null,
@ -449,7 +456,7 @@ firmware_flasher.initialize = function (callback) {
if (!inComment && input.charCodeAt(i) > 255) { if (!inComment && input.charCodeAt(i) > 255) {
self.flashingMessage(i18n.getMessage('firmwareFlasherConfigCorrupted'), self.FLASH_MESSAGE_TYPES.INVALID); self.flashingMessage(i18n.getMessage('firmwareFlasherConfigCorrupted'), self.FLASH_MESSAGE_TYPES.INVALID);
GUI.log(i18n.getMessage('firmwareFlasherConfigCorruptedLogMessage')); gui_log(i18n.getMessage('firmwareFlasherConfigCorruptedLogMessage'));
return null; return null;
} }
@ -494,7 +501,7 @@ firmware_flasher.initialize = function (callback) {
STM32.connect(port, baud, firmware, options); STM32.connect(port, baud, firmware, options);
} else { } else {
console.log('Please select valid serial port'); console.log('Please select valid serial port');
GUI.log(i18n.getMessage('firmwareFlasherNoValidPort')); gui_log(i18n.getMessage('firmwareFlasherNoValidPort'));
} }
} else { } else {
tracking.sendEvent(tracking.EVENT_CATEGORIES.FLASHING, 'Flashing', self.fileName || null); tracking.sendEvent(tracking.EVENT_CATEGORIES.FLASHING, 'Flashing', self.fileName || null);
@ -532,10 +539,10 @@ firmware_flasher.initialize = function (callback) {
if (board !== target) { if (board !== target) {
boardSelect.val(board).trigger('change'); boardSelect.val(board).trigger('change');
} }
GUI.log(i18n.getMessage(targetAvailable ? 'firmwareFlasherBoardVerificationSuccess' : 'firmwareFlasherBoardVerficationTargetNotAvailable', gui_log(i18n.getMessage(targetAvailable ? 'firmwareFlasherBoardVerificationSuccess' : 'firmwareFlasherBoardVerficationTargetNotAvailable',
{ boardName: board })); { boardName: board }));
} else { } else {
GUI.log(i18n.getMessage('firmwareFlasherBoardVerificationFail')); gui_log(i18n.getMessage('firmwareFlasherBoardVerificationFail'));
} }
onClose(); onClose();
} }
@ -565,7 +572,7 @@ firmware_flasher.initialize = function (callback) {
MSP.listen(mspHelper.process_data.bind(mspHelper)); MSP.listen(mspHelper.process_data.bind(mspHelper));
getBoard(); getBoard();
} else { } 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()); 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; 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'); console.log('Releases not loaded yet');
} }
} else { } 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'); tracking.setFirmwareData(tracking.DATA.FIRMWARE_SOURCE, 'http');
if ($('select[name="firmware_version"]').val() === "0") { if ($('select[name="firmware_version"]').val() === "0") {
GUI.log(i18n.getMessage('firmwareFlasherNoFirmwareSelected')); gui_log(i18n.getMessage('firmwareFlasherNoFirmwareSelected'));
return; return;
} }
@ -1090,7 +1097,7 @@ firmware_flasher.initialize = function (callback) {
}); });
} else { } else {
console.log('You don\'t have write permissions for this file, sorry.'); 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]; const port = resultPort[0];
if (!GUI.connect_lock) { if (!GUI.connect_lock) {
GUI.log(i18n.getMessage('firmwareFlasherFlashTrigger', [port])); gui_log(i18n.getMessage('firmwareFlasherFlashTrigger', [port]));
console.log(`Detected: ${port} - triggering flash on connect`); console.log(`Detected: ${port} - triggering flash on connect`);
// Trigger regular Flashing sequence // Trigger regular Flashing sequence
@ -1114,7 +1121,7 @@ firmware_flasher.initialize = function (callback) {
$('a.flash_firmware').click(); $('a.flash_firmware').click();
}, 100); // timeout so bus have time to initialize after being detected by the system }, 100); // timeout so bus have time to initialize after being detected by the system
} else { } else {
GUI.log(i18n.getMessage('firmwareFlasherPreviousDevice', [port])); gui_log(i18n.getMessage('firmwareFlasherPreviousDevice', [port]));
} }
// Since current port_detected request was consumed, create new one // Since current port_detected request was consumed, create new one

View File

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

View File

@ -2,6 +2,9 @@ import { i18n } from "../localization";
import GUI from '../gui'; import GUI from '../gui';
import { mspHelper } from "../msp/MSPHelper"; import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc"; import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import { gui_log } from "../gui_log";
const led_strip = { const led_strip = {
wireMode: false, wireMode: false,
@ -579,7 +582,7 @@ led_strip.initialize = function (callback, scrollPosition) {
function save_to_eeprom() { function save_to_eeprom() {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function() { 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 { i18n } from '../localization';
import { get as getConfig, set as setConfig } from '../ConfigStorage'; import { get as getConfig, set as setConfig } from '../ConfigStorage';
import FC from '../fc.js'; 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 = {}; const logging = {};
logging.initialize = function (callback) { logging.initialize = function (callback) {
@ -86,7 +90,7 @@ logging.initialize = function (callback) {
$(this).text(i18n.getMessage('loggingStop')); $(this).text(i18n.getMessage('loggingStop'));
$(this).data("clicks", clicks !== true); $(this).data("clicks", clicks !== true);
} else { } else {
GUI.log(i18n.getMessage('loggingErrorOneProperty')); gui_log(i18n.getMessage('loggingErrorOneProperty'));
} }
} else { } else {
GUI.interval_kill_all(); GUI.interval_kill_all();
@ -96,10 +100,10 @@ logging.initialize = function (callback) {
$(this).data("clicks", !clicks); $(this).data("clicks", !clicks);
} }
} else { } else {
GUI.log(i18n.getMessage('loggingErrorLogFile')); gui_log(i18n.getMessage('loggingErrorLogFile'));
} }
} else { } else {
GUI.log(i18n.getMessage('loggingErrorNotConnected')); gui_log(i18n.getMessage('loggingErrorNotConnected'));
} }
}); });
@ -297,7 +301,7 @@ logging.initialize = function (callback) {
if (retaining) { if (retaining) {
chrome.fileSystem.getDisplayPath(fileEntry, function (path) { 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 EscDshotDirectionComponent from "../../components/EscDshotDirection/EscDshotDirectionComponent";
import DshotCommand from "../../js/utils/DshotCommand.js"; import DshotCommand from "../../js/utils/DshotCommand.js";
import { tracking } from "../Analytics"; 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 { mspHelper } from "../msp/MSPHelper";
import FC from "../fc"; 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 = { const motors = {
previousDshotBidir: null, previousDshotBidir: null,
@ -1173,7 +1180,7 @@ motors.initialize = async function (callback) {
} }
function reboot() { function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved')); gui_log(i18n.getMessage('configurationEepromSaved'));
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection); 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 { reinitializeConnection } from "../serial_backend";
import { mspHelper } from "../msp/MSPHelper"; import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc"; 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; let sdcardTimer;
@ -55,7 +59,7 @@ onboard_logging.initialize = function (callback) {
} }
function reboot() { function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved')); gui_log(i18n.getMessage('configurationEepromSaved'));
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection); 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) { accepts: [{description: `${suffix.toUpperCase()} files`, extensions: [suffix]}]}, function(fileEntry) {
if (checkChromeRuntimeError()) { if (checkChromeRuntimeError()) {
if (chrome.runtime.lastError.message !== "User cancelled") { if (chrome.runtime.lastError.message !== "User cancelled") {
GUI.log(i18n.getMessage('dataflashFileWriteFailed')); gui_log(i18n.getMessage('dataflashFileWriteFailed'));
} }
return; return;
} }
@ -586,7 +590,7 @@ onboard_logging.initialize = function (callback) {
fileEntry.createWriter(function (fileWriter) { fileEntry.createWriter(function (fileWriter) {
fileWriter.onerror = function (e) { 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); console.error(e);
@ -598,7 +602,7 @@ onboard_logging.initialize = function (callback) {
}, function (e) { }, function (e) {
// File is not readable or does not exist! // File is not readable or does not exist!
console.error(e); console.error(e);
GUI.log(i18n.getMessage('dataflashFileWriteFailed')); gui_log(i18n.getMessage('dataflashFileWriteFailed'));
}); });
}); });
} }

View File

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

View File

@ -1,9 +1,15 @@
import { i18n } from "../localization"; import { i18n } from "../localization";
import GUI from '../gui'; import GUI from '../gui';
import { tracking } from "../Analytics"; import { tracking } from "../Analytics";
import { bit_check } from "../serial_backend"; import { bit_check } from "../bit";
import VirtualFC from "../VirtualFC"; import VirtualFC from "../VirtualFC";
import FC from "../fc"; 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 FONT = {};
const SYM = {}; const SYM = {};
@ -250,7 +256,7 @@ FONT.upload = function($progress) {
.then(function() { .then(function() {
console.log(`Uploaded all ${FONT.data.characters.length} characters`); 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(); OSD.GUI.fontManager.close();
@ -3245,7 +3251,7 @@ osd.initialize = function(callback) {
$('a.save').click(function() { $('a.save').click(function() {
MSP.promise(MSPCodes.MSP_EEPROM_WRITE); MSP.promise(MSPCodes.MSP_EEPROM_WRITE);
GUI.log(i18n.getMessage('osdSettingsSaved')); gui_log(i18n.getMessage('osdSettingsSaved'));
const oldText = $(this).html(); const oldText = $(this).html();
$(this).html(i18n.getMessage('osdButtonSaved')); $(this).html(i18n.getMessage('osdButtonSaved'));
setTimeout(() => { setTimeout(() => {
@ -3365,7 +3371,7 @@ osd.initialize = function(callback) {
}); });
} else { } else {
console.log('You don\'t have write permissions for this file, sorry.'); 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 { colorTables, getColorForPercentage } from '../utils/css.js';
import GUI from '../gui'; import GUI from '../gui';
import { tracking } from "../Analytics"; import { tracking } from "../Analytics";
import { have_sensor } from "../serial_backend"; import { have_sensor } from "../sensor_helpers";
import { mspHelper } from "../msp/MSPHelper"; import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc"; 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 = { const pid_tuning = {
RATE_PROFILE_MASK: 128, RATE_PROFILE_MASK: 128,
@ -1454,7 +1461,7 @@ pid_tuning.initialize = function (callback) {
self.refresh(function () { self.refresh(function () {
self.updating = false; 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'); $('.tab-pid_tuning select[name="profile"]').prop('disabled', 'false');
FC.CONFIG.profile = self.currentProfile; 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; FC.CONFIG.rateProfile = self.currentRateProfile;
self.currentRates = self.rateCurve.getCurrentRates(); 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 () { $('a.refresh').click(function () {
self.refresh(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); self.setDirty(false);
GUI.log(i18n.getMessage('pidTuningEepromSaved')); gui_log(i18n.getMessage('pidTuningEepromSaved'));
self.refresh(); self.refresh();
}); });
@ -2429,12 +2436,12 @@ pid_tuning.checkUpdateProfile = function (updateRateProfile) {
self.refresh(function () { self.refresh(function () {
self.updating = false; self.updating = false;
if (changedProfile) { 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; FC.CONFIG.profile = self.currentProfile;
} }
if (changedRateProfile) { 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; FC.CONFIG.rateProfile = self.currentRateProfile;
} }
}); });

View File

@ -5,6 +5,11 @@ import { tracking } from "../Analytics";
import { reinitializeConnection } from '../serial_backend'; import { reinitializeConnection } from '../serial_backend';
import { mspHelper } from '../msp/MSPHelper'; import { mspHelper } from '../msp/MSPHelper';
import FC from '../fc'; 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 = { const ports = {
analyticsChanges: {}, analyticsChanges: {},
@ -487,7 +492,7 @@ ports.initialize = function (callback) {
} }
function on_saved_handler() { function on_saved_handler() {
GUI.log(i18n.getMessage('configurationEepromSaved')); gui_log(i18n.getMessage('configurationEepromSaved'));
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection); 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 { tracking } from "../Analytics";
import { mspHelper } from '../msp/MSPHelper'; import { mspHelper } from '../msp/MSPHelper';
import FC from '../fc'; import FC from '../fc';
import MSP from '../msp';
import MSPCodes from '../msp/MSPCodes';
import { gui_log } from '../gui_log';
const power = { const power = {
supported: false, supported: false,
@ -500,7 +503,7 @@ power.initialize = function (callback) {
} }
function save_completed() { function save_completed() {
GUI.log(i18n.getMessage('configurationEepromSaved')); gui_log(i18n.getMessage('configurationEepromSaved'));
TABS.power.initialize(); TABS.power.initialize();
} }

View File

@ -2,9 +2,18 @@ import { i18n } from "../localization";
import GUI from '../gui'; import GUI from '../gui';
import { get as getConfig, set as setConfig } from '../ConfigStorage'; import { get as getConfig, set as setConfig } from '../ConfigStorage';
import { tracking } from "../Analytics"; 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 { mspHelper } from "../msp/MSPHelper";
import FC from "../fc"; 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'; import CryptoES from 'crypto-es';
@ -417,7 +426,7 @@ receiver.initialize = function (callback) {
$('a.refresh').click(function () { $('a.refresh').click(function () {
tab.refresh(function () { tab.refresh(function () {
GUI.log(i18n.getMessage('receiverDataRefreshed')); gui_log(i18n.getMessage('receiverDataRefreshed'));
}); });
}); });
@ -489,7 +498,7 @@ receiver.initialize = function (callback) {
} }
function reboot() { function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved')); gui_log(i18n.getMessage('configurationEepromSaved'));
if (boot) { if (boot) {
GUI.tab_switch_cleanup(function() { GUI.tab_switch_cleanup(function() {
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection); MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitializeConnection);
@ -549,7 +558,7 @@ receiver.initialize = function (callback) {
$("a.bind").click(function() { $("a.bind").click(function() {
MSP.send_message(MSPCodes.MSP2_BETAFLIGHT_BIND); MSP.send_message(MSPCodes.MSP2_BETAFLIGHT_BIND);
GUI.log(i18n.getMessage('receiverButtonBindMessage')); gui_log(i18n.getMessage('receiverButtonBindMessage'));
}); });
} }
$(".bind_btn").toggle(showBindButton); $(".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 = [ const css_dark = [
'/css/dark-theme.css', '/css/dark-theme.css',
@ -42,8 +43,9 @@ let gimbalElems;
let sliderElems; let sliderElems;
let enableTX = false; 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 // 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 = { const watchers = {
darkTheme: (val) => { darkTheme: (val) => {

View File

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

View File

@ -2,6 +2,9 @@ import { i18n } from "../localization";
import GUI from '../gui'; import GUI from '../gui';
import { mspHelper } from "../msp/MSPHelper"; import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc"; import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
import { gui_log } from "../gui_log";
const servos = {}; const servos = {};
servos.initialize = function (callback) { servos.initialize = function (callback) {
@ -137,7 +140,7 @@ servos.initialize = function (callback) {
function save_to_eeprom() { function save_to_eeprom() {
if (save_configuration_to_eeprom) { if (save_configuration_to_eeprom) {
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () { 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 { i18n } from '../localization';
import GUI from '../gui'; import GUI from '../gui';
import { configuration_backup, configuration_restore } from '../backup_restore'; 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 { mspHelper } from '../msp/MSPHelper';
import FC from '../fc'; 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 = { const setup = {
yaw_fix: 0.0, yaw_fix: 0.0,
@ -34,13 +39,13 @@ setup.initialize = function (callback) {
const backupButton = $('#content .backup'); const backupButton = $('#content .backup');
const restoreButton = $('#content .restore'); 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(() => { restoreButton.on('click', () => configuration_restore(() => {
// get latest settings // get latest settings
TABS.setup.initialize(); TABS.setup.initialize();
GUI.log(i18n.getMessage('initialSetupRestoreSuccess')); gui_log(i18n.getMessage('initialSetupRestoreSuccess'));
})); }));
if (CONFIGURATOR.virtualMode) { 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 // until this operation finishes, sending more commands through data_poll() will result in serial buffer overflow
GUI.interval_pause('setup_data_pull'); GUI.interval_pause('setup_data_pull');
MSP.send_message(MSPCodes.MSP_ACC_CALIBRATION, false, false, function () { 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_running').show();
$('#accel_calib_rest').hide(); $('#accel_calib_rest').hide();
}); });
@ -117,7 +122,7 @@ setup.initialize = function (callback) {
GUI.timeout_add('button_reset', function () { GUI.timeout_add('button_reset', function () {
GUI.interval_resume('setup_data_pull'); GUI.interval_resume('setup_data_pull');
GUI.log(i18n.getMessage('initialSetupAccelCalibEnded')); gui_log(i18n.getMessage('initialSetupAccelCalibEnded'));
_self.removeClass('calibrating'); _self.removeClass('calibrating');
$('#accel_calib_running').hide(); $('#accel_calib_running').hide();
$('#accel_calib_rest').show(); $('#accel_calib_rest').show();
@ -132,13 +137,13 @@ setup.initialize = function (callback) {
_self.addClass('calibrating'); _self.addClass('calibrating');
MSP.send_message(MSPCodes.MSP_MAG_CALIBRATION, false, false, function () { 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_running').show();
$('#mag_calib_rest').hide(); $('#mag_calib_rest').hide();
}); });
GUI.timeout_add('button_reset', function () { GUI.timeout_add('button_reset', function () {
GUI.log(i18n.getMessage('initialSetupMagCalibEnded')); gui_log(i18n.getMessage('initialSetupMagCalibEnded'));
_self.removeClass('calibrating'); _self.removeClass('calibrating');
$('#mag_calib_running').hide(); $('#mag_calib_running').hide();
$('#mag_calib_rest').show(); $('#mag_calib_rest').show();
@ -159,7 +164,7 @@ setup.initialize = function (callback) {
$('.dialogConfirmReset-confirmbtn').click(function() { $('.dialogConfirmReset-confirmbtn').click(function() {
dialogConfirmReset.close(); dialogConfirmReset.close();
MSP.send_message(MSPCodes.MSP_RESET_CONF, false, false, 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 () { GUI.tab_switch_cleanup(function () {
TABS.setup.initialize(); TABS.setup.initialize();

View File

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

View File

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

View File

@ -5,6 +5,11 @@ import { tracking } from "../Analytics";
import { mspHelper } from "../msp/MSPHelper"; import { mspHelper } from "../msp/MSPHelper";
import FC from '../fc'; import FC from '../fc';
import { VtxDeviceTypes } from '../utils/VtxDeviceStatus/VtxDeviceStatus'; 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 = { const vtx = {
supported: false, supported: false,
@ -639,7 +644,7 @@ vtx.initialize = function (callback) {
writer.onerror = function(){ writer.onerror = function(){
console.error('Failed to write VTX table lua file'); console.error('Failed to write VTX table lua file');
GUI.log(i18n.getMessage('vtxSavedLuaFileKo')); gui_log(i18n.getMessage('vtxSavedLuaFileKo'));
}; };
writer.onwriteend = function() { writer.onwriteend = function() {
@ -652,7 +657,7 @@ vtx.initialize = function (callback) {
writer.onwriteend = function() { writer.onwriteend = function() {
tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'VtxTableLuaSave', text.length); tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'VtxTableLuaSave', text.length);
console.log('Write VTX table lua file end'); console.log('Write VTX table lua file end');
GUI.log(i18n.getMessage('vtxSavedLuaFileOk')); gui_log(i18n.getMessage('vtxSavedLuaFileOk'));
}; };
writer.write(data); writer.write(data);
@ -662,7 +667,7 @@ vtx.initialize = function (callback) {
}, function (){ }, function (){
console.error('Failed to get VTX table lua file writer'); 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(){ writer.onerror = function(){
console.error('Failed to write VTX file'); console.error('Failed to write VTX file');
GUI.log(i18n.getMessage('vtxSavedFileKo')); gui_log(i18n.getMessage('vtxSavedFileKo'));
}; };
writer.onwriteend = function() { writer.onwriteend = function() {
@ -704,7 +709,7 @@ vtx.initialize = function (callback) {
tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'VtxTableSave', text.length); tracking.sendEvent(tracking.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'VtxTableSave', text.length);
console.log(vtxConfig); console.log(vtxConfig);
console.log('Write VTX file end'); console.log('Write VTX file end');
GUI.log(i18n.getMessage('vtxSavedFileOk')); gui_log(i18n.getMessage('vtxSavedFileOk'));
}; };
writer.write(data); writer.write(data);
@ -714,7 +719,7 @@ vtx.initialize = function (callback) {
}, function (){ }, function (){
console.error('Failed to get VTX file writer'); 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; self.analyticsChanges['VtxTableLoadFromFile'] = file.name;
console.log('Load VTX file end'); console.log('Load VTX file end');
GUI.log(i18n.getMessage('vtxLoadFileOk')); gui_log(i18n.getMessage('vtxLoadFileOk'));
}, },
function() { function() {
// JSON is NOT valid // JSON is NOT valid
console.error('VTX Config from file failed validation against schema'); console.error('VTX Config from file failed validation against schema');
GUI.log(i18n.getMessage('vtxLoadFileKo')); gui_log(i18n.getMessage('vtxLoadFileKo'));
}, },
); );
} catch (err) { } catch (err) {
console.error('Failed loading VTX file config'); 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() { }, function() {
console.error('Failed to get VTX file reader'); 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; self.analyticsChanges['VtxTableLoadFromClipboard'] = text.length;
console.log('Load VTX clipboard end'); console.log('Load VTX clipboard end');
GUI.log(i18n.getMessage('vtxLoadClipboardOk')); gui_log(i18n.getMessage('vtxLoadClipboardOk'));
}, },
function() { function() {
// JSON is NOT valid // JSON is NOT valid
GUI.log(i18n.getMessage('vtxLoadClipboardKo')); gui_log(i18n.getMessage('vtxLoadClipboardKo'));
console.error('VTX Config from clipboard failed validation against schema'); console.error('VTX Config from clipboard failed validation against schema');
}, },
); );
}, function(err) { }, function(err) {
GUI.log(i18n.getMessage('vtxLoadClipboardKo')); gui_log(i18n.getMessage('vtxLoadClipboardKo'));
console.error('Failed to read clipboard contents: ', err); console.error('Failed to read clipboard contents: ', err);
}, },
); );
} catch (err) { } catch (err) {
console.error(`Failed loading VTX file config: ${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() { function save_completed() {
GUI.log(i18n.getMessage('configurationEepromSaved')); gui_log(i18n.getMessage('configurationEepromSaved'));
TABS.vtx.vtxTableSavePending = false; 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 class EscProtocols
{ {
@ -71,3 +71,5 @@ class EscProtocols
} }
export default EscProtocols;

View File

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

View File

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

View File

@ -1,5 +1,3 @@
'use strict';
/* /*
This utility is intended to communicate between chrome windows. This utility is intended to communicate between chrome windows.
One window could watch passed values from another window and react to them. 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); 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="./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="./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="./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="./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/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/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="./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> <title></title>
</head> </head>

View File

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

View File

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

View File

@ -1,6 +1,9 @@
import GUI from '../../js/gui'; import GUI from '../../js/gui';
import { get as getConfig, set as setConfig } from '../../js/ConfigStorage'; import { get as getConfig, set as setConfig } from '../../js/ConfigStorage';
import { i18n } from '../../js/localization'; 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 { favoritePresets } from './FavoritePresets';
import CliEngine from './CliEngine'; 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