mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-10-27 20:18:35 +00:00
[ATL-1533] Firmware&Certificate Uploader (#469)
Co-authored-by: Alberto Iannaccone <a.iannaccone@arduino.cc>
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
ArduinoFirmwareUploader,
|
||||
FirmwareInfo,
|
||||
} from '../../../common/protocol/arduino-firmware-uploader';
|
||||
import { AvailableBoard } from '../../boards/boards-service-provider';
|
||||
import { ArduinoSelect } from '../../widgets/arduino-select';
|
||||
import { SelectBoardComponent } from '../certificate-uploader/select-board-components';
|
||||
|
||||
type FirmwareOption = { value: string; label: string };
|
||||
|
||||
export const FirmwareUploaderComponent = ({
|
||||
availableBoards,
|
||||
firmwareUploader,
|
||||
updatableFqbns,
|
||||
flashFirmware,
|
||||
isOpen,
|
||||
}: {
|
||||
availableBoards: AvailableBoard[];
|
||||
firmwareUploader: ArduinoFirmwareUploader;
|
||||
updatableFqbns: string[];
|
||||
flashFirmware: (firmware: FirmwareInfo, port: string) => Promise<any>;
|
||||
isOpen: any;
|
||||
}): React.ReactElement => {
|
||||
// boolean states for buttons
|
||||
const [firmwaresFetching, setFirmwaresFetching] = React.useState(false);
|
||||
|
||||
const [installFeedback, setInstallFeedback] = React.useState<
|
||||
'ok' | 'fail' | 'installing' | null
|
||||
>(null);
|
||||
|
||||
const [selectedBoard, setSelectedBoard] =
|
||||
React.useState<AvailableBoard | null>(null);
|
||||
|
||||
const [availableFirmwares, setAvailableFirmwares] = React.useState<
|
||||
FirmwareInfo[]
|
||||
>([]);
|
||||
React.useEffect(() => {
|
||||
setAvailableFirmwares([]);
|
||||
}, [isOpen]);
|
||||
const [selectedFirmware, setSelectedFirmware] =
|
||||
React.useState<FirmwareOption | null>(null);
|
||||
|
||||
const [firmwareOptions, setFirmwareOptions] = React.useState<
|
||||
FirmwareOption[]
|
||||
>([]);
|
||||
|
||||
const fetchFirmwares = React.useCallback(async () => {
|
||||
setInstallFeedback(null);
|
||||
setFirmwaresFetching(true);
|
||||
if (!selectedBoard) {
|
||||
return;
|
||||
}
|
||||
|
||||
// fetch the firmwares for the selected board
|
||||
const firmwaresForFqbn = await firmwareUploader.availableFirmwares(
|
||||
selectedBoard.fqbn || ''
|
||||
);
|
||||
setAvailableFirmwares(firmwaresForFqbn);
|
||||
|
||||
const firmwaresOpts = firmwaresForFqbn.map((f) => ({
|
||||
label: f.firmware_version,
|
||||
value: f.firmware_version,
|
||||
}));
|
||||
|
||||
setFirmwareOptions(firmwaresOpts);
|
||||
|
||||
if (firmwaresForFqbn.length > 0) setSelectedFirmware(firmwaresOpts[0]);
|
||||
setFirmwaresFetching(false);
|
||||
}, [firmwareUploader, selectedBoard]);
|
||||
|
||||
const installFirmware = React.useCallback(async () => {
|
||||
setInstallFeedback('installing');
|
||||
|
||||
const firmwareToFlash = availableFirmwares.find(
|
||||
(firmware) => firmware.firmware_version === selectedFirmware?.value
|
||||
);
|
||||
|
||||
try {
|
||||
const installStatus =
|
||||
!!firmwareToFlash &&
|
||||
!!selectedBoard?.port &&
|
||||
(await flashFirmware(firmwareToFlash, selectedBoard?.port.address));
|
||||
|
||||
setInstallFeedback((installStatus && 'ok') || 'fail');
|
||||
} catch {
|
||||
setInstallFeedback('fail');
|
||||
}
|
||||
}, [firmwareUploader, selectedBoard, selectedFirmware, availableFirmwares]);
|
||||
|
||||
const onBoardSelect = React.useCallback(
|
||||
(board: AvailableBoard) => {
|
||||
const newFqbn = (board && board.fqbn) || null;
|
||||
const prevFqbn = (selectedBoard && selectedBoard.fqbn) || null;
|
||||
|
||||
if (newFqbn !== prevFqbn) {
|
||||
setInstallFeedback(null);
|
||||
setAvailableFirmwares([]);
|
||||
setSelectedBoard(board);
|
||||
}
|
||||
},
|
||||
[selectedBoard]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="dialogSection">
|
||||
<div className="dialogRow">
|
||||
<label htmlFor="board-select">Select board</label>
|
||||
</div>
|
||||
<div className="dialogRow">
|
||||
<div className="fl1">
|
||||
<SelectBoardComponent
|
||||
availableBoards={availableBoards}
|
||||
updatableFqbns={updatableFqbns}
|
||||
onBoardSelect={onBoardSelect}
|
||||
selectedBoard={selectedBoard}
|
||||
busy={installFeedback === 'installing'}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="theia-button secondary"
|
||||
disabled={
|
||||
selectedBoard === null ||
|
||||
firmwaresFetching ||
|
||||
installFeedback === 'installing'
|
||||
}
|
||||
onClick={fetchFirmwares}
|
||||
>
|
||||
Check Updates
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{availableFirmwares.length > 0 && (
|
||||
<>
|
||||
<div className="dialogSection">
|
||||
<div className="dialogRow">
|
||||
<label htmlFor="firmware-select" className="fl1">
|
||||
Select firmware version
|
||||
</label>
|
||||
<ArduinoSelect
|
||||
id="firmware-select"
|
||||
menuPosition="fixed"
|
||||
isDisabled={
|
||||
!selectedBoard ||
|
||||
firmwaresFetching ||
|
||||
installFeedback === 'installing'
|
||||
}
|
||||
options={firmwareOptions}
|
||||
value={selectedFirmware}
|
||||
tabSelectsValue={false}
|
||||
onChange={(value) => {
|
||||
if (value) {
|
||||
setInstallFeedback(null);
|
||||
setSelectedFirmware(value);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
className="theia-button primary"
|
||||
disabled={
|
||||
selectedFirmware === null ||
|
||||
firmwaresFetching ||
|
||||
installFeedback === 'installing'
|
||||
}
|
||||
onClick={installFirmware}
|
||||
>
|
||||
Install
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="dialogSection">
|
||||
{installFeedback === null && (
|
||||
<div className="dialogRow warn">
|
||||
<i className="fa fa-exclamation status-icon" />
|
||||
Installation will overwrite the Sketch on the board.
|
||||
</div>
|
||||
)}
|
||||
{installFeedback === 'installing' && (
|
||||
<div className="dialogRow success">
|
||||
<div className="spinner" />
|
||||
Installing firmware.
|
||||
</div>
|
||||
)}
|
||||
{installFeedback === 'ok' && (
|
||||
<div className="dialogRow success">
|
||||
<i className="fa fa-info status-icon" />
|
||||
Firmware succesfully installed.
|
||||
</div>
|
||||
)}
|
||||
{installFeedback === 'fail' && (
|
||||
<div className="dialogRow warn">
|
||||
<i className="fa fa-exclamation status-icon" />
|
||||
Installation failed. Please try again.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user