X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2Focpp%2FOCPPRequestService.ts;h=b95e9d239e6864701b41166a47b6a0d19e81094d;hb=291b5ec8b20005de53c4de3eba0e4cd1b068006c;hp=6d0809c59440764674529248c9b2ac858de2c092;hpb=5edd8ba0f8978cfb3ca9d80f299d9748c6c5970e;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ocpp/OCPPRequestService.ts b/src/charging-station/ocpp/OCPPRequestService.ts index 6d0809c5..b95e9d23 100644 --- a/src/charging-station/ocpp/OCPPRequestService.ts +++ b/src/charging-station/ocpp/OCPPRequestService.ts @@ -1,4 +1,4 @@ -import Ajv, { type JSONSchemaType } from 'ajv'; +import Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv'; import ajvFormats from 'ajv-formats'; import { OCPPConstants } from './OCPPConstants'; @@ -44,7 +44,8 @@ export abstract class OCPPRequestService { private readonly version: OCPPVersion; private readonly ajv: Ajv; private readonly ocppResponseService: OCPPResponseService; - protected abstract jsonSchemas: Map>; + private readonly jsonValidateFunctions: Map>; + protected abstract jsonSchemas: Map>; protected constructor(version: OCPPVersion, ocppResponseService: OCPPResponseService) { this.version = version; @@ -53,8 +54,10 @@ export abstract class OCPPRequestService { multipleOfPrecision: 2, }); ajvFormats(this.ajv); + this.jsonValidateFunctions = new Map>(); this.ocppResponseService = ocppResponseService; this.requestHandler = this.requestHandler.bind(this) as < + // eslint-disable-next-line @typescript-eslint/no-unused-vars ReqType extends JsonType, ResType extends JsonType, >( @@ -99,14 +102,14 @@ export abstract class OCPPRequestService { responseCallback: ResponseCallback, errorCallback: ErrorCallback, ) => string; - this.validateRequestPayload = this.validateRequestPayload.bind(this) as ( + this.validateRequestPayload = this.validateRequestPayload.bind(this) as ( chargingStation: ChargingStation, commandName: RequestCommand | IncomingRequestCommand, payload: T, ) => boolean; this.validateIncomingRequestResponsePayload = this.validateIncomingRequestResponsePayload.bind( this, - ) as ( + ) as ( chargingStation: ChargingStation, commandName: RequestCommand | IncomingRequestCommand, payload: T, @@ -142,6 +145,7 @@ export abstract class OCPPRequestService { handleSendMessageError(chargingStation, commandName, error as Error, { throwError: true, }); + return null; } } @@ -162,6 +166,7 @@ export abstract class OCPPRequestService { ); } catch (error) { handleSendMessageError(chargingStation, commandName, error as Error); + return null; } } @@ -170,7 +175,7 @@ export abstract class OCPPRequestService { messageId: string, messagePayload: JsonType, commandName: RequestCommand, - params: RequestParams = defaultRequestParams, + params?: RequestParams, ): Promise { params = { ...defaultRequestParams, @@ -189,10 +194,11 @@ export abstract class OCPPRequestService { handleSendMessageError(chargingStation, commandName, error as Error, { throwError: params.throwError, }); + return null; } } - private validateRequestPayload( + private validateRequestPayload( chargingStation: ChargingStation, commandName: RequestCommand | IncomingRequestCommand, payload: T, @@ -206,7 +212,13 @@ export abstract class OCPPRequestService { ); return true; } - const validate = this.ajv.compile(this.jsonSchemas.get(commandName as RequestCommand)); + if (this.jsonValidateFunctions.has(commandName as RequestCommand) === false) { + this.jsonValidateFunctions.set( + commandName as RequestCommand, + this.ajv.compile(this.jsonSchemas.get(commandName as RequestCommand)!).bind(this), + ); + } + const validate = this.jsonValidateFunctions.get(commandName as RequestCommand)!; payload = cloneObject(payload); OCPPServiceUtils.convertDateToISOString(payload); if (validate(payload)) { @@ -218,14 +230,14 @@ export abstract class OCPPRequestService { ); // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError(). throw new OCPPError( - OCPPServiceUtils.ajvErrorsToErrorType(validate.errors), + OCPPServiceUtils.ajvErrorsToErrorType(validate.errors!), 'Request PDU is invalid', commandName, - JSON.stringify(validate.errors, null, 2), + JSON.stringify(validate.errors, undefined, 2), ); } - private validateIncomingRequestResponsePayload( + private validateIncomingRequestResponsePayload( chargingStation: ChargingStation, commandName: RequestCommand | IncomingRequestCommand, payload: T, @@ -243,11 +255,25 @@ export abstract class OCPPRequestService { ); return true; } - const validate = this.ajv.compile( - this.ocppResponseService.jsonIncomingRequestResponseSchemas.get( + if ( + this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.has( commandName as IncomingRequestCommand, - ), - ); + ) === false + ) { + this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.set( + commandName as IncomingRequestCommand, + this.ajv + .compile( + this.ocppResponseService.jsonIncomingRequestResponseSchemas.get( + commandName as IncomingRequestCommand, + )!, + ) + .bind(this), + ); + } + const validate = this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.get( + commandName as IncomingRequestCommand, + )!; payload = cloneObject(payload); OCPPServiceUtils.convertDateToISOString(payload); if (validate(payload)) { @@ -259,10 +285,10 @@ export abstract class OCPPRequestService { ); // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError(). throw new OCPPError( - OCPPServiceUtils.ajvErrorsToErrorType(validate.errors), + OCPPServiceUtils.ajvErrorsToErrorType(validate.errors!), 'Response PDU is invalid', commandName, - JSON.stringify(validate.errors, null, 2), + JSON.stringify(validate.errors, undefined, 2), ); } @@ -272,7 +298,7 @@ export abstract class OCPPRequestService { messagePayload: JsonType | OCPPError, messageType: MessageType, commandName: RequestCommand | IncomingRequestCommand, - params: RequestParams = defaultRequestParams, + params?: RequestParams, ): Promise { params = { ...defaultRequestParams, @@ -291,7 +317,7 @@ export abstract class OCPPRequestService { const self = this; // Send a message through wsConnection return promiseWithTimeout( - new Promise((resolve, reject) => { + new Promise((resolve, reject) => { /** * Function that will receive the request's response * @@ -384,7 +410,7 @@ export abstract class OCPPRequestService { PerformanceStatistics.endMeasure(commandName, beginId); } const wsClosedOrErrored = !wsOpened || sendError === true; - if (wsClosedOrErrored && params.skipBufferingOnError === false) { + if (wsClosedOrErrored && params?.skipBufferingOnError === false) { // Buffer chargingStation.bufferMessage(messageToSend); // Reject and keep request in the cache @@ -393,7 +419,7 @@ export abstract class OCPPRequestService { ErrorType.GENERIC_ERROR, `WebSocket closed or errored for buffered message id '${messageId}' with content '${messageToSend}'`, commandName, - (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FREEZED_OBJECT, + (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FROZEN_OBJECT, ), ); } else if (wsClosedOrErrored) { @@ -401,7 +427,7 @@ export abstract class OCPPRequestService { ErrorType.GENERIC_ERROR, `WebSocket closed or errored for non buffered message id '${messageId}' with content '${messageToSend}'`, commandName, - (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FREEZED_OBJECT, + (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FROZEN_OBJECT, ); // Reject response if (messageType !== MessageType.CALL_MESSAGE) { @@ -420,7 +446,7 @@ export abstract class OCPPRequestService { ErrorType.GENERIC_ERROR, `Timeout for message id '${messageId}'`, commandName, - (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FREEZED_OBJECT, + (messagePayload as JsonObject)?.details ?? Constants.EMPTY_FROZEN_OBJECT, ), () => { messageType === MessageType.CALL_MESSAGE && chargingStation.requests.delete(messageId); @@ -449,7 +475,7 @@ export abstract class OCPPRequestService { // Request case MessageType.CALL_MESSAGE: // Build request - this.validateRequestPayload(chargingStation, commandName, messagePayload as JsonObject); + this.validateRequestPayload(chargingStation, commandName, messagePayload as JsonType); chargingStation.requests.set(messageId, [ responseCallback, errorCallback, @@ -469,7 +495,7 @@ export abstract class OCPPRequestService { this.validateIncomingRequestResponsePayload( chargingStation, commandName, - messagePayload as JsonObject, + messagePayload as JsonType, ); messageToSend = JSON.stringify([messageType, messageId, messagePayload] as Response); break; @@ -492,6 +518,7 @@ export abstract class OCPPRequestService { public abstract requestHandler( chargingStation: ChargingStation, commandName: RequestCommand, + // FIXME: should be ReqType commandParams?: JsonType, params?: RequestParams, ): Promise;