1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-26 09:45:28 +03:00

Add metered connection and usability check (#4168)

* Add Metered connection and usability check

* Add network speed to status bar

* Add network type

* Introduce network status

* Rephrase option

* Add network info to setup tab

* Reserve statusbar for something else

* Make sonar happy
This commit is contained in:
Mark Haslinghuis 2024-09-21 23:28:10 +02:00 committed by GitHub
parent 4e553d9607
commit 5ef26ae89e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 133 additions and 14 deletions

View file

@ -138,6 +138,10 @@
"rememberLastTab": { "rememberLastTab": {
"message": "Reopen last tab on connect" "message": "Reopen last tab on connect"
}, },
"meteredConnection": {
"message": "Disable internet access (for metered or slow connections)",
"description": "Text for the option to disable internet access for metered connection or to disable data over slow connections"
},
"analyticsOptOut": { "analyticsOptOut": {
"message": "Opt out of the anonymised collection of statistics data" "message": "Opt out of the anonymised collection of statistics data"
}, },
@ -1198,6 +1202,34 @@
"initialSetupEepromSaved": { "initialSetupEepromSaved": {
"message": "EEPROM <span class=\"message-positive\">saved</span>" "message": "EEPROM <span class=\"message-positive\">saved</span>"
}, },
"initialSetupNetworkInfo": {
"message": "Network info"
},
"initialSetupNetworkInfoHelp": {
"message": "Shows network connection status",
"description": "Message that pops up to describe the Network Connection section"
},
"initialSetupNetworkInfoStatus": {
"message": "Status:"
},
"initialSetupNetworkInfoStatusOnline": {
"message": "Online"
},
"initialSetupNetworkInfoStatusOffline": {
"message": "Offline"
},
"initialSetupNetworkInfoStatusSlow": {
"message": "Slow"
},
"initialSetupNetworkType": {
"message": "Type:"
},
"initialSetupNetworkRtt": {
"message": "RTT:"
},
"initialSetupNetworkDownlink": {
"message": "Downlink:"
},
"featureNone": { "featureNone": {
"message": "&lt;Select One&gt;" "message": "&lt;Select One&gt;"
}, },

View file

@ -1,15 +1,16 @@
import BuildApi from './BuildApi'; import BuildApi from './BuildApi';
import DarkTheme from './DarkTheme'; import DarkTheme from './DarkTheme';
import { ispConnected } from './utils/connection';
export default class Sponsor { export default class Sponsor {
constructor () { constructor () {
this._api = new BuildApi(); this._api = new BuildApi();
this._timer = setInterval(() => { this.Refresh(); }, 30000); this._timer = ispConnected() ? setInterval(() => { this.Refresh(); }, 30000) : null;
} }
Refresh() { Refresh() {
if (!navigator.onLine) { if (!ispConnected()) {
return; return;
} }

View file

@ -25,6 +25,7 @@ import BuildApi from "./BuildApi";
import { serialShim } from "./serial_shim.js"; import { serialShim } from "./serial_shim.js";
import { EventBus } from "../components/eventBus"; import { EventBus } from "../components/eventBus";
import { ispConnected } from "./utils/connection";
let serial = serialShim(); let serial = serialShim();
@ -463,7 +464,7 @@ function checkReportProblems() {
if (needsProblemReportingDialog) { if (needsProblemReportingDialog) {
problems.map((problem) => { problems.forEach((problem) => {
problemItemTemplate.clone().html(problem.description).appendTo(problemDialogList); problemItemTemplate.clone().html(problem.description).appendTo(problemDialogList);
}); });
@ -491,7 +492,7 @@ async function processBuildOptions() {
// firmware 1_45 or higher is required to support cloud build options // firmware 1_45 or higher is required to support cloud build options
// firmware 1_46 or higher retrieves build options from the flight controller // firmware 1_46 or higher retrieves build options from the flight controller
if (supported && FC.CONFIG.buildKey.length === 32 && navigator.onLine) { if (supported && FC.CONFIG.buildKey.length === 32 && ispConnected()) {
const buildApi = new BuildApi(); const buildApi = new BuildApi();
function onLoadCloudBuild(options) { function onLoadCloudBuild(options) {

View file

@ -12,6 +12,7 @@ import jBox from "jbox";
import $ from 'jquery'; import $ from 'jquery';
import { serialShim } from "../serial_shim"; import { serialShim } from "../serial_shim";
import FileSystem from "../FileSystem"; import FileSystem from "../FileSystem";
import { ispConnected } from "../utils/connection";
const serial = serialShim(); const serial = serialShim();
@ -229,7 +230,7 @@ cli.initialize = function (callback) {
}); });
$('a.support') $('a.support')
.toggle(navigator.onLine) .toggle(ispConnected())
.on('click', function() { .on('click', function() {
function submitSupportData(data) { function submitSupportData(data) {

View file

@ -18,6 +18,7 @@ import DFU from '../protocols/webusbdfu';
import AutoBackup from '../utils/AutoBackup.js'; import AutoBackup from '../utils/AutoBackup.js';
import AutoDetect from '../utils/AutoDetect.js'; import AutoDetect from '../utils/AutoDetect.js';
import { EventBus } from "../../components/eventBus"; import { EventBus } from "../../components/eventBus";
import { ispConnected } from '../utils/connection.js';
const firmware_flasher = { const firmware_flasher = {
targets: null, targets: null,
@ -147,7 +148,7 @@ firmware_flasher.initialize = function (callback) {
} }
function loadTargetList(targets) { function loadTargetList(targets) {
if (!targets || !navigator.onLine) { if (!targets || !ispConnected()) {
$('select[name="board"]').empty().append('<option value="0">Offline</option>'); $('select[name="board"]').empty().append('<option value="0">Offline</option>');
$('select[name="firmware_version"]').empty().append('<option value="0">Offline</option>'); $('select[name="firmware_version"]').empty().append('<option value="0">Offline</option>');
@ -214,7 +215,7 @@ firmware_flasher.initialize = function (callback) {
} }
function buildOptions(data) { function buildOptions(data) {
if (!navigator.onLine) { if (!ispConnected()) {
return; return;
} }
@ -1133,7 +1134,7 @@ firmware_flasher.initialize = function (callback) {
} }
self.buildApi.loadTargets(() => { self.buildApi.loadTargets(() => {
$('#content').load("./tabs/firmware_flasher.html", onDocumentLoad); $('#content').load("./tabs/firmware_flasher.html", onDocumentLoad);
}); });
}; };
@ -1142,7 +1143,7 @@ firmware_flasher.initialize = function (callback) {
firmware_flasher.validateBuildKey = function() { firmware_flasher.validateBuildKey = function() {
return this.cloudBuildKey?.length === 32 && navigator.onLine; return this.cloudBuildKey?.length === 32 && ispConnected();
}; };
firmware_flasher.cleanup = function (callback) { firmware_flasher.cleanup = function (callback) {

View file

@ -11,6 +11,7 @@ import { mspHelper } from '../msp/MSPHelper';
import { updateTabList } from '../utils/updateTabList'; import { updateTabList } from '../utils/updateTabList';
import { initMap } from './map'; import { initMap } from './map';
import { fromLonLat } from "ol/proj"; import { fromLonLat } from "ol/proj";
import { ispConnected } from "../utils/connection";
const gps = {}; const gps = {};
@ -352,7 +353,7 @@ gps.initialize = async function (callback) {
let gpsFoundPosition = false; let gpsFoundPosition = false;
if (navigator.onLine) { if (ispConnected()) {
$('#connect').hide(); $('#connect').hide();
gpsFoundPosition = !!(lon && lat); gpsFoundPosition = !!(lon && lat);
@ -382,7 +383,7 @@ gps.initialize = async function (callback) {
}, 75, true); }, 75, true);
//check for internet connection on load //check for internet connection on load
if (navigator.onLine) { if (ispConnected()) {
console.log('Online'); console.log('Online');
set_online(); set_online();
} else { } else {
@ -391,7 +392,7 @@ gps.initialize = async function (callback) {
} }
$("#check").on('click',function(){ $("#check").on('click',function(){
if (navigator.onLine) { if (ispConnected()) {
console.log('Online'); console.log('Online');
set_online(); set_online();
} else { } else {

View file

@ -8,6 +8,7 @@ import { checkForConfiguratorUpdates } from '../utils/checkForConfiguratorUpdate
import { checkSetupAnalytics } from '../Analytics'; import { checkSetupAnalytics } from '../Analytics';
import $ from 'jquery'; import $ from 'jquery';
import NotificationManager from '../utils/notifications'; import NotificationManager from '../utils/notifications';
import { ispConnected } from '../utils/connection';
const options = {}; const options = {};
options.initialize = function (callback) { options.initialize = function (callback) {
@ -30,6 +31,7 @@ options.initialize = function (callback) {
TABS.options.initShowDevToolsOnStartup(); TABS.options.initShowDevToolsOnStartup();
TABS.options.initShowNotifications(); TABS.options.initShowNotifications();
TABS.options.initShowWarnings(); TABS.options.initShowWarnings();
TABS.options.initMeteredConnection();
GUI.content_ready(callback); GUI.content_ready(callback);
}); });
@ -228,6 +230,18 @@ options.initShowNotifications = function () {
.change(); .change();
}; };
options.initMeteredConnection = function () {
const result = getConfig("meteredConnection");
$("div.meteredConnection input")
.prop("checked", !!result.meteredConnection)
.on('change', function () {
setConfig({ meteredConnection: $(this).is(":checked") });
// update network status
ispConnected();
})
.trigger('change');
};
// TODO: remove when modules are in place // TODO: remove when modules are in place
TABS.options = options; TABS.options = options;
export { options }; export { options };

View file

@ -11,6 +11,7 @@ import MSPCodes from '../msp/MSPCodes';
import { API_VERSION_1_45, API_VERSION_1_46 } from '../data_storage'; import { API_VERSION_1_45, API_VERSION_1_46 } from '../data_storage';
import { gui_log } from '../gui_log'; import { gui_log } from '../gui_log';
import $ from 'jquery'; import $ from 'jquery';
import { ispConnected } from '../utils/connection';
const setup = { const setup = {
yaw_fix: 0.0, yaw_fix: 0.0,
@ -411,7 +412,7 @@ setup.initialize = function (callback) {
const showBuildInfo = function() { const showBuildInfo = function() {
const supported = FC.CONFIG.buildKey.length === 32; const supported = FC.CONFIG.buildKey.length === 32;
if (supported && navigator.onLine) { if (supported && ispConnected()) {
const buildRoot = `https://build.betaflight.com/api/builds/${FC.CONFIG.buildKey}`; const buildRoot = `https://build.betaflight.com/api/builds/${FC.CONFIG.buildKey}`;
const buildConfig = `<span class="buildInfoBtn" title="${i18n.getMessage('initialSetupInfoBuildConfig')}: ${buildRoot}/json"> const buildConfig = `<span class="buildInfoBtn" title="${i18n.getMessage('initialSetupInfoBuildConfig')}: ${buildRoot}/json">
<a href="${buildRoot}/json" target="_blank"><strong>${i18n.getMessage('initialSetupInfoBuildConfig')}</strong></a></span>`; <a href="${buildRoot}/json" target="_blank"><strong>${i18n.getMessage('initialSetupInfoBuildConfig')}</strong></a></span>`;
@ -426,7 +427,7 @@ setup.initialize = function (callback) {
}; };
const showBuildOptions = function() { const showBuildOptions = function() {
const supported = (semver.eq(FC.CONFIG.apiVersion, API_VERSION_1_45) && navigator.onLine || semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) && FC.CONFIG.buildOptions.length; const supported = (semver.eq(FC.CONFIG.apiVersion, API_VERSION_1_45) && ispConnected() || semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) && FC.CONFIG.buildOptions.length;
if (supported) { if (supported) {
let buildOptionList = `<div class="dialogBuildInfoGrid-container">`; let buildOptionList = `<div class="dialogBuildInfoGrid-container">`;
@ -464,9 +465,33 @@ setup.initialize = function (callback) {
} }
} }
function showNetworkStatus() {
const networkStatus = ispConnected();
let statusText = '';
const type = navigator.connection.effectiveType;
const downlink = navigator.connection.downlink;
const rtt = navigator.connection.rtt;
if (!networkStatus || !navigator.onLine || type === 'none') {
statusText = i18n.getMessage('initialSetupNetworkInfoStatusOffline');
} else if (type === 'slow-2g' || type === '2g' || downlink < 0.115 || rtt > 1000) {
statusText = i18n.getMessage('initialSetupNetworkInfoStatusSlow');
} else {
statusText = i18n.getMessage('initialSetupNetworkInfoStatusOnline');
}
$('.network-status').text(statusText);
$('.network-type').text(navigator.connection.effectiveType);
$('.network-downlink').text(`${navigator.connection.downlink} Mbps`);
$('.network-rtt').text(navigator.connection.rtt);
}
prepareDisarmFlags(); prepareDisarmFlags();
showSensorInfo(); showSensorInfo();
showFirmwareInfo(); showFirmwareInfo();
showNetworkStatus();
// Show Sonar info box if sensor exist // Show Sonar info box if sensor exist
if (!have_sensor(FC.CONFIG.activeSensors, 'sonar')) { if (!have_sensor(FC.CONFIG.activeSensors, 'sonar')) {

View file

@ -0,0 +1,9 @@
import { get as getConfig } from "../ConfigStorage";
export function ispConnected() {
const connected = navigator.onLine;
const isMetered = getConfig('meteredConnection').meteredConnection;
return connected && !isMetered;
}

View file

@ -17,6 +17,12 @@
</div> </div>
<span class="freelabel" i18n="rememberLastTab"></span> <span class="freelabel" i18n="rememberLastTab"></span>
</div> </div>
<div class="meteredConnection margin-bottom">
<div>
<input type="checkbox" class="toggle" />
</div>
<span class="freelabel" i18n="meteredConnection"></span>
</div>
<div class="analyticsOptOut margin-bottom"> <div class="analyticsOptOut margin-bottom">
<div> <div>
<input type="checkbox" class="toggle" /> <input type="checkbox" class="toggle" />

View file

@ -235,6 +235,34 @@
</table> </table>
</div> </div>
</div> </div>
<div class="gui_box grey">
<div class="gui_box_titlebar">
<div class="spacer_box_title" i18n="initialSetupNetworkInfo"></div>
<div class="helpicon cf_tip" i18n_title="initialSetupNetworkInfoHelp"></div>
</div>
<div class="spacer_box">
<table width="100%" border="0" cellpadding="0" cellspacing="0" class="cf_table" role="presentation">
<tbody>
<tr>
<td id="network-status" i18n="initialSetupNetworkInfoStatus"></td>
<td class="network-status"></td>
</tr>
<tr>
<td id="network-type" i18n="initialSetupNetworkType"></td>
<td class="network-type"></td>
</tr>
<tr>
<td id="network-downlink" i18n="initialSetupNetworkDownlink"></td>
<td class="network-downlink"></td>
</tr>
<tr>
<td id="network-rtt" i18n="initialSetupNetworkRtt"></td>
<td class="network-rtt"></td>
</tr>
</tbody>
</table>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>