Skip to content

Commit 4f41259

Browse files
committed
Make a common method showConnectStatus() in workflow.js
Make all workflows able to use the connect status area in the modal connect dialog. - Replicated the connect status section to all workflows in index.js - Updated a few places where showMessage() is used to use showConnectStatus() instead. - Added some calls in the BLE workflow to take advantage of showConnectStatus()
1 parent 90c157b commit 4f41259

4 files changed

Lines changed: 72 additions & 52 deletions

File tree

index.html

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,23 @@ <h1>Web Bluetooth not available!</h1>
221221
<div class="step-number"></div>
222222
<div class="step-content">
223223
<h1>Request Bluetooth Device</h1>
224-
<p>CircuitPython boards with <a href="https://circuitpython.org/downloads?features=Bluetooth%2FBTLE">nrf chips need
225-
CircuitPython 7.0.0 or newer</a>. The first time a device is connected to your host,
226-
you'll need to enable public broadcasting by pressing reset when the faster, blue blink
227-
is happening on start up. The device will reset and the second, blue blink will be solid
228-
when done successfully.</p>
229-
<p>
224+
<p> See the <a href="https://learn.adafruit.com/wirelessly-code-your-bluetooth-device-with-circuitpython/device-setup">online documentation</a>
225+
for platform specific notes on how to use Bluetooth. Note that CircuitPython boards with <a href="https://circuitpython.org/downloads?features=Bluetooth%2FBTLE">nrf chips need
226+
CircuitPython 7.0.0 or newer</a>.
227+
</p>
228+
<p> The first time a device is connected to your host, you'll need to enable
229+
public broadcasting by pressing reset (or bootsel on some devices) when the faster, blue blink
230+
is happening on start up. The device will reset and the second, blue blink will be solid
231+
when done successfully.</p>
230232
<button class="purple-button" id="requestBluetoothDevice">Request Bluetooth Device</button>
231233
</p>
232234
</div>
233235
</section>
236+
<section>
237+
<div class="connect-status" hidden>
238+
<div class="connect-status-content"></div>
239+
</div>
240+
</section>
234241
</div>
235242
</div>
236243
<div class="popup-modal shadow connect-dialog closable" data-popup-modal="web-connect">
@@ -264,6 +271,11 @@ <h1>Navigate to your Device</h1>
264271
a page on your device that loads this website onto the device and to avoid any cross domain security issues.</p>
265272
</div>
266273
</section>
274+
<section>
275+
<div class="connect-status" hidden>
276+
<div class="connect-status-content"></div>
277+
</div>
278+
</section>
267279
</div>
268280
</div>
269281
<div class="popup-modal shadow connect-dialog closable" data-popup-modal="usb-connect">

js/workflows/ble.js

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,13 @@ class BLEWorkflow extends Workflow {
7171
stepOne.classList.add("hidden");
7272
}
7373
try {
74+
this.clearConnectStatus();
7475
const devices = await bluetooth.getDevices();
7576
console.log(devices);
7677
this.connectionStep(devices.length > 0 ? 2 : 1);
77-
} catch (e) {
78-
console.log("New Permissions backend for Web Bluetooth not enabled. Go to chrome://flags/#enable-web-bluetooth-new-permissions-backend to enable.", e);
78+
} catch (error) {
79+
console.error(error);
80+
this.showConnectStatus(this._suggestBLEConnectActions(error));
7981
}
8082
} else {
8183
modal.querySelectorAll('.step:not(:first-of-type)').forEach((stepItem) => {
@@ -128,7 +130,7 @@ class BLEWorkflow extends Workflow {
128130
}
129131
catch (error) {
130132
console.error(error);
131-
await this._showMessage(error);
133+
this.showConnectStatus(this._suggestBLEConnectActions(error));
132134
}
133135
}
134136
}
@@ -152,7 +154,9 @@ class BLEWorkflow extends Workflow {
152154
try {
153155
this.bleServer = await device.gatt.connect();
154156
} catch (error) {
155-
await this._showMessage("Failed to connect to device. Try forgetting device from OS bluetooth devices and try again.");
157+
console.log(error);
158+
// TODO(ericzundel): Add to suggestBLEConnectAction if we can determine the exception type
159+
this.showConnectStatus("Failed to connect to device. Try forgetting device from OS bluetooth devices and try again.");
156160
// Disable the reconnect button
157161
this.connectionStep(1);
158162
}
@@ -169,31 +173,25 @@ class BLEWorkflow extends Workflow {
169173

170174
this.debugLog("connecting to " + device.name);
171175
try {
176+
this.clearConnectStatus();
172177
console.log('Watching advertisements from "' + device.name + '"...');
173178
console.log('If no advertisements are received, make sure the device is powered on and in range. You can also try resetting the device');
174179
await device.watchAdvertisements({signal: abortController.signal});
175180
}
176181
catch (error) {
177182
console.error(error);
178-
await this._showMessage(error);
183+
this.showConnectStatus(this._suggestBLEConnectActions(error));
179184
}
180185
}
181186

182187
// Request Bluetooth Device
183188
async onRequestBluetoothDeviceButtonClick(e) {
184-
//try {
185-
console.log('Requesting any Bluetooth device...');
186-
this.debugLog("Requesting device. Cancel if empty and try existing");
187-
let device = await this.requestDevice();
189+
console.log('Requesting any Bluetooth device...');
190+
this.debugLog("Requesting device. Cancel if empty and try existing");
191+
let device = await this.requestDevice();
188192

189-
console.log('> Requested ' + device.name);
190-
await this.connectToBluetoothDevice(device);
191-
/*}
192-
catch (error) {
193-
console.error(error);
194-
await this._showMessage(error);
195-
this.debugLog('No device selected. Try to connect to existing.');
196-
}*/
193+
console.log('> Requested ' + device.name);
194+
await this.connectToBluetoothDevice(device);
197195
}
198196

199197
async switchToDevice(device) {
@@ -279,6 +277,16 @@ class BLEWorkflow extends Workflow {
279277
async showInfo(documentState) {
280278
return await this.infoDialog.open(this, documentState);
281279
}
280+
281+
// Analyze an exception and make user friendly suggestions
282+
_suggestBLEConnectActions(error) {
283+
if (error.name == "TypeError" &&
284+
(error.message.includes("getDevices is not a function")
285+
|| error.message.includes("watchAdvertisements is not a function"))) {
286+
return "Bluetooth API not available. Make sure you are loading from a secure context (HTTPS), then go to chrome://flags/#enable-web-bluetooth-new-permissions-backend to enable.";
287+
}
288+
return `Connect via Bluetooth returned error: ${error}`;
289+
}
282290
}
283291

284292
export {BLEWorkflow};

js/workflows/usb.js

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ class USBWorkflow extends Workflow {
8484

8585
async connect() {
8686
let result;
87-
this._clearStatus();
8887
if (result = await super.connect() instanceof Error) {
8988
return result;
9089
}
@@ -167,14 +166,14 @@ class USBWorkflow extends Workflow {
167166

168167
btnRequestSerialDevice.disabled = true;
169168
btnSelectHostFolder.disabled = true;
170-
this._clearStatus();
169+
this.clearConnectStatus();
171170
let serialConnect = async (event) => {
172171
try {
173-
this._clearStatus();
172+
this.clearConnectStatus();
174173
await this.connectToSerial();
175174
} catch (e) {
176175
console.log('connectToSerial() returned error: ', e);
177-
this._showStatus(this._suggestSerialConnectActions(e))
176+
this.showConnectStatus(this._suggestSerialConnectActions(e));
178177
}
179178
};
180179
btnRequestSerialDevice.removeEventListener('click', serialConnect);
@@ -183,10 +182,10 @@ class USBWorkflow extends Workflow {
183182
btnSelectHostFolder.removeEventListener('click', this._btnSelectHostFolderCallback)
184183
this._btnSelectHostFolderCallback = async (event) => {
185184
try {
186-
this._clearStatus();
185+
this.clearConnectStatus();
187186
await this._selectHostFolder();
188187
} catch (e) {
189-
this._showStatus(this._suggestFileConnectActions(e))
188+
this.showConnectStatus(this._suggestFileConnectActions(e));
190189
}
191190
};
192191
btnSelectHostFolder.addEventListener('click', this._btnSelectHostFolderCallback);
@@ -281,7 +280,7 @@ class USBWorkflow extends Workflow {
281280
this._serialDevice = device;
282281
console.log("switch to", this._serialDevice);
283282
await this._serialDevice.open({baudRate: 115200}); // Throws if something else is already connected or it isn't found.
284-
console.log("Starting Read Loop")
283+
console.log("Starting Read Loop");
285284
this._readLoopPromise = this._readSerialLoop().catch(
286285
async function(error) {
287286
await this.onDisconnected();
@@ -378,27 +377,6 @@ print(binascii.hexlify(microcontroller.cpu.uid).decode('ascii').upper())`
378377
console.log("Read Loop Stopped. Closing Serial Port.");
379378
}
380379

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-
402380
// Analyzes the error returned from the WebSerial API and returns human readable feedback.
403381
_suggestSerialConnectActions(error) {
404382
if (error.name == "NetworkError" && error.message.includes("Failed to open serial port")) {
@@ -417,7 +395,7 @@ print(binascii.hexlify(microcontroller.cpu.uid).decode('ascii').upper())`
417395
return "Permissions to access the filesystem were not granted. Please check your browser settings and try again.";
418396
} else if (error.name == "AbortError") {
419397
return "No folder selected. Press the 'Select New Folder' button to try again.";
420-
}
398+
} else if (error.name == "TypeError")
421399
return `Connect to Filesystem returned error: ${error}`;
422400

423401
}

js/workflows/workflow.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class Workflow {
8686
}
8787

8888
async connect() {
89+
this.clearConnectStatus();
8990
return await this.available();
9091
}
9192

@@ -337,6 +338,27 @@ class Workflow {
337338
}
338339
}
339340
}
341+
342+
clearConnectStatus(modal) {
343+
try {
344+
const modal = this.connectDialog.getModal();
345+
modal.querySelector('.connect-status').hidden = true;
346+
} catch (e) {
347+
console.log("Modal not active on clearStatus()", e);
348+
}
349+
}
350+
351+
showConnectStatus(message) {
352+
try {
353+
const modal = this.connectDialog.getModal();
354+
const statusBox = modal.querySelector('.connect-status');
355+
statusBox.hidden = false;
356+
let statusContentBox = statusBox.querySelector('.connect-status-content');
357+
statusContentBox.innerHTML = message;
358+
} catch (e) {
359+
console.log("Modal not active on showStatus()", e);
360+
}
361+
}
340362
}
341363

342364
export {

0 commit comments

Comments
 (0)