UI Protocol: add Authorize command support
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStation.ts
index 7d633eb07b97940002922cbefae236dad8e3e39a..d7b67e6a04b73aa960abc5767dec9338ea0038ee 100644 (file)
@@ -498,7 +498,7 @@ export default class ChargingStation {
             this.initialize();
             // Restart the ATG
             this.stopAutomaticTransactionGenerator();
-            if (this.getAutomaticTransactionGeneratorConfigurationFromTemplate()?.enable) {
+            if (this.getAutomaticTransactionGeneratorConfigurationFromTemplate()?.enable === true) {
               this.startAutomaticTransactionGenerator();
             }
             if (this.getEnableStatistics()) {
@@ -519,7 +519,8 @@ export default class ChargingStation {
     parentPort.postMessage(MessageChannelUtils.buildStartedMessage(this));
   }
 
-  public async stop(): Promise<void> {
+  public async stop(reason?: StopTransactionReason): Promise<void> {
+    await this.stopMessageSequence(reason);
     for (const connectorId of this.connectors.keys()) {
       if (connectorId > 0) {
         await this.ocppRequestService.requestHandler<
@@ -545,8 +546,8 @@ export default class ChargingStation {
     parentPort.postMessage(MessageChannelUtils.buildStoppedMessage(this));
   }
 
-  public async reset(): Promise<void> {
-    await this.stop();
+  public async reset(reason?: StopTransactionReason): Promise<void> {
+    await this.stop(reason);
     await Utils.sleep(this.stationInfo.resetTime);
     this.initialize();
     this.start();
@@ -558,57 +559,6 @@ export default class ChargingStation {
     }
   }
 
-  public getChargingProfilePowerLimit(connectorId: number): number | undefined {
-    let limit: number, matchingChargingProfile: ChargingProfile;
-    let chargingProfiles: ChargingProfile[] = [];
-    // Get charging profiles for connector and sort by stack level
-    chargingProfiles = this.getConnectorStatus(connectorId).chargingProfiles.sort(
-      (a, b) => b.stackLevel - a.stackLevel
-    );
-    // Get profiles on connector 0
-    if (this.getConnectorStatus(0).chargingProfiles) {
-      chargingProfiles.push(
-        ...this.getConnectorStatus(0).chargingProfiles.sort((a, b) => b.stackLevel - a.stackLevel)
-      );
-    }
-    if (!Utils.isEmptyArray(chargingProfiles)) {
-      const result = ChargingStationUtils.getLimitFromChargingProfiles(
-        chargingProfiles,
-        this.logPrefix()
-      );
-      if (!Utils.isNullOrUndefined(result)) {
-        limit = result.limit;
-        matchingChargingProfile = result.matchingChargingProfile;
-        switch (this.getCurrentOutType()) {
-          case CurrentType.AC:
-            limit =
-              matchingChargingProfile.chargingSchedule.chargingRateUnit ===
-              ChargingRateUnitType.WATT
-                ? limit
-                : ACElectricUtils.powerTotal(this.getNumberOfPhases(), this.getVoltageOut(), limit);
-            break;
-          case CurrentType.DC:
-            limit =
-              matchingChargingProfile.chargingSchedule.chargingRateUnit ===
-              ChargingRateUnitType.WATT
-                ? limit
-                : DCElectricUtils.power(this.getVoltageOut(), limit);
-        }
-        const connectorMaximumPower = this.getMaximumPower() / this.powerDivider;
-        if (limit > connectorMaximumPower) {
-          logger.error(
-            `${this.logPrefix()} Charging profile id ${
-              matchingChargingProfile.chargingProfileId
-            } limit is greater than connector id ${connectorId} maximum, dump charging profiles' stack: %j`,
-            this.getConnectorStatus(connectorId).chargingProfiles
-          );
-          limit = connectorMaximumPower;
-        }
-      }
-    }
-    return limit;
-  }
-
   public setChargingProfile(connectorId: number, cp: ChargingProfile): void {
     if (Utils.isNullOrUndefined(this.getConnectorStatus(connectorId).chargingProfiles)) {
       logger.error(
@@ -768,24 +718,6 @@ export default class ChargingStation {
     }
   }
 
-  public getNumberOfRunningTransactions(): number {
-    let trxCount = 0;
-    for (const connectorId of this.connectors.keys()) {
-      if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
-        trxCount++;
-      }
-    }
-    return trxCount;
-  }
-
-  public async stopRunningTransactions(reason = StopTransactionReason.NONE): Promise<void> {
-    for (const connectorId of this.connectors.keys()) {
-      if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
-        await this.stopTransactionOnConnector(connectorId, reason);
-      }
-    }
-  }
-
   public async stopTransactionOnConnector(
     connectorId: number,
     reason = StopTransactionReason.NONE
@@ -818,7 +750,6 @@ export default class ChargingStation {
       {
         transactionId,
         meterStop: this.getEnergyActiveImportRegisterByTransactionId(transactionId, true),
-        idTag: this.getTransactionIdTag(transactionId),
         reason,
       }
     );
@@ -1287,7 +1218,11 @@ export default class ChargingStation {
     }
     // Initialize transaction attributes on connectors
     for (const connectorId of this.connectors.keys()) {
-      if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === false) {
+      if (
+        connectorId > 0 &&
+        (this.getConnectorStatus(connectorId).transactionStarted === undefined ||
+          this.getConnectorStatus(connectorId).transactionStarted === false)
+      ) {
         this.initializeConnectorStatus(connectorId);
       }
     }
@@ -1468,7 +1403,6 @@ export default class ChargingStation {
           )}' and reason '${reason}'`
         );
         this.autoReconnectRetryCount = 0;
-        await this.stopMessageSequence(StopTransactionReason.OTHER);
         break;
       // Abnormal close
       default:
@@ -1663,6 +1597,24 @@ export default class ChargingStation {
       : true;
   }
 
+  private getNumberOfRunningTransactions(): number {
+    let trxCount = 0;
+    for (const connectorId of this.connectors.keys()) {
+      if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
+        trxCount++;
+      }
+    }
+    return trxCount;
+  }
+
+  private async stopRunningTransactions(reason = StopTransactionReason.NONE): Promise<void> {
+    for (const connectorId of this.connectors.keys()) {
+      if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
+        await this.stopTransactionOnConnector(connectorId, reason);
+      }
+    }
+  }
+
   // 0 for disabling
   private getConnectionTimeout(): number | undefined {
     if (
@@ -1748,6 +1700,57 @@ export default class ChargingStation {
     }
   }
 
+  private getChargingProfilePowerLimit(connectorId: number): number | undefined {
+    let limit: number, matchingChargingProfile: ChargingProfile;
+    let chargingProfiles: ChargingProfile[] = [];
+    // Get charging profiles for connector and sort by stack level
+    chargingProfiles = this.getConnectorStatus(connectorId).chargingProfiles.sort(
+      (a, b) => b.stackLevel - a.stackLevel
+    );
+    // Get profiles on connector 0
+    if (this.getConnectorStatus(0).chargingProfiles) {
+      chargingProfiles.push(
+        ...this.getConnectorStatus(0).chargingProfiles.sort((a, b) => b.stackLevel - a.stackLevel)
+      );
+    }
+    if (!Utils.isEmptyArray(chargingProfiles)) {
+      const result = ChargingStationUtils.getLimitFromChargingProfiles(
+        chargingProfiles,
+        this.logPrefix()
+      );
+      if (!Utils.isNullOrUndefined(result)) {
+        limit = result.limit;
+        matchingChargingProfile = result.matchingChargingProfile;
+        switch (this.getCurrentOutType()) {
+          case CurrentType.AC:
+            limit =
+              matchingChargingProfile.chargingSchedule.chargingRateUnit ===
+              ChargingRateUnitType.WATT
+                ? limit
+                : ACElectricUtils.powerTotal(this.getNumberOfPhases(), this.getVoltageOut(), limit);
+            break;
+          case CurrentType.DC:
+            limit =
+              matchingChargingProfile.chargingSchedule.chargingRateUnit ===
+              ChargingRateUnitType.WATT
+                ? limit
+                : DCElectricUtils.power(this.getVoltageOut(), limit);
+        }
+        const connectorMaximumPower = this.getMaximumPower() / this.powerDivider;
+        if (limit > connectorMaximumPower) {
+          logger.error(
+            `${this.logPrefix()} Charging profile id ${
+              matchingChargingProfile.chargingProfileId
+            } limit is greater than connector id ${connectorId} maximum, dump charging profiles' stack: %j`,
+            this.getConnectorStatus(connectorId).chargingProfiles
+          );
+          limit = connectorMaximumPower;
+        }
+      }
+    }
+    return limit;
+  }
+
   private async startMessageSequence(): Promise<void> {
     if (this.stationInfo?.autoRegister) {
       await this.ocppRequestService.requestHandler<
@@ -1834,7 +1837,7 @@ export default class ChargingStation {
       }
     }
     // Start the ATG
-    if (this.getAutomaticTransactionGeneratorConfigurationFromTemplate()?.enable) {
+    if (this.getAutomaticTransactionGeneratorConfigurationFromTemplate()?.enable === true) {
       this.startAutomaticTransactionGenerator();
     }
   }
@@ -1847,12 +1850,10 @@ export default class ChargingStation {
     // Stop heartbeat
     this.stopHeartbeat();
     // Stop ongoing transactions
-    if (this.getNumberOfRunningTransactions() > 0) {
-      if (this.automaticTransactionGenerator?.started) {
-        this.stopAutomaticTransactionGenerator();
-      } else {
-        await this.stopRunningTransactions(reason);
-      }
+    if (this.automaticTransactionGenerator?.started === true) {
+      this.stopAutomaticTransactionGenerator();
+    } else {
+      await this.stopRunningTransactions(reason);
     }
   }
 
@@ -2031,7 +2032,6 @@ export default class ChargingStation {
       );
       this.wsConnectionRestarted = true;
     } else if (this.getAutoReconnectMaxRetries() !== -1) {
-      await this.stopMessageSequence(StopTransactionReason.OTHER);
       logger.error(
         `${this.logPrefix()} WebSocket reconnect failure: maximum retries reached (${
           this.autoReconnectRetryCount