Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit cc5cf3b

Browse files
fix 180: prevent erroneous "auto-reconnect"(s) in board selector (#1328)
* ensure auto-select doesn't select wrong port prevent auto-select of unattached boards Co-authored-by: Francesco Spissu <francescospissu@users.noreply.github.com> * clean up * add "uploadInProgress" prop to boards change event * remove unused methods and deps * [WIP]: leverage upload event to derived new port * remove timeout * refine port selection logic * clean up naming * refine port selection logic & add delayed clean up * renaming & refactoring * method syntax & remove unnecessary methods
1 parent 125bd64 commit cc5cf3b

File tree

5 files changed

+122
-21
lines changed

5 files changed

+122
-21
lines changed

‎arduino-ide-extension/src/browser/boards/boards-service-provider.ts‎

Lines changed: 106 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
6565
protected _availablePorts: Port[] = [];
6666
protected _availableBoards: AvailableBoard[] = [];
6767

68+
private lastBoardsConfigOnUpload: BoardsConfig.Config | undefined;
69+
private lastAvailablePortsOnUpload: Port[] | undefined;
70+
private boardConfigToAutoSelect: BoardsConfig.Config | undefined;
71+
6872
/**
6973
* Unlike `onAttachedBoardsChanged` this event fires when the user modifies the selected board in the IDE.\
7074
* This event also fires, when the boards package was not available for the currently selected board,
@@ -112,6 +116,84 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
112116
return this._reconciled.promise;
113117
}
114118

119+
snapshotBoardDiscoveryOnUpload(): void {
120+
this.lastBoardsConfigOnUpload = this._boardsConfig;
121+
this.lastAvailablePortsOnUpload = this._availablePorts;
122+
}
123+
124+
clearBoardDiscoverySnapshot(): void {
125+
this.lastBoardsConfigOnUpload = undefined;
126+
this.lastAvailablePortsOnUpload = undefined;
127+
}
128+
129+
private portToAutoSelectCanBeDerived(): boolean {
130+
return Boolean(
131+
this.lastBoardsConfigOnUpload && this.lastAvailablePortsOnUpload
132+
);
133+
}
134+
135+
attemptPostUploadAutoSelect(): void {
136+
setTimeout(() => {
137+
if (this.portToAutoSelectCanBeDerived()) {
138+
this.attemptAutoSelect({
139+
ports: this._availablePorts,
140+
boards: this._availableBoards,
141+
});
142+
}
143+
}, 2000); // 2 second delay same as IDE 1.8
144+
}
145+
146+
private attemptAutoSelect(
147+
newState: AttachedBoardsChangeEvent['newState']
148+
): void {
149+
this.deriveBoardConfigToAutoSelect(newState);
150+
this.tryReconnect();
151+
}
152+
153+
private deriveBoardConfigToAutoSelect(
154+
newState: AttachedBoardsChangeEvent['newState']
155+
): void {
156+
if (!this.portToAutoSelectCanBeDerived()) {
157+
this.boardConfigToAutoSelect = undefined;
158+
return;
159+
}
160+
161+
const oldPorts = this.lastAvailablePortsOnUpload!;
162+
const { ports: newPorts, boards: newBoards } = newState;
163+
164+
const appearedPorts =
165+
oldPorts.length > 0
166+
? newPorts.filter((newPort: Port) =>
167+
oldPorts.every((oldPort: Port) => !Port.sameAs(newPort, oldPort))
168+
)
169+
: newPorts;
170+
171+
for (const port of appearedPorts) {
172+
const boardOnAppearedPort = newBoards.find((board: Board) =>
173+
Port.sameAs(board.port, port)
174+
);
175+
176+
const lastBoardsConfigOnUpload = this.lastBoardsConfigOnUpload!;
177+
178+
if (
179+
boardOnAppearedPort &&
180+
lastBoardsConfigOnUpload.selectedBoard &&
181+
Board.sameAs(
182+
boardOnAppearedPort,
183+
lastBoardsConfigOnUpload.selectedBoard
184+
)
185+
) {
186+
this.clearBoardDiscoverySnapshot();
187+
188+
this.boardConfigToAutoSelect = {
189+
selectedBoard: boardOnAppearedPort,
190+
selectedPort: port,
191+
};
192+
return;
193+
}
194+
}
195+
}
196+
115197
protected notifyAttachedBoardsChanged(
116198
event: AttachedBoardsChangeEvent
117199
): void {
@@ -120,10 +202,18 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
120202
this.logger.info(AttachedBoardsChangeEvent.toString(event));
121203
this.logger.info('------------------------------------------');
122204
}
205+
123206
this._attachedBoards = event.newState.boards;
124207
this._availablePorts = event.newState.ports;
125208
this.onAvailablePortsChangedEmitter.fire(this._availablePorts);
126-
this.reconcileAvailableBoards().then(() => this.tryReconnect());
209+
this.reconcileAvailableBoards().then(() => {
210+
const { uploadInProgress } = event;
211+
// avoid attempting "auto-selection" while an
212+
// upload is in progress
213+
if (!uploadInProgress) {
214+
this.attemptAutoSelect(event.newState);
215+
}
216+
});
127217
}
128218

129219
protected notifyPlatformInstalled(event: { item: BoardsPackage }): void {
@@ -239,24 +329,12 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
239329
return true;
240330
}
241331
}
242-
// If we could not find an exact match, we compare the board FQBN-name pairs and ignore the port, as it might have changed.
243-
// See documentation on `latestValidBoardsConfig`.
244-
for (const board of this.availableBoards.filter(
245-
({ state }) => state !== AvailableBoard.State.incomplete
246-
)) {
247-
if (
248-
this.latestValidBoardsConfig.selectedBoard.fqbn === board.fqbn &&
249-
this.latestValidBoardsConfig.selectedBoard.name === board.name &&
250-
this.latestValidBoardsConfig.selectedPort.protocol ===
251-
board.port?.protocol
252-
) {
253-
this.boardsConfig = {
254-
...this.latestValidBoardsConfig,
255-
selectedPort: board.port,
256-
};
257-
return true;
258-
}
259-
}
332+
333+
if (!this.boardConfigToAutoSelect) return false;
334+
335+
this.boardsConfig = this.boardConfigToAutoSelect;
336+
this.boardConfigToAutoSelect = undefined;
337+
return true;
260338
}
261339
return false;
262340
}
@@ -450,6 +528,11 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
450528
const board = attachedBoards.find(({ port }) =>
451529
Port.sameAs(boardPort, port)
452530
);
531+
// "board" will always be falsey for
532+
// port that was originally mapped
533+
// to unknown board and then selected
534+
// manually by user
535+
453536
const lastSelectedBoard = await this.getLastSelectedBoardOnPort(
454537
boardPort
455538
);
@@ -468,7 +551,9 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
468551
availableBoard = {
469552
...lastSelectedBoard,
470553
state: AvailableBoard.State.guessed,
471-
selected: BoardsConfig.Config.sameAs(boardsConfig, lastSelectedBoard),
554+
selected:
555+
BoardsConfig.Config.sameAs(boardsConfig, lastSelectedBoard) &&
556+
Port.sameAs(boardPort, boardsConfig.selectedPort), // to avoid double selection
472557
port: boardPort,
473558
};
474559
} else {
@@ -483,7 +568,7 @@ export class BoardsServiceProvider implements FrontendApplicationContribution {
483568

484569
if (
485570
boardsConfig.selectedBoard &&
486-
!availableBoards.some(({ selected }) => selected)
571+
availableBoards.every(({ selected }) => !selected)
487572
) {
488573
// If the selected board has the same port of an unknown board
489574
// that is already in availableBoards we might get a duplicate port.

‎arduino-ide-extension/src/browser/contributions/upload-sketch.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ export class UploadSketch extends CoreServiceContribution {
190190
// toggle the toolbar button and menu item state.
191191
// uploadInProgress will be set to false whether the upload fails or not
192192
this.uploadInProgress = true;
193+
this.boardsServiceProvider.snapshotBoardDiscoveryOnUpload();
193194
this.onDidChangeEmitter.fire();
194195
this.clearVisibleNotification();
195196

@@ -243,6 +244,7 @@ export class UploadSketch extends CoreServiceContribution {
243244
this.handleError(e);
244245
} finally {
245246
this.uploadInProgress = false;
247+
this.boardsServiceProvider.attemptPostUploadAutoSelect();
246248
this.onDidChangeEmitter.fire();
247249
}
248250
}

‎arduino-ide-extension/src/common/protocol/boards-service.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export namespace AvailablePorts {
2525
export interface AttachedBoardsChangeEvent {
2626
readonly oldState: Readonly<{ boards: Board[]; ports: Port[] }>;
2727
readonly newState: Readonly<{ boards: Board[]; ports: Port[] }>;
28+
readonly uploadInProgress: boolean;
2829
}
2930
export namespace AttachedBoardsChangeEvent {
3031
export function isEmpty(event: AttachedBoardsChangeEvent): boolean {

‎arduino-ide-extension/src/node/board-discovery.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ export class BoardDiscovery
5454
private readonly onStreamDidCancelEmitter = new Emitter<void>(); // when the watcher is canceled by the IDE2
5555
private readonly toDisposeOnStopWatch = new DisposableCollection();
5656

57+
private uploadInProgress = false;
58+
5759
/**
5860
* Keys are the `address` of the ports.
5961
*
@@ -123,6 +125,10 @@ export class BoardDiscovery
123125
});
124126
}
125127

128+
setUploadInProgress(uploadAttemptInProgress: boolean): void {
129+
this.uploadInProgress = uploadAttemptInProgress;
130+
}
131+
126132
private createTimeout(
127133
after: number,
128134
onTimeout: (error: Error) => void
@@ -318,6 +324,7 @@ export class BoardDiscovery
318324
ports: newAvailablePorts,
319325
boards: newAttachedBoards,
320326
},
327+
uploadInProgress: this.uploadInProgress,
321328
};
322329

323330
this._availablePorts = newState;

‎arduino-ide-extension/src/node/core-service-impl.ts‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { Instance } from './cli-protocol/cc/arduino/cli/commands/v1/common_pb';
3434
import { firstToUpperCase, notEmpty } from '../common/utils';
3535
import { ServiceError } from './service-error';
3636
import { ExecuteWithProgress, ProgressResponse } from './grpc-progressible';
37+
import { BoardDiscovery } from './board-discovery';
3738

3839
namespace Uploadable {
3940
export type Request = UploadRequest | UploadUsingProgrammerRequest;
@@ -51,6 +52,9 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService {
5152
@inject(CommandService)
5253
private readonly commandService: CommandService;
5354

55+
@inject(BoardDiscovery)
56+
private readonly boardDiscovery: BoardDiscovery;
57+
5458
async compile(options: CoreService.Options.Compile): Promise<void> {
5559
const coreClient = await this.coreClient;
5660
const { client, instance } = coreClient;
@@ -378,6 +382,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService {
378382
fqbn?: string | undefined;
379383
port?: Port | undefined;
380384
}): Promise<void> {
385+
this.boardDiscovery.setUploadInProgress(true);
381386
return this.monitorManager.notifyUploadStarted(fqbn, port);
382387
}
383388

@@ -388,6 +393,7 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService {
388393
fqbn?: string | undefined;
389394
port?: Port | undefined;
390395
}): Promise<Status> {
396+
this.boardDiscovery.setUploadInProgress(false);
391397
return this.monitorManager.notifyUploadFinished(fqbn, port);
392398
}
393399

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /