1 // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
3 import type { JSONSchemaType
} from
'ajv';
4 import { secondsToMilliseconds
} from
'date-fns';
6 import { OCPP16ServiceUtils
} from
'./OCPP16ServiceUtils';
11 hasReservationExpired
,
13 } from
'../../../charging-station';
14 import { OCPPError
} from
'../../../exception';
16 type ChangeConfigurationResponse
,
17 ChargingStationEvents
,
18 type ClearChargingProfileResponse
,
21 type GetConfigurationResponse
,
22 type GetDiagnosticsResponse
,
24 OCPP16AuthorizationStatus
,
25 type OCPP16AuthorizeRequest
,
26 type OCPP16AuthorizeResponse
,
27 type OCPP16BootNotificationResponse
,
28 type OCPP16ChangeAvailabilityResponse
,
29 OCPP16ChargePointStatus
,
30 type OCPP16DataTransferResponse
,
31 type OCPP16DiagnosticsStatusNotificationResponse
,
32 type OCPP16FirmwareStatusNotificationResponse
,
33 type OCPP16GetCompositeScheduleResponse
,
34 type OCPP16HeartbeatResponse
,
35 OCPP16IncomingRequestCommand
,
36 type OCPP16MeterValuesRequest
,
37 type OCPP16MeterValuesResponse
,
39 type OCPP16ReserveNowResponse
,
40 OCPP16StandardParametersKey
,
41 type OCPP16StartTransactionRequest
,
42 type OCPP16StartTransactionResponse
,
43 type OCPP16StatusNotificationResponse
,
44 type OCPP16StopTransactionRequest
,
45 type OCPP16StopTransactionResponse
,
46 type OCPP16TriggerMessageResponse
,
47 type OCPP16UpdateFirmwareResponse
,
49 RegistrationStatusEnumType
,
50 ReservationTerminationReason
,
52 type SetChargingProfileResponse
,
53 type UnlockConnectorResponse
,
54 } from
'../../../types';
55 import { Constants
, convertToInt
, isNullOrUndefined
, logger
} from
'../../../utils';
56 import { OCPPResponseService
} from
'../OCPPResponseService';
58 const moduleName
= 'OCPP16ResponseService';
60 export class OCPP16ResponseService
extends OCPPResponseService
{
61 public jsonIncomingRequestResponseSchemas
: Map
<
62 OCPP16IncomingRequestCommand
,
63 JSONSchemaType
<JsonType
>
66 private responseHandlers
: Map
<OCPP16RequestCommand
, ResponseHandler
>;
67 private jsonSchemas
: Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonType
>>;
69 public constructor() {
70 // if (new.target?.name === moduleName) {
71 // throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
73 super(OCPPVersion
.VERSION_16
);
74 this.responseHandlers
= new Map
<OCPP16RequestCommand
, ResponseHandler
>([
76 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
77 this.handleResponseBootNotification
.bind(this) as ResponseHandler
,
79 [OCPP16RequestCommand
.HEARTBEAT
, this.emptyResponseHandler
.bind(this) as ResponseHandler
],
80 [OCPP16RequestCommand
.AUTHORIZE
, this.handleResponseAuthorize
.bind(this) as ResponseHandler
],
82 OCPP16RequestCommand
.START_TRANSACTION
,
83 this.handleResponseStartTransaction
.bind(this) as ResponseHandler
,
86 OCPP16RequestCommand
.STOP_TRANSACTION
,
87 this.handleResponseStopTransaction
.bind(this) as ResponseHandler
,
90 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
91 this.emptyResponseHandler
.bind(this) as ResponseHandler
,
93 [OCPP16RequestCommand
.METER_VALUES
, this.emptyResponseHandler
.bind(this) as ResponseHandler
],
95 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
96 this.emptyResponseHandler
.bind(this) as ResponseHandler
,
98 [OCPP16RequestCommand
.DATA_TRANSFER
, this.emptyResponseHandler
.bind(this) as ResponseHandler
],
100 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
101 this.emptyResponseHandler
.bind(this) as ResponseHandler
,
104 this.jsonSchemas
= new Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonType
>>([
106 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
107 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16BootNotificationResponse
>(
108 'assets/json-schemas/ocpp/1.6/BootNotificationResponse.json',
114 OCPP16RequestCommand
.HEARTBEAT
,
115 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16HeartbeatResponse
>(
116 'assets/json-schemas/ocpp/1.6/HeartbeatResponse.json',
122 OCPP16RequestCommand
.AUTHORIZE
,
123 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16AuthorizeResponse
>(
124 'assets/json-schemas/ocpp/1.6/AuthorizeResponse.json',
130 OCPP16RequestCommand
.START_TRANSACTION
,
131 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StartTransactionResponse
>(
132 'assets/json-schemas/ocpp/1.6/StartTransactionResponse.json',
138 OCPP16RequestCommand
.STOP_TRANSACTION
,
139 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StopTransactionResponse
>(
140 'assets/json-schemas/ocpp/1.6/StopTransactionResponse.json',
146 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
147 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StatusNotificationResponse
>(
148 'assets/json-schemas/ocpp/1.6/StatusNotificationResponse.json',
154 OCPP16RequestCommand
.METER_VALUES
,
155 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16MeterValuesResponse
>(
156 'assets/json-schemas/ocpp/1.6/MeterValuesResponse.json',
162 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
163 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DiagnosticsStatusNotificationResponse
>(
164 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotificationResponse.json',
170 OCPP16RequestCommand
.DATA_TRANSFER
,
171 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DataTransferResponse
>(
172 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
178 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
179 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16FirmwareStatusNotificationResponse
>(
180 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotificationResponse.json',
186 this.jsonIncomingRequestResponseSchemas
= new Map([
188 OCPP16IncomingRequestCommand
.RESET
,
189 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
190 'assets/json-schemas/ocpp/1.6/ResetResponse.json',
196 OCPP16IncomingRequestCommand
.CLEAR_CACHE
,
197 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
198 'assets/json-schemas/ocpp/1.6/ClearCacheResponse.json',
204 OCPP16IncomingRequestCommand
.CHANGE_AVAILABILITY
,
205 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16ChangeAvailabilityResponse
>(
206 'assets/json-schemas/ocpp/1.6/ChangeAvailabilityResponse.json',
212 OCPP16IncomingRequestCommand
.UNLOCK_CONNECTOR
,
213 OCPP16ServiceUtils
.parseJsonSchemaFile
<UnlockConnectorResponse
>(
214 'assets/json-schemas/ocpp/1.6/UnlockConnectorResponse.json',
220 OCPP16IncomingRequestCommand
.GET_CONFIGURATION
,
221 OCPP16ServiceUtils
.parseJsonSchemaFile
<GetConfigurationResponse
>(
222 'assets/json-schemas/ocpp/1.6/GetConfigurationResponse.json',
228 OCPP16IncomingRequestCommand
.CHANGE_CONFIGURATION
,
229 OCPP16ServiceUtils
.parseJsonSchemaFile
<ChangeConfigurationResponse
>(
230 'assets/json-schemas/ocpp/1.6/ChangeConfigurationResponse.json',
236 OCPP16IncomingRequestCommand
.GET_COMPOSITE_SCHEDULE
,
237 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16GetCompositeScheduleResponse
>(
238 'assets/json-schemas/ocpp/1.6/GetCompositeScheduleResponse.json',
244 OCPP16IncomingRequestCommand
.SET_CHARGING_PROFILE
,
245 OCPP16ServiceUtils
.parseJsonSchemaFile
<SetChargingProfileResponse
>(
246 'assets/json-schemas/ocpp/1.6/SetChargingProfileResponse.json',
252 OCPP16IncomingRequestCommand
.CLEAR_CHARGING_PROFILE
,
253 OCPP16ServiceUtils
.parseJsonSchemaFile
<ClearChargingProfileResponse
>(
254 'assets/json-schemas/ocpp/1.6/ClearChargingProfileResponse.json',
260 OCPP16IncomingRequestCommand
.REMOTE_START_TRANSACTION
,
261 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
262 'assets/json-schemas/ocpp/1.6/RemoteStartTransactionResponse.json',
268 OCPP16IncomingRequestCommand
.REMOTE_STOP_TRANSACTION
,
269 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
270 'assets/json-schemas/ocpp/1.6/RemoteStopTransactionResponse.json',
276 OCPP16IncomingRequestCommand
.GET_DIAGNOSTICS
,
277 OCPP16ServiceUtils
.parseJsonSchemaFile
<GetDiagnosticsResponse
>(
278 'assets/json-schemas/ocpp/1.6/GetDiagnosticsResponse.json',
284 OCPP16IncomingRequestCommand
.TRIGGER_MESSAGE
,
285 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16TriggerMessageResponse
>(
286 'assets/json-schemas/ocpp/1.6/TriggerMessageResponse.json',
292 OCPP16IncomingRequestCommand
.DATA_TRANSFER
,
293 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DataTransferResponse
>(
294 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
300 OCPP16IncomingRequestCommand
.UPDATE_FIRMWARE
,
301 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16UpdateFirmwareResponse
>(
302 'assets/json-schemas/ocpp/1.6/UpdateFirmwareResponse.json',
308 OCPP16IncomingRequestCommand
.RESERVE_NOW
,
309 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16ReserveNowResponse
>(
310 'assets/json-schemas/ocpp/1.6/ReserveNowResponse.json',
316 OCPP16IncomingRequestCommand
.CANCEL_RESERVATION
,
317 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
318 'assets/json-schemas/ocpp/1.6/CancelReservationResponse.json',
324 this.validatePayload
= this.validatePayload
.bind(this) as (
325 chargingStation
: ChargingStation
,
326 commandName
: OCPP16RequestCommand
,
331 public async responseHandler
<ReqType
extends JsonType
, ResType
extends JsonType
>(
332 chargingStation
: ChargingStation
,
333 commandName
: OCPP16RequestCommand
,
335 requestPayload
: ReqType
,
338 chargingStation
.isRegistered() === true ||
339 commandName
=== OCPP16RequestCommand
.BOOT_NOTIFICATION
342 this.responseHandlers
.has(commandName
) === true &&
343 OCPP16ServiceUtils
.isRequestCommandSupported(chargingStation
, commandName
) === true
346 this.validatePayload(chargingStation
, commandName
, payload
);
347 await this.responseHandlers
.get(commandName
)!(chargingStation
, payload
, requestPayload
);
350 `${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handle response error:`,
358 ErrorType
.NOT_IMPLEMENTED
,
359 `${commandName} is not implemented to handle response PDU ${JSON.stringify(
370 ErrorType
.SECURITY_ERROR
,
371 `${commandName} cannot be issued to handle response PDU ${JSON.stringify(
375 )} while the charging station is not registered on the central server.`,
382 private validatePayload(
383 chargingStation
: ChargingStation
,
384 commandName
: OCPP16RequestCommand
,
387 if (this.jsonSchemas
.has(commandName
) === true) {
388 return this.validateResponsePayload(
391 this.jsonSchemas
.get(commandName
)!,
396 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`,
401 private handleResponseBootNotification(
402 chargingStation
: ChargingStation
,
403 payload
: OCPP16BootNotificationResponse
,
405 if (payload
.status === RegistrationStatusEnumType
.ACCEPTED
) {
408 OCPP16StandardParametersKey
.HeartbeatInterval
,
409 payload
.interval
.toString(),
411 { overwrite
: true, save
: true },
415 OCPP16StandardParametersKey
.HeartBeatInterval
,
416 payload
.interval
.toString(),
418 { overwrite
: true, save
: true },
420 OCPP16ServiceUtils
.startHeartbeatInterval(chargingStation
, payload
.interval
);
422 if (Object.values(RegistrationStatusEnumType
).includes(payload
.status)) {
423 const logMsg
= `${chargingStation.logPrefix()} Charging station in '${
425 }' state on the central server`;
426 payload
.status === RegistrationStatusEnumType
.REJECTED
427 ? logger
.warn(logMsg
)
428 : logger
.info(logMsg
);
431 `${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
437 private handleResponseAuthorize(
438 chargingStation
: ChargingStation
,
439 payload
: OCPP16AuthorizeResponse
,
440 requestPayload
: OCPP16AuthorizeRequest
,
442 let authorizeConnectorId
: number | undefined;
443 if (chargingStation
.hasEvses
) {
444 for (const [evseId
, evseStatus
] of chargingStation
.evses
) {
446 for (const [connectorId
, connectorStatus
] of evseStatus
.connectors
) {
447 if (connectorStatus
?.authorizeIdTag
=== requestPayload
.idTag
) {
448 authorizeConnectorId
= connectorId
;
455 for (const connectorId
of chargingStation
.connectors
.keys()) {
458 chargingStation
.getConnectorStatus(connectorId
)?.authorizeIdTag
=== requestPayload
.idTag
460 authorizeConnectorId
= connectorId
;
465 const authorizeConnectorStatus
= chargingStation
.getConnectorStatus(authorizeConnectorId
!);
466 const authorizeConnectorIdDefined
= !isNullOrUndefined(authorizeConnectorId
);
467 if (payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
468 if (authorizeConnectorIdDefined
) {
469 // authorizeConnectorStatus!.authorizeIdTag = requestPayload.idTag;
470 authorizeConnectorStatus
!.idTagAuthorized
= true;
473 `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' accepted${
474 authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}
` : ''
478 if (authorizeConnectorIdDefined
) {
479 authorizeConnectorStatus
!.idTagAuthorized
= false;
480 delete authorizeConnectorStatus
?.authorizeIdTag
;
483 `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' rejected with status '${
484 payload.idTagInfo.status
485 }'${authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}` : ''}`,
490 private async handleResponseStartTransaction(
491 chargingStation: ChargingStation,
492 payload: OCPP16StartTransactionResponse,
493 requestPayload: OCPP16StartTransactionRequest,
495 const { connectorId } = requestPayload;
496 if (connectorId === 0 || chargingStation.hasConnector(connectorId) === false) {
498 `${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector id ${connectorId}
`,
502 const connectorStatus = chargingStation.getConnectorStatus(connectorId);
504 connectorStatus?.transactionRemoteStarted === true &&
505 chargingStation.getAuthorizeRemoteTxRequests() === true &&
506 chargingStation.getLocalAuthListEnabled() === true &&
507 chargingStation.hasIdTags() === true &&
508 connectorStatus?.idTagLocalAuthorized === false
511 `${chargingStation.logPrefix()} Trying to start a transaction
with a not local authorized idTag ${connectorStatus?.localAuthorizeIdTag} on connector id ${connectorId}
`,
513 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
517 connectorStatus?.transactionRemoteStarted === true &&
518 chargingStation.getAuthorizeRemoteTxRequests() === true &&
519 chargingStation.stationInfo?.remoteAuthorization === true &&
520 connectorStatus?.idTagLocalAuthorized === false &&
521 connectorStatus?.idTagAuthorized === false
524 `${chargingStation.logPrefix()} Trying to start a transaction
with a not authorized idTag ${connectorStatus?.authorizeIdTag} on connector id ${connectorId}
`,
526 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
530 connectorStatus?.idTagAuthorized &&
531 connectorStatus?.authorizeIdTag !== requestPayload.idTag
534 `${chargingStation.logPrefix()} Trying to start a transaction
with an idTag $
{
536 } different from the authorize request one ${connectorStatus?.authorizeIdTag} on connector id ${connectorId}
`,
538 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
542 connectorStatus?.idTagLocalAuthorized &&
543 connectorStatus?.localAuthorizeIdTag !== requestPayload.idTag
546 `${chargingStation.logPrefix()} Trying to start a transaction
with an idTag $
{
548 } different from the local authorized one ${connectorStatus?.localAuthorizeIdTag} on connector id ${connectorId}
`,
550 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
553 if (connectorStatus?.transactionStarted === true) {
555 `${chargingStation.logPrefix()} Trying to start a transaction on an already used connector id ${connectorId} by idTag ${connectorStatus?.transactionIdTag}
`,
559 if (chargingStation.hasEvses) {
560 for (const [evseId, evseStatus] of chargingStation.evses) {
561 if (evseStatus.connectors.size > 1) {
562 for (const [id, status] of evseStatus.connectors) {
563 if (id !== connectorId && status?.transactionStarted === true) {
565 `${chargingStation.logPrefix()} Trying to start a transaction on an already used evse id ${evseId} by connector id ${id}
with idTag ${status?.transactionIdTag}
`,
567 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
575 connectorStatus?.status !== OCPP16ChargePointStatus.Available &&
576 connectorStatus?.status !== OCPP16ChargePointStatus.Preparing
579 `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId}
with status ${connectorStatus?.status}
`,
583 if (!Number.isSafeInteger(payload.transactionId)) {
585 `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId}
with a non integer transaction id $
{
586 payload
.transactionId
587 }, converting to integer
`,
589 payload.transactionId = convertToInt(payload.transactionId);
592 if (payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
593 connectorStatus.transactionStarted = true;
594 connectorStatus.transactionStart = requestPayload.timestamp;
595 connectorStatus.transactionId = payload.transactionId;
596 connectorStatus.transactionIdTag = requestPayload.idTag;
597 connectorStatus.transactionEnergyActiveImportRegisterValue = 0;
598 connectorStatus.transactionBeginMeterValue =
599 OCPP16ServiceUtils.buildTransactionBeginMeterValue(
602 requestPayload.meterStart,
604 if (requestPayload.reservationId) {
605 const reservation = chargingStation.getReservationBy(
607 requestPayload.reservationId,
609 if (reservation.idTag !== requestPayload.idTag) {
611 `${chargingStation.logPrefix()} Reserved transaction $
{
612 payload
.transactionId
613 } started
with a different idTag ${requestPayload.idTag} than the reservation one $
{
618 if (hasReservationExpired(reservation)) {
620 `${chargingStation.logPrefix()} Reserved transaction $
{
621 payload
.transactionId
622 } started
with expired reservation $
{
623 requestPayload
.reservationId
624 } (expiry date
: ${reservation.expiryDate.toISOString()}
))`,
627 await chargingStation.removeReservation(
629 ReservationTerminationReason.TRANSACTION_STARTED,
632 chargingStation.stationInfo?.beginEndMeterValues &&
633 (await chargingStation.ocppRequestService.requestHandler<
634 OCPP16MeterValuesRequest,
635 OCPP16MeterValuesResponse
636 >(chargingStation, OCPP16RequestCommand.METER_VALUES, {
638 transactionId: payload.transactionId,
639 meterValue: [connectorStatus.transactionBeginMeterValue],
640 } as OCPP16MeterValuesRequest));
641 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
644 OCPP16ChargePointStatus.Charging,
647 `${chargingStation.logPrefix()} Transaction
with id ${payload.transactionId} STARTED on $
{
648 chargingStation
.stationInfo
.chargingStationId
649 }#${connectorId}
for idTag
'${requestPayload.idTag}'`,
651 if (chargingStation.stationInfo.powerSharedByConnectors) {
652 ++chargingStation.powerDivider;
654 const configuredMeterValueSampleInterval = getConfigurationKey(
656 OCPP16StandardParametersKey.MeterValueSampleInterval,
658 chargingStation.startMeterValues(
660 configuredMeterValueSampleInterval
661 ? secondsToMilliseconds(convertToInt(configuredMeterValueSampleInterval.value))
662 : Constants.DEFAULT_METER_VALUES_INTERVAL,
666 `${chargingStation.logPrefix()} Starting transaction
with id $
{
667 payload
.transactionId
669 chargingStation
.stationInfo
.chargingStationId
670 }#${connectorId}
with status '${payload.idTagInfo?.status}', idTag
'${
673 OCPP16ServiceUtils
.hasReservation(chargingStation
, connectorId
, requestPayload
.idTag
)
674 ? `, reservationId '${requestPayload.reservationId}'`
678 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
682 private async resetConnectorOnStartTransactionError(
683 chargingStation: ChargingStation,
686 const connectorStatus = chargingStation.getConnectorStatus(connectorId);
687 resetConnectorStatus(connectorStatus!);
688 chargingStation.stopMeterValues(connectorId);
689 if (connectorStatus?.status !== OCPP16ChargePointStatus.Available) {
690 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
693 OCPP16ChargePointStatus.Available,
696 chargingStation.emit(ChargingStationEvents.updated);
699 private async handleResponseStopTransaction(
700 chargingStation: ChargingStation,
701 payload: OCPP16StopTransactionResponse,
702 requestPayload: OCPP16StopTransactionRequest,
704 const transactionConnectorId = chargingStation.getConnectorIdByTransactionId(
705 requestPayload.transactionId,
707 if (isNullOrUndefined(transactionConnectorId)) {
709 `${chargingStation.logPrefix()} Trying to stop a non existing transaction
with id $
{
710 requestPayload
.transactionId
715 chargingStation.stationInfo?.beginEndMeterValues === true &&
716 chargingStation.stationInfo?.ocppStrictCompliance === false &&
717 chargingStation.stationInfo?.outOfOrderEndMeterValues === true &&
718 (await chargingStation.ocppRequestService.requestHandler<
719 OCPP16MeterValuesRequest,
720 OCPP16MeterValuesResponse
721 >(chargingStation, OCPP16RequestCommand.METER_VALUES, {
722 connectorId: transactionConnectorId,
723 transactionId: requestPayload.transactionId,
725 OCPP16ServiceUtils.buildTransactionEndMeterValue(
727 transactionConnectorId!,
728 requestPayload.meterStop,
733 chargingStation.isChargingStationAvailable() === false ||
734 chargingStation.isConnectorAvailable(transactionConnectorId!) === false
736 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
738 transactionConnectorId!,
739 OCPP16ChargePointStatus.Unavailable,
742 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
744 transactionConnectorId!,
745 OCPP16ChargePointStatus.Available,
748 if (chargingStation.stationInfo.powerSharedByConnectors) {
749 chargingStation.powerDivider--;
751 resetConnectorStatus(chargingStation.getConnectorStatus(transactionConnectorId!)!);
752 chargingStation.stopMeterValues(transactionConnectorId!);
753 chargingStation.emit(ChargingStationEvents.updated);
754 const logMsg = `${chargingStation.logPrefix()} Transaction
with id $
{
755 requestPayload
.transactionId
757 chargingStation
.stationInfo
.chargingStationId
758 }#${transactionConnectorId}
with status '${payload.idTagInfo?.status}'`;
760 isNullOrUndefined(payload.idTagInfo) ||
761 payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED