refactor: add type parameter to OCPP stack for request and response
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPResponseService.ts
CommitLineData
d270cc87 1import Ajv, { type JSONSchemaType } from 'ajv';
844e496b
JB
2import ajvFormats from 'ajv-formats';
3
4c3c0d59 4import { OCPPServiceUtils } from './OCPPServiceUtils';
2896e06d 5import type { ChargingStation } from '../../charging-station';
268a74bb
JB
6import { OCPPError } from '../../exception';
7import type {
8 IncomingRequestCommand,
9 JsonObject,
10 JsonType,
11 OCPPVersion,
12 RequestCommand,
13} from '../../types';
60a74391 14import { logger } from '../../utils';
c0560973 15
e3018bc4
JB
16const moduleName = 'OCPPResponseService';
17
268a74bb 18export abstract class OCPPResponseService {
08f130a0 19 private static instance: OCPPResponseService | null = null;
d270cc87 20 private readonly version: OCPPVersion;
012ae1a9 21 private readonly ajv: Ajv;
b3fc3ff5
JB
22 public abstract jsonIncomingRequestResponseSchemas: Map<
23 IncomingRequestCommand,
24 JSONSchemaType<JsonObject>
25 >;
10068088 26
d270cc87
JB
27 protected constructor(version: OCPPVersion) {
28 this.version = version;
45988780 29 this.ajv = new Ajv({
98fc1389 30 keywords: ['javaType'],
45988780
JB
31 multipleOfPrecision: 2,
32 });
844e496b 33 ajvFormats(this.ajv);
9429aa42
JB
34 this.responseHandler = this.responseHandler.bind(this) as <
35 ReqType extends JsonType,
36 ResType extends JsonType,
37 >(
31f59c6d
JB
38 chargingStation: ChargingStation,
39 commandName: RequestCommand,
9429aa42
JB
40 payload: ResType,
41 requestPayload: ReqType,
31f59c6d
JB
42 ) => Promise<void>;
43 this.validateResponsePayload = this.validateResponsePayload.bind(this) as <T extends JsonType>(
44 chargingStation: ChargingStation,
45 commandName: RequestCommand,
46 schema: JSONSchemaType<T>,
5edd8ba0 47 payload: T,
31f59c6d 48 ) => boolean;
c0560973
JB
49 }
50
08f130a0 51 public static getInstance<T extends OCPPResponseService>(this: new () => T): T {
1ca780f9 52 if (OCPPResponseService.instance === null) {
08f130a0 53 OCPPResponseService.instance = new this();
9f2e3130 54 }
08f130a0 55 return OCPPResponseService.instance as T;
9f2e3130
JB
56 }
57
844e496b
JB
58 protected validateResponsePayload<T extends JsonType>(
59 chargingStation: ChargingStation,
60 commandName: RequestCommand,
61 schema: JSONSchemaType<T>,
5edd8ba0 62 payload: T,
844e496b 63 ): boolean {
0282b7c0 64 if (chargingStation.getOcppStrictCompliance() === false) {
844e496b
JB
65 return true;
66 }
67 const validate = this.ajv.compile(schema);
68 if (validate(payload)) {
69 return true;
70 }
71 logger.error(
45988780 72 `${chargingStation.logPrefix()} ${moduleName}.validateResponsePayload: Command '${commandName}' response PDU is invalid: %j`,
5edd8ba0 73 validate.errors,
844e496b
JB
74 );
75 throw new OCPPError(
e1d9a0f4 76 OCPPServiceUtils.ajvErrorsToErrorType(validate.errors!),
844e496b
JB
77 'Response PDU is invalid',
78 commandName,
5edd8ba0 79 JSON.stringify(validate.errors, null, 2),
844e496b
JB
80 );
81 }
82
81e3cc38 83 protected emptyResponseHandler() {
bd770dde 84 /* This is intentional */
81e3cc38 85 }
b52c969d 86
9429aa42 87 public abstract responseHandler<ReqType extends JsonType, ResType extends JsonType>(
08f130a0 88 chargingStation: ChargingStation,
e7aeea18 89 commandName: RequestCommand,
9429aa42
JB
90 payload: ResType,
91 requestPayload: ReqType,
e7aeea18 92 ): Promise<void>;
c0560973 93}