From: Jérôme Benoit Date: Mon, 16 Mar 2026 16:54:02 +0000 (+0100) Subject: refactor(ocpp): harmonize post-response event listener pattern across stacks X-Git-Tag: ocpp-server@v3.1.1~12 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=52d9baccce9c35eac81c91fd98a090a5a07ec10a;p=e-mobility-charging-stations-simulator.git refactor(ocpp): harmonize post-response event listener pattern across stacks 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. --- diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 54b8c95d..0973ed7f 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -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 } diff --git a/src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.ts b/src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.ts index e6ce847f..ab9c5b72 100644 --- a/src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.ts +++ b/src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.ts @@ -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 { 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, } }