+ this.requestHandler = this.requestHandler.bind(this) as <
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ ReqType extends JsonType,
+ ResType extends JsonType,
+ >(
+ chargingStation: ChargingStation,
+ commandName: RequestCommand,
+ commandParams?: JsonType,
+ params?: RequestParams,
+ ) => Promise<ResType>;
+ this.sendMessage = this.sendMessage.bind(this) as (
+ chargingStation: ChargingStation,
+ messageId: string,
+ messagePayload: JsonType,
+ commandName: RequestCommand,
+ params?: RequestParams,
+ ) => Promise<ResponseType>;
+ this.sendResponse = this.sendResponse.bind(this) as (
+ chargingStation: ChargingStation,
+ messageId: string,
+ messagePayload: JsonType,
+ commandName: IncomingRequestCommand,
+ ) => Promise<ResponseType>;
+ this.sendError = this.sendError.bind(this) as (
+ chargingStation: ChargingStation,
+ messageId: string,
+ ocppError: OCPPError,
+ commandName: RequestCommand | IncomingRequestCommand,
+ ) => Promise<ResponseType>;
+ this.internalSendMessage = this.internalSendMessage.bind(this) as (
+ chargingStation: ChargingStation,
+ messageId: string,
+ messagePayload: JsonType | OCPPError,
+ messageType: MessageType,
+ commandName: RequestCommand | IncomingRequestCommand,
+ params?: RequestParams,
+ ) => Promise<ResponseType>;
+ this.buildMessageToSend = this.buildMessageToSend.bind(this) as (
+ chargingStation: ChargingStation,
+ messageId: string,
+ messagePayload: JsonType | OCPPError,
+ messageType: MessageType,
+ commandName: RequestCommand | IncomingRequestCommand,
+ responseCallback: ResponseCallback,
+ errorCallback: ErrorCallback,
+ ) => string;
+ this.validateRequestPayload = this.validateRequestPayload.bind(this) as <T extends JsonObject>(
+ chargingStation: ChargingStation,
+ commandName: RequestCommand | IncomingRequestCommand,
+ payload: T,
+ ) => boolean;
+ this.validateIncomingRequestResponsePayload = this.validateIncomingRequestResponsePayload.bind(
+ this,
+ ) as <T extends JsonObject>(
+ chargingStation: ChargingStation,
+ commandName: RequestCommand | IncomingRequestCommand,
+ payload: T,
+ ) => boolean;
+ }
+
+ public static getInstance<T extends OCPPRequestService>(
+ this: new (ocppResponseService: OCPPResponseService) => T,
+ ocppResponseService: OCPPResponseService,
+ ): T {
+ if (OCPPRequestService.instance === null) {
+ OCPPRequestService.instance = new this(ocppResponseService);
+ }
+ return OCPPRequestService.instance as T;
+ }
+
+ public async sendResponse(
+ chargingStation: ChargingStation,
+ messageId: string,
+ messagePayload: JsonType,
+ commandName: IncomingRequestCommand,
+ ): Promise<ResponseType> {
+ try {
+ // Send response message
+ return await this.internalSendMessage(
+ chargingStation,
+ messageId,
+ messagePayload,
+ MessageType.CALL_RESULT_MESSAGE,
+ commandName,
+ );
+ } catch (error) {
+ handleSendMessageError(chargingStation, commandName, error as Error, {
+ throwError: true,
+ });
+ return null;
+ }
+ }
+
+ public async sendError(
+ chargingStation: ChargingStation,
+ messageId: string,
+ ocppError: OCPPError,
+ commandName: RequestCommand | IncomingRequestCommand,
+ ): Promise<ResponseType> {
+ try {
+ // Send error message
+ return await this.internalSendMessage(
+ chargingStation,
+ messageId,
+ ocppError,
+ MessageType.CALL_ERROR_MESSAGE,
+ commandName,
+ );
+ } catch (error) {
+ handleSendMessageError(chargingStation, commandName, error as Error);
+ return null;
+ }
+ }
+
+ protected async sendMessage(
+ chargingStation: ChargingStation,
+ messageId: string,
+ messagePayload: JsonType,
+ commandName: RequestCommand,
+ params?: RequestParams,
+ ): Promise<ResponseType> {
+ params = {
+ ...defaultRequestParams,
+ ...params,
+ };
+ try {
+ return await this.internalSendMessage(
+ chargingStation,
+ messageId,
+ messagePayload,
+ MessageType.CALL_MESSAGE,
+ commandName,
+ params,
+ );
+ } catch (error) {
+ handleSendMessageError(chargingStation, commandName, error as Error, {
+ throwError: params.throwError,
+ });
+ return null;
+ }
+ }
+
+ private validateRequestPayload<T extends JsonObject>(
+ chargingStation: ChargingStation,
+ commandName: RequestCommand | IncomingRequestCommand,
+ payload: T,
+ ): boolean {
+ if (chargingStation.getOcppStrictCompliance() === false) {
+ return true;
+ }
+ if (this.jsonSchemas.has(commandName as RequestCommand) === false) {
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: No JSON schema found for command '${commandName}' PDU validation`,
+ );
+ return true;
+ }
+ const validate = this.ajv.compile(this.jsonSchemas.get(commandName as RequestCommand)!);
+ payload = cloneObject<T>(payload);
+ OCPPServiceUtils.convertDateToISOString<T>(payload);
+ if (validate(payload)) {
+ return true;
+ }
+ logger.error(
+ `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: Command '${commandName}' request PDU is invalid: %j`,
+ validate.errors,
+ );
+ // 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!),
+ 'Request PDU is invalid',
+ commandName,
+ JSON.stringify(validate.errors, null, 2),
+ );
+ }
+
+ private validateIncomingRequestResponsePayload<T extends JsonObject>(
+ chargingStation: ChargingStation,
+ commandName: RequestCommand | IncomingRequestCommand,
+ payload: T,
+ ): boolean {
+ if (chargingStation.getOcppStrictCompliance() === false) {
+ return true;
+ }
+ if (
+ this.ocppResponseService.jsonIncomingRequestResponseSchemas.has(
+ commandName as IncomingRequestCommand,
+ ) === false
+ ) {
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: No JSON schema found for command '${commandName}' PDU validation`,
+ );
+ return true;
+ }
+ const validate = this.ajv.compile(
+ this.ocppResponseService.jsonIncomingRequestResponseSchemas.get(
+ commandName as IncomingRequestCommand,
+ )!,
+ );
+ payload = cloneObject<T>(payload);
+ OCPPServiceUtils.convertDateToISOString<T>(payload);
+ if (validate(payload)) {
+ return true;
+ }
+ logger.error(
+ `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: Command '${commandName}' reponse PDU is invalid: %j`,
+ validate.errors,
+ );
+ // 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!),
+ 'Response PDU is invalid',
+ commandName,
+ JSON.stringify(validate.errors, null, 2),
+ );