]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/blob - src/charging-station/ocpp/OCPPIncomingRequestService.ts
15981f7e42c22513d5f074a9ee840636da50a3f4
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPIncomingRequestService.ts
1 import _Ajv, { type ValidateFunction } from 'ajv'
2 import _ajvFormats from 'ajv-formats'
3 import { EventEmitter } from 'node:events'
4
5 import type {
6 ClearCacheResponse,
7 IncomingRequestCommand,
8 JsonType,
9 OCPPVersion,
10 } from '../../types/index.js'
11
12 import { type ChargingStation, getIdTagsFile } from '../../charging-station/index.js'
13 import { OCPPError } from '../../exception/index.js'
14 import { logger } from '../../utils/index.js'
15 import { OCPPConstants } from './OCPPConstants.js'
16 import { ajvErrorsToErrorType } from './OCPPServiceUtils.js'
17
18 type Ajv = _Ajv.default
19 // eslint-disable-next-line @typescript-eslint/no-redeclare
20 const Ajv = _Ajv.default
21 const ajvFormats = _ajvFormats.default
22
23 const moduleName = 'OCPPIncomingRequestService'
24
25 export abstract class OCPPIncomingRequestService extends EventEmitter {
26 private static instance: null | OCPPIncomingRequestService = null
27 protected readonly ajv: Ajv
28 protected abstract payloadValidateFunctions: Map<
29 IncomingRequestCommand,
30 ValidateFunction<JsonType>
31 >
32
33 private readonly version: OCPPVersion
34
35 protected constructor (version: OCPPVersion) {
36 super()
37 this.version = version
38 this.ajv = new Ajv({
39 keywords: ['javaType'],
40 multipleOfPrecision: 2,
41 })
42 ajvFormats(this.ajv)
43 this.incomingRequestHandler = this.incomingRequestHandler.bind(this)
44 this.validateIncomingRequestPayload = this.validateIncomingRequestPayload.bind(this)
45 }
46
47 public static getInstance<T extends OCPPIncomingRequestService>(this: new () => T): T {
48 OCPPIncomingRequestService.instance ??= new this()
49 return OCPPIncomingRequestService.instance as T
50 }
51
52 // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-unnecessary-type-parameters
53 public abstract incomingRequestHandler<ReqType extends JsonType, ResType extends JsonType>(
54 chargingStation: ChargingStation,
55 messageId: string,
56 commandName: IncomingRequestCommand,
57 commandPayload: ReqType
58 ): Promise<void>
59
60 protected handleRequestClearCache (chargingStation: ChargingStation): ClearCacheResponse {
61 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
62 if (chargingStation.idTagsCache.deleteIdTags(getIdTagsFile(chargingStation.stationInfo!)!)) {
63 return OCPPConstants.OCPP_RESPONSE_ACCEPTED
64 }
65 return OCPPConstants.OCPP_RESPONSE_REJECTED
66 }
67
68 // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
69 protected validateIncomingRequestPayload<T extends JsonType>(
70 chargingStation: ChargingStation,
71 commandName: IncomingRequestCommand,
72 payload: T
73 ): boolean {
74 if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
75 return true
76 }
77 const validate = this.payloadValidateFunctions.get(commandName)
78 if (validate?.(payload) === true) {
79 return true
80 }
81 logger.error(
82 `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestPayload: Command '${commandName}' incoming request PDU is invalid: %j`,
83 validate?.errors
84 )
85 throw new OCPPError(
86 ajvErrorsToErrorType(validate?.errors),
87 'Incoming request PDU is invalid',
88 commandName,
89 JSON.stringify(validate?.errors, undefined, 2)
90 )
91 }
92 }