X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2Focpp%2F1.6%2FOCPP16IncomingRequestService.ts;h=c8bc557c2a6a70ab9f3771e5412d071991113a91;hb=bcf95df12dfe4236db8c278eabea9f5058f40933;hp=69e700a32803a6ec0eb7df41421f4b8fc6f6f881;hpb=a19b897d3aa5cb0f12177a42d8168121ce6ada97;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 69e700a3..c8bc557c 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -4,7 +4,7 @@ import { createWriteStream, readdirSync } from 'node:fs' import { dirname, join, resolve } from 'node:path' import { URL, fileURLToPath } from 'node:url' -import type { JSONSchemaType } from 'ajv' +import type { ValidateFunction } from 'ajv' import { Client, type FTPResponse } from 'basic-ftp' import { type Interval, @@ -83,6 +83,7 @@ import { OCPP16SupportedFeatureProfiles, type OCPP16TriggerMessageRequest, type OCPP16TriggerMessageResponse, + OCPP16TriggerMessageStatus, type OCPP16UpdateFirmwareRequest, type OCPP16UpdateFirmwareResponse, type OCPPConfigurationKey, @@ -102,6 +103,7 @@ import { convertToInt, formatDurationMilliSeconds, getRandomInteger, + isAsyncFunction, isEmptyArray, isNotEmptyArray, isNotEmptyString, @@ -113,7 +115,8 @@ import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js' const moduleName = 'OCPP16IncomingRequestService' export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { - protected jsonSchemas: Map> + protected payloadValidateFunctions: Map> + private readonly incomingRequestHandlers: Map< OCPP16IncomingRequestCommand, IncomingRequestHandler @@ -194,149 +197,395 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { this.handleRequestCancelReservation.bind(this) as unknown as IncomingRequestHandler ] ]) - this.jsonSchemas = new Map>([ + this.payloadValidateFunctions = new Map< + OCPP16IncomingRequestCommand, + ValidateFunction + >([ [ OCPP16IncomingRequestCommand.RESET, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/Reset.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/Reset.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.CLEAR_CACHE, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/ClearCache.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/ClearCache.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/UnlockConnector.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/UnlockConnector.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.GET_CONFIGURATION, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/GetConfiguration.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/GetConfiguration.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/ChangeConfiguration.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/ChangeConfiguration.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.GET_DIAGNOSTICS, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/GetDiagnostics.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/GetDiagnostics.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/GetCompositeSchedule.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/GetCompositeSchedule.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/SetChargingProfile.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/SetChargingProfile.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/ClearChargingProfile.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/ClearChargingProfile.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/ChangeAvailability.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/ChangeAvailability.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/RemoteStartTransaction.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/RemoteStopTransaction.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/TriggerMessage.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/TriggerMessage.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.DATA_TRANSFER, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/DataTransfer.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/DataTransfer.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.UPDATE_FIRMWARE, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/UpdateFirmware.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/UpdateFirmware.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.RESERVE_NOW, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/ReserveNow.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/ReserveNow.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ], [ OCPP16IncomingRequestCommand.CANCEL_RESERVATION, - OCPP16ServiceUtils.parseJsonSchemaFile( - 'assets/json-schemas/ocpp/1.6/CancelReservation.json', - moduleName, - 'constructor' - ) + this.ajv + .compile( + OCPP16ServiceUtils.parseJsonSchemaFile( + 'assets/json-schemas/ocpp/1.6/CancelReservation.json', + moduleName, + 'constructor' + ) + ) + .bind(this) ] ]) - this.validatePayload = this.validatePayload.bind(this) as ( - chargingStation: ChargingStation, - commandName: OCPP16IncomingRequestCommand, - commandPayload: JsonType - ) => boolean + // Handle incoming request events + this.on( + OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION, + ( + chargingStation: ChargingStation, + request: RemoteStartTransactionRequest, + response: GenericResponse + ) => { + if (response.status === GenericStatus.Accepted) { + const { connectorId, idTag } = request + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + chargingStation.getConnectorStatus(connectorId)!.transactionRemoteStarted = true + chargingStation.ocppRequestService + .requestHandler( + chargingStation, + OCPP16RequestCommand.START_TRANSACTION, + { + connectorId, + idTag + } + ) + .then(response => { + if (response.status === OCPP16AuthorizationStatus.ACCEPTED) { + logger.debug( + `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for idTag '${idTag}'` + ) + } else { + logger.debug( + `${chargingStation.logPrefix()} Remote start transaction REJECTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for idTag '${idTag}'` + ) + } + }) + .catch(error => { + logger.error( + `${chargingStation.logPrefix()} ${moduleName}.constructor: Remote start transaction error:`, + error + ) + }) + } + } + ) + this.on( + OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION, + ( + chargingStation: ChargingStation, + request: RemoteStopTransactionRequest, + response: GenericResponse + ) => { + if (response.status === GenericStatus.Accepted) { + const { transactionId } = request + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const connectorId = chargingStation.getConnectorIdByTransactionId(transactionId)! + OCPP16ServiceUtils.remoteStopTransaction(chargingStation, connectorId) + .then(response => { + if (response.status === GenericStatus.Accepted) { + logger.debug( + `${chargingStation.logPrefix()} Remote stop transaction ACCEPTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for transaction '${transactionId}'` + ) + } else { + logger.debug( + `${chargingStation.logPrefix()} Remote stop transaction REJECTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for transaction '${transactionId}'` + ) + } + }) + .catch(error => { + logger.error( + `${chargingStation.logPrefix()} ${moduleName}.constructor: Remote stop transaction error:`, + error + ) + }) + } + } + ) + this.on( + OCPP16IncomingRequestCommand.TRIGGER_MESSAGE, + ( + chargingStation: ChargingStation, + request: OCPP16TriggerMessageRequest, + response: OCPP16TriggerMessageResponse + ) => { + if (response.status !== OCPP16TriggerMessageStatus.ACCEPTED) { + return + } + const { requestedMessage, connectorId } = request + const errorHandler = (error: Error): void => { + logger.error( + `${chargingStation.logPrefix()} ${moduleName}.constructor: Trigger ${requestedMessage} error:`, + error + ) + } + switch (requestedMessage) { + case OCPP16MessageTrigger.BootNotification: + chargingStation.ocppRequestService + .requestHandler( + chargingStation, + OCPP16RequestCommand.BOOT_NOTIFICATION, + chargingStation.bootNotificationRequest, + { skipBufferingOnError: true, triggerMessage: true } + ) + .then(response => { + chargingStation.bootNotificationResponse = response + }) + .catch(errorHandler) + break + case OCPP16MessageTrigger.Heartbeat: + chargingStation.ocppRequestService + .requestHandler( + chargingStation, + OCPP16RequestCommand.HEARTBEAT, + undefined, + { + triggerMessage: true + } + ) + .catch(errorHandler) + break + case OCPP16MessageTrigger.StatusNotification: + if (connectorId != null) { + chargingStation.ocppRequestService + .requestHandler( + chargingStation, + OCPP16RequestCommand.STATUS_NOTIFICATION, + { + connectorId, + errorCode: OCPP16ChargePointErrorCode.NO_ERROR, + status: chargingStation.getConnectorStatus(connectorId)?.status + }, + { + triggerMessage: true + } + ) + .catch(errorHandler) + } else if (chargingStation.hasEvses) { + for (const evseStatus of chargingStation.evses.values()) { + for (const [id, connectorStatus] of evseStatus.connectors) { + chargingStation.ocppRequestService + .requestHandler< + OCPP16StatusNotificationRequest, + OCPP16StatusNotificationResponse + >( + chargingStation, + OCPP16RequestCommand.STATUS_NOTIFICATION, + { + connectorId: id, + errorCode: OCPP16ChargePointErrorCode.NO_ERROR, + status: connectorStatus.status + }, + { + triggerMessage: true + } + ) + .catch(errorHandler) + } + } + } else { + for (const [id, connectorStatus] of chargingStation.connectors) { + chargingStation.ocppRequestService + .requestHandler< + OCPP16StatusNotificationRequest, + OCPP16StatusNotificationResponse + >( + chargingStation, + OCPP16RequestCommand.STATUS_NOTIFICATION, + { + connectorId: id, + errorCode: OCPP16ChargePointErrorCode.NO_ERROR, + status: connectorStatus.status + }, + { + triggerMessage: true + } + ) + .catch(errorHandler) + } + } + break + } + } + ) + this.validatePayload = this.validatePayload.bind(this) } public async incomingRequestHandler( @@ -376,10 +625,12 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { this.validatePayload(chargingStation, commandName, commandPayload) // Call the method to build the response // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - response = (await this.incomingRequestHandlers.get(commandName)!( - chargingStation, - commandPayload - )) as ResType + const incomingRequestHandler = this.incomingRequestHandlers.get(commandName)! + if (isAsyncFunction(incomingRequestHandler)) { + response = (await incomingRequestHandler(chargingStation, commandPayload)) as ResType + } else { + response = incomingRequestHandler(chargingStation, commandPayload) as ResType + } } catch (error) { // Log logger.error( @@ -420,6 +671,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { response, commandName ) + // Emit command name event to allow delayed handling + this.emit(commandName, chargingStation, commandPayload, response) } private validatePayload ( @@ -427,17 +680,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { commandName: OCPP16IncomingRequestCommand, commandPayload: JsonType ): boolean { - if (this.jsonSchemas.has(commandName)) { - return this.validateIncomingRequestPayload( - chargingStation, - commandName, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.jsonSchemas.get(commandName)!, - commandPayload - ) + if (this.payloadValidateFunctions.has(commandName)) { + return this.validateIncomingRequestPayload(chargingStation, commandName, commandPayload) } logger.warn( - `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation` + `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation` ) return false } @@ -726,10 +973,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingProfile.chargingProfileId } startSchedule property is not a Date instance. Trying to convert it to a Date instance` ) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion chargingProfile.chargingSchedule.startSchedule = convertToDate( chargingProfile.chargingSchedule.startSchedule - )! + ) } if (chargingProfile.chargingSchedule.duration == null) { logger.debug( @@ -740,7 +986,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { // OCPP specifies that if duration is not defined, it should be infinite chargingProfile.chargingSchedule.duration = differenceInSeconds( maxTime, - chargingProfile.chargingSchedule.startSchedule + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + chargingProfile.chargingSchedule.startSchedule! ) } if ( @@ -919,95 +1166,40 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { idTag ) } - const remoteStartTransactionLogMsg = ` - ${chargingStation.logPrefix()} Transaction remotely STARTED on ${ - chargingStation.stationInfo?.chargingStationId - }#${transactionConnectorId} for idTag '${idTag}'` - await OCPP16ServiceUtils.sendAndSetConnectorStatus( - chargingStation, - transactionConnectorId, - OCPP16ChargePointStatus.Preparing - ) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId)! - // Authorization check required + // idTag authorization check required if ( chargingStation.getAuthorizeRemoteTxRequests() && - (await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, transactionConnectorId, idTag)) + !(await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, transactionConnectorId, idTag)) ) { - // Authorization successful, start transaction - if ( - (chargingProfile != null && - this.setRemoteStartTransactionChargingProfile( - chargingStation, - transactionConnectorId, - chargingProfile - )) || - chargingProfile == null - ) { - connectorStatus.transactionRemoteStarted = true - if ( - ( - await chargingStation.ocppRequestService.requestHandler< - OCPP16StartTransactionRequest, - OCPP16StartTransactionResponse - >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, { - connectorId: transactionConnectorId, - idTag - }) - ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED - ) { - logger.debug(remoteStartTransactionLogMsg) - return OCPP16Constants.OCPP_RESPONSE_ACCEPTED - } - return await this.notifyRemoteStartTransactionRejected( - chargingStation, - transactionConnectorId, - idTag - ) - } return await this.notifyRemoteStartTransactionRejected( chargingStation, transactionConnectorId, idTag ) } - // No authorization check required, start transaction + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, + transactionConnectorId, + OCPP16ChargePointStatus.Preparing + ) if ( - (chargingProfile != null && - this.setRemoteStartTransactionChargingProfile( - chargingStation, - transactionConnectorId, - chargingProfile - )) || - chargingProfile == null + chargingProfile != null && + !this.setRemoteStartTransactionChargingProfile( + chargingStation, + transactionConnectorId, + chargingProfile + ) ) { - connectorStatus.transactionRemoteStarted = true - if ( - ( - await chargingStation.ocppRequestService.requestHandler< - OCPP16StartTransactionRequest, - OCPP16StartTransactionResponse - >(chargingStation, OCPP16RequestCommand.START_TRANSACTION, { - connectorId: transactionConnectorId, - idTag - }) - ).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED - ) { - logger.debug(remoteStartTransactionLogMsg) - return OCPP16Constants.OCPP_RESPONSE_ACCEPTED - } return await this.notifyRemoteStartTransactionRejected( chargingStation, transactionConnectorId, idTag ) } - return await this.notifyRemoteStartTransactionRejected( - chargingStation, - transactionConnectorId, - idTag + logger.debug( + `${chargingStation.logPrefix()} Remote start transaction ACCEPTED on connector id ${transactionConnectorId}, idTag '${idTag}'` ) + return OCPP16Constants.OCPP_RESPONSE_ACCEPTED } private async notifyRemoteStartTransactionRejected ( @@ -1023,8 +1215,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { OCPP16ChargePointStatus.Available ) } - logger.warn( - `${chargingStation.logPrefix()} Remote starting transaction REJECTED on connector id ${connectorId}, idTag '${idTag}', availability '${connectorStatus?.availability}', status '${connectorStatus?.status}'` + logger.debug( + `${chargingStation.logPrefix()} Remote start transaction REJECTED on connector id ${connectorId}, idTag '${idTag}', availability '${connectorStatus?.availability}', status '${connectorStatus?.status}'` ) return OCPP16Constants.OCPP_RESPONSE_REJECTED } @@ -1042,7 +1234,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ) return true } - logger.warn( + logger.debug( `${chargingStation.logPrefix()} Not allowed to set ${ chargingProfile.chargingProfilePurpose } charging profile(s) at remote start transaction` @@ -1050,33 +1242,19 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return false } - private async handleRequestRemoteStopTransaction ( + private handleRequestRemoteStopTransaction ( chargingStation: ChargingStation, commandPayload: RemoteStopTransactionRequest - ): Promise { + ): GenericResponse { const { transactionId } = commandPayload - if (chargingStation.hasEvses) { - for (const [evseId, evseStatus] of chargingStation.evses) { - if (evseId > 0) { - for (const [connectorId, connectorStatus] of evseStatus.connectors) { - if (connectorStatus.transactionId === transactionId) { - return await OCPP16ServiceUtils.remoteStopTransaction(chargingStation, connectorId) - } - } - } - } - } else { - for (const connectorId of chargingStation.connectors.keys()) { - if ( - connectorId > 0 && - chargingStation.getConnectorStatus(connectorId)?.transactionId === transactionId - ) { - return await OCPP16ServiceUtils.remoteStopTransaction(chargingStation, connectorId) - } - } + if (chargingStation.getConnectorIdByTransactionId(transactionId) != null) { + logger.debug( + `${chargingStation.logPrefix()} Remote stop transaction ACCEPTED for transactionId '${transactionId}'` + ) + return OCPP16Constants.OCPP_RESPONSE_ACCEPTED } - logger.warn( - `${chargingStation.logPrefix()} Trying to remote stop a non existing transaction with id ${transactionId}` + logger.debug( + `${chargingStation.logPrefix()} Remote stop transaction REJECTED for transactionId '${transactionId}'` ) return OCPP16Constants.OCPP_RESPONSE_REJECTED } @@ -1405,110 +1583,13 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ) { return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED } - try { - switch (requestedMessage) { - case OCPP16MessageTrigger.BootNotification: - setTimeout(() => { - chargingStation.ocppRequestService - .requestHandler( - chargingStation, - OCPP16RequestCommand.BOOT_NOTIFICATION, - chargingStation.bootNotificationRequest, - { skipBufferingOnError: true, triggerMessage: true } - ) - .then(response => { - chargingStation.bootNotificationResponse = response - }) - .catch(Constants.EMPTY_FUNCTION) - }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY) - return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED - case OCPP16MessageTrigger.Heartbeat: - setTimeout(() => { - chargingStation.ocppRequestService - .requestHandler( - chargingStation, - OCPP16RequestCommand.HEARTBEAT, - undefined, - { - triggerMessage: true - } - ) - .catch(Constants.EMPTY_FUNCTION) - }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY) - return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED - case OCPP16MessageTrigger.StatusNotification: - setTimeout(() => { - if (connectorId != null) { - chargingStation.ocppRequestService - .requestHandler( - chargingStation, - OCPP16RequestCommand.STATUS_NOTIFICATION, - { - connectorId, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: chargingStation.getConnectorStatus(connectorId)?.status - }, - { - triggerMessage: true - } - ) - .catch(Constants.EMPTY_FUNCTION) - } else if (chargingStation.hasEvses) { - for (const evseStatus of chargingStation.evses.values()) { - for (const [id, connectorStatus] of evseStatus.connectors) { - chargingStation.ocppRequestService - .requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >( - chargingStation, - OCPP16RequestCommand.STATUS_NOTIFICATION, - { - connectorId: id, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: connectorStatus.status - }, - { - triggerMessage: true - } - ) - .catch(Constants.EMPTY_FUNCTION) - } - } - } else { - for (const [id, connectorStatus] of chargingStation.connectors) { - chargingStation.ocppRequestService - .requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >( - chargingStation, - OCPP16RequestCommand.STATUS_NOTIFICATION, - { - connectorId: id, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: connectorStatus.status - }, - { - triggerMessage: true - } - ) - .catch(Constants.EMPTY_FUNCTION) - } - } - }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY) - return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED - default: - return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED - } - } catch (error) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.handleIncomingRequestError( - chargingStation, - OCPP16IncomingRequestCommand.TRIGGER_MESSAGE, - error as Error, - { errorResponse: OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED } - )! + switch (requestedMessage) { + case OCPP16MessageTrigger.BootNotification: + case OCPP16MessageTrigger.Heartbeat: + case OCPP16MessageTrigger.StatusNotification: + return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED + default: + return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED } }