fix: check for the connector status definition in ATG
[e-mobility-charging-stations-simulator.git] / src / charging-station / AutomaticTransactionGenerator.ts
index 578f47e942d89e38c0700c3fec919b80bc750948..dfab482ab2d63af90f06a7011e2e2bbf7ab5c205 100644 (file)
@@ -2,15 +2,16 @@
 
 import { AsyncResource } from 'node:async_hooks';
 
+import { hoursToMilliseconds, secondsToMilliseconds } from 'date-fns';
+
 import type { ChargingStation } from './ChargingStation';
-import { checkChargingStation } from './ChargingStationUtils';
+import { checkChargingStation } from './Helpers';
 import { IdTagsCache } from './IdTagsCache';
+import { OCPPServiceUtils } from './ocpp';
 import { BaseError } from '../exception';
 import { PerformanceStatistics } from '../performance';
 import {
   AuthorizationStatus,
-  type AuthorizeRequest,
-  type AuthorizeResponse,
   ConnectorStatusEnum,
   RequestCommand,
   type StartTransactionRequest,
@@ -188,46 +189,7 @@ export class AutomaticTransactionGenerator extends AsyncResource {
       )}`,
     );
     while (this.connectorsStatus.get(connectorId)?.start === true) {
-      if (new Date() > this.connectorsStatus.get(connectorId)!.stopDate!) {
-        this.stopConnector(connectorId);
-        break;
-      }
-      if (this.chargingStation.inAcceptedState() === false) {
-        logger.error(
-          `${this.logPrefix(
-            connectorId,
-          )} entered in transaction loop while the charging station is not in accepted state`,
-        );
-        this.stopConnector(connectorId);
-        break;
-      }
-      if (this.chargingStation.isChargingStationAvailable() === false) {
-        logger.info(
-          `${this.logPrefix(
-            connectorId,
-          )} entered in transaction loop while the charging station is unavailable`,
-        );
-        this.stopConnector(connectorId);
-        break;
-      }
-      if (this.chargingStation.isConnectorAvailable(connectorId) === false) {
-        logger.info(
-          `${this.logPrefix(
-            connectorId,
-          )} entered in transaction loop while the connector ${connectorId} is unavailable`,
-        );
-        this.stopConnector(connectorId);
-        break;
-      }
-      if (
-        this.chargingStation.getConnectorStatus(connectorId)?.status ===
-        ConnectorStatusEnum.Unavailable
-      ) {
-        logger.info(
-          `${this.logPrefix(
-            connectorId,
-          )} entered in transaction loop while the connector ${connectorId} status is unavailable`,
-        );
+      if (!this.canStartConnector(connectorId)) {
         this.stopConnector(connectorId);
         break;
       }
@@ -241,13 +203,14 @@ export class AutomaticTransactionGenerator extends AsyncResource {
           await sleep(Constants.CHARGING_STATION_ATG_INITIALIZATION_TIME);
         } while (!this.chargingStation?.ocppRequestService);
       }
-      const wait =
+      const wait = secondsToMilliseconds(
         getRandomInteger(
           this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
             .maxDelayBetweenTwoTransactions,
           this.chargingStation.getAutomaticTransactionGeneratorConfiguration()
             .minDelayBetweenTwoTransactions,
-        ) * 1000;
+        ),
+      );
       logger.info(`${this.logPrefix(connectorId)} waiting for ${formatDurationMilliSeconds(wait)}`);
       await sleep(wait);
       const start = secureRandom();
@@ -260,11 +223,12 @@ export class AutomaticTransactionGenerator extends AsyncResource {
         const startResponse = await this.startTransaction(connectorId);
         if (startResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
           // Wait until end of transaction
-          const waitTrxEnd =
+          const waitTrxEnd = secondsToMilliseconds(
             getRandomInteger(
               this.chargingStation.getAutomaticTransactionGeneratorConfiguration().maxDuration,
               this.chargingStation.getAutomaticTransactionGeneratorConfiguration().minDuration,
-            ) * 1000;
+            ),
+          );
           logger.info(
             `${this.logPrefix(connectorId)} transaction started with id ${this.chargingStation
               .getConnectorStatus(connectorId)
@@ -320,14 +284,56 @@ export class AutomaticTransactionGenerator extends AsyncResource {
     this.connectorsStatus.get(connectorId)!.startDate = new Date();
     this.connectorsStatus.get(connectorId)!.stopDate = new Date(
       this.connectorsStatus.get(connectorId)!.startDate!.getTime() +
-        this.chargingStation.getAutomaticTransactionGeneratorConfiguration().stopAfterHours *
-          3600 *
-          1000 -
+        hoursToMilliseconds(
+          this.chargingStation.getAutomaticTransactionGeneratorConfiguration().stopAfterHours,
+        ) -
         previousRunDuration,
     );
     this.connectorsStatus.get(connectorId)!.start = true;
   }
 
+  private canStartConnector(connectorId: number): boolean {
+    if (new Date() > this.connectorsStatus.get(connectorId)!.stopDate!) {
+      return false;
+    }
+    if (this.chargingStation.inAcceptedState() === false) {
+      logger.error(
+        `${this.logPrefix(
+          connectorId,
+        )} entered in transaction loop while the charging station is not in accepted state`,
+      );
+      return false;
+    }
+    if (this.chargingStation.isChargingStationAvailable() === false) {
+      logger.info(
+        `${this.logPrefix(
+          connectorId,
+        )} entered in transaction loop while the charging station is unavailable`,
+      );
+      return false;
+    }
+    if (this.chargingStation.isConnectorAvailable(connectorId) === false) {
+      logger.info(
+        `${this.logPrefix(
+          connectorId,
+        )} entered in transaction loop while the connector ${connectorId} is unavailable`,
+      );
+      return false;
+    }
+    if (
+      this.chargingStation.getConnectorStatus(connectorId)?.status ===
+      ConnectorStatusEnum.Unavailable
+    ) {
+      logger.info(
+        `${this.logPrefix(
+          connectorId,
+        )} entered in transaction loop while the connector ${connectorId} status is unavailable`,
+      );
+      return false;
+    }
+    return true;
+  }
+
   private initializeConnectorsStatus(): void {
     if (this.chargingStation.hasEvses) {
       for (const [evseId, evseStatus] of this.chargingStation.evses) {
@@ -347,8 +353,12 @@ export class AutomaticTransactionGenerator extends AsyncResource {
   }
 
   private getConnectorStatus(connectorId: number): Status {
-    const connectorStatus = this.chargingStation.getAutomaticTransactionGeneratorStatuses()
-      ? cloneObject(this.chargingStation.getAutomaticTransactionGeneratorStatuses()!)[connectorId]
+    const connectorStatus = this.chargingStation.getAutomaticTransactionGeneratorStatuses()?.[
+      connectorId
+    ]
+      ? cloneObject<Status[]>(this.chargingStation.getAutomaticTransactionGeneratorStatuses()!)[
+          connectorId
+        ]
       : undefined;
     delete connectorStatus?.startDate;
     delete connectorStatus?.lastRunDate;
@@ -388,17 +398,8 @@ export class AutomaticTransactionGenerator extends AsyncResource {
         connectorId,
       )} start transaction with an idTag '${idTag}'`;
       if (this.getRequireAuthorize()) {
-        this.chargingStation.getConnectorStatus(connectorId)!.authorizeIdTag = idTag;
-        // Authorize idTag
-        const authorizeResponse: AuthorizeResponse =
-          await this.chargingStation.ocppRequestService.requestHandler<
-            AuthorizeRequest,
-            AuthorizeResponse
-          >(this.chargingStation, RequestCommand.AUTHORIZE, {
-            idTag,
-          });
         ++this.connectorsStatus.get(connectorId)!.authorizeRequests!;
-        if (authorizeResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
+        if (await OCPPServiceUtils.isIdTagAuthorized(this.chargingStation, connectorId, idTag)) {
           ++this.connectorsStatus.get(connectorId)!.acceptedAuthorizeRequests!;
           logger.info(startTransactionLogMsg);
           // Start transaction