1 // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
3 import type { ValidateFunction
} from
'ajv'
4 import { secondsToMilliseconds
} from
'date-fns'
10 hasReservationExpired
,
12 } from
'../../../charging-station/index.js'
13 import { OCPPError
} from
'../../../exception/index.js'
15 type ChangeConfigurationResponse
,
16 ChargingStationEvents
,
19 type GetConfigurationResponse
,
20 type GetDiagnosticsResponse
,
22 OCPP16AuthorizationStatus
,
23 type OCPP16AuthorizeRequest
,
24 type OCPP16AuthorizeResponse
,
25 type OCPP16BootNotificationResponse
,
26 type OCPP16ChangeAvailabilityResponse
,
27 OCPP16ChargePointStatus
,
28 type OCPP16ClearChargingProfileResponse
,
29 type OCPP16DataTransferResponse
,
30 type OCPP16DiagnosticsStatusNotificationResponse
,
31 type OCPP16FirmwareStatusNotificationResponse
,
32 type OCPP16GetCompositeScheduleResponse
,
33 type OCPP16HeartbeatResponse
,
34 OCPP16IncomingRequestCommand
,
35 type OCPP16MeterValuesRequest
,
36 type OCPP16MeterValuesResponse
,
38 type OCPP16ReserveNowResponse
,
39 OCPP16StandardParametersKey
,
40 type OCPP16StartTransactionRequest
,
41 type OCPP16StartTransactionResponse
,
42 type OCPP16StatusNotificationResponse
,
43 type OCPP16StopTransactionRequest
,
44 type OCPP16StopTransactionResponse
,
45 type OCPP16TriggerMessageResponse
,
46 type OCPP16UpdateFirmwareResponse
,
48 RegistrationStatusEnumType
,
49 ReservationTerminationReason
,
51 type SetChargingProfileResponse
,
52 type UnlockConnectorResponse
53 } from
'../../../types/index.js'
54 import { Constants
, convertToInt
, isAsyncFunction
, logger
} from
'../../../utils/index.js'
55 import { OCPPResponseService
} from
'../OCPPResponseService.js'
56 import { OCPP16ServiceUtils
} from
'./OCPP16ServiceUtils.js'
58 const moduleName
= 'OCPP16ResponseService'
60 export class OCPP16ResponseService
extends OCPPResponseService
{
61 public incomingRequestResponsePayloadValidateFunctions
: Map
<
62 OCPP16IncomingRequestCommand
,
63 ValidateFunction
<JsonType
>
66 protected payloadValidateFunctions
: Map
<OCPP16RequestCommand
, ValidateFunction
<JsonType
>>
67 private readonly responseHandlers
: Map
<OCPP16RequestCommand
, ResponseHandler
>
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
],
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
],
95 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
96 this.emptyResponseHandler
.bind(this) as ResponseHandler
98 [OCPP16RequestCommand
.DATA_TRANSFER
, this.emptyResponseHandler
],
99 [OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
, this.emptyResponseHandler
]
101 this.payloadValidateFunctions
= new Map
<OCPP16RequestCommand
, ValidateFunction
<JsonType
>>([
103 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
106 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16BootNotificationResponse
>(
107 'assets/json-schemas/ocpp/1.6/BootNotificationResponse.json',
115 OCPP16RequestCommand
.HEARTBEAT
,
118 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16HeartbeatResponse
>(
119 'assets/json-schemas/ocpp/1.6/HeartbeatResponse.json',
127 OCPP16RequestCommand
.AUTHORIZE
,
130 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16AuthorizeResponse
>(
131 'assets/json-schemas/ocpp/1.6/AuthorizeResponse.json',
139 OCPP16RequestCommand
.START_TRANSACTION
,
142 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StartTransactionResponse
>(
143 'assets/json-schemas/ocpp/1.6/StartTransactionResponse.json',
151 OCPP16RequestCommand
.STOP_TRANSACTION
,
154 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StopTransactionResponse
>(
155 'assets/json-schemas/ocpp/1.6/StopTransactionResponse.json',
163 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
166 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StatusNotificationResponse
>(
167 'assets/json-schemas/ocpp/1.6/StatusNotificationResponse.json',
175 OCPP16RequestCommand
.METER_VALUES
,
178 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16MeterValuesResponse
>(
179 'assets/json-schemas/ocpp/1.6/MeterValuesResponse.json',
187 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
190 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DiagnosticsStatusNotificationResponse
>(
191 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotificationResponse.json',
199 OCPP16RequestCommand
.DATA_TRANSFER
,
202 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DataTransferResponse
>(
203 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
211 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
214 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16FirmwareStatusNotificationResponse
>(
215 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotificationResponse.json',
223 this.incomingRequestResponsePayloadValidateFunctions
= new Map
<
224 OCPP16IncomingRequestCommand
,
225 ValidateFunction
<JsonType
>
228 OCPP16IncomingRequestCommand
.RESET
,
229 this.ajvIncomingRequest
231 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
232 'assets/json-schemas/ocpp/1.6/ResetResponse.json',
240 OCPP16IncomingRequestCommand
.CLEAR_CACHE
,
241 this.ajvIncomingRequest
243 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
244 'assets/json-schemas/ocpp/1.6/ClearCacheResponse.json',
252 OCPP16IncomingRequestCommand
.CHANGE_AVAILABILITY
,
253 this.ajvIncomingRequest
255 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16ChangeAvailabilityResponse
>(
256 'assets/json-schemas/ocpp/1.6/ChangeAvailabilityResponse.json',
264 OCPP16IncomingRequestCommand
.UNLOCK_CONNECTOR
,
265 this.ajvIncomingRequest
267 OCPP16ServiceUtils
.parseJsonSchemaFile
<UnlockConnectorResponse
>(
268 'assets/json-schemas/ocpp/1.6/UnlockConnectorResponse.json',
276 OCPP16IncomingRequestCommand
.GET_CONFIGURATION
,
277 this.ajvIncomingRequest
279 OCPP16ServiceUtils
.parseJsonSchemaFile
<GetConfigurationResponse
>(
280 'assets/json-schemas/ocpp/1.6/GetConfigurationResponse.json',
288 OCPP16IncomingRequestCommand
.CHANGE_CONFIGURATION
,
289 this.ajvIncomingRequest
291 OCPP16ServiceUtils
.parseJsonSchemaFile
<ChangeConfigurationResponse
>(
292 'assets/json-schemas/ocpp/1.6/ChangeConfigurationResponse.json',
300 OCPP16IncomingRequestCommand
.GET_COMPOSITE_SCHEDULE
,
301 this.ajvIncomingRequest
303 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16GetCompositeScheduleResponse
>(
304 'assets/json-schemas/ocpp/1.6/GetCompositeScheduleResponse.json',
312 OCPP16IncomingRequestCommand
.SET_CHARGING_PROFILE
,
313 this.ajvIncomingRequest
315 OCPP16ServiceUtils
.parseJsonSchemaFile
<SetChargingProfileResponse
>(
316 'assets/json-schemas/ocpp/1.6/SetChargingProfileResponse.json',
324 OCPP16IncomingRequestCommand
.CLEAR_CHARGING_PROFILE
,
325 this.ajvIncomingRequest
327 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16ClearChargingProfileResponse
>(
328 'assets/json-schemas/ocpp/1.6/ClearChargingProfileResponse.json',
336 OCPP16IncomingRequestCommand
.REMOTE_START_TRANSACTION
,
337 this.ajvIncomingRequest
339 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
340 'assets/json-schemas/ocpp/1.6/RemoteStartTransactionResponse.json',
348 OCPP16IncomingRequestCommand
.REMOTE_STOP_TRANSACTION
,
349 this.ajvIncomingRequest
351 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
352 'assets/json-schemas/ocpp/1.6/RemoteStopTransactionResponse.json',
360 OCPP16IncomingRequestCommand
.GET_DIAGNOSTICS
,
361 this.ajvIncomingRequest
363 OCPP16ServiceUtils
.parseJsonSchemaFile
<GetDiagnosticsResponse
>(
364 'assets/json-schemas/ocpp/1.6/GetDiagnosticsResponse.json',
372 OCPP16IncomingRequestCommand
.TRIGGER_MESSAGE
,
373 this.ajvIncomingRequest
375 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16TriggerMessageResponse
>(
376 'assets/json-schemas/ocpp/1.6/TriggerMessageResponse.json',
384 OCPP16IncomingRequestCommand
.DATA_TRANSFER
,
385 this.ajvIncomingRequest
387 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DataTransferResponse
>(
388 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
396 OCPP16IncomingRequestCommand
.UPDATE_FIRMWARE
,
397 this.ajvIncomingRequest
399 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16UpdateFirmwareResponse
>(
400 'assets/json-schemas/ocpp/1.6/UpdateFirmwareResponse.json',
408 OCPP16IncomingRequestCommand
.RESERVE_NOW
,
409 this.ajvIncomingRequest
411 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16ReserveNowResponse
>(
412 'assets/json-schemas/ocpp/1.6/ReserveNowResponse.json',
420 OCPP16IncomingRequestCommand
.CANCEL_RESERVATION
,
421 this.ajvIncomingRequest
423 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
424 'assets/json-schemas/ocpp/1.6/CancelReservationResponse.json',
432 this.validatePayload
= this.validatePayload
.bind(this)
435 public async responseHandler
<ReqType
extends JsonType
, ResType
extends JsonType
>(
436 chargingStation
: ChargingStation
,
437 commandName
: OCPP16RequestCommand
,
439 requestPayload
: ReqType
441 if (chargingStation
.isRegistered() || commandName
=== OCPP16RequestCommand
.BOOT_NOTIFICATION
) {
443 this.responseHandlers
.has(commandName
) &&
444 OCPP16ServiceUtils
.isRequestCommandSupported(chargingStation
, commandName
)
447 this.validatePayload(chargingStation
, commandName
, payload
)
448 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
449 const responseHandler
= this.responseHandlers
.get(commandName
)!
450 if (isAsyncFunction(responseHandler
)) {
451 await responseHandler(chargingStation
, payload
, requestPayload
)
455 chargingStation
: ChargingStation
,
457 requestPayload
?: JsonType
459 )(chargingStation
, payload
, requestPayload
)
463 `${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handle response error:`,
471 ErrorType
.NOT_IMPLEMENTED
,
472 `'${commandName}' is not implemented to handle response PDU ${JSON.stringify(
483 ErrorType
.SECURITY_ERROR
,
484 `${commandName} cannot be issued to handle response PDU ${JSON.stringify(
488 )} while the charging station is not registered on the central server`,
495 private validatePayload (
496 chargingStation
: ChargingStation
,
497 commandName
: OCPP16RequestCommand
,
500 if (this.payloadValidateFunctions
.has(commandName
)) {
501 return this.validateResponsePayload(chargingStation
, commandName
, payload
)
504 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
509 private handleResponseBootNotification (
510 chargingStation
: ChargingStation
,
511 payload
: OCPP16BootNotificationResponse
513 if (Object.values(RegistrationStatusEnumType
).includes(payload
.status)) {
514 chargingStation
.bootNotificationResponse
= payload
515 if (chargingStation
.isRegistered()) {
516 chargingStation
.emit(ChargingStationEvents
.registered
)
517 if (chargingStation
.inAcceptedState()) {
520 OCPP16StandardParametersKey
.HeartbeatInterval
,
521 payload
.interval
.toString(),
523 { overwrite
: true, save
: true }
527 OCPP16StandardParametersKey
.HeartBeatInterval
,
528 payload
.interval
.toString(),
530 { overwrite
: true, save
: true }
532 chargingStation
.emit(ChargingStationEvents
.accepted
)
534 } else if (chargingStation
.inRejectedState()) {
535 chargingStation
.emit(ChargingStationEvents
.rejected
)
537 const logMsg
= `${chargingStation.logPrefix()} Charging station in '${
539 }' state on the central server`
540 payload
.status === RegistrationStatusEnumType
.REJECTED
541 ? logger
.warn(logMsg
)
542 : logger
.info(logMsg
)
545 `${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
551 private handleResponseAuthorize (
552 chargingStation
: ChargingStation
,
553 payload
: OCPP16AuthorizeResponse
,
554 requestPayload
: OCPP16AuthorizeRequest
556 let authorizeConnectorId
: number | undefined
557 if (chargingStation
.hasEvses
) {
558 for (const [evseId
, evseStatus
] of chargingStation
.evses
) {
560 for (const [connectorId
, connectorStatus
] of evseStatus
.connectors
) {
561 if (connectorStatus
.authorizeIdTag
=== requestPayload
.idTag
) {
562 authorizeConnectorId
= connectorId
569 for (const connectorId
of chargingStation
.connectors
.keys()) {
572 chargingStation
.getConnectorStatus(connectorId
)?.authorizeIdTag
=== requestPayload
.idTag
574 authorizeConnectorId
= connectorId
579 if (authorizeConnectorId
!= null) {
580 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
581 const authorizeConnectorStatus
= chargingStation
.getConnectorStatus(authorizeConnectorId
)!
582 if (payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
583 authorizeConnectorStatus
.idTagAuthorized
= true
585 `${chargingStation.logPrefix()} idTag '${
587 }' accepted on connector id ${authorizeConnectorId}`
590 authorizeConnectorStatus
.idTagAuthorized
= false
591 delete authorizeConnectorStatus
.authorizeIdTag
593 `${chargingStation.logPrefix()} idTag '${
595 }' rejected with status '${payload.idTagInfo.status}'`
600 `${chargingStation.logPrefix()} idTag '${
602 }' has no authorize request pending`
607 private async handleResponseStartTransaction (
608 chargingStation
: ChargingStation
,
609 payload
: OCPP16StartTransactionResponse
,
610 requestPayload
: OCPP16StartTransactionRequest
612 const { connectorId
} = requestPayload
613 if (connectorId
=== 0 || !chargingStation
.hasConnector(connectorId
)) {
615 `${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector id ${connectorId}`
619 const connectorStatus
= chargingStation
.getConnectorStatus(connectorId
)
621 connectorStatus
?.transactionRemoteStarted
=== true &&
622 chargingStation
.getAuthorizeRemoteTxRequests() &&
623 chargingStation
.getLocalAuthListEnabled() &&
624 chargingStation
.hasIdTags() &&
625 connectorStatus
.idTagLocalAuthorized
=== false
628 `${chargingStation.logPrefix()} Trying to start a transaction with a not local authorized idTag ${
629 connectorStatus.localAuthorizeIdTag
630 } on connector id ${connectorId}`
632 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
636 connectorStatus
?.transactionRemoteStarted
=== true &&
637 chargingStation
.getAuthorizeRemoteTxRequests() &&
638 chargingStation
.stationInfo
?.remoteAuthorization
=== true &&
639 connectorStatus
.idTagLocalAuthorized
=== false &&
640 connectorStatus
.idTagAuthorized
=== false
643 `${chargingStation.logPrefix()} Trying to start a transaction with a not authorized idTag ${
644 connectorStatus.authorizeIdTag
645 } on connector id ${connectorId}`
647 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
651 connectorStatus
?.idTagAuthorized
=== true &&
652 connectorStatus
.authorizeIdTag
!== requestPayload
.idTag
655 `${chargingStation.logPrefix()} Trying to start a transaction with an idTag ${
657 } different from the authorize request one ${
658 connectorStatus.authorizeIdTag
659 } on connector id ${connectorId}`
661 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
665 connectorStatus
?.idTagLocalAuthorized
=== true &&
666 connectorStatus
.localAuthorizeIdTag
!== requestPayload
.idTag
669 `${chargingStation.logPrefix()} Trying to start a transaction with an idTag ${
671 } different from the local authorized one ${
672 connectorStatus.localAuthorizeIdTag
673 } on connector id ${connectorId}`
675 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
678 if (connectorStatus
?.transactionStarted
=== true) {
680 `${chargingStation.logPrefix()} Trying to start a transaction on an already used connector id ${connectorId} by idTag ${
681 connectorStatus.transactionIdTag
686 if (chargingStation
.hasEvses
) {
687 for (const [evseId
, evseStatus
] of chargingStation
.evses
) {
688 if (evseStatus
.connectors
.size
> 1) {
689 for (const [id
, status] of evseStatus
.connectors
) {
690 if (id
!== connectorId
&& status.transactionStarted
=== true) {
692 `${chargingStation.logPrefix()} Trying to start a transaction on an already used evse id ${evseId} by connector id ${id} with idTag ${
693 status.transactionIdTag
696 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
704 connectorStatus
?.status !== OCPP16ChargePointStatus
.Available
&&
705 connectorStatus
?.status !== OCPP16ChargePointStatus
.Preparing
708 `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with status ${
709 connectorStatus?.status
714 if (!Number.isSafeInteger(payload
.transactionId
)) {
716 `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with a non integer transaction id ${
717 payload.transactionId
718 }, converting to integer`
720 payload
.transactionId
= convertToInt(payload
.transactionId
)
723 if (payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
724 connectorStatus
.transactionStarted
= true
725 connectorStatus
.transactionStart
= requestPayload
.timestamp
726 connectorStatus
.transactionId
= payload
.transactionId
727 connectorStatus
.transactionIdTag
= requestPayload
.idTag
728 connectorStatus
.transactionEnergyActiveImportRegisterValue
= 0
729 connectorStatus
.transactionBeginMeterValue
=
730 OCPP16ServiceUtils
.buildTransactionBeginMeterValue(
733 requestPayload
.meterStart
735 if (requestPayload
.reservationId
!= null) {
736 const reservation
= chargingStation
.getReservationBy(
738 requestPayload
.reservationId
740 if (reservation
!= null) {
741 if (reservation
.idTag
!== requestPayload
.idTag
) {
743 `${chargingStation.logPrefix()} Reserved transaction ${
744 payload.transactionId
745 } started with a different idTag ${
747 } than the reservation one ${reservation.idTag}`
750 if (hasReservationExpired(reservation
)) {
752 `${chargingStation.logPrefix()} Reserved transaction ${
753 payload.transactionId
754 } started with expired reservation ${
755 requestPayload.reservationId
756 } (expiry date: ${reservation.expiryDate.toISOString()}))`
759 await chargingStation
.removeReservation(
761 ReservationTerminationReason
.TRANSACTION_STARTED
765 `${chargingStation.logPrefix()} Reserved transaction ${
766 payload.transactionId
767 } started with unknown reservation ${requestPayload.reservationId}`
771 chargingStation
.stationInfo
?.beginEndMeterValues
=== true &&
772 (await chargingStation
.ocppRequestService
.requestHandler
<
773 OCPP16MeterValuesRequest
,
774 OCPP16MeterValuesResponse
775 >(chargingStation
, OCPP16RequestCommand
.METER_VALUES
, {
777 transactionId
: payload
.transactionId
,
778 meterValue
: [connectorStatus
.transactionBeginMeterValue
]
779 } satisfies OCPP16MeterValuesRequest
))
780 await OCPP16ServiceUtils
.sendAndSetConnectorStatus(
783 OCPP16ChargePointStatus
.Charging
786 `${chargingStation.logPrefix()} Transaction with id ${payload.transactionId} STARTED on ${
787 chargingStation.stationInfo?.chargingStationId
788 }#${connectorId} for idTag '${requestPayload.idTag}'`
790 if (chargingStation
.stationInfo
?.powerSharedByConnectors
=== true) {
791 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
792 ++chargingStation
.powerDivider
!
794 const configuredMeterValueSampleInterval
= getConfigurationKey(
796 OCPP16StandardParametersKey
.MeterValueSampleInterval
798 chargingStation
.startMeterValues(
800 configuredMeterValueSampleInterval
!= null
801 ? secondsToMilliseconds(convertToInt(configuredMeterValueSampleInterval
.value
))
802 : Constants
.DEFAULT_METER_VALUES_INTERVAL
806 `${chargingStation.logPrefix()} Starting transaction with id ${
807 payload.transactionId
809 chargingStation.stationInfo?.chargingStationId
810 }#${connectorId} with status '${payload.idTagInfo.status}', idTag '${
813 OCPP16ServiceUtils.hasReservation(chargingStation, connectorId, requestPayload.idTag)
814 ? `, reservationId
'${requestPayload.reservationId}'`
818 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
822 private async resetConnectorOnStartTransactionError (
823 chargingStation
: ChargingStation
,
826 chargingStation
.stopMeterValues(connectorId
)
827 const connectorStatus
= chargingStation
.getConnectorStatus(connectorId
)
828 resetConnectorStatus(connectorStatus
)
829 await OCPP16ServiceUtils
.restoreConnectorStatus(chargingStation
, connectorId
, connectorStatus
)
832 private async handleResponseStopTransaction (
833 chargingStation
: ChargingStation
,
834 payload
: OCPP16StopTransactionResponse
,
835 requestPayload
: OCPP16StopTransactionRequest
837 const transactionConnectorId
= chargingStation
.getConnectorIdByTransactionId(
838 requestPayload
.transactionId
840 if (transactionConnectorId
== null) {
842 `${chargingStation.logPrefix()} Trying to stop a non existing transaction with id ${
843 requestPayload.transactionId
848 chargingStation
.stationInfo
?.beginEndMeterValues
=== true &&
849 chargingStation
.stationInfo
.ocppStrictCompliance
=== false &&
850 chargingStation
.stationInfo
.outOfOrderEndMeterValues
=== true &&
851 (await chargingStation
.ocppRequestService
.requestHandler
<
852 OCPP16MeterValuesRequest
,
853 OCPP16MeterValuesResponse
854 >(chargingStation
, OCPP16RequestCommand
.METER_VALUES
, {
855 connectorId
: transactionConnectorId
,
856 transactionId
: requestPayload
.transactionId
,
858 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
860 transactionConnectorId
,
861 requestPayload
.meterStop
866 !chargingStation
.isChargingStationAvailable() ||
867 !chargingStation
.isConnectorAvailable(transactionConnectorId
)
869 await OCPP16ServiceUtils
.sendAndSetConnectorStatus(
871 transactionConnectorId
,
872 OCPP16ChargePointStatus
.Unavailable
875 await OCPP16ServiceUtils
.sendAndSetConnectorStatus(
877 transactionConnectorId
,
878 OCPP16ChargePointStatus
.Available
881 if (chargingStation
.stationInfo
?.powerSharedByConnectors
=== true) {
882 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
883 chargingStation
.powerDivider
!--
885 resetConnectorStatus(chargingStation
.getConnectorStatus(transactionConnectorId
))
886 chargingStation
.stopMeterValues(transactionConnectorId
)
887 const logMsg
= `${chargingStation.logPrefix()} Transaction with id ${
888 requestPayload.transactionId
890 chargingStation.stationInfo?.chargingStationId
891 }#${transactionConnectorId} with status '${payload.idTagInfo?.status}'`
893 payload
.idTagInfo
== null ||
894 payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED