Skip to content

Commit 4594d86

Browse files
Only start serial when a listener is added (#8)
1 parent 55b09c4 commit 4594d86

File tree

3 files changed

+83
-8
lines changed

3 files changed

+83
-8
lines changed

lib/device.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ export type FlashDataSource = (
9898
) => Promise<string | Uint8Array>;
9999

100100
export interface ConnectOptions {
101-
serial?: boolean;
102101
// Name filter used for Web Bluetooth
103102
name?: string;
104103
}

lib/usb.ts

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ import {
2626
} from "./device.js";
2727
import { TypedEventTarget } from "./events.js";
2828

29+
interface InternalConnectOptions extends ConnectOptions {
30+
serial?: boolean;
31+
}
32+
2933
// Temporary workaround for ChromeOS 105 bug.
3034
// See https://bugs.chromium.org/p/chromium/issues/detail?id=1363712&q=usb&can=2
3135
export const isChromeOS105 = (): boolean => {
@@ -120,7 +124,9 @@ export class MicrobitWebUSBConnection
120124
setTimeout(() => {
121125
if (this.status === ConnectionStatus.CONNECTED) {
122126
this.unloading = false;
123-
this.startSerialInternal();
127+
if (this.addedListeners.serialdata) {
128+
this.startSerialInternal();
129+
}
124130
}
125131
}, assumePageIsStayingOpenDelay);
126132
},
@@ -130,11 +136,26 @@ export class MicrobitWebUSBConnection
130136

131137
private logging: Logging;
132138

139+
private _addEventListener = this.addEventListener;
140+
private _removeEventListener = this.removeEventListener;
141+
142+
private addedListeners = {
143+
serialdata: false,
144+
};
145+
133146
constructor(
134147
options: MicrobitWebUSBConnectionOptions = { logging: new NullLogging() },
135148
) {
136149
super();
137150
this.logging = options.logging;
151+
this.addEventListener = (type, ...args) => {
152+
this._addEventListener(type, ...args);
153+
this.startNotifications(type);
154+
};
155+
this.removeEventListener = (type, ...args) => {
156+
this.stopNotifications(type);
157+
this._removeEventListener(type, ...args);
158+
};
138159
}
139160

140161
private log(v: any) {
@@ -256,10 +277,12 @@ export class MicrobitWebUSBConnection
256277
} else {
257278
// This might not strictly be "reinstating". We should make this
258279
// behaviour configurable when pulling out a library.
259-
this.log("Reinstating serial after flash");
260-
if (this.connection.daplink) {
261-
await this.connection.daplink.connect();
262-
await this.startSerialInternal();
280+
if (this.addedListeners.serialdata) {
281+
this.log("Reinstating serial after flash");
282+
if (this.connection.daplink) {
283+
await this.connection.daplink.connect();
284+
await this.startSerialInternal();
285+
}
263286
}
264287
}
265288
}
@@ -387,13 +410,15 @@ export class MicrobitWebUSBConnection
387410
this.setStatus(ConnectionStatus.NO_AUTHORIZED_DEVICE);
388411
}
389412

390-
private async connectInternal(options: ConnectOptions): Promise<void> {
413+
private async connectInternal(
414+
options: InternalConnectOptions,
415+
): Promise<void> {
391416
if (!this.connection) {
392417
const device = await this.chooseDevice();
393418
this.connection = new DAPWrapper(device, this.logging);
394419
}
395420
await withTimeout(this.connection.reconnectAsync(), 10_000);
396-
if (options.serial === undefined || options.serial) {
421+
if (this.addedListeners.serialdata && options.serial !== false) {
397422
this.startSerialInternal();
398423
}
399424
this.setStatus(ConnectionStatus.CONNECTED);
@@ -410,6 +435,26 @@ export class MicrobitWebUSBConnection
410435
this.dispatchTypedEvent("afterrequestdevice", new AfterRequestDevice());
411436
return this.device;
412437
}
438+
439+
private async startNotifications(type: string) {
440+
switch (type as keyof DeviceConnectionEventMap) {
441+
case "serialdata": {
442+
this.startSerialInternal();
443+
this.addedListeners.serialdata = true;
444+
break;
445+
}
446+
}
447+
}
448+
449+
private async stopNotifications(type: string) {
450+
switch (type as keyof DeviceConnectionEventMap) {
451+
case "serialdata": {
452+
this.stopSerialInternal();
453+
this.addedListeners.serialdata = false;
454+
break;
455+
}
456+
}
457+
}
413458
}
414459

415460
const genericErrorSuggestingReconnect = (e: any) =>

src/demo.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
ConnectionStatus,
1212
ConnectionStatusEvent,
1313
DeviceConnection,
14+
SerialDataEvent,
1415
} from "../lib/device";
1516
import { MicrobitWebBluetoothConnection } from "../lib/bluetooth";
1617
import { AccelerometerDataEvent } from "../lib/accelerometer";
@@ -30,6 +31,10 @@ document.querySelector<HTMLDivElement>("#app")!.innerHTML = `
3031
<p class="status"></p>
3132
<label><div>File to flash</div><input type="file"/></label>
3233
<button class="flash">Flash</button>
34+
<div class="serial-controls">
35+
<button class="serial-listen">Listen to serial</button>
36+
<button class="serial-stop">Stop serial data</button>
37+
</div>
3338
<div class="acc-data-controls">
3439
<button class="acc-data-get">Get accelerometer data</button>
3540
<button class="acc-data-listen">Listen to accelerometer data</button>
@@ -73,6 +78,12 @@ const accPeriodInput = document.querySelector(
7378
const accPeriodSet = document.querySelector(
7479
"#flash > .acc-period-controls > .acc-period-set",
7580
)!;
81+
const serialListen = document.querySelector(
82+
"#flash > .serial-controls > .serial-listen",
83+
)!;
84+
const serialStop = document.querySelector(
85+
"#flash > .serial-controls > .serial-stop",
86+
)!;
7687

7788
const displayStatus = (status: ConnectionStatus) => {
7889
statusParagraph.textContent = status.toString();
@@ -212,3 +223,23 @@ accPeriodSet.addEventListener("click", async () => {
212223
);
213224
}
214225
});
226+
227+
let data = "";
228+
const serialDataListener = (event: SerialDataEvent) => {
229+
for (const char of event.data) {
230+
if (char === "\n") {
231+
console.log(data);
232+
data = "";
233+
} else {
234+
data += char;
235+
}
236+
}
237+
};
238+
239+
serialListen.addEventListener("click", async () => {
240+
connection.addEventListener("serialdata", serialDataListener);
241+
});
242+
243+
serialStop.addEventListener("click", async () => {
244+
connection.removeEventListener("serialdata", serialDataListener);
245+
});

0 commit comments

Comments
 (0)