fix: fix reservation removal at transaction start
authorJérôme Benoit <jerome.benoit@sap.com>
Sun, 30 Jul 2023 19:16:20 +0000 (21:16 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Sun, 30 Jul 2023 19:16:20 +0000 (21:16 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/AutomaticTransactionGenerator.ts
src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
src/charging-station/ocpp/1.6/OCPP16ResponseService.ts
src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts

index bdeffbd25489dae3f2e7169ea4a51eef5292afc7..20c8e81a992b1f6944dfe4f2136c1502a576e162 100644 (file)
@@ -397,7 +397,6 @@ 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<
@@ -408,6 +407,14 @@ export class AutomaticTransactionGenerator extends AsyncResource {
           });
         ++this.connectorsStatus.get(connectorId)!.authorizeRequests!;
         if (authorizeResponse?.idTagInfo?.status === AuthorizationStatus.ACCEPTED) {
+          if (
+            isNullOrUndefined(this.chargingStation.getConnectorStatus(connectorId)!.authorizeIdTag)
+          ) {
+            logger.warn(
+              `${this.chargingStation.logPrefix()} IdTag ${idTag} is not set as authorized remotely, applying deferred initialization`,
+            );
+            this.chargingStation.getConnectorStatus(connectorId)!.authorizeIdTag = idTag;
+          }
           ++this.connectorsStatus.get(connectorId)!.acceptedAuthorizeRequests!;
           logger.info(startTransactionLogMsg);
           // Start transaction
index cc16622a5bc72782cb3147bb4b67b68f4f153600..f4799d8fce31db9c14408e78bedd37a6ec1acdcf 100644 (file)
@@ -84,7 +84,6 @@ import {
   type ResetRequest,
   type SetChargingProfileRequest,
   type SetChargingProfileResponse,
-  type StartTransactionRequest,
   type UnlockConnectorRequest,
   type UnlockConnectorResponse,
 } from '../../../types';
@@ -826,15 +825,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
     commandPayload: RemoteStartTransactionRequest,
   ): Promise<GenericResponse> {
     const { connectorId: transactionConnectorId, idTag, chargingProfile } = commandPayload;
-    const reserved =
-      chargingStation.getConnectorStatus(transactionConnectorId)!.status ===
-      OCPP16ChargePointStatus.Reserved;
-    const reservedOnConnectorZero =
-      chargingStation.getConnectorStatus(0)!.status === OCPP16ChargePointStatus.Reserved;
     if (
-      (reserved &&
+      (chargingStation.getConnectorStatus(transactionConnectorId)!.status ===
+        OCPP16ChargePointStatus.Reserved &&
         chargingStation.getReservationBy('connectorId', transactionConnectorId)?.idTag !== idTag) ||
-      (reservedOnConnectorZero &&
+      (chargingStation.getConnectorStatus(0)!.status === OCPP16ChargePointStatus.Reserved &&
         chargingStation.getReservationBy('connectorId', 0)?.idTag !== idTag)
     ) {
       return OCPP16Constants.OCPP_RESPONSE_REJECTED;
@@ -866,9 +861,20 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       OCPP16ChargePointStatus.Preparing,
     );
     const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId)!;
-    // Check if authorized
     if (
       chargingStation.getAuthorizeRemoteTxRequests() &&
+      !chargingStation.getLocalAuthListEnabled() &&
+      !chargingStation.getMustAuthorizeAtRemoteStart()
+    ) {
+      logger.warn(
+        `${chargingStation.logPrefix()} The charging station configuration expects authorize at remote start transaction
+          but local authorization or must authorize at remote start isn't enabled`,
+      );
+    }
+    // Authorization check required
+    if (
+      chargingStation.getAuthorizeRemoteTxRequests() === true &&
+      chargingStation.getMustAuthorizeAtRemoteStart() === true &&
       (await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, transactionConnectorId, idTag))
     ) {
       // Authorization successful, start transaction
@@ -880,27 +886,15 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         ) === true
       ) {
         connectorStatus.transactionRemoteStarted = true;
-        const startTransactionPayload: Partial<StartTransactionRequest> = {
-          connectorId: transactionConnectorId,
-          idTag,
-        };
-        if (reserved || reservedOnConnectorZero) {
-          const reservation = chargingStation.getReservationBy(
-            'connectorId',
-            reservedOnConnectorZero ? 0 : transactionConnectorId,
-          )!;
-          startTransactionPayload.reservationId = reservation.reservationId;
-          await chargingStation.removeReservation(
-            reservation,
-            ReservationTerminationReason.TRANSACTION_STARTED,
-          );
-        }
         if (
           (
             await chargingStation.ocppRequestService.requestHandler<
               OCPP16StartTransactionRequest,
               OCPP16StartTransactionResponse
-            >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, startTransactionPayload)
+            >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, {
+              connectorId: transactionConnectorId,
+              idTag,
+            })
           ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED
         ) {
           logger.debug(remoteStartTransactionLogMsg);
@@ -1547,7 +1541,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
     const { reservationId, idTag, connectorId } = commandPayload;
     let response: OCPP16ReserveNowResponse;
     try {
-      if (!chargingStation.isConnectorAvailable(connectorId) && connectorId > 0) {
+      if (connectorId > 0 && !chargingStation.isConnectorAvailable(connectorId)) {
         return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED;
       }
       if (connectorId === 0 && !chargingStation.getReserveConnectorZeroSupported()) {
index 3816c54fd2f35a201508dc72172fda679e60ed25..7cafe937dc7623e48e6ddfa27907722fb2ab5dc7 100644 (file)
@@ -48,6 +48,7 @@ import {
   type OCPP16UpdateFirmwareResponse,
   OCPPVersion,
   RegistrationStatusEnumType,
+  ReservationTerminationReason,
   type ResponseHandler,
   type SetChargingProfileResponse,
   type UnlockConnectorResponse,
@@ -470,8 +471,11 @@ export class OCPP16ResponseService extends OCPPResponseService {
     }
     const authorizeConnectorIdDefined = !isNullOrUndefined(authorizeConnectorId);
     if (payload.idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED) {
-      authorizeConnectorIdDefined &&
-        (chargingStation.getConnectorStatus(authorizeConnectorId!)!.idTagAuthorized = true);
+      if (authorizeConnectorIdDefined) {
+        chargingStation.getConnectorStatus(authorizeConnectorId!)!.idTagAuthorized = true;
+        chargingStation.getConnectorStatus(authorizeConnectorId!)!.authorizeIdTag =
+          requestPayload.idTag;
+      }
       logger.debug(
         `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' accepted${
           authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}` : ''
@@ -510,7 +514,7 @@ export class OCPP16ResponseService extends OCPPResponseService {
         true &&
       chargingStation.getAuthorizeRemoteTxRequests() === true &&
       chargingStation.getLocalAuthListEnabled() === true &&
-      chargingStation.hasIdTags() &&
+      chargingStation.hasIdTags() === true &&
       chargingStation.getConnectorStatus(transactionConnectorId)?.idTagLocalAuthorized === false
     ) {
       logger.error(
@@ -635,6 +639,23 @@ export class OCPP16ResponseService extends OCPPResponseService {
           transactionConnectorId,
           requestPayload.meterStart,
         );
+      const reservedOnConnectorZero =
+        chargingStation.getConnectorStatus(0)!.status === OCPP16ChargePointStatus.Reserved;
+      if (
+        chargingStation.getConnectorStatus(transactionConnectorId)!.status ===
+          OCPP16ChargePointStatus.Reserved ||
+        reservedOnConnectorZero
+      ) {
+        const reservation = chargingStation.getReservationBy(
+          'connectorId',
+          reservedOnConnectorZero ? 0 : transactionConnectorId,
+        )!;
+        payload.reservationId = reservation.reservationId;
+        await chargingStation.removeReservation(
+          reservation,
+          ReservationTerminationReason.TRANSACTION_STARTED,
+        );
+      }
       chargingStation.getBeginEndMeterValues() &&
         (await chargingStation.ocppRequestService.requestHandler<
           OCPP16MeterValuesRequest,
index 7f065d30bed7dd29c684edaa358c82c0866cbe9e..bf019cee3c6fffc6756f0f8d0a97b664dc676387 100644 (file)
@@ -897,14 +897,14 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       connectorStatus.localAuthorizeIdTag = idTag;
       connectorStatus.idTagLocalAuthorized = true;
       authorized = true;
-    } else if (chargingStation.getMustAuthorizeAtRemoteStart() === true) {
-      connectorStatus.authorizeIdTag = idTag;
-      authorized = await OCPP16ServiceUtils.isIdTagRemoteAuthorized(chargingStation, idTag);
     } else {
-      logger.warn(
-        `${chargingStation.logPrefix()} The charging station configuration expects authorize at
-          remote start transaction but local authorization or authorize isn't enabled`,
-      );
+      authorized = await OCPP16ServiceUtils.isIdTagRemoteAuthorized(chargingStation, idTag);
+      if (authorized && isNullOrUndefined(connectorStatus.authorizeIdTag)) {
+        logger.warn(
+          `${chargingStation.logPrefix()} IdTag ${idTag} is not set as authorized remotely, applying deferred initialization`,
+        );
+        connectorStatus.authorizeIdTag = idTag;
+      }
     }
     return authorized;
   }
@@ -1006,7 +1006,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
         OCPP16AuthorizeRequest,
         OCPP16AuthorizeResponse
       >(chargingStation, OCPP16RequestCommand.AUTHORIZE, {
-        idTag: idTag,
+        idTag,
       });
     return authorizeResponse?.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED;
   }