Skip to content

Commit 90c157b

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 77e98ea commit 90c157b

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
@@ -301,6 +301,11 @@ <h1>Select USB Host Folder</h1>
301301
</p>
302302
</div>
303303
</section>
304+
<section>
305+
<div class="connect-status" hidden>
306+
<div class="connect-status-content"></div>
307+
</div>
308+
</section>
304309
</div>
305310
</div>
306311
<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
@@ -84,6 +84,7 @@ class USBWorkflow extends Workflow {
8484

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

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

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

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

138139
// If we didn't automatically use a saved device
139140
if (!this._serialDevice) {
140141
console.log('> Requested ', device);
141142
await this._switchToDevice(device);
142143
}
143-
console.log(this._serialDevice);
144+
144145
if (this._serialDevice != null) {
146+
console.log(`Current serial device is: ${this._serialDevice}. Proceeding to step 2.`);
145147
this.connectionStep(2);
146148
return true;
147149
}
148-
150+
console.log("Couldn't connect to serial port");
149151
return false;
150152
}
151153

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

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

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

@@ -274,9 +280,8 @@ class USBWorkflow extends Workflow {
274280

275281
this._serialDevice = device;
276282
console.log("switch to", this._serialDevice);
277-
await this._serialDevice.open({baudRate: 115200}); // TODO: Will fail if something else is already connected or it isn't found.
278-
279-
// Start the read loop
283+
await this._serialDevice.open({baudRate: 115200}); // Throws if something else is already connected or it isn't found.
284+
console.log("Starting Read Loop")
280285
this._readLoopPromise = this._readSerialLoop().catch(
281286
async function(error) {
282287
await this.onDisconnected();
@@ -373,6 +378,50 @@ print(binascii.hexlify(microcontroller.cpu.uid).decode('ascii').upper())`
373378
console.log("Read Loop Stopped. Closing Serial Port.");
374379
}
375380

381+
_clearStatus(modal) {
382+
try {
383+
const modal = this.connectDialog.getModal();
384+
modal.querySelector('.connect-status').hidden = true;
385+
} catch (e) {
386+
console.log("Modal not active on _clearStatus()", e);
387+
}
388+
}
389+
390+
_showStatus(message) {
391+
try {
392+
const modal = this.connectDialog.getModal();
393+
const statusBox = modal.querySelector('.connect-status');
394+
statusBox.hidden = false;
395+
let statusContentBox = statusBox.querySelector('.connect-status-content')
396+
statusContentBox.innerHTML = message
397+
} catch (e) {
398+
console.log("Modal not active on _setStatus()", e);
399+
}
400+
}
401+
402+
// Analyzes the error returned from the WebSerial API and returns human readable feedback.
403+
_suggestSerialConnectActions(error) {
404+
if (error.name == "NetworkError" && error.message.includes("Failed to open serial port")) {
405+
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.";
406+
} else if (error.name == "NotFoundError" && error.message.includes("No port selected")) {
407+
return "No serial port was selected. Press the 'Connect to Device' button to try again.";
408+
} else if (error.name == "SecurityError") {
409+
return "Permissions to access the serial port were not granted. Please check your browser settings and try again.";
410+
}
411+
return `Connect to Serial Port returned error: ${error}`;
412+
}
413+
414+
// Analyzes the error from the FSAPI and returns human readable feedback
415+
_suggestFileConnectActions(error) {
416+
if (error.name == "SecurityError") {
417+
return "Permissions to access the filesystem were not granted. Please check your browser settings and try again.";
418+
} else if (error.name == "AbortError") {
419+
return "No folder selected. Press the 'Select New Folder' button to try again.";
420+
}
421+
return `Connect to Filesystem returned error: ${error}`;
422+
423+
}
424+
376425
async showInfo(documentState) {
377426
return await this.infoDialog.open(this, documentState);
378427
}

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)