import GUI from "./gui"; import FC from "./fc"; import { i18n } from "./localization"; import { generateVirtualApiVersions } from './utils/common'; import { get as getConfig } from "./ConfigStorage"; import serial from "./serial"; import MdnsDiscovery from "./mdns_discovery"; const TIMEOUT_CHECK = 500 ; // With 250 it seems that it produces a memory leak and slowdown in some versions, reason unknown export const usbDevices = { filters: [ {'vendorId': 1155, 'productId': 57105}, // STM Device in DFU Mode || Digital Radio in USB mode {'vendorId': 10473, 'productId': 393}, // GD32 DFU Bootloader ] }; const PortHandler = new function () { this.initialPorts = false; this.port_detected_callbacks = []; this.port_removed_callbacks = []; this.dfu_available = false; this.port_available = false; this.showAllSerialDevices = false; this.showVirtualMode = false; }; PortHandler.initialize = function () { const self = this; const portPickerElementSelector = "div#port-picker #port"; self.portPickerElement = $(portPickerElementSelector); self.selectList = document.querySelector(portPickerElementSelector); self.initialWidth = self.selectList.offsetWidth + 12; // fill dropdown with version numbers generateVirtualApiVersions(); this.reinitialize(); // just to prevent code redundancy }; PortHandler.reinitialize = function () { this.initialPorts = false; if (this.usbCheckLoop) { clearTimeout(this.usbCheckLoop); } this.showVirtualMode = getConfig('showVirtualMode').showVirtualMode; this.showAllSerialDevices = getConfig('showAllSerialDevices').showAllSerialDevices; this.check(); // start listening, check after TIMEOUT_CHECK ms }; PortHandler.check = function () { const self = this; if (!self.port_available) { self.check_usb_devices(); } if (!self.dfu_available) { self.check_serial_devices(); } self.usbCheckLoop = setTimeout(() => { self.check(); }, TIMEOUT_CHECK); }; PortHandler.check_serial_devices = function () { const self = this; serial.getDevices(function(cp) { let currentPorts = [ ...cp, ...(MdnsDiscovery.mdnsBrowser.services?.filter(s => s.txt.vendor === 'elrs' && s.txt.type === 'rx' && s.ready === true) .map(s => s.addresses.map(a => ({ path: `tcp://${a}`, displayName: `${s.txt.target} - ${s.txt.version}`, fqdn: s.fqdn, vendorId: 0, productId: 0, }))).flat() ?? []), ].filter(Boolean); // auto-select port (only during initialization) if (!self.initialPorts) { currentPorts = self.updatePortSelect(currentPorts); self.selectPort(currentPorts); self.initialPorts = currentPorts; GUI.updateManualPortVisibility(); } else { self.removePort(currentPorts); self.detectPort(currentPorts); } }); }; PortHandler.check_usb_devices = function (callback) { const self = this; chrome.usb.getDevices(usbDevices, function (result) { 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}`); } else { usbText = "DFU"; } self.portPickerElement.append($('