diff --git a/locales/en/messages.json b/locales/en/messages.json index 8a6195e8..7792f495 100644 --- a/locales/en/messages.json +++ b/locales/en/messages.json @@ -405,7 +405,9 @@ "serialUnrecoverable" : { "message": "Unrecoverable failure of serial connection, disconnecting..." }, - + "serialPortLoading" : { + "message": "Loading ..." + }, "usbDeviceOpened": { "message": "USB device successfully opened with ID: $1" }, diff --git a/src/js/port_handler.js b/src/js/port_handler.js index e79c621d..d1232cd0 100644 --- a/src/js/port_handler.js +++ b/src/js/port_handler.js @@ -1,6 +1,6 @@ 'use strict'; -const TIMEOUT_CHECK = 500; // With 250 it seems that it produces a memory leak and slowdown in some versions, reason unknown +const TIMEOUT_CHECK = 250 ; // With 250 it seems that it produces a memory leak and slowdown in some versions, reason unknown const usbDevices = { filters: [ {'vendorId': 1155, 'productId': 57105}, @@ -8,7 +8,7 @@ const usbDevices = { filters: [ ] }; const PortHandler = new function () { - this.initial_ports = false; + this.initialPorts = false; this.port_detected_callbacks = []; this.port_removed_callbacks = []; this.dfu_available = false; @@ -25,10 +25,11 @@ PortHandler.initialize = function () { PortHandler.check = function () { const self = this; - - self.check_serial_devices(); - self.check_usb_devices(); - + if (!GUI.connect_lock) { + self.check_serial_devices(); + } else { + self.check_usb_devices(); + } GUI.updateManualPortVisibility(); setTimeout(function () { @@ -40,29 +41,34 @@ PortHandler.check = function () { PortHandler.check_serial_devices = function () { const self = this; - serial.getDevices(function(current_ports) { - // port got removed or initial_ports wasn't initialized yet - if (self.array_difference(self.initial_ports, current_ports).length > 0 || !self.initial_ports) { - const removedPorts = self.array_difference(self.initial_ports, current_ports); + // disable Exit DFU Mode button + if (self.dfu_available){ + if (!$('option:selected', self.portPickerElement).data().isDFU) { + self.portPickerElement.trigger('change'); + self.dfu_available = false; + } + } - if (self.initial_ports !== false && removedPorts.length > 0) { + serial.getDevices(function(currentPorts) { + // auto-select last used port (only during initialization) + if (!self.initialPorts) { + currentPorts = self.updatePortSelect(currentPorts); + self.detectPort(currentPorts); + self.initialPorts = currentPorts; + } else if (self.array_difference(self.initialPorts, currentPorts).length > 0) { + // port got removed + const removedPorts = self.array_difference(self.initialPorts, currentPorts); + if (removedPorts.length > 0) { console.log(`PortHandler - Removed: ${JSON.stringify(removedPorts)}`); - } - - // disconnect "UI" if necessary - // Keep in mind that this routine can not fire during atmega32u4 reboot procedure !!! - if (GUI.connected_to) { - for (let i = 0; i < removedPorts.length; i++) { - if (removedPorts[i] === GUI.connected_to) { - $('div#header_btns a.connect').click(); + // disconnect "UI" - routine can't fire during atmega32u4 reboot procedure !!! + if (GUI.connected_to) { + for (let i = 0; i < removedPorts.length; i++) { + if (removedPorts[i] === GUI.connected_to) { + $('div#header_btns a.connect').click(); + } } } - } - - self.update_port_select(current_ports); - - // trigger callbacks (only after initialization) - if (self.initial_ports) { + // trigger callbacks (only after initialization) for (let i = (self.port_removed_callbacks.length - 1); i >= 0; i--) { const obj = self.port_removed_callbacks[i]; @@ -78,82 +84,52 @@ PortHandler.check_serial_devices = function () { self.port_removed_callbacks.splice(index, 1); } } - } - - // auto-select last used port (only during initialization) - if (!self.initial_ports) { - ConfigStorage.get('last_used_port', function (result) { - // if last_used_port was set, we try to select it - if (result.last_used_port) { - current_ports.forEach(function(port) { - if (port === result.last_used_port) { - console.log(`Selecting last used port: ${result.last_used_port}`); - - self.portPickerElement.val(result.last_used_port); - } - }); - } else { - console.log('Last used port wasn\'t saved "yet", auto-select disabled.'); - } - }); - } - - if (!self.initial_ports) { - // initialize - self.initial_ports = current_ports; - } else { for (let i = 0; i < removedPorts.length; i++) { - self.initial_ports.splice(self.initial_ports.indexOf(removedPorts[i]), 1); + self.initialPorts.splice(self.initialPorts.indexOf(removedPorts[i]), 1); + } + self.initialPorts = false; + } + } else { + // new port detected + const newPorts = self.array_difference(currentPorts, self.initialPorts); + if (typeof newPorts.length !== 'undefined') { + if (newPorts.length > 0) { + currentPorts = self.updatePortSelect(currentPorts); + console.log(`PortHandler - Found: ${JSON.stringify(newPorts)}`); + // select / highlight new port, if connected -> select connected port + if (GUI.connected_to) { + self.portPickerElement.val(GUI.connected_to); + } else if (newPorts.length === 1) { + self.portPickerElement.val(newPorts[0].path); + } else if (newPorts.length > 1) { + self.detectPort(currentPorts); + } else if (GUI.active_tab !== 'firmware_flasher' && GUI.auto_connect && !GUI.connecting_to) { + // start connect procedure. We need firmware flasher protection over here + GUI.timeout_add('auto-connect_timeout', function () { + $('div#header_btns a.connect').click(); + }, 100); // timeout so bus have time to initialize after being detected by the system + } + // trigger callbacks + for (let i = (self.port_detected_callbacks.length - 1); i >= 0; i--) { + const obj = self.port_detected_callbacks[i]; + + // remove timeout + clearTimeout(obj.timer); + + // trigger callback + obj.code(newPorts); + + // remove object from array + const index = self.port_detected_callbacks.indexOf(obj); + if (index > -1) { + self.port_detected_callbacks.splice(index, 1); + } + } + self.initialPorts = currentPorts; } } } - - // new port detected - const newPorts = self.array_difference(current_ports, self.initial_ports); - - if (newPorts.length) { - if (newPorts.length > 0) { - console.log(`PortHandler - Found: ${JSON.stringify(newPorts)}`); - } - - self.update_port_select(current_ports); - - // select / highlight new port, if connected -> select connected port - if (!GUI.connected_to) { - self.portPickerElement.val(newPorts[0].path); - } else { - self.portPickerElement.val(GUI.connected_to); - } - - // start connect procedure (if statement is valid) - if (GUI.active_tab !== 'firmware_flasher' && GUI.auto_connect && !GUI.connecting_to && !GUI.connected_to) { - // we need firmware flasher protection over here - GUI.timeout_add('auto-connect_timeout', function () { - $('div#header_btns a.connect').click(); - }, 100); // timeout so bus have time to initialize after being detected by the system - } - - // trigger callbacks - for (let i = (self.port_detected_callbacks.length - 1); i >= 0; i--) { - const obj = self.port_detected_callbacks[i]; - - // remove timeout - clearTimeout(obj.timer); - - // trigger callback - obj.code(newPorts); - - // remove object from array - const index = self.port_detected_callbacks.indexOf(obj); - if (index > -1) { - self.port_detected_callbacks.splice(index, 1); - } - } - - self.initial_ports = current_ports; - } }); - }; PortHandler.check_usb_devices = function (callback) { @@ -163,6 +139,7 @@ PortHandler.check_usb_devices = function (callback) { const dfuElement = self.portPickerElement.children("[value='DFU']"); if (result.length) { if (!dfuElement.length) { + self.portPickerElement.empty(); let usbText; if (result[0].productName) { usbText = (`DFU - ${result[0].productName}`); @@ -187,15 +164,20 @@ PortHandler.check_usb_devices = function (callback) { if(callback) { callback(self.dfu_available); } - - if (!$('option:selected', self.portPickerElement).data().isDFU) { - self.portPickerElement.trigger('change'); - } }); }; -PortHandler.update_port_select = function (ports) { +PortHandler.sortPorts = function(ports) { + return ports.sort(function(a, b) { + return a.path.localeCompare(b.path, window.navigator.language, { + numeric: true, + sensitivity: 'base', + }); + }); +}; +PortHandler.updatePortSelect = function (ports) { + ports = this.sortPorts(ports); this.portPickerElement.empty(); for (let i = 0; i < ports.length; i++) { @@ -219,6 +201,23 @@ PortHandler.update_port_select = function (ports) { data: {isManual: true}, })); i18n.localizePage(); + return ports; +}; + +PortHandler.detectPort = function(ports) { + const OS = GUI.operating_system; + for (let i = 0; i < ports.length; i++) { + const portName = ports[i].displayName; + if (portName) { + if (portName.includes('STM') || portName.includes('CP210')) { + const pathSelect = ports[i].path; + if (OS === 'Windows' || (OS !== 'Windows' && pathSelect.includes('tty'))) { + this.portPickerElement.val(pathSelect); + console.log(`Porthandler detected device ${portName} on port: ${pathSelect}`); + } + } + } + } }; PortHandler.port_detected = function(name, code, timeout, ignore_timeout) { diff --git a/src/js/serial_backend.js b/src/js/serial_backend.js index b236386f..93503ed6 100644 --- a/src/js/serial_backend.js +++ b/src/js/serial_backend.js @@ -223,19 +223,6 @@ function onOpen(openInfo) { GUI.log(i18n.getMessage('serialPortOpened', [openInfo.connectionId])); - // save selected port with chrome.storage if the port differs - ConfigStorage.get('last_used_port', function (result) { - if (result.last_used_port) { - if (result.last_used_port != GUI.connected_to) { - // last used port doesn't match the one found in local db, we will store the new one - ConfigStorage.set({'last_used_port': GUI.connected_to}); - } - } else { - // variable isn't stored yet, saving - ConfigStorage.set({'last_used_port': GUI.connected_to}); - } - }); - serial.onReceive.addListener(read_serial); setConnectionTimeout(); diff --git a/src/main.html b/src/main.html index e3b3731b..4365a640 100644 --- a/src/main.html +++ b/src/main.html @@ -169,7 +169,7 @@