@@ -2,7 +2,6 @@ import { injectable, inject, postConstruct } from 'inversify';
22import { deepClone } from '@theia/core/lib/common/objects' ;
33import { Emitter , Event } from '@theia/core/lib/common/event' ;
44import { MessageService } from '@theia/core/lib/common/message-service' ;
5- import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state' ;
65import {
76 MonitorService ,
87 MonitorConfig ,
@@ -23,13 +22,8 @@ import { NotificationCenter } from '../notification-center';
2322import { ThemeService } from '@theia/core/lib/browser/theming' ;
2423import { nls } from '@theia/core/lib/browser/nls' ;
2524
26- export enum SerialType {
27- Monitor = 'Monitor' ,
28- Plotter = 'Plotter' ,
29- }
30-
3125@injectable ( )
32- export class MonitorConnection {
26+ export class SerialConnectionManager {
3327 @inject ( MonitorModel )
3428 protected readonly monitorModel : MonitorModel ;
3529
@@ -51,26 +45,19 @@ export class MonitorConnection {
5145 @inject ( MessageService )
5246 protected messageService : MessageService ;
5347
54- @inject ( FrontendApplicationStateService )
55- protected readonly applicationState : FrontendApplicationStateService ;
56-
57- @inject ( MonitorModel )
58- protected readonly model : MonitorModel ;
59-
6048 @inject ( ThemeService )
6149 protected readonly themeService : ThemeService ;
62-
63- protected _state : MonitorConnection . State = [ ] ;
50+ protected _state : Serial . State = [ ] ;
6451 protected _connected : boolean ;
6552
6653 /**
6754 * Note: The idea is to toggle this property from the UI (`Monitor` view)
6855 * and the boards config and the boards attachment/detachment logic can be at on place, here.
6956 */
70- protected readonly onConnectionChangedEmitter =
71- new Emitter < MonitorConnection . State > ( ) ;
57+ protected readonly onConnectionChangedEmitter = new Emitter < boolean > ( ) ;
58+
7259 /**
73- * This emitter forwards all read events **iff ** the connection is established.
60+ * This emitter forwards all read events **if ** the connection is established.
7461 */
7562 protected readonly onReadEmitter = new Emitter < { messages : string [ ] } > ( ) ;
7663
@@ -82,8 +69,13 @@ export class MonitorConnection {
8269 protected monitorErrors : MonitorError [ ] = [ ] ;
8370 protected reconnectTimeout ?: number ;
8471
72+ /**
73+ * When the websocket server is up on the backend, we save the port here, so that the client knows how to connect to it
74+ * */
8575 protected wsPort ?: number ;
76+
8677 protected webSocket ?: WebSocket ;
78+
8779 protected config : Partial < MonitorConfig > = {
8880 board : undefined ,
8981 port : undefined ,
@@ -117,15 +109,21 @@ export class MonitorConnection {
117109 } ) ;
118110 }
119111
112+ /**
113+ * Set the config passing only the properties that has changed. If some has changed and the serial is open,
114+ * we try to reconnect
115+ *
116+ * @param newConfig the porperties of the config that has changed
117+ */
120118 protected setConfig ( newConfig : Partial < MonitorConfig > ) : void {
121- let shouldReconnect = false ;
119+ let configHasChanged = false ;
122120 Object . keys ( this . config ) . forEach ( ( key : keyof MonitorConfig ) => {
123121 if ( newConfig [ key ] && newConfig [ key ] !== this . config [ key ] ) {
124- shouldReconnect = true ;
122+ configHasChanged = true ;
125123 this . config = { ...this . config , [ key ] : newConfig [ key ] } ;
126124 }
127125 } ) ;
128- if ( shouldReconnect && this . isSerialOpen ( ) ) {
126+ if ( configHasChanged && this . isSerialOpen ( ) ) {
129127 this . disconnect ( ) . then ( ( ) => this . connect ( ) ) ;
130128 }
131129 }
@@ -134,10 +132,13 @@ export class MonitorConnection {
134132 return this . wsPort ;
135133 }
136134
137- handleWebSocketChanged ( wsPort : number ) : void {
135+ protected handleWebSocketChanged ( wsPort : number ) : void {
138136 this . wsPort = wsPort ;
139137 }
140138
139+ /**
140+ * When the serial monitor is open and the frontend is connected to the serial, we create the websocket here
141+ */
141142 protected createWsConnection ( ) : boolean {
142143 if ( this . wsPort ) {
143144 try {
@@ -154,10 +155,17 @@ export class MonitorConnection {
154155 return false ;
155156 }
156157
157- protected async setState ( s : MonitorConnection . State ) : Promise < Status > {
158+ /**
159+ * Sets the types of connections needed by the client.
160+ *
161+ * @param s The new types of connections (can be 'Monitor', 'Plotter', none or both).
162+ * If the previuos state was empty and 's' is not, it tries to reconnect to the serial service
163+ * If the provios state was NOT empty and now it is, it disconnects to the serial service
164+ * @returns The status of the operation
165+ */
166+ protected async setState ( s : Serial . State ) : Promise < Status > {
158167 const oldState = deepClone ( this . _state ) ;
159168 this . _state = s ;
160- this . onConnectionChangedEmitter . fire ( this . _state ) ;
161169 let status = Status . OK ;
162170
163171 if ( this . isSerialOpen ( oldState ) && ! this . isSerialOpen ( ) ) {
@@ -166,34 +174,14 @@ export class MonitorConnection {
166174 status = await this . connect ( ) ;
167175 }
168176
169- // if (this.connected) {
170- // switch (this.state.connected) {
171- // case SerialType.All:
172- // return Status.OK;
173- // case SerialType.Plotter:
174- // if (type === SerialType.Monitor) {
175- // if (this.createWsConnection()) {
176- // this.state = { ...this.state, connected: SerialType.All };
177- // return Status.OK;
178- // }
179- // return Status.NOT_CONNECTED;
180- // }
181- // return Status.OK;
182- // case SerialType.Monitor:
183- // if (type === SerialType.Plotter)
184- // this.state = { ...this.state, connected: SerialType.All };
185- // return SerialType.All;
186- // }
187- // }
188-
189177 return status ;
190178 }
191179
192- protected get state ( ) : MonitorConnection . State {
180+ protected get state ( ) : Serial . State {
193181 return this . _state ;
194182 }
195183
196- isSerialOpen ( state ?: MonitorConnection . State ) : boolean {
184+ isSerialOpen ( state ?: Serial . State ) : boolean {
197185 return ( state ? state : this . _state ) . length > 0 ;
198186 }
199187
@@ -209,19 +197,32 @@ export class MonitorConnection {
209197
210198 set connected ( c : boolean ) {
211199 this . _connected = c ;
200+ this . onConnectionChangedEmitter . fire ( this . _connected ) ;
212201 }
213-
214- async openSerial ( type : SerialType ) : Promise < Status > {
202+ /**
203+ * Called when a client opens the serial from the GUI
204+ *
205+ * @param type could be either 'Monitor' or 'Plotter'. If it's 'Monitor' we also connect to the websocket and
206+ * listen to the message events
207+ * @returns the status of the operation
208+ */
209+ async openSerial ( type : Serial . Type ) : Promise < Status > {
215210 if ( this . state . includes ( type ) ) return Status . OK ;
216211 const newState = deepClone ( this . state ) ;
217212 newState . push ( type ) ;
218213 const status = await this . setState ( newState ) ;
219- if ( Status . isOK ( status ) && type === SerialType . Monitor )
214+ if ( Status . isOK ( status ) && type === Serial . Type . Monitor )
220215 this . createWsConnection ( ) ;
221216 return status ;
222217 }
223218
224- async closeSerial ( type : SerialType ) : Promise < Status > {
219+ /**
220+ * Called when a client closes the serial from the GUI
221+ *
222+ * @param type could be either 'Monitor' or 'Plotter'. If it's 'Monitor' we close the websocket connection
223+ * @returns the status of the operation
224+ */
225+ async closeSerial ( type : Serial . Type ) : Promise < Status > {
225226 const index = this . state . indexOf ( type ) ;
226227 let status = Status . OK ;
227228 if ( index >= 0 ) {
@@ -230,7 +231,7 @@ export class MonitorConnection {
230231 status = await this . setState ( newState ) ;
231232 if (
232233 Status . isOK ( status ) &&
233- type === SerialType . Monitor &&
234+ type === Serial . Type . Monitor &&
234235 this . webSocket
235236 ) {
236237 this . webSocket . close ( ) ;
@@ -240,6 +241,9 @@ export class MonitorConnection {
240241 return status ;
241242 }
242243
244+ /**
245+ * Handles error on the MonitorServiceClient and try to reconnect, eventually
246+ */
243247 handleError ( error : MonitorError ) : void {
244248 if ( ! this . connected ) return ;
245249 const { code, config } = error ;
@@ -248,7 +252,7 @@ export class MonitorConnection {
248252 switch ( code ) {
249253 case MonitorError . ErrorCodes . CLIENT_CANCEL : {
250254 console . debug (
251- `Serial connection was canceled by client: ${ MonitorConnection . Config . toString (
255+ `Serial connection was canceled by client: ${ Serial . Config . toString (
252256 this . config
253257 ) } .`
254258 ) ;
@@ -394,14 +398,14 @@ export class MonitorConnection {
394398 if ( Status . isOK ( status ) ) {
395399 this . connected = false ;
396400 console . log (
397- `<<< Disposed serial connection. Was: ${ MonitorConnection . Config . toString (
401+ `<<< Disposed serial connection. Was: ${ Serial . Config . toString (
398402 this . config
399403 ) } `
400404 ) ;
401405 this . wsPort = undefined ;
402406 } else {
403407 console . warn (
404- `<<< Could not dispose serial connection. Activate connection: ${ MonitorConnection . Config . toString (
408+ `<<< Could not dispose serial connection. Activate connection: ${ Serial . Config . toString (
405409 this . config
406410 ) } `
407411 ) ;
@@ -426,7 +430,7 @@ export class MonitorConnection {
426430 } ) ;
427431 }
428432
429- get onConnectionChanged ( ) : Event < MonitorConnection . State > {
433+ get onConnectionChanged ( ) : Event < boolean > {
430434 return this . onConnectionChangedEmitter . event ;
431435 }
432436
@@ -459,8 +463,18 @@ export class MonitorConnection {
459463 }
460464}
461465
462- export namespace MonitorConnection {
463- export type State = SerialType [ ] ;
466+ export namespace Serial {
467+ export enum Type {
468+ Monitor = 'Monitor' ,
469+ Plotter = 'Plotter' ,
470+ }
471+
472+ /**
473+ * The state represents which types of connections are needed by the client, and it should match whether the Serial Monitor
474+ * or the Serial Plotter are open or not in the GUI. It's an array cause it's possible to have both, none or only one of
475+ * them open
476+ */
477+ export type State = Serial . Type [ ] ;
464478
465479 export namespace Config {
466480 export function toString ( config : Partial < MonitorConfig > ) : string {
0 commit comments