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