Skip to content

Commit f471b1f

Browse files
authored
Show a clear error on OS driver errors (#70)
Add more handlers for catching when the OS denies access to the driver. This is very likely to be one of the first issues anyone encounters and it's more likely they'll see a clear error message with next steps.
1 parent 9038af0 commit f471b1f

6 files changed

Lines changed: 456 additions & 123 deletions

File tree

demo/advanced.html

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@
7575

7676
// We'll drop these into the Window object so we can play with them in
7777
// the DevTools console if we want to.
78-
window.WebLabel = WebLabel;
79-
window.WebDevices = WebDevices;
78+
(window as any).WebLabel = WebLabel;
79+
(window as any).WebDevices = WebDevices;
8080

8181
// For this demo we're going to make use of the USB printer manager
8282
// so it can take care of concerns like the USB connect and disconnect events.
@@ -104,11 +104,50 @@
104104
// We'll wire up some basic event listeners to the printer manager.
105105
// First, a button to prompt a user to add a printer.
106106
const addPrinterBtn = document.getElementById('addprinter')!;
107-
addPrinterBtn.addEventListener('click', async () => printerMgr.promptForNewDevice());
107+
addPrinterBtn.addEventListener('click', async () => {
108+
try {
109+
await printerMgr.promptForNewDevice();
110+
} catch (e) {
111+
if (e instanceof WebDevices.DriverAccessDeniedError) {
112+
deviceErrorAlert();
113+
} else {
114+
throw e;
115+
}
116+
}
117+
});
118+
119+
// And a function to call if it fails
120+
function deviceErrorAlert() {
121+
// This happens when the operating system didn't let Chrome connect.
122+
// Usually either another tab is open talking to the device, or the driver
123+
// is already loaded by another application.
124+
showAlert(
125+
'danger',
126+
'alert-printer-comm-error',
127+
`Operating system denied device access`,
128+
`<p>Chrome wasn't allowed to connect to a device. This usually happens because:
129+
<ul>
130+
<li>Another browser tab is already connected to that device.
131+
<li>You're on Windows and <a href="https://cellivar.github.io/WebZLP/docs/windows_driver">need to replace the driver for the device</a>.
132+
<li>Another application loaded a driver to talk to the device.
133+
</ul>
134+
Fix the issue and re-connect to the device.</p>`
135+
);
136+
}
108137

109138
// Next a button to manually refresh all printers, just in case.
110139
const refreshPrinterBtn = document.getElementById('refreshPrinters')!;
111-
refreshPrinterBtn.addEventListener('click', async () => printerMgr.forceReconnect());
140+
refreshPrinterBtn.addEventListener('click', async () => {
141+
try {
142+
await printerMgr.forceReconnect();
143+
} catch (e) {
144+
if (e instanceof WebDevices.DriverAccessDeniedError) {
145+
deviceErrorAlert();
146+
} else {
147+
throw e;
148+
}
149+
}
150+
});
112151

113152
// Next we wire up some events on the UsbDeviceManager itself.
114153
printerMgr.addEventListener('connectedDevice', ({ detail }) => {
@@ -174,13 +213,13 @@
174213
// commands or configs specific to their printers.
175214
// Sensors
176215
modalZplRibbonTHold: HTMLInputElement
177-
modalZplRibbonGain : HTMLInputElement
216+
modalZplRibbonGain : HTMLInputElement
178217
modalZplWebTHold : HTMLInputElement
179218
modalZplWebMedia : HTMLInputElement
180-
modalZplTransGain : HTMLInputElement
219+
modalZplTransGain : HTMLInputElement
181220
modalZplMarkTHold : HTMLInputElement
182221
modalZplMarkMedia : HTMLInputElement
183-
modalZplMarkGain : HTMLInputElement
222+
modalZplMarkGain : HTMLInputElement
184223

185224
modalZplWithSensorGraph: HTMLInputElement
186225

@@ -748,33 +787,17 @@ <h4>${titleHtml}</h4>
748787
// and let it take over the UI.
749788
await app.init();
750789

751-
// Make the TypeScript type system happy by adding a property to the Window object.
752-
declare global {
753-
interface Window { label_app: BasicLabelDesignerApp }
754-
}
755790
// Now we can access our printer in the dev console if we want to mess with it!
756-
window.label_app = app;
791+
(window as any).label_app = app;
757792

758793
// Now we'll fire the reconnect since our UI is wired up.
759794
try {
760795
await printerMgr.forceReconnect();
761796
} catch (e) {
762797
if (e instanceof WebDevices.DriverAccessDeniedError) {
763-
// This happens when the operating system didn't let Chrome connect.
764-
// Usually either another tab is open talking to the device, or the driver
765-
// is already loaded by another application.
766-
showAlert(
767-
'danger',
768-
'alert-printer-comm-error',
769-
`Operating system refused device access`,
770-
`<p>This usually happens for one of these reasons:
771-
<ul>
772-
<li>Another browser tab is already connected.
773-
<li>Another application loaded a driver to talk to the device.
774-
<li>You're on Windows and need to replace the driver.
775-
</ul>
776-
Fix the issue and re-connect to the device.</p>`
777-
);
798+
deviceErrorAlert();
799+
} else {
800+
throw e;
778801
}
779802
}
780803

demo/editor.html

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@
7272
// Internally it makes use of an HTML canvas, and thus it's easy to plug into
7373
// WebZLP for label designing!
7474
// Import the canvas editor lib and create a canvas to use for printing.
75-
import * as Editor from 'fabricjs-label-editor'
7675
import * as WebLabel from 'webzlp';
7776
import * as WebDevices from 'web-device-mux';
77+
import * as Editor from 'fabricjs-label-editor'
7878
(window as any).FabricEditor = Editor;
7979
(window as any).WebLabel = WebLabel;
8080
(window as any).WebDevices = WebDevices;
@@ -85,9 +85,6 @@
8585
// For this demo we're going to make use of the USB printer manager
8686
// so it can take care of concerns like the USB connect and disconnect events.
8787

88-
// For this demo we're going to make use of the USB printer manager
89-
// so it can take care of concerns like the USB connect and disconnect events.
90-
9188
// We'll set a type alias so it's easier to read our code
9289
type PrinterManager = WebDevices.UsbDeviceManager<WebLabel.LabelPrinterUsb>;
9390
// Then we'll construct one to use
@@ -111,11 +108,50 @@
111108
// We'll wire up some basic event listeners to the printer manager.
112109
// First, a button to prompt a user to add a printer.
113110
const addPrinterBtn = document.getElementById('addprinter')!;
114-
addPrinterBtn.addEventListener('click', async () => printerMgr.promptForNewDevice());
111+
addPrinterBtn.addEventListener('click', async () => {
112+
try {
113+
await printerMgr.promptForNewDevice();
114+
} catch (e) {
115+
if (e instanceof WebDevices.DriverAccessDeniedError) {
116+
deviceErrorAlert();
117+
} else {
118+
throw e;
119+
}
120+
}
121+
});
122+
123+
// And a function to call if it fails
124+
function deviceErrorAlert() {
125+
// This happens when the operating system didn't let Chrome connect.
126+
// Usually either another tab is open talking to the device, or the driver
127+
// is already loaded by another application.
128+
showAlert(
129+
'danger',
130+
'alert-printer-comm-error',
131+
`Operating system denied device access`,
132+
`<p>Chrome wasn't allowed to connect to a device. This usually happens because:
133+
<ul>
134+
<li>Another browser tab is already connected to that device.
135+
<li>You're on Windows and <a href="https://cellivar.github.io/WebZLP/docs/windows_driver">need to replace the driver for the device</a>.
136+
<li>Another application loaded a driver to talk to the device.
137+
</ul>
138+
Fix the issue and re-connect to the device.</p>`
139+
);
140+
}
115141

116142
// Next a button to manually refresh all printers, just in case.
117143
const refreshPrinterBtn = document.getElementById('refreshPrinters')!;
118-
refreshPrinterBtn.addEventListener('click', async () => printerMgr.forceReconnect());
144+
refreshPrinterBtn.addEventListener('click', async () => {
145+
try {
146+
await printerMgr.forceReconnect();
147+
} catch (e) {
148+
if (e instanceof WebDevices.DriverAccessDeniedError) {
149+
deviceErrorAlert();
150+
} else {
151+
throw e;
152+
}
153+
}
154+
});
119155

120156
// Get some bookkeeping out of the way..
121157
// First we create an interface to describe our settings form.
@@ -156,7 +192,6 @@
156192
modalZplHeadCloseAction: HTMLSelectElement
157193
}
158194

159-
160195
// A function to find and hide any alerts for a given alert ID.
161196
function hideAlerts(alertId: string) {
162197
const existingAlerts = document.getElementById('printerAlertSpace')?.querySelectorAll(`.${alertId}`) ?? [];
@@ -685,21 +720,9 @@ <h4>${titleHtml}</h4>
685720
await printerMgr.forceReconnect();
686721
} catch (e) {
687722
if (e instanceof WebDevices.DriverAccessDeniedError) {
688-
// This happens when the operating system didn't let Chrome connect.
689-
// Usually either another tab is open talking to the device, or the driver
690-
// is already loaded by another application.
691-
showAlert(
692-
'danger',
693-
'alert-printer-comm-error',
694-
`Operating system refused device access`,
695-
`<p>This usually happens for one of these reasons:
696-
<ul>
697-
<li>Another browser tab is already connected.
698-
<li>Another application loaded a driver to talk to the device.
699-
<li>You're on Windows and need to replace the driver.
700-
</ul>
701-
Fix the issue and re-connect to the device.</p>`
702-
);
723+
deviceErrorAlert();
724+
} else {
725+
throw e;
703726
}
704727
}
705728

0 commit comments

Comments
 (0)