Skip to content

Commit 1487720

Browse files
committed
Added status message area to USB connect workflow
- Removed some catching of exceptions inside the workflow to catch at outer function so we can report. - Added an element to the dialog to hold status messages. - Catch and analyze exceptions to print user friendly messages if possible.
1 parent 8e9dec5 commit 1487720

File tree

3 files changed

+82
-20
lines changed

3 files changed

+82
-20
lines changed

index.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,11 @@ <h1>Select USB Host Folder</h1>
313313
</p>
314314
</div>
315315
</section>
316+
<section>
317+
<div class="connect-status" hidden>
318+
<div class="connect-status-content"></div>
319+
</div>
320+
</section>
316321
</div>
317322
</div>
318323
<div class="popup-modal shadow closable" data-popup-modal="device-discovery">

js/workflows/usb.js

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class USBWorkflow extends Workflow {
8383

8484
async connect() {
8585
let result;
86+
this._clearStatus();
8687
if (result = await super.connect() instanceof Error) {
8788
return result;
8889
}
@@ -100,6 +101,7 @@ class USBWorkflow extends Workflow {
100101
// the device on the stored port is currently connected by checking if the
101102
// readable and writable properties are null.
102103

104+
// Can throw a Security Error if permissions are not granted
103105
let allDevices = await navigator.serial.getPorts();
104106
let connectedDevices = [];
105107
for (let device of allDevices) {
@@ -112,7 +114,8 @@ class USBWorkflow extends Workflow {
112114

113115
if (connectedDevices.length == 1) {
114116
device = connectedDevices[0];
115-
console.log(await device.getInfo());
117+
deviceInfo = await device.getInfo()
118+
console.log(`Got previously connected device: ${deviceInfo}`);
116119
try {
117120
// Attempt to connect to the saved device. If it's not found, this will fail.
118121
await this._switchToDevice(device);
@@ -121,37 +124,35 @@ class USBWorkflow extends Workflow {
121124
await device.forget();
122125

123126
console.log("Failed to automatically connect to saved device. Prompting user to select a device.");
127+
// If the user doesn't select a port, an exception is thrown
124128
device = await navigator.serial.requestPort();
125-
console.log(device);
126129
}
127130
} else {
128-
console.log('Requesting any serial device...');
129-
try {
130-
device = await navigator.serial.requestPort();
131-
} catch (e) {
132-
console.log(e);
133-
return false;
134-
}
131+
console.log('No previously connected device. Prompting user to select a device.');
132+
// If the user doesn't select a port, an exception is thrown
133+
device = await navigator.serial.requestPort();
135134
}
135+
console.log(`Selected device: ${device}`);
136+
136137

137138
// If we didn't automatically use a saved device
138139
if (!this._serialDevice) {
139140
console.log('> Requested ', device);
140141
await this._switchToDevice(device);
141142
}
142-
console.log(this._serialDevice);
143+
143144
if (this._serialDevice != null) {
145+
console.log(`Current serial device is: ${this._serialDevice}. Proceeding to step 2.`);
144146
this.connectionStep(2);
145147
return true;
146148
}
147-
149+
console.log("Couldn't connect to serial port");
148150
return false;
149151
}
150152

151153
async showConnect(documentState) {
152154
let p = this.connectDialog.open();
153155
let modal = this.connectDialog.getModal();
154-
155156
btnRequestSerialDevice = modal.querySelector('#requestSerialDevice');
156157
btnSelectHostFolder = modal.querySelector('#selectHostFolder');
157158
btnUseHostFolder = modal.querySelector('#useHostFolder');
@@ -165,22 +166,27 @@ class USBWorkflow extends Workflow {
165166

166167
btnRequestSerialDevice.disabled = true;
167168
btnSelectHostFolder.disabled = true;
169+
this._clearStatus();
168170
let serialConnect = async (event) => {
169171
try {
172+
this._clearStatus();
170173
await this.connectToSerial();
171174
} catch (e) {
172-
//console.log(e);
173-
//alert(e.message);
174-
//alert("Unable to connect to device. Make sure it is not already in use.");
175-
// TODO: I think this also occurs if the user cancels the requestPort dialog
175+
console.log('connectToSerial() returned error: ', e);
176+
this._showStatus(this._suggestSerialConnectActions(e))
176177
}
177178
};
178179
btnRequestSerialDevice.removeEventListener('click', serialConnect);
179180
btnRequestSerialDevice.addEventListener('click', serialConnect);
180181

181182
btnSelectHostFolder.removeEventListener('click', this._btnSelectHostFolderCallback)
182183
this._btnSelectHostFolderCallback = async (event) => {
183-
await this._selectHostFolder();
184+
try {
185+
this._clearStatus();
186+
await this._selectHostFolder();
187+
} catch (e) {
188+
this._showStatus(this._suggestFileConnectActions(e))
189+
}
184190
};
185191
btnSelectHostFolder.addEventListener('click', this._btnSelectHostFolderCallback);
186192

@@ -269,9 +275,8 @@ class USBWorkflow extends Workflow {
269275

270276
this._serialDevice = device;
271277
console.log("switch to", this._serialDevice);
272-
await this._serialDevice.open({baudRate: 115200}); // TODO: Will fail if something else is already connected or it isn't found.
273-
274-
// Start the read loop
278+
await this._serialDevice.open({baudRate: 115200}); // Throws if something else is already connected or it isn't found.
279+
console.log("Starting Read Loop")
275280
this._readLoopPromise = this._readSerialLoop().catch(
276281
async function(error) {
277282
await this.onDisconnected();
@@ -368,6 +373,50 @@ print(binascii.hexlify(microcontroller.cpu.uid).decode('ascii').upper())`
368373
console.log("Read Loop Stopped. Closing Serial Port.");
369374
}
370375

376+
_clearStatus(modal) {
377+
try {
378+
const modal = this.connectDialog.getModal();
379+
modal.querySelector('.connect-status').hidden = true;
380+
} catch (e) {
381+
console.log("Modal not active on _clearStatus()", e);
382+
}
383+
}
384+
385+
_showStatus(message) {
386+
try {
387+
const modal = this.connectDialog.getModal();
388+
const statusBox = modal.querySelector('.connect-status');
389+
statusBox.hidden = false;
390+
let statusContentBox = statusBox.querySelector('.connect-status-content')
391+
statusContentBox.innerHTML = message
392+
} catch (e) {
393+
console.log("Modal not active on _setStatus()", e);
394+
}
395+
}
396+
397+
// Analyzes the error returned from the WebSerial API and returns human readable feedback.
398+
_suggestSerialConnectActions(error) {
399+
if (error.name == "NetworkError" && error.message.includes("Failed to open serial port")) {
400+
return "The serial port could not be opened. Make sure the correct port is selected and no other program is using it. For more information, see the JavaScript console.";
401+
} else if (error.name == "NotFoundError" && error.message.includes("No port selected")) {
402+
return "No serial port was selected. Press the 'Connect to Device' button to try again.";
403+
} else if (error.name == "SecurityError") {
404+
return "Permissions to access the serial port were not granted. Please check your browser settings and try again.";
405+
}
406+
return `Connect to Serial Port returned error: ${error}`;
407+
}
408+
409+
// Analyzes the error from the FSAPI and returns human readable feedback
410+
_suggestFileConnectActions(error) {
411+
if (error.name == "SecurityError") {
412+
return "Permissions to access the filesystem were not granted. Please check your browser settings and try again.";
413+
} else if (error.name == "AbortError") {
414+
return "No folder selected. Press the 'Select New Folder' button to try again.";
415+
}
416+
return `Connect to Filesystem returned error: ${error}`;
417+
418+
}
419+
371420
async showInfo(documentState) {
372421
return await this.infoDialog.open(this, documentState);
373422
}

sass/layout/_layout.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,14 @@
151151
}
152152
}
153153

154+
.connect-status-content {
155+
background-color: #eebbbb;
156+
color: #222222;
157+
border-radius: 10px;
158+
padding: 10px;
159+
margin: 10px;
160+
}
161+
154162
.popup-modal {
155163
#message {
156164
a {

0 commit comments

Comments
 (0)