Add charging stations listing to WS server commands
authorJérôme Benoit <jerome.benoit@sap.com>
Mon, 29 Nov 2021 20:51:45 +0000 (21:51 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Mon, 29 Nov 2021 20:51:45 +0000 (21:51 +0100)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
src/charging-station/Bootstrap.ts
src/charging-station/ChargingStation.ts
src/charging-station/WebSocketServer.ts
src/charging-station/WebSocketServices/ui/0.0.1/UIService.ts
src/charging-station/WebSocketServices/ui/AbstractUIService.ts
src/types/ChargingStationWorker.ts
src/types/UIProtocol.ts

index 06bc50e391695090eb25d6e469a98c5e5be7ce3d..fe344407dc03400970fc89fb911f45011ce422b5 100644 (file)
@@ -109,7 +109,11 @@ export default class Bootstrap {
           workerChoiceStrategy: Configuration.getWorkerPoolStrategy()
         },
         messageHandler: async (msg: ChargingStationWorkerMessage) => {
-          if (msg.id === ChargingStationWorkerMessageEvents.PERFORMANCE_STATISTICS) {
+          if (msg.id === ChargingStationWorkerMessageEvents.STARTED) {
+            this.webSocketServer.webSocketServerService.chargingStations.add(msg.data.id);
+          } else if (msg.id === ChargingStationWorkerMessageEvents.STOPPED) {
+            this.webSocketServer.webSocketServerService.chargingStations.delete(msg.data.id);
+          } else if (msg.id === ChargingStationWorkerMessageEvents.PERFORMANCE_STATISTICS) {
             await this.storage.storePerformanceStatistics(msg.data);
           }
         }
index db385612bf85615090fd7493fee30838f60068f5..c50d2ad9ba3bf104f14b64aa4a7770698d95d785 100644 (file)
@@ -14,6 +14,7 @@ import AutomaticTransactionGenerator from './AutomaticTransactionGenerator';
 import { ChargePointStatus } from '../types/ocpp/ChargePointStatus';
 import { ChargingProfile } from '../types/ocpp/ChargingProfile';
 import ChargingStationInfo from '../types/ChargingStationInfo';
+import { ChargingStationWorkerMessageEvents } from '../types/ChargingStationWorker';
 import { ClientRequestArgs } from 'http';
 import Configuration from '../utils/Configuration';
 import Constants from '../utils/Constants';
@@ -34,6 +35,7 @@ import Utils from '../utils/Utils';
 import crypto from 'crypto';
 import fs from 'fs';
 import logger from '../utils/Logger';
+import { parentPort } from 'worker_threads';
 import path from 'path';
 
 export default class ChargingStation {
@@ -335,6 +337,7 @@ export default class ChargingStation {
     this.wsConnection.on('ping', this.onPing.bind(this));
     // Handle WebSocket pong
     this.wsConnection.on('pong', this.onPong.bind(this));
+    parentPort.postMessage({ id: ChargingStationWorkerMessageEvents.STARTED, data: { id: this.stationInfo.chargingStationId } });
   }
 
   public async stop(reason: StopTransactionReason = StopTransactionReason.NONE): Promise<void> {
@@ -353,6 +356,7 @@ export default class ChargingStation {
       this.performanceStatistics.stop();
     }
     this.bootNotificationResponse = null;
+    parentPort.postMessage({ id: ChargingStationWorkerMessageEvents.STOPPED, data: { id: this.stationInfo.chargingStationId } });
     this.stopped = true;
   }
 
index 426c80721598cdeb247ba35f0cce47aa6e2d578c..81e57675f7b895fa908a955daae991c186da984d 100644 (file)
@@ -8,16 +8,16 @@ import WebSocket from 'ws';
 import logger from '../utils/Logger';
 
 export default class WebSocketServer extends WebSocket.Server {
-  private webSocketServerService: AbstractUIService;
+  public webSocketServerService: AbstractUIService;
 
   public constructor(options?: WebSocket.ServerOptions, callback?: () => void) {
     // Create the WebSocket Server
-    super(options, callback);
+    super({ ...options, port: 80 }, callback);
     // FIXME: version the instantiation
     this.webSocketServerService = new UIService(this);
   }
 
-  public broadcastToClients(message: Record<string, unknown>): void {
+  public broadcastToClients(message: string | Record<string, unknown>): void {
     for (const client of this.clients) {
       if (client?.readyState === WebSocket.OPEN) {
         client.send(message);
@@ -34,7 +34,7 @@ export default class WebSocketServer extends WebSocket.Server {
         [version, command, payload] = JSON.parse(messageData.toString()) as ProtocolRequest;
         switch (version) {
           case ProtocolVersion['0.0.1']:
-            this.webSocketServerService.handleMessage(command, payload).catch(() => {
+            this.webSocketServerService.handleMessage(version, command, payload).catch(() => {
               logger.error(`${this.logPrefix()} Error while handling command %s message: %j`, command, payload);
             });
             break;
index 8ca0c6dc9495624c0d0f376b89547f35cf157b48..f2db451240135a182d0921cac1bcc28c9a19f121 100644 (file)
@@ -1,4 +1,4 @@
-import { ProtocolCommand, ProtocolRequestHandler } from '../../../../types/UIProtocol';
+import { ProtocolCommand, ProtocolRequestHandler, ProtocolVersion } from '../../../../types/UIProtocol';
 
 import AbstractUIService from '../AbstractUIService';
 import BaseError from '../../../../exception/BaseError';
@@ -11,12 +11,13 @@ export default class UIService extends AbstractUIService {
   constructor(webSocketServer: WebSocketServer) {
     super(webSocketServer);
     this.messageHandlers = new Map<ProtocolCommand, ProtocolRequestHandler>([
+      [ProtocolCommand.LIST_CHARGING_STATIONS, this.handleListChargingStations.bind(this)],
       [ProtocolCommand.START_TRANSACTION, this.handleStartTransaction.bind(this)],
       [ProtocolCommand.STOP_TRANSACTION, this.handleStopTransaction.bind(this)],
     ]);
   }
 
-  async handleMessage(command: ProtocolCommand, payload: Record<string, unknown>): Promise<void> {
+  async handleMessage(version: ProtocolVersion, command: ProtocolCommand, payload: Record<string, unknown>): Promise<void> {
     let messageResponse: Record<string, unknown>;
     if (this.messageHandlers.has(command) && command !== ProtocolCommand.UNKNOWN) {
       try {
@@ -32,7 +33,11 @@ export default class UIService extends AbstractUIService {
       throw new BaseError(`${command} is not implemented to handle message payload ${JSON.stringify(payload, null, 2)}`);
     }
     // Send the built response
-    this.webSocketServer.broadcastToClients(messageResponse);
+    this.webSocketServer.broadcastToClients(this.buildProtocolMessage(version, command, messageResponse));
+  }
+
+  private handleListChargingStations(payload: Record<string, unknown>) {
+    return this.chargingStations;
   }
 
   private handleStartTransaction(payload: Record<string, unknown>) { }
index 7a078bc2418cf048a199937e3341e10938fe0196..d8c61861c63995b319734cd0b61aa1985e354dac 100644 (file)
@@ -1,12 +1,23 @@
-import { ProtocolCommand } from '../../../types/UIProtocol';
+import { ProtocolCommand, ProtocolVersion } from '../../../types/UIProtocol';
+
 import WebSocketServer from '../../WebSocketServer';
 
 export default abstract class AbstractUIService {
+  public readonly chargingStations: Set<string>;
   protected readonly webSocketServer: WebSocketServer;
 
   constructor(webSocketServer: WebSocketServer) {
+    this.chargingStations = new Set<string>();
     this.webSocketServer = webSocketServer;
   }
 
-  abstract handleMessage(command: ProtocolCommand, payload: Record<string, unknown>): Promise<void>;
+  protected buildProtocolMessage(
+      version: ProtocolVersion,
+      command: ProtocolCommand,
+      payload: Record<string, unknown>,
+  ): string {
+    return JSON.stringify([version, command, payload]);
+  }
+
+  abstract handleMessage(version: ProtocolVersion, command: ProtocolCommand, payload: Record<string, unknown>): Promise<void>;
 }
index f016d8ffba7f980cf4ddb77d6222a5c236005676..a48e07688f4df67b21eee449fa407c3ba85518de 100644 (file)
@@ -6,6 +6,8 @@ export interface ChargingStationWorkerData extends WorkerData {
 }
 
 enum InternalChargingStationWorkerMessageEvents {
+  STARTED = 'started',
+  STOPPED = 'stopped',
   PERFORMANCE_STATISTICS = 'performanceStatistics'
 }
 
index a7dfa334ef7f3fbb7c0e1b2ec03782c6a00a2538..3e4d6232ba6202ca395fa57791fe8886b0f332e5 100644 (file)
@@ -5,6 +5,7 @@ export enum ProtocolVersion {
 }
 
 export enum ProtocolCommand {
+  LIST_CHARGING_STATIONS = 'listChargingStations',
   START_TRANSACTION = 'startTransaction',
   STOP_TRANSACTION = 'stopTransaction',
   UNKNOWN = 'unknown',