WIT integration - Configuration
MODIFY
src/integration/asset/AssetFactory.ts
src/integration/asset/AssetFactory.ts
@@ -11,6 +11,7 @@ import Tenant from '../../types/Tenant';
import TenantComponents from '../../types/TenantComponents';
import TenantStorage from '../../storage/mongodb/TenantStorage';
import Utils from '../../utils/Utils';
+import WitAssetIntegration from './wit/WitAssetIntegration';
const MODULE_NAME = 'AssetFactory';
@@ -37,6 +38,9 @@ export default class AssetFactory {
case AssetConnectionType.IOTHINK:
assetIntegrationImpl = new IothinkAssetIntegration(tenantID, settings.asset, foundConnection);
break;
+ case AssetConnectionType.WIT:
+ assetIntegrationImpl = new WitAssetIntegration(tenantID, settings.asset, foundConnection);
+ break;
}
return assetIntegrationImpl;
}

ADD
src/integration/asset/wit/WitAssetIntegration.ts
+import { AssetConnectionSetting, AssetSetting } from '../../../types/Setting';
+
+import { AbstractCurrentConsumption } from '../../../types/Consumption';
+import Asset from '../../../types/Asset';
+import AssetIntegration from '../AssetIntegration';
+import AxiosFactory from '../../../utils/AxiosFactory';
+import { AxiosInstance } from 'axios';
+import BackendError from '../../../exception/BackendError';
+import Constants from '../../../utils/Constants';
+import Cypher from '../../../utils/Cypher';
+import Logging from '../../../utils/Logging';
+import { ServerAction } from '../../../types/Server';
+import Utils from '../../../utils/Utils';
+
+const MODULE_NAME = 'WitAssetIntegration';
+
+export default class WitAssetIntegration extends AssetIntegration<AssetSetting> {
+ private axiosInstance: AxiosInstance;
+
+ public constructor(tenantID: string, settings: AssetSetting, connection: AssetConnectionSetting) {
+ super(tenantID, settings, connection);
+ this.axiosInstance = AxiosFactory.getAxiosInstance(tenantID);
+ }
+
+ public async checkConnection(): Promise<void> {
+ await this.connect();
+ }
+
+ public async retrieveConsumptions(asset: Asset, manualCall: boolean): Promise<AbstractCurrentConsumption[]> {
+
+ throw Error('Function is not implemented for this connection type');
+
+ // Function is not implemented yet, call async function to
+ await Logging.logError({
+ tenantID: this.tenantID,
+ action: ServerAction.RETRIEVE_ASSET_CONSUMPTION,
+ module: MODULE_NAME, method: 'retrieveConsumptions',
+ message: 'Error while retrieving consumption. Function is not implemented for this connection type',
+ });
+
+ return [];
+ }
+
+ private async connect(): Promise<string> {
+ // Check if connection is initialized
+ this.checkConnectionIsProvided();
+ // Get credential params
+ const credentials = await this.getCredentialURLParams();
+ // Send credentials to get the token
+ const response = await Utils.executePromiseWithTimeout(5000,
+ this.axiosInstance.post(`${this.connection.witConnection.authenticationUrl}/token`,
+ credentials,
+ {
+ // @ts-ignore
+ 'axios-retry': {
+ retries: 0
+ },
+ headers: this.buildFormHeaders()
+ }),
+ `Time out error (5s) when getting the token with the connection URL '${this.connection.witConnection.authenticationUrl}/token'`
+ );
+ // Return the Token
+ return response.data.access_token;
+ }
+
+ private async getCredentialURLParams(): Promise<URLSearchParams> {
+ const params = new URLSearchParams();
+ params.append('client_id', this.connection.witConnection.clientId);
+ params.append('client_secret', await Cypher.decrypt(this.tenantID, this.connection.witConnection.clientSecret));
+ params.append('grant_type', 'password');
+ params.append('username', this.connection.witConnection.user);
+ params.append('password', await Cypher.decrypt(this.tenantID, this.connection.witConnection.password));
+ params.append('scope', 'https://api.wit-datacenter.com');
+ return params;
+ }
+
+ private checkConnectionIsProvided(): void {
+ if (!this.connection) {
+ throw new BackendError({
+ source: Constants.CENTRAL_SERVER,
+ module: MODULE_NAME,
+ method: 'checkConnectionIsProvided',
+ action: ServerAction.CHECK_CONNECTION,
+ message: 'No connection provided'
+ });
+ }
+ }
+
+ private buildFormHeaders(): any {
+ return {
+ 'Content-Type': 'application/x-www-form-urlencoded'
+ };
+ }
+
+ private buildAuthHeader(token: string): any {
+ return {
+ 'Authorization': 'Bearer ' + token
+ };
+ }
+}

MODIFY
src/server/rest/v1/service/security/SettingSecurity.ts
src/server/rest/v1/service/security/SettingSecurity.ts
@@ -234,6 +234,15 @@ export default class SettingSecurity {
password: sanitize(connection.iothinkConnection.password),
};
break;
+ case AssetConnectionType.WIT:
+ sanitizedConnection.witConnection = {
+ authenticationUrl: sanitize(connection.witConnection.authenticationUrl),
+ clientId: sanitize(connection.witConnection.clientId),
+ clientSecret: sanitize(connection.witConnection.clientSecret),
+ user: sanitize(connection.witConnection.user),
+ password: sanitize(connection.witConnection.password),
+ };
+ break;
}
settings.content.asset.connections.push(sanitizedConnection);
}

MODIFY
src/types/Setting.ts
src/types/Setting.ts
@@ -278,12 +278,14 @@ export interface AssetConnectionSetting {
schneiderConnection?: AssetSchneiderConnectionType;
greencomConnection?: AssetGreencomConnectionType;
iothinkConnection?: AssetIothinkConnectionType;
+ witConnection?: AssetWitConnectionType;
}
export enum AssetConnectionType {
SCHNEIDER = 'schneider',
GREENCOM = 'greencom',
- IOTHINK = 'iothink'
+ IOTHINK = 'iothink',
+ WIT = 'wit',
}
export interface AssetUserPasswordConnectionType {
@@ -304,6 +306,12 @@ export interface AssetSchneiderConnectionType extends AssetUserPasswordConnectio
export interface AssetIothinkConnectionType extends AssetUserPasswordConnectionType {
}
+export interface AssetWitConnectionType extends AssetUserPasswordConnectionType {
+ clientId: string;
+ clientSecret: string;
+ authenticationUrl: string;
+}
+
export enum CarConnectorSettingsType {
CAR_CONNECTOR = 'carConnector',
}

WIT integration - Configuration