UI HTTP server: fix stop simulator response handling
authorJérôme Benoit <jerome.benoit@sap.com>
Sat, 3 Sep 2022 21:10:48 +0000 (23:10 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Sat, 3 Sep 2022 21:10:48 +0000 (23:10 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/AutomaticTransactionGenerator.ts
src/charging-station/ChargingStation.ts
src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
src/charging-station/ocpp/OCPPIncomingRequestService.ts
src/charging-station/ocpp/OCPPRequestService.ts
src/charging-station/ui-server/UIHttpServer.ts

index eb7876e2b34d16a8efa91bccc72be25dfade3fef..83bedaab3f52c6073d28195ad80a6df8bee54fbe 100644 (file)
@@ -226,7 +226,6 @@ export default class AutomaticTransactionGenerator {
       }
       this.connectorsStatus.get(connectorId).lastRunDate = new Date();
     }
-    // await this.stopTransaction(connectorId);
     this.connectorsStatus.get(connectorId).stoppedDate = new Date();
     logger.info(
       this.logPrefix(connectorId) +
index 7d633eb07b97940002922cbefae236dad8e3e39a..3b83dfe40578f637e2bc77a70f736f585a25d17e 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
@@ -1468,7 +1400,6 @@ export default class ChargingStation {
           )}' and reason '${reason}'`
         );
         this.autoReconnectRetryCount = 0;
-        await this.stopMessageSequence(StopTransactionReason.OTHER);
         break;
       // Abnormal close
       default:
@@ -1663,6 +1594,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 +1697,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 +1834,7 @@ export default class ChargingStation {
       }
     }
     // Start the ATG
-    if (this.getAutomaticTransactionGeneratorConfigurationFromTemplate()?.enable) {
+    if (this.getAutomaticTransactionGeneratorConfigurationFromTemplate()?.enable === true) {
       this.startAutomaticTransactionGenerator();
     }
   }
@@ -1847,12 +1847,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) {
+      this.stopAutomaticTransactionGenerator();
+    } else {
+      await this.stopRunningTransactions(reason);
     }
   }
 
@@ -2031,7 +2029,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
index e80d0d3d3c1c4eb4c81de02b8703a6ebb53470a4..6c11ad57c4a8e11d8cb581e5feb0745bed231bdf 100644 (file)
@@ -380,12 +380,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer
   ): DefaultResponse {
     // eslint-disable-next-line @typescript-eslint/no-misused-promises
     setImmediate(async (): Promise<void> => {
-      if (chargingStation.getNumberOfRunningTransactions() > 0) {
-        await chargingStation.stopRunningTransactions(
-          (commandPayload.type + 'Reset') as OCPP16StopTransactionReason
-        );
-      }
-      await chargingStation.reset();
+      await chargingStation.reset((commandPayload.type + 'Reset') as OCPP16StopTransactionReason);
     });
     logger.info(
       `${chargingStation.logPrefix()} ${
index 2ee0465cb583476288289fdd9523d637b2fbde27..013cb62ad8235c002cf3e4d97fd65d3af5643412 100644 (file)
@@ -37,7 +37,7 @@ export default abstract class OCPPIncomingRequestService {
     params: HandleErrorParams<T> = { throwError: true }
   ): T {
     logger.error(
-      `${chargingStation.logPrefix()} ${moduleName}.handleIncomingRequestError: Incoming request command ${commandName} error:`,
+      `${chargingStation.logPrefix()} ${moduleName}.handleIncomingRequestError: Incoming request command '${commandName}' error:`,
       error
     );
     if (!params?.throwError && params?.errorResponse) {
index 25c8943564a7f91afc639c22a7f99a0a28d247d9..6993e1ecabdbefbdd8ebe244063e4aa594ee430f 100644 (file)
@@ -361,7 +361,7 @@ export default abstract class OCPPRequestService {
     error: Error,
     params: HandleErrorParams<EmptyObject> = { throwError: true }
   ): void {
-    logger.error(`${chargingStation.logPrefix()} Request command ${commandName} error:`, error);
+    logger.error(`${chargingStation.logPrefix()} Request command '${commandName}' error:`, error);
     if (params?.throwError) {
       throw error;
     }
index 2747738a65d1aadff3b59d654d51570bb0b8a1c1..a6a6313e02182b6dbd0e1e4c5aaaf417f9ee9728 100644 (file)
@@ -41,7 +41,6 @@ export default class UIHttpServer extends AbstractUIServer {
 
   public stop(): void {
     this.chargingStations.clear();
-    this.responseHandlers.clear();
   }
 
   // eslint-disable-next-line @typescript-eslint/no-unused-vars