Combined PR (#197)
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStation.ts
index d3c33fc3a3f8936cf0c2a039599f30bbcb523416..d70223e367eb2ecf0b6ef2b656ae475d1b2d66ad 100644 (file)
@@ -12,13 +12,14 @@ import BaseError from '../exception/BaseError';
 import OCPPError from '../exception/OCPPError';
 import PerformanceStatistics from '../performance/PerformanceStatistics';
 import type { AutomaticTransactionGeneratorConfiguration } from '../types/AutomaticTransactionGenerator';
-import type ChargingStationConfiguration from '../types/ChargingStationConfiguration';
-import type ChargingStationInfo from '../types/ChargingStationInfo';
+import type { ChargingStationConfiguration } from '../types/ChargingStationConfiguration';
+import type { ChargingStationInfo } from '../types/ChargingStationInfo';
 import type { ChargingStationOcppConfiguration } from '../types/ChargingStationOcppConfiguration';
-import ChargingStationTemplate, {
+import {
+  type ChargingStationTemplate,
   CurrentType,
   PowerUnits,
-  WsOptions,
+  type WsOptions,
 } from '../types/ChargingStationTemplate';
 import { SupervisionUrlDistribution } from '../types/ConfigurationData';
 import type { ConnectorStatus } from '../types/ConnectorStatus';
@@ -84,6 +85,7 @@ import type OCPPRequestService from './ocpp/OCPPRequestService';
 import SharedLRUCache from './SharedLRUCache';
 
 export default class ChargingStation {
+  public readonly index: number;
   public readonly templateFile: string;
   public stationInfo!: ChargingStationInfo;
   public started: boolean;
@@ -101,13 +103,13 @@ export default class ChargingStation {
   public powerDivider!: number;
   private starting: boolean;
   private stopping: boolean;
-  private readonly index: number;
   private configurationFile!: string;
   private configurationFileHash!: string;
   private connectorsConfigurationHash!: string;
   private ocppIncomingRequestService!: OCPPIncomingRequestService;
   private readonly messageBuffer: Set<string>;
   private configuredSupervisionUrl!: URL;
+  private configuredSupervisionUrlIndex!: number;
   private wsConnectionRestarted: boolean;
   private autoReconnectRetryCount: number;
   private templateFileWatcher!: fs.FSWatcher;
@@ -155,14 +157,6 @@ export default class ChargingStation {
     );
   }
 
-  public getRandomIdTag(): string {
-    const authorizationFile = ChargingStationUtils.getAuthorizationFile(this.stationInfo);
-    const index = Math.floor(
-      Utils.secureRandom() * this.authorizedTagsCache.getAuthorizedTags(authorizationFile).length
-    );
-    return this.authorizedTagsCache.getAuthorizedTags(authorizationFile)[index];
-  }
-
   public hasAuthorizedTags(): boolean {
     return !Utils.isEmptyArray(
       this.authorizedTagsCache.getAuthorizedTags(
@@ -631,7 +625,7 @@ export default class ChargingStation {
     parentPort.postMessage(MessageChannelUtils.buildUpdatedMessage(this));
   }
 
-  public hasFeatureProfile(featureProfile: SupportedFeatureProfiles) {
+  public hasFeatureProfile(featureProfile: SupportedFeatureProfiles): boolean {
     return ChargingStationConfigurationUtils.getConfigurationKey(
       this,
       StandardParametersKey.SupportedFeatureProfiles
@@ -717,13 +711,15 @@ export default class ChargingStation {
     }
   }
 
-  public startAutomaticTransactionGenerator(connectorIds?: number[]): void {
-    if (!this.automaticTransactionGenerator) {
-      this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(
+  public startAutomaticTransactionGenerator(
+    connectorIds?: number[],
+    automaticTransactionGeneratorConfiguration?: AutomaticTransactionGeneratorConfiguration
+  ): void {
+    this.automaticTransactionGenerator = AutomaticTransactionGenerator.getInstance(
+      automaticTransactionGeneratorConfiguration ??
         this.getAutomaticTransactionGeneratorConfigurationFromTemplate(),
-        this
-      );
-    }
+      this
+    );
     if (!Utils.isEmptyArray(connectorIds)) {
       for (const connectorId of connectorIds) {
         this.automaticTransactionGenerator.startConnector(connectorId);
@@ -879,10 +875,8 @@ export default class ChargingStation {
     stationInfo.resetTime = stationTemplate.resetTime
       ? stationTemplate.resetTime * 1000
       : Constants.CHARGING_STATION_DEFAULT_RESET_TIME;
-    const configuredMaxConnectors = ChargingStationUtils.getConfiguredNumberOfConnectors(
-      this.index,
-      stationTemplate
-    );
+    const configuredMaxConnectors =
+      ChargingStationUtils.getConfiguredNumberOfConnectors(stationTemplate);
     ChargingStationUtils.checkConfiguredMaxConnectors(
       configuredMaxConnectors,
       this.templateFile,
@@ -1644,7 +1638,7 @@ export default class ChargingStation {
   }
 
   // 0 for disabling
-  private getConnectionTimeout(): number | undefined {
+  private getConnectionTimeout(): number {
     if (
       ChargingStationConfigurationUtils.getConfigurationKey(
         this,
@@ -1664,7 +1658,7 @@ export default class ChargingStation {
   }
 
   // -1 for unlimited, 0 for disabling
-  private getAutoReconnectMaxRetries(): number | undefined {
+  private getAutoReconnectMaxRetries(): number {
     if (!Utils.isUndefined(this.stationInfo.autoReconnectMaxRetries)) {
       return this.stationInfo.autoReconnectMaxRetries;
     }
@@ -1675,7 +1669,7 @@ export default class ChargingStation {
   }
 
   // 0 for disabling
-  private getRegistrationMaxRetries(): number | undefined {
+  private getRegistrationMaxRetries(): number {
     if (!Utils.isUndefined(this.stationInfo.registrationMaxRetries)) {
       return this.stationInfo.registrationMaxRetries;
     }
@@ -1927,39 +1921,34 @@ export default class ChargingStation {
       this.stationInfo.supervisionUrls ?? Configuration.getSupervisionUrls()
     );
     if (!Utils.isEmptyArray(supervisionUrls)) {
-      let urlIndex = 0;
       switch (Configuration.getSupervisionUrlDistribution()) {
         case SupervisionUrlDistribution.ROUND_ROBIN:
-          urlIndex = (this.index - 1) % supervisionUrls.length;
+          // FIXME
+          this.configuredSupervisionUrlIndex = (this.index - 1) % supervisionUrls.length;
           break;
         case SupervisionUrlDistribution.RANDOM:
-          // Get a random url
-          urlIndex = Math.floor(Utils.secureRandom() * supervisionUrls.length);
+          this.configuredSupervisionUrlIndex = Math.floor(
+            Utils.secureRandom() * supervisionUrls.length
+          );
           break;
-        case SupervisionUrlDistribution.SEQUENTIAL:
-          if (this.index <= supervisionUrls.length) {
-            urlIndex = this.index - 1;
-          } else {
-            logger.warn(
-              `${this.logPrefix()} No more configured supervision urls available, using the first one`
-            );
-          }
+        case SupervisionUrlDistribution.CHARGING_STATION_AFFINITY:
+          this.configuredSupervisionUrlIndex = (this.index - 1) % supervisionUrls.length;
           break;
         default:
           logger.error(
             `${this.logPrefix()} Unknown supervision url distribution '${Configuration.getSupervisionUrlDistribution()}' from values '${SupervisionUrlDistribution.toString()}', defaulting to ${
-              SupervisionUrlDistribution.ROUND_ROBIN
+              SupervisionUrlDistribution.CHARGING_STATION_AFFINITY
             }`
           );
-          urlIndex = (this.index - 1) % supervisionUrls.length;
+          this.configuredSupervisionUrlIndex = (this.index - 1) % supervisionUrls.length;
           break;
       }
-      return new URL(supervisionUrls[urlIndex]);
+      return new URL(supervisionUrls[this.configuredSupervisionUrlIndex]);
     }
     return new URL(supervisionUrls as string);
   }
 
-  private getHeartbeatInterval(): number | undefined {
+  private getHeartbeatInterval(): number {
     const HeartbeatInterval = ChargingStationConfigurationUtils.getConfigurationKey(
       this,
       StandardParametersKey.HeartbeatInterval
@@ -2002,7 +1991,7 @@ export default class ChargingStation {
     }
   }
 
-  private getReconnectExponentialDelay(): boolean | undefined {
+  private getReconnectExponentialDelay(): boolean {
     return !Utils.isUndefined(this.stationInfo.reconnectExponentialDelay)
       ? this.stationInfo.reconnectExponentialDelay
       : false;