@@ -35,6 +35,7 @@ export interface MicrobitRadioBridgeConnectionOptions {
35
35
interface ConnectCallbacks {
36
36
onConnecting : ( ) => void ;
37
37
onReconnecting : ( ) => void ;
38
+ onRestartConnection : ( ) => void ;
38
39
onFail : ( ) => void ;
39
40
onSuccess : ( ) => void ;
40
41
}
@@ -54,8 +55,12 @@ export class MicrobitRadioBridgeConnection
54
55
private remoteDeviceId : number | undefined ;
55
56
private disconnectPromise : Promise < void > | undefined ;
56
57
private serialSessionOpen = false ;
58
+ private ignoreDelegateStatus = false ;
57
59
58
60
private delegateStatusListener = ( e : ConnectionStatusEvent ) => {
61
+ if ( this . ignoreDelegateStatus ) {
62
+ return ;
63
+ }
59
64
const currentStatus = this . status ;
60
65
if ( e . status !== ConnectionStatus . CONNECTED ) {
61
66
this . setStatus ( e . status ) ;
@@ -122,7 +127,7 @@ export class MicrobitRadioBridgeConnection
122
127
type : "Connect" ,
123
128
message : "Serial connect start" ,
124
129
} ) ;
125
-
130
+ this . ignoreDelegateStatus = false ;
126
131
await this . delegate . connect ( ) ;
127
132
128
133
try {
@@ -139,17 +144,23 @@ export class MicrobitRadioBridgeConnection
139
144
this . setStatus ( ConnectionStatus . RECONNECTING ) ;
140
145
}
141
146
} ,
147
+ onRestartConnection : ( ) => {
148
+ // So that serial session does not get repetitively disposed in
149
+ // delegate status listener when delegate is disconnected for restarting connection
150
+ this . ignoreDelegateStatus = true ;
151
+ } ,
142
152
onFail : ( ) => {
143
153
if ( this . status !== ConnectionStatus . DISCONNECTED ) {
144
154
this . setStatus ( ConnectionStatus . DISCONNECTED ) ;
145
155
}
146
- this . serialSession ?. dispose ( ) ;
156
+ this . ignoreDelegateStatus = false ;
147
157
this . serialSessionOpen = false ;
148
158
} ,
149
159
onSuccess : ( ) => {
150
160
if ( this . status !== ConnectionStatus . CONNECTED ) {
151
161
this . setStatus ( ConnectionStatus . CONNECTED ) ;
152
162
}
163
+ this . ignoreDelegateStatus = false ;
153
164
this . serialSessionOpen = true ;
154
165
} ,
155
166
} ,
@@ -177,9 +188,9 @@ export class MicrobitRadioBridgeConnection
177
188
if ( this . disconnectPromise ) {
178
189
return this . disconnectPromise ;
179
190
}
191
+ this . serialSessionOpen = false ;
180
192
this . disconnectPromise = ( async ( ) => {
181
- this . serialSessionOpen = false ;
182
- await this . serialSession ?. dispose ( ) ;
193
+ await this . serialSession ?. dispose ( true ) ;
183
194
this . disconnectPromise = undefined ;
184
195
} ) ( ) ;
185
196
}
@@ -210,6 +221,7 @@ class RadioBridgeSerialSession {
210
221
private onPeriodicMessageReceived : ( ( ) => void ) | undefined ;
211
222
private lastReceivedMessageTimestamp : number | undefined ;
212
223
private connectionCheckIntervalId : ReturnType < typeof setInterval > | undefined ;
224
+ private isRestartingConnection : boolean = false ;
213
225
214
226
private serialErrorListener = ( e : unknown ) => {
215
227
this . logging . error ( "Serial error" , e ) ;
@@ -289,7 +301,11 @@ class RadioBridgeSerialSession {
289
301
this . delegate . addEventListener ( "serialdata" , this . serialDataListener ) ;
290
302
this . delegate . addEventListener ( "serialerror" , this . serialErrorListener ) ;
291
303
try {
292
- this . callbacks . onConnecting ( ) ;
304
+ if ( this . isRestartingConnection ) {
305
+ this . callbacks . onReconnecting ( ) ;
306
+ } else {
307
+ this . callbacks . onConnecting ( ) ;
308
+ }
293
309
await this . handshake ( ) ;
294
310
295
311
this . logging . log ( `Serial: using remote device id ${ this . remoteDeviceId } ` ) ;
@@ -330,14 +346,16 @@ class RadioBridgeSerialSession {
330
346
// TODO: in the first-time connection case we used to move the error/disconnect to the background here, why? timing?
331
347
await periodicMessagePromise ;
332
348
333
- this . startConnectionCheck ( ) ;
349
+ this . isRestartingConnection = false ;
350
+ await this . startConnectionCheck ( ) ;
334
351
this . callbacks . onSuccess ( ) ;
335
352
} catch ( e ) {
336
353
this . callbacks . onFail ( ) ;
354
+ await this . dispose ( ) ;
337
355
}
338
356
}
339
357
340
- async dispose ( ) {
358
+ async dispose ( disconnect : boolean = false ) {
341
359
this . stopConnectionCheck ( ) ;
342
360
try {
343
361
await this . sendCmdWaitResponse ( protocol . generateCmdStop ( ) ) ;
@@ -347,6 +365,9 @@ class RadioBridgeSerialSession {
347
365
this . responseMap . clear ( ) ;
348
366
this . delegate . removeEventListener ( "serialdata" , this . serialDataListener ) ;
349
367
this . delegate . removeEventListener ( "serialerror" , this . serialErrorListener ) ;
368
+ if ( disconnect ) {
369
+ await this . delegate . disconnect ( ) ;
370
+ }
350
371
await this . delegate . softwareReset ( ) ;
351
372
}
352
373
@@ -366,10 +387,10 @@ class RadioBridgeSerialSession {
366
387
return responsePromise ;
367
388
}
368
389
369
- private startConnectionCheck ( ) {
390
+ private async startConnectionCheck ( ) {
370
391
// Check for connection lost
371
392
if ( this . connectionCheckIntervalId === undefined ) {
372
- this . connectionCheckIntervalId = setInterval ( ( ) => {
393
+ this . connectionCheckIntervalId = setInterval ( async ( ) => {
373
394
if (
374
395
this . lastReceivedMessageTimestamp &&
375
396
Date . now ( ) - this . lastReceivedMessageTimestamp <= 1_000
@@ -382,7 +403,7 @@ class RadioBridgeSerialSession {
382
403
) {
383
404
this . logging . event ( {
384
405
type : "Serial" ,
385
- message : "Serial connection lost - attempting to reconnect" ,
406
+ message : "Serial connection lost...attempt to reconnect" ,
386
407
} ) ;
387
408
this . callbacks . onReconnecting ( ) ;
388
409
}
@@ -391,16 +412,24 @@ class RadioBridgeSerialSession {
391
412
Date . now ( ) - this . lastReceivedMessageTimestamp >
392
413
connectTimeoutDuration
393
414
) {
394
- this . logging . event ( {
395
- type : "Serial" ,
396
- message : "Serial connection lost" ,
397
- } ) ;
398
- this . callbacks . onFail ( ) ;
415
+ await this . restartConnection ( ) ;
399
416
}
400
417
} , 1000 ) ;
401
418
}
402
419
}
403
420
421
+ private async restartConnection ( ) {
422
+ this . isRestartingConnection = true ;
423
+ this . logging . event ( {
424
+ type : "Serial" ,
425
+ message : "Serial connection lost...restart connection" ,
426
+ } ) ;
427
+ this . callbacks . onRestartConnection ( ) ;
428
+ await this . dispose ( true ) ;
429
+ await this . delegate . connect ( ) ;
430
+ await this . connect ( ) ;
431
+ }
432
+
404
433
private stopConnectionCheck ( ) {
405
434
clearInterval ( this . connectionCheckIntervalId ) ;
406
435
this . connectionCheckIntervalId = undefined ;
0 commit comments