Fix and secure random number generation code
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStation.ts
index 103a96f0bdc970b003169adccb801009a4d1c57b..575d70962c21022c1888ebac3f1ec1e90079f18b 100644 (file)
@@ -85,7 +85,7 @@ export default class ChargingStation {
   }
 
   public getRandomTagId(): string {
-    const index = Math.floor(Math.random() * this.authorizedTags.length);
+    const index = Math.floor(Utils.secureRandom() * this.authorizedTags.length);
     return this.authorizedTags[index];
   }
 
@@ -225,17 +225,17 @@ export default class ChargingStation {
   public getSampledValueTemplate(connectorId: number, measurand: MeterValueMeasurand = MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
       phase?: MeterValuePhase): SampledValueTemplate | undefined {
     if (!Constants.SUPPORTED_MEASURANDS.includes(measurand)) {
-      logger.warn(`${this.logPrefix()} Trying to get unsupported MeterValues measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId}`);
+      logger.warn(`${this.logPrefix()} Trying to get unsupported MeterValues measurand '${measurand}' ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId}`);
       return;
     }
     if (measurand !== MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER && !this.getConfigurationKey(StandardParametersKey.MeterValuesSampledData).value.includes(measurand)) {
-      logger.debug(`${this.logPrefix()} Trying to get MeterValues measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId} not found in '${StandardParametersKey.MeterValuesSampledData}' OCPP parameter`);
+      logger.debug(`${this.logPrefix()} Trying to get MeterValues measurand '${measurand}' ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId} not found in '${StandardParametersKey.MeterValuesSampledData}' OCPP parameter`);
       return;
     }
     const sampledValueTemplates: SampledValueTemplate[] = this.getConnector(connectorId).MeterValues;
     for (let index = 0; !Utils.isEmptyArray(sampledValueTemplates) && index < sampledValueTemplates.length; index++) {
       if (!Constants.SUPPORTED_MEASURANDS.includes(sampledValueTemplates[index]?.measurand ?? MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER)) {
-        logger.warn(`${this.logPrefix()} Unsupported MeterValues measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId}`);
+        logger.warn(`${this.logPrefix()} Unsupported MeterValues measurand '${measurand}' ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId}`);
       } else if (phase && sampledValueTemplates[index]?.phase === phase && sampledValueTemplates[index]?.measurand === measurand
                  && this.getConfigurationKey(StandardParametersKey.MeterValuesSampledData).value.includes(measurand)) {
         return sampledValueTemplates[index];
@@ -248,11 +248,11 @@ export default class ChargingStation {
       }
     }
     if (measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) {
-      const errorMsg = `${this.logPrefix()} Missing MeterValues for default measurand ${measurand} in template on connectorId ${connectorId}`;
+      const errorMsg = `${this.logPrefix()} Missing MeterValues for default measurand '${measurand}' in template on connectorId ${connectorId}`;
       logger.error(errorMsg);
       throw new Error(errorMsg);
     }
-    logger.debug(`${this.logPrefix()} No MeterValues for measurand ${measurand} ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId}`);
+    logger.debug(`${this.logPrefix()} No MeterValues for measurand '${measurand}' ${phase ? `on phase ${phase} ` : ''}in template on connectorId ${connectorId}`);
   }
 
   public getAutomaticTransactionGeneratorRequireAuthorize(): boolean {
@@ -435,8 +435,7 @@ export default class ChargingStation {
 
   private getChargingStationId(stationTemplate: ChargingStationTemplate): string {
     // In case of multiple instances: add instance index to charging station id
-    let instanceIndex = process.env.CF_INSTANCE_INDEX ?? 0;
-    instanceIndex = instanceIndex > 0 ? instanceIndex : '';
+    const instanceIndex = process.env.CF_INSTANCE_INDEX ?? 0;
     const idSuffix = stationTemplate.nameSuffix ?? '';
     return stationTemplate.fixedName ? stationTemplate.baseName : stationTemplate.baseName + '-' + instanceIndex.toString() + ('000000000' + this.index.toString()).substr(('000000000' + this.index.toString()).length - 4) + idSuffix;
   }
@@ -454,7 +453,7 @@ export default class ChargingStation {
     const stationInfo: ChargingStationInfo = stationTemplateFromFile ?? {} as ChargingStationInfo;
     if (!Utils.isEmptyArray(stationTemplateFromFile.power)) {
       stationTemplateFromFile.power = stationTemplateFromFile.power as number[];
-      const powerArrayRandomIndex = Math.floor(Math.random() * stationTemplateFromFile.power.length);
+      const powerArrayRandomIndex = Math.floor(Utils.secureRandom() * stationTemplateFromFile.power.length);
       stationInfo.maxPower = stationTemplateFromFile.powerUnit === PowerUnits.KILO_WATT
         ? stationTemplateFromFile.power[powerArrayRandomIndex] * 1000
         : stationTemplateFromFile.power[powerArrayRandomIndex];
@@ -641,7 +640,7 @@ export default class ChargingStation {
         break;
       // Abnormal close
       default:
-        logger.error(`${this.logPrefix()} Socket abnormally closed with status '${Utils.getWebSocketCloseEventStatusString(code)} and reason '${reason}'`);
+        logger.error(`${this.logPrefix()} Socket abnormally closed with status '${Utils.getWebSocketCloseEventStatusString(code)}' and reason '${reason}'`);
         await this.reconnect(code);
         break;
     }
@@ -867,8 +866,7 @@ export default class ChargingStation {
         this.automaticTransactionGeneration = new AutomaticTransactionGenerator(this);
       }
       if (this.automaticTransactionGeneration.timeToStop) {
-        // The ATG might sleep
-        this.automaticTransactionGeneration.start().catch(() => { });
+        this.automaticTransactionGeneration.start();
       }
     }
   }
@@ -901,7 +899,7 @@ export default class ChargingStation {
     if (webSocketPingInterval > 0 && !this.webSocketPingSetInterval) {
       this.webSocketPingSetInterval = setInterval(() => {
         if (this.isWebSocketConnectionOpened()) {
-          this.wsConnection.ping((): void => { });
+          this.wsConnection.ping((): void => { /* This is intentional */ });
         }
       }, webSocketPingInterval * 1000);
       logger.info(this.logPrefix() + ' WebSocket ping started every ' + Utils.secondsToHHMMSS(webSocketPingInterval));
@@ -926,7 +924,7 @@ export default class ChargingStation {
         indexUrl = this.index % supervisionUrls.length;
       } else {
         // Get a random url
-        indexUrl = Math.floor(Math.random() * supervisionUrls.length);
+        indexUrl = Math.floor(Utils.secureRandom() * supervisionUrls.length);
       }
       return new URL(supervisionUrls[indexUrl]);
     }