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