Validate response PDU (#137)
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16ResponseService.ts
1 // Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
2
3 import fs from 'fs';
4 import path from 'path';
5 import { fileURLToPath } from 'url';
6
7 import { JSONSchemaType } from 'ajv';
8
9 import OCPPError from '../../../exception/OCPPError';
10 import { JsonType } from '../../../types/JsonType';
11 import { OCPP16ChargePointErrorCode } from '../../../types/ocpp/1.6/ChargePointErrorCode';
12 import { OCPP16ChargePointStatus } from '../../../types/ocpp/1.6/ChargePointStatus';
13 import { OCPP16StandardParametersKey } from '../../../types/ocpp/1.6/Configuration';
14 import {
15 OCPP16MeterValuesRequest,
16 OCPP16MeterValuesResponse,
17 } from '../../../types/ocpp/1.6/MeterValues';
18 import {
19 OCPP16BootNotificationRequest,
20 OCPP16RequestCommand,
21 OCPP16StatusNotificationRequest,
22 } from '../../../types/ocpp/1.6/Requests';
23 import {
24 OCPP16BootNotificationResponse,
25 OCPP16HeartbeatResponse,
26 OCPP16RegistrationStatus,
27 OCPP16StatusNotificationResponse,
28 } from '../../../types/ocpp/1.6/Responses';
29 import {
30 OCPP16AuthorizationStatus,
31 OCPP16AuthorizeRequest,
32 OCPP16AuthorizeResponse,
33 OCPP16StartTransactionRequest,
34 OCPP16StartTransactionResponse,
35 OCPP16StopTransactionRequest,
36 OCPP16StopTransactionResponse,
37 } from '../../../types/ocpp/1.6/Transaction';
38 import { ErrorType } from '../../../types/ocpp/ErrorType';
39 import { ResponseHandler } from '../../../types/ocpp/Responses';
40 import logger from '../../../utils/Logger';
41 import Utils from '../../../utils/Utils';
42 import type ChargingStation from '../../ChargingStation';
43 import { ChargingStationConfigurationUtils } from '../../ChargingStationConfigurationUtils';
44 import { ChargingStationUtils } from '../../ChargingStationUtils';
45 import OCPPResponseService from '../OCPPResponseService';
46 import { OCPP16ServiceUtils } from './OCPP16ServiceUtils';
47
48 const moduleName = 'OCPP16ResponseService';
49
50 export default class OCPP16ResponseService extends OCPPResponseService {
51 private responseHandlers: Map<OCPP16RequestCommand, ResponseHandler>;
52 private bootNotificationResponseJsonSchema: JSONSchemaType<OCPP16BootNotificationResponse>;
53 private heartbeatResponseJsonSchema: JSONSchemaType<OCPP16HeartbeatResponse>;
54 private authorizeResponseJsonSchema: JSONSchemaType<OCPP16AuthorizeResponse>;
55 private startTransactionResponseJsonSchema: JSONSchemaType<OCPP16StartTransactionResponse>;
56 private stopTransactionResponseJsonSchema: JSONSchemaType<OCPP16StopTransactionResponse>;
57 private statusNotificationResponseJsonSchema: JSONSchemaType<OCPP16StatusNotificationResponse>;
58 private meterValuesResponseJsonSchema: JSONSchemaType<OCPP16MeterValuesResponse>;
59
60 public constructor() {
61 if (new.target?.name === moduleName) {
62 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
63 }
64 super();
65 this.responseHandlers = new Map<OCPP16RequestCommand, ResponseHandler>([
66 [OCPP16RequestCommand.BOOT_NOTIFICATION, this.handleResponseBootNotification.bind(this)],
67 [OCPP16RequestCommand.HEARTBEAT, this.handleResponseHeartbeat.bind(this)],
68 [OCPP16RequestCommand.AUTHORIZE, this.handleResponseAuthorize.bind(this)],
69 [OCPP16RequestCommand.START_TRANSACTION, this.handleResponseStartTransaction.bind(this)],
70 [OCPP16RequestCommand.STOP_TRANSACTION, this.handleResponseStopTransaction.bind(this)],
71 [OCPP16RequestCommand.STATUS_NOTIFICATION, this.handleResponseStatusNotification.bind(this)],
72 [OCPP16RequestCommand.METER_VALUES, this.handleResponseMeterValues.bind(this)],
73 ]);
74 this.bootNotificationResponseJsonSchema = JSON.parse(
75 fs.readFileSync(
76 path.resolve(
77 path.dirname(fileURLToPath(import.meta.url)),
78 '../../../assets/json-schemas/ocpp/1.6/BootNotificationResponse.json'
79 ),
80 'utf8'
81 )
82 ) as JSONSchemaType<OCPP16BootNotificationResponse>;
83 this.heartbeatResponseJsonSchema = JSON.parse(
84 fs.readFileSync(
85 path.resolve(
86 path.dirname(fileURLToPath(import.meta.url)),
87 '../../../assets/json-schemas/ocpp/1.6/HeartbeatResponse.json'
88 ),
89 'utf8'
90 )
91 ) as JSONSchemaType<OCPP16HeartbeatResponse>;
92 this.authorizeResponseJsonSchema = JSON.parse(
93 fs.readFileSync(
94 path.resolve(
95 path.dirname(fileURLToPath(import.meta.url)),
96 '../../../assets/json-schemas/ocpp/1.6/AuthorizeResponse.json'
97 ),
98 'utf8'
99 )
100 ) as JSONSchemaType<OCPP16AuthorizeResponse>;
101 this.startTransactionResponseJsonSchema = JSON.parse(
102 fs.readFileSync(
103 path.resolve(
104 path.dirname(fileURLToPath(import.meta.url)),
105 '../../../assets/json-schemas/ocpp/1.6/StartTransactionResponse.json'
106 ),
107 'utf8'
108 )
109 ) as JSONSchemaType<OCPP16StartTransactionResponse>;
110 this.stopTransactionResponseJsonSchema = JSON.parse(
111 fs.readFileSync(
112 path.resolve(
113 path.dirname(fileURLToPath(import.meta.url)),
114 '../../../assets/json-schemas/ocpp/1.6/StopTransactionResponse.json'
115 ),
116 'utf8'
117 )
118 ) as JSONSchemaType<OCPP16StopTransactionResponse>;
119 this.statusNotificationResponseJsonSchema = JSON.parse(
120 fs.readFileSync(
121 path.resolve(
122 path.dirname(fileURLToPath(import.meta.url)),
123 '../../../assets/json-schemas/ocpp/1.6/StatusNotificationResponse.json'
124 ),
125 'utf8'
126 )
127 ) as JSONSchemaType<OCPP16StatusNotificationResponse>;
128 this.meterValuesResponseJsonSchema = JSON.parse(
129 fs.readFileSync(
130 path.resolve(
131 path.dirname(fileURLToPath(import.meta.url)),
132 '../../../assets/json-schemas/ocpp/1.6/MeterValuesResponse.json'
133 ),
134 'utf8'
135 )
136 ) as JSONSchemaType<OCPP16MeterValuesResponse>;
137 }
138
139 public async responseHandler(
140 chargingStation: ChargingStation,
141 commandName: OCPP16RequestCommand,
142 payload: JsonType,
143 requestPayload: JsonType
144 ): Promise<void> {
145 if (chargingStation.isRegistered() || commandName === OCPP16RequestCommand.BOOT_NOTIFICATION) {
146 if (
147 this.responseHandlers.has(commandName) &&
148 ChargingStationUtils.isRequestCommandSupported(commandName, chargingStation)
149 ) {
150 try {
151 await this.responseHandlers.get(commandName)(chargingStation, payload, requestPayload);
152 } catch (error) {
153 logger.error(chargingStation.logPrefix() + ' Handle request response error: %j', error);
154 throw error;
155 }
156 } else {
157 // Throw exception
158 throw new OCPPError(
159 ErrorType.NOT_IMPLEMENTED,
160 `${commandName} is not implemented to handle request response PDU ${JSON.stringify(
161 payload,
162 null,
163 2
164 )}`,
165 commandName,
166 payload
167 );
168 }
169 } else {
170 throw new OCPPError(
171 ErrorType.SECURITY_ERROR,
172 `${commandName} cannot be issued to handle request response PDU ${JSON.stringify(
173 payload,
174 null,
175 2
176 )} while the charging station is not registered on the central server. `,
177 commandName,
178 payload
179 );
180 }
181 }
182
183 private handleResponseBootNotification(
184 chargingStation: ChargingStation,
185 payload: OCPP16BootNotificationResponse
186 ): void {
187 this.validateResponsePayload(
188 chargingStation,
189 OCPP16RequestCommand.BOOT_NOTIFICATION,
190 this.bootNotificationResponseJsonSchema,
191 payload
192 );
193 if (payload.status === OCPP16RegistrationStatus.ACCEPTED) {
194 ChargingStationConfigurationUtils.addConfigurationKey(
195 chargingStation,
196 OCPP16StandardParametersKey.HeartbeatInterval,
197 payload.interval.toString(),
198 {},
199 { overwrite: true, save: true }
200 );
201 ChargingStationConfigurationUtils.addConfigurationKey(
202 chargingStation,
203 OCPP16StandardParametersKey.HeartBeatInterval,
204 payload.interval.toString(),
205 { visible: false },
206 { overwrite: true, save: true }
207 );
208 chargingStation.heartbeatSetInterval
209 ? chargingStation.restartHeartbeat()
210 : chargingStation.startHeartbeat();
211 }
212 if (Object.values(OCPP16RegistrationStatus).includes(payload.status)) {
213 const logMsg = `${chargingStation.logPrefix()} Charging station in '${
214 payload.status
215 }' state on the central server`;
216 payload.status === OCPP16RegistrationStatus.REJECTED
217 ? logger.warn(logMsg)
218 : logger.info(logMsg);
219 } else {
220 logger.error(
221 chargingStation.logPrefix() +
222 ' Charging station boot notification response received: %j with undefined registration status',
223 payload
224 );
225 }
226 }
227
228 private handleResponseHeartbeat(
229 chargingStation: ChargingStation,
230 payload: OCPP16HeartbeatResponse
231 ): void {
232 this.validateResponsePayload(
233 chargingStation,
234 OCPP16RequestCommand.HEARTBEAT,
235 this.heartbeatResponseJsonSchema,
236 payload
237 );
238 }
239
240 private handleResponseAuthorize(
241 chargingStation: ChargingStation,
242 payload: OCPP16AuthorizeResponse,
243 requestPayload: OCPP16AuthorizeRequest
244 ): void {
245 this.validateResponsePayload(
246 chargingStation,
247 OCPP16RequestCommand.AUTHORIZE,
248 this.authorizeResponseJsonSchema,
249 payload
250 );
251 let authorizeConnectorId: number;
252 for (const connectorId of chargingStation.connectors.keys()) {
253 if (
254 connectorId > 0 &&
255 chargingStation.getConnectorStatus(connectorId)?.authorizeIdTag === requestPayload.idTag
256 ) {
257 authorizeConnectorId = connectorId;
258 break;
259 }
260 }
261 if (payload.idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED) {
262 chargingStation.getConnectorStatus(authorizeConnectorId).idTagAuthorized = true;
263 logger.debug(
264 `${chargingStation.logPrefix()} IdTag ${
265 requestPayload.idTag
266 } authorized on connector ${authorizeConnectorId}`
267 );
268 } else {
269 chargingStation.getConnectorStatus(authorizeConnectorId).idTagAuthorized = false;
270 delete chargingStation.getConnectorStatus(authorizeConnectorId).authorizeIdTag;
271 logger.debug(
272 `${chargingStation.logPrefix()} IdTag ${requestPayload.idTag} refused with status '${
273 payload.idTagInfo.status
274 }' on connector ${authorizeConnectorId}`
275 );
276 }
277 }
278
279 private async handleResponseStartTransaction(
280 chargingStation: ChargingStation,
281 payload: OCPP16StartTransactionResponse,
282 requestPayload: OCPP16StartTransactionRequest
283 ): Promise<void> {
284 this.validateResponsePayload(
285 chargingStation,
286 OCPP16RequestCommand.START_TRANSACTION,
287 this.startTransactionResponseJsonSchema,
288 payload
289 );
290 const connectorId = requestPayload.connectorId;
291
292 let transactionConnectorId: number;
293 for (const id of chargingStation.connectors.keys()) {
294 if (id > 0 && id === connectorId) {
295 transactionConnectorId = id;
296 break;
297 }
298 }
299 if (!transactionConnectorId) {
300 logger.error(
301 chargingStation.logPrefix() +
302 ' Trying to start a transaction on a non existing connector Id ' +
303 connectorId.toString()
304 );
305 return;
306 }
307 if (
308 chargingStation.getConnectorStatus(connectorId).transactionRemoteStarted &&
309 chargingStation.getAuthorizeRemoteTxRequests() &&
310 chargingStation.getLocalAuthListEnabled() &&
311 chargingStation.hasAuthorizedTags() &&
312 !chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized
313 ) {
314 logger.error(
315 chargingStation.logPrefix() +
316 ' Trying to start a transaction with a not local authorized idTag ' +
317 chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag +
318 ' on connector Id ' +
319 connectorId.toString()
320 );
321 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
322 return;
323 }
324 if (
325 chargingStation.getConnectorStatus(connectorId).transactionRemoteStarted &&
326 chargingStation.getAuthorizeRemoteTxRequests() &&
327 chargingStation.getMayAuthorizeAtRemoteStart() &&
328 !chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized &&
329 !chargingStation.getConnectorStatus(connectorId).idTagAuthorized
330 ) {
331 logger.error(
332 chargingStation.logPrefix() +
333 ' Trying to start a transaction with a not authorized idTag ' +
334 chargingStation.getConnectorStatus(connectorId).authorizeIdTag +
335 ' on connector Id ' +
336 connectorId.toString()
337 );
338 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
339 return;
340 }
341 if (
342 chargingStation.getConnectorStatus(connectorId).idTagAuthorized &&
343 chargingStation.getConnectorStatus(connectorId).authorizeIdTag !== requestPayload.idTag
344 ) {
345 logger.error(
346 chargingStation.logPrefix() +
347 ' Trying to start a transaction with an idTag ' +
348 requestPayload.idTag +
349 ' different from the authorize request one ' +
350 chargingStation.getConnectorStatus(connectorId).authorizeIdTag +
351 ' on connector Id ' +
352 connectorId.toString()
353 );
354 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
355 return;
356 }
357 if (
358 chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized &&
359 chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag !== requestPayload.idTag
360 ) {
361 logger.error(
362 chargingStation.logPrefix() +
363 ' Trying to start a transaction with an idTag ' +
364 requestPayload.idTag +
365 ' different from the local authorized one ' +
366 chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag +
367 ' on connector Id ' +
368 connectorId.toString()
369 );
370 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
371 return;
372 }
373 if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted) {
374 logger.debug(
375 chargingStation.logPrefix() +
376 ' Trying to start a transaction on an already used connector ' +
377 connectorId.toString() +
378 ': %j',
379 chargingStation.getConnectorStatus(connectorId)
380 );
381 return;
382 }
383 if (
384 chargingStation.getConnectorStatus(connectorId)?.status !==
385 OCPP16ChargePointStatus.AVAILABLE &&
386 chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.PREPARING
387 ) {
388 logger.error(
389 `${chargingStation.logPrefix()} Trying to start a transaction on connector ${connectorId.toString()} with status ${
390 chargingStation.getConnectorStatus(connectorId)?.status
391 }`
392 );
393 return;
394 }
395 if (!Number.isInteger(payload.transactionId)) {
396 logger.warn(
397 `${chargingStation.logPrefix()} Trying to start a transaction on connector ${connectorId.toString()} with a non integer transaction Id ${
398 payload.transactionId
399 }, converting to integer`
400 );
401 payload.transactionId = Utils.convertToInt(payload.transactionId);
402 }
403
404 if (payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
405 chargingStation.getConnectorStatus(connectorId).transactionStarted = true;
406 chargingStation.getConnectorStatus(connectorId).transactionId = payload.transactionId;
407 chargingStation.getConnectorStatus(connectorId).transactionIdTag = requestPayload.idTag;
408 chargingStation.getConnectorStatus(
409 connectorId
410 ).transactionEnergyActiveImportRegisterValue = 0;
411 chargingStation.getConnectorStatus(connectorId).transactionBeginMeterValue =
412 OCPP16ServiceUtils.buildTransactionBeginMeterValue(
413 chargingStation,
414 connectorId,
415 requestPayload.meterStart
416 );
417 chargingStation.getBeginEndMeterValues() &&
418 (await chargingStation.ocppRequestService.requestHandler<
419 OCPP16MeterValuesRequest,
420 OCPP16MeterValuesResponse
421 >(chargingStation, OCPP16RequestCommand.METER_VALUES, {
422 connectorId,
423 transactionId: payload.transactionId,
424 meterValue: [chargingStation.getConnectorStatus(connectorId).transactionBeginMeterValue],
425 }));
426 await chargingStation.ocppRequestService.requestHandler<
427 OCPP16StatusNotificationRequest,
428 OCPP16StatusNotificationResponse
429 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
430 connectorId,
431 status: OCPP16ChargePointStatus.CHARGING,
432 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
433 });
434 chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.CHARGING;
435 logger.info(
436 chargingStation.logPrefix() +
437 ' Transaction ' +
438 payload.transactionId.toString() +
439 ' STARTED on ' +
440 chargingStation.stationInfo.chargingStationId +
441 '#' +
442 connectorId.toString() +
443 ' for idTag ' +
444 requestPayload.idTag
445 );
446 if (chargingStation.stationInfo.powerSharedByConnectors) {
447 chargingStation.powerDivider++;
448 }
449 const configuredMeterValueSampleInterval =
450 ChargingStationConfigurationUtils.getConfigurationKey(
451 chargingStation,
452 OCPP16StandardParametersKey.MeterValueSampleInterval
453 );
454 chargingStation.startMeterValues(
455 connectorId,
456 configuredMeterValueSampleInterval
457 ? Utils.convertToInt(configuredMeterValueSampleInterval.value) * 1000
458 : 60000
459 );
460 } else {
461 logger.warn(
462 chargingStation.logPrefix() +
463 ' Starting transaction id ' +
464 payload.transactionId.toString() +
465 " REJECTED with status '" +
466 payload?.idTagInfo?.status +
467 "', idTag " +
468 requestPayload.idTag
469 );
470 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
471 }
472 }
473
474 private async resetConnectorOnStartTransactionError(
475 chargingStation: ChargingStation,
476 connectorId: number
477 ): Promise<void> {
478 chargingStation.resetConnectorStatus(connectorId);
479 if (
480 chargingStation.getConnectorStatus(connectorId).status !== OCPP16ChargePointStatus.AVAILABLE
481 ) {
482 await chargingStation.ocppRequestService.requestHandler<
483 OCPP16StatusNotificationRequest,
484 OCPP16StatusNotificationResponse
485 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
486 connectorId,
487 status: OCPP16ChargePointStatus.AVAILABLE,
488 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
489 });
490 chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.AVAILABLE;
491 }
492 }
493
494 private async handleResponseStopTransaction(
495 chargingStation: ChargingStation,
496 payload: OCPP16StopTransactionResponse,
497 requestPayload: OCPP16StopTransactionRequest
498 ): Promise<void> {
499 this.validateResponsePayload(
500 chargingStation,
501 OCPP16RequestCommand.STOP_TRANSACTION,
502 this.stopTransactionResponseJsonSchema,
503 payload
504 );
505 const transactionConnectorId = chargingStation.getConnectorIdByTransactionId(
506 requestPayload.transactionId
507 );
508 if (!transactionConnectorId) {
509 logger.error(
510 chargingStation.logPrefix() +
511 ' Trying to stop a non existing transaction ' +
512 requestPayload.transactionId.toString()
513 );
514 return;
515 }
516 if (payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
517 chargingStation.getBeginEndMeterValues() &&
518 !chargingStation.getOcppStrictCompliance() &&
519 chargingStation.getOutOfOrderEndMeterValues() &&
520 (await chargingStation.ocppRequestService.requestHandler<
521 OCPP16MeterValuesRequest,
522 OCPP16MeterValuesResponse
523 >(chargingStation, OCPP16RequestCommand.METER_VALUES, {
524 connectorId: transactionConnectorId,
525 transactionId: requestPayload.transactionId,
526 meterValue: [
527 OCPP16ServiceUtils.buildTransactionEndMeterValue(
528 chargingStation,
529 transactionConnectorId,
530 requestPayload.meterStop
531 ),
532 ],
533 }));
534 if (
535 !chargingStation.isChargingStationAvailable() ||
536 !chargingStation.isConnectorAvailable(transactionConnectorId)
537 ) {
538 await chargingStation.ocppRequestService.requestHandler<
539 OCPP16StatusNotificationRequest,
540 OCPP16StatusNotificationResponse
541 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
542 connectorId: transactionConnectorId,
543 status: OCPP16ChargePointStatus.UNAVAILABLE,
544 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
545 });
546 chargingStation.getConnectorStatus(transactionConnectorId).status =
547 OCPP16ChargePointStatus.UNAVAILABLE;
548 } else {
549 await chargingStation.ocppRequestService.requestHandler<
550 OCPP16BootNotificationRequest,
551 OCPP16BootNotificationResponse
552 >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, {
553 connectorId: transactionConnectorId,
554 status: OCPP16ChargePointStatus.AVAILABLE,
555 errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
556 });
557 chargingStation.getConnectorStatus(transactionConnectorId).status =
558 OCPP16ChargePointStatus.AVAILABLE;
559 }
560 if (chargingStation.stationInfo.powerSharedByConnectors) {
561 chargingStation.powerDivider--;
562 }
563 logger.info(
564 chargingStation.logPrefix() +
565 ' Transaction ' +
566 requestPayload.transactionId.toString() +
567 ' STOPPED on ' +
568 chargingStation.stationInfo.chargingStationId +
569 '#' +
570 transactionConnectorId.toString()
571 );
572 chargingStation.resetConnectorStatus(transactionConnectorId);
573 } else {
574 logger.warn(
575 chargingStation.logPrefix() +
576 ' Stopping transaction id ' +
577 requestPayload.transactionId.toString() +
578 " REJECTED with status '" +
579 payload.idTagInfo?.status +
580 "'"
581 );
582 }
583 }
584
585 private handleResponseStatusNotification(
586 chargingStation: ChargingStation,
587 payload: OCPP16StatusNotificationResponse
588 ): void {
589 this.validateResponsePayload(
590 chargingStation,
591 OCPP16RequestCommand.STATUS_NOTIFICATION,
592 this.statusNotificationResponseJsonSchema,
593 payload
594 );
595 }
596
597 private handleResponseMeterValues(
598 chargingStation: ChargingStation,
599 payload: OCPP16MeterValuesResponse
600 ): void {
601 this.validateResponsePayload(
602 chargingStation,
603 OCPP16RequestCommand.METER_VALUES,
604 this.meterValuesResponseJsonSchema,
605 payload
606 );
607 }
608 }