Merge branch 'master' into MrD_Move-AHI-on-OSD-screen

pull/1540/head
Darren Lines 2 years ago
commit 3b1a9b8453

@ -83,6 +83,7 @@ in the `./dist/` directory.
- **release**: Create NW.js apps for each supported platform (win32, osx64 and linux64) in the `./apps`
directory. Running this task on macOS or Linux requires Wine, since it's needed to set the icon
for the Windows app. If you don't have Wine installed you can create a release by running the **release-only-linux** task.
<br>`--installer` argument can be added to build installers for particular OS. NOTE: MacOS Installer can be built with MacOS only.
To build a specific release, use the command `release --platform="win64"` for example.

@ -49,6 +49,9 @@
"savingDefaults": {
"message": "Device - <span style=\"color: red\">Saving default settings</span>"
},
"resettingPIDs": {
"message": "Device - <span style=\"color: red\">Resetting PID & related settings</span>"
},
"fcNotConnected": {
"message": "Not connected"
},
@ -3883,7 +3886,7 @@
"message": "This will allow to select new default values for all settings. Existing PID tune and other settings might be lost!\nDo you want to continue?"
},
"confirm_reset_pid": {
"message": "This will reset all PID settings to firmware default values and save.\nDo you want to continue?"
"message": "This will reset all PID settings for the current profile to platform default values and save.\nDo you want to continue?"
},
"mappingTableOutput": {
"message": "Output"
@ -4123,7 +4126,7 @@
"message": "Should be enabled on Airplanes, Rovers and Boats. Should not be enabled on Multirotors! On Multirotors, when Airmode is active, motors will not stop."
},
"reversibleEscWarning": {
"message": "When Reversible Motors are used, set Motors IDLE power ot 0%"
"message": "When Reversible Motors are used, set Motors IDLE power to 0%"
},
"dynamic_gyro_notch_enabled_help": {
"message": "Matrix Gyro Filter is the new generation of dynamic gyro notches available in INAV. It is recommended to enable it on all Multirotor builds on F4 and F7 flight controllers."
@ -4293,6 +4296,18 @@
"BLACKBOX_FEATURE_MOTORS": {
"message": "Motors output"
},
"BLACKBOX_FEATURE_GYRO_RAW": {
"message": "Gyro RAW (no filtering)"
},
"BLACKBOX_FEATURE_GYRO_PEAKS_ROLL": {
"message": "Gyro Noise peak freq. Roll"
},
"BLACKBOX_FEATURE_GYRO_PEAKS_PITCH": {
"message": "Gyro Noise peak freq. Pitch"
},
"BLACKBOX_FEATURE_GYRO_PEAKS_YAW": {
"message": "Gyro Noise peak freq. Yaw"
},
"axisRoll": {
"message": "Roll"
},

@ -0,0 +1,23 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: INAV Configurator
Source: https://github.com/iNavFlight/inav-configurator
Files: *
Copyright: Copyright 2022 The INAV open source project
License: GPL-3
License: GPL-3
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU General Public License
can be found in `/usr/share/common-licenses/GPL-3'.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

@ -0,0 +1,8 @@
[Desktop Entry]
Name=INAV Configurator
Comment=Crossplatform configuration tool for the INAV flight control system
Exec=/opt/inav/inav-configurator/inav-configurator
Icon=/opt/inav/inav-configurator/icon/inav_icon_128.png
Terminal=false
Type=Application
Categories=Utility

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

@ -0,0 +1,169 @@
; ------------------------------------------
; Installer for INAV
; ------------------------------------------
; It receives from the command line with /D the parameters:
; version
; archName
; archAllowed
; archInstallIn64bit
; sourceFolder
; targetFolder
#define ApplicationName "INAV Configurator"
#define CompanyName "The INAV open source project"
#define CompanyUrl "https://github.com/iNavFlight/inav"
#define ExecutableFileName "inav-configurator.exe"
#define GroupName "INAV"
#define InstallerFileName "INAV-Configurator_" + archName + "-installer" + "_" + version
#define SourcePath "..\..\" + sourceFolder + "\inav-configurator\" + archName
#define TargetFolderName "INAV-Configurator"
#define UpdatesUrl "https://github.com/iNavFlight/inav-configurator/releases"
[CustomMessages]
AppName=inav-configurator
LaunchProgram=Start {#ApplicationName}
[Files]
Source: "{#SourcePath}\*"; DestDir: "{app}"; Flags: recursesubdirs
[Icons]
; Programs group
Name: "{group}\{#ApplicationName}"; Filename: "{app}\{#ExecutableFileName}";
; Desktop icon
Name: "{autodesktop}\{#ApplicationName}"; Filename: "{app}\{#ExecutableFileName}";
; Non admin users, uninstall icon
Name: "{group}\Uninstall {#ApplicationName}"; Filename: "{uninstallexe}"; Check: not IsAdminInstallMode
[Languages]
; English default, it must be first
Name: "en"; MessagesFile: "compiler:Default.isl"
; Official languages
;Name: "ca"; MessagesFile: "compiler:Languages\Catalan.isl"
;Name: "da"; MessagesFile: "compiler:Languages\Danish.isl"
;Name: "de"; MessagesFile: "compiler:Languages\German.isl"
;Name: "es"; MessagesFile: "compiler:Languages\Spanish.isl"
;Name: "fr"; MessagesFile: "compiler:Languages\French.isl"
;Name: "it"; MessagesFile: "compiler:Languages\Italian.isl"
;Name: "ja"; MessagesFile: "compiler:Languages\Japanese.isl"
;Name: "nl"; MessagesFile: "compiler:Languages\Dutch.isl"
;Name: "pt"; MessagesFile: "compiler:Languages\Portuguese.isl"
;Name: "pl"; MessagesFile: "compiler:Languages\Polish.isl"
;Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"
; Not official. Sometimes not updated to latest version (strings missing)
;Name: "ga"; MessagesFile: "unofficial_inno_languages\Galician.isl"
;Name: "eu"; MessagesFile: "unofficial_inno_languages\Basque.isl"
;Name: "hr"; MessagesFile: "unofficial_inno_languages\Croatian.isl"
;Name: "hu"; MessagesFile: "unofficial_inno_languages\Hungarian.isl"
;Name: "id"; MessagesFile: "unofficial_inno_languages\Indonesian.isl"
;Name: "ko"; MessagesFile: "unofficial_inno_languages\Korean.isl"
;Name: "lv"; MessagesFile: "unofficial_inno_languages\Latvian.isl"
;Name: "sv"; MessagesFile: "unofficial_inno_languages\Swedish.isl"
;Name: "zh_CN"; MessagesFile: "unofficial_inno_languages\ChineseSimplified.isl"
;Name: "zh_TW"; MessagesFile: "unofficial_inno_languages\ChineseTraditional.isl"
; Not available
; pt_BR (Portuguese Brasileiro)
[Run]
; Add a checkbox to start the app after installed
Filename: {app}\{cm:AppName}.exe; Description: {cm:LaunchProgram,{cm:AppName}}; Flags: nowait postinstall skipifsilent
[Setup]
AppId=2e5662ca-1fb3-8f1e-a7e1-e390add7a19d
AppName={#ApplicationName}
AppPublisher={#CompanyName}
AppPublisherURL={#CompanyUrl}
AppUpdatesURL={#UpdatesUrl}
AppVersion={#version}
ArchitecturesAllowed={#archAllowed}
ArchitecturesInstallIn64BitMode={#archInstallIn64bit}
Compression=lzma2
DefaultDirName={autopf}\{#GroupName}\{#TargetFolderName}
DefaultGroupName={#GroupName}\{#ApplicationName}
LicenseFile=..\..\LICENSE
MinVersion=6.2
OutputBaseFilename={#InstallerFileName}
OutputDir=..\..\{#targetFolder}\
PrivilegesRequiredOverridesAllowed=commandline dialog
SetupIconFile=inav_installer_icon.ico
ShowLanguageDialog=yes
SolidCompression=yes
UninstallDisplayIcon={app}\{#ExecutableFileName}
UninstallDisplayName={#ApplicationName}
WizardImageFile=inav_installer.bmp
WizardSmallImageFile=inav_installer_small.bmp
WizardStyle=modern
[Code]
function GetOldNsisUninstallerPath(): String;
var
RegKey: String;
begin
Result := '';
// Look into the different registry entries: win32, win64 and without user rights
if not RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\INAV Configurator', 'UninstallString', Result) then
begin
if not RegQueryStringValue(HKLM, 'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\INAV Configurator', 'UninstallString', Result) then
begin
RegQueryStringValue(HKCU, 'SOFTWARE\INAV\INAV Configurator', 'UninstallString', Result)
end;
end;
end;
function GetQuietUninstallerPath(): String;
var
RegKey: String;
begin
Result := '';
RegKey := Format('%s\%s_is1', ['Software\Microsoft\Windows\CurrentVersion\Uninstall', '{#emit SetupSetting("AppId")}']);
if not RegQueryStringValue(HKEY_LOCAL_MACHINE, RegKey, 'QuietUninstallString', Result) then
begin
RegQueryStringValue(HKEY_CURRENT_USER, RegKey, 'QuietUninstallString', Result);
end;
end;
function InitializeSetup(): Boolean;
var
ResultCode: Integer;
ParameterStr : String;
UninstPath : String;
begin
Result := True;
// Check if the application is already installed by the old NSIS installer, and uninstall it
UninstPath := GetOldNsisUninstallerPath();
// Found, start uninstall
if UninstPath <> '' then
begin
UninstPath := RemoveQuotes(UninstPath);
// Add this parameter to not return until uninstall finished. The drawback is that the uninstaller file is not deleted
ParameterStr := '_?=' + ExtractFilePath(UninstPath);
if Exec(UninstPath, ParameterStr, '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
begin
// Delete the unistaller file and empty folders. Not deleting the files.
DeleteFile(UninstPath);
DelTree(ExtractFilePath(UninstPath), True, False, True);
end
else begin
Result := False;
MsgBox('Error uninstalling old Configurator ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
end;
end
else begin
// Search for new Inno Setup installations
UninstPath := GetQuietUninstallerPath();
if UninstPath <> '' then
begin
if not Exec('>', UninstPath, '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
begin
Result := False;
MsgBox('Error uninstalling Configurator ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
end;
end;
end;
end;

@ -13,6 +13,8 @@ var semver = require('semver');
var gulp = require('gulp');
var concat = require('gulp-concat');
const commandExistsSync = require('command-exists').sync;
// Each key in the *sources* variable must be an array of
// the source files that will be combined into a single
// file and stored in *outputDir*. Each key in *sources*
@ -284,38 +286,75 @@ function get_nw_version() {
return semver.valid(semver.coerce(require('./package.json').dependencies.nw));
}
function get_release_filename(platform, ext) {
function get_release_filename(platform, ext, addition = '') {
var pkg = require('./package.json');
return 'INAV-Configurator_' + platform + '_' + pkg.version + '.' + ext;
return 'INAV-Configurator_' + platform + addition + '_' + pkg.version + '.' + ext;
}
gulp.task('release-win32', function() {
var pkg = require('./package.json');
var src = path.join(appsDir, pkg.name, 'win32');
var output = fs.createWriteStream(path.join(appsDir, get_release_filename('win32', 'zip')));
var archive = archiver('zip', {
zlib: { level: 9 }
});
archive.on('warning', function(err) { throw err; });
archive.on('error', function(err) { throw err; });
archive.pipe(output);
archive.directory(src, 'INAV Configurator');
return archive.finalize();
});
function build_win_zip(arch) {
return function build_win_zip_proc(done) {
var pkg = require('./package.json');
// Create ZIP
console.log(`Creating ${arch} ZIP file...`);
var src = path.join(appsDir, pkg.name, arch);
var output = fs.createWriteStream(path.join(appsDir, get_release_filename(arch, 'zip', '-portable')));
var archive = archiver('zip', {
zlib: { level: 9 }
});
archive.on('warning', function(err) { throw err; });
archive.on('error', function(err) { throw err; });
archive.pipe(output);
archive.directory(src, 'INAV Configurator');
return archive.finalize();
}
}
gulp.task('release-win64', function() {
var pkg = require('./package.json');
var src = path.join(appsDir, pkg.name, 'win64');
var output = fs.createWriteStream(path.join(appsDir, get_release_filename('win64', 'zip')));
var archive = archiver('zip', {
zlib: { level: 9 }
});
archive.on('warning', function(err) { throw err; });
archive.on('error', function(err) { throw err; });
archive.pipe(output);
archive.directory(src, 'INAV Configurator');
return archive.finalize();
});
function build_win_iss(arch) {
return function build_win_iss_proc(done) {
if (!getArguments().installer) {
done();
return null;
}
// Create Installer
console.log(`Creating ${arch} Installer...`);
const innoSetup = require('@quanle94/innosetup');
const APPS_DIR = './apps/';
const pkg = require('./package.json');
// Parameters passed to the installer script
const parameters = [];
// Extra parameters to replace inside the iss file
parameters.push(`/Dversion=${pkg.version}`);
parameters.push(`/DarchName=${arch}`);
parameters.push(`/DarchAllowed=${(arch === 'win32') ? 'x86 x64' : 'x64'}`);
parameters.push(`/DarchInstallIn64bit=${(arch === 'win32') ? '' : 'x64'}`);
parameters.push(`/DsourceFolder=${APPS_DIR}`);
parameters.push(`/DtargetFolder=${APPS_DIR}`);
// Show only errors in console
parameters.push(`/Q`);
// Script file to execute
parameters.push("assets/windows/installer.iss");
innoSetup(parameters, {},
function(error) {
if (error != null) {
console.error(`Installer for platform ${arch} finished with error ${error}`);
} else {
console.log(`Installer for platform ${arch} finished`);
}
done();
});
}
}
gulp.task('release-win32', gulp.series(build_win_zip('win32'), build_win_iss('win32')));
gulp.task('release-win64', gulp.series(build_win_zip('win64'), build_win_iss('win64')));
gulp.task('release-osx64', function(done) {
var pkg = require('./package.json');
@ -336,37 +375,295 @@ gulp.task('release-osx64', function(done) {
codesignArgs.push('-e', 'entitlements.plist');
codesignArgs.push(src)
execSync.apply(this, codesignArgs);
// Check if the bundle is signed
const codesignCheckArgs = [ 'codesign', '-vvv', '--deep', '--strict', src ];
execSync.apply(this, codesignCheckArgs);
}
const zipFilename = path.join(appsDir, get_release_filename('macOS', 'zip'));
var output = fs.createWriteStream(zipFilename);
var archive = archiver('zip', {
zlib: { level: 9 }
});
archive.on('warning', function(err) { throw err; });
archive.on('error', function(err) { throw err; });
archive.pipe(output);
archive.directory(src, 'INAV Configurator.app');
output.on('close', function() {
if (getArguments().notarize) {
const notarizeArgs = ['macapptool', '-v', '1', 'notarize'];
const notarizationUsername = getArguments()['notarization-username'];
if (notarizationUsername) {
notarizeArgs.push('-u', notarizationUsername)
// 'old' .zip mode
if (!getArguments().installer) {
const zipFilename = path.join(appsDir, get_release_filename('macOS', 'zip'));
console.log('Creating ZIP file: ' + zipFilename);
var output = fs.createWriteStream(zipFilename);
var archive = archiver('zip', {
zlib: { level: 9 }
});
archive.on('warning', function(err) { throw err; });
archive.on('error', function(err) { throw err; });
archive.pipe(output);
archive.directory(src, 'INAV Configurator.app');
output.on('close', function() {
if (getArguments().notarize) {
console.log('Notarizing DMG file: ' + zipFilename);
const notarizeArgs = ['macapptool', '-v', '1', 'notarize'];
const notarizationUsername = getArguments()['notarization-username'];
if (notarizationUsername) {
notarizeArgs.push('-u', notarizationUsername)
}
const notarizationPassword = getArguments()['notarization-password'];
if (notarizationPassword) {
notarizeArgs.push('-p', notarizationPassword)
}
notarizeArgs.push(zipFilename)
execSync.apply(this, notarizeArgs);
}
done();
});
archive.finalize();
}
// 'new' .dmg mode
else {
const appdmg = require('appdmg');
var target = path.join(appsDir, get_release_filename('macOS', 'dmg'));
console.log('Creating DMG file: ' + target);
var basepath = path.join(appsDir, pkg.name, 'osx64');
console.log('Base path: ' + basepath);
if (fs.existsSync(target)) {
fs.unlinkSync(target);
}
var specs = {};
specs["title"] = "INAV Configurator";
specs["contents"] = [
{ "x": 448, "y": 342, "type": "link", "path": "/Applications" },
{ "x": 192, "y": 344, "type": "file", "path": pkg.name + ".app", "name": "INAV Configurator.app" },
];
specs["background"] = path.join(__dirname, 'assets/osx/dmg-background.png');
specs["format"] = "UDZO";
specs["window"] = {
"size": {
"width": 638,
"height": 479,
}
const notarizationPassword = getArguments()['notarization-password'];
if (notarizationPassword) {
notarizeArgs.push('-p', notarizationPassword)
};
const codesignIdentity = getArguments()['codesign-identity'];
if (getArguments().codesign) {
specs['code-sign'] = {
'signing-identity': codesignIdentity,
}
notarizeArgs.push(zipFilename)
execSync.apply(this, notarizeArgs);
}
done();
});
archive.finalize();
const ee = appdmg({
target: target,
basepath: basepath,
specification: specs,
});
ee.on('progress', function(info) {
//console.log(info);
});
ee.on('error', function(err) {
console.log(err);
});
ee.on('finish', function() {
if (getArguments().codesign) {
// Check if the bundle is signed
const codesignCheckArgs = [ 'codesign', '-vvv', '--deep', '--strict', target ];
execSync.apply(this, codesignCheckArgs);
}
if (getArguments().notarize) {
console.log('Notarizing DMG file: ' + target);
const notarizeArgs = ['xcrun', 'notarytool', 'submit'];
notarizeArgs.push(target);
const notarizationUsername = getArguments()['notarization-username'];
if (notarizationUsername) {
notarizeArgs.push('--apple-id', notarizationUsername)
} else {
throw new Error('Missing notarization username');
}
const notarizationPassword = getArguments()['notarization-password'];
if (notarizationPassword) {
notarizeArgs.push('--password', notarizationPassword)
} else {
throw new Error('Missing notarization password');
}
const notarizationTeamId = getArguments()['notarization-team-id'];
if (notarizationTeamId) {
notarizeArgs.push('--team-id', notarizationTeamId)
} else {
throw new Error('Missing notarization Team ID');
}
notarizeArgs.push('--wait');
const notarizationWebhook = getArguments()['notarization-webhook'];
if (notarizationWebhook) {
notarizeArgs.push('--webhook', notarizationWebhook);
}
execSync.apply(this, notarizeArgs);
console.log('Stapling DMG file: ' + target);
const stapleArgs = ['xcrun', 'stapler', 'staple'];
stapleArgs.push(target);
execSync.apply(this, stapleArgs);
console.log('Checking DMG file: ' + target);
const checkArgs = ['spctl', '-vvv', '--assess', '--type', 'install', target];
execSync.apply(this, checkArgs);
}
done();
});
}
});
function post_build(arch, folder) {
return function post_build_linux(done) {
if ((arch === 'linux32') || (arch === 'linux64')) {
const metadata = require('./package.json');
// Copy Ubuntu launcher scripts to destination dir
const launcherDir = path.join(folder, metadata.name, arch);
console.log(`Copy Ubuntu launcher scripts to ${launcherDir}`);
return gulp.src('assets/linux/**')
.pipe(gulp.dest(launcherDir));
}
return done();
}
}
// Create the dir directory, with write permissions
function createDirIfNotExists(dir) {
fs.mkdir(dir, '0775', function(err) {
if (err && err.code !== 'EEXIST') {
throw err;
}
});
}
function release_deb(arch) {
return function release_deb_proc(done) {
if (!getArguments().installer) {
done();
return null;
}
// Check if dpkg-deb exists
if (!commandExistsSync('dpkg-deb')) {
console.warn(`dpkg-deb command not found, not generating deb package for ${arch}`);
done();
return null;
}
const deb = require('gulp-debian');
const LINUX_INSTALL_DIR = '/opt/inav';
const metadata = require('./package.json');
console.log(`Generating deb package for ${arch}`);
return gulp.src([path.join(appsDir, metadata.name, arch, '*')])
.pipe(deb({
package: metadata.name,
version: metadata.version,
section: 'base',
priority: 'optional',
architecture: getLinuxPackageArch('deb', arch),
maintainer: metadata.author,
description: metadata.description,
preinst: [`rm -rf ${LINUX_INSTALL_DIR}/${metadata.name}`],
postinst: [
`chown root:root ${LINUX_INSTALL_DIR}`,
`chown -R root:root ${LINUX_INSTALL_DIR}/${metadata.name}`,
`xdg-desktop-menu install ${LINUX_INSTALL_DIR}/${metadata.name}/${metadata.name}.desktop`,
],
prerm: [`xdg-desktop-menu uninstall ${metadata.name}.desktop`],
depends: ['libgconf-2-4', 'libatomic1'],
changelog: [],
_target: `${LINUX_INSTALL_DIR}/${metadata.name}`,
_out: appsDir,
_copyright: 'assets/linux/copyright',
_clean: true,
}));
}
}
function release_rpm(arch) {
return function release_rpm_proc(done) {
if (!getArguments().installer) {
done();
return null;
}
// Check if rpmbuild exists
if (!commandExistsSync('rpmbuild')) {
console.warn(`rpmbuild command not found, not generating rpm package for ${arch}`);
done();
return;
}
const buildRpm = require('rpm-builder');
const NAME_REGEX = /-/g;
const LINUX_INSTALL_DIR = '/opt/inav';
const metadata = require('./package.json');
console.log(`Generating rpm package for ${arch}`);
// The buildRpm does not generate the folder correctly, manually
createDirIfNotExists(appsDir);
const options = {
name: metadata.name,
version: metadata.version.replace(NAME_REGEX, '_'), // RPM does not like release candidate versions
buildArch: getLinuxPackageArch('rpm', arch),
vendor: metadata.author,
summary: metadata.description,
license: 'GNU General Public License v3.0',
requires: ['libgconf-2-4', 'libatomic1'],
prefix: '/opt',
files: [{
cwd: path.join(appsDir, metadata.name, arch),
src: '*',
dest: `${LINUX_INSTALL_DIR}/${metadata.name}`,
}],
postInstallScript: [`xdg-desktop-menu install ${LINUX_INSTALL_DIR}/${metadata.name}/${metadata.name}.desktop`],
preUninstallScript: [`xdg-desktop-menu uninstall ${metadata.name}.desktop`],
tempDir: path.join(appsDir, `tmp-rpm-build-${arch}`),
keepTemp: false,
verbose: false,
rpmDest: appsDir,
execOpts: { maxBuffer: 1024 * 1024 * 16 },
};
buildRpm(options, function(err) {
if (err) {
console.error(`Error generating rpm package: ${err}`);
}
done();
});
}
}
function getLinuxPackageArch(type, arch) {
let packArch;
switch (arch) {
case 'linux32':
packArch = 'i386';
break;
case 'linux64':
if (type === 'rpm') {
packArch = 'x86_64';
} else {
packArch = 'amd64';
}
break;
default:
console.error(`Package error, arch: ${arch}`);
process.exit(1);
break;
}
return packArch;
}
function releaseLinux(bits) {
return function() {
console.log(`Generating zip package for linux${bits}`);
var dirname = 'linux' + bits;
var pkg = require('./package.json');
var src = path.join(appsDir, pkg.name, dirname);
@ -383,8 +680,8 @@ function releaseLinux(bits) {
}
}
gulp.task('release-linux32', releaseLinux(32));
gulp.task('release-linux64', releaseLinux(64));
gulp.task('release-linux32', gulp.series(releaseLinux(32), post_build('linux32', appsDir), release_deb('linux32')));
gulp.task('release-linux64', gulp.series(releaseLinux(64), post_build('linux64', appsDir), release_deb('linux64'), release_rpm('linux64')));
// Create distributable .zip files in ./apps
gulp.task('release', gulp.series('apps', getPlatforms().map(function(v) { return 'release-' + v; })));

@ -3,7 +3,7 @@
var CONFIGURATOR = {
// all versions are specified and compared using semantic versioning http://semver.org/
'minfirmwareVersionAccepted': '5.0.0',
'maxFirmwareVersionAccepted': '6.0.0', // Condition is < (lt) so we accept all in 5.x branch
'maxFirmwareVersionAccepted': '7.0.0', // Condition is < (lt) so we accept all in 6.x branch
'connectionValid': false,
'connectionValidCliOnly': false,
'cliActive': false,

File diff suppressed because it is too large Load Diff

@ -596,10 +596,7 @@ var FC = {
return [
'NMEA',
'UBLOX',
'I2C-NAV',
'DJI NAZA',
'UBLOX7',
'MTK',
'MSP'
];
},

@ -32,6 +32,12 @@ const INPUT_STABILIZED_ROLL = 0,
INPUT_GIMBAL_PITCH = 12,
INPUT_GIMBAL_ROLL = 13,
INPUT_FEATURE_FLAPS = 14;
STABILIZED_ROLL_POSITIVE = 23;
STABILIZED_ROLL_NEGATIVE = 24;
STABILIZED_PITCH_POSITIVE = 25;
STABILIZED_PITCH_NEGATIVE = 26;
STABILIZED_YAW_POSITIVE = 27;
STABILIZED_YAW_NEGATIVE = 28;
const
PLATFORM_MULTIROTOR = 0,

@ -250,15 +250,16 @@ var Settings = (function () {
const oldValue = element.val();
//display names for the units
const unitDisplayDames = {
// Display names for the units
const unitDisplayNames = {
// Misc
'us' : "uS",
'cw' : 'cW',
'percent' : '%',
'cmss' : 'cm/s/s',
// Time
'us' : "uS",
'msec' : 'ms',
'msec-nc' : 'ms', // Milliseconds, but not converted.
'dsec' : 'ds',
'sec' : 's',
// Angles
@ -291,6 +292,47 @@ var Settings = (function () {
'nm' : 'NM'
}
// Hover full descriptions for the units
const unitExpandedNames = {
// Misc
'cw' : 'CentiWatts',
'percent' : 'Percent',
'cmss' : 'Centimetres per second, per second',
// Time
'us' : "Microseconds",
'msec' : 'Milliseconds',
'msec-nc' : 'Milliseconds',
'dsec' : 'Deciseconds',
'sec' : 'Seconds',
// Angles
'deg' : 'Degrees',
'decideg' : 'DeciDegrees',
'decideg-lrg' : 'DeciDegrees',
// Rotational speed
'degps' : 'Degrees per second',
'decadegps' : 'DecaDegrees per second',
// Temperature
'decidegc' : 'DeciDegrees Celsius',
'degc' : 'Degrees Celsius',
'degf' : 'Degrees Fahrenheit',
// Speed
'cms' : 'Centimetres per second',
'v-cms' : 'Centimetres per second',
'ms' : 'Metres per second',
'kmh' : 'Kilometres per hour',
'mph' : 'Miles per hour',
'hftmin' : 'Hundred feet per minute',
'fts' : 'Feet per second',
'kt' : 'Knots',
// Distance
'cm' : 'Centimetres',
'm' : 'Metres',
'km' : 'Kilometres',
'm-lrg' : 'Metres',
'ft' : 'Feet',
'mi' : 'Miles',
'nm' : 'Nautical Miles'
}
// Ensure we can do conversions
if (!inputUnit || !oldValue || !element) {
@ -326,6 +368,9 @@ var Settings = (function () {
'hftmin' : 50.8,
'fts' : 30.48
},
'msec-nc' : {
'msec-nc' : 1
},
'msec' : {
'sec' : 1000
},
@ -476,7 +521,7 @@ var Settings = (function () {
element.data('setting-multiplier', multiplier);
// Now wrap the input in a display that shows the unit
element.wrap(`<div data-unit="${unitDisplayDames[unitName]}" class="unit_wrapper unit"></div>`);
element.wrap(`<div data-unit="${unitDisplayNames[unitName]}" title="${unitExpandedNames[unitName]}" class="unit_wrapper unit"></div>`);
function toFahrenheit(decidegC) {
return (decidegC / 10) * 1.8 + 32;

@ -2163,13 +2163,13 @@ select {
text-align: center;
}
#modal-saving-defaults {
#modal-saving-defaults, #modal-resetting-pids {
/* width: 100%; */
height: 90px;
background: url(../images/loading-bars.svg) no-repeat center 100%;
}
#modal-saving-defaults div {
#modal-saving-defaults div, #modal-resetting-pids div {
text-align: center;
}

@ -301,6 +301,9 @@
<div id="modal-saving-defaults" class="is-hidden">
<div data-i18n="savingDefaults"></div>
</div>
<div id="modal-resetting-pids" class="is-hidden">
<div data-i18n="resettingPIDs"></div>
</div>
<div id="defaults-wrapper" style="display: none">
<div class="defaults-dialog__background"></div>
<div class="defaults-dialog__content">

@ -1,7 +1,7 @@
{
"manifest_version": 2,
"minimum_chrome_version": "38",
"version": "5.0.0",
"version": "6.0.0",
"author": "Several",
"name": "INAV - Configurator",
"short_name": "INAV",

1644
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
{
"name": "inav-configurator",
"description": "INAV Configurator",
"version": "5.0.0",
"version": "6.0.0",
"main": "main.html",
"default_locale": "en",
"scripts": {
@ -25,6 +25,7 @@
"dependencies": {
"archiver": "^2.0.3",
"bluebird": "3.4.1",
"command-exists": "^1.2.8",
"del": "^3.0.0",
"fs": "0.0.1-security",
"graceful-fs": "^4.2.0",
@ -44,7 +45,13 @@
"xml2js": "^0.4.19"
},
"devDependencies": {
"gulp-debian": "^0.1.9",
"nw-builder": "^3.5.7",
"semver": "6.3.0"
"rpm-builder": "^1.2.1",
"semver": "6.3.0",
"@quanle94/innosetup": "^6.0.2"
},
"optionalDependencies": {
"appdmg": "^0.6.2"
}
}

@ -125,6 +125,7 @@
.tab-onboard_logging dialog {
width: 40em;
border-radius: 5px;
height: fit-content;
}
.tab-onboard_logging dialog .buttons {

@ -17,7 +17,7 @@
</div>
<div class="number">
<input type="number" id="launchIdleDelay" data-unit="ms" data-setting="nav_fw_launch_idle_motor_delay" data-setting-multiplier="1" step="1" min="0" max="60000" />
<input type="number" id="launchIdleDelay" data-unit="msec" data-setting="nav_fw_launch_idle_motor_delay" data-setting-multiplier="1" step="1" min="0" max="60000" />
<label for="launchIdleDelay"><span data-i18n="configurationLaunchIdleDelay"></span></label>
<div for="launchIdleDelay" class="helpicon cf_tip" data-i18n_title="configurationLaunchIdleDelayHelp"></div>
</div>
@ -38,22 +38,22 @@
<div for="launchAccel" class="helpicon cf_tip" data-i18n_title="configurationLaunchAccelHelp"></div>
</div>
<div class="number">
<input type="number" id="launchDetectTime" data-unit="ms" data-setting="nav_fw_launch_detect_time" data-setting-multiplier="1" step="1" min="10" max="1000" />
<input type="number" id="launchDetectTime" data-unit="msec-nc" data-setting="nav_fw_launch_detect_time" data-setting-multiplier="1" step="1" min="10" max="1000" />
<label for="launchDetectTime"><span data-i18n="configurationLaunchDetectTime"></span></label>
<div for="launchDetectTime" class="helpicon cf_tip" data-i18n_title="configurationLaunchDetectTimeHelp"></div>
</div>
<div class="number">
<input type="number" id="launchMotorDelay" data-unit="ms" data-setting="nav_fw_launch_motor_delay" data-setting-multiplier="1" step="1" min="0" max="5000" />
<input type="number" id="launchMotorDelay" data-unit="msec-nc" data-setting="nav_fw_launch_motor_delay" data-setting-multiplier="1" step="1" min="0" max="5000" />
<label for="launchMotorDelay"><span data-i18n="configurationLaunchMotorDelay"></span></label>
<div for="launchMotorDelay" class="helpicon cf_tip" data-i18n_title="configurationLaunchMotorDelayHelp"></div>
</div>
<div class="number">
<input type="number" id="launchMinTime" data-unit="ms" data-setting="nav_fw_launch_min_time" data-setting-multiplier="1" step="1" min="0" max="60000" />
<input type="number" id="launchMinTime" data-unit="msec" data-setting="nav_fw_launch_min_time" data-setting-multiplier="1" step="1" min="0" max="60000" />
<label for="launchMinTime"><span data-i18n="configurationLaunchMinTime"></span></label>
<div for="launchMinTime" class="helpicon cf_tip" data-i18n_title="configurationLaunchMinTimeHelp"></div>
</div>
<div class="number">
<input type="number" id="launchSpinupTime" data-unit="ms" data-setting="nav_fw_launch_spinup_time" data-setting-multiplier="1" step="1" min="0" max="1000" />
<input type="number" id="launchSpinupTime" data-unit="msec-nc" data-setting="nav_fw_launch_spinup_time" data-setting-multiplier="1" step="1" min="0" max="1000" />
<label for="launchSpinupTime"><span data-i18n="configurationLaunchSpinupTime"></span></label>
<div for="launchSpinupTime" class="helpicon cf_tip" data-i18n_title="configurationLaunchSpinupTimeHelp"></div>
</div>
@ -68,7 +68,7 @@
<div for="launchClimbAngle" class="helpicon cf_tip" data-i18n_title="configurationLaunchClimbAngleHelp"></div>
</div>
<div class="number">
<input type="number" id="launchTimeout" data-unit="ms" data-setting="nav_fw_launch_timeout" data-setting-multiplier="1" step="1" min="0" max="60000" />
<input type="number" id="launchTimeout" data-unit="msec" data-setting="nav_fw_launch_timeout" data-setting-multiplier="1" step="1" min="0" max="60000" />
<label for="launchTimeout"><span data-i18n="configurationLaunchTimeout"></span></label>
<div for="launchTimeout" class="helpicon cf_tip" data-i18n_title="configurationLaunchTimeoutHelp"></div>
</div>
@ -78,7 +78,7 @@
<div for="launchMaxAltitude" class="helpicon cf_tip" data-i18n_title="configurationLaunchMaxAltitudeHelp"></div>
</div>
<div class="number">
<input type="number" id="launchEndTime" data-unit="ms" data-setting="nav_fw_launch_end_time" data-setting-multiplier="1" step="1" min="0" max="5000" />
<input type="number" id="launchEndTime" data-unit="msec" data-setting="nav_fw_launch_end_time" data-setting-multiplier="1" step="1" min="0" max="5000" />
<label for="launchEndTime"><span data-i18n="configurationLaunchEndTime"></span></label>
<div for="launchEndTime" class="helpicon cf_tip" data-i18n_title="configurationLaunchEndTimeHelp"></div>
</div>
@ -128,7 +128,7 @@
</div>
<div class="number">
<input id="pitchToThrottle" type="number" data-setting="nav_fw_pitch2thr" data-setting-multiplier="1" step="1" min="0" max="100" />
<input id="pitchToThrottle" type="number" data-unit="us" data-setting="nav_fw_pitch2thr" data-setting-multiplier="1" step="1" min="0" max="100" />
<label for="pitchToThrottle"><span data-i18n="pitchToThrottle"></span></label>
<div for="pitchToThrottle" class="helpicon cf_tip" data-i18n_title="pitchToThrottleHelp"></div>
</div>
@ -278,7 +278,7 @@
</div>
<div class="number">
<input id="brakingTimeout" type="number" data-unit="ms" data-setting="nav_mc_braking_timeout" data-setting-multiplier="1" step="1" min="100" max="5000" />
<input id="brakingTimeout" type="number" data-unit="msec" data-setting="nav_mc_braking_timeout" data-setting-multiplier="1" step="1" min="100" max="5000" />
<label for="brakingTimeout"><span data-i18n="brakingTimeout"></span></label>
<div for="brakingTimeout" class="helpicon cf_tip" data-i18n_title="brakingTimeoutTip"></div>
</div>
@ -290,7 +290,7 @@
</div>
<div class="number">
<input id="brakingBoostTimeout" type="number" data-unit="ms" data-setting="nav_mc_braking_boost_timeout" data-setting-multiplier="1" step="1" min="0" max="5000" />
<input id="brakingBoostTimeout" type="number" data-unit="msec" data-setting="nav_mc_braking_boost_timeout" data-setting-multiplier="1" step="1" min="0" max="5000" />
<label for="brakingBoostTimeout"><span data-i18n="brakingBoostTimeout"></span></label>
<div for="brakingBoostTimeout" class="helpicon cf_tip" data-i18n_title="brakingBoostTimeoutTip"></div>
</div>

@ -276,8 +276,13 @@ TABS.cli.initialize = function (callback) {
var out_string = textarea.val();
self.history.add(out_string.trim());
var outputArray = out_string.split("\n");
Promise.reduce(outputArray, sendLinesWithDelay(outputArray), 0);
if (out_string.trim().toLowerCase() == "cls") {
self.outputHistory = "";
$('.tab-cli .window .wrapper').empty();
} else {
var outputArray = out_string.split("\n");
Promise.reduce(outputArray, sendLinesWithDelay(outputArray), 0);
}
textarea.val('');
}

@ -226,8 +226,8 @@ TABS.configuration.initialize = function (callback, scrollPosition) {
// fill battery capacity
$('#battery_capacity').val(MISC.battery_capacity);
$('#battery_capacity_warning').val(MISC.battery_capacity_warning * 100 / MISC.battery_capacity);
$('#battery_capacity_critical').val(MISC.battery_capacity_critical * 100 / MISC.battery_capacity);
$('#battery_capacity_warning').val(Math.round(MISC.battery_capacity_warning * 100 / MISC.battery_capacity));
$('#battery_capacity_critical').val(Math.round(MISC.battery_capacity_critical * 100 / MISC.battery_capacity));
$('#battery_capacity_unit').val(MISC.battery_capacity_unit);
let $i2cSpeed = $('#i2c_speed'),

@ -130,6 +130,8 @@ TABS.mixer.initialize = function (callback, scrollPosition) {
switch (parseInt(servo.getInput())) {
case INPUT_STABILIZED_PITCH:
case STABILIZED_PITCH_POSITIVE:
case STABILIZED_PITCH_NEGATIVE:
case INPUT_RC_PITCH:
outputArea = getOutputImageArea(currentMixerPreset.imageOutputsNumbers, INPUT_STABILIZED_PITCH, surfaces.elevatorSet);
if (outputArea != null) {
@ -152,6 +154,8 @@ TABS.mixer.initialize = function (callback, scrollPosition) {
}
break;
case INPUT_STABILIZED_ROLL:
case STABILIZED_ROLL_POSITIVE:
case STABILIZED_ROLL_NEGATIVE:
case INPUT_RC_ROLL:
outputArea = getOutputImageArea(currentMixerPreset.imageOutputsNumbers, INPUT_STABILIZED_ROLL, surfaces.aileronSet);
if (outputArea != null) {
@ -174,6 +178,8 @@ TABS.mixer.initialize = function (callback, scrollPosition) {
}
break;
case INPUT_STABILIZED_YAW:
case STABILIZED_YAW_POSITIVE:
case STABILIZED_YAW_NEGATIVE:
case INPUT_RC_YAW:
outputArea = getOutputImageArea(currentMixerPreset.imageOutputsNumbers, INPUT_STABILIZED_YAW, surfaces.rudderSet);
if (outputArea != null) {

@ -22,6 +22,10 @@ TABS.onboard_logging.initialize = function (callback) {
"BLACKBOX_FEATURE_RC_DATA",
"BLACKBOX_FEATURE_RC_COMMAND",
"BLACKBOX_FEATURE_MOTORS",
"BLACKBOX_FEATURE_GYRO_RAW",
"BLACKBOX_FEATURE_GYRO_PEAKS_ROLL",
"BLACKBOX_FEATURE_GYRO_PEAKS_PITCH",
"BLACKBOX_FEATURE_GYRO_PEAKS_YAW",
];
if (GUI.active_tab != 'onboard_logging') {

@ -2791,6 +2791,7 @@ OSD.GUI.updateAll = function() {
layouts.on('change', function() {
OSD.updateSelectedLayout(parseInt(layouts.val()));
OSD.GUI.updateFields();
OSD.GUI.updateDjiView($('#djiUnsupportedElements').find('input').is(':checked'));
OSD.GUI.updatePreviews();
});
} else {

@ -16,7 +16,6 @@
</div>
<!--list of generated features goes here-->
<div id="esc-protocols">
<div id="esc-protocol-warning" class="warning-box"></div>
<div class="select">
<select name="esc-protocol" id="esc-protocol" data-setting-placeholder="motor_pwm_protocol"></select>
<label for="esc-protocol">
@ -24,13 +23,6 @@
</label>
<div for="esc-protocol" class="helpicon cf_tip" data-i18n_title="escProtocolHelp"></div>
</div>
<div class="select hide-for-shot">
<select name="esc-rate" id="esc-rate" data-setting-placeholder="motor_pwm_rate"></select>
<label for="esc-rate">
<span data-i18n="escRefreshRate"></span>
</label>
<div for="esc-rate" class="helpicon cf_tip" data-i18n_title="escRefreshRatelHelp"></div>
</div>
<div class="clear-both"></div>
</div>

@ -99,24 +99,7 @@ TABS.outputs.initialize = function (callback) {
$motorStopWarningBox = $("#motor-stop-warning"),
$reversibleMotorBox = $(".for-reversible-motors");
function buildMotorRates() {
var protocolData = escProtocols[ADVANCED_CONFIG.motorPwmProtocol];
$escRate.find('option').remove();
for (var i in protocolData.rates) {
if (protocolData.rates.hasOwnProperty(i)) {
$escRate.append('<option value="' + i + '">' + protocolData.rates[i] + '</option>');
}
}
/*
* If rate from FC is not on the list, add a new entry
*/
if ($escRate.find('[value="' + ADVANCED_CONFIG.motorPwmRate + '"]').length == 0) {
$escRate.append('<option value="' + ADVANCED_CONFIG.motorPwmRate + '">' + ADVANCED_CONFIG.motorPwmRate + 'Hz</option>');
}
function handleIdleMessageBox() {
$idleInfoBox.hide();
if (ADVANCED_CONFIG.motorPwmProtocol >= 5) {
$('.hide-for-shot').hide();
@ -133,18 +116,10 @@ TABS.outputs.initialize = function (callback) {
$idleInfoBox.show();
}
}
if (protocolData.message !== null) {
$('#esc-protocol-warning').html(chrome.i18n.getMessage(protocolData.message));
$('#esc-protocol-warning').show();
} else {
$('#esc-protocol-warning').hide();
}
}
let $escProtocol = $('#esc-protocol');
let $escRate = $('#esc-rate');
for (i in escProtocols) {
if (escProtocols.hasOwnProperty(i)) {
var protocolData = escProtocols[i];
@ -153,21 +128,13 @@ TABS.outputs.initialize = function (callback) {
}
$escProtocol.val(ADVANCED_CONFIG.motorPwmProtocol);
buildMotorRates();
$escRate.val(ADVANCED_CONFIG.motorPwmRate);
$escProtocol.change(function () {
ADVANCED_CONFIG.motorPwmProtocol = $(this).val();
buildMotorRates();
ADVANCED_CONFIG.motorPwmRate = escProtocols[ADVANCED_CONFIG.motorPwmProtocol].defaultRate;
$escRate.val(ADVANCED_CONFIG.motorPwmRate);
});
$escRate.change(function () {
ADVANCED_CONFIG.motorPwmRate = $(this).val();
});
$idlePercent.change(buildMotorRates);
$idlePercent.change(handleIdleMessageBox);
handleIdleMessageBox();
$("#esc-protocols").show();

@ -538,7 +538,7 @@
<tr>
<th data-i18n="pidTuning_FW_TPATimeConstant"></th>
<td>
<div class="pidTuning_number"><input id="tpaTimeConstant" type="number" class="rate-tpa_input" data-setting="fw_tpa_time_constant" data-unit="ms" /></div>
<div class="pidTuning_number"><input id="tpaTimeConstant" type="number" class="rate-tpa_input" data-setting="fw_tpa_time_constant" data-unit="msec" /></div>
<div for="tpaTimeConstant" class="helpicon cf_tip" data-i18n_title="pidTuning_FW_TPATimeConstantHelp"></div>
</td>
</tr>

@ -93,6 +93,7 @@ TABS.pid_tuning.initialize = function (callback) {
RC_tuning.manual_pitch_rate = $('#rate-manual-pitch').val();
RC_tuning.manual_yaw_rate = $('#rate-manual-yaw').val();
}
function hideUnusedPids(sensors_detected) {
$('.tab-pid_tuning table.pid_tuning').hide();
$('#pid_main').show();
@ -113,6 +114,7 @@ TABS.pid_tuning.initialize = function (callback) {
$('#pid_baro').show();
}
}
function process_html() {
// translate to user-selected language
localize();
@ -135,16 +137,24 @@ TABS.pid_tuning.initialize = function (callback) {
});
$('#resetPIDs').on('click', function() {
if (confirm(chrome.i18n.getMessage('confirm_reset_pid'))) {
MSP.send_message(MSPCodes.MSP_SET_RESET_CURR_PID, false, false, false);
updateActivatedTab();
resettingPIDsModal = new jBox('Modal', {
width: 400,
height: 100,
animation: false,
closeOnClick: false,
closeOnEsc: false,
content: $('#modal-resetting-pids')
}).open();
helper.defaultsDialog.resetSettings();
}
});
$('#resetDefaults').on('click', function() {
if (confirm(chrome.i18n.getMessage('confirm_select_defaults'))) {
helper.features.reset();
helper.features.fromUI($('.tab-pid_tuning'));
mspHelper.setSetting("applied_defaults", 0, function() {
mspHelper.saveToEeprom( function () {
GUI.log(chrome.i18n.getMessage('configurationEepromSaved'));

@ -178,11 +178,6 @@ TABS.receiver.initialize = function (callback) {
// set current value
$rcMap.val(str);
/*
* Send tracking event so we can know if users are using different mappings than EATR
*/
googleAnalytics.sendEvent('Setting', 'RcMappingRead', str);
// validation / filter
var last_valid = str;
@ -297,6 +292,8 @@ TABS.receiver.initialize = function (callback) {
RC_MAP[i] = strBuffer.indexOf(FC.getRcMapLetters()[i]);
}
googleAnalytics.sendEvent('Setting', 'RcProtocol', $('#receiver_type option:selected').text() + ":" + $('#serialrx_provider option:selected').text());
// catch rssi aux
MISC.rssi_channel = parseInt($('select[name="rssi_channel"]').val());

Loading…
Cancel
Save