1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-25 01:05:15 +03:00

Feat/web virtual mode (#3882)

* feat: add virtual mode on web

* feat: only show msp virtual version on virtual mode selection

* feat: update port selection to update the options
This commit is contained in:
Tomas Chmelevskij 2024-04-28 19:51:41 +02:00 committed by GitHub
parent 8499939bdf
commit 18eb8dd1b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 116 additions and 165 deletions

View file

@ -0,0 +1,2 @@
import Vue from "vue";
export const EventBus = new Vue();

View file

@ -14,6 +14,7 @@ import BatteryIcon from "./quad-status/BatteryIcon.vue";
import FC from '../js/fc.js';
import MSP from '../js/msp.js';
import PortUsage from '../js/port_usage.js';
import PortPicker from './port-picker/PortPicker.vue';
import CONFIGURATOR from '../js/data_storage.js';
// Most of the global objects can go here at first.
@ -44,6 +45,7 @@ i18next.on('initialized', function() {
BetaflightLogo,
StatusBar,
BatteryIcon,
PortPicker,
},
data: betaflightModel,
});

View file

@ -5,6 +5,7 @@
>
<div class="dropdown dropdown-dark">
<select
id="firmware-version-dropdown"
class="dropdown-select"
:title="$t('virtualMSPVersion')"
>
@ -43,12 +44,12 @@ export default {
};
</script>
<style>
<style scoped>
#firmware-virtual-option {
height: 76px;
width: 180px;
margin-right: 15px;
margin-top: 16px;
margin-top: 0px;
display: none;
}
.dropdown {
@ -148,19 +149,6 @@ export default {
cursor: pointer;
}
/* Fix for IE 8 putting the arrows behind the select element. */
.lt-ie9 .dropdown {
z-index: 1;
}
.lt-ie9 .dropdown-select {
z-index: -1;
}
.lt-ie9 .dropdown-select:focus {
z-index: 3;
}
.dropdown-dark {
background: #636363; /* NEW2 */
background: #3e403f; /* NEW */

View file

@ -0,0 +1,30 @@
<template>
<div class="web-port-picker">
<FirmwareVirtualOption :is-virtual="port === 'virtual'" />
<PortsInput v-model="port" />
</div>
</template>
<script>
import FirmwareVirtualOption from "./FirmwareVirtualOption.vue";
import PortsInput from "./PortsInput.vue";
export default {
components: {
FirmwareVirtualOption,
PortsInput,
},
data() {
return {
port: 'manual',
};
},
};
</script>
<style scoped>
.web-port-picker {
display: flex;
margin-left: auto;
}
</style>

View file

@ -8,48 +8,21 @@
id="port"
class="dropdown-select"
:title="$t('firmwareFlasherManualPort')"
@value="value"
@input="$emit('input', $event.target.value)"
>
<option value="virtual">
{{ $t("portsSelectVirtual") }}
</option>
<option value="manual">
{{ $t("portsSelectManual") }}
</option>
<option
v-if="showVirtual"
value="virtual"
>
{{ $t("portsSelectVirtual") }}
</option>
</select>
</div>
<div id="auto-connect-and-baud">
<div id="auto-connect-switch">
<label style="display: flex; align-items: baseline">
<input
type="checkbox"
class="auto_connect"
title="Auto-Connect: Enabled - Configurator automatically tries to connect when new port is detected"
style="display: none"
data-switchery="true"
>
<span
class="switchery switchery-small"
:style="{
backgroundColor: isAutoConnect
? '#ffbb00'
: '#858585',
}"
>
<small
:style="{
left: isAutoConnect ? '10px' : '0px',
transition: 'ease-in-out 0.2s',
}"
@click="isAutoConnect = !isAutoConnect"
/></span>
<span
i18n="autoConnect"
class="auto_connect"
title="Auto-Connect: Enabled - Configurator automatically tries to connect when new port is detected"
>{{ $t("autoConnect") }}
</span>
</label>
</div>
<div id="baudselect">
<div class="dropdown dropdown-dark">
<select
@ -57,7 +30,6 @@
v-model="selectedBaudRate"
class="dropdown-select"
:title="$t('firmwareFlasherBaudRate')"
:disabled="isAutoConnect"
>
<option
v-for="baudRate in baudRates"
@ -74,10 +46,20 @@
</template>
<script>
import { get as getConfig } from '../../js/ConfigStorage';
import { EventBus } from '../eventBus';
export default {
props: {
value: {
type: String,
default: 'manual',
},
},
data() {
return {
isAutoConnect: false,
showVirtual: false,
selectedBaudRate: "115200",
baudRates: [
{ value: "1000000", label: "1000000" },
@ -96,6 +78,17 @@ export default {
],
};
},
mounted() {
EventBus.$on('config-storage:set', this.setShowVirtual);
},
destroyed() {
EventBus.$off('config-storage:set', this.setShowVirtual);
},
methods: {
setShowVirtual() {
this.showVirtual = getConfig('showVirtualMode').showVirtualMode;
},
},
};
</script>
<style scoped>
@ -173,55 +166,6 @@ export default {
float: right;
}
#auto-connect-switch {
width: 110px;
float: left;
margin-top: 4px;
margin-right: 20px;
}
.auto_connect {
color: var(--subtleAccent);
font-family: "Open Sans", "Segoe UI", Tahoma, sans-serif;
font-size: 12px;
}
.switchery {
height: 14px;
width: 45px;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
box-sizing: content-box;
background-clip: content-box;
cursor: pointer;
display: inline-block;
position: relative;
vertical-align: middle;
}
.switchery-small {
border-radius: 20px;
height: 10px;
width: 20px;
margin-right: 5px;
background-color: var(--switcherysecond);
transition: border 0.3s ease 0s, box-shadow 0.3s ease 0s,
background-color 0.5s ease 0s;
}
.switchery small {
background: #fff;
border-radius: 100%;
box-shadow: 0 1px 3px rgb(0 0 0 / 40%);
height: 10px;
width: 10px;
position: absolute;
top: 0;
}
#baudselect {
width: 80px;
float: right;

View file

@ -26,54 +26,7 @@
:firmware-id="FC.CONFIG.flightControllerIdentifier"
:hardware-id="FC.CONFIG.hardwareName"
></betaflight-logo>
<div id="port-picker">
<div id="port-override-option">
<label for="port-override">
<span i18n="portOverrideText">Port:</span>
<input id="port-override" type="text" value="/dev/rfcomm0"/>
</label>
</div>
<div id="firmware-virtual-option">
<div class="dropdown dropdown-dark">
<select id="firmware-version-dropdown" class="dropdown-select" i18n_title="virtualMSPVersion"></select>
</div>
</div>
<div id="portsinput" style="display: none">
<div class="dropdown dropdown-dark">
<select class="dropdown-select" id="port" i18n_title="firmwareFlasherManualPort">
<option value="loading" i18n="serialPortLoading">Loading</option>
<!-- port list gets generated here -->
</select>
</div>
<div id="auto-connect-and-baud">
<div id="auto-connect-switch">
<label>
<input class="auto_connect togglesmall" type="checkbox"/>
<span class="auto_connect" i18n="autoConnect"></span>
</label>
</div>
<div id="baudselect">
<div class="dropdown dropdown-dark">
<select class="dropdown-select" id="baud" i18n_title="firmwareFlasherBaudRate">
<option value="1000000">1000000</option>
<option value="500000">500000</option>
<option value="250000">250000</option>
<option value="115200" selected="selected">115200</option>
<option value="57600">57600</option>
<option value="38400">38400</option>
<option value="28800">28800</option>
<option value="19200">19200</option>
<option value="14400">14400</option>
<option value="9600">9600</option>
<option value="4800">4800</option>
<option value="2400">2400</option>
<option value="1200">1200</option>
</select>
</div>
</div>
</div>
</div>
</div>
<port-picker></port-picker>
<div class="header-wrapper">
<div id="quad-status_wrapper">
<battery-icon

View file

@ -1,3 +1,5 @@
import { EventBus } from "../components/eventBus";
/**
* Gets one or more items from localStorage
* @param {string | string[]} key string or array of strings
@ -43,6 +45,7 @@ export function set(input) {
tmpObj[element] = input[element];
try {
localStorage.setItem(element, JSON.stringify(tmpObj));
EventBus.$emit(`config-storage:set`, 'element');
} catch (e) {
console.error(e);
}

View file

@ -3,8 +3,9 @@ import CONFIGURATOR from "./data_storage.js";
import serialNWJS from "./serial.js";
import serialWeb from "./webSerial.js";
import { isWeb } from "./utils/isWeb.js";
import { serialShim } from "./serial_shim.js";
const serial = isWeb() ? serialWeb : serialNWJS;
const serial = serialShim();
const MSP = {
symbols: {

View file

@ -135,12 +135,18 @@ PortHandler.check_usb_devices = function (callback) {
self.portPickerElement.append($('<option/>', {
value: "DFU",
text: usbText,
/**
* @deprecated please avoid using `isDFU` and friends for new code.
*/
data: {isDFU: true},
}));
self.portPickerElement.append($('<option/>', {
value: 'manual',
text: i18n.getMessage('portsSelectManual'),
/**
* @deprecated please avoid using `isDFU` and friends for new code.
*/
data: {isManual: true},
}));
@ -153,7 +159,7 @@ PortHandler.check_usb_devices = function (callback) {
self.setPortsInputWidth();
self.dfu_available = false;
}
if (!$('option:selected', self.portPickerElement).data().isDFU) {
if ($('option:selected', self.portPickerElement).val() !== 'DFU') {
if (!(GUI.connected_to || GUI.connect_lock)) {
FC.resetState();
}
@ -282,6 +288,9 @@ PortHandler.updatePortSelect = function (ports) {
this.portPickerElement.append($("<option/>", {
value: ports[i].path,
text: portText,
/**
* @deprecated please avoid using `isDFU` and friends for new code.
*/
data: {isManual: false},
}));
}
@ -290,6 +299,9 @@ PortHandler.updatePortSelect = function (ports) {
this.portPickerElement.append($("<option/>", {
value: 'virtual',
text: i18n.getMessage('portsSelectVirtual'),
/**
* @deprecated please avoid using `isDFU` and friends for new code.
*/
data: {isVirtual: true},
}));
}
@ -297,6 +309,9 @@ PortHandler.updatePortSelect = function (ports) {
this.portPickerElement.append($("<option/>", {
value: 'manual',
text: i18n.getMessage('portsSelectManual'),
/**
* @deprecated please avoid using `isDFU` and friends for new code.
*/
data: {isManual: true},
}));

View file

@ -24,11 +24,10 @@ import CryptoES from "crypto-es";
import $ from 'jquery';
import BuildApi from "./BuildApi";
import serialNWJS from "./serial.js";
import serialWeb from "./webSerial.js";
import { isWeb } from "./utils/isWeb";
import { serialShim } from "./serial_shim.js";
const serial = isWeb() ? serialWeb : serialNWJS;
let serial = serialShim();
let mspHelper;
let connectionTimestamp;
@ -51,21 +50,25 @@ function disconnectHandler(event) {
export function initializeSerialBackend() {
GUI.updateManualPortVisibility = function() {
const selected_port = $('div#port-picker #port option:selected');
if (selected_port.data().isManual) {
if(isWeb()) {
return;
}
const selected_port = $('#port').val();
if (selected_port === 'manual') {
$('#port-override-option').show();
}
else {
$('#port-override-option').hide();
}
if (selected_port.data().isVirtual) {
if (selected_port === 'virtual') {
$('#firmware-virtual-option').show();
}
else {
$('#firmware-virtual-option').hide();
}
$('#auto-connect-and-baud').toggle(!selected_port.data().isDFU);
$('#auto-connect-and-baud').toggle(selected_port !== 'DFU');
};
GUI.updateManualPortVisibility();
@ -86,9 +89,9 @@ export function initializeSerialBackend() {
$("div.connect_controls a.connect").on('click', function () {
const selectedPort = $('div#port-picker #port option:selected');
const selectedPort = $('#port').val();
let portName;
if (selectedPort.data().isManual) {
if (selectedPort === 'manual') {
portName = $('#port-override').val();
} else {
portName = String($('div#port-picker #port').val());
@ -100,9 +103,9 @@ export function initializeSerialBackend() {
GUI.configuration_loaded = false;
const selected_baud = parseInt($('div#port-picker #baud').val());
const selectedPort = $('div#port-picker #port option:selected');
const selectedPort = $('#port').val();
if (selectedPort.data().isDFU) {
if (selectedPort === 'DFU') {
$('select#baud').hide();
} else if (portName !== '0') {
if (!isConnected) {
@ -113,13 +116,17 @@ export function initializeSerialBackend() {
$('div#port-picker #port, div#port-picker #baud, div#port-picker #delay').prop('disabled', true);
$('div.connect_controls div.connect_state').text(i18n.getMessage('connecting'));
const baudRate = parseInt($('div#port-picker #baud').val());
if (selectedPort.data().isVirtual) {
const baudRate = parseInt($('#baud').val());
if (selectedPort === 'virtual') {
CONFIGURATOR.virtualMode = true;
CONFIGURATOR.virtualApiVersion = $('#firmware-version-dropdown :selected').val();
CONFIGURATOR.virtualApiVersion = $('#firmware-version-dropdown').val();
// Hack to get virtual working on the web
serial = serialShim();
serial.connect('virtual', {}, onOpenVirtual);
} else if (isWeb()) {
CONFIGURATOR.virtualMode = false;
serial = serialShim();
// Explicitly disconnect the event listeners before attaching the new ones.
serial.removeEventListener('connect', connectHandler);
serial.addEventListener('connect', connectHandler);

6
src/js/serial_shim.js Normal file
View file

@ -0,0 +1,6 @@
import CONFIGURATOR from "./data_storage";
import serialNWJS from "./serial.js";
import serialWeb from "./webSerial.js";
import { isWeb } from "./utils/isWeb";
export let serialShim = () => CONFIGURATOR.virtualMode ? serialNWJS : isWeb() ? serialWeb : serialNWJS;