-import { Injectable, Inject } from '@angular/core';
+/**
+* @license
+* Copyright (C) 2017-2018 "IoT.bzh"
+* Author Sebastien Douheret <sebastien@iot.bzh>
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { Injectable, Inject, isDevMode } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { DOCUMENT } from '@angular/common';
import { Observable } from 'rxjs/Observable';
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 RxJs required methods
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 {
status?: string;
isInSync?: boolean;
defaultSdkID: string;
+ clientData?: string;
}
export interface IXDSVer {
public XdsConfig$: Observable<IXDSConfig>;
public Status$: Observable<IAgentStatus>;
- public ProjectState$ = <Subject<IXDSProjectConfig>>new Subject();
public CmdOutput$ = <Subject<ICmdOutput>>new Subject();
public CmdExit$ = <Subject<ICmdExit>>new Subject();
+ protected projectAdd$ = new Subject<IXDSProjectConfig>();
+ protected projectDel$ = new Subject<IXDSProjectConfig>();
+ protected projectChange$ = new Subject<IXDSProjectConfig>();
+
+ protected sdkAdd$ = new Subject<ISdk>();
+ protected sdkRemove$ = new Subject<ISdk>();
+ protected sdkChange$ = new Subject<ISdk>();
+ protected sdkManagement$ = new Subject<ISdkManagementMsg>();
+
private baseUrl: string;
private wsUrl: string;
+ private httpSessionID: string;
private _config = <IXDSConfig>{ servers: [] };
private _status = { connected: false, servers: [] };
const originUrl = this.document.location.origin;
this.baseUrl = originUrl + '/api/v1';
- 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();
- }
+ // 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);
+ });
}
private _NotifyXdsAgentState(sts: boolean) {
console.error('WS error:', err);
});
+ // XDS Events decoding
+
this.socket.on('make:output', data => {
this.CmdOutput$.next(Object.assign({}, <ICmdOutput>data));
});
this.CmdExit$.next(Object.assign({}, <ICmdExit>data));
});
- // Events
- // (project-add and project-delete events are managed by project.service)
this.socket.on('event:server-config', ev => {
if (ev && ev.data) {
const cfg: IXDServerCfg = ev.data;
}
});
+ /*** 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 !== '' && ev.sessionID !== this.httpSessionID && ev.data.label) {
+ this.alert.info('Project "' + ev.data.label + '" has been added by another tool.');
+ }
+ } else if (isDevMode) {
+ /* tslint:disable:no-console */
+ console.log('Warning: received event:project-add with unknown data: ev=', 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 !== '' && ev.sessionID !== this.httpSessionID && ev.data.label) {
+ this.alert.info('Project "' + ev.data.label + '" has been deleted by another tool.');
+ }
+ } else if (isDevMode) {
+ console.log('Warning: received event:project-delete with unknown data: ev=', ev);
+ }
+ });
+
this.socket.on('event:project-state-change', ev => {
if (ev && ev.data) {
- this.ProjectState$.next(Object.assign({}, ev.data));
+ this.projectChange$.next(Object.assign({}, ev.data));
+ } else if (isDevMode) {
+ console.log('Warning: received event:project-state-change with unkn220own data: ev=', ev);
+ }
+ });
+
+ /*** SDK Events ***/
+
+ this.socket.on('event:sdk-add', (ev) => {
+ if (ev && ev.data && ev.data.id) {
+ const evt = <ISdk>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 = <ISdk>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 = <ISdk>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 = <ISdkManagementMsg>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);
}
});
}
/**
- ** Events
+ ** Events registration
***/
- addEventListener(ev: string, fn: Function): SocketIOClient.Emitter {
- return this.socket.addEventListener(ev, fn);
+ onProjectAdd(): Observable<IXDSProjectConfig> {
+ return this.projectAdd$.asObservable();
+ }
+
+ onProjectDelete(): Observable<IXDSProjectConfig> {
+ return this.projectDel$.asObservable();
+ }
+
+ onProjectChange(): Observable<IXDSProjectConfig> {
+ return this.projectChange$.asObservable();
+ }
+
+ onSdkAdd(): Observable<ISdk> {
+ return this.sdkAdd$.asObservable();
+ }
+
+ onSdkRemove(): Observable<ISdk> {
+ return this.sdkRemove$.asObservable();
+ }
+
+ onSdkChange(): Observable<ISdk> {
+ return this.sdkChange$.asObservable();
+ }
+
+ onSdkManagement(): Observable<ISdkManagementMsg> {
+ return this.sdkManagement$.asObservable();
}
/**
if (!svr || !svr.connected) {
return Observable.of([]);
}
-
return this._get(svr.partialUrl + '/sdks');
}
+ installSdk(serverID: string, id: string, filename?: string, force?: boolean): Observable<ISdk> {
+ return this._post(this._getServerUrl(serverID) + '/sdks', { id: id, filename: filename, force: force });
+ }
+
+ abortInstall(serverID: string, id: string): Observable<ISdk> {
+ return this._post(this._getServerUrl(serverID) + '/sdks/abortinstall', { id: id });
+ }
+
+ removeSdk(serverID: string, id: string): Observable<ISdk> {
+ return this._delete(this._getServerUrl(serverID) + '/sdks/' + id);
+ }
+
+
/***
** Projects
***/
return this._delete('/projects/' + id);
}
+ updateProject(cfg: IXDSProjectConfig): Observable<IXDSProjectConfig> {
+ return this._put('/projects/' + cfg.id, cfg);
+ }
+
syncProject(id: string): Observable<string> {
return this._post('/projects/sync/' + id, {});
}
res => { },
error => {
this.alert.error('ERROR while registering to all events: ' + error);
- }
- );
+ },
+ );
}
private _getServer(ID: string): IXDServerCfg {
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();
return this._decodeError(error);
});
}
+ private _put(url: string, body: any): Observable<any> {
+ return this.http.put(this.baseUrl + url, JSON.stringify(body), this._attachAuthHeaders())
+ .catch((error) => {
+ return this._decodeError(error);
+ });
+ }
private _delete(url: string): Observable<any> {
return this.http.delete(this.baseUrl + url, this._attachAuthHeaders())
.catch(this._decodeError);
} else {
e = err.message ? err.message : err.toString();
}
- console.log('xdsagent.service - ERROR: ', e);
+ /* tslint:disable:no-console */
+ if (isDevMode) {
+ console.log('xdsagent.service - ERROR: ', e);
+ }
return Observable.throw(e);
}
}