mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-25 17:25:16 +03:00
Add websocket support and fix port override (#4187)
* Add websocket support * remove waitforconnection
This commit is contained in:
parent
6908b7efb8
commit
36ccc26acc
5 changed files with 182 additions and 17 deletions
|
@ -1,8 +1,7 @@
|
|||
<template>
|
||||
<div
|
||||
v-if="isManual"
|
||||
id="port-override-option"
|
||||
style="display: none"
|
||||
:style="{ display: isManual ? 'flex' : 'none' }"
|
||||
>
|
||||
<label
|
||||
for="port-override"
|
||||
|
@ -10,30 +9,40 @@
|
|||
<input
|
||||
id="port-override"
|
||||
type="text"
|
||||
value="/dev/rfcomm0"
|
||||
:value="value"
|
||||
@change="inputValueChanged($event)"
|
||||
></label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { set as setConfig } from '../../js/ConfigStorage';
|
||||
|
||||
import { set as setConfig } from "../../js/ConfigStorage";
|
||||
export default {
|
||||
props: {
|
||||
isManual: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: '/dev/rfcomm0',
|
||||
},
|
||||
isManual: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
inputValueChanged(event) {
|
||||
setConfig({'portOverride': event.target.value});
|
||||
this.$emit('input', event.target.value);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
#port-override-option {
|
||||
label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -11,6 +11,8 @@ const CONFIGURATOR = {
|
|||
|
||||
connectionValid: false,
|
||||
connectionValidCliOnly: false,
|
||||
bluetoothMode: false,
|
||||
manualMode: false,
|
||||
virtualMode: false,
|
||||
virtualApiVersion: '0.0.1',
|
||||
cliActive: false,
|
||||
|
|
132
src/js/protocols/websocket.js
Normal file
132
src/js/protocols/websocket.js
Normal file
|
@ -0,0 +1,132 @@
|
|||
class WebsocketSerial extends EventTarget {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.connected = false;
|
||||
this.connectionInfo = null;
|
||||
|
||||
this.bitrate = 0;
|
||||
this.bytesSent = 0;
|
||||
this.bytesReceived = 0;
|
||||
this.failed = 0;
|
||||
|
||||
this.logHead = "[WEBSOCKET] ";
|
||||
|
||||
this.address = "ws://localhost:5761";
|
||||
|
||||
this.ws = null;
|
||||
|
||||
this.connect = this.connect.bind(this);
|
||||
}
|
||||
|
||||
handleReceiveBytes(info) {
|
||||
this.bytesReceived += info.detail.byteLength;
|
||||
}
|
||||
|
||||
handleDisconnect() {
|
||||
this.disconnect();
|
||||
}
|
||||
|
||||
createPort(url) {
|
||||
this.address = url;
|
||||
return {
|
||||
path: url,
|
||||
displayName: `Betaflight SITL`,
|
||||
vendorId: 0,
|
||||
productId: 0,
|
||||
port: 0,
|
||||
};
|
||||
}
|
||||
|
||||
getConnectedPort() {
|
||||
return {
|
||||
path: this.address,
|
||||
displayName: `Betaflight SITL`,
|
||||
vendorId: 0,
|
||||
productId: 0,
|
||||
port: 0,
|
||||
};
|
||||
}
|
||||
|
||||
async getDevices() {
|
||||
return [];
|
||||
}
|
||||
|
||||
async blob2uint(blob) {
|
||||
const buffer = await new Response(blob).arrayBuffer();
|
||||
return new Uint8Array(buffer);
|
||||
}
|
||||
|
||||
async connect(path, options) {
|
||||
this.address = path;
|
||||
console.log(`${this.logHead} Connecting to ${this.address}`);
|
||||
|
||||
this.ws = new WebSocket(this.address, "wsSerial");
|
||||
let socket = this;
|
||||
|
||||
this.ws.onopen = function(e) {
|
||||
console.log(`${socket.logHead} Connected: `, e);
|
||||
socket.connected = true;
|
||||
socket.dispatchEvent(
|
||||
new CustomEvent("connect", { detail: {
|
||||
socketId: socket.address,
|
||||
}}),
|
||||
);
|
||||
};
|
||||
|
||||
this.ws.onclose = function(e) {
|
||||
console.log(`${socket.logHead} Connection closed: `, e);
|
||||
|
||||
socket.disconnect(() => {
|
||||
socket.dispatchEvent(new CustomEvent("disconnect", this.disconnect.bind(this)));
|
||||
});
|
||||
};
|
||||
|
||||
this.ws.onerror = function(e) {
|
||||
console.error(`${socket.logHead} Connection error: `, e);
|
||||
|
||||
socket.disconnect(() => {
|
||||
socket.dispatchEvent(new CustomEvent("disconnect", this.disconnect.bind(this)));
|
||||
});
|
||||
};
|
||||
|
||||
this.ws.onmessage = async function(msg) {
|
||||
let uint8Chunk = await socket.blob2uint(msg.data);
|
||||
socket.dispatchEvent(
|
||||
new CustomEvent("receive", { detail: uint8Chunk }),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
this.connected = false;
|
||||
this.bytesReceived = 0;
|
||||
this.bytesSent = 0;
|
||||
|
||||
if (this.ws) {
|
||||
try {
|
||||
this.ws.close();
|
||||
} catch (e) {
|
||||
console.error(`${this.logHead}Failed to close socket: ${e}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async send(data, cb) {
|
||||
if (this.ws) {
|
||||
try {
|
||||
this.ws.send(data);
|
||||
this.bytesSent += data.byteLength;
|
||||
}
|
||||
catch(e) {
|
||||
console.error(`${this.logHead}Failed to send data e: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
bytesSent: data.byteLength,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default new WebsocketSerial();
|
|
@ -107,7 +107,6 @@ function connectDisconnect() {
|
|||
GUI.configuration_loaded = false;
|
||||
|
||||
const baudRate = PortHandler.portPicker.selectedBauds;
|
||||
const selectedPort = portName;
|
||||
|
||||
if (!isConnected) {
|
||||
// prevent connection when we do not have permission
|
||||
|
@ -124,6 +123,7 @@ function connectDisconnect() {
|
|||
|
||||
CONFIGURATOR.virtualMode = selectedPort === 'virtual';
|
||||
CONFIGURATOR.bluetoothMode = selectedPort.startsWith('bluetooth');
|
||||
CONFIGURATOR.manualMode = selectedPort === 'manual';
|
||||
|
||||
if (CONFIGURATOR.virtualMode) {
|
||||
CONFIGURATOR.virtualApiVersion = PortHandler.portPicker.virtualMspVersion;
|
||||
|
@ -131,6 +131,16 @@ function connectDisconnect() {
|
|||
// Hack to get virtual working on the web
|
||||
serial = serialShim();
|
||||
serial.connect(onOpenVirtual);
|
||||
} else if (selectedPort === 'manual') {
|
||||
serial = serialShim();
|
||||
// Explicitly disconnect the event listeners before attaching the new ones.
|
||||
serial.removeEventListener('connect', connectHandler);
|
||||
serial.addEventListener('connect', connectHandler);
|
||||
|
||||
serial.removeEventListener('disconnect', disconnectHandler);
|
||||
serial.addEventListener('disconnect', disconnectHandler);
|
||||
|
||||
serial.connect(portName, { baudRate });
|
||||
} else {
|
||||
CONFIGURATOR.virtualMode = false;
|
||||
serial = serialShim();
|
||||
|
|
|
@ -1,6 +1,18 @@
|
|||
import CONFIGURATOR from "./data_storage";
|
||||
import serialWeb from "./webSerial.js";
|
||||
import BT from "./protocols/bluetooth.js";
|
||||
import websocketSerial from "./protocols/websocket.js";
|
||||
import virtualSerial from "./virtualSerial.js";
|
||||
|
||||
export let serialShim = () => CONFIGURATOR.virtualMode ? virtualSerial: CONFIGURATOR.bluetoothMode ? BT : serialWeb;
|
||||
export const serialShim = () => {
|
||||
if (CONFIGURATOR.virtualMode) {
|
||||
return virtualSerial;
|
||||
}
|
||||
if (CONFIGURATOR.manualMode) {
|
||||
return websocketSerial;
|
||||
}
|
||||
if (CONFIGURATOR.bluetoothMode) {
|
||||
return BT;
|
||||
}
|
||||
return serialWeb;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue