Skip to content

Commit 4a04960

Browse files
committed
Cleanup serial
1 parent 292093a commit 4a04960

File tree

4 files changed

+68
-273
lines changed

4 files changed

+68
-273
lines changed

src/js/main.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import "./jqueryPlugins";
22
import $ from "jquery";
33
import "../components/init.js";
44
import { gui_log } from "./gui_log.js";
5-
// same, msp seems to be everywhere used from global scope
6-
import "./msp/MSPHelper.js";
75
import { i18n } from "./localization.js";
86
import GUI, { TABS } from "./gui.js";
97
import { get as getConfig, set as setConfig } from "./ConfigStorage.js";
@@ -184,13 +182,18 @@ function startProcess() {
184182
return;
185183
}
186184

187-
if (GUI.allowedTabs.indexOf(tab) < 0 && tab === "firmware_flasher") {
188-
if (GUI.connected_to || GUI.connecting_to) {
189-
$("a.connection_button__link").click();
185+
if (!GUI.allowedTabs.includes(tab)) {
186+
if (tab === "firmware_flasher") {
187+
// Special handling for firmware flasher tab
188+
if (GUI.connected_to || GUI.connecting_to) {
189+
$("a.connection_button__link").trigger("click");
190+
}
191+
// This line is required but it triggers opening the firmware flasher tab again
192+
$("a.firmware_flasher_button__link").trigger("click");
193+
} else {
194+
gui_log(i18n.getMessage("tabSwitchUpgradeRequired", [tabName]));
195+
return;
190196
}
191-
} else if (GUI.allowedTabs.indexOf(tab) < 0) {
192-
gui_log(i18n.getMessage("tabSwitchUpgradeRequired", [tabName]));
193-
return;
194197
}
195198

196199
GUI.tab_switch_in_progress = true;

src/js/protocols/WebSerial.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -378,15 +378,6 @@ class WebSerial extends EventTarget {
378378
return { bytesSent: 0 };
379379
}
380380
}
381-
382-
/**
383-
* Clean up resources when the protocol is no longer needed
384-
*/
385-
cleanup() {
386-
if (this.connected) {
387-
this.disconnect();
388-
}
389-
}
390381
}
391382

392383
// Export the class itself, not an instance

src/js/serial.js

Lines changed: 57 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -15,83 +15,40 @@ class Serial extends EventTarget {
1515

1616
this.logHead = "[SERIAL]";
1717

18-
// Initialize the available protocols
19-
this._webSerial = new WebSerial();
20-
this._webBluetooth = new WebBluetooth();
21-
this._webSocket = new Websocket();
22-
this._virtual = new VirtualSerial();
23-
24-
// Update protocol map to use consistent naming
25-
this._protocolMap = {
26-
webserial: this._webSerial,
27-
webbluetooth: this._webBluetooth,
28-
websocket: this._webSocket,
29-
virtual: this._virtual,
30-
};
18+
// Initialize protocols with metadata for easier lookup
19+
this._protocols = [
20+
{ name: "webserial", instance: new WebSerial() },
21+
{ name: "webbluetooth", instance: new WebBluetooth() },
22+
{ name: "websocket", instance: new Websocket() },
23+
{ name: "virtual", instance: new VirtualSerial() },
24+
];
3125

3226
// Forward events from all protocols to the Serial class
3327
this._setupEventForwarding();
3428
}
3529

36-
// Add a getter method to safely access the protocol map
37-
_getProtocolByType(type) {
38-
if (!type) {
39-
return this._protocol;
40-
}
41-
42-
const protocol = this._protocolMap[type.toLowerCase()];
43-
44-
if (!protocol) {
45-
console.warn(`${this.logHead} Unknown protocol type: ${type}`);
46-
}
47-
48-
return protocol || null;
49-
}
50-
51-
/**
52-
* Get the protocol type as a string
53-
* @param {Object} protocol - Protocol instance
54-
* @returns {string} - Protocol type name
55-
*/
56-
_getProtocolType(protocol) {
57-
if (protocol === this._webSerial) {
58-
return "webserial";
59-
}
60-
if (protocol === this._webBluetooth) {
61-
return "webbluetooth";
62-
}
63-
if (protocol === this._webSocket) {
64-
return "websocket";
65-
}
66-
if (protocol === this._virtual) {
67-
return "virtual";
68-
}
69-
return "unknown";
70-
}
71-
7230
/**
7331
* Set up event forwarding from all protocols to the Serial class
7432
*/
7533
_setupEventForwarding() {
76-
const protocols = [this._webSerial, this._webBluetooth, this._webSocket, this._virtual];
7734
const events = ["addedDevice", "removedDevice", "connect", "disconnect", "receive"];
7835

79-
protocols.forEach((protocol) => {
80-
if (protocol && typeof protocol.addEventListener === "function") {
36+
this._protocols.forEach(({ name, instance }) => {
37+
if (typeof instance?.addEventListener === "function") {
8138
events.forEach((eventType) => {
82-
protocol.addEventListener(eventType, (event) => {
39+
instance.addEventListener(eventType, (event) => {
8340
let newDetail;
8441
if (event.type === "receive") {
8542
// For 'receive' events, we need to handle the data differently
8643
newDetail = {
8744
data: event.detail,
88-
protocolType: this._getProtocolType(protocol),
45+
protocolType: name,
8946
};
9047
} else {
9148
// For other events, we can use the detail directly
9249
newDetail = {
9350
...event.detail,
94-
protocolType: this._getProtocolType(protocol),
51+
protocolType: name,
9552
};
9653
}
9754

@@ -111,47 +68,25 @@ class Serial extends EventTarget {
11168

11269
/**
11370
* Selects the appropriate protocol based on port path
114-
* @param {string|null} portPath - Optional port path to determine protocol
115-
* @param {boolean} forceDisconnect - Whether to force disconnect from current protocol
71+
* @param {string|null} portPath - Port path to determine protocol
11672
*/
117-
selectProtocol(portPath = null, forceDisconnect = true) {
73+
selectProtocol(portPath) {
11874
// Determine which protocol to use based on port path
119-
let newProtocol;
120-
121-
if (portPath) {
122-
// Select protocol based on port path
123-
if (portPath === "virtual") {
124-
console.log(`${this.logHead} Using virtual protocol (based on port path)`);
125-
newProtocol = this._virtual;
126-
} else if (portPath === "manual" || /^(tcp|ws):\/\/([A-Za-z0-9.-]+)(?::(\d+))?$/.test(portPath)) {
127-
console.log(`${this.logHead} Using websocket protocol (based on port path)`);
128-
newProtocol = this._webSocket;
129-
} else if (portPath.startsWith("bluetooth")) {
130-
console.log(`${this.logHead} Using bluetooth protocol (based on port path: ${portPath})`);
131-
newProtocol = this._webBluetooth;
132-
} else {
133-
console.log(`${this.logHead} Using web serial protocol (based on port path: ${portPath})`);
134-
newProtocol = this._webSerial;
135-
}
136-
}
137-
138-
// If we're switching to a different protocol
139-
if (this._protocol !== newProtocol) {
140-
// Clean up previous protocol if exists
141-
if (this._protocol && forceDisconnect) {
142-
// Disconnect if connected
143-
if (this._protocol.connected) {
144-
console.log(`${this.logHead} Disconnecting from current protocol before switching`);
145-
this._protocol.disconnect();
146-
}
147-
}
148-
149-
// Set new protocol
150-
this._protocol = newProtocol;
151-
console.log(`${this.logHead} Protocol switched successfully to:`, this._protocol);
75+
let protocol;
76+
77+
// Select protocol based on port path. Default to webSerial for
78+
// typical serial device identifiers (e.g., COM1, /dev/ttyUSB0).
79+
if (portPath === "virtual") {
80+
protocol = this._protocols.find((p) => p.name === "virtual")?.instance;
81+
} else if (portPath === "manual" || /^(tcp|ws):\/\/([A-Za-z0-9.-]+)(?::(\d+))?$/.test(portPath)) {
82+
protocol = this._protocols.find((p) => p.name === "websocket")?.instance;
83+
} else if (portPath.startsWith("bluetooth")) {
84+
protocol = this._protocols.find((p) => p.name === "webbluetooth")?.instance;
85+
} else {
86+
protocol = this._protocols.find((p) => p.name === "webserial")?.instance;
15287
}
15388

154-
return this._protocol;
89+
return protocol;
15590
}
15691

15792
/**
@@ -161,38 +96,16 @@ class Serial extends EventTarget {
16196
*/
16297
async connect(path, options, callback) {
16398
// Select the appropriate protocol based directly on the port path
164-
this.selectProtocol(path);
165-
166-
if (!this._protocol) {
167-
console.error(`${this.logHead} No valid protocol selected for connection`);
168-
return false;
169-
}
170-
171-
// Check if already connected
172-
if (this._protocol.connected) {
173-
console.warn(`${this.logHead} Protocol already connected, not connecting again`);
174-
175-
// If we're already connected to the requested port, return success
176-
const connectedPort = this._protocol.getConnectedPort?.();
177-
if (connectedPort && connectedPort.path === path) {
178-
console.log(`${this.logHead} Already connected to the requested port`);
179-
return true;
180-
}
181-
182-
// If we're connected to a different port, disconnect first
183-
console.log(`${this.logHead} Connected to a different port, disconnecting first`);
184-
const success = await this.disconnect();
185-
if (!success) {
186-
console.error(`${this.logHead} Failed to disconnect before reconnecting`);
187-
return false;
188-
}
189-
190-
console.log(`${this.logHead} Reconnecting to new port:`, path);
191-
return this._protocol.connect(path, options, callback);
99+
let result = false;
100+
try {
101+
this._protocol = this.selectProtocol(path);
102+
result = await this._protocol.connect(path, options, callback);
103+
} catch (error) {
104+
console.error(`${this.logHead} Error during connection:`, error);
105+
} finally {
106+
callback && callback(result);
107+
return result;
192108
}
193-
194-
console.log(`${this.logHead} Connecting to port:`, path, "with options:", options);
195-
return this._protocol.connect(path, options, callback);
196109
}
197110

198111
/**
@@ -201,34 +114,14 @@ class Serial extends EventTarget {
201114
* @returns {Promise<boolean>} - Promise resolving to true if disconnection was successful
202115
*/
203116
async disconnect(callback) {
204-
// Return immediately if no protocol is selected
205-
if (!this._protocol) {
206-
console.warn(`${this.logHead} No protocol selected, nothing to disconnect`);
207-
if (callback) callback(false);
208-
return false;
209-
}
210-
117+
let result = false;
211118
try {
212-
// Handle case where we're already disconnected
213-
if (!this._protocol.connected) {
214-
console.log(`${this.logHead} Already disconnected, performing cleanup`);
215-
if (callback) {
216-
callback(true);
217-
}
218-
return true;
219-
}
220-
221-
// Create a promise that will resolve/reject based on the protocol's disconnect result
222-
const success = await this._protocol.disconnect();
223-
224-
if (callback) callback(success);
225-
return success;
119+
result = await this._protocol?.disconnect();
226120
} catch (error) {
227121
console.error(`${this.logHead} Error during disconnect:`, error);
228-
if (callback) {
229-
callback(false);
230-
}
231-
return Promise.resolve(false);
122+
} finally {
123+
callback && callback(result);
124+
return result;
232125
}
233126
}
234127

@@ -253,7 +146,7 @@ class Serial extends EventTarget {
253146
async getDevices(protocolType = null) {
254147
try {
255148
// Get the appropriate protocol
256-
const targetProtocol = this._getProtocolByType(protocolType);
149+
const targetProtocol = this._protocols.find((p) => p.name === protocolType?.toLowerCase())?.instance;
257150

258151
if (!targetProtocol) {
259152
console.warn(`${this.logHead} No valid protocol for getting devices`);
@@ -265,7 +158,7 @@ class Serial extends EventTarget {
265158
return [];
266159
}
267160

268-
return targetProtocol.getDevices() || [];
161+
return targetProtocol.getDevices?.() || [];
269162
} catch (error) {
270163
console.error(`${this.logHead} Error getting devices:`, error);
271164
return [];
@@ -278,25 +171,15 @@ class Serial extends EventTarget {
278171
* @param {string} protocolType - Optional protocol type ('serial', 'bluetooth', etc.)
279172
* @returns {Promise<Object>} - Promise resolving to the selected device
280173
*/
281-
async requestPermissionDevice(showAllDevices = false, protocolType = null) {
174+
async requestPermissionDevice(showAllDevices = false, protocolType) {
175+
let result = false;
282176
try {
283-
// Get the appropriate protocol
284-
const targetProtocol = this._getProtocolByType(protocolType);
285-
286-
if (!targetProtocol) {
287-
console.warn(`${this.logHead} No valid protocol for permission request`);
288-
return null;
289-
}
290-
291-
if (typeof targetProtocol.requestPermissionDevice !== "function") {
292-
console.error(`${this.logHead} Selected protocol does not support permission requests`);
293-
return null;
294-
}
295-
296-
return targetProtocol.requestPermissionDevice(showAllDevices);
177+
const targetProtocol = this._protocols.find((p) => p.name === protocolType?.toLowerCase())?.instance;
178+
result = await targetProtocol.requestPermissionDevice(showAllDevices);
297179
} catch (error) {
298180
console.error(`${this.logHead} Error requesting device permission:`, error);
299-
return null;
181+
} finally {
182+
return result;
300183
}
301184
}
302185

@@ -311,7 +194,14 @@ class Serial extends EventTarget {
311194
* Get connection status
312195
*/
313196
get connected() {
314-
return this._protocol ? this._protocol.connected : false;
197+
return this._protocol?.connected || false;
198+
}
199+
200+
/**
201+
* Get connectionId
202+
*/
203+
get connectionId() {
204+
return this._protocol?.connectionId || null;
315205
}
316206
}
317207

0 commit comments

Comments
 (0)