From 6a49ad23c5b2b65424a2374c4eeca027beb77e79 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Wed, 1 Dec 2021 13:07:27 +0100 Subject: [PATCH] Add a configuration section for the UI WS server MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- src/charging-station/Bootstrap.ts | 22 +++++++---- src/charging-station/UIWebSocketServer.ts | 11 +++--- src/types/ConfigurationData.ts | 7 ++++ src/utils/Configuration.ts | 45 +++++++++++++++++------ src/utils/Constants.ts | 12 +++++- 5 files changed, 71 insertions(+), 26 deletions(-) diff --git a/src/charging-station/Bootstrap.ts b/src/charging-station/Bootstrap.ts index 74fb74b7..ce20f0bf 100644 --- a/src/charging-station/Bootstrap.ts +++ b/src/charging-station/Bootstrap.ts @@ -18,8 +18,8 @@ import { version } from '../../package.json'; export default class Bootstrap { private static instance: Bootstrap | null = null; private workerImplementation: WorkerAbstract | null = null; - private readonly uiWebSocketServer: UIWebSocketServer; - private readonly storage: Storage; + private readonly uiWebSocketServer!: UIWebSocketServer; + private readonly storage!: Storage; private numberOfChargingStations: number; private readonly version: string = version; private started: boolean; @@ -29,8 +29,14 @@ export default class Bootstrap { this.started = false; this.workerScript = path.join(path.resolve(__dirname, '../'), 'charging-station', 'ChargingStationWorker.js'); this.initWorkerImplementation(); - this.uiWebSocketServer = new UIWebSocketServer({ port: 80, handleProtocols: UIServiceUtils.handleProtocols }); - this.storage = StorageFactory.getStorage(Configuration.getPerformanceStorage().type, Configuration.getPerformanceStorage().URI, this.logPrefix()); + Configuration.getUIWebSocketServer().enabled && (this.uiWebSocketServer = new UIWebSocketServer({ + ...Configuration.getUIWebSocketServer().options, handleProtocols: UIServiceUtils.handleProtocols + })); + Configuration.getPerformanceStorage().enabled && (this.storage = StorageFactory.getStorage( + Configuration.getPerformanceStorage().type, + Configuration.getPerformanceStorage().URI, + this.logPrefix() + )); Configuration.setConfigurationChangeCallback(async () => Bootstrap.getInstance().restart()); } @@ -45,9 +51,9 @@ export default class Bootstrap { if (isMainThread && !this.started) { try { this.numberOfChargingStations = 0; - await this.storage.open(); + await this.storage?.open(); await this.workerImplementation.start(); - this.uiWebSocketServer.start(); + this.uiWebSocketServer?.start(); // Start ChargingStation object in worker thread if (Configuration.getStationTemplateURLs()) { for (const stationURL of Configuration.getStationTemplateURLs()) { @@ -85,8 +91,8 @@ export default class Bootstrap { public async stop(): Promise { if (isMainThread && this.started) { await this.workerImplementation.stop(); - this.uiWebSocketServer.stop(); - await this.storage.close(); + this.uiWebSocketServer?.stop(); + await this.storage?.close(); } else { console.error(chalk.red('Trying to stop the charging stations simulator while not started')); } diff --git a/src/charging-station/UIWebSocketServer.ts b/src/charging-station/UIWebSocketServer.ts index f941b138..5903b85c 100644 --- a/src/charging-station/UIWebSocketServer.ts +++ b/src/charging-station/UIWebSocketServer.ts @@ -1,24 +1,25 @@ import { Protocol, ProtocolCommand, ProtocolRequest, ProtocolVersion } from '../types/UIProtocol'; +import WebSocket, { OPEN, Server, ServerOptions } from 'ws'; import AbstractUIService from './UIWebSocketServices/AbstractUIService'; import BaseError from '../exception/BaseError'; +import Configuration from '../utils/Configuration'; import { IncomingMessage } from 'http'; import UIServiceFactory from './UIWebSocketServices/UIServiceFactory'; import Utils from '../utils/Utils'; -import WebSocket from 'ws'; import logger from '../utils/Logger'; -export default class UIWebSocketServer extends WebSocket.Server { +export default class UIWebSocketServer extends Server { public uiService: AbstractUIService; - public constructor(options?: WebSocket.ServerOptions, callback?: () => void) { + public constructor(options?: ServerOptions, callback?: () => void) { // Create the WebSocket Server - super(options ?? { port: 80 }, callback); + super(options ?? Configuration.getUIWebSocketServer().options, callback); } public broadcastToClients(message: string | Record): void { for (const client of this.clients) { - if (client?.readyState === WebSocket.OPEN) { + if (client?.readyState === OPEN) { client.send(message); } } diff --git a/src/types/ConfigurationData.ts b/src/types/ConfigurationData.ts index 1a2dd165..d218e08a 100644 --- a/src/types/ConfigurationData.ts +++ b/src/types/ConfigurationData.ts @@ -1,3 +1,4 @@ +import { ServerOptions } from 'ws'; import { StorageType } from './Storage'; import type { WorkerChoiceStrategy } from 'poolifier'; import { WorkerProcessType } from './Worker'; @@ -7,6 +8,11 @@ export interface StationTemplateURL { numberOfStations: number; } +export interface UIWebSocketServerConfiguration { + enabled?: boolean; + options?: ServerOptions; +} + export interface StorageConfiguration { enabled?: boolean; type?: StorageType; @@ -16,6 +22,7 @@ export interface StorageConfiguration { export default interface ConfigurationData { supervisionURLs?: string[]; stationTemplateURLs: StationTemplateURL[]; + uiWebSocketServer?: UIWebSocketServerConfiguration; performanceStorage?: StorageConfiguration; autoReconnectMaxRetries?: number; distributeStationsToTenantsEqually?: boolean; diff --git a/src/utils/Configuration.ts b/src/utils/Configuration.ts index 2ac26642..391db0c0 100644 --- a/src/utils/Configuration.ts +++ b/src/utils/Configuration.ts @@ -1,6 +1,7 @@ -import ConfigurationData, { StationTemplateURL, StorageConfiguration } from '../types/ConfigurationData'; +import ConfigurationData, { StationTemplateURL, StorageConfiguration, UIWebSocketServerConfiguration } from '../types/ConfigurationData'; import Constants from './Constants'; +import { ServerOptions } from 'ws'; import { StorageType } from '../types/Storage'; import type { WorkerChoiceStrategy } from 'poolifier'; import { WorkerProcessType } from '../types/Worker'; @@ -24,24 +25,46 @@ export default class Configuration { return Configuration.objectHasOwnProperty(Configuration.getConfig(), 'logStatisticsInterval') ? Configuration.getConfig().logStatisticsInterval : 60; } + static getUIWebSocketServer(): UIWebSocketServerConfiguration { + let options: ServerOptions = { + host: Constants.DEFAULT_UI_WEBSOCKET_SERVER_HOST, + port: Constants.DEFAULT_UI_WEBSOCKET_SERVER_PORT + }; + let uiWebSocketServerConfiguration: UIWebSocketServerConfiguration = { + enabled: true, + options + }; + if (Configuration.objectHasOwnProperty(Configuration.getConfig(), 'uiWebSocketServer')) { + if (Configuration.objectHasOwnProperty(Configuration.getConfig().uiWebSocketServer, 'options')) { + options = { + ...Configuration.objectHasOwnProperty(Configuration.getConfig().uiWebSocketServer.options, 'host') && { host: Configuration.getConfig().uiWebSocketServer.options.host }, + ...Configuration.objectHasOwnProperty(Configuration.getConfig().uiWebSocketServer.options, 'port') && { port: Configuration.getConfig().uiWebSocketServer.options.port } + }; + } + uiWebSocketServerConfiguration = + { + ...Configuration.objectHasOwnProperty(Configuration.getConfig().uiWebSocketServer, 'enabled') && { enabled: Configuration.getConfig().uiWebSocketServer.enabled }, + options + }; + } + return uiWebSocketServerConfiguration; + } + static getPerformanceStorage(): StorageConfiguration { - let storageConfiguration: StorageConfiguration; + let storageConfiguration: StorageConfiguration = { + enabled: false, + type: StorageType.JSON_FILE, + URI: this.getDefaultPerformanceStorageURI(StorageType.JSON_FILE) + }; if (Configuration.objectHasOwnProperty(Configuration.getConfig(), 'performanceStorage')) { storageConfiguration = { - ...Configuration.objectHasOwnProperty(Configuration.getConfig().performanceStorage, 'enabled') ? { enabled: Configuration.getConfig().performanceStorage.enabled } : { enabled: false }, - ...Configuration.objectHasOwnProperty(Configuration.getConfig().performanceStorage, 'type') ? { type: Configuration.getConfig().performanceStorage.type } : { type: StorageType.JSON_FILE }, + ...Configuration.objectHasOwnProperty(Configuration.getConfig().performanceStorage, 'enabled') && { enabled: Configuration.getConfig().performanceStorage.enabled }, + ...Configuration.objectHasOwnProperty(Configuration.getConfig().performanceStorage, 'type') && { type: Configuration.getConfig().performanceStorage.type }, ...Configuration.objectHasOwnProperty(Configuration.getConfig().performanceStorage, 'URI') ? { URI: Configuration.getConfig().performanceStorage.URI } : { URI: this.getDefaultPerformanceStorageURI(Configuration.getConfig()?.performanceStorage?.type ?? StorageType.JSON_FILE) } }; - } else { - storageConfiguration = - { - enabled: false, - type: StorageType.JSON_FILE, - URI: this.getDefaultPerformanceStorageURI(StorageType.JSON_FILE) - }; } return storageConfiguration; } diff --git a/src/utils/Constants.ts b/src/utils/Constants.ts index c10a320b..034d7970 100644 --- a/src/utils/Constants.ts +++ b/src/utils/Constants.ts @@ -45,8 +45,13 @@ export default class Constants { static readonly DEFAULT_HEARTBEAT_INTERVAL = 60000; // Ms - static readonly SUPPORTED_MEASURANDS = Object.freeze([MeterValueMeasurand.STATE_OF_CHARGE, MeterValueMeasurand.VOLTAGE, - MeterValueMeasurand.POWER_ACTIVE_IMPORT, MeterValueMeasurand.CURRENT_IMPORT, MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER]); + static readonly SUPPORTED_MEASURANDS = Object.freeze([ + MeterValueMeasurand.STATE_OF_CHARGE, + MeterValueMeasurand.VOLTAGE, + MeterValueMeasurand.POWER_ACTIVE_IMPORT, + MeterValueMeasurand.CURRENT_IMPORT, + MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER + ]); static readonly DEFAULT_FLUCTUATION_PERCENT = 5; @@ -54,4 +59,7 @@ export default class Constants { static readonly DEFAULT_PERFORMANCE_RECORDS_FILENAME = 'performanceRecords.json'; static readonly DEFAULT_PERFORMANCE_RECORDS_DB_NAME = 'charging-stations-simulator'; static readonly PERFORMANCE_RECORDS_TABLE = 'performance_records'; + + static readonly DEFAULT_UI_WEBSOCKET_SERVER_HOST = 'localhost'; + static readonly DEFAULT_UI_WEBSOCKET_SERVER_PORT = 80; } -- 2.34.1