5ee6e2d09058e9199dffc8015ab28298ef434155
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPResponseService.ts
1 import _Ajv, { type ValidateFunction } from 'ajv'
2 import _ajvFormats from 'ajv-formats'
3
4 import { OCPPServiceUtils } from './OCPPServiceUtils.js'
5 import type { ChargingStation } from '../../charging-station/index.js'
6 import { OCPPError } from '../../exception/index.js'
7 import type {
8 IncomingRequestCommand,
9 JsonType,
10 OCPPVersion,
11 RequestCommand
12 } from '../../types/index.js'
13 import { Constants, logger } from '../../utils/index.js'
14 type Ajv = _Ajv.default
15 // eslint-disable-next-line @typescript-eslint/no-redeclare
16 const Ajv = _Ajv.default
17 const ajvFormats = _ajvFormats.default
18
19 const moduleName = 'OCPPResponseService'
20
21 export abstract class OCPPResponseService {
22 private static instance: OCPPResponseService | null = null
23 private readonly version: OCPPVersion
24 protected readonly ajv: Ajv
25 protected abstract jsonSchemasValidateFunction: Map<RequestCommand, ValidateFunction<JsonType>>
26 public abstract jsonSchemasIncomingRequestResponseValidateFunction: Map<
27 IncomingRequestCommand,
28 ValidateFunction<JsonType>
29 >
30
31 protected constructor (version: OCPPVersion) {
32 this.version = version
33 this.ajv = new Ajv({
34 keywords: ['javaType'],
35 multipleOfPrecision: 2
36 })
37 ajvFormats(this.ajv)
38 this.responseHandler = this.responseHandler.bind(this)
39 this.validateResponsePayload = this.validateResponsePayload.bind(this)
40 }
41
42 public static getInstance<T extends OCPPResponseService>(this: new () => T): T {
43 if (OCPPResponseService.instance === null) {
44 OCPPResponseService.instance = new this()
45 }
46 return OCPPResponseService.instance as T
47 }
48
49 protected validateResponsePayload<T extends JsonType>(
50 chargingStation: ChargingStation,
51 commandName: RequestCommand,
52 payload: T
53 ): boolean {
54 if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
55 return true
56 }
57 const validate = this.jsonSchemasValidateFunction.get(commandName)
58 if (validate?.(payload) === true) {
59 return true
60 }
61 logger.error(
62 `${chargingStation.logPrefix()} ${moduleName}.validateResponsePayload: Command '${commandName}' response PDU is invalid: %j`,
63 validate?.errors
64 )
65 throw new OCPPError(
66 OCPPServiceUtils.ajvErrorsToErrorType(validate?.errors),
67 'Response PDU is invalid',
68 commandName,
69 JSON.stringify(validate?.errors, undefined, 2)
70 )
71 }
72
73 protected emptyResponseHandler = Constants.EMPTY_FUNCTION
74
75 public abstract responseHandler<ReqType extends JsonType, ResType extends JsonType>(
76 chargingStation: ChargingStation,
77 commandName: RequestCommand,
78 payload: ResType,
79 requestPayload: ReqType
80 ): Promise<void>
81 }