import GUI, { TABS } from "./gui"; import FC from "./fc"; import { i18n } from "./localization"; import { get as getConfig } from "./ConfigStorage"; import MdnsDiscovery from "./mdns_discovery"; import { isWeb } from "./utils/isWeb"; import { usbDevices } from "./usb_devices"; import { serialShim } from "./serial_shim.js"; import { EventBus } from "../components/eventBus"; const serial = serialShim(); const DEFAULT_PORT = 'manual'; const DEFAULT_BAUDS = 115200; const PortHandler = new function () { this.currentPorts = []; this.initialPorts = false; this.portPicker = { selectedPort: DEFAULT_PORT, selectedBauds: DEFAULT_BAUDS, portOverride: "/dev/rfcomm0", virtualMspVersion: "1.46.0", }; this.portPickerDisabled = false; this.port_detected_callbacks = []; this.port_removed_callbacks = []; this.dfu_available = false; this.port_available = false; this.showAllSerialDevices = false; this.useMdnsBrowser = false; this.showVirtualMode = false; this.showManualMode = false; }; PortHandler.initialize = function () { EventBus.$on('ports-input:request-permission', this.askPermissionPort.bind(this)); EventBus.$on('ports-input:change', this.onChangeSelectedPort.bind(this)); serial.addEventListener("addedDevice", this.check_serial_devices.bind(this)); serial.addEventListener("removedDevice", this.check_serial_devices.bind(this)); 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.showManualMode = getConfig('showManualMode').showManualMode; this.showAllSerialDevices = getConfig('showAllSerialDevices').showAllSerialDevices; this.useMdnsBrowser = getConfig('useMdnsBrowser').useMdnsBrowser; if (this.useMdnsBrowser) { MdnsDiscovery.initialize(); } 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(); } this.check_serial_devices(); }; PortHandler.check_serial_devices = function () { const self = this; const updatePorts = function(cp) { self.currentPorts = []; if (self.useMdnsBrowser) { self.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); } else { self.currentPorts = cp; } // auto-select port (only during initialization) if (!self.initialPorts) { self.updatePortSelect(self.currentPorts); self.selectActivePort(); self.initialPorts = self.currentPorts; GUI.updateManualPortVisibility(); } else { self.removePort(); self.detectPort(); self.selectActivePort(); } }; serial.getDevices().then(updatePorts); }; PortHandler.onChangeSelectedPort = function(port) { this.portPicker.selectedPort = port; }; PortHandler.check_usb_devices = function (callback) { // TODO needs USB code refactor for web if (isWeb()) { return; } const self = this; chrome.usb.getDevices(usbDevices, function (result) { const dfuElement = self.portPickerElement.children("[value='DFU']"); if (result.length) { // Found device in DFU mode, add it to the list if (!dfuElement.length) { self.portPickerElement.empty(); const productName = result[0].productName; const usbText = productName ? `DFU - ${productName}` : 'DFU'; self.portPickerElement.append($('