Merge branch 'master' into advanced-tuning-tab
commit
01569e7df8
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 76.5 76.3" style="enable-background:new 0 0 76.5 76.3;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;stroke:#37A8DB;stroke-width:5;stroke-miterlimit:10;}
|
||||
.st1{fill:#37A8DB;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<circle class="st0" cx="39.4" cy="38.4" r="33.3"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M29.5,25.4l-4.9-4.9h-2.5v2.5l4.9,4.9L29.5,25.4z M32,18h2.5v4.9H32V18L32,18z M41.9,30.3h4.9v2.5h-4.9V30.3z
|
||||
M44.3,22.9v-2.5h-2.5l-4.9,5l2.5,2.5L44.3,22.9z M19.6,30.3h4.9v2.5h-4.9V30.3z M32,40.2h2.5v4.9H32V40.2L32,40.2z M22.1,40.2
|
||||
v2.5h2.5l4.9-4.9l-2.5-2.5L22.1,40.2z M58.6,52L34.1,27.5c-0.7-0.7-1.9-0.7-2.6,0l-2.3,2.3c-0.7,0.7-0.7,1.9,0,2.6L53.7,57
|
||||
c0.7,0.7,1.9,0.7,2.6,0l2.3-2.3C59.4,53.9,59.4,52.7,58.6,52z M38.2,39l-7.4-7.4l2.5-2.5l7.4,7.4L38.2,39z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 76.5 76.3" style="enable-background:new 0 0 76.5 76.3;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;stroke:#ADADAD;stroke-width:5;stroke-miterlimit:10;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
.st2{fill:#37A8DB;}
|
||||
.st3{fill:none;stroke:#606060;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<circle class="st0" cx="39.4" cy="38.4" r="33.3"/>
|
||||
<g>
|
||||
<circle class="st1" cx="15.1" cy="15.9" r="11.4"/>
|
||||
<circle class="st2" cx="15.1" cy="15.9" r="9.3"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M18.9,14.6l-0.2-0.4c0.6-1.4,0.6-1.4,0.5-1.5l-0.8-0.8l-0.1-0.1h-0.1c0,0-0.2,0-1.4,0.5l-0.4-0.2
|
||||
c-0.6-1.4-0.6-1.4-0.8-1.4h-1.1c-0.2,0-0.2,0-0.8,1.4l-0.4,0.2c-0.8-0.3-1.3-0.5-1.4-0.5h-0.1l-0.8,0.8
|
||||
c-0.1,0.1-0.2,0.2,0.5,1.5l-0.2,0.4c-1.4,0.6-1.4,0.6-1.4,0.8v1.1c0,0.2,0,0.2,1.4,0.7l0.2,0.4c-0.6,1.4-0.6,1.4-0.5,1.5
|
||||
l0.8,0.8l0.1,0.1h0.1c0,0,0.2,0,1.4-0.5l0.4,0.2c0.6,1.4,0.6,1.4,0.8,1.4h1.1c0.2,0,0.2,0,0.8-1.4l0.4-0.2
|
||||
c0.8,0.3,1.3,0.5,1.4,0.5h0.1l0.8-0.8c0.1-0.1,0.2-0.2-0.5-1.5l0.2-0.4c1.4-0.6,1.4-0.6,1.4-0.8v-1.1
|
||||
C20.3,15.2,20.3,15.1,18.9,14.6z M15.1,17.7c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8s1.8,0.8,1.8,1.8
|
||||
C16.9,16.9,16.1,17.7,15.1,17.7z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path class="st3" d="M62.1,45.7v-5.9l-19.2-9.2c0.1-2.9,0.2-6.6,0.2-7.6c0-4.1-3.3-5.5-3.6-5.6l0,0l0,0c-0.3,0.2-3.6,1.5-3.6,5.6
|
||||
c0,0.9,0.1,4.6,0.2,7.6L16,39.8l0,5.9l20.9-4.3c0.2,3.9,0.1,5.2,0.3,8.4l-4.6,3.2v2.7l5.2-1.6c0.1,2.1,1.3,3.4,1.3,3.4h0.3h0h0.3
|
||||
c0,0,1.2-1.2,1.3-3.4l5.2,1.6v-2.7l-4.6-3.2c0.2-3.3,0.1-4.5,0.3-8.4L62.1,45.7z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="-61 62.7 76.5 76.3" style="enable-background:new -61 62.7 76.5 76.3;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;stroke:#ADADAD;stroke-width:5;stroke-miterlimit:10;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
.st2{fill:#37A8DB;}
|
||||
.st3{fill:none;stroke:#606060;stroke-miterlimit:10;}
|
||||
.st4{fill:#606060;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<circle class="st0" cx="-21.6" cy="101.1" r="33.3"/>
|
||||
<g>
|
||||
<circle class="st1" cx="-45.9" cy="78.6" r="11.4"/>
|
||||
<circle class="st2" cx="-45.9" cy="78.6" r="9.3"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M-42.1,77.3l-0.2-0.4c0.6-1.4,0.6-1.4,0.5-1.5l-0.8-0.8l-0.1-0.1h-0.1c0,0-0.2,0-1.4,0.5l-0.4-0.2
|
||||
c-0.6-1.4-0.6-1.4-0.8-1.4h-1.1c-0.2,0-0.2,0-0.8,1.4l-0.4,0.2c-0.8-0.3-1.3-0.5-1.4-0.5h-0.1l-0.8,0.8
|
||||
c-0.1,0.1-0.2,0.2,0.5,1.5l-0.2,0.4c-1.4,0.6-1.4,0.6-1.4,0.8v1.1c0,0.2,0,0.2,1.4,0.7l0.2,0.4c-0.6,1.4-0.6,1.4-0.5,1.5
|
||||
l0.8,0.8l0.1,0.1h0.1c0,0,0.2,0,1.4-0.5l0.4,0.2c0.6,1.4,0.6,1.4,0.8,1.4h1.1c0.2,0,0.2,0,0.8-1.4l0.4-0.2
|
||||
c0.8,0.3,1.3,0.5,1.4,0.5h0.1l0.8-0.8c0.1-0.1,0.2-0.2-0.5-1.5l0.2-0.4c1.4-0.6,1.4-0.6,1.4-0.8V78
|
||||
C-40.7,77.9-40.7,77.8-42.1,77.3z M-45.9,80.4c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8s1.8,0.8,1.8,1.8S-44.9,80.4-45.9,80.4z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st3" d="M-9.4,110.7c-0.1,0-0.1-0.1-0.2-0.1c-1.6-0.7-2.8-1.3-4.2-3.6s-2.1-3.4-2.2-5.1c0.1-1.6,0.9-2.7,2.2-5
|
||||
s2.6-2.9,4.2-3.6c0.1,0,0.1-0.1,0.2-0.1c0.7-0.3,1.2-1.1,1.2-1.9c0-1.2-0.9-2.1-2.1-2.1c-0.9,0-1.7,0.6-2,1.4
|
||||
c-1.3,2.1-2.3,3-4.2,4.5s-4,2.4-5.1,2.4h-0.2c-1.1,0-3.2-0.9-5.1-2.4c-1.8-1.5-2.9-2.3-4.2-4.5c-0.3-0.8-1.1-1.4-2-1.4
|
||||
c-1.2,0-2.1,0.9-2.1,2.1c0,0.8,0.5,1.6,1.2,1.9c0.1,0,0.1,0.1,0.2,0.1c1.7,0.7,2.9,1.3,4.3,3.6c1.4,2.3,2.1,3.4,2.2,5.1
|
||||
c-0.1,1.6-0.9,2.7-2.2,5c-1.4,2.3-2.6,2.9-4.2,3.6c-0.1,0-0.1,0.1-0.2,0.1c-0.7,0.3-1.2,1.1-1.2,1.9c0,1.2,0.9,2.1,2.1,2.1
|
||||
c0.9,0,1.7-0.6,2-1.4c1.3-2.1,2.3-3,4.2-4.5c1.9-1.5,4-2.4,5.1-2.4h0.2c1.1,0,3.2,0.9,5.1,2.4c1.8,1.5,2.9,2.3,4.2,4.5
|
||||
c0.3,0.8,1.1,1.4,2,1.4c1.2,0,2.1-0.9,2.1-2.1C-8.2,111.8-8.7,111-9.4,110.7z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path class="st4" d="M-32,96c-0.3,0.1-0.7,0.1-1,0.1c-2.7,0-4.8-2.2-4.8-4.8s2.2-4.8,4.8-4.8s4.8,2.2,4.8,4.8c0,0.2,0,0.4-0.1,0.7
|
||||
l0.9,0.6c0.1-0.4,0.1-0.8,0.1-1.3c0-3.2-2.6-5.8-5.8-5.8s-5.8,2.6-5.8,5.8c0,3.2,2.6,5.8,5.8,5.8c0.6,0,1.1-0.1,1.7-0.2L-32,96z"
|
||||
/>
|
||||
<path class="st4" d="M-10.2,85.5c-3.2,0-5.8,2.6-5.8,5.8c0,0.5,0.1,0.9,0.2,1.3l0.9-0.6c0-0.2-0.1-0.5-0.1-0.7
|
||||
c0-2.7,2.2-4.8,4.8-4.8s4.8,2.2,4.8,4.8c0,2.6-2.2,4.8-4.8,4.8c-0.3,0-0.6,0-1-0.1l-0.6,0.9c0.5,0.1,1,0.2,1.6,0.2
|
||||
c3.2,0,5.8-2.6,5.8-5.8C-4.4,88.1-7,85.5-10.2,85.5z"/>
|
||||
<path class="st4" d="M-32,108c-0.3-0.1-0.7-0.1-1-0.1c-2.7,0-4.8,2.2-4.8,4.8s2.2,4.8,4.8,4.8s4.8-2.2,4.8-4.8
|
||||
c0-0.2,0-0.4-0.1-0.7l0.9-0.6c0.1,0.4,0.1,0.8,0.1,1.3c0,3.2-2.6,5.8-5.8,5.8s-5.8-2.6-5.8-5.8s2.6-5.8,5.8-5.8
|
||||
c0.6,0,1.1,0.1,1.7,0.2L-32,108z"/>
|
||||
<path class="st4" d="M-10.2,118.5c-3.2,0-5.8-2.6-5.8-5.8c0-0.5,0.1-0.9,0.2-1.3l0.9,0.6c0,0.2-0.1,0.5-0.1,0.7
|
||||
c0,2.7,2.2,4.8,4.8,4.8s4.8-2.2,4.8-4.8s-2.2-4.8-4.8-4.8c-0.3,0-0.6,0-1,0.1l-0.6-0.9c0.5-0.1,1-0.2,1.6-0.2
|
||||
c3.2,0,5.8,2.6,5.8,5.8C-4.4,115.9-7,118.5-10.2,118.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 76.5 76.3" style="enable-background:new 0 0 76.5 76.3;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;stroke:#ADADAD;stroke-width:5;stroke-miterlimit:10;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
.st2{fill:#37A8DB;}
|
||||
.st3{fill:none;stroke:#606060;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<circle class="st0" cx="39.4" cy="38.4" r="33.3"/>
|
||||
<g>
|
||||
<circle class="st1" cx="15.1" cy="15.9" r="11.4"/>
|
||||
<circle class="st2" cx="15.1" cy="15.9" r="9.3"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st1" d="M18.9,14.6l-0.2-0.4c0.6-1.4,0.6-1.4,0.5-1.5l-0.8-0.8l-0.1-0.1h-0.1c0,0-0.2,0-1.4,0.5l-0.4-0.2
|
||||
c-0.6-1.4-0.6-1.4-0.8-1.4h-1.1c-0.2,0-0.2,0-0.8,1.4l-0.4,0.2c-0.8-0.3-1.3-0.5-1.4-0.5h-0.1l-0.8,0.8
|
||||
c-0.1,0.1-0.2,0.2,0.5,1.5l-0.2,0.4c-1.4,0.6-1.4,0.6-1.4,0.8v1.1c0,0.2,0,0.2,1.4,0.7l0.2,0.4c-0.6,1.4-0.6,1.4-0.5,1.5
|
||||
l0.8,0.8l0.1,0.1h0.1c0,0,0.2,0,1.4-0.5l0.4,0.2c0.6,1.4,0.6,1.4,0.8,1.4h1.1c0.2,0,0.2,0,0.8-1.4l0.4-0.2
|
||||
c0.8,0.3,1.3,0.5,1.4,0.5h0.1l0.8-0.8c0.1-0.1,0.2-0.2-0.5-1.5l0.2-0.4c1.4-0.6,1.4-0.6,1.4-0.8v-1.1
|
||||
C20.3,15.2,20.3,15.1,18.9,14.6z M15.1,17.7c-1,0-1.8-0.8-1.8-1.8s0.8-1.8,1.8-1.8s1.8,0.8,1.8,1.8S16.1,17.7,15.1,17.7z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st3" d="M42.1,26c-0.3-0.1-0.5-0.3-0.7-0.3c-0.3,0-1.6,0-2.1,0c-0.1,0-0.2,0-0.2,0c-0.5,0-1.8,0-2.1,0
|
||||
c-0.2,0-0.4,0.1-0.7,0.3C35.6,26.3,16,37.8,16,37.8v8.4l0.6-0.1v-1.6l18.2-3.3l0.4-0.5v-1.5h3v1.3h2.1v-1.3h3v1.5l0.4,0.5
|
||||
l18.2,3.3v1.6l0.6,0.1v-8.4C62.4,37.8,42.8,26.3,42.1,26z"/>
|
||||
<path class="st3" d="M39.7,40.9c0,0.5-0.2,0.7-0.5,0.9c-0.2-0.1-0.5-0.4-0.5-0.9v-0.2h1.1V40.9z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
@ -1,817 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// code below is highly experimental, although it runs fine on latest firmware
|
||||
// the data inside nested objects needs to be verified if deep copy works properly
|
||||
function configuration_backup(callback) {
|
||||
var activeProfile = null,
|
||||
profilesN = 3;
|
||||
|
||||
var configuration = {
|
||||
'generatedBy': chrome.runtime.getManifest().version,
|
||||
'apiVersion': CONFIG.apiVersion,
|
||||
'profiles': [],
|
||||
};
|
||||
|
||||
var profileSpecificData = [
|
||||
MSPCodes.MSP_PID,
|
||||
MSPCodes.MSP_RC_TUNING,
|
||||
MSPCodes.MSP_ACC_TRIM,
|
||||
MSPCodes.MSP_SERVO_CONFIGURATIONS,
|
||||
MSPCodes.MSP_MODE_RANGES,
|
||||
MSPCodes.MSP_ADJUSTMENT_RANGES
|
||||
];
|
||||
|
||||
function update_profile_specific_data_list() {
|
||||
if (semver.lt(CONFIG.apiVersion, "1.12.0")) {
|
||||
profileSpecificData.push(MSPCodes.MSP_CHANNEL_FORWARDING);
|
||||
} else {
|
||||
profileSpecificData.push(MSPCodes.MSP_SERVO_MIX_RULES);
|
||||
}
|
||||
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
|
||||
profileSpecificData.push(MSPCodes.MSP_RC_DEADBAND);
|
||||
}
|
||||
}
|
||||
|
||||
update_profile_specific_data_list();
|
||||
|
||||
MSP.send_message(MSPCodes.MSP_STATUS, false, false, function () {
|
||||
activeProfile = CONFIG.profile;
|
||||
select_profile();
|
||||
});
|
||||
|
||||
function select_profile() {
|
||||
if (activeProfile > 0) {
|
||||
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [0], false, fetch_specific_data);
|
||||
} else {
|
||||
fetch_specific_data();
|
||||
}
|
||||
}
|
||||
|
||||
function fetch_specific_data() {
|
||||
var fetchingProfile = 0,
|
||||
codeKey = 0;
|
||||
|
||||
function fetch_specific_data_item() {
|
||||
if (fetchingProfile < profilesN) {
|
||||
MSP.send_message(profileSpecificData[codeKey], false, false, function () {
|
||||
codeKey++;
|
||||
|
||||
if (codeKey < profileSpecificData.length) {
|
||||
fetch_specific_data_item();
|
||||
} else {
|
||||
configuration.profiles.push({
|
||||
'PID': jQuery.extend(true, {}, PID),
|
||||
'PIDs': jQuery.extend(true, [], PIDs),
|
||||
'RC': jQuery.extend(true, {}, RC_tuning),
|
||||
'AccTrim': jQuery.extend(true, [], CONFIG.accelerometerTrims),
|
||||
'ServoConfig': jQuery.extend(true, [], SERVO_CONFIG),
|
||||
'ServoRules': jQuery.extend(true, [], SERVO_RULES),
|
||||
'ModeRanges': jQuery.extend(true, [], MODE_RANGES),
|
||||
'AdjustmentRanges': jQuery.extend(true, [], ADJUSTMENT_RANGES)
|
||||
});
|
||||
|
||||
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
|
||||
configuration.profiles[fetchingProfile].RCdeadband = jQuery.extend(true, {}, RC_deadband);
|
||||
}
|
||||
codeKey = 0;
|
||||
fetchingProfile++;
|
||||
|
||||
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [fetchingProfile], false, fetch_specific_data_item);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [activeProfile], false, fetch_unique_data);
|
||||
}
|
||||
}
|
||||
|
||||
// start fetching
|
||||
fetch_specific_data_item();
|
||||
}
|
||||
|
||||
var uniqueData = [
|
||||
MSPCodes.MSP_MISC,
|
||||
MSPCodes.MSP_RX_MAP,
|
||||
MSPCodes.MSP_BF_CONFIG,
|
||||
MSPCodes.MSP_CF_SERIAL_CONFIG,
|
||||
MSPCodes.MSP_LED_STRIP_CONFIG,
|
||||
MSPCodes.MSP_LED_COLORS
|
||||
];
|
||||
|
||||
function update_unique_data_list() {
|
||||
if (semver.gte(CONFIG.apiVersion, "1.8.0")) {
|
||||
uniqueData.push(MSPCodes.MSP_LOOP_TIME);
|
||||
uniqueData.push(MSPCodes.MSP_ARMING_CONFIG);
|
||||
}
|
||||
if (semver.gte(CONFIG.apiVersion, "1.14.0")) {
|
||||
uniqueData.push(MSPCodes.MSP_3D);
|
||||
}
|
||||
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
|
||||
uniqueData.push(MSPCodes.MSP_SENSOR_ALIGNMENT);
|
||||
uniqueData.push(MSPCodes.MSP_RX_CONFIG);
|
||||
uniqueData.push(MSPCodes.MSP_FAILSAFE_CONFIG);
|
||||
uniqueData.push(MSPCodes.MSP_RXFAIL_CONFIG);
|
||||
}
|
||||
if (semver.gte(CONFIG.apiVersion, "1.19.0")) {
|
||||
uniqueData.push(MSPCodes.MSP_LED_STRIP_MODECOLOR);
|
||||
}
|
||||
}
|
||||
|
||||
update_unique_data_list();
|
||||
|
||||
function fetch_unique_data() {
|
||||
var codeKey = 0;
|
||||
|
||||
function fetch_unique_data_item() {
|
||||
if (codeKey < uniqueData.length) {
|
||||
MSP.send_message(uniqueData[codeKey], false, false, function () {
|
||||
codeKey++;
|
||||
fetch_unique_data_item();
|
||||
});
|
||||
} else {
|
||||
configuration.MISC = jQuery.extend(true, {}, MISC);
|
||||
configuration.RCMAP = jQuery.extend(true, [], RC_MAP);
|
||||
configuration.BF_CONFIG = jQuery.extend(true, {}, BF_CONFIG);
|
||||
configuration.SERIAL_CONFIG = jQuery.extend(true, {}, SERIAL_CONFIG);
|
||||
configuration.LED_STRIP = jQuery.extend(true, [], LED_STRIP);
|
||||
configuration.LED_COLORS = jQuery.extend(true, [], LED_COLORS);
|
||||
|
||||
if (semver.gte(CONFIG.apiVersion, "1.19.0")) {
|
||||
configuration.LED_MODE_COLORS = jQuery.extend(true, [], LED_MODE_COLORS);
|
||||
}
|
||||
if (semver.gte(CONFIG.apiVersion, "1.8.0")) {
|
||||
configuration.FC_CONFIG = jQuery.extend(true, {}, FC_CONFIG);
|
||||
configuration.ARMING_CONFIG = jQuery.extend(true, {}, ARMING_CONFIG);
|
||||
}
|
||||
if (semver.gte(CONFIG.apiVersion, "1.14.0")) {
|
||||
configuration._3D = jQuery.extend(true, {}, _3D);
|
||||
}
|
||||
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
|
||||
configuration.SENSOR_ALIGNMENT = jQuery.extend(true, {}, SENSOR_ALIGNMENT);
|
||||
configuration.RX_CONFIG = jQuery.extend(true, {}, RX_CONFIG);
|
||||
configuration.FAILSAFE_CONFIG = jQuery.extend(true, {}, FAILSAFE_CONFIG);
|
||||
configuration.RXFAIL_CONFIG = jQuery.extend(true, [], RXFAIL_CONFIG);
|
||||
}
|
||||
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
// start fetching
|
||||
fetch_unique_data_item();
|
||||
}
|
||||
|
||||
function save() {
|
||||
var chosenFileEntry = null;
|
||||
|
||||
var accepts = [{
|
||||
extensions: ['txt']
|
||||
}];
|
||||
|
||||
// generate timestamp for the backup file
|
||||
var d = new Date(),
|
||||
now = (d.getMonth() + 1) + '.' + d.getDate() + '.' + d.getFullYear() + '.' + d.getHours() + '.' + d.getMinutes();
|
||||
|
||||
// create or load the file
|
||||
chrome.fileSystem.chooseEntry({type: 'saveFile', suggestedName: 'inav_backup_' + now, accepts: accepts}, function (fileEntry) {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(chrome.runtime.lastError.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fileEntry) {
|
||||
console.log('No file selected, backup aborted.');
|
||||
return;
|
||||
}
|
||||
|
||||
chosenFileEntry = fileEntry;
|
||||
|
||||
// echo/console log path specified
|
||||
chrome.fileSystem.getDisplayPath(chosenFileEntry, function (path) {
|
||||
console.log('Backup file path: ' + path);
|
||||
});
|
||||
|
||||
// change file entry from read only to read/write
|
||||
chrome.fileSystem.getWritableEntry(chosenFileEntry, function (fileEntryWritable) {
|
||||
// check if file is writable
|
||||
chrome.fileSystem.isWritableEntry(fileEntryWritable, function (isWritable) {
|
||||
if (isWritable) {
|
||||
chosenFileEntry = fileEntryWritable;
|
||||
|
||||
// crunch the config object
|
||||
var serialized_config_object = JSON.stringify(configuration);
|
||||
var blob = new Blob([serialized_config_object], {type: 'text/plain'}); // first parameter for Blob needs to be an array
|
||||
|
||||
chosenFileEntry.createWriter(function (writer) {
|
||||
writer.onerror = function (e) {
|
||||
console.error(e);
|
||||
};
|
||||
|
||||
var truncated = false;
|
||||
writer.onwriteend = function () {
|
||||
if (!truncated) {
|
||||
// onwriteend will be fired again when truncation is finished
|
||||
truncated = true;
|
||||
writer.truncate(blob.size);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Write SUCCESSFUL');
|
||||
if (callback) callback();
|
||||
};
|
||||
|
||||
writer.write(blob);
|
||||
}, function (e) {
|
||||
console.error(e);
|
||||
});
|
||||
} else {
|
||||
// Something went wrong or file is set to read only and cannot be changed
|
||||
console.log('File appears to be read only, sorry.');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function configuration_restore(callback) {
|
||||
var chosenFileEntry = null;
|
||||
|
||||
var accepts = [{
|
||||
extensions: ['txt']
|
||||
}];
|
||||
|
||||
// load up the file
|
||||
chrome.fileSystem.chooseEntry({type: 'openFile', accepts: accepts}, function (fileEntry) {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error(chrome.runtime.lastError.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fileEntry) {
|
||||
console.log('No file selected, restore aborted.');
|
||||
return;
|
||||
}
|
||||
|
||||
chosenFileEntry = fileEntry;
|
||||
|
||||
// echo/console log path specified
|
||||
chrome.fileSystem.getDisplayPath(chosenFileEntry, function (path) {
|
||||
console.log('Restore file path: ' + path);
|
||||
});
|
||||
|
||||
// read contents into variable
|
||||
chosenFileEntry.file(function (file) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onprogress = function (e) {
|
||||
if (e.total > 1048576) { // 1 MB
|
||||
// dont allow reading files bigger then 1 MB
|
||||
console.log('File limit (1 MB) exceeded, aborting');
|
||||
reader.abort();
|
||||
}
|
||||
};
|
||||
|
||||
reader.onloadend = function (e) {
|
||||
if (e.total != 0 && e.total == e.loaded) {
|
||||
console.log('Read SUCCESSFUL');
|
||||
|
||||
try { // check if string provided is a valid JSON
|
||||
var configuration = JSON.parse(e.target.result);
|
||||
} catch (e) {
|
||||
// data provided != valid json object
|
||||
console.log('Data provided != valid JSON string, restore aborted.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// validate
|
||||
if (typeof configuration.generatedBy !== 'undefined' && compareVersions(configuration.generatedBy, CONFIGURATOR.backupFileMinVersionAccepted)) {
|
||||
|
||||
if (!migrate(configuration)) {
|
||||
GUI.log(chrome.i18n.getMessage('backupFileUnmigratable'));
|
||||
return;
|
||||
}
|
||||
|
||||
configuration_upload(configuration, callback);
|
||||
|
||||
} else {
|
||||
GUI.log(chrome.i18n.getMessage('backupFileIncompatible'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
});
|
||||
});
|
||||
|
||||
function compareVersions(generated, required) {
|
||||
if (generated == undefined) {
|
||||
return false;
|
||||
}
|
||||
return semver.gte(generated, required);
|
||||
}
|
||||
|
||||
|
||||
function migrate(configuration) {
|
||||
var appliedMigrationsCount = 0;
|
||||
var migratedVersion = configuration.generatedBy;
|
||||
GUI.log(chrome.i18n.getMessage('configMigrationFrom', [migratedVersion]));
|
||||
|
||||
if (!compareVersions(migratedVersion, '0.59.1')) {
|
||||
|
||||
// variable was renamed
|
||||
configuration.MISC.rssi_channel = configuration.MISC.rssi_aux_channel;
|
||||
configuration.MISC.rssi_aux_channel = undefined;
|
||||
|
||||
migratedVersion = '0.59.1';
|
||||
GUI.log(chrome.i18n.getMessage('configMigratedTo', [migratedVersion]));
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (!compareVersions(migratedVersion, '0.60.1')) {
|
||||
|
||||
// LED_STRIP support was added.
|
||||
if (!configuration.LED_STRIP) {
|
||||
configuration.LED_STRIP = [];
|
||||
}
|
||||
|
||||
migratedVersion = '0.60.1';
|
||||
GUI.log(chrome.i18n.getMessage('configMigratedTo', [migratedVersion]));
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (!compareVersions(migratedVersion, '0.61.0')) {
|
||||
|
||||
// Changing PID controller via UI was added.
|
||||
if (!configuration.PIDs && configuration.PID) {
|
||||
configuration.PIDs = configuration.PID;
|
||||
}
|
||||
|
||||
migratedVersion = '0.61.0';
|
||||
GUI.log(chrome.i18n.getMessage('configMigratedTo', [migratedVersion]));
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (!compareVersions(migratedVersion, '0.63.0')) {
|
||||
|
||||
// LED Strip was saved as object instead of array.
|
||||
if (typeof(configuration.LED_STRIP) == 'object') {
|
||||
var fixed_led_strip = [];
|
||||
|
||||
var index = 0;
|
||||
while (configuration.LED_STRIP[index]) {
|
||||
fixed_led_strip.push(configuration.LED_STRIP[index++]);
|
||||
}
|
||||
configuration.LED_STRIP = fixed_led_strip;
|
||||
}
|
||||
|
||||
|
||||
for (var profileIndex = 0; profileIndex < 3; profileIndex++) {
|
||||
var RC = configuration.profiles[profileIndex].RC;
|
||||
// TPA breakpoint was added
|
||||
if (!RC.dynamic_THR_breakpoint) {
|
||||
RC.dynamic_THR_breakpoint = 1500; // firmware default
|
||||
}
|
||||
|
||||
// Roll and pitch rates were split
|
||||
RC.roll_rate = RC.roll_pitch_rate;
|
||||
RC.pitch_rate = RC.roll_pitch_rate;
|
||||
}
|
||||
|
||||
migratedVersion = '0.63.0';
|
||||
GUI.log(chrome.i18n.getMessage('configMigratedTo', [migratedVersion]));
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (configuration.apiVersion == undefined) {
|
||||
configuration.apiVersion = "1.0.0" // a guess that will satisfy the rest of the code
|
||||
}
|
||||
// apiVersion previously stored without patchlevel
|
||||
if (!semver.parse(configuration.apiVersion)) {
|
||||
configuration.apiVersion += ".0";
|
||||
if (!semver.parse(configuration.apiVersion)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (compareVersions(migratedVersion, '0.63.0') && !compareVersions(configuration.apiVersion, '1.7.0')) {
|
||||
// Serial configuation redesigned, 0.63.0 saves old and new configurations.
|
||||
var ports = [];
|
||||
for (var portIndex = 0; portIndex < configuration.SERIAL_CONFIG.ports.length; portIndex++) {
|
||||
var oldPort = configuration.SERIAL_CONFIG.ports[portIndex];
|
||||
|
||||
var newPort = {
|
||||
identifier: oldPort.identifier,
|
||||
functions: [],
|
||||
msp_baudrate: String(configuration.SERIAL_CONFIG.mspBaudRate),
|
||||
gps_baudrate: String(configuration.SERIAL_CONFIG.gpsBaudRate),
|
||||
telemetry_baudrate: 'AUTO',
|
||||
blackbox_baudrate: '115200',
|
||||
};
|
||||
|
||||
switch(oldPort.scenario) {
|
||||
case 1: // MSP, CLI, TELEMETRY, SMARTPORT TELEMETRY, GPS-PASSTHROUGH
|
||||
case 5: // MSP, CLI, GPS-PASSTHROUGH
|
||||
case 8: // MSP ONLY
|
||||
newPort.functions.push('MSP');
|
||||
break;
|
||||
case 2: // GPS
|
||||
newPort.functions.push('GPS');
|
||||
break;
|
||||
case 3: // RX_SERIAL
|
||||
newPort.functions.push('RX_SERIAL');
|
||||
break;
|
||||
case 10: // BLACKBOX ONLY
|
||||
newPort.functions.push('BLACKBOX');
|
||||
break;
|
||||
case 11: // MSP, CLI, BLACKBOX, GPS-PASSTHROUGH
|
||||
newPort.functions.push('MSP');
|
||||
newPort.functions.push('BLACKBOX');
|
||||
break;
|
||||
}
|
||||
|
||||
ports.push(newPort);
|
||||
}
|
||||
configuration.SERIAL_CONFIG = {
|
||||
ports: ports
|
||||
};
|
||||
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (compareVersions(migratedVersion, '0.63.0') && !compareVersions(configuration.apiVersion, '1.8.0')) {
|
||||
// api 1.8 exposes looptime and arming config
|
||||
|
||||
if (configuration.FC_CONFIG == undefined) {
|
||||
configuration.FC_CONFIG = {
|
||||
loopTime: 3500
|
||||
};
|
||||
}
|
||||
|
||||
if (configuration.ARMING_CONFIG == undefined) {
|
||||
configuration.ARMING_CONFIG = {
|
||||
auto_disarm_delay: 5,
|
||||
disarm_kill_switch: 1
|
||||
};
|
||||
}
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (compareVersions(migratedVersion, '0.63.0')) {
|
||||
// backups created with 0.63.0 for firmwares with api < 1.8 were saved with incorrect looptime
|
||||
if (configuration.FC_CONFIG.loopTime == 0) {
|
||||
//reset it to the default
|
||||
configuration.FC_CONFIG.loopTime = 3500;
|
||||
}
|
||||
}
|
||||
|
||||
if (semver.lt(migratedVersion, '0.66.0')) {
|
||||
// api 1.12 updated servo configuration protocol and added servo mixer rules
|
||||
for (var profileIndex = 0; profileIndex < configuration.profiles.length; profileIndex++) {
|
||||
|
||||
if (semver.eq(configuration.apiVersion, '1.10.0')) {
|
||||
// drop two unused servo configurations
|
||||
while (configuration.profiles[profileIndex].ServoConfig.length > 8) {
|
||||
configuration.profiles[profileIndex].ServoConfig.pop();
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < configuration.profiles[profileIndex].ServoConfig.length; i++) {
|
||||
var servoConfig = profiles[profileIndex].ServoConfig;
|
||||
|
||||
servoConfig[i].angleAtMin = 45;
|
||||
servoConfig[i].angleAtMax = 45;
|
||||
servoConfig[i].reversedInputSources = 0;
|
||||
|
||||
// set the rate to 0 if an invalid value is detected.
|
||||
if (servoConfig[i].rate < -100 || servoConfig[i].rate > 100) {
|
||||
servoConfig[i].rate = 0;
|
||||
}
|
||||
}
|
||||
|
||||
configuration.profiles[profileIndex].ServoRules = [];
|
||||
}
|
||||
|
||||
migratedVersion = '0.66.0';
|
||||
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (compareVersions(migratedVersion, '0.66.0') && !compareVersions(configuration.apiVersion, '1.14.0')) {
|
||||
// api 1.14 exposes 3D configuration
|
||||
|
||||
if (configuration._3D == undefined) {
|
||||
configuration._3D = {
|
||||
deadband3d_low: 1406,
|
||||
deadband3d_high: 1514,
|
||||
neutral3d: 1460,
|
||||
deadband3d_throttle: 50
|
||||
};
|
||||
}
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
|
||||
if (compareVersions(migratedVersion, '0.66.0') && !compareVersions(configuration.apiVersion, '1.15.0')) {
|
||||
// api 1.15 exposes RCdeadband and sensor alignment
|
||||
|
||||
|
||||
for (var profileIndex = 0; profileIndex < configuration.profiles.length; profileIndex++) {
|
||||
if (configuration.profiles[profileIndex].RCdeadband == undefined) {
|
||||
configuration.profiles[profileIndex].RCdeadband = {
|
||||
deadband: 0,
|
||||
yaw_deadband: 0,
|
||||
alt_hold_deadband: 40,
|
||||
};
|
||||
}
|
||||
}
|
||||
if (configuration.SENSOR_ALIGNMENT == undefined) {
|
||||
configuration.SENSOR_ALIGNMENT = {
|
||||
align_gyro: 0,
|
||||
align_acc: 0,
|
||||
align_mag: 0
|
||||
};
|
||||
}
|
||||
|
||||
// api 1.15 exposes RX_CONFIG, FAILSAFE_CONFIG and RXFAIL_CONFIG configuration
|
||||
|
||||
if (configuration.RX_CONFIG == undefined) {
|
||||
configuration.RX_CONFIG = {
|
||||
serialrx_provider: 0,
|
||||
spektrum_sat_bind: 0,
|
||||
midrc: 1500,
|
||||
mincheck: 1100,
|
||||
maxcheck: 1900,
|
||||
rx_min_usec: 885,
|
||||
rx_max_usec: 2115,
|
||||
nrf24rx_protocol: 0,
|
||||
nrf24rx_id: 0
|
||||
};
|
||||
}
|
||||
|
||||
if (configuration.FAILSAFE_CONFIG == undefined) {
|
||||
configuration.FAILSAFE_CONFIG = {
|
||||
failsafe_delay: 10,
|
||||
failsafe_off_delay: 200,
|
||||
failsafe_throttle: 1000,
|
||||
failsafe_kill_switch: 0,
|
||||
failsafe_throttle_low_delay: 100,
|
||||
failsafe_procedure: 0
|
||||
};
|
||||
}
|
||||
|
||||
if (configuration.RXFAIL_CONFIG == undefined) {
|
||||
configuration.RXFAIL_CONFIG = [
|
||||
{mode: 0, value: 1500},
|
||||
{mode: 0, value: 1500},
|
||||
{mode: 0, value: 1500},
|
||||
{mode: 0, value: 875}
|
||||
];
|
||||
|
||||
for (var i = 0; i < 14; i++) {
|
||||
var rxfailChannel = {
|
||||
mode: 1,
|
||||
value: 1500
|
||||
};
|
||||
configuration.RXFAIL_CONFIG.push(rxfailChannel);
|
||||
}
|
||||
}
|
||||
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (compareVersions(migratedVersion, '1.2.0')) {
|
||||
// old version of the configurator incorrectly had a 'disabled' option for GPS SBAS mode.
|
||||
if (MISC.gps_ubx_sbas < 0) {
|
||||
MISC.gps_ubx_sbas = 0;
|
||||
}
|
||||
migratedVersion = '1.2.0';
|
||||
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (!compareVersions(migratedVersion, '1.2.0')) {
|
||||
|
||||
// LED_COLORS & LED_MODE_COLORS support was added.
|
||||
if (!configuration.LED_COLORS) {
|
||||
configuration.LED_COLORS = [];
|
||||
}
|
||||
if (!configuration.LED_MODE_COLORS) {
|
||||
configuration.LED_MODE_COLORS = [];
|
||||
}
|
||||
|
||||
migratedVersion = '1.3.1';
|
||||
GUI.log(chrome.i18n.getMessage('configMigratedTo', [migratedVersion]));
|
||||
appliedMigrationsCount++;
|
||||
}
|
||||
|
||||
if (appliedMigrationsCount > 0) {
|
||||
GUI.log(chrome.i18n.getMessage('configMigrationSuccessful', [appliedMigrationsCount]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function configuration_upload(configuration, callback) {
|
||||
function upload() {
|
||||
var activeProfile = null,
|
||||
profilesN = 3;
|
||||
|
||||
var profileSpecificData = [
|
||||
MSPCodes.MSP_SET_PID,
|
||||
MSPCodes.MSP_SET_RC_TUNING,
|
||||
MSPCodes.MSP_SET_ACC_TRIM
|
||||
];
|
||||
|
||||
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
|
||||
profileSpecificData.push(MSPCodes.MSP_SET_RC_DEADBAND);
|
||||
}
|
||||
|
||||
MSP.send_message(MSPCodes.MSP_STATUS, false, false, function () {
|
||||
activeProfile = CONFIG.profile;
|
||||
select_profile();
|
||||
});
|
||||
|
||||
function select_profile() {
|
||||
if (activeProfile > 0) {
|
||||
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [0], false, upload_specific_data);
|
||||
} else {
|
||||
upload_specific_data();
|
||||
}
|
||||
}
|
||||
|
||||
function upload_specific_data() {
|
||||
var savingProfile = 0,
|
||||
codeKey = 0;
|
||||
|
||||
function load_objects(profile) {
|
||||
PID = configuration.profiles[profile].PID;
|
||||
PIDs = configuration.profiles[profile].PIDs;
|
||||
RC_tuning = configuration.profiles[profile].RC;
|
||||
CONFIG.accelerometerTrims = configuration.profiles[profile].AccTrim;
|
||||
SERVO_CONFIG = configuration.profiles[profile].ServoConfig;
|
||||
SERVO_RULES = configuration.profiles[profile].ServoRules;
|
||||
MODE_RANGES = configuration.profiles[profile].ModeRanges;
|
||||
ADJUSTMENT_RANGES = configuration.profiles[profile].AdjustmentRanges;
|
||||
RC_deadband = configuration.profiles[profile].RCdeadband;
|
||||
}
|
||||
|
||||
function upload_using_specific_commands() {
|
||||
MSP.send_message(profileSpecificData[codeKey], mspHelper.crunch(profileSpecificData[codeKey]), false, function () {
|
||||
codeKey++;
|
||||
|
||||
if (codeKey < profileSpecificData.length) {
|
||||
upload_using_specific_commands();
|
||||
} else {
|
||||
codeKey = 0;
|
||||
savingProfile++;
|
||||
|
||||
if (savingProfile < profilesN) {
|
||||
load_objects(savingProfile);
|
||||
|
||||
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () {
|
||||
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [savingProfile], false, upload_using_specific_commands);
|
||||
});
|
||||
} else {
|
||||
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, function () {
|
||||
MSP.send_message(MSPCodes.MSP_SELECT_SETTING, [activeProfile], false, upload_unique_data);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function upload_servo_mix_rules() {
|
||||
mspHelper.sendServoMixRules(upload_servo_configuration);
|
||||
}
|
||||
|
||||
function upload_servo_configuration() {
|
||||
mspHelper.sendServoConfigurations(upload_mode_ranges);
|
||||
}
|
||||
|
||||
function upload_mode_ranges() {
|
||||
mspHelper.sendModeRanges(upload_adjustment_ranges);
|
||||
}
|
||||
|
||||
function upload_adjustment_ranges() {
|
||||
mspHelper.sendAdjustmentRanges(upload_using_specific_commands);
|
||||
}
|
||||
// start uploading
|
||||
load_objects(0);
|
||||
upload_servo_configuration();
|
||||
}
|
||||
|
||||
function upload_unique_data() {
|
||||
var codeKey = 0;
|
||||
|
||||
var uniqueData = [
|
||||
MSPCodes.MSP_SET_MISC,
|
||||
MSPCodes.MSP_SET_RX_MAP,
|
||||
MSPCodes.MSP_SET_BF_CONFIG,
|
||||
MSPCodes.MSP_SET_CF_SERIAL_CONFIG
|
||||
];
|
||||
|
||||
function update_unique_data_list() {
|
||||
if (semver.gte(CONFIG.apiVersion, "1.8.0")) {
|
||||
uniqueData.push(MSPCodes.MSP_SET_LOOP_TIME);
|
||||
uniqueData.push(MSPCodes.MSP_SET_ARMING_CONFIG);
|
||||
}
|
||||
if (semver.gte(CONFIG.apiVersion, "1.14.0")) {
|
||||
uniqueData.push(MSPCodes.MSP_SET_3D);
|
||||
}
|
||||
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
|
||||
uniqueData.push(MSPCodes.MSP_SET_SENSOR_ALIGNMENT);
|
||||
uniqueData.push(MSPCodes.MSP_SET_RX_CONFIG);
|
||||
uniqueData.push(MSPCodes.MSP_SET_FAILSAFE_CONFIG);
|
||||
}
|
||||
}
|
||||
|
||||
function load_objects() {
|
||||
MISC = configuration.MISC;
|
||||
RC_MAP = configuration.RCMAP;
|
||||
BF_CONFIG = configuration.BF_CONFIG;
|
||||
SERIAL_CONFIG = configuration.SERIAL_CONFIG;
|
||||
LED_STRIP = configuration.LED_STRIP;
|
||||
LED_COLORS = configuration.LED_COLORS;
|
||||
LED_MODE_COLORS = configuration.LED_MODE_COLORS;
|
||||
ARMING_CONFIG = configuration.ARMING_CONFIG;
|
||||
FC_CONFIG = configuration.FC_CONFIG;
|
||||
_3D = configuration._3D;
|
||||
SENSOR_ALIGNMENT = configuration.SENSOR_ALIGNMENT;
|
||||
RX_CONFIG = configuration.RX_CONFIG;
|
||||
FAILSAFE_CONFIG = configuration.FAILSAFE_CONFIG;
|
||||
RXFAIL_CONFIG = configuration.RXFAIL_CONFIG;
|
||||
}
|
||||
|
||||
function send_unique_data_item() {
|
||||
if (codeKey < uniqueData.length) {
|
||||
MSP.send_message(uniqueData[codeKey], mspHelper.crunch(uniqueData[codeKey]), false, function () {
|
||||
codeKey++;
|
||||
send_unique_data_item();
|
||||
});
|
||||
} else {
|
||||
send_led_strip_config();
|
||||
}
|
||||
}
|
||||
|
||||
load_objects();
|
||||
|
||||
update_unique_data_list();
|
||||
|
||||
// start uploading
|
||||
send_unique_data_item();
|
||||
}
|
||||
|
||||
function send_led_strip_config() {
|
||||
mspHelper.sendLedStripConfig(send_led_strip_colors);
|
||||
}
|
||||
|
||||
function send_led_strip_colors() {
|
||||
mspHelper.sendLedStripColors(send_led_strip_mode_colors);
|
||||
}
|
||||
|
||||
function send_led_strip_mode_colors() {
|
||||
if (semver.gte(CONFIG.apiVersion, "1.19.0"))
|
||||
mspHelper.sendLedStripModeColors(send_rxfail_config);
|
||||
else
|
||||
send_rxfail_config();
|
||||
}
|
||||
|
||||
function send_rxfail_config() {
|
||||
if (semver.gte(CONFIG.apiVersion, "1.15.0")) {
|
||||
mspHelper.sendRxFailConfig(save_to_eeprom);
|
||||
} else {
|
||||
save_to_eeprom();
|
||||
}
|
||||
}
|
||||
|
||||
function save_to_eeprom() {
|
||||
MSP.send_message(MSPCodes.MSP_EEPROM_WRITE, false, false, reboot);
|
||||
}
|
||||
|
||||
function reboot() {
|
||||
GUI.log(chrome.i18n.getMessage('eeprom_saved_ok'));
|
||||
|
||||
GUI.tab_switch_cleanup(function() {
|
||||
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false, reinitialize);
|
||||
});
|
||||
}
|
||||
|
||||
function reinitialize() {
|
||||
GUI.log(chrome.i18n.getMessage('deviceRebooting'));
|
||||
|
||||
GUI.timeout_add('waiting_for_bootup', function waiting_for_bootup() {
|
||||
MSP.send_message(MSPCodes.MSP_IDENT, false, false, function () {
|
||||
GUI.log(chrome.i18n.getMessage('deviceReady'));
|
||||
|
||||
if (callback) callback();
|
||||
});
|
||||
}, 1500); // 1500 ms seems to be just the right amount of delay to prevent data request timeouts
|
||||
}
|
||||
}
|
||||
|
||||
upload();
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
'use s';
|
||||
|
||||
var helper = helper || {};
|
||||
|
||||
/**
|
||||
* Simple analyzer that returns frequency of events using 5s buffer
|
||||
* Usage: register periodic events with 'put', then call 'get' to get results
|
||||
*/
|
||||
helper.eventFrequencyAnalyzer = (function () {
|
||||
|
||||
var privateScope = {},
|
||||
publicScope = {},
|
||||
bufferPeriod = 5000;
|
||||
|
||||
privateScope.data = {};
|
||||
privateScope.output = {};
|
||||
privateScope.intervalHandler;
|
||||
|
||||
/**
|
||||
* Periodically executed aggregation task
|
||||
* @returns {{}|*}
|
||||
*/
|
||||
publicScope.analyze = function () {
|
||||
privateScope.output = {};
|
||||
|
||||
for (var i in privateScope.data) {
|
||||
if (privateScope.data.hasOwnProperty(i)) {
|
||||
privateScope.output[i] = privateScope.data[i] / bufferPeriod * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
privateScope.data = {};
|
||||
return privateScope.output;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return event list with frequencies
|
||||
* @returns {{}|*}
|
||||
*/
|
||||
publicScope.get = function () {
|
||||
return privateScope.output;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns raw data
|
||||
* @returns {{}|*}
|
||||
*/
|
||||
publicScope.getRaw = function () {
|
||||
return privateScope.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Put event into analyzer
|
||||
* @param {object} event
|
||||
*/
|
||||
publicScope.put = function (event) {
|
||||
if (privateScope.data[event]) {
|
||||
privateScope.data[event]++;
|
||||
} else {
|
||||
privateScope.data[event] = 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number} buffer buffer length in milliseconds
|
||||
*/
|
||||
publicScope.setBufferPeriod = function (buffer) {
|
||||
bufferPeriod = buffer;
|
||||
clearInterval(privateScope.intervalHandler);
|
||||
privateScope.intervalHandler = setInterval(publicScope.analyze, bufferPeriod);
|
||||
};
|
||||
|
||||
privateScope.intervalHandler = setInterval(publicScope.analyze, bufferPeriod);
|
||||
|
||||
return publicScope;
|
||||
})();
|
@ -0,0 +1,137 @@
|
||||
'use strict';
|
||||
|
||||
var helper = helper || {};
|
||||
|
||||
helper.interval = (function () {
|
||||
|
||||
var privateScope = {},
|
||||
publicScope = {};
|
||||
|
||||
privateScope.intervals = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {String} name
|
||||
* @param {Function} code function reference (code to be executed)
|
||||
* @param {int} interval time interval in milliseconds
|
||||
* @param {boolean=} first true/false if code should be ran initially before next timer interval hits
|
||||
* @returns {{name: *, timer: null, code: *, interval: *, fired: number, paused: boolean}}
|
||||
*/
|
||||
publicScope.add = function (name, code, interval, first) {
|
||||
|
||||
/*
|
||||
* Kill existing interval with this name if exists
|
||||
*/
|
||||
publicScope.remove(name);
|
||||
|
||||
var data = {
|
||||
'name': name,
|
||||
'timer': null,
|
||||
'code': code,
|
||||
'interval': interval,
|
||||
'fired': 0,
|
||||
'paused': false
|
||||
};
|
||||
|
||||
if (first == true) {
|
||||
code(); // execute code
|
||||
data.fired++; // increment counter
|
||||
}
|
||||
|
||||
data.timer = setInterval(function() {
|
||||
code();
|
||||
data.fired++;
|
||||
}, interval);
|
||||
|
||||
privateScope.intervals.push(data);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Method removes and stop execution of interval callback
|
||||
* @param {string} name
|
||||
* @returns {boolean}
|
||||
*/
|
||||
publicScope.remove = function (name) {
|
||||
for (var i = 0; i < privateScope.intervals.length; i++) {
|
||||
if (privateScope.intervals[i].name == name) {
|
||||
clearInterval(privateScope.intervals[i].timer); // stop timer
|
||||
privateScope.intervals.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} name
|
||||
* @returns {boolean}
|
||||
*/
|
||||
publicScope.pause = function (name) {
|
||||
for (var i = 0; i < privateScope.intervals.length; i++) {
|
||||
if (privateScope.intervals[i].name == name) {
|
||||
clearInterval(privateScope.intervals[i].timer);
|
||||
privateScope.intervals[i].paused = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} name
|
||||
* @returns {boolean}
|
||||
*/
|
||||
publicScope.resume = function (name) {
|
||||
for (var i = 0; i < privateScope.intervals.length; i++) {
|
||||
if (privateScope.intervals[i].name == name && privateScope.intervals[i].paused) {
|
||||
var obj = privateScope.intervals[i];
|
||||
|
||||
obj.timer = setInterval(function() {
|
||||
obj.code(); // execute code
|
||||
obj.fired++; // increment counter
|
||||
}, obj.interval);
|
||||
|
||||
obj.paused = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {=} keep_array
|
||||
* @returns {number}
|
||||
*/
|
||||
publicScope.killAll = function (keep_array) {
|
||||
var timers_killed = 0;
|
||||
|
||||
for (var i = (privateScope.intervals.length - 1); i >= 0; i--) { // reverse iteration
|
||||
var keep = false;
|
||||
if (keep_array) { // only run through the array if it exists
|
||||
keep_array.forEach(function (name) {
|
||||
if (privateScope.intervals[i].name == name) {
|
||||
keep = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!keep) {
|
||||
clearInterval(privateScope.intervals[i].timer); // stop timer
|
||||
privateScope.intervals.splice(i, 1); // remove element/object from array
|
||||
timers_killed++;
|
||||
}
|
||||
}
|
||||
|
||||
return timers_killed;
|
||||
};
|
||||
|
||||
return publicScope;
|
||||
})();
|
@ -0,0 +1,128 @@
|
||||
'use strict';
|
||||
|
||||
var helper = helper || {};
|
||||
|
||||
helper.periodicStatusUpdater = (function () {
|
||||
|
||||
var publicScope = {},
|
||||
privateScope = {};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {number=} baudSpeed
|
||||
* @returns {number}
|
||||
*/
|
||||
publicScope.getUpdateInterval = function (baudSpeed) {
|
||||
|
||||
if (!baudSpeed) {
|
||||
baudSpeed = 115200;
|
||||
}
|
||||
|
||||
if (baudSpeed >= 115200) {
|
||||
return 200;
|
||||
} else if (baudSpeed >= 57600) {
|
||||
return 400;
|
||||
} else if (baudSpeed >= 38400) {
|
||||
return 500;
|
||||
} else if (baudSpeed >= 19200) {
|
||||
return 600;
|
||||
} else if (baudSpeed >= 9600) {
|
||||
return 750;
|
||||
} else {
|
||||
return 1000;
|
||||
}
|
||||
};
|
||||
|
||||
privateScope.updateView = function () {
|
||||
|
||||
var active = ((Date.now() - MSP.analog_last_received_timestamp) < publicScope.getUpdateInterval(serial.bitrate) * 3);
|
||||
|
||||
for (var i = 0; i < AUX_CONFIG.length; i++) {
|
||||
if (AUX_CONFIG[i] == 'ARM') {
|
||||
if (bit_check(CONFIG.mode, i))
|
||||
$(".armedicon").css({
|
||||
'background-image': 'url(images/icons/cf_icon_armed_active.svg)'
|
||||
});
|
||||
else
|
||||
$(".armedicon").css({
|
||||
'background-image': 'url(images/icons/cf_icon_armed_grey.svg)'
|
||||
});
|
||||
}
|
||||
if (AUX_CONFIG[i] == 'FAILSAFE') {
|
||||
if (bit_check(CONFIG.mode, i))
|
||||
$(".failsafeicon").css({
|
||||
'background-image': 'url(images/icons/cf_icon_failsafe_active.svg)'
|
||||
});
|
||||
else
|
||||
$(".failsafeicon").css({
|
||||
'background-image': 'url(images/icons/cf_icon_failsafe_grey.svg)'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (ANALOG != undefined) {
|
||||
var nbCells = Math.floor(ANALOG.voltage / MISC.vbatmaxcellvoltage) + 1;
|
||||
if (ANALOG.voltage == 0)
|
||||
nbCells = 1;
|
||||
|
||||
var min = MISC.vbatmincellvoltage * nbCells;
|
||||
var max = MISC.vbatmaxcellvoltage * nbCells;
|
||||
var warn = MISC.vbatwarningcellvoltage * nbCells;
|
||||
|
||||
$(".battery-status").css({
|
||||
width: ((ANALOG.voltage - min) / (max - min) * 100) + "%",
|
||||
display: 'inline-block'
|
||||
});
|
||||
|
||||
if (active) {
|
||||
$(".linkicon").css({
|
||||
'background-image': 'url(images/icons/cf_icon_link_active.svg)'
|
||||
});
|
||||
} else {
|
||||
$(".linkicon").css({
|
||||
'background-image': 'url(images/icons/cf_icon_link_grey.svg)'
|
||||
});
|
||||
}
|
||||
|
||||
if (ANALOG.voltage < warn) {
|
||||
$(".battery-status").css('background-color', '#D42133');
|
||||
} else {
|
||||
$(".battery-status").css('background-color', '#59AA29');
|
||||
}
|
||||
|
||||
$(".battery-legend").text(ANALOG.voltage + " V");
|
||||
}
|
||||
|
||||
$('#quad-status_wrapper').show();
|
||||
};
|
||||
|
||||
publicScope.run = function () {
|
||||
|
||||
if (!CONFIGURATOR.connectionValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(".quad-status-contents").css({
|
||||
display: 'inline-block'
|
||||
});
|
||||
|
||||
if (GUI.active_tab != 'cli') {
|
||||
|
||||
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
|
||||
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS, false, false);
|
||||
}
|
||||
|
||||
if (semver.gte(CONFIG.flightControllerVersion, "1.2.0")) {
|
||||
MSP.send_message(MSPCodes.MSP_STATUS_EX, false, false);
|
||||
} else {
|
||||
MSP.send_message(MSPCodes.MSP_STATUS, false, false);
|
||||
}
|
||||
|
||||
MSP.send_message(MSPCodes.MSP_ANALOG, false, false);
|
||||
|
||||
privateScope.updateView();
|
||||
}
|
||||
};
|
||||
|
||||
return publicScope;
|
||||
})();
|
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
var helper = helper || {};
|
||||
|
||||
helper.task = (function () {
|
||||
|
||||
var publicScope = {},
|
||||
privateScope = {};
|
||||
|
||||
privateScope.getStatusPullInterval = function () {
|
||||
//TODO use serial connection speed to determine update interval
|
||||
return 250;
|
||||
};
|
||||
|
||||
publicScope.statusPullStart = function () {
|
||||
helper.interval.add('status_pull', function () {
|
||||
MSP.send_message(MSPCodes.MSP_STATUS, false, false, function () {
|
||||
if (semver.gte(CONFIG.flightControllerVersion, "1.5.0")) {
|
||||
MSP.send_message(MSPCodes.MSP_SENSOR_STATUS);
|
||||
}
|
||||
});
|
||||
|
||||
}, privateScope.getStatusPullInterval(), true);
|
||||
};
|
||||
|
||||
return publicScope;
|
||||
})();
|
@ -0,0 +1,66 @@
|
||||
'use strict';
|
||||
|
||||
var helper = helper || {};
|
||||
|
||||
helper.timeout = (function () {
|
||||
|
||||
var privateScope = {},
|
||||
publicScope = {};
|
||||
|
||||
privateScope.timeouts = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {function } code
|
||||
* @param {number} timeout
|
||||
* @returns {{name: *, timer: null, timeout: *}}
|
||||
*/
|
||||
publicScope.add = function (name, code, timeout) {
|
||||
var data = {'name': name, 'timer': null, 'timeout': timeout};
|
||||
|
||||
// start timer with "cleaning" callback
|
||||
data.timer = setTimeout(function() {
|
||||
code(); // execute code
|
||||
|
||||
// remove object from array
|
||||
var index = privateScope.timeouts.indexOf(data);
|
||||
if (index > -1) privateScope.timeouts.splice(index, 1);
|
||||
}, timeout);
|
||||
|
||||
privateScope.timeouts.push(data); // push to primary timeout array
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
publicScope.remove = function (name) {
|
||||
for (var i = 0; i < privateScope.timeouts.length; i++) {
|
||||
if (privateScope.timeouts[i].name == name) {
|
||||
clearTimeout(privateScope.timeouts[i].timer); // stop timer
|
||||
privateScope.timeouts.splice(i, 1); // remove element/object from array
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {number} number of killed timeouts
|
||||
*/
|
||||
publicScope.killAll = function () {
|
||||
var timers_killed = 0;
|
||||
|
||||
for (var i = 0; i < privateScope.timeouts.length; i++) {
|
||||
clearTimeout(privateScope.timeouts[i].timer); // stop timer
|
||||
timers_killed++;
|
||||
}
|
||||
|
||||
privateScope.timeouts = []; // drop objects
|
||||
|
||||
return timers_killed;
|
||||
};
|
||||
|
||||
return publicScope;
|
||||
})();
|
@ -1,27 +1,148 @@
|
||||
#presets-list option {
|
||||
.tab-configuration #presets-list option {
|
||||
padding: 0.4em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.preset__head {
|
||||
.tab-configuration .preset__head {
|
||||
color: #37a8db;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.preset__description {
|
||||
margin-top: 1em;
|
||||
.tab-configuration .preset__description {
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.preset__features {
|
||||
margin-top: 1em;
|
||||
.tab-configuration .preset__description span {
|
||||
margin-top: 5px;
|
||||
font-family: 'open_sansregular', Arial, serif;
|
||||
}
|
||||
|
||||
.preset__feature {
|
||||
list-style: disc;
|
||||
.tab-configuration .preset__features {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.tab-configuration .preset__feature {
|
||||
list-style: inside disc;
|
||||
list-style-type: afar;
|
||||
color: #37a8db;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
.preset__feature-text {
|
||||
.tab-configuration .preset__feature-text {
|
||||
color: #000000;
|
||||
margin-left: -0.5em;
|
||||
}
|
||||
|
||||
.tab-configuration #preset-image {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
background-image:url(../images/icons/peset_default.svg);
|
||||
background-size:contain;
|
||||
background-repeat:no-repeat;
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.tab-configuration .clearboth {
|
||||
width:100%;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
.tab-configuration .preset__list-wrapper {
|
||||
background-color: #525252;
|
||||
background: #525252 -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.35));
|
||||
min-height: 400px;
|
||||
border-right: 3px solid #37a8db;
|
||||
overflow:hidden;
|
||||
border-top-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
box-shadow: inset -10px 0px 20px rgba(50,50,50, 0.5);
|
||||
}
|
||||
|
||||
.tab-configuration .list-menu ul {
|
||||
}
|
||||
|
||||
.tab-configuration .list-menu li {
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.30);
|
||||
}
|
||||
|
||||
.tab-configuration .list-menu li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
|
||||
.tab-configuration .list-menu li a {
|
||||
font-family: 'open_sansregular', Arial, serif;
|
||||
display:block;
|
||||
height:30px;
|
||||
line-height: 30px;
|
||||
font-size: 13px;
|
||||
padding-left: 10px;
|
||||
text-shadow: 0 1px rgba(0, 0, 0, 0.45);
|
||||
border-top: solid 1px rgba(255, 255, 255, 0.07);
|
||||
color: #999999;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tab-configuration .list-menu li a:hover {
|
||||
background-color: rgba(128, 128, 128, 0.50);
|
||||
color: white;
|
||||
text-shadow: 0 1px rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
.tab-configuration .preset {
|
||||
width: calc(75% - 5px);
|
||||
}
|
||||
|
||||
.tab-configuration .preset-spacer {
|
||||
padding: 20px;
|
||||
float:left;
|
||||
width: calc(100% - 38px);
|
||||
}
|
||||
|
||||
.tab-configuration .list-menu li.active a {
|
||||
background-color: #37a8db;
|
||||
text-shadow: 0 1px rgba(0, 0, 0, 0.45);
|
||||
color: white;
|
||||
|
||||
}
|
||||
|
||||
.tab-configuration .airplane {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image:url(../images/icons/peset_plane.svg);
|
||||
}
|
||||
|
||||
.tab-configuration .flyingwing {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image:url(../images/icons/peset_wing.svg);
|
||||
|
||||
}
|
||||
|
||||
.tab-configuration .multirotor {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image:url(../images/icons/peset_quad.svg);
|
||||
}
|
||||
|
||||
.tab-configuration .preset .top {
|
||||
background-color: #e6e6e6;
|
||||
box-shadow: inset 0px -5px 5px rgba(50,50,50, 0.1);
|
||||
border-top-right-radius: 3px;
|
||||
}
|
||||
|
||||
.tab-configuration .preset .bottom {
|
||||
border-bottom-right-radius: 3px;
|
||||
}
|
||||
|
||||
.tab-configuration .modal__content h1 {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.tab-configuration #details-head {
|
||||
display: none;
|
||||
float: left;
|
||||
width: 100%;
|
||||
margin-bottom: 5px;
|
||||
}
|
Loading…
Reference in New Issue