Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,45 @@
"tabOptions": {
"message": "Options"
},

"tabNornConfig": {
"message": "NORN Config"
},
"nornManticore": {
"message": "Manticore"
},
"nornVtx": {
"message": "VTX"
},
"nornNone": {
"message": "None"
},
"nornGenerate": {
"message": "Generate"
},
"nornOutput": {
"message": "NORN Configuration"
},
"nornDrone": {
"message": "Drone"
},
"nornController": {
"message": "Controller"
},
"nornSize": {
"message": "Size"
},
"nornCraftName": {
"message": "Craft Name"
},
"nornGPS": {
"message": "GPS"
},
"nornCopy": {
"message": "Copy to clipboard"
},
"nornSave": {
"message": "Save"
},
"tabSetup": {
"message": "Setup"
},
Expand Down Expand Up @@ -1937,6 +1975,12 @@
"portsFunction_VTX_MSP": {
"message": "VTX (MSP + Displayport)"
},
"portsFunction_MANTICORE_INITIATOR_V1": {
"message": "Manticore V1"
},
"portsFunction_MANTICORE_INITIATOR_V2": {
"message": "Manticore V2"
},
"pidTuningProfileOption": {
"message": "Profile $1"
},
Expand Down Expand Up @@ -7745,6 +7789,15 @@
"message": "Sonar",
"description": "Displays distance from sonar sensor in cm"
},
"osdTextElementManticoreV1": {
"message": "Manticore V1"
},
"osdTextElementManticoreV2": {
"message": "Manticore V2"
},
"osdTextElementManticoreV2Logger": {
"message": "Manticore V2 Logger"
},
Comment on lines +7808 to +7815
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add the missing OSD description strings.

Every OSD element string in this file has a paired osdDescElement… entry. Without the new descriptions, the UI falls back to the raw key (or shows nothing) for the tooltips of these Manticore elements. Please add the descriptions alongside the text entries so the help popovers remain readable.

     "osdTextElementManticoreV1": {
         "message": "Manticore V1"
     },
+    "osdDescElementManticoreV1": {
+        "message": "Displays the status/state for the Manticore V1 data feed."
+    },
     "osdTextElementManticoreV2": {
         "message": "Manticore V2"
     },
+    "osdDescElementManticoreV2": {
+        "message": "Displays the status/state for the Manticore V2 data feed."
+    },
     "osdTextElementManticoreV2Logger": {
         "message": "Manticore V2 Logger"
     },
+    "osdDescElementManticoreV2Logger": {
+        "message": "Displays the logger status for the Manticore V2 data feed."
+    },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"message": "Manticore V1"
},
"osdTextElementManticoreV2": {
"message": "Manticore V2"
},
"osdTextElementManticoreV2Logger": {
"message": "Manticore V2 Logger"
},
"osdTextElementManticoreV1": {
"message": "Manticore V1"
},
"osdDescElementManticoreV1": {
"message": "Displays the status/state for the Manticore V1 data feed."
},
"osdTextElementManticoreV2": {
"message": "Manticore V2"
},
"osdDescElementManticoreV2": {
"message": "Displays the status/state for the Manticore V2 data feed."
},
"osdTextElementManticoreV2Logger": {
"message": "Manticore V2 Logger"
},
"osdDescElementManticoreV2Logger": {
"message": "Displays the logger status for the Manticore V2 data feed."
},
🤖 Prompt for AI Agents
In locales/en/messages.json around lines 7793-7800, three OSD text keys
(osdTextElementManticoreV1, osdTextElementManticoreV2,
osdTextElementManticoreV2Logger) are missing their corresponding description
keys; add matching osdDescElementManticoreV1, osdDescElementManticoreV2, and
osdDescElementManticoreV2Logger entries directly alongside the existing text
entries with concise tooltip strings (e.g., brief descriptions of each Manticore
element) so the UI help popovers display human-readable descriptions instead of
raw keys.

"osdDescElementLidar": {
"message": "$t(osdTextElementLidar.message)",
"description": "Don't translate!!!"
Expand Down
39 changes: 39 additions & 0 deletions locales/uk/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -7510,5 +7510,44 @@
"osdDescElementLidar": {
"message": "$t(osdTextElementLidar.message)",
"description": "Don't translate!!!"
},
"nornManticore": {
"message": "Manticore"
},
"nornVtx": {
"message": "VTX"
},
"nornNone": {
"message": "Немає"
},
"nornGenerate": {
"message": "Згенерувати"
},
"nornOutput": {
"message": "Конфігурація"
},
"nornDrone": {
"message": "Дрон"
},
"nornController": {
"message": "Контролер"
},
"nornSize": {
"message": "Розмір"
},
"nornCraftName": {
"message": "Назва дрона"
},
"nornGPS": {
"message": "GPS"
},
"nornCopy": {
"message": "Копіювати в буффер"
},
"nornSave": {
"message": "Зберегти"
},
Comment on lines +7545 to +7549
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo in user-facing text.

"Копіювати в буффер" має одну зайву літера ф. Будь ласка, виправте на "Копіювати в буфер", щоб уникнути помилки в інтерфейсі.

🤖 Prompt for AI Agents
In locales/uk/messages.json around lines 7545 to 7549, the Ukrainian translation
for the copy-to-clipboard label contains a typo ("Копіювати в буффер" with an
extra "ф"); replace that value with the correct spelling "Копіювати в буфер"
while preserving the JSON key structure and surrounding formatting.

"tabNornConfig": {
"message": "NORN Налаштування"
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"node": "20.x"
},
"dependencies": {
"ejs": "^3.1.9",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify EJS version for security advisories and latest updates.

The EJS dependency version 3.1.9 was published in March 2023. Given the security-sensitive nature of template engines (server-side template injection risks are documented for EJS), ensure this version has no known vulnerabilities and consider whether a newer version is available.

Based on learnings

Run the following script to check for security advisories and the latest version:


🏁 Script executed:

#!/bin/bash
# Check for the latest version of EJS
curl -s https://registry.npmjs.org/ejs | jq -r '.["dist-tags"].latest'

# Check for security advisories using GitHub API
gh api graphql -f query='
{
  securityVulnerabilities(first: 10, ecosystem: NPM, package: "ejs") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Length of output: 1108


Upgrade EJS to ≥3.1.10. Version 3.1.9 is vulnerable to a moderate‐severity “pollution protection” issue (published 2024-04-28) fixed in 3.1.10.

🤖 Prompt for AI Agents
In package.json around line 44, the ejs dependency is pinned to "3.1.9" which is
vulnerable; update the dependency to ">=3.1.10" (e.g., set the version to
"3.1.10" or a caret range "^3.1.10"), then run your package manager to update
node_modules and the lockfile (npm install / npm ci or yarn install), run the
test suite and any build steps to verify nothing breaks, and commit the updated
package.json and lockfile.

"@capacitor/android": "^7.0.1",
"@capacitor/core": "^7.0.1",
"@fortawesome/fontawesome-free": "^6.5.2",
Expand Down
1 change: 1 addition & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@
<li class="tab_setup_osd"><a href="#" i18n="tabSetupOSD" class="tabicon ic_setup" i18n_title="tabSetupOSD"></a></li>
<li class="tab_ports"><a href="#" i18n="tabPorts" class="tabicon ic_ports" i18n_title="tabPorts"></a></li>
<li class="tab_configuration"><a href="#" i18n="tabConfiguration" class="tabicon ic_config" i18n_title="tabConfiguration"></a></li>
<li class="tab_norn_config"><a href="#" i18n="tabNornConfig" class="tabicon ic_setup" i18n_title="tabNornConfig"></a></li>
<li class="tab_power"><a href="#" i18n="tabPower" class="tabicon ic_power" i18n_title="tabPower"></a></li>
<li class="tab_failsafe"><a href="#" i18n="tabFailsafe" class="tabicon ic_failsafe" i18n_title="tabFailsafe"></a></li>
<li class="tab_presets"><a href="#" i18n="tabPresets" class="tabicon ic_wizzard" i18n_title="tabPresets"></a></li>
Expand Down
1 change: 1 addition & 0 deletions src/js/gui.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class GuiControl {
"presets",
"cli",
"configuration",
"norn_config",
"logging",
"onboard_logging",
"modes",
Expand Down
3 changes: 3 additions & 0 deletions src/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,9 @@ function startProcess() {
configuration.initialize(content_ready),
);
break;
case "norn_config":
import("./tabs/norn_config").then(({ norn_config }) => norn_config.initialize(content_ready));
break;
case "pid_tuning":
import("./tabs/pid_tuning").then(({ pid_tuning }) => pid_tuning.initialize(content_ready));
break;
Expand Down
5 changes: 5 additions & 0 deletions src/js/msp/MSPHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ function MspHelper() {
LIDAR_TF: 15,
FRSKY_OSD: 16,
VTX_MSP: 17,
GIMBAL: 18,
KOLIBRI_INITIATOR: 19,
DETONATOR: 20,
MANTICORE_INITIATOR_V1: 21,
MANTICORE_INITIATOR_V2: 22,
};

self.REBOOT_TYPES = {
Expand Down
1 change: 1 addition & 0 deletions src/js/serial_backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ function checkReportProblems() {
}
}

needsProblemReportingDialog = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Remove the unconditional suppression of the problem-reporting dialog.

This line unconditionally sets needsProblemReportingDialog = false immediately before the conditional check, effectively disabling all problem reporting to users. The code above (lines 482-509) carefully detects firmware compatibility issues, calibration problems, and other configuration issues, but this line prevents users from ever seeing these warnings.

This appears to be debug or development code that should not be in production. Users need to see these warnings to diagnose and fix problems with their flight controllers.

Remove this line to restore proper problem reporting:

-        needsProblemReportingDialog = false;
         if (needsProblemReportingDialog) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
needsProblemReportingDialog = false;
if (needsProblemReportingDialog) {
🤖 Prompt for AI Agents
In src/js/serial_backend.js around line 511, there is an unconditional
assignment "needsProblemReportingDialog = false" that suppresses the
problem-reporting dialog; remove this line so that the boolean set earlier by
the detection logic is preserved and the subsequent conditional that shows the
dialog can run normally, restoring user-facing warnings about
firmware/calibration/configuration issues.

if (needsProblemReportingDialog) {
problems.forEach((problem) => {
problemItemTemplate.clone().html(problem.description).appendTo(problemDialogList);
Expand Down
67 changes: 67 additions & 0 deletions src/js/tabs/firmware_flasher.js
Original file line number Diff line number Diff line change
Expand Up @@ -740,10 +740,60 @@ firmware_flasher.initialize = async function (callback) {
STM32.rebootMode = 0;
GUI.connect_lock = false;
startFlashing();
} else {
// Auto-detect board when firmware flasher tab is active and no flash-on-connect
console.log(`${self.logHead} Auto-detecting board for connected USB device`);
AutoDetect.verifyBoard();
}
}

function detectedSerialDevice(device) {
const isFlashOnConnect = $("input.flash_on_connect").is(":checked");

console.log(`${self.logHead} Detected serial device:`, device);
console.log(`${self.logHead} Reboot mode: %s, flash on connect`, STM32.rebootMode, isFlashOnConnect);

if (STM32.rebootMode || isFlashOnConnect) {
STM32.rebootMode = 0;
GUI.connect_lock = false;
startFlashing();
} else {
// Auto-detect board when firmware flasher tab is active and no flash-on-connect
console.log(`${self.logHead} Auto-detecting board for connected serial device`);
AutoDetect.verifyBoard();
}
}

EventBus.$on("port-handler:auto-select-usb-device", detectedUsbDevice);
EventBus.$on("port-handler:auto-select-serial-device", detectedSerialDevice);

// Also listen for port changes to catch reconnections
function onPortChange(port) {
console.log(`${self.logHead} Port changed to:`, port);
// Auto-detect board when port changes and we're on firmware flasher tab
if (port && port !== "0" && !$("input.flash_on_connect").is(":checked") && !STM32.rebootMode) {
console.log(`${self.logHead} Auto-detecting board for port change`);
setTimeout(() => {
AutoDetect.verifyBoard();
}, 500); // Small delay to ensure port is ready
} else if (!port || port === "0") {
// Clear board selection when no port is selected
console.log(`${self.logHead} Clearing board selection - no port selected`);
$('select[name="board"]').val("0").trigger("change");
}
}
Comment on lines +770 to +784
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Store timeout references for cleanup.

The setTimeout callback at line 777 is not stored, so it cannot be canceled if the tab closes or changes before the 500ms delay completes. This can lead to AutoDetect.verifyBoard() executing in an invalid context.

Store the timeout reference and clear it in the cleanup function:

+let portChangeTimeout = null;
+
 function onPortChange(port) {
     console.log(`${self.logHead} Port changed to:`, port);
+    // Clear any pending timeout
+    if (portChangeTimeout) {
+        clearTimeout(portChangeTimeout);
+        portChangeTimeout = null;
+    }
     // Auto-detect board when port changes and we're on firmware flasher tab
     if (port && port !== "0" && !$("input.flash_on_connect").is(":checked") && !STM32.rebootMode) {
         console.log(`${self.logHead} Auto-detecting board for port change`);
-        setTimeout(() => {
+        portChangeTimeout = setTimeout(() => {
             AutoDetect.verifyBoard();
+            portChangeTimeout = null;
         }, 500); // Small delay to ensure port is ready

Then in firmware_flasher.cleanup, add:

 firmware_flasher.cleanup = function (callback) {
+    // Clear any pending timeouts
+    if (portChangeTimeout) {
+        clearTimeout(portChangeTimeout);
+        portChangeTimeout = null;
+    }
     // unbind "global" events
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Also listen for port changes to catch reconnections
function onPortChange(port) {
console.log(`${self.logHead} Port changed to:`, port);
// Auto-detect board when port changes and we're on firmware flasher tab
if (port && port !== "0" && !$("input.flash_on_connect").is(":checked") && !STM32.rebootMode) {
console.log(`${self.logHead} Auto-detecting board for port change`);
setTimeout(() => {
AutoDetect.verifyBoard();
}, 500); // Small delay to ensure port is ready
} else if (!port || port === "0") {
// Clear board selection when no port is selected
console.log(`${self.logHead} Clearing board selection - no port selected`);
$('select[name="board"]').val("0").trigger("change");
}
}
// At top of the module scope
let portChangeTimeout = null;
// Also listen for port changes to catch reconnections
function onPortChange(port) {
console.log(`${self.logHead} Port changed to:`, port);
// Clear any pending timeout
if (portChangeTimeout) {
clearTimeout(portChangeTimeout);
portChangeTimeout = null;
}
// Auto-detect board when port changes and we're on firmware flasher tab
if (port && port !== "0" && !$("input.flash_on_connect").is(":checked") && !STM32.rebootMode) {
console.log(`${self.logHead} Auto-detecting board for port change`);
portChangeTimeout = setTimeout(() => {
AutoDetect.verifyBoard();
portChangeTimeout = null;
}, 500); // Small delay to ensure port is ready
} else if (!port || port === "0") {
// Clear board selection when no port is selected
console.log(`${self.logHead} Clearing board selection - no port selected`);
$('select[name="board"]').val("0").trigger("change");
}
}
// ...
firmware_flasher.cleanup = function (callback) {
// Clear any pending timeouts
if (portChangeTimeout) {
clearTimeout(portChangeTimeout);
portChangeTimeout = null;
}
// unbind "global" events
// ...
};
🤖 Prompt for AI Agents
In src/js/tabs/firmware_flasher.js around lines 770 to 784, the setTimeout
started for AutoDetect.verifyBoard() is not stored so it cannot be cancelled
when the tab closes; create a scoped variable (e.g., autoDetectTimeout) on the
module/this so the timeout ID is assigned whenever you call setTimeout, clear
any existing timeout before creating a new one
(clearTimeout(autoDetectTimeout)), and replace setTimeout(...) with
autoDetectTimeout = setTimeout(...); then, in firmware_flasher.cleanup, call
clearTimeout(autoDetectTimeout) and null out the variable to ensure the pending
callback is cancelled when the tab is torn down.


// Listen for device removal to clear board selection
function onDeviceRemoved(devicePath) {
console.log(`${self.logHead} Device removed:`, devicePath);
// Clear board selection when device is removed
$('select[name="board"]').val("0").trigger("change");
// Also clear any loaded firmware
clearBufferedFirmware();
}

EventBus.$on("ports-input:change", onPortChange);
EventBus.$on("port-handler:device-removed", onDeviceRemoved);

async function saveFirmware() {
const fileType = self.firmware_type;
Expand Down Expand Up @@ -1458,6 +1508,17 @@ firmware_flasher.initialize = async function (callback) {
$("a.exit_dfu").removeClass("disabled");
}

// Auto-detect board if a drone is already connected when tab becomes active
if (
(PortHandler.portAvailable && !$('select[name="board"]').val()) ||
$('select[name="board"]').val() === "0"
) {
console.log(`${self.logHead} Auto-detecting board for already connected device`);
setTimeout(() => {
AutoDetect.verifyBoard();
}, 1000); // Small delay to ensure tab is fully loaded
}
Comment on lines +1511 to +1520
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Store timeout reference for cleanup.

The setTimeout callback at line 1517 is not stored, preventing cleanup if the tab closes before the 1000ms delay completes. This can result in AutoDetect.verifyBoard() executing after the tab has been deactivated.

Store the timeout reference and clear it in the cleanup function:

+let tabActivationTimeout = null;
+
 // Auto-detect board if a drone is already connected when tab becomes active
 if (
     (PortHandler.portAvailable && !$('select[name="board"]').val()) ||
     $('select[name="board"]').val() === "0"
 ) {
     console.log(`${self.logHead} Auto-detecting board for already connected device`);
-    setTimeout(() => {
+    tabActivationTimeout = setTimeout(() => {
         AutoDetect.verifyBoard();
+        tabActivationTimeout = null;
     }, 1000); // Small delay to ensure tab is fully loaded
 }

Then in firmware_flasher.cleanup, add:

 firmware_flasher.cleanup = function (callback) {
+    // Clear any pending timeouts
+    if (tabActivationTimeout) {
+        clearTimeout(tabActivationTimeout);
+        tabActivationTimeout = null;
+    }
     // unbind "global" events
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Auto-detect board if a drone is already connected when tab becomes active
if (
(PortHandler.portAvailable && !$('select[name="board"]').val()) ||
$('select[name="board"]').val() === "0"
) {
console.log(`${self.logHead} Auto-detecting board for already connected device`);
setTimeout(() => {
AutoDetect.verifyBoard();
}, 1000); // Small delay to ensure tab is fully loaded
}
// At top of src/js/tabs/firmware_flasher.js
let tabActivationTimeout = null;
// Auto-detect board if a drone is already connected when tab becomes active
if (
(PortHandler.portAvailable && !$('select[name="board"]').val()) ||
$('select[name="board"]').val() === "0"
) {
console.log(`${self.logHead} Auto-detecting board for already connected device`);
tabActivationTimeout = setTimeout(() => {
AutoDetect.verifyBoard();
tabActivationTimeout = null;
}, 1000); // Small delay to ensure tab is fully loaded
}
// … later in the same file …
firmware_flasher.cleanup = function (callback) {
// Clear any pending timeouts
if (tabActivationTimeout) {
clearTimeout(tabActivationTimeout);
tabActivationTimeout = null;
}
// unbind "global" events
};
🤖 Prompt for AI Agents
In src/js/tabs/firmware_flasher.js around lines 1511-1520, the setTimeout used
to call AutoDetect.verifyBoard() is not stored, so it may fire after the tab is
closed; save the timeout ID (e.g. this.autoDetectTimeout or
self.autoDetectTimeout) when calling setTimeout, clear any existing timeout
before setting a new one, and in the firmware_flasher.cleanup function call
clearTimeout on that saved ID and null it to prevent AutoDetect.verifyBoard()
running after the tab is deactivated.


GUI.content_ready(callback);
}

Expand All @@ -1476,6 +1537,12 @@ firmware_flasher.cleanup = function (callback) {
$(document).unbind("keypress");
$(document).off("click", "span.progressLabel a");

// Clean up EventBus listeners
EventBus.$off("port-handler:auto-select-usb-device");
EventBus.$off("port-handler:auto-select-serial-device");
EventBus.$off("ports-input:change");
EventBus.$off("port-handler:device-removed");
Comment on lines +1540 to +1544
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Pass handler references to EventBus.$off.

Calling EventBus.$off() without handler references removes ALL listeners for these events globally, not just the ones registered by this tab. This will break other components that listen to these events.

Pass the handler function references to properly unsubscribe only this tab's listeners:

 // Clean up EventBus listeners
-EventBus.$off("port-handler:auto-select-usb-device");
-EventBus.$off("port-handler:auto-select-serial-device");
-EventBus.$off("ports-input:change");
-EventBus.$off("port-handler:device-removed");
+EventBus.$off("port-handler:auto-select-usb-device", detectedUsbDevice);
+EventBus.$off("port-handler:auto-select-serial-device", detectedSerialDevice);
+EventBus.$off("ports-input:change", onPortChange);
+EventBus.$off("port-handler:device-removed", onDeviceRemoved);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Clean up EventBus listeners
EventBus.$off("port-handler:auto-select-usb-device");
EventBus.$off("port-handler:auto-select-serial-device");
EventBus.$off("ports-input:change");
EventBus.$off("port-handler:device-removed");
// Clean up EventBus listeners
EventBus.$off("port-handler:auto-select-usb-device", detectedUsbDevice);
EventBus.$off("port-handler:auto-select-serial-device", detectedSerialDevice);
EventBus.$off("ports-input:change", onPortChange);
EventBus.$off("port-handler:device-removed", onDeviceRemoved);


if (callback) callback();
};

Expand Down
Loading
Loading