1
1
import { injectable , inject } from 'inversify' ;
2
- import { deepClone } from '@theia/core/lib/common/objects' ;
3
2
import { Emitter , Event } from '@theia/core/lib/common/event' ;
4
3
import { MessageService } from '@theia/core/lib/common/message-service' ;
5
4
import {
@@ -23,7 +22,6 @@ import { nls } from '@theia/core/lib/common/nls';
23
22
24
23
@injectable ( )
25
24
export class SerialConnectionManager {
26
- protected _state : Serial . State = [ ] ;
27
25
protected config : Partial < SerialConfig > = {
28
26
board : undefined ,
29
27
port : undefined ,
@@ -61,7 +59,9 @@ export class SerialConnectionManager {
61
59
protected readonly boardsServiceProvider : BoardsServiceProvider ,
62
60
@inject ( MessageService ) protected messageService : MessageService ,
63
61
@inject ( ThemeService ) protected readonly themeService : ThemeService ,
64
- @inject ( CoreService ) protected readonly core : CoreService
62
+ @inject ( CoreService ) protected readonly core : CoreService ,
63
+ @inject ( BoardsServiceProvider )
64
+ protected readonly boardsServiceClientImpl : BoardsServiceProvider
65
65
) {
66
66
this . serialServiceClient . onWebSocketChanged (
67
67
this . handleWebSocketChanged . bind ( this )
@@ -129,17 +129,16 @@ export class SerialConnectionManager {
129
129
this . config = { ...this . config , [ key ] : newConfig [ key ] } ;
130
130
}
131
131
} ) ;
132
- if (
133
- configHasChanged &&
134
- this . widgetsAttached ( ) &&
135
- ! ( await this . core . isUploading ( ) )
136
- ) {
132
+
133
+ if ( configHasChanged ) {
137
134
this . serialService . updateWsConfigParam ( {
138
135
currentBaudrate : this . config . baudRate ,
139
136
serialPort : this . config . port ?. address ,
140
137
} ) ;
141
- await this . disconnect ( ) ;
142
- await this . connect ( ) ;
138
+
139
+ if ( isSerialConfig ( this . config ) ) {
140
+ this . serialService . setSerialConfig ( this . config ) ;
141
+ }
143
142
}
144
143
}
145
144
@@ -159,61 +158,6 @@ export class SerialConnectionManager {
159
158
this . wsPort = wsPort ;
160
159
}
161
160
162
- /**
163
- * When the serial is open and the frontend is connected to the serial, we create the websocket here
164
- */
165
- protected createWsConnection ( ) : boolean {
166
- if ( this . wsPort ) {
167
- try {
168
- this . webSocket = new WebSocket ( `ws://localhost:${ this . wsPort } ` ) ;
169
- this . webSocket . onmessage = ( res ) => {
170
- const messages = JSON . parse ( res . data ) ;
171
- this . onReadEmitter . fire ( { messages } ) ;
172
- } ;
173
- return true ;
174
- } catch {
175
- return false ;
176
- }
177
- }
178
- return false ;
179
- }
180
-
181
- /**
182
- * Sets the types of connections needed by the client.
183
- *
184
- * @param newState The array containing the list of desired connections.
185
- * If the previuos state was empty and 'newState' is not, it tries to reconnect to the serial service
186
- * If the provios state was NOT empty and now it is, it disconnects to the serial service
187
- * @returns The status of the operation
188
- */
189
- protected async setState ( newState : Serial . State ) : Promise < Status > {
190
- const oldState = deepClone ( this . _state ) ;
191
- let status = Status . OK ;
192
-
193
- if ( this . widgetsAttached ( oldState ) && ! this . widgetsAttached ( newState ) ) {
194
- status = await this . disconnect ( ) ;
195
- } else if (
196
- ! this . widgetsAttached ( oldState ) &&
197
- this . widgetsAttached ( newState )
198
- ) {
199
- if ( await this . core . isUploading ( ) ) {
200
- this . messageService . error ( `Cannot open serial port when uploading` ) ;
201
- return Status . NOT_CONNECTED ;
202
- }
203
- status = await this . connect ( ) ;
204
- }
205
- this . _state = newState ;
206
- return status ;
207
- }
208
-
209
- protected get state ( ) : Serial . State {
210
- return this . _state ;
211
- }
212
-
213
- widgetsAttached ( state ?: Serial . State ) : boolean {
214
- return ( state ? state : this . _state ) . length > 0 ;
215
- }
216
-
217
161
get serialConfig ( ) : SerialConfig | undefined {
218
162
return isSerialConfig ( this . config )
219
163
? ( this . config as SerialConfig )
@@ -224,52 +168,36 @@ export class SerialConnectionManager {
224
168
return await this . serialService . isSerialPortOpen ( ) ;
225
169
}
226
170
227
- /**
228
- * Called when a client opens the serial from the GUI
229
- *
230
- * @param type could be either 'Monitor' or 'Plotter'. If it's 'Monitor' we also connect to the websocket and
231
- * listen to the message events
232
- * @returns the status of the operation
233
- */
234
- async openSerial ( type : Serial . Type ) : Promise < Status > {
171
+ openSerial ( ) : void {
235
172
if ( ! isSerialConfig ( this . config ) ) {
236
173
this . messageService . error (
237
174
`Please select a board and a port to open the serial connection.`
238
175
) ;
239
- return Status . NOT_CONNECTED ;
176
+ return ;
177
+ }
178
+
179
+ if ( ! this . webSocket && this . wsPort ) {
180
+ try {
181
+ this . webSocket = new WebSocket ( `ws://localhost:${ this . wsPort } ` ) ;
182
+ this . webSocket . onmessage = ( res ) => {
183
+ const messages = JSON . parse ( res . data ) ;
184
+ this . onReadEmitter . fire ( { messages } ) ;
185
+ } ;
186
+ } catch {
187
+ this . messageService . error ( `Unable to connect to websocket` ) ;
188
+ }
240
189
}
241
- if ( this . state . includes ( type ) ) return Status . OK ;
242
- const newState = deepClone ( this . state ) ;
243
- newState . push ( type ) ;
244
- const status = await this . setState ( newState ) ;
245
- if ( Status . isOK ( status ) && type === Serial . Type . Monitor )
246
- this . createWsConnection ( ) ;
247
- return status ;
248
190
}
249
191
250
- /**
251
- * Called when a client closes the serial from the GUI
252
- *
253
- * @param type could be either 'Monitor' or 'Plotter'. If it's 'Monitor' we close the websocket connection
254
- * @returns the status of the operation
255
- */
256
- async closeSerial ( type : Serial . Type ) : Promise < Status > {
257
- const index = this . state . indexOf ( type ) ;
258
- let status = Status . OK ;
259
- if ( index >= 0 ) {
260
- const newState = deepClone ( this . state ) ;
261
- newState . splice ( index , 1 ) ;
262
- status = await this . setState ( newState ) ;
263
- if (
264
- Status . isOK ( status ) &&
265
- type === Serial . Type . Monitor &&
266
- this . webSocket
267
- ) {
192
+ closeSerial ( ) : void {
193
+ if ( this . webSocket ) {
194
+ try {
268
195
this . webSocket . close ( ) ;
269
196
this . webSocket = undefined ;
197
+ } catch {
198
+ this . messageService . error ( `Unable to close websocket` ) ;
270
199
}
271
200
}
272
- return status ;
273
201
}
274
202
275
203
/**
@@ -330,7 +258,7 @@ export class SerialConnectionManager {
330
258
}
331
259
}
332
260
333
- if ( this . widgetsAttached ( ) ) {
261
+ if ( ( await this . serialService . clientsAttached ( ) ) > 0 ) {
334
262
if ( this . serialErrors . length >= 10 ) {
335
263
this . messageService . warn (
336
264
nls . localize (
@@ -362,36 +290,56 @@ export class SerialConnectionManager {
362
290
)
363
291
) ;
364
292
this . reconnectTimeout = window . setTimeout (
365
- ( ) => this . connect ( ) ,
293
+ ( ) => this . reconnectAfterUpload ( ) ,
366
294
timeout
367
295
) ;
368
296
}
369
297
}
370
298
}
371
299
372
- async connect ( ) : Promise < Status > {
373
- if ( await this . serialService . isSerialPortOpen ( ) )
374
- return Status . ALREADY_CONNECTED ;
375
- if ( ! isSerialConfig ( this . config ) ) return Status . NOT_CONNECTED ;
376
-
377
- console . info (
378
- `>>> Creating serial connection for ${ Board . toString (
379
- this . config . board
380
- ) } on port ${ Port . toString ( this . config . port ) } ...`
381
- ) ;
382
- const connectStatus = await this . serialService . connect ( this . config ) ;
383
- if ( Status . isOK ( connectStatus ) ) {
384
- console . info (
385
- `<<< Serial connection created for ${ Board . toString ( this . config . board , {
386
- useFqbn : false ,
387
- } ) } on port ${ Port . toString ( this . config . port ) } .`
300
+ // async connect(): Promise<Status> {
301
+ // if (await this.serialService.isSerialPortOpen())
302
+ // return Status.ALREADY_CONNECTED;
303
+ // if (!isSerialConfig(this.config)) return Status.NOT_CONNECTED;
304
+
305
+ // console.info(
306
+ // `>>> Creating serial connection for ${Board.toString(
307
+ // this.config.board
308
+ // )} on port ${Port.toString(this.config.port)}...`
309
+ // );
310
+ // const connectStatus = await this.serialService.connect(this.config);
311
+ // if (Status.isOK(connectStatus)) {
312
+ // console.info(
313
+ // `<<< Serial connection created for ${Board.toString(this.config.board, {
314
+ // useFqbn: false,
315
+ // }) } on port ${Port.toString(this.config.port)}.`
316
+ // );
317
+ // }
318
+
319
+ // return Status.isOK(connectStatus);
320
+ // }
321
+
322
+ async reconnectAfterUpload ( ) : Promise < void > {
323
+ try {
324
+ if ( isSerialConfig ( this . config ) ) {
325
+ await this . boardsServiceClientImpl . waitUntilAvailable (
326
+ Object . assign ( this . config . board , { port : this . config . port } ) ,
327
+ 10_000
328
+ ) ;
329
+ this . serialService . connectSerialIfRequired ( ) ;
330
+ }
331
+ } catch ( waitError ) {
332
+ this . messageService . error (
333
+ nls . localize (
334
+ 'arduino/sketch/couldNotConnectToSerial' ,
335
+ 'Could not reconnect to serial port. {0}' ,
336
+ waitError . toString ( )
337
+ )
388
338
) ;
389
339
}
390
-
391
- return Status . isOK ( connectStatus ) ;
392
340
}
393
341
394
- async disconnect ( ) : Promise < Status > {
342
+ async disconnectSerialPort ( ) : Promise < Status > {
395
343
if ( ! ( await this . serialService . isSerialPortOpen ( ) ) ) {
396
344
return Status . OK ;
397
345
}
0 commit comments