UI Server: Add support for starting the ATG on defined connectors
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 30 Aug 2022 23:56:48 +0000 (01:56 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 30 Aug 2022 23:56:48 +0000 (01:56 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/assets/Insomnia_CSSimulatorUIProtocol.json
src/charging-station/AutomaticTransactionGenerator.ts
src/charging-station/ChargingStation.ts
src/charging-station/ChargingStationWorkerBroadcastChannel.ts
src/types/WorkerBroadcastChannel.ts

index 36f80849157e725830d966b3cc4e905e3e688dda..478f12e08c50403cd36243c05ffa2ad5c531cb03 100644 (file)
@@ -1,13 +1,13 @@
 {
   "_type": "export",
   "__export_format": 4,
-  "__export_date": "2022-08-29T21:30:31.588Z",
+  "__export_date": "2022-08-30T23:51:59.143Z",
   "__export_source": "insomnia.desktop.app:v2022.5.1",
   "resources": [
     {
       "_id": "req_606dcee139984772877def40fcbb5c76",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661806107269,
+      "modified": 1661902790226,
       "created": 1661789624987,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/listChargingStations",
       "name": "listChargingStations",
@@ -46,7 +46,7 @@
     {
       "_id": "req_7d5f9506e7ac49208a4f960a7740663e",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661803912361,
+      "modified": 1661899373583,
       "created": 1661789624990,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/startSimulator",
       "name": "startSimulator",
@@ -75,7 +75,7 @@
     {
       "_id": "req_59056be11534481c80a0b0da32e2a06a",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661803913261,
+      "modified": 1661868197495,
       "created": 1661789624994,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/stopSimulator",
       "name": "stopSimulator",
     {
       "_id": "req_aad7fd6db4c64869b60048b915010efc",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661803915999,
+      "modified": 1661902835643,
       "created": 1661789624998,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/startChargingStation",
       "name": "startChargingStation",
     {
       "_id": "req_d72d91cf3fb044179b8ae9d92a74f99c",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661803917031,
+      "modified": 1661901541707,
       "created": 1661789625002,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/stopChargingStation",
       "name": "stopChargingStation",
     {
       "_id": "req_747f458d196f4681b5fe15204b0067aa",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661803918135,
+      "modified": 1661901542755,
       "created": 1661789625005,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/openConnection",
       "name": "openConnection",
     {
       "_id": "req_401e6a62a33c4b6c90aaa2e019daab6d",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661803955362,
+      "modified": 1661901532668,
       "created": 1661789625014,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/closeConnection",
       "name": "closeConnection",
     {
       "_id": "req_2f757efe92fb4936ad4fa4b6763f9293",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661808615447,
+      "modified": 1661901511510,
       "created": 1661789625017,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/startTransaction",
       "name": "startTransaction",
     {
       "_id": "req_7c285fb6cb6948a08235a6c73cbeb1f9",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661808613804,
+      "modified": 1661903221120,
       "created": 1661789625020,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/stopTransaction",
       "name": "stopTransaction",
     {
       "_id": "req_b33c704fe3464dc5a5d3694abd9320d0",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661808616683,
+      "modified": 1661903422637,
       "created": 1661803778569,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/startAutomaticTransactionGenerator",
       "name": "startAutomaticTransactionGenerator",
       "method": "POST",
       "body": {
         "mimeType": "application/json",
-        "text": "{\n\t\"hashIds\": [\n\t\t\"e4a2cd1d8b719aca0a3655bc19cd5f98edceea6aef6af25bf3306c49b342df881cec2a00ba8db95dffabea9b309563d2\"\n\t]\n}"
+        "text": "{\n\t\"hashIds\": [\n\t\t\"0058d8b50e422cce5bbd0c0a4ad13d5d657e8a88670dcf04c1b2b563fea3db5b96a3686278b374ed050e21baef89060e\",\n\t\t\"331d024fea36e3e2483a0e5dc9376234241c8c099ad201a441437b23622c308555183f37cbc84a1818c1c45aaae50896\"\n\t],\n\t\"connectorIds\": [\n\t\t2\n\t]\n}"
       },
       "parameters": [],
       "headers": [
     {
       "_id": "req_24c1c55fe3ba4ddb94702408f21a64df",
       "parentId": "wrk_d64b10b1e0c14563a80484ee684b5205",
-      "modified": 1661808612661,
+      "modified": 1661903489161,
       "created": 1661803846882,
       "url": "{{baseUrl}}/{{protocol}}/{{version}}/stopAutomaticTransactionGenerator",
       "name": "stopAutomaticTransactionGenerator",
       "method": "POST",
       "body": {
         "mimeType": "application/json",
-        "text": "{\n\t\"hashIds\": [\n\t\t\"e4a2cd1d8b719aca0a3655bc19cd5f98edceea6aef6af25bf3306c49b342df881cec2a00ba8db95dffabea9b309563d2\"\n\t]\n}"
+        "text": "{\n\t\"hashIds\": [\n\t\t\"0058d8b50e422cce5bbd0c0a4ad13d5d657e8a88670dcf04c1b2b563fea3db5b96a3686278b374ed050e21baef89060e\",\n\t\t\"331d024fea36e3e2483a0e5dc9376234241c8c099ad201a441437b23622c308555183f37cbc84a1818c1c45aaae50896\"\n\t],\n\t\"connectorIds\": [\n\t\t2\n\t]\n}"
       },
       "parameters": [],
       "headers": [
index c1674069bad7c188a9462865ee85ed6f205e3c95..6145ac101db56196eed74f77f1df17da840213cb 100644 (file)
@@ -62,8 +62,8 @@ export default class AutomaticTransactionGenerator {
   }
 
   public start(): void {
-    if (this.started) {
-      logger.error(`${this.logPrefix()} trying to start while already started`);
+    if (this.started === true) {
+      logger.warn(`${this.logPrefix()} trying to start while already started`);
       return;
     }
     this.startConnectors();
@@ -71,14 +71,38 @@ export default class AutomaticTransactionGenerator {
   }
 
   public stop(): void {
-    if (!this.started) {
-      logger.error(`${this.logPrefix()} trying to stop while not started`);
+    if (this.started === false) {
+      logger.warn(`${this.logPrefix()} trying to stop while not started`);
       return;
     }
     this.stopConnectors();
     this.started = false;
   }
 
+  public startConnector(connectorId: number): void {
+    if (this.connectorsStatus.has(connectorId) === false) {
+      logger.warn(`${this.logPrefix(connectorId)} trying to start on non existing connector`);
+      return;
+    }
+    if (this.connectorsStatus.get(connectorId)?.start === false) {
+      // Avoid hogging the event loop with a busy loop
+      setImmediate(() => {
+        this.internalStartConnector(connectorId).catch(() => {
+          /* This is intentional */
+        });
+      });
+    } else {
+      logger.warn(`${this.logPrefix(connectorId)} already started on connector`);
+    }
+  }
+
+  public stopConnector(connectorId: number): void {
+    this.connectorsStatus.set(connectorId, {
+      ...this.connectorsStatus.get(connectorId),
+      start: false,
+    });
+  }
+
   private startConnectors(): void {
     if (
       this.connectorsStatus?.size > 0 &&
@@ -111,7 +135,7 @@ export default class AutomaticTransactionGenerator {
             this.connectorsStatus.get(connectorId).startDate.getTime()
         )
     );
-    while (this.connectorsStatus.get(connectorId).start) {
+    while (this.connectorsStatus.get(connectorId).start === true) {
       if (new Date() > this.connectorsStatus.get(connectorId).stopDate) {
         this.stopConnector(connectorId);
         break;
@@ -221,22 +245,6 @@ export default class AutomaticTransactionGenerator {
     );
   }
 
-  private startConnector(connectorId: number): void {
-    // Avoid hogging the event loop with a busy loop
-    setImmediate(() => {
-      this.internalStartConnector(connectorId).catch(() => {
-        /* This is intentional */
-      });
-    });
-  }
-
-  private stopConnector(connectorId: number): void {
-    this.connectorsStatus.set(connectorId, {
-      ...this.connectorsStatus.get(connectorId),
-      start: false,
-    });
-  }
-
   private initializeConnectorStatus(connectorId: number): void {
     this.connectorsStatus.get(connectorId).authorizeRequests =
       this?.connectorsStatus.get(connectorId)?.authorizeRequests ?? 0;
@@ -395,7 +403,7 @@ export default class AutomaticTransactionGenerator {
   private logPrefix(connectorId?: number): string {
     return Utils.logPrefix(
       ` ${this.chargingStation.stationInfo.chargingStationId} | ATG${
-        connectorId && ` on connector #${connectorId.toString()}`
+        connectorId !== undefined ? ` on connector #${connectorId.toString()}` : ''
       }:`
     );
   }
index 0c2123a6fb123d693fedb4ad7e7540c9f8a65ccc..89fffc3bffc03b3399837d211a9d8d31ea5411c3 100644 (file)
@@ -85,12 +85,13 @@ import SharedLRUCache from './SharedLRUCache';
 
 export default class ChargingStation {
   public readonly templateFile: string;
-  public authorizedTagsCache: AuthorizedTagsCache;
   public stationInfo!: ChargingStationInfo;
   public stopped: boolean;
-  public readonly connectors: Map<number, ConnectorStatus>;
+  public authorizedTagsCache: AuthorizedTagsCache;
+  public automaticTransactionGenerator!: AutomaticTransactionGenerator;
   public ocppConfiguration!: ChargingStationOcppConfiguration;
   public wsConnection!: WebSocket;
+  public readonly connectors: Map<number, ConnectorStatus>;
   public readonly requests: Map<string, CachedRequest>;
   public performanceStatistics!: PerformanceStatistics;
   public heartbeatSetInterval!: NodeJS.Timeout;
@@ -109,7 +110,6 @@ export default class ChargingStation {
   private autoReconnectRetryCount: number;
   private templateFileWatcher!: fs.FSWatcher;
   private readonly sharedLRUCache: SharedLRUCache;
-  private automaticTransactionGenerator!: AutomaticTransactionGenerator;
   private webSocketPingSetInterval!: NodeJS.Timeout;
   private readonly chargingStationWorkerBroadcastChannel: ChargingStationWorkerBroadcastChannel;
 
@@ -743,21 +743,29 @@ export default class ChargingStation {
     }
   }
 
-  public startAutomaticTransactionGenerator(): void {
+  public startAutomaticTransactionGenerator(connectorIds?: number[]): void {
     if (!this.automaticTransactionGenerator) {
       this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(
         this.getAutomaticTransactionGeneratorConfigurationFromTemplate(),
         this
       );
     }
-    if (!this.automaticTransactionGenerator.started) {
+    if (!Utils.isEmptyArray(connectorIds)) {
+      for (const connectorId of connectorIds) {
+        this.automaticTransactionGenerator.startConnector(connectorId);
+      }
+    } else {
       this.automaticTransactionGenerator.start();
     }
   }
 
-  public stopAutomaticTransactionGenerator(): void {
-    if (this.automaticTransactionGenerator?.started) {
-      this.automaticTransactionGenerator.stop();
+  public stopAutomaticTransactionGenerator(connectorIds?: number[]): void {
+    if (!Utils.isEmptyArray(connectorIds)) {
+      for (const connectorId of connectorIds) {
+        this.automaticTransactionGenerator?.stopConnector(connectorId);
+      }
+    } else {
+      this.automaticTransactionGenerator?.stop();
       this.automaticTransactionGenerator = null;
     }
   }
index 1d788505d541e00c00b0fadb46de0a4f889a0180..159743a049104cd3d9d210b6a799c374c7614aa7 100644 (file)
@@ -140,10 +140,10 @@ export default class ChargingStationWorkerBroadcastChannel extends WorkerBroadca
           reason: StopTransactionReason.NONE,
         });
       case BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR:
-        this.chargingStation.startAutomaticTransactionGenerator();
+        this.chargingStation.startAutomaticTransactionGenerator(requestPayload.connectorIds);
         break;
       case BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR:
-        this.chargingStation.stopAutomaticTransactionGenerator();
+        this.chargingStation.stopAutomaticTransactionGenerator(requestPayload.connectorIds);
         break;
       default:
         // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
index 65c431404a44d2e842f56c12784a9613a49ea4e3..2cc18943cfbe11019dec4115acf8ad21138f5dc5 100644 (file)
@@ -20,6 +20,7 @@ export enum BroadcastChannelProcedureName {
 
 interface BaseBroadcastChannelRequestPayload extends Omit<RequestPayload, 'hashId' | 'hashIds'> {
   connectorId?: number;
+  connectorIds?: number[];
   transactionId?: number;
   idTag?: string;
 }