@@ -2,7 +2,6 @@ import { get as getConfig } from "./ConfigStorage";
22import { EventBus } from "../components/eventBus" ;
33import { serial } from "./serial.js" ;
44import WEBUSBDFU from "./protocols/webusbdfu" ;
5- import WebBluetooth from "./protocols/WebBluetooth.js" ;
65import { reactive } from "vue" ;
76
87const DEFAULT_PORT = "noselection" ;
@@ -35,44 +34,42 @@ const PortHandler = new (function () {
3534} ) ( ) ;
3635
3736PortHandler . initialize = function ( ) {
38- EventBus . $on ( "ports-input:request-permission-bluetooth" , this . askBluetoothPermissionPort . bind ( this ) ) ;
39- EventBus . $on ( "ports-input:request-permission" , this . askSerialPermissionPort . bind ( this ) ) ;
37+ EventBus . $on ( "ports-input:request-permission-bluetooth" , ( ) => this . requestDevicePermission ( "bluetooth" ) ) ;
38+ EventBus . $on ( "ports-input:request-permission" , ( ) => this . requestDevicePermission ( "serial" ) ) ;
4039 EventBus . $on ( "ports-input:change" , this . onChangeSelectedPort . bind ( this ) ) ;
4140
4241 // Use serial for all protocol events
4342 serial . addEventListener ( "addedDevice" , ( event ) => {
4443 const detail = event . detail ;
4544
46- // Determine the device type based on its properties
4745 if ( detail ?. path ?. startsWith ( "bluetooth" ) ) {
48- this . addedBluetoothDevice ( detail ) ;
49- } else if ( detail ?. path ?. startsWith ( "usb_" ) ) {
50- this . addedUsbDevice ( detail ) ;
46+ this . handleDeviceAdded ( detail , "bluetooth" ) ;
5147 } else {
52- this . addedSerialDevice ( detail ) ;
48+ this . handleDeviceAdded ( detail , "serial" ) ;
5349 }
5450 } ) ;
5551
5652 serial . addEventListener ( "removedDevice" , ( event ) => {
57- const detail = event . detail ;
58-
59- // Determine the device type based on its properties
60- if ( detail ?. path ?. startsWith ( "bluetooth" ) ) {
61- this . removedBluetoothDevice ( detail ) ;
62- } else if ( detail ?. path ?. startsWith ( "usb_" ) ) {
63- // Handle USB device removal if needed
64- } else {
65- this . removedSerialDevice ( detail ) ;
66- }
53+ this . removedSerialDevice ( event . detail ) ;
6754 } ) ;
6855
6956 // Keep USB listener separate as it's not part of the serial protocols
7057 WEBUSBDFU . addEventListener ( "addedDevice" , ( event ) => this . addedUsbDevice ( event . detail ) ) ;
7158
72- // Initial device discovery
73- this . addedSerialDevice ( ) ;
74- this . addedBluetoothDevice ( ) ;
75- this . addedUsbDevice ( ) ;
59+ // Initial device discovery using the serial facade
60+ this . refreshAllDeviceLists ( ) ;
61+ } ;
62+
63+ // Refactored refreshAllDeviceLists to use updateDeviceList
64+ PortHandler . refreshAllDeviceLists = async function ( ) {
65+ // Update all device lists in parallel
66+ return Promise . all ( [
67+ this . updateDeviceList ( "serial" ) ,
68+ this . updateDeviceList ( "bluetooth" ) ,
69+ this . updateDeviceList ( "usb" ) ,
70+ ] ) . then ( ( ) => {
71+ this . selectActivePort ( ) ;
72+ } ) ;
7673} ;
7774
7875PortHandler . setShowVirtualMode = function ( showVirtualMode ) {
@@ -89,44 +86,40 @@ PortHandler.setShowAllSerialDevices = function (showAllSerialDevices) {
8986 this . showAllSerialDevices = showAllSerialDevices ;
9087} ;
9188
92- PortHandler . addedSerialDevice = function ( device ) {
93- this . updateCurrentSerialPortsList ( ) . then ( ( ) => {
94- const selectedPort = this . selectActivePort ( device ) ;
95- if ( ! device || selectedPort === device . path ) {
96- // Send this event when the port handler auto selects a new device
97- EventBus . $emit ( "port-handler:auto-select-serial-device" , selectedPort ) ;
98- }
99- } ) ;
100- } ;
101-
10289PortHandler . removedSerialDevice = function ( device ) {
103- this . updateCurrentSerialPortsList ( ) . then ( ( ) => {
104- if ( this . portPicker . selectedPort === device . path ) {
90+ console . log ( `${ this . logHead } Device removal event received:` , device ) ;
91+
92+ // Get device path safely
93+ const devicePath = device ?. path || ( typeof device === "string" ? device : null ) ;
94+
95+ if ( ! devicePath ) {
96+ console . warn ( `${ this . logHead } Device removal event missing path information` , device ) ;
97+ // Still update ports, but don't try to use the undefined path
98+ this . updateDeviceList ( "serial" ) . then ( ( ) => {
10599 this . selectActivePort ( ) ;
106- }
107- } ) ;
108- } ;
100+ } ) ;
101+ return ;
102+ }
109103
110- PortHandler . addedBluetoothDevice = function ( device ) {
111- this . updateCurrentBluetoothPortsList ( ) . then ( ( ) => {
112- const selectedPort = this . selectActivePort ( device ) ;
113- if ( ! device || selectedPort === device . path ) {
114- // Send this event when the port handler auto selects a new device
115- EventBus . $emit ( "port-handler:auto-select-bluetooth-device" , selectedPort ) ;
116- }
117- } ) ;
118- } ;
104+ // Update the appropriate ports list based on the device type
105+ const updatePromise = devicePath . startsWith ( "bluetooth" )
106+ ? this . updateDeviceList ( "bluetooth" )
107+ : this . updateDeviceList ( "serial" ) ;
119108
120- PortHandler . removedBluetoothDevice = function ( device ) {
121- this . updateCurrentBluetoothPortsList ( ) . then ( ( ) => {
122- if ( this . portPicker . selectedPort === device . path ) {
109+ const wasSelectedPort = this . portPicker . selectedPort === devicePath ;
110+
111+ updatePromise . then ( ( ) => {
112+ if ( wasSelectedPort ) {
123113 this . selectActivePort ( ) ;
114+
115+ // Send event for UI components that might need to update
116+ EventBus . $emit ( "port-handler:device-removed" , devicePath ) ;
124117 }
125118 } ) ;
126119} ;
127120
128121PortHandler . addedUsbDevice = function ( device ) {
129- this . updateCurrentUsbPortsList ( ) . then ( ( ) => {
122+ this . updateDeviceList ( "usb" ) . then ( ( ) => {
130123 const selectedPort = this . selectActivePort ( device ) ;
131124 if ( ! device || selectedPort === device . path ) {
132125 // Send this event when the port handler auto selects a new device
@@ -139,30 +132,28 @@ PortHandler.onChangeSelectedPort = function (port) {
139132 this . portPicker . selectedPort = port ;
140133} ;
141134
142- PortHandler . updateCurrentSerialPortsList = async function ( ) {
143- const ports = await serial . getDevices ( ) ;
144- const orderedPorts = this . sortPorts ( ports ) ;
145- this . portAvailable = orderedPorts . length > 0 ;
146- console . log ( `${ this . logHead } Found serial port` , orderedPorts ) ;
147- this . currentSerialPorts = [ ...orderedPorts ] ;
148- } ;
149-
150- PortHandler . updateCurrentUsbPortsList = async function ( ) {
151- const ports = await WEBUSBDFU . getDevices ( ) ;
152- const orderedPorts = this . sortPorts ( ports ) ;
153- this . dfuAvailable = orderedPorts . length > 0 ;
154- console . log ( `${ this . logHead } Found DFU port` , orderedPorts ) ;
155- this . currentUsbPorts = [ ...orderedPorts ] ;
156- } ;
157-
158- PortHandler . updateCurrentBluetoothPortsList = async function ( ) {
159- if ( WebBluetooth . bluetooth ) {
160- const ports = await WebBluetooth . getDevices ( ) ;
161- const orderedPorts = this . sortPorts ( ports ) ;
162- this . bluetoothAvailable = orderedPorts . length > 0 ;
163- console . log ( `${ this . logHead } Found bluetooth port` , orderedPorts ) ;
164- this . currentBluetoothPorts = [ ...orderedPorts ] ;
165- }
135+ /**
136+ * Request permission for a device of the specified type
137+ * @param {string } deviceType - Type of device ('serial' or 'bluetooth')
138+ */
139+ PortHandler . requestDevicePermission = function ( deviceType = "serial" ) {
140+ // Determine whether to show all devices based on device type
141+ const showAllDevices = deviceType === "serial" ? this . showAllSerialDevices : false ;
142+
143+ // Use serial facade to request permission
144+ serial
145+ . requestPermissionDevice ( showAllDevices , deviceType )
146+ . then ( ( port ) => {
147+ if ( port ) {
148+ console . log ( `${ this . logHead } Permission granted for ${ deviceType } device:` , port ) ;
149+ this . selectActivePort ( port ) ;
150+ } else {
151+ console . log ( `${ this . logHead } Permission request cancelled or failed for ${ deviceType } ` ) ;
152+ }
153+ } )
154+ . catch ( ( error ) => {
155+ console . error ( `${ this . logHead } Error requesting permission for ${ deviceType } :` , error ) ;
156+ } ) ;
166157} ;
167158
168159PortHandler . sortPorts = function ( ports ) {
@@ -174,31 +165,11 @@ PortHandler.sortPorts = function (ports) {
174165 } ) ;
175166} ;
176167
177- PortHandler . askBluetoothPermissionPort = function ( ) {
178- if ( WebBluetooth . bluetooth ) {
179- WebBluetooth . requestPermissionDevice ( ) . then ( ( port ) => {
180- // When giving permission to a new device, the port is selected in the handleNewDevice method, but if the user
181- // selects a device that had already permission, or cancels the permission request, we need to select the port
182- // so do it here too
183- this . selectActivePort ( port ) ;
184- } ) ;
185- }
186- } ;
187-
188- PortHandler . askSerialPermissionPort = function ( ) {
189- serial . requestPermissionDevice ( this . showAllSerialDevices ) . then ( ( port ) => {
190- // When giving permission to a new device, the port is selected in the handleNewDevice method, but if the user
191- // selects a device that had already permission, or cancels the permission request, we need to select the port
192- // so do it here too
193- this . selectActivePort ( port ) ;
194- } ) ;
195- } ;
196-
197- PortHandler . selectActivePort = function ( suggestedDevice ) {
168+ PortHandler . selectActivePort = function ( suggestedDevice = false ) {
198169 const deviceFilter = [ "AT32" , "CP210" , "SPR" , "STM" ] ;
199170 let selectedPort ;
200171
201- // Return the same that is connected to serial
172+ // First check for active connections
202173 if ( serial . connected ) {
203174 selectedPort = this . currentSerialPorts . find ( ( device ) => device === serial . getConnectedPort ( ) ) ;
204175 }
@@ -208,10 +179,22 @@ PortHandler.selectActivePort = function (suggestedDevice) {
208179 selectedPort = this . currentUsbPorts . find ( ( device ) => device === WEBUSBDFU . getConnectedPort ( ) ) ;
209180 }
210181
211- // Return the same that is connected to bluetooth
212- if ( WebBluetooth . device ) {
213- selectedPort = this . currentBluetoothPorts . find ( ( device ) => device === WebBluetooth . getConnectedPort ( ) ) ;
214- }
182+ // If there is a connection, return it
183+ // if (selectedPort) {
184+ // console.log(`${this.logHead} Using connected device: ${selectedPort.path}`);
185+ // selectedPort = selectedPort.path;
186+ // return selectedPort;
187+ // }
188+
189+ // If there is no connection, check for the last used device
190+ // Check if the device is already connected
191+ // if (this.portPicker.selectedPort && this.portPicker.selectedPort !== DEFAULT_PORT) {
192+ // selectedPort = this.currentSerialPorts.find((device) => device.path === this.portPicker.selectedPort);
193+ // if (selectedPort) {
194+ // console.log(`${this.logHead} Using previously selected device: ${selectedPort.path}`);
195+ // return selectedPort.path;
196+ // }
197+ // }
215198
216199 // Return the suggested device (the new device that has been detected)
217200 if ( ! selectedPort && suggestedDevice ) {
@@ -269,6 +252,81 @@ PortHandler.selectActivePort = function (suggestedDevice) {
269252 return selectedPort ;
270253} ;
271254
255+ // Create a unified handler for device addition
256+ PortHandler . handleDeviceAdded = function ( device , deviceType ) {
257+ if ( ! device ) {
258+ console . warn ( `${ this . logHead } Invalid ${ deviceType } device added event` ) ;
259+ return ;
260+ }
261+
262+ console . log ( `${ this . logHead } ${ deviceType } device added:` , device ) ;
263+
264+ // Update the appropriate device list
265+ const updatePromise =
266+ deviceType === "bluetooth" ? this . updateDeviceList ( "bluetooth" ) : this . updateDeviceList ( "serial" ) ;
267+
268+ updatePromise . then ( ( ) => {
269+ const selectedPort = this . selectActivePort ( device ) ;
270+
271+ if ( selectedPort === device . path ) {
272+ // Emit an event with the proper type for backward compatibility
273+ EventBus . $emit ( `port-handler:auto-select-${ deviceType } -device` , selectedPort ) ;
274+ }
275+ } ) ;
276+ } ;
277+
278+ /**
279+ * Update device list with common implementation
280+ * @param {string } deviceType - Type of device ('serial', 'bluetooth', 'usb')
281+ * @returns {Promise } - Promise that resolves after updating the ports list
282+ */
283+ PortHandler . updateDeviceList = async function ( deviceType ) {
284+ let ports = [ ] ;
285+
286+ try {
287+ switch ( deviceType ) {
288+ case "bluetooth" :
289+ ports = await serial . getDevices ( "bluetooth" ) ;
290+ break ;
291+ case "usb" :
292+ ports = await WEBUSBDFU . getDevices ( ) ;
293+ break ;
294+ case "serial" :
295+ default :
296+ ports = await serial . getDevices ( "serial" ) ;
297+ break ;
298+ }
299+
300+ // Sort the ports
301+ const orderedPorts = this . sortPorts ( ports ) ;
302+
303+ // Update the appropriate properties based on device type
304+ switch ( deviceType ) {
305+ case "bluetooth" :
306+ this . bluetoothAvailable = orderedPorts . length > 0 ;
307+ this . currentBluetoothPorts = [ ...orderedPorts ] ;
308+ console . log ( `${ this . logHead } Found bluetooth port(s)` , orderedPorts ) ;
309+ break ;
310+ case "usb" :
311+ this . dfuAvailable = orderedPorts . length > 0 ;
312+ this . currentUsbPorts = [ ...orderedPorts ] ;
313+ console . log ( `${ this . logHead } Found DFU port(s)` , orderedPorts ) ;
314+ break ;
315+ case "serial" :
316+ default :
317+ this . portAvailable = orderedPorts . length > 0 ;
318+ this . currentSerialPorts = [ ...orderedPorts ] ;
319+ console . log ( `${ this . logHead } Found serial port(s)` , orderedPorts ) ;
320+ break ;
321+ }
322+
323+ return orderedPorts ;
324+ } catch ( error ) {
325+ console . error ( `${ this . logHead } Error updating ${ deviceType } devices:` , error ) ;
326+ return [ ] ;
327+ }
328+ } ;
329+
272330// We need to explicit make it reactive. If not, Vue3 does not detect correctly changes in array properties
273331// like currentSerialPorts, currentUsbPorts, currentBluetoothPorts
274332export default reactive ( PortHandler ) ;
0 commit comments