chore: switch coding style to JS standard
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPRequestService.ts
CommitLineData
66a7748d
JB
1import _Ajv, { type JSONSchemaType, type ValidateFunction } from 'ajv'
2import _ajvFormats from 'ajv-formats'
b52c969d 3
66a7748d
JB
4import { OCPPConstants } from './OCPPConstants.js'
5import type { OCPPResponseService } from './OCPPResponseService.js'
6import { OCPPServiceUtils } from './OCPPServiceUtils.js'
7import type { ChargingStation } from '../../charging-station/index.js'
8import { OCPPError } from '../../exception/index.js'
9import { PerformanceStatistics } from '../../performance/index.js'
e7aeea18 10import {
8baae8ee 11 ChargingStationEvents,
27782dbc 12 type ErrorCallback,
268a74bb
JB
13 type ErrorResponse,
14 ErrorType,
27782dbc 15 type IncomingRequestCommand,
268a74bb
JB
16 type JsonType,
17 MessageType,
18 type OCPPVersion,
27782dbc 19 type OutgoingRequest,
e7aeea18 20 RequestCommand,
27782dbc 21 type RequestParams,
268a74bb 22 type Response,
27782dbc 23 type ResponseCallback,
66a7748d
JB
24 type ResponseType
25} from '../../types/index.js'
2b94ad12
JB
26import {
27 cloneObject,
28 formatDurationMilliSeconds,
29 handleSendMessageError,
30 isNullOrUndefined,
66a7748d
JB
31 logger
32} from '../../utils/index.js'
33type Ajv = _Ajv.default
34// eslint-disable-next-line @typescript-eslint/no-redeclare
35const Ajv = _Ajv.default
36const ajvFormats = _ajvFormats.default
c0560973 37
66a7748d 38const moduleName = 'OCPPRequestService'
e3018bc4 39
b9da1bc2
JB
40const defaultRequestParams: RequestParams = {
41 skipBufferingOnError: false,
42 triggerMessage: false,
66a7748d
JB
43 throwError: false
44}
b9da1bc2 45
268a74bb 46export abstract class OCPPRequestService {
66a7748d
JB
47 private static instance: OCPPRequestService | null = null
48 private readonly version: OCPPVersion
49 private readonly ajv: Ajv
50 private readonly ocppResponseService: OCPPResponseService
51 private readonly jsonValidateFunctions: Map<RequestCommand, ValidateFunction<JsonType>>
52 protected abstract jsonSchemas: Map<RequestCommand, JSONSchemaType<JsonType>>
c0560973 53
66a7748d
JB
54 protected constructor (version: OCPPVersion, ocppResponseService: OCPPResponseService) {
55 this.version = version
45988780 56 this.ajv = new Ajv({
98fc1389 57 keywords: ['javaType'],
66a7748d
JB
58 multipleOfPrecision: 2
59 })
60 ajvFormats(this.ajv)
61 this.jsonValidateFunctions = new Map<RequestCommand, ValidateFunction<JsonType>>()
62 this.ocppResponseService = ocppResponseService
31f59c6d 63 this.requestHandler = this.requestHandler.bind(this) as <
e1d9a0f4 64 // eslint-disable-next-line @typescript-eslint/no-unused-vars
31f59c6d 65 ReqType extends JsonType,
66a7748d 66 ResType extends JsonType
31f59c6d
JB
67 >(
68 chargingStation: ChargingStation,
69 commandName: RequestCommand,
70 commandParams?: JsonType,
66a7748d
JB
71 params?: RequestParams
72 ) => Promise<ResType>
31f59c6d
JB
73 this.sendMessage = this.sendMessage.bind(this) as (
74 chargingStation: ChargingStation,
75 messageId: string,
76 messagePayload: JsonType,
77 commandName: RequestCommand,
66a7748d
JB
78 params?: RequestParams
79 ) => Promise<ResponseType>
31f59c6d
JB
80 this.sendResponse = this.sendResponse.bind(this) as (
81 chargingStation: ChargingStation,
82 messageId: string,
83 messagePayload: JsonType,
66a7748d
JB
84 commandName: IncomingRequestCommand
85 ) => Promise<ResponseType>
31f59c6d
JB
86 this.sendError = this.sendError.bind(this) as (
87 chargingStation: ChargingStation,
88 messageId: string,
89 ocppError: OCPPError,
66a7748d
JB
90 commandName: RequestCommand | IncomingRequestCommand
91 ) => Promise<ResponseType>
31f59c6d
JB
92 this.internalSendMessage = this.internalSendMessage.bind(this) as (
93 chargingStation: ChargingStation,
94 messageId: string,
95 messagePayload: JsonType | OCPPError,
96 messageType: MessageType,
97 commandName: RequestCommand | IncomingRequestCommand,
66a7748d
JB
98 params?: RequestParams
99 ) => Promise<ResponseType>
31f59c6d
JB
100 this.buildMessageToSend = this.buildMessageToSend.bind(this) as (
101 chargingStation: ChargingStation,
102 messageId: string,
103 messagePayload: JsonType | OCPPError,
104 messageType: MessageType,
66a7748d
JB
105 commandName: RequestCommand | IncomingRequestCommand
106 ) => string
291b5ec8 107 this.validateRequestPayload = this.validateRequestPayload.bind(this) as <T extends JsonType>(
31f59c6d
JB
108 chargingStation: ChargingStation,
109 commandName: RequestCommand | IncomingRequestCommand,
66a7748d
JB
110 payload: T
111 ) => boolean
31f59c6d 112 this.validateIncomingRequestResponsePayload = this.validateIncomingRequestResponsePayload.bind(
66a7748d 113 this
291b5ec8 114 ) as <T extends JsonType>(
31f59c6d
JB
115 chargingStation: ChargingStation,
116 commandName: RequestCommand | IncomingRequestCommand,
66a7748d
JB
117 payload: T
118 ) => boolean
c0560973
JB
119 }
120
e7aeea18 121 public static getInstance<T extends OCPPRequestService>(
08f130a0 122 this: new (ocppResponseService: OCPPResponseService) => T,
66a7748d 123 ocppResponseService: OCPPResponseService
e7aeea18 124 ): T {
1ca780f9 125 if (OCPPRequestService.instance === null) {
66a7748d 126 OCPPRequestService.instance = new this(ocppResponseService)
9f2e3130 127 }
66a7748d 128 return OCPPRequestService.instance as T
9f2e3130
JB
129 }
130
66a7748d 131 public async sendResponse (
08f130a0 132 chargingStation: ChargingStation,
e7aeea18 133 messageId: string,
5cc4b63b 134 messagePayload: JsonType,
66a7748d 135 commandName: IncomingRequestCommand
5eaabe90 136 ): Promise<ResponseType> {
5e0c67e8 137 try {
c75a6675 138 // Send response message
e7aeea18 139 return await this.internalSendMessage(
08f130a0 140 chargingStation,
e7aeea18
JB
141 messageId,
142 messagePayload,
143 MessageType.CALL_RESULT_MESSAGE,
66a7748d
JB
144 commandName
145 )
5e0c67e8 146 } catch (error) {
fa5995d6 147 handleSendMessageError(chargingStation, commandName, error as Error, {
66a7748d
JB
148 throwError: true
149 })
150 return null
5e0c67e8
JB
151 }
152 }
153
66a7748d 154 public async sendError (
08f130a0 155 chargingStation: ChargingStation,
e7aeea18
JB
156 messageId: string,
157 ocppError: OCPPError,
66a7748d 158 commandName: RequestCommand | IncomingRequestCommand
e7aeea18 159 ): Promise<ResponseType> {
5e0c67e8
JB
160 try {
161 // Send error message
e7aeea18 162 return await this.internalSendMessage(
08f130a0 163 chargingStation,
e7aeea18
JB
164 messageId,
165 ocppError,
166 MessageType.CALL_ERROR_MESSAGE,
66a7748d
JB
167 commandName
168 )
5e0c67e8 169 } catch (error) {
66a7748d
JB
170 handleSendMessageError(chargingStation, commandName, error as Error)
171 return null
5e0c67e8
JB
172 }
173 }
174
66a7748d 175 protected async sendMessage (
08f130a0 176 chargingStation: ChargingStation,
e7aeea18 177 messageId: string,
5cc4b63b 178 messagePayload: JsonType,
e7aeea18 179 commandName: RequestCommand,
66a7748d 180 params?: RequestParams
e7aeea18 181 ): Promise<ResponseType> {
7b5dbe91 182 params = {
b9da1bc2 183 ...defaultRequestParams,
66a7748d
JB
184 ...params
185 }
5e0c67e8 186 try {
e7aeea18 187 return await this.internalSendMessage(
08f130a0 188 chargingStation,
e7aeea18
JB
189 messageId,
190 messagePayload,
191 MessageType.CALL_MESSAGE,
192 commandName,
66a7748d
JB
193 params
194 )
5e0c67e8 195 } catch (error) {
fa5995d6 196 handleSendMessageError(chargingStation, commandName, error as Error, {
66a7748d
JB
197 throwError: params.throwError
198 })
199 return null
5e0c67e8
JB
200 }
201 }
202
291b5ec8 203 private validateRequestPayload<T extends JsonType>(
b52c969d 204 chargingStation: ChargingStation,
45988780 205 commandName: RequestCommand | IncomingRequestCommand,
66a7748d 206 payload: T
b52c969d 207 ): boolean {
5398cecf 208 if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
66a7748d 209 return true
b52c969d 210 }
66a7748d 211 if (!this.jsonSchemas.has(commandName as RequestCommand)) {
b3fc3ff5 212 logger.warn(
66a7748d
JB
213 `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: No JSON schema found for command '${commandName}' PDU validation`
214 )
215 return true
45988780 216 }
66a7748d
JB
217 const validate = this.getJsonRequestValidateFunction<T>(commandName as RequestCommand)
218 payload = cloneObject<T>(payload)
219 OCPPServiceUtils.convertDateToISOString<T>(payload)
b52c969d 220 if (validate(payload)) {
66a7748d 221 return true
b52c969d
JB
222 }
223 logger.error(
45988780 224 `${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: Command '${commandName}' request PDU is invalid: %j`,
66a7748d
JB
225 validate.errors
226 )
e909d2a7 227 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
b52c969d 228 throw new OCPPError(
9ff486f4 229 OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
b52c969d
JB
230 'Request PDU is invalid',
231 commandName,
66a7748d
JB
232 JSON.stringify(validate.errors, undefined, 2)
233 )
b52c969d
JB
234 }
235
66a7748d
JB
236 private getJsonRequestValidateFunction<T extends JsonType>(
237 commandName: RequestCommand
238 ): ValidateFunction<JsonType> {
239 if (!this.jsonValidateFunctions.has(commandName)) {
0b0ca54f
JB
240 this.jsonValidateFunctions.set(
241 commandName,
66a7748d
JB
242 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
243 this.ajv.compile<T>(this.jsonSchemas.get(commandName)!).bind(this)
244 )
0b0ca54f 245 }
66a7748d
JB
246 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
247 return this.jsonValidateFunctions.get(commandName)!
0b0ca54f
JB
248 }
249
291b5ec8 250 private validateIncomingRequestResponsePayload<T extends JsonType>(
b3fc3ff5
JB
251 chargingStation: ChargingStation,
252 commandName: RequestCommand | IncomingRequestCommand,
66a7748d 253 payload: T
b3fc3ff5 254 ): boolean {
5398cecf 255 if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
66a7748d 256 return true
b3fc3ff5
JB
257 }
258 if (
66a7748d
JB
259 !this.ocppResponseService.jsonIncomingRequestResponseSchemas.has(
260 commandName as IncomingRequestCommand
261 )
b3fc3ff5
JB
262 ) {
263 logger.warn(
66a7748d
JB
264 `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: No JSON schema found for command '${commandName}' PDU validation`
265 )
266 return true
b3fc3ff5 267 }
0b0ca54f 268 const validate = this.getJsonRequestResponseValidateFunction<T>(
66a7748d
JB
269 commandName as IncomingRequestCommand
270 )
271 payload = cloneObject<T>(payload)
272 OCPPServiceUtils.convertDateToISOString<T>(payload)
b3fc3ff5 273 if (validate(payload)) {
66a7748d 274 return true
b3fc3ff5
JB
275 }
276 logger.error(
02887891 277 `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: Command '${commandName}' reponse PDU is invalid: %j`,
66a7748d
JB
278 validate.errors
279 )
b3fc3ff5
JB
280 // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
281 throw new OCPPError(
9ff486f4 282 OCPPServiceUtils.ajvErrorsToErrorType(validate.errors),
b3fc3ff5
JB
283 'Response PDU is invalid',
284 commandName,
66a7748d
JB
285 JSON.stringify(validate.errors, undefined, 2)
286 )
b3fc3ff5
JB
287 }
288
0b0ca54f 289 private getJsonRequestResponseValidateFunction<T extends JsonType>(
66a7748d
JB
290 commandName: IncomingRequestCommand
291 ): ValidateFunction<JsonType> {
292 if (!this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.has(commandName)) {
0b0ca54f
JB
293 this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.set(
294 commandName,
295 this.ajv
66a7748d 296 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
0b0ca54f 297 .compile<T>(this.ocppResponseService.jsonIncomingRequestResponseSchemas.get(commandName)!)
66a7748d
JB
298 .bind(this)
299 )
0b0ca54f 300 }
66a7748d
JB
301 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
302 return this.ocppResponseService.jsonIncomingRequestResponseValidateFunctions.get(commandName)!
0b0ca54f
JB
303 }
304
66a7748d 305 private async internalSendMessage (
08f130a0 306 chargingStation: ChargingStation,
e7aeea18 307 messageId: string,
5cc4b63b 308 messagePayload: JsonType | OCPPError,
e7aeea18 309 messageType: MessageType,
72092cfc 310 commandName: RequestCommand | IncomingRequestCommand,
66a7748d 311 params?: RequestParams
e7aeea18 312 ): Promise<ResponseType> {
7b5dbe91 313 params = {
b9da1bc2 314 ...defaultRequestParams,
66a7748d
JB
315 ...params
316 }
e7aeea18 317 if (
66a7748d 318 (chargingStation.inUnknownState() && commandName === RequestCommand.BOOT_NOTIFICATION) ||
5398cecf 319 (chargingStation.stationInfo?.ocppStrictCompliance === false &&
66a7748d
JB
320 chargingStation.inUnknownState()) ||
321 chargingStation.inAcceptedState() ||
322 (chargingStation.inPendingState() &&
3a13fc92 323 (params.triggerMessage === true || messageType === MessageType.CALL_RESULT_MESSAGE))
e7aeea18 324 ) {
caad9d6b 325 // eslint-disable-next-line @typescript-eslint/no-this-alias
66a7748d 326 const self = this
caad9d6b 327 // Send a message through wsConnection
66a7748d 328 return await new Promise<ResponseType>((resolve, reject) => {
1b2acf4e
JB
329 /**
330 * Function that will receive the request's response
331 *
332 * @param payload -
333 * @param requestPayload -
334 */
335 const responseCallback = (payload: JsonType, requestPayload: JsonType): void => {
336 if (chargingStation.stationInfo?.enableStatistics === true) {
337 chargingStation.performanceStatistics?.addRequestStatistic(
338 commandName,
66a7748d
JB
339 MessageType.CALL_RESULT_MESSAGE
340 )
1b2acf4e
JB
341 }
342 // Handle the request's response
343 self.ocppResponseService
344 .responseHandler(
345 chargingStation,
346 commandName as RequestCommand,
347 payload,
66a7748d 348 requestPayload
1b2acf4e
JB
349 )
350 .then(() => {
66a7748d 351 resolve(payload)
1b2acf4e 352 })
b7ee97c1 353 .catch(reject)
1b2acf4e 354 .finally(() => {
66a7748d
JB
355 chargingStation.requests.delete(messageId)
356 chargingStation.emit(ChargingStationEvents.updated)
357 })
358 }
e8a92d57 359
1b2acf4e
JB
360 /**
361 * Function that will receive the request's error response
362 *
9d7b5fa3 363 * @param ocppError -
1b2acf4e
JB
364 * @param requestStatistic -
365 */
9d7b5fa3 366 const errorCallback = (ocppError: OCPPError, requestStatistic = true): void => {
66a7748d 367 if (requestStatistic && chargingStation.stationInfo?.enableStatistics === true) {
1b2acf4e
JB
368 chargingStation.performanceStatistics?.addRequestStatistic(
369 commandName,
66a7748d
JB
370 MessageType.CALL_ERROR_MESSAGE
371 )
764d2c91 372 }
1b2acf4e
JB
373 logger.error(
374 `${chargingStation.logPrefix()} Error occurred at ${OCPPServiceUtils.getMessageTypeString(
66a7748d 375 messageType
1b2acf4e 376 )} command ${commandName} with PDU %j:`,
e7aeea18 377 messagePayload,
66a7748d
JB
378 ocppError
379 )
380 chargingStation.requests.delete(messageId)
381 chargingStation.emit(ChargingStationEvents.updated)
382 reject(ocppError)
383 }
9d7b5fa3 384
3c80de96
JB
385 const handleSendError = (ocppError: OCPPError): void => {
386 if (params?.skipBufferingOnError === false) {
387 // Buffer
66a7748d 388 chargingStation.bufferMessage(messageToSend)
3c80de96
JB
389 if (messageType === MessageType.CALL_MESSAGE) {
390 this.cacheRequestPromise(
391 chargingStation,
392 messageId,
393 messagePayload as JsonType,
394 commandName,
395 responseCallback,
66a7748d
JB
396 errorCallback
397 )
3c80de96 398 }
9aa1a33f
JB
399 } else if (
400 params?.skipBufferingOnError === true &&
401 messageType === MessageType.CALL_MESSAGE
402 ) {
2b94ad12 403 // Remove request from the cache
66a7748d 404 chargingStation.requests.delete(messageId)
d42379d8 405 }
66a7748d
JB
406 reject(ocppError)
407 }
d42379d8 408
1b2acf4e 409 if (chargingStation.stationInfo?.enableStatistics === true) {
66a7748d 410 chargingStation.performanceStatistics?.addRequestStatistic(commandName, messageType)
1b2acf4e
JB
411 }
412 const messageToSend = this.buildMessageToSend(
413 chargingStation,
414 messageId,
415 messagePayload,
416 messageType,
66a7748d
JB
417 commandName
418 )
1b2acf4e 419 // Check if wsConnection opened
66a7748d
JB
420 if (chargingStation.isWebSocketConnectionOpened()) {
421 const beginId = PerformanceStatistics.beginMeasure(commandName)
1a32c36b 422 const sendTimeout = setTimeout(() => {
66a7748d 423 handleSendError(
1a32c36b
JB
424 new OCPPError(
425 ErrorType.GENERIC_ERROR,
2b94ad12 426 `Timeout ${formatDurationMilliSeconds(
66a7748d 427 OCPPConstants.OCPP_WEBSOCKET_TIMEOUT
2b94ad12
JB
428 )} reached for ${
429 params?.skipBufferingOnError === false ? '' : 'non '
42b8cf5c 430 }buffered message id '${messageId}' with content '${messageToSend}'`,
1a32c36b 431 commandName,
66a7748d
JB
432 (messagePayload as OCPPError).details
433 )
434 )
435 }, OCPPConstants.OCPP_WEBSOCKET_TIMEOUT)
1a32c36b 436 chargingStation.wsConnection?.send(messageToSend, (error?: Error) => {
66a7748d
JB
437 PerformanceStatistics.endMeasure(commandName, beginId)
438 clearTimeout(sendTimeout)
d42379d8
JB
439 if (isNullOrUndefined(error)) {
440 logger.debug(
441 `${chargingStation.logPrefix()} >> Command '${commandName}' sent ${OCPPServiceUtils.getMessageTypeString(
66a7748d
JB
442 messageType
443 )} payload: ${messageToSend}`
444 )
d42379d8
JB
445 if (messageType === MessageType.CALL_MESSAGE) {
446 this.cacheRequestPromise(
447 chargingStation,
448 messageId,
449 messagePayload as JsonType,
450 commandName,
451 responseCallback,
66a7748d
JB
452 errorCallback
453 )
69dae411
JB
454 } else {
455 // Resolve response
66a7748d 456 resolve(messagePayload)
d42379d8 457 }
66a7748d
JB
458 } else if (error != null) {
459 handleSendError(
3c80de96
JB
460 new OCPPError(
461 ErrorType.GENERIC_ERROR,
462 `WebSocket errored for ${
463 params?.skipBufferingOnError === false ? '' : 'non '
464 }buffered message id '${messageId}' with content '${messageToSend}'`,
465 commandName,
66a7748d
JB
466 { name: error.name, message: error.message, stack: error.stack }
467 )
468 )
1a32c36b 469 }
66a7748d 470 })
82fa1110 471 } else {
66a7748d 472 handleSendError(
3c80de96
JB
473 new OCPPError(
474 ErrorType.GENERIC_ERROR,
475 `WebSocket closed for ${
476 params?.skipBufferingOnError === false ? '' : 'non '
477 }buffered message id '${messageId}' with content '${messageToSend}'`,
478 commandName,
66a7748d
JB
479 (messagePayload as OCPPError).details
480 )
481 )
1b2acf4e 482 }
66a7748d 483 })
caad9d6b 484 }
e7aeea18
JB
485 throw new OCPPError(
486 ErrorType.SECURITY_ERROR,
05e2446f 487 `Cannot send command ${commandName} PDU when the charging station is in ${chargingStation?.bootNotificationResponse?.status} state on the central server`,
66a7748d
JB
488 commandName
489 )
c0560973
JB
490 }
491
66a7748d 492 private buildMessageToSend (
08f130a0 493 chargingStation: ChargingStation,
e7aeea18 494 messageId: string,
5cc4b63b 495 messagePayload: JsonType | OCPPError,
e7aeea18 496 messageType: MessageType,
66a7748d 497 commandName: RequestCommand | IncomingRequestCommand
e7aeea18 498 ): string {
66a7748d 499 let messageToSend: string
e7accadb
JB
500 // Type of message
501 switch (messageType) {
502 // Request
503 case MessageType.CALL_MESSAGE:
504 // Build request
66a7748d 505 this.validateRequestPayload(chargingStation, commandName, messagePayload as JsonType)
b3ec7bc1
JB
506 messageToSend = JSON.stringify([
507 messageType,
508 messageId,
509 commandName,
66a7748d
JB
510 messagePayload
511 ] as OutgoingRequest)
512 break
e7accadb
JB
513 // Response
514 case MessageType.CALL_RESULT_MESSAGE:
515 // Build response
02887891
JB
516 this.validateIncomingRequestResponsePayload(
517 chargingStation,
518 commandName,
66a7748d
JB
519 messagePayload as JsonType
520 )
521 messageToSend = JSON.stringify([messageType, messageId, messagePayload] as Response)
522 break
e7accadb
JB
523 // Error Message
524 case MessageType.CALL_ERROR_MESSAGE:
525 // Build Error Message
e7aeea18
JB
526 messageToSend = JSON.stringify([
527 messageType,
528 messageId,
7375968c
JB
529 (messagePayload as OCPPError).code,
530 (messagePayload as OCPPError).message,
531 (messagePayload as OCPPError).details ?? {
66a7748d
JB
532 command: (messagePayload as OCPPError).command ?? commandName
533 }
534 ] as ErrorResponse)
535 break
e7accadb 536 }
66a7748d 537 return messageToSend
e7accadb
JB
538 }
539
66a7748d 540 private cacheRequestPromise (
82fa1110 541 chargingStation: ChargingStation,
82fa1110
JB
542 messageId: string,
543 messagePayload: JsonType,
544 commandName: RequestCommand | IncomingRequestCommand,
54a8fbc7 545 responseCallback: ResponseCallback,
66a7748d 546 errorCallback: ErrorCallback
82fa1110
JB
547 ): void {
548 chargingStation.requests.set(messageId, [
549 responseCallback,
550 errorCallback,
551 commandName,
66a7748d
JB
552 messagePayload
553 ])
82fa1110
JB
554 }
555
ef6fa3fb 556 // eslint-disable-next-line @typescript-eslint/no-unused-vars
e0b0ee21 557 public abstract requestHandler<ReqType extends JsonType, ResType extends JsonType>(
08f130a0 558 chargingStation: ChargingStation,
94a464f9 559 commandName: RequestCommand,
e1d9a0f4 560 // FIXME: should be ReqType
5cc4b63b 561 commandParams?: JsonType,
66a7748d
JB
562 params?: RequestParams
563 ): Promise<ResType>
c0560973 564}