Skip to content
33 changes: 25 additions & 8 deletions src/js/protocols/webstm32.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,25 @@ function readSerialAdapter(event) {
}

function onTimeoutHandler() {
GUI.connect_lock = false;
console.log(`${STM32Protocol.logHead} Looking for capabilities via MSP failed`);

TABS.firmware_flasher.flashingMessage(
i18n.getMessage("stm32RebootingToBootloaderFailed"),
TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID,
);

STM32.handleError();
}

function onFailureHandler() {
GUI.connect_lock = false;
TABS.firmware_flasher.refresh();
console.log(`${STM32Protocol.logHead} MSP connection failed`);

TABS.firmware_flasher.flashingMessage(
i18n.getMessage("stm32RebootingToBootloaderFailed"),
TABS.firmware_flasher.FLASH_MESSAGE_TYPES.INVALID,
);

STM32.handleError();
}

class STM32Protocol {
Expand Down Expand Up @@ -88,6 +95,18 @@ class STM32Protocol {
this.handleMSPConnect = this.handleMSPConnect.bind(this);
}

/**
* Centralized error handling method that resets UI state and releases connection lock
* @param {boolean} resetRebootMode - Whether to reset the reboot mode
*/
handleError(resetRebootMode = true) {
GUI.connect_lock = false;
if (resetRebootMode) {
this.rebootMode = 0;
}
TABS.firmware_flasher.resetFlashingState();
}

handleConnect(event) {
console.log(`${this.logHead} Connected to serial port`, event.detail, event);
if (event) {
Expand Down Expand Up @@ -118,19 +137,17 @@ class STM32Protocol {
console.log(`${this.logHead} DFU request permission granted`, device);
} else {
console.error(`${this.logHead} DFU request permission denied`);
this.rebootMode = 0;
GUI.connect_lock = false;
this.handleError();
}
})
.catch((e) => {
console.error(`${this.logHead} DFU request permission failed`, e);
this.rebootMode = 0;
GUI.connect_lock = false;
this.handleError();
});
}
}, 3000);
} else {
GUI.connect_lock = false;
this.handleError(false);
}
}

Expand Down
59 changes: 51 additions & 8 deletions src/js/tabs/firmware_flasher.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ const firmware_flasher = {
selectedBoard: undefined,
cloudBuildKey: null,
cloudBuildOptions: null,
isFlashing: false,
intel_hex: undefined, // standard intel hex in string format
parsed_hex: undefined, // parsed raw hex in array format
isConfigLocal: false, // Set to true if the user loads one locally
Expand All @@ -38,6 +37,9 @@ const firmware_flasher = {
config: {},
developmentFirmwareLoaded: false, // Is the firmware to be flashed from the development branch?
cancelBuild: false,
// Properties to preserve firmware state during flashing
preFlashingMessage: null,
preFlashingMessageType: null,
};

firmware_flasher.initialize = async function (callback) {
Expand Down Expand Up @@ -803,12 +805,17 @@ firmware_flasher.initialize = async function (callback) {
} else {
// Maybe the board is in DFU mode, but it does not have permissions. Ask for them.
console.log(`${self.logHead} No valid port detected, asking for permissions`);
DFU.requestPermission().then((device) => {
DFU.connect(device.path, firmware, options);
});

DFU.requestPermission()
.then((device) => {
DFU.connect(device.path, firmware, options);
})
.catch((error) => {
console.error("Permission request failed", error);
firmware_flasher.resetFlashingState();
});
}

self.isFlashing = false;
GUI.interval_resume("sponsor");
}

Expand Down Expand Up @@ -1258,7 +1265,6 @@ firmware_flasher.initialize = async function (callback) {

const aborted = function (message) {
GUI.connect_lock = false;
self.isFlashing = false;
self.enableFlashButton(true);
self.enableLoadRemoteFileButton(true);
self.enableLoadFileButton(true);
Expand Down Expand Up @@ -1381,7 +1387,9 @@ firmware_flasher.initialize = async function (callback) {
return;
}

self.isFlashing = true;
// Preserve current firmware message state before flashing
self.preservePreFlashingState();

GUI.interval_pause("sponsor");

self.enableFlashButton(false);
Expand All @@ -1404,7 +1412,6 @@ firmware_flasher.initialize = async function (callback) {
: i18n.getMessage("firmwareFlasherUF2SaveFailed"),
saved ? self.FLASH_MESSAGE_TYPES.VALID : self.FLASH_MESSAGE_TYPES.INVALID,
);
self.isFlashing = false;
GUI.interval_resume("sponsor");
self.enableFlashButton(true);
self.enableLoadRemoteFileButton(true);
Expand Down Expand Up @@ -1500,6 +1507,42 @@ firmware_flasher.enableDfuExitButton = function (enabled) {
$("a.exit_dfu").toggleClass("disabled", !enabled);
};

firmware_flasher.resetFlashingState = function () {
console.log(`${this.logHead} Reset flashing state`);
this.enableFlashButton(!!this.parsed_hex || !!this.uf2_binary); // Only enable if firmware is loaded
this.enableDfuExitButton(PortHandler.dfuAvailable);
this.enableLoadRemoteFileButton(true);
this.enableLoadFileButton(true);

// Restore pre-flashing message if firmware is still loaded, otherwise show "not loaded"
if (this.parsed_hex || this.uf2_binary) {
if (this.preFlashingMessage && this.preFlashingMessageType) {
this.flashingMessage(this.preFlashingMessage, this.preFlashingMessageType);
}
} else {
this.flashingMessage(i18n.getMessage("firmwareFlasherFirmwareNotLoaded"), this.FLASH_MESSAGE_TYPES.NEUTRAL);
}

GUI.interval_resume("sponsor");
};

firmware_flasher.preservePreFlashingState = function () {
// Preserve the current firmware message and type before flashing starts
const progressLabel = $("span.progressLabel");
this.preFlashingMessage = progressLabel.html();

// Determine the current message type based on CSS classes
if (progressLabel.hasClass("valid")) {
this.preFlashingMessageType = this.FLASH_MESSAGE_TYPES.VALID;
} else if (progressLabel.hasClass("invalid")) {
this.preFlashingMessageType = this.FLASH_MESSAGE_TYPES.INVALID;
} else if (progressLabel.hasClass("actionRequired")) {
this.preFlashingMessageType = this.FLASH_MESSAGE_TYPES.ACTION;
} else {
this.preFlashingMessageType = this.FLASH_MESSAGE_TYPES.NEUTRAL;
}
};

firmware_flasher.refresh = function (callback) {
const self = this;

Expand Down
6 changes: 5 additions & 1 deletion src/js/utils/AutoDetect.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ class AutoDetect {
const port = PortHandler.portPicker.selectedPort;
const isLoaded = TABS.firmware_flasher.targets ? Object.keys(TABS.firmware_flasher.targets).length > 0 : false;

if (!PortHandler.portAvailable) {
gui_log(i18n.getMessage("firmwareFlasherNoValidPort"));
return;
}

if (!isLoaded) {
console.log("Releases not loaded yet");
gui_log(i18n.getMessage("firmwareFlasherNoTargetsLoaded"));
return;
}
Expand Down