Ensure performance statistics is started before connection to the OCPP
authorJérôme Benoit <jerome.benoit@sap.com>
Fri, 13 Aug 2021 20:44:30 +0000 (22:44 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Fri, 13 Aug 2021 20:44:30 +0000 (22:44 +0200)
server.

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
14 files changed:
src/assets/station-templates/evlink.station-template.json
src/assets/station-templates/keba.station-template.json
src/assets/station-templates/schneider-imredd.station-template.json
src/assets/station-templates/siemens.station-template.json
src/assets/station-templates/virtual-simple-atg.station-template.json
src/assets/station-templates/virtual-simple.station-template.json
src/assets/station-templates/virtual.station-template.json
src/charging-station/Bootstrap.ts
src/charging-station/ChargingStation.ts
src/utils/PerformanceStatistics.ts
src/worker/WorkerDynamicPool.ts
src/worker/WorkerSet.ts
src/worker/WorkerStaticPool.ts
src/worker/WorkerUtils.ts [new file with mode: 0644]

index de6d2983e3f359d9a8e6fdec847434763e0ff5b7..0b8e1506e081a6f3f2ddcc1ac09c4cf07cb3f725 100644 (file)
         "key": "AuthorizeRemoteTxRequests",
         "readonly": false,
         "value": "false"
+      },
+      {
+        "key": "WebSocketPingInterval",
+        "readonly": false,
+        "value": "60"
       }
     ]
   },
index 78e43df9a18af235228c0e30a5e1b723743272bc..72ac62c42094552bb74553fe7d8fe98612a03535 100644 (file)
         "key": "AuthorizeRemoteTxRequests",
         "readonly": false,
         "value": "false"
+      },
+      {
+        "key": "WebSocketPingInterval",
+        "readonly": false,
+        "value": "60"
       }
     ]
   },
index 24f6daacaf65d3f482684a9e127ee9379b4d7412..4609eac287cf244c1378b7f23ffd9ba88a1d27e8 100644 (file)
         "key": "AuthorizeRemoteTxRequests",
         "readonly": false,
         "value": "false"
+      },
+      {
+        "key": "WebSocketPingInterval",
+        "readonly": false,
+        "value": "60"
       }
     ]
   },
index 4d78cca233dfccf6563f49138d07022a6324367e..29141bf8ff78f77659d99d3c4df7d98e805076a0 100644 (file)
         "key": "AuthorizeRemoteTxRequests",
         "readonly": false,
         "value": "false"
+      },
+      {
+        "key": "WebSocketPingInterval",
+        "readonly": false,
+        "value": "60"
       }
     ]
   },
index 306e03a14c3f9c054ae1bd67f60aa8ef4803102a..79d0cb4b5a139ef1111fd397213967eb93f11a3b 100644 (file)
         "key": "AuthorizeRemoteTxRequests",
         "readonly": false,
         "value": "false"
+      },
+      {
+        "key": "WebSocketPingInterval",
+        "readonly": false,
+        "value": "60"
       }
     ]
   },
index 6eb68a4611f37463313f2ae2fe602cfe59a36b3f..d3939c8e91b6674f7e63b58e085823d80cac7519 100644 (file)
         "key": "AuthorizeRemoteTxRequests",
         "readonly": false,
         "value": "false"
+      },
+      {
+        "key": "WebSocketPingInterval",
+        "readonly": false,
+        "value": "60"
       }
     ]
   },
index 31d52b59b5e47a3232e036a4346394e79029ef9b..d330a85cc1a6e7263d8e57c09b980af9b7c7f774 100644 (file)
         "key": "AuthorizeRemoteTxRequests",
         "readonly": false,
         "value": "false"
+      },
+      {
+        "key": "WebSocketPingInterval",
+        "readonly": false,
+        "value": "60"
       }
     ]
   },
index f5c0de9f6b722a50aca6ab0a8c85315e6d3455ce..acfd99145e9a33b4d983bbecfc864427c0ebd9ae 100644 (file)
@@ -17,7 +17,7 @@ export default class Bootstrap {
   private constructor() {
     this.started = false;
     this.workerScript = path.join(path.resolve(__dirname, '../'), 'charging-station', 'StationWorker.js');
-    Configuration.setConfigurationChangeCallback(async () => await Bootstrap.getInstance().restart());
+    Configuration.setConfigurationChangeCallback(async () => Bootstrap.getInstance().restart());
   }
 
   public static getInstance(): Bootstrap {
index 79c9e65afc219c2672f6fc49a964f0333b618a0e..4fc275bcdc7cc0b5f5206b5d731748b525d30f9f 100644 (file)
@@ -298,6 +298,9 @@ export default class ChargingStation {
   }
 
   public start(): void {
+    if (this.getEnableStatistics()) {
+      this.performanceStatistics.start();
+    }
     this.openWSConnection();
     // Monitor authorization file
     this.startAuthorizationFileMonitoring();
@@ -329,18 +332,20 @@ export default class ChargingStation {
     if (this.isWebSocketOpen()) {
       this.wsConnection.close();
     }
+    if (this.getEnableStatistics()) {
+      this.performanceStatistics.stop();
+    }
     this.bootNotificationResponse = null;
     this.hasStopped = true;
   }
 
   public getConfigurationKey(key: string | StandardParametersKey, caseInsensitive = false): ConfigurationKey | undefined {
-    const configurationKey: ConfigurationKey | undefined = this.configuration.configurationKey.find((configElement) => {
+    return this.configuration.configurationKey.find((configElement) => {
       if (caseInsensitive) {
         return configElement.key.toLowerCase() === key.toLowerCase();
       }
       return configElement.key === key;
     });
-    return configurationKey;
   }
 
   public addConfigurationKey(key: string | StandardParametersKey, value: string, readonly = false, visible = true, reboot = false): void {
@@ -716,7 +721,7 @@ export default class ChargingStation {
   }
 
   private getTemplateChargingStationConfiguration(): ChargingStationConfiguration {
-    return this.stationInfo.Configuration ? this.stationInfo.Configuration : {} as ChargingStationConfiguration;
+    return this.stationInfo.Configuration ?? {} as ChargingStationConfiguration;
   }
 
   private getAuthorizationFile(): string | undefined {
@@ -840,9 +845,6 @@ export default class ChargingStation {
     }
     // Start the ATG
     this.startAutomaticTransactionGenerator();
-    if (this.getEnableStatistics()) {
-      this.performanceStatistics.start();
-    }
   }
 
   private startAutomaticTransactionGenerator() {
@@ -1012,6 +1014,8 @@ export default class ChargingStation {
   }
 
   private async reconnect(error: any): Promise<void> {
+    // Stop WebSocket ping
+    this.stopWebSocketPing();
     // Stop heartbeat
     this.stopHeartbeat();
     // Stop the ATG if needed
index e7cd58e8b9e17a39d1546c37c2a9d39d447d4c22..49f75adea6ef7fa12f43b82ad6b1aa967ea0e3ef 100644 (file)
@@ -75,7 +75,9 @@ export default class PerformanceStatistics {
   }
 
   public stop(): void {
-    clearInterval(this.displayInterval);
+    if (this.displayInterval) {
+      clearInterval(this.displayInterval);
+    }
     performance.clearMarks();
     this.performanceObserver.disconnect();
   }
index 9141c2f0b2f05ae3beb4c597731e4e256f326187..8ab960f365c986eec798c10e1f7e6d0cf1af8451 100644 (file)
@@ -4,6 +4,7 @@ import Utils from '../utils/Utils';
 import { Worker } from 'worker_threads';
 import WorkerAbstract from './WorkerAbstract';
 import { WorkerData } from '../types/Worker';
+import { WorkerUtils } from './WorkerUtils';
 
 export default class WorkerDynamicPool<T> extends WorkerAbstract {
   private pool: DynamicPool;
@@ -70,11 +71,7 @@ class DynamicPool extends DynamicThreadPool<WorkerData> {
 
   public static getInstance(min: number, max: number, workerScript: string, opts?: PoolOptions<Worker>): DynamicPool {
     if (!DynamicPool.instance) {
-      opts.exitHandler = opts?.exitHandler ?? ((code) => {
-        if (code !== 0) {
-          console.error(`Worker stopped with exit code ${code}`);
-        }
-      });
+      opts.exitHandler = opts?.exitHandler ?? WorkerUtils.defaultExitHandler;
       DynamicPool.instance = new DynamicPool(min, max, workerScript, opts);
     }
     return DynamicPool.instance;
index 2ccd27961941ac5c56eb3ddb1a463138dea21495..9a6f457dd672bcfe42a004997db7ab8244108a6b 100644 (file)
@@ -3,6 +3,7 @@ import { WorkerEvents, WorkerSetElement } from '../types/Worker';
 import Utils from '../utils/Utils';
 import { Worker } from 'worker_threads';
 import WorkerAbstract from './WorkerAbstract';
+import { WorkerUtils } from './WorkerUtils';
 
 export default class WorkerSet<T> extends WorkerAbstract {
   public maxElementsPerWorker: number;
@@ -76,9 +77,7 @@ export default class WorkerSet<T> extends WorkerAbstract {
     worker.on('message', () => { });
     worker.on('error', () => { });
     worker.on('exit', (code) => {
-      if (code !== 0) {
-        console.error(`Worker stopped with exit code ${code}`);
-      }
+      WorkerUtils.defaultExitHandler(code);
       this.workerSet.delete(this.getWorkerSetElementByWorker(worker));
     });
     this.workerSet.add({ worker, numberOfWorkerElements: 0 });
index 7a304b707d62b0083c98ce82795921f5ff92072c..cf46cfa55f7662f671a5a24635c1f9566feb55f4 100644 (file)
@@ -4,6 +4,7 @@ import Utils from '../utils/Utils';
 import { Worker } from 'worker_threads';
 import WorkerAbstract from './WorkerAbstract';
 import { WorkerData } from '../types/Worker';
+import { WorkerUtils } from './WorkerUtils';
 
 export default class WorkerStaticPool<T> extends WorkerAbstract {
   private pool: StaticPool;
@@ -68,11 +69,7 @@ class StaticPool extends FixedThreadPool<WorkerData> {
 
   public static getInstance(numberOfThreads: number, workerScript: string, opts?: PoolOptions<Worker>): StaticPool {
     if (!StaticPool.instance) {
-      opts.exitHandler = opts?.exitHandler ?? ((code) => {
-        if (code !== 0) {
-          console.error(`Worker stopped with exit code ${code}`);
-        }
-      });
+      opts.exitHandler = opts?.exitHandler ?? WorkerUtils.defaultExitHandler;
       StaticPool.instance = new StaticPool(numberOfThreads, workerScript, opts);
     }
     return StaticPool.instance;
diff --git a/src/worker/WorkerUtils.ts b/src/worker/WorkerUtils.ts
new file mode 100644 (file)
index 0000000..7db9de9
--- /dev/null
@@ -0,0 +1,7 @@
+export class WorkerUtils {
+  public static defaultExitHandler = (code: number): void => {
+    if (code !== 0) {
+      console.error(`Worker stopped with exit code ${code}`);
+    }
+  };
+}