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