X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=webapp%2Fsrc%2Fapp%2F%40core-xds%2Fservices%2Fxdsagent.service.ts;h=002c84ba47d98b8a6627dee8368b53fe942570f1;hb=ee66af78c42c4d7ff33f104415bc09d60dbdc27b;hp=94d3dec640df737936e8b0c1e80bfdf5d32039d6;hpb=82ede02a56e12026b2dfb1baeacabfbd564006b1;p=src%2Fxds%2Fxds-agent.git diff --git a/webapp/src/app/@core-xds/services/xdsagent.service.ts b/webapp/src/app/@core-xds/services/xdsagent.service.ts index 94d3dec..002c84b 100644 --- a/webapp/src/app/@core-xds/services/xdsagent.service.ts +++ b/webapp/src/app/@core-xds/services/xdsagent.service.ts @@ -1,6 +1,6 @@ /** * @license -* Copyright (C) 2017 "IoT.bzh" +* Copyright (C) 2017-2018 "IoT.bzh" * Author Sebastien Douheret * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,8 +25,9 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import * as io from 'socket.io-client'; import { AlertService } from './alert.service'; -import { ISdk } from './sdk.service'; +import { ISdk, ISdkManagementMsg } from './sdk.service'; import { ProjectType, ProjectTypeEnum } from './project.service'; +import { TargetType, TargetTypeEnum } from './target.service'; // Import RxJs required methods import 'rxjs/add/operator/map'; @@ -34,7 +35,7 @@ import 'rxjs/add/operator/catch'; import 'rxjs/add/observable/throw'; import 'rxjs/add/operator/mergeMap'; import 'rxjs/add/observable/of'; -import 'rxjs/add/operator/retryWhen'; +import { ErrorObservable } from 'rxjs/observable/ErrorObservable'; export interface IXDSConfigProject { @@ -65,6 +66,25 @@ export interface IXDSProjectConfig { clientData?: string; } +/** Targets **/ +export interface IXDSTargetConfig { + id?: string; + name: string; + type: TargetTypeEnum; + ip: string; + status?: string; + terms?: IXDSTargetTerminal[]; +} + +export interface IXDSTargetTerminal { + id?: string; + type: string; + name: string; + status?: string; + cols?: number; + rows?: number; +} + export interface IXDSVer { id: string; version: string; @@ -124,15 +144,33 @@ export interface IAgentStatus { @Injectable() export class XDSAgentService { + public Socket: SocketIOClient.Socket; public XdsConfig$: Observable; public Status$: Observable; public CmdOutput$ = >new Subject(); public CmdExit$ = >new Subject(); + protected sockConnect$ = new Subject(); + protected sockDisconnect$ = new Subject(); + protected projectAdd$ = new Subject(); protected projectDel$ = new Subject(); protected projectChange$ = new Subject(); + protected sdkAdd$ = new Subject(); + protected sdkRemove$ = new Subject(); + protected sdkChange$ = new Subject(); + protected sdkManagement$ = new Subject(); + + protected targetAdd$ = new Subject(); + protected targetDel$ = new Subject(); + protected targetChange$ = new Subject(); + + protected targetTerminalAdd$ = new Subject(); + protected targetTerminalDel$ = new Subject(); + protected targetTerminalChange$ = new Subject(); + + private _socket: SocketIOClient.Socket; private baseUrl: string; private wsUrl: string; private httpSessionID: string; @@ -142,9 +180,9 @@ export class XDSAgentService { private configSubject = >new BehaviorSubject(this._config); private statusSubject = >new BehaviorSubject(this._status); - private socket: SocketIOClient.Socket; - constructor( @Inject(DOCUMENT) private document: Document, + + constructor(@Inject(DOCUMENT) private document: Document, private http: HttpClient, private alert: AlertService) { this.XdsConfig$ = this.configSubject.asObservable(); @@ -156,22 +194,22 @@ export class XDSAgentService { // Retrieve Session ID / token this.http.get(this.baseUrl + '/version', { observe: 'response' }) .subscribe( - resp => { - this.httpSessionID = resp.headers.get('xds-agent-sid'); - - const re = originUrl.match(/http[s]?:\/\/([^\/]*)[\/]?/); - if (re === null || re.length < 2) { - console.error('ERROR: cannot determine Websocket url'); - } else { - this.wsUrl = 'ws://' + re[1]; - this._handleIoSocket(); - this._RegisterEvents(); - } - }, - err => { - /* tslint:disable:no-console */ - console.error('ERROR while retrieving session id:', err); - }); + resp => { + this.httpSessionID = resp.headers.get('xds-agent-sid'); + + const re = originUrl.match(/http[s]?:\/\/([^\/]*)[\/]?/); + if (re === null || re.length < 2) { + console.error('ERROR: cannot determine Websocket url'); + } else { + this.wsUrl = 'ws://' + re[1]; + this._handleIoSocket(); + this._RegisterEvents(); + } + }, + err => { + /* tslint:disable:no-console */ + console.error('ERROR while retrieving session id:', err); + }); } private _NotifyXdsAgentState(sts: boolean) { @@ -196,45 +234,39 @@ export class XDSAgentService { } private _handleIoSocket() { - this.socket = io(this.wsUrl, { transports: ['websocket'] }); + this.Socket = this._socket = io(this.wsUrl, { transports: ['websocket'] }); - this.socket.on('connect_error', (res) => { + this._socket.on('connect_error', (res) => { this._NotifyXdsAgentState(false); console.error('XDS Agent WebSocket Connection error !'); }); - this.socket.on('connect', (res) => { + this._socket.on('connect', (res) => { this._NotifyXdsAgentState(true); + this.sockConnect$.next(this._socket); }); - this.socket.on('disconnection', (res) => { + this._socket.on('disconnection', (res) => { this._NotifyXdsAgentState(false); this.alert.error('WS disconnection: ' + res); + this.sockDisconnect$.next(this._socket); }); - this.socket.on('error', (err) => { + this._socket.on('error', (err) => { console.error('WS error:', err); }); // XDS Events decoding - this.socket.on('make:output', data => { + this._socket.on('exec:output', data => { this.CmdOutput$.next(Object.assign({}, data)); }); - this.socket.on('make:exit', data => { + this._socket.on('exec:exit', data => { this.CmdExit$.next(Object.assign({}, data)); }); - this.socket.on('exec:output', data => { - this.CmdOutput$.next(Object.assign({}, data)); - }); - - this.socket.on('exec:exit', data => { - this.CmdExit$.next(Object.assign({}, data)); - }); - - this.socket.on('event:server-config', ev => { + this._socket.on('event:server-config', ev => { if (ev && ev.data) { const cfg: IXDServerCfg = ev.data; const idx = this._config.servers.findIndex(el => el.id === cfg.id); @@ -246,10 +278,12 @@ export class XDSAgentService { } }); - this.socket.on('event:project-add', (ev) => { + /*** Project events ****/ + + this._socket.on('event:project-add', (ev) => { if (ev && ev.data && ev.data.id) { this.projectAdd$.next(Object.assign({}, ev.data)); - if (ev.sessionID !== this.httpSessionID && ev.data.label) { + if (ev.sessionID !== '' && ev.sessionID !== this.httpSessionID && ev.data.label) { this.alert.info('Project "' + ev.data.label + '" has been added by another tool.'); } } else if (isDevMode) { @@ -258,10 +292,10 @@ export class XDSAgentService { } }); - this.socket.on('event:project-delete', (ev) => { + this._socket.on('event:project-delete', (ev) => { if (ev && ev.data && ev.data.id) { this.projectDel$.next(Object.assign({}, ev.data)); - if (ev.sessionID !== this.httpSessionID && ev.data.label) { + if (ev.sessionID !== '' && ev.sessionID !== this.httpSessionID && ev.data.label) { this.alert.info('Project "' + ev.data.label + '" has been deleted by another tool.'); } } else if (isDevMode) { @@ -269,7 +303,7 @@ export class XDSAgentService { } }); - this.socket.on('event:project-state-change', ev => { + this._socket.on('event:project-state-change', ev => { if (ev && ev.data) { this.projectChange$.next(Object.assign({}, ev.data)); } else if (isDevMode) { @@ -277,11 +311,138 @@ export class XDSAgentService { } }); + /*** SDK Events ***/ + + this._socket.on('event:sdk-add', (ev) => { + if (ev && ev.data && ev.data.id) { + const evt = ev.data; + this.sdkAdd$.next(Object.assign({}, evt)); + + if (ev.sessionID !== '' && ev.sessionID !== this.httpSessionID && evt.name) { + this.alert.info('SDK "' + evt.name + '" has been added by another tool.'); + } + } else if (isDevMode) { + console.log('Warning: received event:sdk-add with unknown data: ev=', ev); + } + }); + + this._socket.on('event:sdk-remove', (ev) => { + if (ev && ev.data && ev.data.id) { + const evt = ev.data; + this.sdkRemove$.next(Object.assign({}, evt)); + + if (ev.sessionID !== '' && ev.sessionID !== this.httpSessionID && evt.name) { + this.alert.info('SDK "' + evt.name + '" has been removed by another tool.'); + } + } else if (isDevMode) { + console.log('Warning: received event:sdk-remove with unknown data: ev=', ev); + } + }); + + this._socket.on('event:sdk-state-change', (ev) => { + if (ev && ev.data && ev.data.id) { + const evt = ev.data; + this.sdkChange$.next(Object.assign({}, evt)); + + } else if (isDevMode) { + console.log('Warning: received event:sdk-state-change with unknown data: ev=', ev); + } + }); + + this._socket.on('event:sdk-management', (ev) => { + if (ev && ev.data && ev.data.sdk) { + const evt = ev.data; + this.sdkManagement$.next(Object.assign({}, evt)); + + if (ev.sessionID !== '' && ev.sessionID !== this.httpSessionID && evt.sdk.name) { + this.alert.info('SDK "' + evt.sdk.name + '" has been installed by another tool.'); + } + } else if (isDevMode) { + /* tslint:disable:no-console */ + console.log('Warning: received event:sdk-install with unknown data: ev=', ev); + } + }); + + /*** Target events ****/ + + this._socket.on('event:target-add', (ev) => { + if (ev && ev.data && ev.data.id) { + this.targetAdd$.next(Object.assign({}, ev.data)); + if (ev.sessionID !== '' && ev.sessionID !== this.httpSessionID && ev.data.label) { + this.alert.info('Target "' + ev.data.label + '" has been added by another tool.'); + } + } else if (isDevMode) { + /* tslint:disable:no-console */ + console.log('Warning: received event:target-add with unknown data: ev=', ev); + } + }); + + this._socket.on('event:target-remove', (ev) => { + if (ev && ev.data && ev.data.id) { + this.targetDel$.next(Object.assign({}, ev.data)); + if (ev.sessionID !== '' && ev.sessionID !== this.httpSessionID && ev.data.label) { + this.alert.info('Target "' + ev.data.label + '" has been deleted by another tool.'); + } + } else if (isDevMode) { + console.log('Warning: received event:target-remove with unknown data: ev=', ev); + } + }); + + this._socket.on('event:target-state-change', ev => { + if (ev && ev.data) { + this.targetChange$.next(Object.assign({}, ev.data)); + } else if (isDevMode) { + console.log('Warning: received event:target-state-change with unknown data: ev=', ev); + } + }); + + /*** Target Terminal events ****/ + + this._socket.on('event:target-terminal-add', (ev) => { + if (ev && ev.data && ev.data.id) { + this.targetTerminalAdd$.next(Object.assign({}, ev.data)); + if (ev.sessionID !== '' && ev.sessionID !== this.httpSessionID && ev.data.label) { + this.alert.info('Target terminal "' + ev.data.label + '" has been added by another tool.'); + } + } else if (isDevMode) { + /* tslint:disable:no-console */ + console.log('Warning: received event:target-terminal-add with unknown data: ev=', ev); + } + }); + + this._socket.on('event:target-terminal-delete', (ev) => { + if (ev && ev.data && ev.data.id) { + this.targetTerminalDel$.next(Object.assign({}, ev.data)); + if (ev.sessionID !== '' && ev.sessionID !== this.httpSessionID && ev.data.label) { + this.alert.info('Target terminal "' + ev.data.label + '" has been deleted by another tool.'); + } + } else if (isDevMode) { + console.log('Warning: received event:target-terminal-delete with unknown data: ev=', ev); + } + }); + + this._socket.on('event:target-terminal-state-change', ev => { + if (ev && ev.data) { + this.targetTerminalChange$.next(Object.assign({}, ev.data)); + } else if (isDevMode) { + console.log('Warning: received event:target-terminal-state-change with unknown data: ev=', ev); + } + }); + } /** ** Events registration ***/ + + onSocketConnect(): Observable { + return this.sockConnect$.asObservable(); + } + + onSocketDisconnect(): Observable { + return this.sockDisconnect$.asObservable(); + } + onProjectAdd(): Observable { return this.projectAdd$.asObservable(); } @@ -294,6 +455,46 @@ export class XDSAgentService { return this.projectChange$.asObservable(); } + onSdkAdd(): Observable { + return this.sdkAdd$.asObservable(); + } + + onSdkRemove(): Observable { + return this.sdkRemove$.asObservable(); + } + + onSdkChange(): Observable { + return this.sdkChange$.asObservable(); + } + + onSdkManagement(): Observable { + return this.sdkManagement$.asObservable(); + } + + onTargetAdd(): Observable { + return this.targetAdd$.asObservable(); + } + + onTargetDelete(): Observable { + return this.targetDel$.asObservable(); + } + + onTargetChange(): Observable { + return this.targetChange$.asObservable(); + } + + onTargetTerminalAdd(): Observable { + return this.targetTerminalAdd$.asObservable(); + } + + onTargetTerminalDelete(): Observable { + return this.targetTerminalDel$.asObservable(); + } + + onTargetTerminalChange(): Observable { + return this.targetTerminalChange$.asObservable(); + } + /** ** Misc / Version ***/ @@ -355,10 +556,22 @@ export class XDSAgentService { if (!svr || !svr.connected) { return Observable.of([]); } - return this._get(svr.partialUrl + '/sdks'); } + installSdk(serverID: string, id: string, filename?: string, force?: boolean): Observable { + return this._post(this._getServerUrl(serverID) + '/sdks', { id: id, filename: filename, force: force }); + } + + abortInstall(serverID: string, id: string): Observable { + return this._post(this._getServerUrl(serverID) + '/sdks/abortinstall', { id: id }); + } + + removeSdk(serverID: string, id: string): Observable { + return this._delete(this._getServerUrl(serverID) + '/sdks/' + id); + } + + /*** ** Projects ***/ @@ -397,6 +610,76 @@ export class XDSAgentService { }); } + + /*** + ** Targets + ***/ + getTargets(serverID: string): Observable { + return this._get(this._getServerUrl(serverID) + '/targets'); + } + + addTarget(serverID: string, cfg: IXDSTargetConfig): Observable { + return this._post(this._getServerUrl(serverID) + '/targets', cfg); + } + + deleteTarget(serverID: string, id: string): Observable { + return this._delete(this._getServerUrl(serverID) + '/targets/' + id); + } + + updateTarget(serverID: string, cfg: IXDSTargetConfig): Observable { + return this._put(this._getServerUrl(serverID) + '/targets/' + cfg.id, cfg); + } + + /*** + ** Terminals + ***/ + getTerminalsTarget(serverID, targetID: string): Observable { + return this._get(this._getServerUrl(serverID) + '/targets/' + targetID + '/terminals'); + } + + getTerminalTarget(serverID, targetID, termID: string): Observable { + return this._get(this._getServerUrl(serverID) + '/targets/' + targetID + '/terminals/' + termID); + } + + createTerminalTarget(serverID, targetID: string, cfg: IXDSTargetTerminal): Observable { + return this._post(this._getServerUrl(serverID) + '/targets/' + targetID + '/terminals', cfg); + } + + updateTerminalTarget(serverID, targetID: string, cfg: IXDSTargetTerminal): Observable { + if (cfg && (cfg.id !== '' || cfg.id !== undefined)) { + return this._put(this._getServerUrl(serverID) + '/targets/' + targetID + '/terminals/' + cfg.id, cfg); + } + return Observable.throw('Undefined terminal id'); + } + + openTerminalTarget(serverID, targetID, termID: string): Observable { + return this._post(this._getServerUrl(serverID) + '/targets/' + targetID + '/terminals/' + termID + '/open', {}); + } + + closeTerminalTarget(serverID, targetID, termID: string): Observable { + return this._post(this._getServerUrl(serverID) + '/targets/' + targetID + '/terminals/' + termID + '/close', {}); + } + + resizeTerminalTarget(serverID, targetID, termID: string, cols, rows: number): Observable { + return this._post(this._getServerUrl(serverID) + '/targets/' + targetID + '/terminals/' + termID + '/resize', + { cols: cols, rows: rows }); + } + + /*** + ** Supervision + ***/ + getTopoSupervisor(): Observable { + return this._get('/supervisor/topo'); + } + + startTraceSupervisor(cfg: any): Observable { + return this._post('/supervisor/trace/start', cfg); + } + + stopTraceSupervisor(cfg: any): Observable { + return this._post('/supervisor/trace/stop', cfg); + } + /** ** Private functions ***/ @@ -405,10 +688,10 @@ export class XDSAgentService { // Register to all existing events this._post('/events/register', { 'name': 'event:all' }) .subscribe( - res => { }, - error => { - this.alert.error('ERROR while registering to all events: ' + error); - }, + res => { }, + error => { + this.alert.error('ERROR while registering to all events: ' + error); + }, ); } @@ -420,6 +703,17 @@ export class XDSAgentService { return svr[0]; } + private _getServerUrl(serverID: string): string | ErrorObservable { + const svr = this._getServer(serverID); + if (!svr || !svr.connected) { + if (isDevMode) { + console.log('ERROR: XDS Server unknown: serverID=' + serverID); + } + return Observable.throw('Cannot identify XDS Server'); + } + return svr.partialUrl; + } + private _attachAuthHeaders(options?: any) { options = options || {}; const headers = options.headers || new HttpHeaders();