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
)
544 delete chargingStation
.bootNotificationResponse
546 `${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
552 private handleResponseAuthorize (
553 chargingStation
: ChargingStation
,
554 payload
: OCPP16AuthorizeResponse
,
555 requestPayload
: OCPP16AuthorizeRequest
557 let authorizeConnectorId
: number | undefined
558 if (chargingStation
.hasEvses
) {
559 for (const [evseId
, evseStatus
] of chargingStation
.evses
) {
561 for (const [connectorId
, connectorStatus
] of evseStatus
.connectors
) {
562 if (connectorStatus
.authorizeIdTag
=== requestPayload
.idTag
) {
563 authorizeConnectorId
= connectorId
570 for (const connectorId
of chargingStation
.connectors
.keys()) {
573 chargingStation
.getConnectorStatus(connectorId
)?.authorizeIdTag
=== requestPayload
.idTag
575 authorizeConnectorId
= connectorId
580 if (authorizeConnectorId
!= null) {
581 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
582 const authorizeConnectorStatus
= chargingStation
.getConnectorStatus(authorizeConnectorId
)!
583 if (payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
584 authorizeConnectorStatus
.idTagAuthorized
= true
586 `${chargingStation.logPrefix()} idTag '${
588 }' accepted on connector id ${authorizeConnectorId}`
591 authorizeConnectorStatus
.idTagAuthorized
= false
592 delete authorizeConnectorStatus
.authorizeIdTag
594 `${chargingStation.logPrefix()} idTag '${
596 }' rejected with status '${payload.idTagInfo.status}'`
601 `${chargingStation.logPrefix()} idTag '${
603 }' has no authorize request pending`
608 private async handleResponseStartTransaction (
609 chargingStation
: ChargingStation
,
610 payload
: OCPP16StartTransactionResponse
,
611 requestPayload
: OCPP16StartTransactionRequest
613 const { connectorId
} = requestPayload
614 if (connectorId
=== 0 || !chargingStation
.hasConnector(connectorId
)) {
616 `${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector id ${connectorId}`
620 const connectorStatus
= chargingStation
.getConnectorStatus(connectorId
)
622 connectorStatus
?.transactionRemoteStarted
=== true &&
623 chargingStation
.getAuthorizeRemoteTxRequests() &&
624 chargingStation
.getLocalAuthListEnabled() &&
625 chargingStation
.hasIdTags() &&
626 connectorStatus
.idTagLocalAuthorized
=== false
629 `${chargingStation.logPrefix()} Trying to start a transaction with a not local authorized idTag ${
630 connectorStatus.localAuthorizeIdTag
631 } on connector id ${connectorId}`
633 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
637 connectorStatus
?.transactionRemoteStarted
=== true &&
638 chargingStation
.getAuthorizeRemoteTxRequests() &&
639 chargingStation
.stationInfo
?.remoteAuthorization
=== true &&
640 connectorStatus
.idTagLocalAuthorized
=== false &&
641 connectorStatus
.idTagAuthorized
=== false
644 `${chargingStation.logPrefix()} Trying to start a transaction with a not authorized idTag ${
645 connectorStatus.authorizeIdTag
646 } on connector id ${connectorId}`
648 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
652 connectorStatus
?.idTagAuthorized
=== true &&
653 connectorStatus
.authorizeIdTag
!== requestPayload
.idTag
656 `${chargingStation.logPrefix()} Trying to start a transaction with an idTag ${
658 } different from the authorize request one ${
659 connectorStatus.authorizeIdTag
660 } on connector id ${connectorId}`
662 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
666 connectorStatus
?.idTagLocalAuthorized
=== true &&
667 connectorStatus
.localAuthorizeIdTag
!== requestPayload
.idTag
670 `${chargingStation.logPrefix()} Trying to start a transaction with an idTag ${
672 } different from the local authorized one ${
673 connectorStatus.localAuthorizeIdTag
674 } on connector id ${connectorId}`
676 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
679 if (connectorStatus
?.transactionStarted
=== true) {
681 `${chargingStation.logPrefix()} Trying to start a transaction on an already used connector id ${connectorId} by idTag ${
682 connectorStatus.transactionIdTag
687 if (chargingStation
.hasEvses
) {
688 for (const [evseId
, evseStatus
] of chargingStation
.evses
) {
689 if (evseStatus
.connectors
.size
> 1) {
690 for (const [id
, status] of evseStatus
.connectors
) {
691 if (id
!== connectorId
&& status.transactionStarted
=== true) {
693 `${chargingStation.logPrefix()} Trying to start a transaction on an already used evse id ${evseId} by connector id ${id} with idTag ${
694 status.transactionIdTag
697 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
705 connectorStatus
?.status !== OCPP16ChargePointStatus
.Available
&&
706 connectorStatus
?.status !== OCPP16ChargePointStatus
.Preparing
709 `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with status ${
710 connectorStatus?.status
715 if (!Number.isSafeInteger(payload
.transactionId
)) {
717 `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with a non integer transaction id ${
718 payload.transactionId
719 }, converting to integer`
721 payload
.transactionId
= convertToInt(payload
.transactionId
)
724 if (payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
725 connectorStatus
.transactionStarted
= true
726 connectorStatus
.transactionStart
= requestPayload
.timestamp
727 connectorStatus
.transactionId
= payload
.transactionId
728 connectorStatus
.transactionIdTag
= requestPayload
.idTag
729 connectorStatus
.transactionEnergyActiveImportRegisterValue
= 0
730 connectorStatus
.transactionBeginMeterValue
=
731 OCPP16ServiceUtils
.buildTransactionBeginMeterValue(
734 requestPayload
.meterStart
736 if (requestPayload
.reservationId
!= null) {
737 const reservation
= chargingStation
.getReservationBy(
739 requestPayload
.reservationId
741 if (reservation
!= null) {
742 if (reservation
.idTag
!== requestPayload
.idTag
) {
744 `${chargingStation.logPrefix()} Reserved transaction ${
745 payload.transactionId
746 } started with a different idTag ${
748 } than the reservation one ${reservation.idTag}`
751 if (hasReservationExpired(reservation
)) {
753 `${chargingStation.logPrefix()} Reserved transaction ${
754 payload.transactionId
755 } started with expired reservation ${
756 requestPayload.reservationId
757 } (expiry date: ${reservation.expiryDate.toISOString()}))`
760 await chargingStation
.removeReservation(
762 ReservationTerminationReason
.TRANSACTION_STARTED
766 `${chargingStation.logPrefix()} Reserved transaction ${
767 payload.transactionId
768 } started with unknown reservation ${requestPayload.reservationId}`
772 chargingStation
.stationInfo
?.beginEndMeterValues
=== true &&
773 (await chargingStation
.ocppRequestService
.requestHandler
<
774 OCPP16MeterValuesRequest
,
775 OCPP16MeterValuesResponse
776 >(chargingStation
, OCPP16RequestCommand
.METER_VALUES
, {
778 transactionId
: payload
.transactionId
,
779 meterValue
: [connectorStatus
.transactionBeginMeterValue
]
780 } satisfies OCPP16MeterValuesRequest
))
781 await OCPP16ServiceUtils
.sendAndSetConnectorStatus(
784 OCPP16ChargePointStatus
.Charging
787 `${chargingStation.logPrefix()} Transaction with id ${payload.transactionId} STARTED on ${
788 chargingStation.stationInfo?.chargingStationId
789 }#${connectorId} for idTag '${requestPayload.idTag}'`
791 if (chargingStation
.stationInfo
?.powerSharedByConnectors
=== true) {
792 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
793 ++chargingStation
.powerDivider
!
795 const configuredMeterValueSampleInterval
= getConfigurationKey(
797 OCPP16StandardParametersKey
.MeterValueSampleInterval
799 chargingStation
.startMeterValues(
801 configuredMeterValueSampleInterval
!= null
802 ? secondsToMilliseconds(convertToInt(configuredMeterValueSampleInterval
.value
))
803 : Constants
.DEFAULT_METER_VALUES_INTERVAL
807 `${chargingStation.logPrefix()} Starting transaction with id ${
808 payload.transactionId
810 chargingStation.stationInfo?.chargingStationId
811 }#${connectorId} with status '${payload.idTagInfo.status}', idTag '${
814 OCPP16ServiceUtils.hasReservation(chargingStation, connectorId, requestPayload.idTag)
815 ? `, reservationId
'${requestPayload.reservationId}'`
819 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
823 private async resetConnectorOnStartTransactionError (
824 chargingStation
: ChargingStation
,
827 chargingStation
.stopMeterValues(connectorId
)
828 const connectorStatus
= chargingStation
.getConnectorStatus(connectorId
)
829 resetConnectorStatus(connectorStatus
)
830 await OCPP16ServiceUtils
.restoreConnectorStatus(chargingStation
, connectorId
, connectorStatus
)
833 private async handleResponseStopTransaction (
834 chargingStation
: ChargingStation
,
835 payload
: OCPP16StopTransactionResponse
,
836 requestPayload
: OCPP16StopTransactionRequest
838 const transactionConnectorId
= chargingStation
.getConnectorIdByTransactionId(
839 requestPayload
.transactionId
841 if (transactionConnectorId
== null) {
843 `${chargingStation.logPrefix()} Trying to stop a non existing transaction with id ${
844 requestPayload.transactionId
849 chargingStation
.stationInfo
?.beginEndMeterValues
=== true &&
850 chargingStation
.stationInfo
.ocppStrictCompliance
=== false &&
851 chargingStation
.stationInfo
.outOfOrderEndMeterValues
=== true &&
852 (await chargingStation
.ocppRequestService
.requestHandler
<
853 OCPP16MeterValuesRequest
,
854 OCPP16MeterValuesResponse
855 >(chargingStation
, OCPP16RequestCommand
.METER_VALUES
, {
856 connectorId
: transactionConnectorId
,
857 transactionId
: requestPayload
.transactionId
,
859 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
861 transactionConnectorId
,
862 requestPayload
.meterStop
867 !chargingStation
.isChargingStationAvailable() ||
868 !chargingStation
.isConnectorAvailable(transactionConnectorId
)
870 await OCPP16ServiceUtils
.sendAndSetConnectorStatus(
872 transactionConnectorId
,
873 OCPP16ChargePointStatus
.Unavailable
876 await OCPP16ServiceUtils
.sendAndSetConnectorStatus(
878 transactionConnectorId
,
879 OCPP16ChargePointStatus
.Available
882 if (chargingStation
.stationInfo
?.powerSharedByConnectors
=== true) {
883 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
884 chargingStation
.powerDivider
!--
886 resetConnectorStatus(chargingStation
.getConnectorStatus(transactionConnectorId
))
887 chargingStation
.stopMeterValues(transactionConnectorId
)
888 const logMsg
= `${chargingStation.logPrefix()} Transaction with id ${
889 requestPayload.transactionId
891 chargingStation.stationInfo?.chargingStationId
892 }#${transactionConnectorId} with status '${payload.idTagInfo?.status}'`
894 payload
.idTagInfo
== null ||
895 payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED