Add error handling to JSON schemas file reading
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 2.0 / OCPP20IncomingRequestService.ts
CommitLineData
edd13439 1// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
953d6b02
JB
2
3import type { JSONSchemaType } from 'ajv';
4
78202038 5import { OCPP20ServiceUtils } from './OCPP20ServiceUtils';
953d6b02
JB
6import OCPPError from '../../../exception/OCPPError';
7import type { JsonObject, JsonType } from '../../../types/JsonType';
d270cc87 8import {
81533a20 9 type OCPP20ClearCacheRequest,
d270cc87
JB
10 OCPP20IncomingRequestCommand,
11} from '../../../types/ocpp/2.0/Requests';
953d6b02 12import { ErrorType } from '../../../types/ocpp/ErrorType';
d270cc87 13import { OCPPVersion } from '../../../types/ocpp/OCPPVersion';
953d6b02
JB
14import type { IncomingRequestHandler } from '../../../types/ocpp/Requests';
15import logger from '../../../utils/Logger';
16import type ChargingStation from '../../ChargingStation';
17import OCPPIncomingRequestService from '../OCPPIncomingRequestService';
953d6b02
JB
18
19const moduleName = 'OCPP20IncomingRequestService';
20
21export default class OCPP20IncomingRequestService extends OCPPIncomingRequestService {
b3fc3ff5 22 protected jsonSchemas: Map<OCPP20IncomingRequestCommand, JSONSchemaType<JsonObject>>;
953d6b02 23 private incomingRequestHandlers: Map<OCPP20IncomingRequestCommand, IncomingRequestHandler>;
953d6b02
JB
24
25 public constructor() {
26 if (new.target?.name === moduleName) {
27 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
28 }
d270cc87
JB
29 super(OCPPVersion.VERSION_20);
30 this.incomingRequestHandlers = new Map<OCPP20IncomingRequestCommand, IncomingRequestHandler>([
31 [OCPP20IncomingRequestCommand.CLEAR_CACHE, this.handleRequestClearCache.bind(this)],
32 ]);
33 this.jsonSchemas = new Map<OCPP20IncomingRequestCommand, JSONSchemaType<JsonObject>>([
34 [
35 OCPP20IncomingRequestCommand.CLEAR_CACHE,
130783a7 36 OCPP20ServiceUtils.parseJsonSchemaFile<OCPP20ClearCacheRequest>(
e9a4164c
JB
37 '../../../assets/json-schemas/ocpp/2.0/ClearCacheRequest.json'
38 ),
d270cc87
JB
39 ],
40 ]);
953d6b02
JB
41 this.validatePayload.bind(this);
42 }
43
44 public async incomingRequestHandler(
45 chargingStation: ChargingStation,
46 messageId: string,
47 commandName: OCPP20IncomingRequestCommand,
48 commandPayload: JsonType
49 ): Promise<void> {
50 let response: JsonType;
51 if (
52 chargingStation.getOcppStrictCompliance() === true &&
81533a20
JB
53 chargingStation.isInPendingState() === true &&
54 (commandName === OCPP20IncomingRequestCommand.REQUEST_START_TRANSACTION ||
55 commandName === OCPP20IncomingRequestCommand.REQUEST_STOP_TRANSACTION)
953d6b02
JB
56 ) {
57 throw new OCPPError(
58 ErrorType.SECURITY_ERROR,
59 `${commandName} cannot be issued to handle request PDU ${JSON.stringify(
60 commandPayload,
61 null,
62 2
63 )} while the charging station is in pending state on the central server`,
64 commandName,
65 commandPayload
66 );
67 }
68 if (
69 chargingStation.isRegistered() === true ||
70 (chargingStation.getOcppStrictCompliance() === false &&
71 chargingStation.isInUnknownState() === true)
72 ) {
73 if (
74 this.incomingRequestHandlers.has(commandName) === true &&
75 OCPP20ServiceUtils.isIncomingRequestCommandSupported(chargingStation, commandName) === true
76 ) {
77 try {
78 this.validatePayload(chargingStation, commandName, commandPayload);
79 // Call the method to build the response
80 response = await this.incomingRequestHandlers.get(commandName)(
81 chargingStation,
82 commandPayload
83 );
84 } catch (error) {
85 // Log
86 logger.error(
87 `${chargingStation.logPrefix()} ${moduleName}.incomingRequestHandler: Handle incoming request error:`,
88 error
89 );
90 throw error;
91 }
92 } else {
93 // Throw exception
94 throw new OCPPError(
95 ErrorType.NOT_IMPLEMENTED,
96 `${commandName} is not implemented to handle request PDU ${JSON.stringify(
97 commandPayload,
98 null,
99 2
100 )}`,
101 commandName,
102 commandPayload
103 );
104 }
105 } else {
106 throw new OCPPError(
107 ErrorType.SECURITY_ERROR,
108 `${commandName} cannot be issued to handle request PDU ${JSON.stringify(
109 commandPayload,
110 null,
111 2
112 )} while the charging station is not registered on the central server.`,
113 commandName,
114 commandPayload
115 );
116 }
117 // Send the built response
118 await chargingStation.ocppRequestService.sendResponse(
119 chargingStation,
120 messageId,
121 response,
122 commandName
123 );
124 }
125
126 private validatePayload(
127 chargingStation: ChargingStation,
128 commandName: OCPP20IncomingRequestCommand,
129 commandPayload: JsonType
130 ): boolean {
45988780 131 if (this.jsonSchemas.has(commandName) === true) {
953d6b02
JB
132 return this.validateIncomingRequestPayload(
133 chargingStation,
134 commandName,
135 this.jsonSchemas.get(commandName),
136 commandPayload
137 );
138 }
139 logger.warn(
b3fc3ff5 140 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`
953d6b02
JB
141 );
142 return false;
143 }
144}