Merge remote-tracking branch 'upstream/master' into abo_waypoint_bing_datum_fix

pull/2043/head
breadoven 5 months ago
commit 335d6af9d5

@ -58,7 +58,7 @@ jobs:
name: ${{ env.BUILD_NAME }}_ZIP name: ${{ env.BUILD_NAME }}_ZIP
path: ./out/make/zip/linux/x64/*.zip path: ./out/make/zip/linux/x64/*.zip
build-mac: build-mac:
runs-on: macos-latest runs-on: macos-13
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup environment - name: Setup environment
@ -85,7 +85,7 @@ jobs:
cache: 'npm' cache: 'npm'
# Workaround due to a bug in node-gyp: https://github.com/electron/rebuild/issues/1116 # Workaround due to a bug in node-gyp: https://github.com/electron/rebuild/issues/1116
- name: Install Setuptools - name: Install Setuptools
run: pip install setuptools run: python3 -m pip install --break-system-packages setuptools
- name: Install deps - name: Install deps
uses: nick-fields/retry@v2 uses: nick-fields/retry@v2
with: with:

@ -20,32 +20,32 @@ everything, the hardware is not working, or you have any other _support_ problem
## Installation ## Installation
Depending on the target operating system, _INAV Configurator_ is distributed as a _standalone_ application or Chrome App. _INAV Configurator_ is distributed as a _standalone_ application.
### Windows ### Windows
1. Visit [release page](https://github.com/iNavFlight/inav-configurator/releases) 1. Visit [release page](https://github.com/iNavFlight/inav-configurator/releases)
2. Download Configurator for Windows platform (win32 or win64 is present) 2. Download Configurator for Windows platform (ia32 or win64 is present)
3. Install 3. Install
* Extract ZIP archive and run the INAV Configurator app from the unpacked folder * Extract ZIP archive and run the INAV Configurator app from the unpacked folder
* OR just use the setup program `INAV Configurator.msi` * OR just use the setup program `INAV-Configurator_win32_arch_x.y.z.msi`, **arch** is your computer architecture (ia32 (32bit) or x64 (64bit)), **x.y.z** is the INAV Configurator version number.
4. Configurator is not signed, so you have to allow Windows to run untrusted applications. There might be a monit for it during the first run 4. Configurator is not signed, so you have to allow Windows to run untrusted applications. There might be a monit for it during the first run
### Linux ### Linux
1. Visit [release page](https://github.com/iNavFlight/inav-configurator/releases) 1. Visit [release page](https://github.com/iNavFlight/inav-configurator/releases)
2. Download Configurator for Linux platform (linux32 and linux64 are present) 2. Download Configurator for Linux platform (only linux64 is present)
* **.rpm** is the Fedora installation file. Just download and install using `sudo dnf localinstall /path/to/INAV-Configurator_linux64-x.y.z-x86_64.rpm` or open it with a package manager (e.g. via Files) * **.rpm** is the Fedora installation file. Just download and install using `sudo dnf localinstall /path/to/INAV-Configurator_linux_x64-x.y.z.rpm` or open it with a package manager (e.g. via Files)
* **.deb** is the Debian/Ubuntu installation file. Just download and install using `sudo apt install /path/to/INAV-Configurator_linux64_x.y.z.deb` or open it with a package manager (e.g. via the File Manager) * **.deb** is the Debian/Ubuntu installation file. Just download and install using `sudo apt install /path/to/INAV-Configurator_linux_x64_x.y.z.deb` or open it with a package manager (e.g. via the File Manager)
* **.zip** is a universal archive. Download and continue with these instructions to install * **.zip** is a universal archive. Download and continue with these instructions to install
3. Change to the directory containing the downloaded **zip** file 3. Change to the directory containing the downloaded **zip** file
4. download [this](https://raw.githubusercontent.com/iNavFlight/inav-configurator/master/assets/linux/inav-configurator.desktop) file to the same directory. Its filename should be `inav-configurator.desktop`. 4. download [this](https://raw.githubusercontent.com/iNavFlight/inav-configurator/master/assets/linux/inav-configurator.desktop) file to the same directory. Its filename should be `inav-configurator.desktop`.
5. Extract **zip** archive 5. Extract **zip** archive
``` ```
unzip INAV-Configurator_linuxNN_x.y.z.tar.gz -d /tmp/ unzip INAV-Configurator_linux_arch_x.y.z.zip -d /tmp/
``` ```
**NN** is the bits of your OS. **x.y.z** is the INAV Configurator version number. **arch** is your computer architecture (x64, armv7l, ...), **x.y.z** is the INAV Configurator version number.
6. If this is the first time installing INAV Configurator, create a home for its files 6. If this is the first time installing INAV Configurator, create a home for its files
``` ```
@ -93,21 +93,27 @@ Options:
See [Electron Forge CLI Documentation](https://www.electronforge.io/cli#options-2) for details See [Electron Forge CLI Documentation](https://www.electronforge.io/cli#options-2) for details
Note: Not all architectures are available for all platforms. For example, ia32 (32bit) support is not available for Linux.
Tested architectures:
- Windows: x64 and ia32
- Linux: x64 and armv7l
- MacOS: x64 and arm64
To build the setup program for windows, you have to install [WiX Toolset V3](https://github.com/wixtoolset/wix3/releases) and add the `bin` folder to you `PATH`, e.g. To build the setup program for windows, you have to install [WiX Toolset V3](https://github.com/wixtoolset/wix3/releases) and add the `bin` folder to you `PATH`, e.g.
```C:\Program Files (x86)\WiX Toolset v3.14\bin``` ```C:\Program Files (x86)\WiX Toolset v3.14\bin```
To build deb and rpm packages for Linux, you have to install the following packages: To build deb and rpm packages for Linux, you have to install the following packages:
- Ubuntu/Debian: `dpkg, fakeroot, rpmbuild, build-essential, libudev-dev` - Ubuntu/Debian: `dpkg, fakeroot, rpm, build-essential, libudev-dev`
- OpenSuse/Fedora: `dpkg, fakeroot, rpmbuild, systemd-devel, devel-basis (zypper install -t pattern devel_basis), zip` - OpenSuse/Fedora: `dpkg, fakeroot, rpmbuild, systemd-devel, devel-basis (zypper install -t pattern devel_basis), zip`
Example (note the double -- ): Example (note the double -- ):
``` npm run make -- --arch="x64" ``` ```npm run make -- --arch="x64"```
### Running with debug | Inspector ### Running with debug | Inspector
To be able to open Inspector, set envorinment variable `NODE_ENV` to `develpoment` or set the flag directly when run `npm start`: To be able to open Inspector, set envorinment variable `NODE_ENV` to `develpoment` or set the flag directly when run `npm start`:
```NODE_ENV=development npm start``` ```NODE_ENV=development npm start``` or ```$env:NODE_ENV="development" | npm start``` for Windows PowerShell
Or use vscode and start a debug session `Debug Configurator` (Just hit F5!) Or use vscode and start a debug session `Debug Configurator` (Just hit F5!)

@ -74,7 +74,8 @@ module.exports = {
name: '@electron-forge/maker-dmg', name: '@electron-forge/maker-dmg',
config: { config: {
name: "INAV Configurator", name: "INAV Configurator",
background: "./assets/osx/dmg-background.png" background: "./assets/osx/dmg-background.png",
icon: "./images/inav.icns"
} }
}, },
{ {

@ -339,9 +339,6 @@
<div> <div>
<span id="hardware-roundtrip"> </span> <span id="hardware-roundtrip"> </span>
</div> </div>
<div>
<span id="drop-rate"> </span>
</div>
<div> <div>
<span data-i18n="statusbar_arming_flags"></span> <span class="arming-flags">-</span> <span data-i18n="statusbar_arming_flags"></span> <span class="arming-flags">-</span>
</div> </div>

@ -255,8 +255,10 @@ class Connection {
getTimeout() { getTimeout() {
if (this._bitrate >= 57600) { if (this._bitrate >= 57600) {
return 3000; return 3000;
} else { } if (this._bitrate >= 19200) {
return 4000; return 4000;
} else {
return 6000;
} }
} }
} }

@ -18,13 +18,13 @@ class ConnectionSerial extends Connection {
super._type = ConnectionType.Serial; super._type = ConnectionType.Serial;
} }
connectImplementation(path, options, callback) { connectImplementation(path, options, callback) {
try { try {
this._serialport = new SerialPortStream({binding, path: path, baudRate: options.bitrate, autoOpen: true}, () => { this._serialport = new SerialPortStream({binding, path: path, baudRate: options.bitrate, autoOpen: true}, () => {
if (callback) { if (callback) {
callback({ callback({
connectionId: ++this._connectionId, connectionId: ++this._connectionId,
bitrate: options.bitrate bitrate: options.bitrate
}); });
} }
}); });
@ -50,12 +50,12 @@ class ConnectionSerial extends Connection {
this.abort(); this.abort();
console.log("Serial error: " + error); console.log("Serial error: " + error);
this._onReceiveErrorListeners.forEach(listener => { this._onReceiveErrorListeners.forEach(listener => {
listener(error); listener(error);
}); });
}); });
} }
disconnectImplementation(callback) { disconnectImplementation(callback) {
if (this._serialport && this._serialport.isOpen) { if (this._serialport && this._serialport.isOpen) {
this._serialport.close(error => { this._serialport.close(error => {
if (error) { if (error) {
@ -68,7 +68,7 @@ class ConnectionSerial extends Connection {
callback(true); callback(true);
} }
} }
sendImplementation(data, callback) { sendImplementation(data, callback) {
if (this._serialport && this._serialport.isOpen) { if (this._serialport && this._serialport.isOpen) {
this._serialport.write(Buffer.from(data), error => { this._serialport.write(Buffer.from(data), error => {
@ -105,14 +105,23 @@ class ConnectionSerial extends Connection {
this._onReceiveErrorListeners = this._onReceiveErrorListeners.filter(listener => listener !== callback); this._onReceiveErrorListeners = this._onReceiveErrorListeners.filter(listener => listener !== callback);
} }
static async getDevices(callback) { static async getDevices(callback) {
SerialPort.list().then((ports, error) => { SerialPort.list().then((ports, error) => {
var devices = []; var devices = [];
if (error) { if (error) {
GUI.log("Unable to list serial ports."); GUI.log("Unable to list serial ports.");
} else { } else {
ports.forEach(port => { ports.forEach(port => {
devices.push(port.path); if (GUI.operating_system == 'Linux') {
/* Limit to: USB serial, RFCOMM (BT), 6 legacy devices */
if (port.pnpId ||
port.path.match(/rfcomm\d*/) ||
port.path.match(/ttyS[0-5]$/)) {
devices.push(port.path);
}
} else {
devices.push(port.path);
}
}); });
} }
if (callback) if (callback)

@ -1,11 +1,12 @@
'use strict'; 'use strict';
const { dialog } = require("@electron/remote");
const CONFIGURATOR = require('./data_storage'); const CONFIGURATOR = require('./data_storage');
const Switchery = require('./libraries/switchery/switchery') const Switchery = require('./libraries/switchery/switchery')
const MSP = require('./msp'); const MSP = require('./msp');
const FC = require('./fc'); const FC = require('./fc');
const interval = require('./intervals'); const interval = require('./intervals');
const mspBalancedInterval = require('./msp_balanced_interval');
const { scaleRangeInt } = require('./helpers'); const { scaleRangeInt } = require('./helpers');
const i18n = require('./localization'); const i18n = require('./localization');
@ -92,7 +93,6 @@ GUI_control.prototype.tab_switch_cleanup = function (callback) {
MSP.callbacks_cleanup(); // we don't care about any old data that might or might not arrive MSP.callbacks_cleanup(); // we don't care about any old data that might or might not arrive
interval.killAll(['global_data_refresh', 'msp-load-update', 'ltm-connection-check']); interval.killAll(['global_data_refresh', 'msp-load-update', 'ltm-connection-check']);
mspBalancedInterval.flush();
if (this.active_tab) { if (this.active_tab) {
TABS[this.active_tab].cleanup(callback); TABS[this.active_tab].cleanup(callback);
@ -529,6 +529,13 @@ GUI_control.prototype.update_dataflash_global = function () {
} }
}; };
/**
* Don't use alert() in Electron, it has a nasty bug: https://github.com/electron/electron/issues/31917
*/
GUI_control.prototype.alert = function(message) {
dialog.showMessageBoxSync({ message: message, icon: "./images/inav_icon_128.png" });
}
// initialize object into GUI variable // initialize object into GUI variable
var GUI = new GUI_control(); var GUI = new GUI_control();

@ -1,4 +1,4 @@
const { app, BrowserWindow, ipcMain } = require('electron'); const { app, BrowserWindow, ipcMain, Menu, MenuItem } = require('electron');
const windowStateKeeper = require('electron-window-state'); const windowStateKeeper = require('electron-window-state');
const path = require('path'); const path = require('path');
const Store = require('electron-store'); const Store = require('electron-store');
@ -53,6 +53,10 @@ function createDeviceChooser() {
} }
app.on('ready', () => { app.on('ready', () => {
createWindow();
});
function createWindow() {
let mainWindowState = windowStateKeeper({ let mainWindowState = windowStateKeeper({
defaultWidth: 800, defaultWidth: 800,
@ -72,6 +76,24 @@ app.on('ready', () => {
}, },
}); });
mainWindow.webContents.on('context-menu', (_, props) => {
const menu = new Menu() ;
menu.append(new MenuItem({ label: "Undo", role: "undo", accelerator: 'CmdOrCtrl+Z', visible: props.isEditable }));
menu.append(new MenuItem({ label: "Redo", role: "redo", accelerator: 'CmdOrCtrl+Y', visible: props.isEditable }));
menu.append(new MenuItem({ type: "separator", visible: props.isEditable }));
menu.append(new MenuItem({ label: 'Cut', role: 'cut', accelerator: 'CmdOrCtrl+X', visible: props.isEditable && props.selectionText }));
menu.append(new MenuItem({ label: 'Copy', role: 'copy', accelerator: 'CmdOrCtrl+C', visible: props.selectionText }));
menu.append(new MenuItem({ label: 'Paste', role: 'paste', accelerator: 'CmdOrCtrl+V', visible: props.isEditable }));
menu.append(new MenuItem({ label: "Select all", role: 'selectAll', accelerator: 'CmdOrCtrl+A', visible: props.isEditable}));
menu.items.forEach(item => {
if (item.visible) {
menu.popup();
return;
}
});
});
mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => { mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
event.preventDefault(); event.preventDefault();
selectBluetoothCallback = callback; selectBluetoothCallback = callback;
@ -147,7 +169,7 @@ app.on('ready', () => {
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
mainWindow.webContents.openDevTools(); mainWindow.webContents.openDevTools();
} }
}); }
app.on('window-all-closed', () => { app.on('window-all-closed', () => {

@ -2,6 +2,8 @@
const MSPCodes = require('./msp/MSPCodes') const MSPCodes = require('./msp/MSPCodes')
const mspQueue = require('./serial_queue'); const mspQueue = require('./serial_queue');
const eventFrequencyAnalyzer = require('./eventFrequencyAnalyzer');
const timeout = require('./timeouts');
/** /**
* *
@ -265,7 +267,9 @@ var MSP = {
/* /*
* Free port * Free port
*/ */
mspQueue.freeHardLock(); timeout.add('delayedFreeHardLock', function() {
mspQueue.freeHardLock();
}, 10);
// Reset variables // Reset variables
this.message_length_received = 0; this.message_length_received = 0;
@ -301,6 +305,8 @@ var MSP = {
var checksum; var checksum;
var ii; var ii;
eventFrequencyAnalyzer.put('MPS ' + code);
if (!protocolVersion) { if (!protocolVersion) {
protocolVersion = this.protocolVersion; protocolVersion = this.protocolVersion;
} }

@ -18,6 +18,8 @@ const ProgrammingPid = require('./../programmingPid');
const Safehome = require('./../safehome'); const Safehome = require('./../safehome');
const { FwApproach } = require('./../fwApproach'); const { FwApproach } = require('./../fwApproach');
const Waypoint = require('./../waypoint'); const Waypoint = require('./../waypoint');
const mspDeduplicationQueue = require('./mspDeduplicationQueue');
const mspStatistics = require('./mspStatistics');
var mspHelper = (function () { var mspHelper = (function () {
var self = {}; var self = {};
@ -922,7 +924,7 @@ var mspHelper = (function () {
directions = []; directions = [];
for (directionLetterIndex = 0; directionLetterIndex < MSP.ledDirectionLetters.length; directionLetterIndex++) { for (directionLetterIndex = 0; directionLetterIndex < MSP.ledDirectionLetters.length; directionLetterIndex++) {
if (bit_check(directionMask, directionLetterIndex)) { if (BitHelper.bit_check(directionMask, directionLetterIndex)) {
directions.push(MSP.ledDirectionLetters[directionLetterIndex]); directions.push(MSP.ledDirectionLetters[directionLetterIndex]);
} }
} }
@ -932,7 +934,7 @@ var mspHelper = (function () {
functions = []; functions = [];
for (var functionLetterIndex = 0; functionLetterIndex < MSP.ledFunctionLetters.length; functionLetterIndex++) { for (var functionLetterIndex = 0; functionLetterIndex < MSP.ledFunctionLetters.length; functionLetterIndex++) {
if (bit_check(functionMask, functionLetterIndex)) { if (BitHelper.bit_check(functionMask, functionLetterIndex)) {
functions.push(MSP.ledFunctionLetters[functionLetterIndex]); functions.push(MSP.ledFunctionLetters[functionLetterIndex]);
} }
} }
@ -962,7 +964,7 @@ var mspHelper = (function () {
var overlayMask = (mask >> 12) & 0x3F; var overlayMask = (mask >> 12) & 0x3F;
for (var overlayLetterIndex = 0; overlayLetterIndex < MSP.ledOverlayLetters.length; overlayLetterIndex++) { for (var overlayLetterIndex = 0; overlayLetterIndex < MSP.ledOverlayLetters.length; overlayLetterIndex++) {
if (bit_check(overlayMask, overlayLetterIndex)) { if (BitHelper.bit_check(overlayMask, overlayLetterIndex)) {
functions.push(MSP.ledOverlayLetters[overlayLetterIndex]); functions.push(MSP.ledOverlayLetters[overlayLetterIndex]);
} }
} }
@ -971,7 +973,7 @@ var mspHelper = (function () {
directions = []; directions = [];
for (directionLetterIndex = 0; directionLetterIndex < MSP.ledDirectionLetters.length; directionLetterIndex++) { for (directionLetterIndex = 0; directionLetterIndex < MSP.ledDirectionLetters.length; directionLetterIndex++) {
if (bit_check(directionMask, directionLetterIndex)) { if (BitHelper.bit_check(directionMask, directionLetterIndex)) {
directions.push(MSP.ledDirectionLetters[directionLetterIndex]); directions.push(MSP.ledDirectionLetters[directionLetterIndex]);
} }
} }
@ -1017,7 +1019,7 @@ var mspHelper = (function () {
var overlayMask = (mask >> 16) & 0xFF; var overlayMask = (mask >> 16) & 0xFF;
for (var overlayLetterIndex = 0; overlayLetterIndex < MSP.ledOverlayLetters.length; overlayLetterIndex++) { for (var overlayLetterIndex = 0; overlayLetterIndex < MSP.ledOverlayLetters.length; overlayLetterIndex++) {
if (bit_check(overlayMask, overlayLetterIndex)) { if (BitHelper.bit_check(overlayMask, overlayLetterIndex)) {
functions.push(MSP.ledOverlayLetters[overlayLetterIndex]); functions.push(MSP.ledOverlayLetters[overlayLetterIndex]);
} }
} }
@ -1026,7 +1028,7 @@ var mspHelper = (function () {
directions = []; directions = [];
for (directionLetterIndex = 0; directionLetterIndex < MSP.ledDirectionLetters.length; directionLetterIndex++) { for (directionLetterIndex = 0; directionLetterIndex < MSP.ledDirectionLetters.length; directionLetterIndex++) {
if (bit_check(directionMask, directionLetterIndex)) { if (BitHelper.bit_check(directionMask, directionLetterIndex)) {
directions.push(MSP.ledDirectionLetters[directionLetterIndex]); directions.push(MSP.ledDirectionLetters[directionLetterIndex]);
} }
} }
@ -1618,9 +1620,17 @@ var mspHelper = (function () {
*/ */
if (dataHandler.callbacks[i]) { if (dataHandler.callbacks[i]) {
mspQueue.putRoundtrip(new Date().getTime() - dataHandler.callbacks[i].createdOn); mspQueue.putRoundtrip(new Date().getTime() - dataHandler.callbacks[i].createdOn);
mspQueue.putHardwareRoundtrip(new Date().getTime() - dataHandler.callbacks[i].sentOn);
const hardwareRountrip = new Date().getTime() - dataHandler.callbacks[i].sentOn;
mspQueue.putHardwareRoundtrip(hardwareRountrip);
mspStatistics.add(dataHandler.code, hardwareRountrip);
} }
//remove message from queue as received
mspDeduplicationQueue.remove(dataHandler.code);
// remove object from array // remove object from array
dataHandler.callbacks.splice(i, 1); dataHandler.callbacks.splice(i, 1);
@ -2260,7 +2270,7 @@ var mspHelper = (function () {
buffer.push(BitHelper.lowByte(servoConfiguration.middle)); buffer.push(BitHelper.lowByte(servoConfiguration.middle));
buffer.push(BitHelper.highByte(servoConfiguration.middle)); buffer.push(BitHelper.highByte(servoConfiguration.middle));
buffer.push(lowByte(servoConfiguration.rate)); buffer.push(BitHelper.lowByte(servoConfiguration.rate));
// prepare for next iteration // prepare for next iteration
servoIndex++; servoIndex++;
@ -2650,7 +2660,7 @@ var mspHelper = (function () {
bitIndex = MSP.ledOverlayLetters.indexOf(led.functions[overlayLetterIndex]); bitIndex = MSP.ledOverlayLetters.indexOf(led.functions[overlayLetterIndex]);
if (bitIndex >= 0) { if (bitIndex >= 0) {
mask |= bit_set(mask, bitIndex + 16); mask |= BitHelper.bit_set(mask, bitIndex + 16);
} }
} }
@ -2662,9 +2672,9 @@ var mspHelper = (function () {
bitIndex = MSP.ledDirectionLetters.indexOf(led.directions[directionLetterIndex]); bitIndex = MSP.ledDirectionLetters.indexOf(led.directions[directionLetterIndex]);
if (bitIndex >= 0) { if (bitIndex >= 0) {
if(bitIndex < 4) { if(bitIndex < 4) {
mask |= bit_set(mask, bitIndex + 28); mask |= BitHelper.bit_set(mask, bitIndex + 28);
} else { } else {
extra |= bit_set(extra, bitIndex - 4); extra |= BitHelper.bit_set(extra, bitIndex - 4);
} }
} }
} }
@ -3065,6 +3075,7 @@ var mspHelper = (function () {
}; };
self._getSetting = function (name) { self._getSetting = function (name) {
console.log("Getting setting " + name);
if (FC.SETTINGS[name]) { if (FC.SETTINGS[name]) {
return Promise.resolve(FC.SETTINGS[name]); return Promise.resolve(FC.SETTINGS[name]);
} }

@ -0,0 +1,41 @@
'use strict';
/**
* This module is a queue for deduplication of MSP requests.
* We do not want to process the same request multiple times unless response is received.
* This improves wireless handling and lower amount of data that is put on the air
*/
var mspDeduplicationQueue = function() {
let publicScope = {},
privateScope = {};
privateScope.queue = [];
publicScope.put = function(item) {
privateScope.queue.push(item);
};
publicScope.remove = function(item) {
const index = privateScope.queue.indexOf(item);
if (index > -1) {
privateScope.queue.splice(index, 1);
}
};
publicScope.check = function(item) {
return privateScope.queue.includes(item);
};
publicScope.flush = function() {
privateScope.queue = [];
};
publicScope.get = function() {
return privateScope.queue;
};
return publicScope;
}();
module.exports = mspDeduplicationQueue;

@ -0,0 +1,39 @@
'use strict';
var mspStatistics = function() {
let publicScope = {},
privateScope = {};
privateScope.statistics = {};
publicScope.add = function(code, duration) {
if (!privateScope.statistics[code]) {
privateScope.statistics[code] = {
ctime: new Date().getTime(),
count: 0,
duration: 0,
average: 0,
callsPerSecond: 0
};
}
privateScope.statistics[code].count++;
privateScope.statistics[code].duration += duration;
privateScope.statistics[code].average = privateScope.statistics[code].duration / privateScope.statistics[code].count;
privateScope.statistics[code].callsPerSecond = privateScope.statistics[code].count / ((new Date().getTime() - privateScope.statistics[code].ctime) / 1000);
};
publicScope.get = function() {
return privateScope.statistics;
};
publicScope.reset = function() {
privateScope.statistics = {};
};
return publicScope;
}();
module.exports = mspStatistics;

@ -1,75 +0,0 @@
'use strict';
const mspQueue = require('./serial_queue');
const interval = require('./intervals');
var mspBalancedInterval = (function (mspQueue, intervalHandler) {
var publicScope = {},
privateScope = {};
/**
* How often balancing should be executed [Hz]
* @type {number}
*/
privateScope.balancingFrequency = 0.5;
privateScope.intervals = [];
/**
*
* @param {string} name
* @param {number} requestedInterval
* @param {number} messagesInInterval
* @param {function} code
*/
publicScope.add = function (name, requestedInterval, messagesInInterval, code) {
privateScope.intervals.push({
name: name,
requestedInterval: requestedInterval,
messagesInInterval: messagesInInterval,
code: code
});
intervalHandler.add(name, code, mspQueue.getIntervalPrediction(requestedInterval, messagesInInterval));
};
/**
* Periodically executed balancing handler
*/
publicScope.balancer = function () {
var interval;
for (var i in privateScope.intervals) {
if (privateScope.intervals.hasOwnProperty(i)) {
interval = privateScope.intervals[i];
intervalHandler.remove(interval.name);
intervalHandler.add(
interval.name,
interval.code,
mspQueue.getIntervalPrediction(
interval.requestedInterval,
interval.messagesInInterval
)
);
}
}
};
/**
* Real interval cleaning happens win interval.killAll method
* both methods have to be executed
*/
publicScope.flush = function () {
privateScope.intervals = [];
};
setInterval(publicScope.balancer, Math.round(1000 / privateScope.balancingFrequency));
return publicScope;
})(mspQueue, interval);
module.exports = mspBalancedInterval;

@ -104,11 +104,6 @@ const mspQueue = require('./serial_queue');
if (!stoppped && GUI.active_tab != 'cli') { if (!stoppped && GUI.active_tab != 'cli') {
if (mspQueue.shouldDropStatus()) {
return;
}
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS, false, false); MSP.send_message(MSPCodes.MSP_SENSOR_STATUS, false, false);
MSP.send_message(MSPCodes.MSPV2_INAV_STATUS, false, false); MSP.send_message(MSPCodes.MSPV2_INAV_STATUS, false, false);
MSP.send_message(MSPCodes.MSP_ACTIVEBOXES, false, false); MSP.send_message(MSPCodes.MSP_ACTIVEBOXES, false, false);

@ -1,130 +0,0 @@
'use strict';
var PidController = function () {
var self = {},
privateScope = {};
/**
*
* @type {number}
*/
privateScope.target = null;
/**
*
* @type {{P: null, I: null, D: null}}
*/
privateScope.gains = {
P: null,
I: null,
D: null
};
/**
*
* @type {number}
*/
privateScope.Iterm = 0;
/**
*
* @type {{min: number, max: number}}
*/
privateScope.ItermLimit = {
min: -1000,
max: 1000
};
/**
*
* @type {number}
*/
privateScope.previousError = 0;
/**
*
* @type {{min: number, max: number, minThreshold: number}}
*/
privateScope.output = {
min: null,
max: null,
minThreshold: null
};
/**
*
* @param {number} value
*/
self.setTarget = function (value) {
privateScope.target = value;
};
/**
* @param {number} Pgain
* @param {number} Igain
* @param {number} Dgain
*/
self.setGains = function (Pgain, Igain, Dgain) {
privateScope.gains.P = Pgain;
privateScope.gains.I = Igain;
privateScope.gains.D = Dgain;
};
/**
* Sets min and max value for output
* @param {number} min
* @param {number} max
* @param {number} minThreshold if output is below this value, [min] is returned
*/
self.setOutput = function (min, max, minThreshold) {
privateScope.output.min = min;
privateScope.output.max = max;
privateScope.output.minThreshold = minThreshold;
};
/**
* Sets upper and lower limit for Iterm accumulator
* @param {number} min
* @param {number} max
*/
self.setItermLimit = function (min, max) {
privateScope.ItermLimit.min = min;
privateScope.ItermLimit.max = max;
};
/**
* Executes PID controller based on current value and target
* @param {number} current
* @returns {number}
*/
self.run = function (current) {
var error = current - privateScope.target,
Pterm = error * privateScope.gains.P,
Dterm = (error - privateScope.previousError) * privateScope.gains.D,
output;
privateScope.previousError = error;
privateScope.Iterm += error * privateScope.gains.I;
if (privateScope.Iterm > privateScope.ItermLimit.max) {
privateScope.Iterm = privateScope.ItermLimit.max;
} else if (privateScope.Iterm < privateScope.ItermLimit.min) {
privateScope.Iterm = privateScope.ItermLimit.min;
}
output = Pterm + privateScope.Iterm + Dterm;
if (output < privateScope.output.minThreshold) {
output = privateScope.output.min;
} else if (output > privateScope.output.max) {
output = privateScope.output.max;
}
return output;
};
return self;
};
module.exports = PidController;

@ -18,7 +18,6 @@ const interval = require('./intervals');
const periodicStatusUpdater = require('./periodicStatusUpdater'); const periodicStatusUpdater = require('./periodicStatusUpdater');
const mspQueue = require('./serial_queue'); const mspQueue = require('./serial_queue');
const timeout = require('./timeouts'); const timeout = require('./timeouts');
const mspBalancedInterval = require('./msp_balanced_interval');
const defaultsDialog = require('./defaults_dialog'); const defaultsDialog = require('./defaults_dialog');
const { SITLProcess } = require('./sitl'); const { SITLProcess } = require('./sitl');
const update = require('./globalUpdates'); const update = require('./globalUpdates');
@ -27,6 +26,7 @@ const BOARD = require('./boards');
const jBox = require('./libraries/jBox/jBox.min'); const jBox = require('./libraries/jBox/jBox.min');
const groundstation = require('./groundstation'); const groundstation = require('./groundstation');
const ltmDecoder = require('./ltmDecoder'); const ltmDecoder = require('./ltmDecoder');
const mspDeduplicationQueue = require('./msp/mspDeduplicationQueue');
var SerialBackend = (function () { var SerialBackend = (function () {
@ -35,6 +35,8 @@ var SerialBackend = (function () {
privateScope.isDemoRunning = false; privateScope.isDemoRunning = false;
privateScope.isWirelessMode = false;
/* /*
* Handle "Wireless" mode with strict queueing of messages * Handle "Wireless" mode with strict queueing of messages
*/ */
@ -215,7 +217,6 @@ var SerialBackend = (function () {
timeout.killAll(); timeout.killAll();
interval.killAll(['global_data_refresh', 'msp-load-update']); interval.killAll(['global_data_refresh', 'msp-load-update']);
mspBalancedInterval.flush();
if (CONFIGURATOR.cliActive) { if (CONFIGURATOR.cliActive) {
GUI.tab_switch_cleanup(finishDisconnect); GUI.tab_switch_cleanup(finishDisconnect);
@ -237,6 +238,7 @@ var SerialBackend = (function () {
mspQueue.flush(); mspQueue.flush();
mspQueue.freeHardLock(); mspQueue.freeHardLock();
mspQueue.freeSoftLock(); mspQueue.freeSoftLock();
mspDeduplicationQueue.flush();
CONFIGURATOR.connection.disconnect(privateScope.onClosed); CONFIGURATOR.connection.disconnect(privateScope.onClosed);
MSP.disconnect_cleanup(); MSP.disconnect_cleanup();
@ -374,6 +376,7 @@ var SerialBackend = (function () {
mspQueue.flush(); mspQueue.flush();
mspQueue.freeHardLock(); mspQueue.freeHardLock();
mspQueue.freeSoftLock(); mspQueue.freeSoftLock();
mspDeduplicationQueue.flush();
CONFIGURATOR.connection.emptyOutputBuffer(); CONFIGURATOR.connection.emptyOutputBuffer();
$('div.connect_controls a').click(); // disconnect $('div.connect_controls a').click(); // disconnect
@ -451,35 +454,35 @@ var SerialBackend = (function () {
$('.mode-disconnected').hide(); $('.mode-disconnected').hide();
$('.mode-connected').show(); $('.mode-connected').show();
MSP.send_message(MSPCodes.MSP_DATAFLASH_SUMMARY, false, false); MSP.send_message(MSPCodes.MSP_DATAFLASH_SUMMARY, false, false, function () {
$('#sensor-status').show();
$('#sensor-status').show(); $('#portsinput').hide();
$('#portsinput').hide(); $('#dataflash_wrapper_global').show();
$('#dataflash_wrapper_global').show();
/* /*
* Get BOXNAMES since it is used for some reason.... * Get BOXNAMES since it is used for some reason....
*/ */
MSP.send_message(MSPCodes.MSP_BOXNAMES, false, false); MSP.send_message(MSPCodes.MSP_BOXNAMES, false, false, function () {
/*
* Init PIDs bank with a length that depends on the version
*/
let pidCount = 11;
/* for (let i = 0; i < pidCount; i++) {
* Init PIDs bank with a length that depends on the version FC.PIDs.push(new Array(4));
*/ }
let pidCount = 11;
for (let i = 0; i < pidCount; i++) { interval.add('msp-load-update', function () {
FC.PIDs.push(new Array(4)); $('#msp-version').text("MSP version: " + MSP.protocolVersion.toFixed(0));
} $('#msp-load').text("MSP load: " + mspQueue.getLoad().toFixed(1));
$('#msp-roundtrip').text("MSP round trip: " + mspQueue.getRoundtrip().toFixed(0));
$('#hardware-roundtrip').text("HW round trip: " + mspQueue.getHardwareRoundtrip().toFixed(0));
}, 100);
interval.add('msp-load-update', function () { interval.add('global_data_refresh', periodicStatusUpdater.run, periodicStatusUpdater.getUpdateInterval(CONFIGURATOR.connection.bitrate), false);
$('#msp-version').text("MSP version: " + MSP.protocolVersion.toFixed(0)); });
$('#msp-load').text("MSP load: " + mspQueue.getLoad().toFixed(1)); });
$('#msp-roundtrip').text("MSP round trip: " + mspQueue.getRoundtrip().toFixed(0));
$('#hardware-roundtrip').text("HW round trip: " + mspQueue.getHardwareRoundtrip().toFixed(0));
$('#drop-rate').text("Drop ratio: " + mspQueue.getDropRatio().toFixed(0) + "%");
}, 100);
interval.add('global_data_refresh', periodicStatusUpdater.run, periodicStatusUpdater.getUpdateInterval(CONFIGURATOR.connection.bitrate), false);
} }
privateScope.onClosed = function (result) { privateScope.onClosed = function (result) {

@ -3,8 +3,8 @@
const CONFIGURATOR = require('./data_storage'); const CONFIGURATOR = require('./data_storage');
const MSPCodes = require('./msp/MSPCodes'); const MSPCodes = require('./msp/MSPCodes');
const SimpleSmoothFilter = require('./simple_smooth_filter'); const SimpleSmoothFilter = require('./simple_smooth_filter');
const PidController = require('./pid_controller');
const eventFrequencyAnalyzer = require('./eventFrequencyAnalyzer'); const eventFrequencyAnalyzer = require('./eventFrequencyAnalyzer');
const mspDeduplicationQueue = require('./msp/mspDeduplicationQueue');
var mspQueue = function () { var mspQueue = function () {
@ -27,29 +27,9 @@ var mspQueue = function () {
privateScope.currentLoad = 0; privateScope.currentLoad = 0;
/**
* PID controller used to perform throttling
* @type {PidController}
*/
privateScope.loadPidController = new PidController();
privateScope.loadPidController.setTarget(privateScope.targetLoad);
privateScope.loadPidController.setOutput(0, 99, 0);
privateScope.loadPidController.setGains(5, 6, 3);
privateScope.loadPidController.setItermLimit(0, 90);
privateScope.dropRatio = 0;
privateScope.removeCallback = null; privateScope.removeCallback = null;
privateScope.putCallback = null; privateScope.putCallback = null;
publicScope.computeDropRatio = function () {
privateScope.dropRatio = privateScope.loadPidController.run(publicScope.getLoad());
};
publicScope.getDropRatio = function () {
return privateScope.dropRatio;
};
privateScope.queue = []; privateScope.queue = [];
privateScope.softLock = false; privateScope.softLock = false;
@ -86,6 +66,10 @@ var mspQueue = function () {
privateScope.lockMethod = method; privateScope.lockMethod = method;
}; };
publicScope.getLockMethod = function () {
return privateScope.lockMethod;
};
publicScope.setSoftLock = function () { publicScope.setSoftLock = function () {
privateScope.softLock = new Date().getTime(); privateScope.softLock = new Date().getTime();
}; };
@ -160,6 +144,7 @@ var mspQueue = function () {
request.timer = setTimeout(function () { request.timer = setTimeout(function () {
console.log('MSP data request timed-out: ' + request.code); console.log('MSP data request timed-out: ' + request.code);
mspDeduplicationQueue.remove(request.code);
/* /*
* Remove current callback * Remove current callback
*/ */
@ -223,10 +208,19 @@ var mspQueue = function () {
*/ */
publicScope.put = function (mspRequest) { publicScope.put = function (mspRequest) {
const isMessageInQueue = mspDeduplicationQueue.check(mspRequest.code);
if (isMessageInQueue) {
eventFrequencyAnalyzer.put('MSP Duplicate ' + mspRequest.code);
return false;
}
if (privateScope.queueLocked === true) { if (privateScope.queueLocked === true) {
return false; return false;
} }
mspDeduplicationQueue.put(mspRequest.code);
privateScope.queue.push(mspRequest); privateScope.queue.push(mspRequest);
return true; return true;
}; };
@ -269,7 +263,6 @@ var mspQueue = function () {
publicScope.balancer = function () { publicScope.balancer = function () {
privateScope.currentLoad = privateScope.loadFilter.get(); privateScope.currentLoad = privateScope.loadFilter.get();
publicScope.computeDropRatio();
/* /*
* Also, check if port lock if hanging. Free is so * Also, check if port lock if hanging. Free is so
@ -277,29 +270,25 @@ var mspQueue = function () {
var currentTimestamp = new Date().getTime(), var currentTimestamp = new Date().getTime(),
threshold = publicScope.getHardwareRoundtrip() * 3; threshold = publicScope.getHardwareRoundtrip() * 3;
if (threshold > 1000) { if (threshold > 5000) {
threshold = 5000;
}
if (threshold < 1000) {
threshold = 1000; threshold = 1000;
} }
if (privateScope.softLock !== false && currentTimestamp - privateScope.softLock > threshold) { if (privateScope.softLock !== false && currentTimestamp - privateScope.softLock > threshold) {
privateScope.softLock = false; publicScope.freeSoftLock();
eventFrequencyAnalyzer.put('force free soft lock'); eventFrequencyAnalyzer.put('force free soft lock');
} }
if (privateScope.hardLock !== false && currentTimestamp - privateScope.hardLock > threshold) { if (privateScope.hardLock !== false && currentTimestamp - privateScope.hardLock > threshold) {
privateScope.hardLock = false; console.log('Force free hard lock');
publicScope.freeHardLock();
eventFrequencyAnalyzer.put('force free hard lock'); eventFrequencyAnalyzer.put('force free hard lock');
} }
}; };
publicScope.shouldDrop = function () {
return (Math.round(Math.random()*100) < privateScope.dropRatio);
};
publicScope.shouldDropStatus = function () {
return (Math.round(Math.random()*100) < (privateScope.dropRatio * privateScope.statusDropFactor));
};
/** /**
* This method return periodic for polling interval that should populate queue in 80% or less * This method return periodic for polling interval that should populate queue in 80% or less
* @param {number} requestedInterval * @param {number} requestedInterval
@ -317,6 +306,10 @@ var mspQueue = function () {
} }
}; };
publicScope.getQueue = function () {
return privateScope.queue;
};
setInterval(publicScope.executor, Math.round(1000 / privateScope.handlerFrequency)); setInterval(publicScope.executor, Math.round(1000 / privateScope.handlerFrequency));
setInterval(publicScope.balancer, Math.round(1000 / privateScope.balancerFrequency)); setInterval(publicScope.balancer, Math.round(1000 / privateScope.balancerFrequency));

@ -65,7 +65,14 @@ var Ser2TCP = {
if (err) if (err)
console.log(err); console.log(err);
}); });
} else if (GUI.operating_system == 'MacOS') {
path = './../resources/sitl/macos/Ser2TCP'
chmod(path, 0o755, (err) => {
if (err)
console.log(err);
});
} else { } else {
alert(GUI.operating_system);
return; return;
} }
@ -131,19 +138,20 @@ var Ser2TCP = {
var devices = []; var devices = [];
if (error) { if (error) {
GUI.log("Unable to list serial ports."); GUI.log("Unable to list serial ports.");
} else { } else {
ports.forEach((device) => { ports.forEach((device) => {
if (GUI.operating_system == 'Windows') { if (GUI.operating_system == 'Windows') {
var m = device.path.match(/COM\d?\d/g) var m = device.path.match(/COM\d?\d/g)
if (m) if (m)
devices.push(m[0]); devices.push(m[0]);
} else { } else {
if (device.displayName != null) { /* Limit to: USB serial, RFCOMM (BT), 6 legacy devices */
var m = device.path.match(/\/dev\/.*/) if (device.pnpId ||
if (m) device.path.match(/rfcomm\d*/) ||
devices.push(m[0]); device.path.match(/ttyS[0-5]$/)) {
devices.push(device.path);
} }
} }
}); });
} }
callback(devices); callback(devices);
@ -217,7 +225,16 @@ var SITLProcess = {
if (err) if (err)
console.log(err); console.log(err);
}); });
} else if (GUI.operating_system == 'MacOS') {
sitlExePath = path.join(__dirname, './../resources/sitl/macos/inav_SITL');
eepromPath = `${app.getPath('userData')}/${eepromFileName}`
chmod(sitlExePath, 0o755, err => {
if (err)
console.log(err);
});
} else { } else {
alert(GUI.operating_system);
return; return;
} }

Binary file not shown.

Binary file not shown.

@ -6,12 +6,10 @@ const wNumb = require('wnumb/wNumb')
const mspHelper = require('./../js/msp/MSPHelper'); const mspHelper = require('./../js/msp/MSPHelper');
const MSPCodes = require('./../js/msp/MSPCodes'); const MSPCodes = require('./../js/msp/MSPCodes');
const MSP = require('./../js/msp'); const MSP = require('./../js/msp');
const mspQueue = require('./../js/serial_queue');
const { GUI, TABS } = require('./../js/gui'); const { GUI, TABS } = require('./../js/gui');
const FC = require('./../js/fc'); const FC = require('./../js/fc');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const i18n = require('./../js/localization'); const i18n = require('./../js/localization');
const interval = require('./../js/intervals');
TABS.adjustments = {}; TABS.adjustments = {};
@ -260,11 +258,6 @@ TABS.adjustments.initialize = function (callback) {
// data pulling functions used inside interval timer // data pulling functions used inside interval timer
function get_rc_data() { function get_rc_data() {
if (mspQueue.shouldDrop()) {
return;
}
MSP.send_message(MSPCodes.MSP_RC, false, false, update_ui); MSP.send_message(MSPCodes.MSP_RC, false, false, update_ui);
} }
@ -280,7 +273,7 @@ TABS.adjustments.initialize = function (callback) {
update_ui(); update_ui();
// enable data pulling // enable data pulling
mspBalancedInterval.add('aux_data_pull', 50, 1, get_rc_data); interval.add('aux_data_pull', get_rc_data, 50);
GUI.content_ready(callback); GUI.content_ready(callback);
} }

@ -9,13 +9,11 @@ const store = new Store();
const mspHelper = require('./../js/msp/MSPHelper'); const mspHelper = require('./../js/msp/MSPHelper');
const MSPCodes = require('./../js/msp/MSPCodes'); const MSPCodes = require('./../js/msp/MSPCodes');
const MSP = require('./../js/msp'); const MSP = require('./../js/msp');
const mspQueue = require('./../js/serial_queue');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const { GUI, TABS } = require('./../js/gui'); const { GUI, TABS } = require('./../js/gui');
const FC = require('./../js/fc'); const FC = require('./../js/fc');
const adjustBoxNameIfPeripheralWithModeID = require('./../js/peripherals'); const adjustBoxNameIfPeripheralWithModeID = require('./../js/peripherals');
const i18n = require('./../js/localization'); const i18n = require('./../js/localization');
const interval = require('./../js/intervals');
var ORIG_AUX_CONFIG_IDS = []; var ORIG_AUX_CONFIG_IDS = [];
@ -375,11 +373,6 @@ TABS.auxiliary.initialize = function (callback) {
// data pulling functions used inside interval timer // data pulling functions used inside interval timer
function get_rc_data() { function get_rc_data() {
if (mspQueue.shouldDrop()) {
return;
}
MSP.send_message(MSPCodes.MSP_RC, false, false, update_ui); MSP.send_message(MSPCodes.MSP_RC, false, false, update_ui);
} }
@ -516,7 +509,7 @@ TABS.auxiliary.initialize = function (callback) {
update_ui(); update_ui();
// enable data pulling // enable data pulling
mspBalancedInterval.add('aux_data_pull', 50, 1, get_rc_data); interval.add('aux_data_pull', get_rc_data, 50);
$(".tab-auxiliary .acroEnabled").width($("#mode-0 .info").width()); $(".tab-auxiliary .acroEnabled").width($("#mode-0 .info").width());

@ -1,6 +1,7 @@
'use strict'; 'use strict';
const path = require('path'); const path = require('path');
const fs = require('fs');
const { dialog } = require("@electron/remote"); const { dialog } = require("@electron/remote");
const MSP = require('./../js/msp'); const MSP = require('./../js/msp');
@ -13,6 +14,7 @@ const { globalSettings } = require('./../js/globalSettings');
const CliAutoComplete = require('./../js/CliAutoComplete'); const CliAutoComplete = require('./../js/CliAutoComplete');
const { ConnectionType } = require('./../js/connection/connection'); const { ConnectionType } = require('./../js/connection/connection');
const jBox = require('./../js/libraries/jBox/jBox.min'); const jBox = require('./../js/libraries/jBox/jBox.min');
const mspDeduplicationQueue = require('./msp/mspDeduplicationQueue');
TABS.cli = { TABS.cli = {
lineDelayMs: 50, lineDelayMs: 50,
@ -94,6 +96,7 @@ TABS.cli.initialize = function (callback) {
// Flush MSP queue as well as all MSP registered callbacks // Flush MSP queue as well as all MSP registered callbacks
mspQueue.flush(); mspQueue.flush();
mspDeduplicationQueue.flush();
MSP.callbacks_cleanup(); MSP.callbacks_cleanup();
self.outputHistory = ""; self.outputHistory = "";
@ -170,7 +173,6 @@ TABS.cli.initialize = function (callback) {
return; return;
} }
const fs = require('fs');
fs.writeFile(result.filePath, self.outputHistory, (err) => { fs.writeFile(result.filePath, self.outputHistory, (err) => {
if (err) { if (err) {
GUI.log(i18n.getMessage('ErrorWritingFile')); GUI.log(i18n.getMessage('ErrorWritingFile'));
@ -255,7 +257,6 @@ TABS.cli.initialize = function (callback) {
} }
if (result.filePaths.length == 1) { if (result.filePaths.length == 1) {
const fs = require('fs');
fs.readFile(result.filePaths[0], (err, data) => { fs.readFile(result.filePaths[0], (err, data) => {
if (err) { if (err) {
GUI.log(i18n.getMessage('ErrorReadingFile')); GUI.log(i18n.getMessage('ErrorReadingFile'));

@ -1,6 +1,7 @@
'use strict'; 'use strict';
const { marked } = require('marked'); const { marked } = require('marked');
const fs = require('fs');
const path = require('path'); const path = require('path');
const semver = require('semver'); const semver = require('semver');
const { dialog } = require('@electron/remote'); const { dialog } = require('@electron/remote');
@ -17,11 +18,11 @@ const CONFIGURATOR = require('./../js/data_storage');
const SerialBackend = require('./../js/serial_backend'); const SerialBackend = require('./../js/serial_backend');
const timeout = require('./../js/timeouts'); const timeout = require('./../js/timeouts');
const interval = require('./../js/intervals'); const interval = require('./../js/intervals');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const mspQueue = require('./../js/serial_queue'); const mspQueue = require('./../js/serial_queue');
const mspHelper = require('./../js/msp/MSPHelper'); const mspHelper = require('./../js/msp/MSPHelper');
const STM32 = require('./../js/protocols/stm32'); const STM32 = require('./../js/protocols/stm32');
const STM32DFU = require('./../js/protocols/stm32usbdfu'); const STM32DFU = require('./../js/protocols/stm32usbdfu');
const mspDeduplicationQueue = require('./msp/mspDeduplicationQueue');
TABS.firmware_flasher = {}; TABS.firmware_flasher = {};
TABS.firmware_flasher.initialize = function (callback) { TABS.firmware_flasher.initialize = function (callback) {
@ -254,8 +255,6 @@ TABS.firmware_flasher.initialize = function (callback) {
if (result.filePaths.length == 1) { if (result.filePaths.length == 1) {
filename = result.filePaths[0]; filename = result.filePaths[0];
} }
const fs = require('fs');
$('div.git_info').slideUp(); $('div.git_info').slideUp();
@ -775,11 +774,11 @@ TABS.firmware_flasher.onValidFirmware = function() {
TABS.firmware_flasher.closeTempConnection = function() { TABS.firmware_flasher.closeTempConnection = function() {
timeout.killAll(); timeout.killAll();
interval.killAll(['global_data_refresh', 'msp-load-update', 'ltm-connection-check']); interval.killAll(['global_data_refresh', 'msp-load-update', 'ltm-connection-check']);
mspBalancedInterval.flush();
mspQueue.flush(); mspQueue.flush();
mspQueue.freeHardLock(); mspQueue.freeHardLock();
mspQueue.freeSoftLock(); mspQueue.freeSoftLock();
mspDeduplicationQueue.flush();
CONFIGURATOR.connection.emptyOutputBuffer(); CONFIGURATOR.connection.emptyOutputBuffer();
CONFIGURATOR.connectionValid = false; CONFIGURATOR.connectionValid = false;

@ -8,8 +8,7 @@ const MSPChainerClass = require('./../js/msp/MSPchainer');
const mspHelper = require('./../js/msp/MSPHelper'); const mspHelper = require('./../js/msp/MSPHelper');
const MSPCodes = require('./../js/msp/MSPCodes'); const MSPCodes = require('./../js/msp/MSPCodes');
const MSP = require('./../js/msp'); const MSP = require('./../js/msp');
const mspBalancedInterval = require('./../js/msp_balanced_interval'); const interval = require('./../js/intervals');
const mspQueue = require('./../js/serial_queue');
const { GUI, TABS } = require('./../js/gui'); const { GUI, TABS } = require('./../js/gui');
const FC = require('./../js/fc'); const FC = require('./../js/fc');
const i18n = require('./../js/localization'); const i18n = require('./../js/localization');
@ -262,7 +261,6 @@ TABS.gps.initialize = function (callback) {
} }
function update_ui() { function update_ui() {
let lat = FC.GPS_DATA.lat / 10000000; let lat = FC.GPS_DATA.lat / 10000000;
let lon = FC.GPS_DATA.lon / 10000000; let lon = FC.GPS_DATA.lon / 10000000;
@ -400,19 +398,15 @@ TABS.gps.initialize = function (callback) {
* enable data pulling * enable data pulling
* GPS is usually refreshed at 5Hz, there is no reason to pull it much more often, really... * GPS is usually refreshed at 5Hz, there is no reason to pull it much more often, really...
*/ */
mspBalancedInterval.add('gps_pull', 200, 3, function gps_update() { interval.add('gps_pull', function gps_update() {
// avoid usage of the GPS commands until a GPS sensor is detected for targets that are compiled without GPS support. // avoid usage of the GPS commands until a GPS sensor is detected for targets that are compiled without GPS support.
if (!SerialBackend.have_sensor(FC.CONFIG.activeSensors, 'gps')) { if (!SerialBackend.have_sensor(FC.CONFIG.activeSensors, 'gps')) {
update_ui(); update_ui();
return; return;
} }
if (mspQueue.shouldDrop()) {
return;
}
get_raw_gps_data(); get_raw_gps_data();
}); }, 200);
$('a.save').on('click', function () { $('a.save').on('click', function () {

@ -230,9 +230,8 @@ TABS.led_strip.initialize = function (callback, scrollPosition) {
$('.colors').on('dblclick', 'button', function(e) { $('.colors').on('dblclick', 'button', function(e) {
var pp = $('.tab-led-strip').position(); var moveLeft = $('.tab-led-strip').offset().left + ($('.colorDefineSliders').width() / 2);
var moveLeft = $('.tab-led-strip').position().left + ($('.colorDefineSliders').width() / 2); var moveUp = $('.tab-led-strip').offset().top + $('.colorDefineSliders').height() + 20;
var moveUp = $('.tab-led-strip').position().top + $('.colorDefineSliders').height() + 20;
$('.colorDefineSliders').css('left', e.pageX - e.offsetX - moveLeft); $('.colorDefineSliders').css('left', e.pageX - e.offsetX - moveLeft);
$('.colorDefineSliders').css('top', e.pageY - e.offsetY - moveUp); $('.colorDefineSliders').css('top', e.pageY - e.offsetY - moveUp);

@ -1,13 +1,13 @@
'use strict'; 'use strict';
const path = require('path'); const path = require('path');
const fs = require('fs');
const { dialog } = require("@electron/remote"); const { dialog } = require("@electron/remote");
const Store = require('electron-store'); const Store = require('electron-store');
const store = new Store(); const store = new Store();
const MSPCodes = require('./../js/msp/MSPCodes'); const MSPCodes = require('./../js/msp/MSPCodes');
const MSP = require('./../js/msp'); const MSP = require('./../js/msp');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const { GUI, TABS } = require('./../js/gui'); const { GUI, TABS } = require('./../js/gui');
const FC = require('./../js/fc'); const FC = require('./../js/fc');
const CONFIGURATOR = require('./../js/data_storage'); const CONFIGURATOR = require('./../js/data_storage');
@ -84,7 +84,6 @@ TABS.logging.initialize = function (callback) {
} }
interval.add('log_data_poll', log_data_poll, parseInt($('select.speed').val()), true); // refresh rate goes here interval.add('log_data_poll', log_data_poll, parseInt($('select.speed').val()), true); // refresh rate goes here
const fs = require('fs');
interval.add('write_data', function write_data() { interval.add('write_data', function write_data() {
if (log_buffer.length && readyToWrite) { // only execute when there is actual data to write if (log_buffer.length && readyToWrite) { // only execute when there is actual data to write
@ -106,7 +105,6 @@ TABS.logging.initialize = function (callback) {
} }
} else { } else {
interval.killAll(['global_data_refresh', 'msp-load-update', 'ltm-connection-check']); interval.killAll(['global_data_refresh', 'msp-load-update', 'ltm-connection-check']);
mspBalancedInterval.flush();
$('.speed').prop('disabled', false); $('.speed').prop('disabled', false);
$(this).text(i18n.getMessage('loggingStart')); $(this).text(i18n.getMessage('loggingStart'));

@ -6,12 +6,11 @@ const MSPChainerClass = require('./../js/msp/MSPchainer');
const MSP = require('./../js/msp'); const MSP = require('./../js/msp');
const MSPCodes = require('./../js/msp/MSPCodes'); const MSPCodes = require('./../js/msp/MSPCodes');
const mspHelper = require('./../js/msp/MSPHelper'); const mspHelper = require('./../js/msp/MSPHelper');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const mspQueue = require('./../js/serial_queue');
const FC = require('./../js/fc'); const FC = require('./../js/fc');
const { GUI, TABS } = require('./../js/gui'); const { GUI, TABS } = require('./../js/gui');
const i18n = require('./../js/localization'); const i18n = require('./../js/localization');
const { mixer } = require('./../js/model'); const { mixer } = require('./../js/model');
const interval = require('./../js/intervals');
TABS.magnetometer = {}; TABS.magnetometer = {};
@ -524,9 +523,6 @@ TABS.magnetometer.initialize = function (callback) {
}); });
function get_fast_data() { function get_fast_data() {
if (mspQueue.shouldDrop()) {
return;
}
MSP.send_message(MSPCodes.MSP_ATTITUDE, false, false, function () { MSP.send_message(MSPCodes.MSP_ATTITUDE, false, false, function () {
self.roll_e.text(i18n.getMessage('initialSetupAttitude', [FC.SENSOR_DATA.kinematics[0]])); self.roll_e.text(i18n.getMessage('initialSetupAttitude', [FC.SENSOR_DATA.kinematics[0]]));
@ -536,7 +532,7 @@ TABS.magnetometer.initialize = function (callback) {
}); });
} }
mspBalancedInterval.add('setup_data_pull_fast', 40, 1, get_fast_data); interval.add('setup_data_pull_fast', get_fast_data, 40);
GUI.content_ready(callback); GUI.content_ready(callback);
} }

@ -1,7 +1,9 @@
'use strict'; 'use strict';
const path = require('path'); const path = require('path');
const fs = require('fs');
const ol = require('openlayers'); const ol = require('openlayers');
const xml2js = require('xml2js');
const Store = require('electron-store'); const Store = require('electron-store');
const store = new Store(); const store = new Store();
const { dialog } = require("@electron/remote"); const { dialog } = require("@electron/remote");
@ -10,7 +12,6 @@ const MSPChainerClass = require('./../js/msp/MSPchainer');
const mspHelper = require('./../js/msp/MSPHelper'); const mspHelper = require('./../js/msp/MSPHelper');
const MSPCodes = require('./../js/msp/MSPCodes'); const MSPCodes = require('./../js/msp/MSPCodes');
const MSP = require('./../js/msp'); const MSP = require('./../js/msp');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const mspQueue = require('./../js/serial_queue'); const mspQueue = require('./../js/serial_queue');
const { GUI, TABS } = require('./../js/gui'); const { GUI, TABS } = require('./../js/gui');
const FC = require('./../js/fc'); const FC = require('./../js/fc');
@ -27,6 +28,7 @@ const FwApproachCollection = require('./../js/fwApproachCollection');
const SerialBackend = require('./../js/serial_backend'); const SerialBackend = require('./../js/serial_backend');
const { distanceOnLine, wrap_360, calculate_new_cooridatnes } = require('./../js/helpers'); const { distanceOnLine, wrap_360, calculate_new_cooridatnes } = require('./../js/helpers');
const Plotly = require('./../js/libraries/plotly-latest.min'); const Plotly = require('./../js/libraries/plotly-latest.min');
const interval = require('./../js/intervals');
var MAX_NEG_FW_LAND_ALT = -2000; // cm var MAX_NEG_FW_LAND_ALT = -2000; // cm
@ -334,19 +336,15 @@ TABS.mission_control.initialize = function (callback) {
*/ */
if(!isOffline) if(!isOffline)
{ {
mspBalancedInterval.add('gps_pull', 200, 3, function gps_update() { interval.add('gps_pull', function gps_update() {
// avoid usage of the GPS commands until a GPS sensor is detected for targets that are compiled without GPS support. // avoid usage of the GPS commands until a GPS sensor is detected for targets that are compiled without GPS support.
if (!SerialBackend.have_sensor(FC.CONFIG.activeSensors, 'gps')) { if (!SerialBackend.have_sensor(FC.CONFIG.activeSensors, 'gps')) {
update_gpsTrack(); update_gpsTrack();
return; return;
} }
if (mspQueue.shouldDrop()) {
return;
}
get_raw_gps_data(); get_raw_gps_data();
}); }, 200);
} }
GUI.content_ready(callback); GUI.content_ready(callback);
@ -483,7 +481,7 @@ TABS.mission_control.initialize = function (callback) {
function checkApproachAltitude(altitude, isSeaLevelRef, sealevel) { function checkApproachAltitude(altitude, isSeaLevelRef, sealevel) {
if (altitude - (isSeaLevelRef ? sealevel * 100 : 0 ) < 0) { if (altitude - (isSeaLevelRef ? sealevel * 100 : 0 ) < 0) {
alert(i18n.getMessage('MissionPlannerAltitudeChangeReset')); GUI.alert(i18n.getMessage('MissionPlannerAltitudeChangeReset'));
return false; return false;
} }
@ -493,7 +491,7 @@ TABS.mission_control.initialize = function (callback) {
function checkLandingAltitude(altitude, isSeaLevelRef, sealevel) { function checkLandingAltitude(altitude, isSeaLevelRef, sealevel) {
if (altitude - (isSeaLevelRef ? sealevel * 100 : 0 ) < MAX_NEG_FW_LAND_ALT) { if (altitude - (isSeaLevelRef ? sealevel * 100 : 0 ) < MAX_NEG_FW_LAND_ALT) {
alert(i18n.getMessage('MissionPlannerFwLAndingAltitudeChangeReset')); GUI.alert(i18n.getMessage('MissionPlannerFwLAndingAltitudeChangeReset'));
return false; return false;
} }
@ -1489,26 +1487,26 @@ TABS.mission_control.initialize = function (callback) {
if ($(this).val() >= 360 || ($(this).val() < 0 && $(this).val() != -1)) if ($(this).val() >= 360 || ($(this).val() < 0 && $(this).val() != -1))
{ {
$(this).val(-1); $(this).val(-1);
alert(i18n.getMessage('MissionPlannerHeadSettingsCheck')); GUI.alert(i18n.getMessage('MissionPlannerHeadSettingsCheck'));
} }
} }
else if (MWNP.WPTYPE.REV[element.getAction()] == "RTH") { else if (MWNP.WPTYPE.REV[element.getAction()] == "RTH") {
if ($(this).val() != 0 && $(this).val() != 1) if ($(this).val() != 0 && $(this).val() != 1)
{ {
$(this).val(0); $(this).val(0);
alert(i18n.getMessage('MissionPlannerRTHSettingsCheck')); GUI.alert(i18n.getMessage('MissionPlannerRTHSettingsCheck'));
} }
} }
else if (MWNP.WPTYPE.REV[element.getAction()] == "JUMP") { else if (MWNP.WPTYPE.REV[element.getAction()] == "JUMP") {
if ($(this).val() > mission.getNonAttachedList().length || $(this).val() < 1) if ($(this).val() > mission.getNonAttachedList().length || $(this).val() < 1)
{ {
$(this).val(1); $(this).val(1);
alert(i18n.getMessage('MissionPlannerJumpSettingsCheck')); GUI.alert(i18n.getMessage('MissionPlannerJumpSettingsCheck'));
} }
else if (mission.getPoiList().length != 0 && mission.getPoiList()) { else if (mission.getPoiList().length != 0 && mission.getPoiList()) {
if (mission.getPoiList().includes(mission.convertJumpNumberToWaypoint(Number($(this).val())-1))) { if (mission.getPoiList().includes(mission.convertJumpNumberToWaypoint(Number($(this).val())-1))) {
$(this).val(1); $(this).val(1);
alert(i18n.getMessage('MissionPlannerJump3SettingsCheck')); GUI.alert(i18n.getMessage('MissionPlannerJump3SettingsCheck'));
} }
} }
} }
@ -1523,7 +1521,7 @@ TABS.mission_control.initialize = function (callback) {
if ($(this).val() > 10 || ($(this).val() < 0 && $(this).val() != -1)) if ($(this).val() > 10 || ($(this).val() < 0 && $(this).val() != -1))
{ {
$(this).val(0); $(this).val(0);
alert(i18n.getMessage('MissionPlannerJump2SettingsCheck')); GUI.alert(i18n.getMessage('MissionPlannerJump2SettingsCheck'));
} }
} }
element.setP2(Number($(this).val())); element.setP2(Number($(this).val()));
@ -2310,7 +2308,7 @@ TABS.mission_control.initialize = function (callback) {
let found = false; let found = false;
mission.get().forEach(wp => { mission.get().forEach(wp => {
if (wp.getAction() == MWNP.WPTYPE.LAND) { if (wp.getAction() == MWNP.WPTYPE.LAND) {
alert(i18n.getMessage('MissionPlannerOnlyOneLandWp')); GUI.alert(i18n.getMessage('MissionPlannerOnlyOneLandWp'));
found = true; found = true;
$(event.currentTarget).val(selectedMarker.getAction()); $(event.currentTarget).val(selectedMarker.getAction());
} }
@ -2684,7 +2682,7 @@ TABS.mission_control.initialize = function (callback) {
$('#addSafehome').on('click', () => { $('#addSafehome').on('click', () => {
if (FC.SAFEHOMES.safehomeCount() + 1 > FC.SAFEHOMES.getMaxSafehomeCount()){ if (FC.SAFEHOMES.safehomeCount() + 1 > FC.SAFEHOMES.getMaxSafehomeCount()){
alert(i18n.getMessage('missionSafehomeMaxSafehomesReached')); GUI.alert(i18n.getMessage('missionSafehomeMaxSafehomesReached'));
return; return;
} }
@ -3016,7 +3014,7 @@ TABS.mission_control.initialize = function (callback) {
$('#removePoint').on('click', function () { $('#removePoint').on('click', function () {
if (selectedMarker) { if (selectedMarker) {
if (mission.isJumpTargetAttached(selectedMarker)) { if (mission.isJumpTargetAttached(selectedMarker)) {
alert(i18n.getMessage('MissionPlannerJumpTargetRemoval')); GUI.alert(i18n.getMessage('MissionPlannerJumpTargetRemoval'));
} }
else if (mission.getAttachedFromWaypoint(selectedMarker) && mission.getAttachedFromWaypoint(selectedMarker).length != 0) { else if (mission.getAttachedFromWaypoint(selectedMarker) && mission.getAttachedFromWaypoint(selectedMarker).length != 0) {
if (confirm(i18n.getMessage('confirm_delete_point_with_options'))) { if (confirm(i18n.getMessage('confirm_delete_point_with_options'))) {
@ -3096,7 +3094,7 @@ TABS.mission_control.initialize = function (callback) {
$('#saveMissionButton').on('click', function () { $('#saveMissionButton').on('click', function () {
if (mission.isEmpty()) { if (mission.isEmpty()) {
alert(i18n.getMessage('no_waypoints_to_save')); GUI.alert(i18n.getMessage('no_waypoints_to_save'));
return; return;
} }
$(this).addClass('disabled'); $(this).addClass('disabled');
@ -3115,7 +3113,7 @@ TABS.mission_control.initialize = function (callback) {
$('#saveEepromMissionButton').on('click', function () { $('#saveEepromMissionButton').on('click', function () {
if (mission.isEmpty()) { if (mission.isEmpty()) {
alert(i18n.getMessage('no_waypoints_to_save')); GUI.alert(i18n.getMessage('no_waypoints_to_save'));
return; return;
} }
$(this).addClass('disabled'); $(this).addClass('disabled');
@ -3161,9 +3159,6 @@ TABS.mission_control.initialize = function (callback) {
// //
///////////////////////////////////////////// /////////////////////////////////////////////
function loadMissionFile(filename) { function loadMissionFile(filename) {
const fs = require('fs');
if (!window.xml2js) return GUI.log(i18n.getMessage('errorReadingFileXml2jsNotFound'));
for (let i = FC.SAFEHOMES.getMaxSafehomeCount(); i < FC.FW_APPROACH.getMaxFwApproachCount(); i++) { for (let i = FC.SAFEHOMES.getMaxSafehomeCount(); i < FC.FW_APPROACH.getMaxFwApproachCount(); i++) {
FC.FW_APPROACH.clean(i); FC.FW_APPROACH.clean(i);
} }
@ -3174,7 +3169,7 @@ TABS.mission_control.initialize = function (callback) {
return console.error(err); return console.error(err);
} }
window.xml2js.Parser({ 'explicitChildren': true, 'preserveChildrenOrder': true }).parseString(data, (err, result) => { xml2js.Parser({ 'explicitChildren': true, 'preserveChildrenOrder': true }).parseString(data, (err, result) => {
if (err) { if (err) {
GUI.log(i18n.getMessage('errorParsingFile')); GUI.log(i18n.getMessage('errorParsingFile'));
return console.error(err); return console.error(err);
@ -3344,9 +3339,6 @@ TABS.mission_control.initialize = function (callback) {
} }
function saveMissionFile(filename) { function saveMissionFile(filename) {
const fs = require('fs');
if (!window.xml2js) return GUI.log(i18n.getMessage('errorWritingFileXml2jsNotFound'));
var center = ol.proj.toLonLat(map.getView().getCenter()); var center = ol.proj.toLonLat(map.getView().getCenter());
var zoom = map.getView().getZoom(); var zoom = map.getView().getZoom();
let multimission = multimissionCount && !singleMissionActive(); let multimission = multimissionCount && !singleMissionActive();
@ -3408,7 +3400,7 @@ TABS.mission_control.initialize = function (callback) {
approachIdx++; approachIdx++;
} }
var builder = new window.xml2js.Builder({ 'rootName': 'mission', 'renderOpts': { 'pretty': true, 'indent': '\t', 'newline': '\n' } }); var builder = new xml2js.Builder({ 'rootName': 'mission', 'renderOpts': { 'pretty': true, 'indent': '\t', 'newline': '\n' } });
var xml = builder.buildObject(data); var xml = builder.buildObject(data);
xml = xml.replace(/missionitem mission/g, 'meta mission'); xml = xml.replace(/missionitem mission/g, 'meta mission');
fs.writeFile(filename, xml, (err) => { fs.writeFile(filename, xml, (err) => {
@ -3445,7 +3437,7 @@ TABS.mission_control.initialize = function (callback) {
$('#loadMissionButton').removeClass('disabled'); $('#loadMissionButton').removeClass('disabled');
} }
if (!FC.MISSION_PLANNER.getCountBusyPoints()) { if (!FC.MISSION_PLANNER.getCountBusyPoints()) {
alert(i18n.getMessage('no_waypoints_to_load')); GUI.alert(i18n.getMessage('no_waypoints_to_load'));
return; return;
} }
mission.reinit(); mission.reinit();
@ -3555,7 +3547,7 @@ TABS.mission_control.initialize = function (callback) {
if (AbsAltCheck) { if (AbsAltCheck) {
if (checkAltitude < 100 * elevation) { if (checkAltitude < 100 * elevation) {
if (resetAltitude) { if (resetAltitude) {
alert(i18n.getMessage('MissionPlannerAltitudeChangeReset')); GUI.alert(i18n.getMessage('MissionPlannerAltitudeChangeReset'));
altitude = selectedMarker.getAlt(); altitude = selectedMarker.getAlt();
} else { } else {
altitude = settings.alt + 100 * elevation; altitude = settings.alt + 100 * elevation;
@ -3566,7 +3558,7 @@ TABS.mission_control.initialize = function (callback) {
let elevationAtHome = HOME.getAlt(); let elevationAtHome = HOME.getAlt();
if ((checkAltitude / 100 + elevationAtHome) < elevation) { if ((checkAltitude / 100 + elevationAtHome) < elevation) {
if (resetAltitude) { if (resetAltitude) {
alert(i18n.getMessage('MissionPlannerAltitudeChangeReset')); GUI.alert(i18n.getMessage('MissionPlannerAltitudeChangeReset'));
altitude = selectedMarker.getAlt(); altitude = selectedMarker.getAlt();
} else { } else {
let currentGroundClearance = 100 * Number($('#groundClearanceValueAtWP').text()); let currentGroundClearance = 100 * Number($('#groundClearanceValueAtWP').text());
@ -3702,9 +3694,9 @@ TABS.mission_control.setBit = function(bits, bit, value) {
// function handleError(evt) { // function handleError(evt) {
// if (evt.message) { // Chrome sometimes provides this // if (evt.message) { // Chrome sometimes provides this
// alert("error: "+evt.message +" at linenumber: "+evt.lineno+" of file: "+evt.filename); // GUI.alert("error: "+evt.message +" at linenumber: "+evt.lineno+" of file: "+evt.filename);
// } else { // } else {
// alert("error: "+evt.type+" from element: "+(evt.srcElement || evt.target)); // GUI.alert("error: "+evt.type+" from element: "+(evt.srcElement || evt.target));
// } // }
// } // }

@ -11,8 +11,8 @@ const FC = require('./../js/fc');
const i18n = require('./../js/localization'); const i18n = require('./../js/localization');
const { mixer, platform, PLATFORM, INPUT, STABILIZED } = require('./../js/model'); const { mixer, platform, PLATFORM, INPUT, STABILIZED } = require('./../js/model');
const Settings = require('./../js/settings'); const Settings = require('./../js/settings');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const jBox = require('../js/libraries/jBox/jBox.min'); const jBox = require('../js/libraries/jBox/jBox.min');
const interval = require('./../js/intervals');
TABS.mixer = {}; TABS.mixer = {};
@ -823,9 +823,9 @@ TABS.mixer.initialize = function (callback, scrollPosition) {
FC.LOGIC_CONDITIONS.init($('#logic-wrapper')); FC.LOGIC_CONDITIONS.init($('#logic-wrapper'));
i18n.localize();; i18n.localize();;
mspBalancedInterval.add('logic_conditions_pull', 350, 1, getLogicConditionsStatus); interval.add('logic_conditions_pull', getLogicConditionsStatus, 350);
GUI.content_ready(callback); GUI.content_ready(callback);
} }

@ -152,7 +152,6 @@
<div class="legend"></div> <div class="legend"></div>
</li> </li>
</ul><bbr /> </ul><bbr />
<a class="require-msc-ready regular-button onboardLoggingRebootMsc" href="#" i18n="cliMscBtn"></a>
</div> </div>
</div> </div>
</div> </div>

@ -1,9 +1,12 @@
'use strict'; 'use strict';
const { dialog } = require("@electron/remote");
const fs = require('fs');
const path = require('path'); const path = require('path');
const MSPCodes = require('./../js/msp/MSPCodes'); const MSPCodes = require('./../js/msp/MSPCodes');
const MSP = require('./../js/msp'); const MSP = require('./../js/msp');
const mspHelper = require("./../js/msp/MSPHelper");
const { GUI, TABS } = require('./../js/gui'); const { GUI, TABS } = require('./../js/gui');
const FC = require('./../js/fc'); const FC = require('./../js/fc');
const CONFIGURATOR = require('./../js/data_storage'); const CONFIGURATOR = require('./../js/data_storage');
@ -355,7 +358,6 @@ TABS.onboard_logging.initialize = function (callback) {
const maxBytes = FC.DATAFLASH.usedSize; const maxBytes = FC.DATAFLASH.usedSize;
prepare_file(function(filename) { prepare_file(function(filename) {
const fs = require('fs');
let nextAddress = 0; let nextAddress = 0;
show_saving_dialog(); show_saving_dialog();

@ -1,6 +1,7 @@
'use strict'; 'use strict';
const inflection = require( 'inflection' ); const inflection = require( 'inflection' );
const fs = require('fs');
const path = require('path'); const path = require('path');
const semver = require('semver'); const semver = require('semver');
const mapSeries = require('promise-map-series'); const mapSeries = require('promise-map-series');
@ -269,7 +270,6 @@ FONT.openFontFile = function ($preview) {
} }
if (result.filePaths.length == 1) { if (result.filePaths.length == 1) {
const fs = require('fs');
const fontData = fs.readFileSync(result.filePaths[0], {flag: "r"}); const fontData = fs.readFileSync(result.filePaths[0], {flag: "r"});
FONT.parseMCMFontFile(fontData.toString()); FONT.parseMCMFontFile(fontData.toString());
resolve(); resolve();

@ -5,7 +5,6 @@ const path = require('path');
const MSPChainerClass = require('./../js/msp/MSPchainer'); const MSPChainerClass = require('./../js/msp/MSPchainer');
const mspHelper = require('./../js/msp/MSPHelper'); const mspHelper = require('./../js/msp/MSPHelper');
const MSPCodes = require('./../js/msp/MSPCodes'); const MSPCodes = require('./../js/msp/MSPCodes');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const mspQueue = require('./../js/serial_queue') const mspQueue = require('./../js/serial_queue')
const MSP = require('./../js/msp'); const MSP = require('./../js/msp');
const { GUI, TABS } = require('./../js/gui'); const { GUI, TABS } = require('./../js/gui');
@ -430,18 +429,8 @@ TABS.outputs.initialize = function (callback) {
// timer initialization // timer initialization
interval.killAll(['motor_and_status_pull', 'global_data_refresh', 'msp-load-update', 'ltm-connection-check']); interval.killAll(['motor_and_status_pull', 'global_data_refresh', 'msp-load-update', 'ltm-connection-check']);
mspBalancedInterval.flush();
interval.add('IMU_pull', function () { interval.add('IMU_pull', function () {
/*
* Enable balancer
*/
if (mspQueue.shouldDrop()) {
update_accel_graph();
return;
}
MSP.send_message(MSPCodes.MSP_RAW_IMU, false, false, update_accel_graph); MSP.send_message(MSPCodes.MSP_RAW_IMU, false, false, update_accel_graph);
}, 25, true); }, 25, true);
@ -662,21 +651,10 @@ TABS.outputs.initialize = function (callback) {
$motorsEnableTestMode.trigger('change'); $motorsEnableTestMode.trigger('change');
function getPeriodicMotorOutput() { function getPeriodicMotorOutput() {
if (mspQueue.shouldDrop()) {
getPeriodicServoOutput();
return;
}
MSP.send_message(MSPCodes.MSP_MOTOR, false, false, getPeriodicServoOutput); MSP.send_message(MSPCodes.MSP_MOTOR, false, false, getPeriodicServoOutput);
} }
function getPeriodicServoOutput() { function getPeriodicServoOutput() {
if (mspQueue.shouldDrop()) {
update_ui();
return;
}
MSP.send_message(MSPCodes.MSP_SERVO, false, false, update_ui); MSP.send_message(MSPCodes.MSP_SERVO, false, false, update_ui);
} }

@ -3,13 +3,12 @@
const path = require('path'); const path = require('path');
const MSPChainerClass = require('./../js/msp/MSPchainer'); const MSPChainerClass = require('./../js/msp/MSPchainer');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const mspHelper = require('./../js/msp/MSPHelper'); const mspHelper = require('./../js/msp/MSPHelper');
const { GUI, TABS } = require('./../js/gui'); const { GUI, TABS } = require('./../js/gui');
const FC = require('./../js/fc'); const FC = require('./../js/fc');
const tabs = require('./../js/tabs'); const tabs = require('./../js/tabs');
const i18n = require('./../js/localization'); const i18n = require('./../js/localization');
const interval = require('./../js/intervals');
TABS.programming = {}; TABS.programming = {};
@ -68,9 +67,9 @@ TABS.programming.initialize = function (callback, scrollPosition) {
GUI.log(i18n.getMessage('programmingEepromSaved')); GUI.log(i18n.getMessage('programmingEepromSaved'));
}); });
mspBalancedInterval.add('logic_conditions_pull', 100, 1, function () { interval.add('logic_conditions_pull', function () {
statusChainer.execute(); statusChainer.execute();
}); }, 100);
GUI.content_ready(callback); GUI.content_ready(callback);
} }

@ -4,8 +4,6 @@ const path = require('path');
const MSPChainerClass = require('./../js/msp/MSPchainer'); const MSPChainerClass = require('./../js/msp/MSPchainer');
const mspHelper = require('./../js/msp/MSPHelper'); const mspHelper = require('./../js/msp/MSPHelper');
const mspQueue = require('./../js/serial_queue');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const MSPCodes = require('./../js/msp/MSPCodes'); const MSPCodes = require('./../js/msp/MSPCodes');
const MSP = require('./../js/msp'); const MSP = require('./../js/msp');
const { GUI, TABS } = require('./../js/gui'); const { GUI, TABS } = require('./../js/gui');
@ -13,6 +11,7 @@ const FC = require('./../js/fc');
const CONFIGURATOR = require('./../js/data_storage'); const CONFIGURATOR = require('./../js/data_storage');
const Settings = require('./../js/settings'); const Settings = require('./../js/settings');
const i18n = require('./../js/localization'); const i18n = require('./../js/localization');
const interval = require('./../js/intervals');
TABS.receiver = { TABS.receiver = {
rateChartHeight: 117 rateChartHeight: 117
@ -370,21 +369,10 @@ TABS.receiver.initialize = function (callback) {
}); });
function get_rc_data() { function get_rc_data() {
/*
* Throttling
*/
if (mspQueue.shouldDrop()) {
update_ui();
return;
}
MSP.send_message(MSPCodes.MSP_RC, false, false, update_ui); MSP.send_message(MSPCodes.MSP_RC, false, false, update_ui);
} }
function update_ui() { function update_ui() {
var i;
// update bars with latest data // update bars with latest data
for (let i = 0; i < FC.RC.active_channels; i++) { for (let i = 0; i < FC.RC.active_channels; i++) {
meter_fill_array[i].css('width', ((FC.RC.channels[i] - meter_scale.min) / (meter_scale.max - meter_scale.min) * 100).clamp(0, 100) + '%'); meter_fill_array[i].css('width', ((FC.RC.channels[i] - meter_scale.min) / (meter_scale.max - meter_scale.min) * 100).clamp(0, 100) + '%');
@ -393,7 +381,7 @@ TABS.receiver.initialize = function (callback) {
} }
mspBalancedInterval.add('receiver_pull', 35, 1, get_rc_data); interval.add('receiver_pull', get_rc_data, 25);
GUI.content_ready(callback); GUI.content_ready(callback);
} }

@ -442,90 +442,36 @@ TABS.sensors.initialize = function (callback) {
// data pulling timers // data pulling timers
if (checkboxes[0] || checkboxes[1] || checkboxes[2]) { if (checkboxes[0] || checkboxes[1] || checkboxes[2]) {
interval.add('IMU_pull', function () { interval.add('IMU_pull', function () {
/*
* Enable balancer
*/
if (mspQueue.shouldDrop()) {
update_imu_graphs();
return;
}
MSP.send_message(MSPCodes.MSP_RAW_IMU, false, false, update_imu_graphs); MSP.send_message(MSPCodes.MSP_RAW_IMU, false, false, update_imu_graphs);
}, fastest, true); }, fastest, true);
} }
if (checkboxes[3]) { if (checkboxes[3]) {
interval.add('altitude_pull', function altitude_data_pull() { interval.add('altitude_pull', function altitude_data_pull() {
/*
* Enable balancer
*/
if (mspQueue.shouldDrop()) {
update_altitude_graph();
return;
}
MSP.send_message(MSPCodes.MSP_ALTITUDE, false, false, update_altitude_graph); MSP.send_message(MSPCodes.MSP_ALTITUDE, false, false, update_altitude_graph);
}, rates.baro, true); }, rates.baro, true);
} }
if (checkboxes[4]) { if (checkboxes[4]) {
interval.add('sonar_pull', function sonar_data_pull() { interval.add('sonar_pull', function sonar_data_pull() {
/*
* Enable balancer
*/
if (mspQueue.shouldDrop()) {
update_sonar_graphs();
return;
}
MSP.send_message(MSPCodes.MSP_SONAR, false, false, update_sonar_graphs); MSP.send_message(MSPCodes.MSP_SONAR, false, false, update_sonar_graphs);
}, rates.sonar, true); }, rates.sonar, true);
} }
if (checkboxes[5]) { if (checkboxes[5]) {
interval.add('airspeed_pull', function airspeed_data_pull() { interval.add('airspeed_pull', function airspeed_data_pull() {
/*
* Enable balancer
*/
if (mspQueue.shouldDrop()) {
update_airspeed_graphs();
return;
}
MSP.send_message(MSPCodes.MSPV2_INAV_AIR_SPEED, false, false, update_airspeed_graphs); MSP.send_message(MSPCodes.MSPV2_INAV_AIR_SPEED, false, false, update_airspeed_graphs);
}, rates.airspeed, true); }, rates.airspeed, true);
} }
if (checkboxes[6]) { if (checkboxes[6]) {
interval.add('temperature_pull', function temperature_data_pull() { interval.add('temperature_pull', function temperature_data_pull() {
/*
* Enable balancer
*/
if (mspQueue.shouldDrop()) {
update_temperature_graphs();
return;
}
MSP.send_message(MSPCodes.MSP2_INAV_TEMPERATURES, false, false, update_temperature_graphs); MSP.send_message(MSPCodes.MSP2_INAV_TEMPERATURES, false, false, update_temperature_graphs);
}, 1000, true); }, 1000, true);
} }
if (checkboxes[7]) { if (checkboxes[7]) {
interval.add('debug_pull', function debug_data_pull() { interval.add('debug_pull', function debug_data_pull() {
/*
* Enable balancer
*/
if (mspQueue.shouldDrop()) {
update_debug_graphs();
return;
}
MSP.send_message(MSPCodes.MSP2_INAV_DEBUG, false, false, update_debug_graphs); MSP.send_message(MSPCodes.MSP2_INAV_DEBUG, false, false, update_debug_graphs);
}, rates.debug, true); }, rates.debug, true);
} }

@ -9,9 +9,7 @@ const MSP = require('./../js/msp');
const MSPCodes = require('./../js/msp/MSPCodes'); const MSPCodes = require('./../js/msp/MSPCodes');
const i18n = require('./../js/localization'); const i18n = require('./../js/localization');
const mspHelper = require('./../js/msp/MSPHelper'); const mspHelper = require('./../js/msp/MSPHelper');
const mspBalancedInterval = require('./../js/msp_balanced_interval');
const interval = require('./../js/intervals'); const interval = require('./../js/intervals');
const mspQueue = require('./../js/serial_queue');
const SerialBackend = require('./../js/serial_backend'); const SerialBackend = require('./../js/serial_backend');
const { mixer } = require('./../js/model'); const { mixer } = require('./../js/model');
const BitHelper = require('./../js/bitHelper') const BitHelper = require('./../js/bitHelper')
@ -119,14 +117,6 @@ TABS.setup.initialize = function (callback) {
function get_slow_data() { function get_slow_data() {
if (SerialBackend.have_sensor(FC.CONFIG.activeSensors, 'gps')) { if (SerialBackend.have_sensor(FC.CONFIG.activeSensors, 'gps')) {
/*
* Enable balancer
*/
if (mspQueue.shouldDrop()) {
return;
}
MSP.send_message(MSPCodes.MSP_RAW_GPS, false, false, function () { MSP.send_message(MSPCodes.MSP_RAW_GPS, false, false, function () {
var gpsFixType = i18n.getMessage('gpsFixNone'); var gpsFixType = i18n.getMessage('gpsFixNone');
if (FC.GPS_DATA.fix >= 2) if (FC.GPS_DATA.fix >= 2)
@ -142,14 +132,6 @@ TABS.setup.initialize = function (callback) {
} }
function get_fast_data() { function get_fast_data() {
/*
* Enable balancer
*/
if (mspQueue.shouldDrop()) {
return;
}
MSP.send_message(MSPCodes.MSP_ATTITUDE, false, false, function () { MSP.send_message(MSPCodes.MSP_ATTITUDE, false, false, function () {
roll_e.text(i18n.getMessage('initialSetupAttitude', [FC.SENSOR_DATA.kinematics[0]])); roll_e.text(i18n.getMessage('initialSetupAttitude', [FC.SENSOR_DATA.kinematics[0]]));
pitch_e.text(i18n.getMessage('initialSetupAttitude', [FC.SENSOR_DATA.kinematics[1]])); pitch_e.text(i18n.getMessage('initialSetupAttitude', [FC.SENSOR_DATA.kinematics[1]]));
@ -159,8 +141,8 @@ TABS.setup.initialize = function (callback) {
}); });
} }
mspBalancedInterval.add('setup_data_pull_fast', 40, 1, get_fast_data); interval.add('setup_data_pull_fast', get_fast_data, 50);
mspBalancedInterval.add('setup_data_pull_slow', 250, 1, get_slow_data); interval.add('setup_data_pull_slow', get_slow_data, 250);
interval.add('gui_analog_update', function () { interval.add('gui_analog_update', function () {
bat_cells_e.text(i18n.getMessage('initialSetupBatteryDetectedCellsValue', [FC.ANALOG.cell_count])); bat_cells_e.text(i18n.getMessage('initialSetupBatteryDetectedCellsValue', [FC.ANALOG.cell_count]));

@ -78,17 +78,6 @@ TABS.sitl.initialize = (callback) => {
GUI.load(path.join(__dirname, "sitl.html"), function () { GUI.load(path.join(__dirname, "sitl.html"), function () {
i18n.localize(); i18n.localize();
var os = GUI.operating_system;
if (os != 'Windows' && os != 'Linux') {
$('.content_wrapper').find('*').remove();
$('.content_wrapper').append(`<h2>${i18n.getMessage('sitlOSNotSupported')}</h2>`);
GUI.content_ready(callback);
return;
}
var currentSim, currentProfile, profiles; var currentSim, currentProfile, profiles;
var mapping = new Array(28).fill(0); var mapping = new Array(28).fill(0);
var serialProtocolls = Ser2TCP.getProtocolls(); var serialProtocolls = Ser2TCP.getProtocolls();
@ -253,7 +242,7 @@ TABS.sitl.initialize = (callback) => {
return; return;
if (profiles.find(e => { return e.name == name })) { if (profiles.find(e => { return e.name == name })) {
alert(i18n.getMessage('sitlProfileExists')) GUI.alert(i18n.getMessage('sitlProfileExists'))
return; return;
} }
var eerpromName = name.replace(/[^a-z0-9]/gi, '_').toLowerCase() + ".bin"; var eerpromName = name.replace(/[^a-z0-9]/gi, '_').toLowerCase() + ".bin";
@ -284,7 +273,7 @@ TABS.sitl.initialize = (callback) => {
profileDeleteBtn_e.on('click', function () { profileDeleteBtn_e.on('click', function () {
if (currentProfile.isStdProfile) { if (currentProfile.isStdProfile) {
alert(i18n.getMessage('sitlStdProfileCantDeleted')); GUI.alert(i18n.getMessage('sitlStdProfileCantDeleted'));
return; return;
} }
@ -385,7 +374,7 @@ TABS.sitl.initialize = (callback) => {
function saveProfiles() { function saveProfiles() {
if (currentProfile.isStdProfile) { if (currentProfile.isStdProfile) {
alert(i18n.getMessage('sitlStdProfileCantOverwritten')); GUI.alert(i18n.getMessage('sitlStdProfileCantOverwritten'));
return; return;
} }
var profilesToSave = []; var profilesToSave = [];
@ -524,4 +513,4 @@ TABS.sitl.cleanup = (callback) => {
Ser2TCP.stopPollSerialPorts(); Ser2TCP.stopPollSerialPorts();
if (callback) if (callback)
callback(); callback();
}; };

Loading…
Cancel
Save