Add UI server factory with server class abstraction
authorJérôme Benoit <jerome.benoit@sap.com>
Fri, 13 May 2022 12:31:34 +0000 (14:31 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Fri, 13 May 2022 12:31:34 +0000 (14:31 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/Bootstrap.ts
src/charging-station/ui-server/AbstractUIServer.ts [new file with mode: 0644]
src/charging-station/ui-server/UIServerFactory.ts [new file with mode: 0644]
src/charging-station/ui-server/UIWebSocketServer.ts
src/charging-station/ui-server/ui-services/AbstractUIService.ts
src/charging-station/ui-server/ui-services/UIService001.ts
src/charging-station/ui-server/ui-services/UIServiceFactory.ts

index 3701b1706616522a7e23f9cc129ddffabb8c2891..1f5c898f914102a010688155120f6db6ab662d04 100644 (file)
@@ -6,13 +6,15 @@ import {
   ChargingStationWorkerMessageEvents,
 } from '../types/ChargingStationWorker';
 
+import { AbstractUIServer } from './ui-server/AbstractUIServer';
+import { ApplicationProtocol } from '../types/UIProtocol';
 import Configuration from '../utils/Configuration';
 import { StationTemplateUrl } from '../types/ConfigurationData';
 import Statistics from '../types/Statistics';
 import { Storage } from '../performance/storage/Storage';
 import { StorageFactory } from '../performance/storage/StorageFactory';
+import UIServerFactory from './ui-server/UIServerFactory';
 import { UIServiceUtils } from './ui-server/ui-services/UIServiceUtils';
-import UIWebSocketServer from './ui-server/UIWebSocketServer';
 import Utils from '../utils/Utils';
 import WorkerAbstract from '../worker/WorkerAbstract';
 import WorkerFactory from '../worker/WorkerFactory';
@@ -24,7 +26,7 @@ import { version } from '../../package.json';
 export default class Bootstrap {
   private static instance: Bootstrap | null = null;
   private workerImplementation: WorkerAbstract<ChargingStationWorkerData> | null = null;
-  private readonly uiServer!: UIWebSocketServer;
+  private readonly uiServer!: AbstractUIServer;
   private readonly storage!: Storage;
   private numberOfChargingStations: number;
   private readonly version: string = version;
@@ -40,7 +42,7 @@ export default class Bootstrap {
     );
     this.initWorkerImplementation();
     Configuration.getUIServer().enabled &&
-      (this.uiServer = new UIWebSocketServer({
+      (this.uiServer = UIServerFactory.getUIServerImplementation(ApplicationProtocol.WS, {
         ...Configuration.getUIServer().options,
         handleProtocols: UIServiceUtils.handleProtocols,
       }));
diff --git a/src/charging-station/ui-server/AbstractUIServer.ts b/src/charging-station/ui-server/AbstractUIServer.ts
new file mode 100644 (file)
index 0000000..2608e83
--- /dev/null
@@ -0,0 +1,20 @@
+import AbstractUIService from './ui-services/AbstractUIService';
+import { Server as HttpServer } from 'http';
+import { ProtocolVersion } from '../../types/UIProtocol';
+import { Server as WSServer } from 'ws';
+
+export abstract class AbstractUIServer {
+  public readonly chargingStations: Set<string>;
+  protected readonly uiServices: Map<ProtocolVersion, AbstractUIService>;
+  protected uiServer: WSServer | HttpServer;
+
+  public constructor() {
+    this.chargingStations = new Set<string>();
+    this.uiServices = new Map<ProtocolVersion, AbstractUIService>();
+  }
+
+  public abstract start(): void;
+  public abstract stop(): void;
+  public abstract sendResponse(message: string): void;
+  public abstract logPrefix(): string;
+}
diff --git a/src/charging-station/ui-server/UIServerFactory.ts b/src/charging-station/ui-server/UIServerFactory.ts
new file mode 100644 (file)
index 0000000..cdcd251
--- /dev/null
@@ -0,0 +1,24 @@
+import { AbstractUIServer } from './AbstractUIServer';
+import { ApplicationProtocol } from '../../types/UIProtocol';
+import Configuration from '../../utils/Configuration';
+import { ServerOptions } from '../../types/ConfigurationData';
+import UIWebSocketServer from './UIWebSocketServer';
+
+export default class UIServerFactory {
+  private constructor() {
+    // This is intentional
+  }
+
+  public static getUIServerImplementation(
+    applicationProtocol: ApplicationProtocol,
+    options?: ServerOptions,
+    callback?: () => void
+  ): AbstractUIServer | null {
+    switch (applicationProtocol) {
+      case ApplicationProtocol.WS:
+        return new UIWebSocketServer(options ?? Configuration.getUIServer().options, callback);
+      default:
+        return null;
+    }
+  }
+}
index 2e03ebc290e726ba3830d37dc5476e3956ca7c7a..da476895d5f87dc3476797efd011e389808ade66 100644 (file)
@@ -1,7 +1,7 @@
 import { Protocol, ProtocolVersion } from '../../types/UIProtocol';
 import WebSocket, { OPEN, Server } from 'ws';
 
-import AbstractUIService from './ui-services/AbstractUIService';
+import { AbstractUIServer } from './AbstractUIServer';
 import Configuration from '../../utils/Configuration';
 import { IncomingMessage } from 'http';
 import { ServerOptions } from '../../types/ConfigurationData';
@@ -9,19 +9,14 @@ import UIServiceFactory from './ui-services/UIServiceFactory';
 import Utils from '../../utils/Utils';
 import logger from '../../utils/Logger';
 
-export default class UIWebSocketServer extends Server {
-  public readonly chargingStations: Set<string>;
-  private readonly uiServices: Map<ProtocolVersion, AbstractUIService>;
-
+export default class UIWebSocketServer extends AbstractUIServer {
   public constructor(options?: ServerOptions, callback?: () => void) {
-    // Create the WebSocket server
-    super(options ?? Configuration.getUIServer().options, callback);
-    this.chargingStations = new Set<string>();
-    this.uiServices = new Map<ProtocolVersion, AbstractUIService>();
+    super();
+    this.uiServer = new Server(options ?? Configuration.getUIServer().options, callback);
   }
 
   public start(): void {
-    this.on('connection', (socket: WebSocket, request: IncomingMessage): void => {
+    this.uiServer.on('connection', (socket: WebSocket, request: IncomingMessage): void => {
       const protocolIndex = socket.protocol.indexOf(Protocol.UI);
       const version = socket.protocol.substring(
         protocolIndex + Protocol.UI.length
@@ -45,7 +40,7 @@ export default class UIWebSocketServer extends Server {
   }
 
   public stop(): void {
-    this.close();
+    this.uiServer.close();
   }
 
   public sendResponse(message: string): void {
@@ -57,7 +52,7 @@ export default class UIWebSocketServer extends Server {
   }
 
   private broadcastToClients(message: string): void {
-    for (const client of this.clients) {
+    for (const client of (this.uiServer as Server).clients) {
       if (client?.readyState === OPEN) {
         client.send(message);
       }
index d4ad33988e2062f7c99b779026f07cf5323c1fe0..151cff336ce33b012a21b8e20d51cd2c9e7b2277 100644 (file)
@@ -4,18 +4,18 @@ import {
   ProtocolRequestHandler,
 } from '../../../types/UIProtocol';
 
+import { AbstractUIServer } from '../AbstractUIServer';
 import BaseError from '../../../exception/BaseError';
 import { JsonType } from '../../../types/JsonType';
 import { RawData } from 'ws';
-import UIWebSocketServer from '../UIWebSocketServer';
 import Utils from '../../../utils/Utils';
 import logger from '../../../utils/Logger';
 
 export default abstract class AbstractUIService {
-  protected readonly uiServer: UIWebSocketServer;
+  protected readonly uiServer: AbstractUIServer;
   protected readonly messageHandlers: Map<ProtocolCommand, ProtocolRequestHandler>;
 
-  constructor(uiServer: UIWebSocketServer) {
+  constructor(uiServer: AbstractUIServer) {
     this.uiServer = uiServer;
     this.messageHandlers = new Map<ProtocolCommand, ProtocolRequestHandler>([
       [ProtocolCommand.LIST_CHARGING_STATIONS, this.handleListChargingStations.bind(this)],
index eecdcd34792da1ef2bf6beae1f4cff19595ab704..cbe4c8c3c0d893bde2d36fee9bb349b6520993d9 100644 (file)
@@ -1,11 +1,11 @@
 import { ProtocolCommand, ProtocolRequestHandler } from '../../../types/UIProtocol';
 
+import { AbstractUIServer } from '../AbstractUIServer';
 import AbstractUIService from './AbstractUIService';
 import { JsonType } from '../../../types/JsonType';
-import UIWebSocketServer from '../UIWebSocketServer';
 
 export default class UIService001 extends AbstractUIService {
-  constructor(uiServer: UIWebSocketServer) {
+  constructor(uiServer: AbstractUIServer) {
     super(uiServer);
     this.messageHandlers.set(
       ProtocolCommand.START_TRANSACTION,
index d4f92c10d30345845aff373e5bbb29cb995252ce..7136e4472735e7e3ec6dffee11f58a360962d3cd 100644 (file)
@@ -1,7 +1,7 @@
+import { AbstractUIServer } from '../AbstractUIServer';
 import AbstractUIService from './AbstractUIService';
 import { ProtocolVersion } from '../../../types/UIProtocol';
 import UIService001 from './UIService001';
-import UIWebSocketServer from '../UIWebSocketServer';
 
 export default class UIServiceFactory {
   private constructor() {
@@ -10,7 +10,7 @@ export default class UIServiceFactory {
 
   public static getUIServiceImplementation(
     version: ProtocolVersion,
-    uiServer: UIWebSocketServer
+    uiServer: AbstractUIServer
   ): AbstractUIService | null {
     switch (version) {
       case ProtocolVersion['0.0.1']: