build(simulator): cleanup TS configuration
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStationUtils.ts
index d8f67c21460b626875d01be4bae961e93d1c3b78..ab781fae3cb3382022abb8f61ed7b55f021e9ef0 100644 (file)
@@ -1,11 +1,12 @@
-import crypto from 'node:crypto';
-import path from 'node:path';
+import { createHash, randomBytes } from 'node:crypto';
+import type { EventEmitter } from 'node:events';
+import { basename, dirname, join } from 'node:path';
 import { fileURLToPath } from 'node:url';
 
 import chalk from 'chalk';
 import moment from 'moment';
 
-import type { ChargingStation } from './internal';
+import type { ChargingStation } from './ChargingStation';
 import { BaseError } from '../exception';
 import {
   AmpereUnits,
@@ -18,6 +19,7 @@ import {
   type ChargingSchedulePeriod,
   type ChargingStationInfo,
   type ChargingStationTemplate,
+  ChargingStationWorkerMessageEvents,
   ConnectorPhaseRotation,
   type ConnectorStatus,
   ConnectorStatusEnum,
@@ -29,15 +31,7 @@ import {
   RecurrencyKindType,
   Voltage,
 } from '../types';
-import {
-  ACElectricUtils,
-  Configuration,
-  Constants,
-  DCElectricUtils,
-  Utils,
-  logger,
-} from '../utils';
-import { WorkerProcessType } from '../worker';
+import { ACElectricUtils, Constants, DCElectricUtils, Utils, logger } from '../utils';
 
 const moduleName = 'ChargingStationUtils';
 
@@ -61,6 +55,19 @@ export class ChargingStationUtils {
         )}${idSuffix}`;
   }
 
+  public static countReservableConnectors(connectors: Map<number, ConnectorStatus>) {
+    let reservableConnectors = 0;
+    for (const [connectorId, connectorStatus] of connectors) {
+      if (connectorId === 0) {
+        continue;
+      }
+      if (connectorStatus.status === ConnectorStatusEnum.Available) {
+        ++reservableConnectors;
+      }
+    }
+    return reservableConnectors;
+  }
+
   public static getHashId(index: number, stationTemplate: ChargingStationTemplate): string {
     const chargingStationInfo = {
       chargePointModel: stationTemplate.chargePointModel,
@@ -78,8 +85,7 @@ export class ChargingStationUtils {
         meterType: stationTemplate.meterType,
       }),
     };
-    return crypto
-      .createHash(Constants.DEFAULT_HASH_ALGORITHM)
+    return createHash(Constants.DEFAULT_HASH_ALGORITHM)
       .update(
         `${JSON.stringify(chargingStationInfo)}${ChargingStationUtils.getChargingStationId(
           index,
@@ -153,7 +159,7 @@ export class ChargingStationUtils {
     return connectorBootStatus;
   }
 
-  public static checkTemplateFile(
+  public static checkTemplate(
     stationTemplate: ChargingStationTemplate,
     logPrefix: string,
     templateFile: string
@@ -169,18 +175,18 @@ export class ChargingStationUtils {
       throw new BaseError(errorMsg);
     }
     if (Utils.isEmptyObject(stationTemplate.AutomaticTransactionGenerator)) {
-      stationTemplate.AutomaticTransactionGenerator = {
-        enable: false,
-        minDuration: 60,
-        maxDuration: 120,
-        minDelayBetweenTwoTransactions: 15,
-        maxDelayBetweenTwoTransactions: 30,
-        probabilityOfStart: 1,
-        stopAfterHours: 0.3,
-        stopOnConnectionFailure: true,
-      };
+      stationTemplate.AutomaticTransactionGenerator = Constants.DEFAULT_ATG_CONFIGURATION;
       logger.warn(
-        `${logPrefix} Empty automatic transaction generator configuration from template file ${templateFile}, set to default values`
+        `${logPrefix} Empty automatic transaction generator configuration from template file ${templateFile}, set to default: %j`,
+        Constants.DEFAULT_ATG_CONFIGURATION
+      );
+    }
+    if (
+      Utils.isNullOrUndefined(stationTemplate.idTagsFile) ||
+      Utils.isEmptyString(stationTemplate.idTagsFile)
+    ) {
+      logger.warn(
+        `${logPrefix} Missing id tags file in template file ${templateFile}. That can lead to issues with the Automatic Transaction Generator`
       );
     }
   }
@@ -351,16 +357,6 @@ export class ChargingStationUtils {
     }
   }
 
-  public static workerPoolInUse(): boolean {
-    return [WorkerProcessType.dynamicPool, WorkerProcessType.staticPool].includes(
-      Configuration.getWorker().processType
-    );
-  }
-
-  public static workerDynamicPoolInUse(): boolean {
-    return Configuration.getWorker().processType === WorkerProcessType.dynamicPool;
-  }
-
   public static warnTemplateKeysDeprecation(
     stationTemplate: ChargingStationTemplate,
     logPrefix: string,
@@ -549,14 +545,29 @@ export class ChargingStationUtils {
   public static getIdTagsFile(stationInfo: ChargingStationInfo): string | undefined {
     return (
       stationInfo.idTagsFile &&
-      path.join(
-        path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../'),
-        'assets',
-        path.basename(stationInfo.idTagsFile)
-      )
+      join(dirname(fileURLToPath(import.meta.url)), 'assets', basename(stationInfo.idTagsFile))
     );
   }
 
+  public static waitForChargingStationEvents = async (
+    emitter: EventEmitter,
+    event: ChargingStationWorkerMessageEvents,
+    eventsToWait: number
+  ): Promise<number> => {
+    return new Promise((resolve) => {
+      let events = 0;
+      if (eventsToWait === 0) {
+        resolve(events);
+      }
+      emitter.on(event, () => {
+        ++events;
+        if (events === eventsToWait) {
+          resolve(events);
+        }
+      });
+    });
+  };
+
   private static getConfiguredNumberOfConnectors(stationTemplate: ChargingStationTemplate): number {
     let configuredMaxConnectors: number;
     if (Utils.isNotEmptyArray(stationTemplate.numberOfConnectors) === true) {
@@ -762,9 +773,7 @@ export class ChargingStationUtils {
     randomBytesLength?: number;
     upperCase?: boolean;
   }): string {
-    const randomSerialNumberSuffix = crypto
-      .randomBytes(params?.randomBytesLength ?? 16)
-      .toString('hex');
+    const randomSerialNumberSuffix = randomBytes(params?.randomBytesLength ?? 16).toString('hex');
     if (params?.upperCase) {
       return randomSerialNumberSuffix.toUpperCase();
     }