1 import { AsyncResource
} from
'node:async_hooks';
3 import Ajv
, { type JSONSchemaType
, type ValidateFunction
} from
'ajv';
4 import ajvFormats from
'ajv-formats';
6 import { OCPPConstants
} from
'./OCPPConstants';
7 import { OCPPServiceUtils
} from
'./OCPPServiceUtils';
8 import { type ChargingStation
, getIdTagsFile
} from
'../../charging-station';
9 import { OCPPError
} from
'../../exception';
13 IncomingRequestCommand
,
18 import { logger
, setDefaultErrorParams
} from
'../../utils';
20 const moduleName
= 'OCPPIncomingRequestService';
22 export abstract class OCPPIncomingRequestService
extends AsyncResource
{
23 private static instance
: OCPPIncomingRequestService
| null = null;
24 private readonly version
: OCPPVersion
;
25 private readonly ajv
: Ajv
;
26 private jsonValidateFunctions
: Map
<IncomingRequestCommand
, ValidateFunction
<JsonObject
>>;
27 protected abstract jsonSchemas
: Map
<IncomingRequestCommand
, JSONSchemaType
<JsonObject
>>;
29 protected constructor(version
: OCPPVersion
) {
31 this.version
= version
;
33 keywords
: ['javaType'],
34 multipleOfPrecision
: 2,
37 this.jsonValidateFunctions
= new Map
<IncomingRequestCommand
, ValidateFunction
<JsonObject
>>();
38 this.incomingRequestHandler
= this.incomingRequestHandler
.bind(this) as <
39 ReqType
extends JsonType
,
40 // eslint-disable-next-line @typescript-eslint/no-unused-vars
41 ResType
extends JsonType
,
43 chargingStation
: ChargingStation
,
45 commandName
: IncomingRequestCommand
,
46 commandPayload
: ReqType
,
48 this.validateIncomingRequestPayload
= this.validateIncomingRequestPayload
.bind(this) as <
51 chargingStation
: ChargingStation
,
52 commandName
: IncomingRequestCommand
,
53 schema
: JSONSchemaType
<T
>,
58 public static getInstance
<T
extends OCPPIncomingRequestService
>(this: new () => T
): T
{
59 if (OCPPIncomingRequestService
.instance
=== null) {
60 OCPPIncomingRequestService
.instance
= new this();
62 return OCPPIncomingRequestService
.instance
as T
;
65 protected handleIncomingRequestError
<T
extends JsonType
>(
66 chargingStation
: ChargingStation
,
67 commandName
: IncomingRequestCommand
,
69 params
: HandleErrorParams
<T
> = { throwError
: true, consoleOut
: false },
71 setDefaultErrorParams(params
);
73 `${chargingStation.logPrefix()} ${moduleName}.handleIncomingRequestError: Incoming request command '${commandName}' error:`,
76 if (!params
?.throwError
&& params
?.errorResponse
) {
77 return params
?.errorResponse
;
79 if (params
?.throwError
&& !params
?.errorResponse
) {
82 if (params
?.throwError
&& params
?.errorResponse
) {
83 return params
?.errorResponse
;
87 protected validateIncomingRequestPayload
<T
extends JsonType
>(
88 chargingStation
: ChargingStation
,
89 commandName
: IncomingRequestCommand
,
90 schema
: JSONSchemaType
<T
>,
93 if (chargingStation
.getOcppStrictCompliance() === false) {
96 if (this.jsonValidateFunctions
.has(commandName
) === false) {
97 this.jsonValidateFunctions
.set(commandName
, this.ajv
.compile
<JsonObject
>(schema
).bind(this));
99 const validate
= this.jsonValidateFunctions
.get(commandName
)!;
100 if (validate(payload
)) {
104 `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestPayload: Command '${commandName}' incoming request PDU is invalid: %j`,
108 OCPPServiceUtils
.ajvErrorsToErrorType(validate
.errors
!),
109 'Incoming request PDU is invalid',
111 JSON
.stringify(validate
.errors
, undefined, 2),
115 protected handleRequestClearCache(chargingStation
: ChargingStation
): ClearCacheResponse
{
116 if (chargingStation
.idTagsCache
.deleteIdTags(getIdTagsFile(chargingStation
.stationInfo
)!)) {
117 return OCPPConstants
.OCPP_RESPONSE_ACCEPTED
;
119 return OCPPConstants
.OCPP_RESPONSE_REJECTED
;
122 // eslint-disable-next-line @typescript-eslint/no-unused-vars
123 public abstract incomingRequestHandler
<ReqType
extends JsonType
, ResType
extends JsonType
>(
124 chargingStation
: ChargingStation
,
126 commandName
: IncomingRequestCommand
,
127 commandPayload
: ReqType
,