fix(simulator): fix empty array detection helper semantic
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStation.ts
index 9d69f038ea23dcf64f235e004e19b9b425dbfb8e..a425d865651ead0c168a714b163705255f5b3434 100644 (file)
@@ -1,9 +1,9 @@
 // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
 
-import fs from 'fs';
 import crypto from 'node:crypto';
-import path from 'path';
-import { URL } from 'url';
+import fs from 'node:fs';
+import path from 'node:path';
+import { URL } from 'node:url';
 import { parentPort } from 'worker_threads';
 
 import merge from 'just-merge';
@@ -36,6 +36,7 @@ import type { ChargingStationOcppConfiguration } from '../types/ChargingStationO
 import {
   type ChargingStationTemplate,
   CurrentType,
+  type FirmwareUpgrade,
   PowerUnits,
   type WsOptions,
 } from '../types/ChargingStationTemplate';
@@ -157,17 +158,19 @@ export default class ChargingStation {
     );
   }
 
-  public logPrefix(): string {
+  public logPrefix = (): string => {
     return Utils.logPrefix(
       ` ${
-        this?.stationInfo?.chargingStationId ??
-        ChargingStationUtils.getChargingStationId(this.index, this.getTemplateFromFile())
+        (Utils.isNotEmptyString(this?.stationInfo?.chargingStationId) &&
+          this?.stationInfo?.chargingStationId) ??
+        ChargingStationUtils.getChargingStationId(this.index, this.getTemplateFromFile()) ??
+        ''
       } |`
     );
-  }
+  };
 
   public hasAuthorizedTags(): boolean {
-    return !Utils.isEmptyArray(
+    return Utils.isNotEmptyArray(
       this.authorizedTagsCache.getAuthorizedTags(
         ChargingStationUtils.getAuthorizationFile(this.stationInfo)
       )
@@ -452,7 +455,7 @@ export default class ChargingStation {
       return;
     } else if (
       this.getConnectorStatus(connectorId)?.transactionStarted === true &&
-      !this.getConnectorStatus(connectorId)?.transactionId
+      Utils.isNullOrUndefined(this.getConnectorStatus(connectorId)?.transactionId)
     ) {
       logger.error(
         `${this.logPrefix()} Trying to start MeterValues on connector Id ${connectorId} with no transaction id`
@@ -506,12 +509,12 @@ export default class ChargingStation {
         this.openWSConnection();
         // Monitor charging station template file
         this.templateFileWatcher = FileUtils.watchJsonFile(
-          this.logPrefix(),
-          FileType.ChargingStationTemplate,
           this.templateFile,
-          null,
+          FileType.ChargingStationTemplate,
+          this.logPrefix(),
+          undefined,
           (event, filename): void => {
-            if (filename && event === 'change') {
+            if (Utils.isNotEmptyString(filename) && event === 'change') {
               try {
                 logger.debug(
                   `${this.logPrefix()} ${FileType.ChargingStationTemplate} ${
@@ -596,12 +599,12 @@ export default class ChargingStation {
     this.getConnectorStatus(connectorId).idTagAuthorized = false;
     this.getConnectorStatus(connectorId).transactionRemoteStarted = false;
     this.getConnectorStatus(connectorId).transactionStarted = false;
-    delete this.getConnectorStatus(connectorId).localAuthorizeIdTag;
-    delete this.getConnectorStatus(connectorId).authorizeIdTag;
-    delete this.getConnectorStatus(connectorId).transactionId;
-    delete this.getConnectorStatus(connectorId).transactionIdTag;
+    delete this.getConnectorStatus(connectorId)?.localAuthorizeIdTag;
+    delete this.getConnectorStatus(connectorId)?.authorizeIdTag;
+    delete this.getConnectorStatus(connectorId)?.transactionId;
+    delete this.getConnectorStatus(connectorId)?.transactionIdTag;
     this.getConnectorStatus(connectorId).transactionEnergyActiveImportRegisterValue = 0;
-    delete this.getConnectorStatus(connectorId).transactionBeginMeterValue;
+    delete this.getConnectorStatus(connectorId)?.transactionBeginMeterValue;
     this.stopMeterValues(connectorId);
     parentPort?.postMessage(MessageChannelUtils.buildUpdatedMessage(this));
   }
@@ -710,7 +713,7 @@ export default class ChargingStation {
         this.getAutomaticTransactionGeneratorConfigurationFromTemplate(),
       this
     );
-    if (!Utils.isEmptyArray(connectorIds)) {
+    if (Utils.isNotEmptyArray(connectorIds)) {
       for (const connectorId of connectorIds) {
         this.automaticTransactionGenerator?.startConnector(connectorId);
       }
@@ -721,7 +724,7 @@ export default class ChargingStation {
   }
 
   public stopAutomaticTransactionGenerator(connectorIds?: number[]): void {
-    if (!Utils.isEmptyArray(connectorIds)) {
+    if (Utils.isNotEmptyArray(connectorIds)) {
       for (const connectorId of connectorIds) {
         this.automaticTransactionGenerator?.stopConnector(connectorId);
       }
@@ -819,10 +822,10 @@ export default class ChargingStation {
       }
     } catch (error) {
       FileUtils.handleFileException(
-        this.logPrefix(),
-        FileType.ChargingStationTemplate,
         this.templateFile,
-        error as NodeJS.ErrnoException
+        FileType.ChargingStationTemplate,
+        error as NodeJS.ErrnoException,
+        this.logPrefix()
       );
     }
     return template;
@@ -862,7 +865,7 @@ export default class ChargingStation {
     );
     stationInfo.ocppVersion = stationTemplate?.ocppVersion ?? OCPPVersion.VERSION_16;
     ChargingStationUtils.createSerialNumber(stationTemplate, stationInfo);
-    if (!Utils.isEmptyArray(stationTemplate?.power)) {
+    if (Utils.isNotEmptyArray(stationTemplate?.power)) {
       stationTemplate.power = stationTemplate.power as number[];
       const powerArrayRandomIndex = Math.floor(Utils.secureRandom() * stationTemplate.power.length);
       stationInfo.maximumPower =
@@ -879,7 +882,7 @@ export default class ChargingStation {
     stationInfo.firmwareVersionPattern =
       stationTemplate?.firmwareVersionPattern ?? Constants.SEMVER_PATTERN;
     if (
-      stationInfo.firmwareVersion &&
+      Utils.isNotEmptyString(stationInfo.firmwareVersion) &&
       new RegExp(stationInfo.firmwareVersionPattern).test(stationInfo.firmwareVersion) === false
     ) {
       logger.warn(
@@ -888,13 +891,16 @@ export default class ChargingStation {
         } does not match firmware version pattern '${stationInfo.firmwareVersionPattern}'`
       );
     }
-    stationInfo.firmwareUpgrade = merge(
+    stationInfo.firmwareUpgrade = merge<FirmwareUpgrade>(
       {
+        versionUpgrade: {
+          step: 1,
+        },
         reset: true,
       },
       stationTemplate?.firmwareUpgrade ?? {}
     );
-    stationInfo.resetTime = stationTemplate?.resetTime
+    stationInfo.resetTime = !Utils.isNullOrUndefined(stationTemplate?.resetTime)
       ? stationTemplate.resetTime * 1000
       : Constants.CHARGING_STATION_DEFAULT_RESET_TIME;
     const configuredMaxConnectors =
@@ -1031,19 +1037,19 @@ export default class ChargingStation {
     }
     if (
       this.stationInfo.firmwareStatus === FirmwareStatus.Installing &&
-      this.stationInfo.firmwareVersion &&
-      this.stationInfo.firmwareVersionPattern
+      Utils.isNotEmptyString(this.stationInfo.firmwareVersion) &&
+      Utils.isNotEmptyString(this.stationInfo.firmwareVersionPattern)
     ) {
-      const versionStep = this.stationInfo.firmwareUpgrade?.versionUpgrade?.step ?? 1;
-      const patternGroup: number =
+      const patternGroup: number | undefined =
         this.stationInfo.firmwareUpgrade?.versionUpgrade?.patternGroup ??
-        this.stationInfo.firmwareVersion.split('.').length;
+        this.stationInfo.firmwareVersion?.split('.').length;
       const match = this.stationInfo?.firmwareVersion
         ?.match(new RegExp(this.stationInfo.firmwareVersionPattern))
         ?.slice(1, patternGroup + 1);
       const patchLevelIndex = match.length - 1;
       match[patchLevelIndex] = (
-        Utils.convertToInt(match[patchLevelIndex]) + versionStep
+        Utils.convertToInt(match[patchLevelIndex]) +
+        this.stationInfo.firmwareUpgrade?.versionUpgrade?.step
       ).toString();
       this.stationInfo.firmwareVersion = match?.join('.');
     }
@@ -1096,7 +1102,7 @@ export default class ChargingStation {
       );
     }
     if (
-      this.stationInfo.amperageLimitationOcppKey &&
+      Utils.isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
       !ChargingStationConfigurationUtils.getConfigurationKey(
         this,
         this.stationInfo.amperageLimitationOcppKey
@@ -1335,10 +1341,10 @@ export default class ChargingStation {
         }
       } catch (error) {
         FileUtils.handleFileException(
-          this.logPrefix(),
-          FileType.ChargingStationConfiguration,
           this.configurationFile,
-          error as NodeJS.ErrnoException
+          FileType.ChargingStationConfiguration,
+          error as NodeJS.ErrnoException,
+          this.logPrefix()
         );
       }
     }
@@ -1381,10 +1387,10 @@ export default class ChargingStation {
         }
       } catch (error) {
         FileUtils.handleFileException(
-          this.logPrefix(),
-          FileType.ChargingStationConfiguration,
           this.configurationFile,
-          error as NodeJS.ErrnoException
+          FileType.ChargingStationConfiguration,
+          error as NodeJS.ErrnoException,
+          this.logPrefix()
         );
       }
     } else {
@@ -1677,9 +1683,7 @@ export default class ChargingStation {
 
   private getUseConnectorId0(stationInfo?: ChargingStationInfo): boolean {
     const localStationInfo = stationInfo ?? this.stationInfo;
-    return !Utils.isUndefined(localStationInfo.useConnectorId0)
-      ? localStationInfo.useConnectorId0
-      : true;
+    return localStationInfo?.useConnectorId0 ?? true;
   }
 
   private getNumberOfRunningTransactions(): number {
@@ -1763,7 +1767,7 @@ export default class ChargingStation {
 
   private getAmperageLimitation(): number | undefined {
     if (
-      this.stationInfo.amperageLimitationOcppKey &&
+      Utils.isNotEmptyString(this.stationInfo?.amperageLimitationOcppKey) &&
       ChargingStationConfigurationUtils.getConfigurationKey(
         this,
         this.stationInfo.amperageLimitationOcppKey
@@ -1924,7 +1928,7 @@ export default class ChargingStation {
 
   private getConfiguredSupervisionUrl(): URL {
     const supervisionUrls = this.stationInfo?.supervisionUrls ?? Configuration.getSupervisionUrls();
-    if (!Utils.isEmptyArray(supervisionUrls)) {
+    if (Utils.isNotEmptyArray(supervisionUrls)) {
       switch (Configuration.getSupervisionUrlDistribution()) {
         case SupervisionUrlDistribution.ROUND_ROBIN:
           // FIXME
@@ -1996,9 +2000,7 @@ export default class ChargingStation {
   }
 
   private getReconnectExponentialDelay(): boolean {
-    return !Utils.isUndefined(this.stationInfo.reconnectExponentialDelay)
-      ? this.stationInfo.reconnectExponentialDelay
-      : false;
+    return this.stationInfo?.reconnectExponentialDelay ?? false;
   }
 
   private async reconnect(): Promise<void> {