]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor(ocpp): harmonize post-response event listener pattern across stacks
authorJérôme Benoit <jerome.benoit@sap.com>
Mon, 16 Mar 2026 16:54:02 +0000 (17:54 +0100)
committerJérôme Benoit <jerome.benoit@sap.com>
Mon, 16 Mar 2026 16:54:02 +0000 (17:54 +0100)
Move post-response logic from inline handler to event listeners:
- OCPP16 UpdateFirmware: fire-and-forget in handler → event listener
  matching OCPP20 UpdateFirmware pattern
- OCPP20 RequestStopTransaction: await in handler → event listener
  matching OCPP16 RemoteStopTransaction pattern

All commands with post-response behavior now use the same pattern:
handler validates and returns response, event listener performs
the async action after the response is sent to the CSMS.

src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.ts

index 54b8c95ded13dc340a63a47013c7dfcdeb6660aa..0973ed7f92fef3e6613ce9f19146d0bad3bdeca7 100644 (file)
@@ -542,6 +542,35 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
         }
       }
     )
+    this.on(
+      OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
+      (
+        chargingStation: ChargingStation,
+        request: OCPP16UpdateFirmwareRequest,
+        _response: OCPP16UpdateFirmwareResponse
+      ) => {
+        const retrieveDate = convertToDate(request.retrieveDate)
+        if (retrieveDate == null) return
+        const now = Date.now()
+        if (retrieveDate.getTime() <= now) {
+          this.updateFirmwareSimulation(chargingStation).catch((error: unknown) => {
+            logger.error(
+              `${chargingStation.logPrefix()} ${moduleName}.constructor: UpdateFirmware simulation error:`,
+              error
+            )
+          })
+        } else {
+          setTimeout(() => {
+            this.updateFirmwareSimulation(chargingStation).catch((error: unknown) => {
+              logger.error(
+                `${chargingStation.logPrefix()} ${moduleName}.constructor: UpdateFirmware simulation error:`,
+                error
+              )
+            })
+          }, retrieveDate.getTime() - now)
+        }
+      }
+    )
   }
 
   public override stop (chargingStation: ChargingStation): void {
@@ -1565,7 +1594,6 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
     }
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
     commandPayload.retrieveDate = convertToDate(commandPayload.retrieveDate)!
-    const { retrieveDate } = commandPayload
     if (
       chargingStation.stationInfo?.firmwareStatus === OCPP16FirmwareStatus.Downloading ||
       chargingStation.stationInfo?.firmwareStatus === OCPP16FirmwareStatus.Downloaded ||
@@ -1576,24 +1604,6 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService {
       )
       return OCPP16Constants.OCPP_RESPONSE_EMPTY
     }
-    const now = Date.now()
-    if (retrieveDate.getTime() <= now) {
-      this.updateFirmwareSimulation(chargingStation).catch((error: unknown) => {
-        logger.error(
-          `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Firmware update simulation error:`,
-          error
-        )
-      })
-    } else {
-      setTimeout(() => {
-        this.updateFirmwareSimulation(chargingStation).catch((error: unknown) => {
-          logger.error(
-            `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Firmware update simulation error:`,
-            error
-          )
-        })
-      }, retrieveDate.getTime() - now)
-    }
     return OCPP16Constants.OCPP_RESPONSE_EMPTY
   }
 
index e6ce847ffce6d1ea7c38e9686654bc1e1af23e6f..ab9c5b72f437c32750d47e5f79c1201359217779 100644 (file)
@@ -370,6 +370,29 @@ export class OCPP20IncomingRequestService extends OCPPIncomingRequestService {
         }
       }
     )
+    this.on(
+      OCPP20IncomingRequestCommand.REQUEST_STOP_TRANSACTION,
+      (
+        chargingStation: ChargingStation,
+        request: OCPP20RequestStopTransactionRequest,
+        response: OCPP20RequestStopTransactionResponse
+      ) => {
+        if (response.status === RequestStartStopStatusEnumType.Accepted) {
+          const connectorId = chargingStation.getConnectorIdByTransactionId(request.transactionId)
+          const evseId = chargingStation.getEvseIdByTransactionId(request.transactionId)
+          if (connectorId != null && evseId != null) {
+            OCPP20ServiceUtils.requestStopTransaction(chargingStation, connectorId, evseId).catch(
+              (error: unknown) => {
+                logger.error(
+                  `${chargingStation.logPrefix()} ${moduleName}.constructor: RequestStopTransaction error:`,
+                  error
+                )
+              }
+            )
+          }
+        }
+      }
+    )
     this.on(
       OCPP20IncomingRequestCommand.TRIGGER_MESSAGE,
       (
@@ -2524,10 +2547,10 @@ export class OCPP20IncomingRequestService extends OCPPIncomingRequestService {
     }
   }
 
-  private async handleRequestStopTransaction (
+  private handleRequestStopTransaction (
     chargingStation: ChargingStation,
     commandPayload: OCPP20RequestStopTransactionRequest
-  ): Promise<OCPP20RequestStopTransactionResponse> {
+  ): OCPP20RequestStopTransactionResponse {
     const { transactionId } = commandPayload
     logger.info(
       `${chargingStation.logPrefix()} ${moduleName}.handleRequestStopTransaction: Remote stop transaction request received for transaction ID ${transactionId as string}`
@@ -2574,44 +2597,11 @@ export class OCPP20IncomingRequestService extends OCPPIncomingRequestService {
       }
     }
 
-    try {
-      const stopResponse = await OCPP20ServiceUtils.requestStopTransaction(
-        chargingStation,
-        connectorId,
-        evseId
-      )
-
-      if (stopResponse.status === GenericStatus.Accepted) {
-        logger.info(
-          `${chargingStation.logPrefix()} ${moduleName}.handleRequestStopTransaction: Remote stop transaction ACCEPTED for transactionId '${transactionId as string}'`
-        )
-        return {
-          status: RequestStartStopStatusEnumType.Accepted,
-        }
-      }
-
-      logger.warn(
-        `${chargingStation.logPrefix()} ${moduleName}.handleRequestStopTransaction: Remote stop transaction REJECTED for transactionId '${transactionId as string}'`
-      )
-      return {
-        status: RequestStartStopStatusEnumType.Rejected,
-        statusInfo: {
-          additionalInfo: 'Remote stop transaction rejected',
-          reasonCode: ReasonCodeEnumType.Unspecified,
-        },
-      }
-    } catch (error) {
-      logger.error(
-        `${chargingStation.logPrefix()} ${moduleName}.handleRequestStopTransaction: Error occurred during remote stop transaction for transaction ID ${transactionId as string} on connector ${connectorId.toString()}:`,
-        error
-      )
-      return {
-        status: RequestStartStopStatusEnumType.Rejected,
-        statusInfo: {
-          additionalInfo: 'Error occurred during remote stop transaction',
-          reasonCode: ReasonCodeEnumType.InternalError,
-        },
-      }
+    logger.info(
+      `${chargingStation.logPrefix()} ${moduleName}.handleRequestStopTransaction: Remote stop transaction ACCEPTED for transactionId '${transactionId as string}'`
+    )
+    return {
+      status: RequestStartStopStatusEnumType.Accepted,
     }
   }