Skip to content

Commit b5d093d

Browse files
Handle radio connecting, reconnecting, fail and success (#22)
Also, remove unused disconnecting state
1 parent 06289c9 commit b5d093d

File tree

2 files changed

+58
-37
lines changed

2 files changed

+58
-37
lines changed

lib/device.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,6 @@ export enum ConnectionStatus {
8181
* but has not been connected via the browser security UI.
8282
*/
8383
NO_AUTHORIZED_DEVICE = "NO_AUTHORIZED_DEVICE",
84-
/**
85-
* Disconnecting.
86-
*/
87-
DISCONNECTING = "DISCONNECTING",
8884
/**
8985
* Authorized device available but we haven't connected to it.
9086
*/

lib/usb-radio-bridge.ts

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ export interface MicrobitRadioBridgeConnectionOptions {
3232
logging: Logging;
3333
}
3434

35+
interface ConnectCallbacks {
36+
onConnecting: () => void;
37+
onReconnecting: () => void;
38+
onFail: () => void;
39+
onSuccess: () => void;
40+
}
41+
3542
/**
3643
* Wraps around a USB connection to implement a subset of services over a serial protocol.
3744
*
@@ -48,7 +55,7 @@ export class MicrobitRadioBridgeConnection
4855
private disconnectPromise: Promise<void> | undefined;
4956
private serialSessionOpen = false;
5057

51-
private delegateStatusListner = (e: ConnectionStatusEvent) => {
58+
private delegateStatusListener = (e: ConnectionStatusEvent) => {
5259
const currentStatus = this.status;
5360
if (e.status !== ConnectionStatus.CONNECTED) {
5461
this.setStatus(e.status);
@@ -84,11 +91,11 @@ export class MicrobitRadioBridgeConnection
8491
async initialize(): Promise<void> {
8592
await this.delegate.initialize();
8693
this.setStatus(this.statusFromDelegate());
87-
this.delegate.addEventListener("status", this.delegateStatusListner);
94+
this.delegate.addEventListener("status", this.delegateStatusListener);
8895
}
8996

9097
dispose(): void {
91-
this.delegate.removeEventListener("status", this.delegateStatusListner);
98+
this.delegate.removeEventListener("status", this.delegateStatusListener);
9299
this.delegate.dispose();
93100
}
94101

@@ -124,36 +131,39 @@ export class MicrobitRadioBridgeConnection
124131
this.remoteDeviceId,
125132
this.delegate,
126133
this.dispatchTypedEvent.bind(this),
127-
this.setStatus.bind(this),
128-
() => {
129-
// Remote connection lost
130-
this.logging.event({
131-
type: "Serial",
132-
message: "Serial connection lost 1",
133-
});
134-
// This is the point we tell the consumer that we're trying to reconnect
135-
// in the background.
136-
// Leave serial connection running in case the remote device comes back.
137-
},
138-
() => {
139-
// Remote connection... even more lost?
140-
this.logging.event({
141-
type: "Serial",
142-
message: "Serial connection lost 2",
143-
});
144-
this.serialSession?.dispose();
134+
{
135+
onConnecting: () => this.setStatus(ConnectionStatus.CONNECTING),
136+
onReconnecting: () => {
137+
// Leave serial connection running in case the remote device comes back.
138+
if (this.status !== ConnectionStatus.RECONNECTING) {
139+
this.setStatus(ConnectionStatus.RECONNECTING);
140+
}
141+
},
142+
onFail: () => {
143+
if (this.status !== ConnectionStatus.DISCONNECTED) {
144+
this.setStatus(ConnectionStatus.DISCONNECTED);
145+
}
146+
this.serialSession?.dispose();
147+
this.serialSessionOpen = false;
148+
},
149+
onSuccess: () => {
150+
if (this.status !== ConnectionStatus.CONNECTED) {
151+
this.setStatus(ConnectionStatus.CONNECTED);
152+
}
153+
this.serialSessionOpen = true;
154+
},
145155
},
146156
);
147157

148158
await this.serialSession.connect();
149-
this.serialSessionOpen = true;
150159

151160
this.logging.event({
152161
type: "Connect",
153162
message: "Serial connect success",
154163
});
155164
return this.status;
156165
} catch (e) {
166+
this.serialSessionOpen = false;
157167
this.logging.error("Failed to initialise serial protocol", e);
158168
this.logging.event({
159169
type: "Connect",
@@ -174,8 +184,13 @@ export class MicrobitRadioBridgeConnection
174184
})();
175185
}
176186

187+
private log(v: any) {
188+
this.logging.log(v);
189+
}
190+
177191
private setStatus(status: ConnectionStatus) {
178192
this.status = status;
193+
this.log("Radio connection status " + status);
179194
this.dispatchTypedEvent("status", new ConnectionStatusEvent(status));
180195
}
181196

@@ -267,18 +282,15 @@ class RadioBridgeSerialSession {
267282
private remoteDeviceId: number,
268283
private delegate: MicrobitWebUSBConnection,
269284
private dispatchTypedEvent: TypedServiceEventDispatcher,
270-
private onStatusChanged: (status: ConnectionStatus) => void,
271-
private onRemoteConnectionLost1: () => void,
272-
private onRemoteConnectionLost2: () => void,
285+
private callbacks: ConnectCallbacks,
273286
) {}
274287

275288
async connect() {
276289
this.delegate.addEventListener("serialdata", this.serialDataListener);
277290
this.delegate.addEventListener("serialerror", this.serialErrorListener);
278-
279291
try {
292+
this.callbacks.onConnecting();
280293
await this.handshake();
281-
this.onStatusChanged(ConnectionStatus.CONNECTED);
282294

283295
this.logging.log(`Serial: using remote device id ${this.remoteDeviceId}`);
284296
const remoteMbIdCommand = protocol.generateCmdRemoteMbId(
@@ -319,8 +331,9 @@ class RadioBridgeSerialSession {
319331
await periodicMessagePromise;
320332

321333
this.startConnectionCheck();
334+
this.callbacks.onSuccess();
322335
} catch (e) {
323-
this.dispose();
336+
this.callbacks.onFail();
324337
}
325338
}
326339

@@ -335,8 +348,6 @@ class RadioBridgeSerialSession {
335348
this.delegate.removeEventListener("serialdata", this.serialDataListener);
336349
this.delegate.removeEventListener("serialerror", this.serialErrorListener);
337350
await this.delegate.softwareReset();
338-
339-
this.onStatusChanged(ConnectionStatus.DISCONNECTED);
340351
}
341352

342353
private async sendCmdWaitResponse(
@@ -358,19 +369,33 @@ class RadioBridgeSerialSession {
358369
private startConnectionCheck() {
359370
// Check for connection lost
360371
if (this.connectionCheckIntervalId === undefined) {
361-
this.connectionCheckIntervalId = setInterval(async () => {
372+
this.connectionCheckIntervalId = setInterval(() => {
373+
if (
374+
this.lastReceivedMessageTimestamp &&
375+
Date.now() - this.lastReceivedMessageTimestamp <= 1_000
376+
) {
377+
this.callbacks.onSuccess();
378+
}
362379
if (
363380
this.lastReceivedMessageTimestamp &&
364381
Date.now() - this.lastReceivedMessageTimestamp > 1_000
365382
) {
366-
this.onRemoteConnectionLost1();
383+
this.logging.event({
384+
type: "Serial",
385+
message: "Serial connection lost - attempting to reconnect",
386+
});
387+
this.callbacks.onReconnecting();
367388
}
368389
if (
369390
this.lastReceivedMessageTimestamp &&
370391
Date.now() - this.lastReceivedMessageTimestamp >
371392
connectTimeoutDuration
372393
) {
373-
this.onRemoteConnectionLost2();
394+
this.logging.event({
395+
type: "Serial",
396+
message: "Serial connection lost",
397+
});
398+
this.callbacks.onFail();
374399
}
375400
}, 1000);
376401
}

0 commit comments

Comments
 (0)