1 // Partial Copyright Jerome Benoit. 2021-2024. All Rights Reserved.
3 import type { JSONSchemaType
} from
'ajv'
4 import { secondsToMilliseconds
} from
'date-fns'
6 import { OCPP16ServiceUtils
} from
'./OCPP16ServiceUtils.js'
11 hasReservationExpired
,
13 } from
'../../../charging-station/index.js'
14 import { OCPPError
} from
'../../../exception/index.js'
16 type ChangeConfigurationResponse
,
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
, logger
} from
'../../../utils/index.js'
55 import { OCPPResponseService
} from
'../OCPPResponseService.js'
57 const moduleName
= 'OCPP16ResponseService'
59 export class OCPP16ResponseService
extends OCPPResponseService
{
60 public jsonIncomingRequestResponseSchemas
: Map
<
61 OCPP16IncomingRequestCommand
,
62 JSONSchemaType
<JsonType
>
65 private readonly responseHandlers
: Map
<OCPP16RequestCommand
, ResponseHandler
>
66 private readonly jsonSchemas
: Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonType
>>
68 public constructor () {
69 // if (new.target.name === moduleName) {
70 // throw new TypeError(`Cannot construct ${new.target.name} instances directly`)
72 super(OCPPVersion
.VERSION_16
)
73 this.responseHandlers
= new Map
<OCPP16RequestCommand
, ResponseHandler
>([
75 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
76 this.handleResponseBootNotification
.bind(this) as ResponseHandler
78 [OCPP16RequestCommand
.HEARTBEAT
, this.emptyResponseHandler
.bind(this) as ResponseHandler
],
79 [OCPP16RequestCommand
.AUTHORIZE
, this.handleResponseAuthorize
.bind(this) as ResponseHandler
],
81 OCPP16RequestCommand
.START_TRANSACTION
,
82 this.handleResponseStartTransaction
.bind(this) as ResponseHandler
85 OCPP16RequestCommand
.STOP_TRANSACTION
,
86 this.handleResponseStopTransaction
.bind(this) as ResponseHandler
89 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
90 this.emptyResponseHandler
.bind(this) as ResponseHandler
92 [OCPP16RequestCommand
.METER_VALUES
, this.emptyResponseHandler
.bind(this) as ResponseHandler
],
94 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
95 this.emptyResponseHandler
.bind(this) as ResponseHandler
97 [OCPP16RequestCommand
.DATA_TRANSFER
, this.emptyResponseHandler
.bind(this) as ResponseHandler
],
99 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
100 this.emptyResponseHandler
.bind(this) as ResponseHandler
103 this.jsonSchemas
= new Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonType
>>([
105 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
106 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16BootNotificationResponse
>(
107 'assets/json-schemas/ocpp/1.6/BootNotificationResponse.json',
113 OCPP16RequestCommand
.HEARTBEAT
,
114 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16HeartbeatResponse
>(
115 'assets/json-schemas/ocpp/1.6/HeartbeatResponse.json',
121 OCPP16RequestCommand
.AUTHORIZE
,
122 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16AuthorizeResponse
>(
123 'assets/json-schemas/ocpp/1.6/AuthorizeResponse.json',
129 OCPP16RequestCommand
.START_TRANSACTION
,
130 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StartTransactionResponse
>(
131 'assets/json-schemas/ocpp/1.6/StartTransactionResponse.json',
137 OCPP16RequestCommand
.STOP_TRANSACTION
,
138 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StopTransactionResponse
>(
139 'assets/json-schemas/ocpp/1.6/StopTransactionResponse.json',
145 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
146 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StatusNotificationResponse
>(
147 'assets/json-schemas/ocpp/1.6/StatusNotificationResponse.json',
153 OCPP16RequestCommand
.METER_VALUES
,
154 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16MeterValuesResponse
>(
155 'assets/json-schemas/ocpp/1.6/MeterValuesResponse.json',
161 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
162 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DiagnosticsStatusNotificationResponse
>(
163 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotificationResponse.json',
169 OCPP16RequestCommand
.DATA_TRANSFER
,
170 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DataTransferResponse
>(
171 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
177 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
178 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16FirmwareStatusNotificationResponse
>(
179 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotificationResponse.json',
185 this.jsonIncomingRequestResponseSchemas
= new Map([
187 OCPP16IncomingRequestCommand
.RESET
,
188 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
189 'assets/json-schemas/ocpp/1.6/ResetResponse.json',
195 OCPP16IncomingRequestCommand
.CLEAR_CACHE
,
196 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
197 'assets/json-schemas/ocpp/1.6/ClearCacheResponse.json',
203 OCPP16IncomingRequestCommand
.CHANGE_AVAILABILITY
,
204 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16ChangeAvailabilityResponse
>(
205 'assets/json-schemas/ocpp/1.6/ChangeAvailabilityResponse.json',
211 OCPP16IncomingRequestCommand
.UNLOCK_CONNECTOR
,
212 OCPP16ServiceUtils
.parseJsonSchemaFile
<UnlockConnectorResponse
>(
213 'assets/json-schemas/ocpp/1.6/UnlockConnectorResponse.json',
219 OCPP16IncomingRequestCommand
.GET_CONFIGURATION
,
220 OCPP16ServiceUtils
.parseJsonSchemaFile
<GetConfigurationResponse
>(
221 'assets/json-schemas/ocpp/1.6/GetConfigurationResponse.json',
227 OCPP16IncomingRequestCommand
.CHANGE_CONFIGURATION
,
228 OCPP16ServiceUtils
.parseJsonSchemaFile
<ChangeConfigurationResponse
>(
229 'assets/json-schemas/ocpp/1.6/ChangeConfigurationResponse.json',
235 OCPP16IncomingRequestCommand
.GET_COMPOSITE_SCHEDULE
,
236 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16GetCompositeScheduleResponse
>(
237 'assets/json-schemas/ocpp/1.6/GetCompositeScheduleResponse.json',
243 OCPP16IncomingRequestCommand
.SET_CHARGING_PROFILE
,
244 OCPP16ServiceUtils
.parseJsonSchemaFile
<SetChargingProfileResponse
>(
245 'assets/json-schemas/ocpp/1.6/SetChargingProfileResponse.json',
251 OCPP16IncomingRequestCommand
.CLEAR_CHARGING_PROFILE
,
252 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16ClearChargingProfileResponse
>(
253 'assets/json-schemas/ocpp/1.6/ClearChargingProfileResponse.json',
259 OCPP16IncomingRequestCommand
.REMOTE_START_TRANSACTION
,
260 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
261 'assets/json-schemas/ocpp/1.6/RemoteStartTransactionResponse.json',
267 OCPP16IncomingRequestCommand
.REMOTE_STOP_TRANSACTION
,
268 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
269 'assets/json-schemas/ocpp/1.6/RemoteStopTransactionResponse.json',
275 OCPP16IncomingRequestCommand
.GET_DIAGNOSTICS
,
276 OCPP16ServiceUtils
.parseJsonSchemaFile
<GetDiagnosticsResponse
>(
277 'assets/json-schemas/ocpp/1.6/GetDiagnosticsResponse.json',
283 OCPP16IncomingRequestCommand
.TRIGGER_MESSAGE
,
284 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16TriggerMessageResponse
>(
285 'assets/json-schemas/ocpp/1.6/TriggerMessageResponse.json',
291 OCPP16IncomingRequestCommand
.DATA_TRANSFER
,
292 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DataTransferResponse
>(
293 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
299 OCPP16IncomingRequestCommand
.UPDATE_FIRMWARE
,
300 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16UpdateFirmwareResponse
>(
301 'assets/json-schemas/ocpp/1.6/UpdateFirmwareResponse.json',
307 OCPP16IncomingRequestCommand
.RESERVE_NOW
,
308 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16ReserveNowResponse
>(
309 'assets/json-schemas/ocpp/1.6/ReserveNowResponse.json',
315 OCPP16IncomingRequestCommand
.CANCEL_RESERVATION
,
316 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
317 'assets/json-schemas/ocpp/1.6/CancelReservationResponse.json',
323 this.validatePayload
= this.validatePayload
.bind(this) as (
324 chargingStation
: ChargingStation
,
325 commandName
: OCPP16RequestCommand
,
330 public async responseHandler
<ReqType
extends JsonType
, ResType
extends JsonType
>(
331 chargingStation
: ChargingStation
,
332 commandName
: OCPP16RequestCommand
,
334 requestPayload
: ReqType
336 if (chargingStation
.isRegistered() || commandName
=== OCPP16RequestCommand
.BOOT_NOTIFICATION
) {
338 this.responseHandlers
.has(commandName
) &&
339 OCPP16ServiceUtils
.isRequestCommandSupported(chargingStation
, commandName
)
342 this.validatePayload(chargingStation
, commandName
, payload
)
343 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
344 await this.responseHandlers
.get(commandName
)!(chargingStation
, payload
, requestPayload
)
347 `${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handle response error:`,
355 ErrorType
.NOT_IMPLEMENTED
,
356 `${commandName} is not implemented to handle response PDU ${JSON.stringify(
367 ErrorType
.SECURITY_ERROR
,
368 `${commandName} cannot be issued to handle response PDU ${JSON.stringify(
372 )} while the charging station is not registered on the central server.`,
379 private validatePayload (
380 chargingStation
: ChargingStation
,
381 commandName
: OCPP16RequestCommand
,
384 if (this.jsonSchemas
.has(commandName
)) {
385 return this.validateResponsePayload(
388 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
389 this.jsonSchemas
.get(commandName
)!,
394 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`
399 private handleResponseBootNotification (
400 chargingStation
: ChargingStation
,
401 payload
: OCPP16BootNotificationResponse
403 if (payload
.status === RegistrationStatusEnumType
.ACCEPTED
) {
406 OCPP16StandardParametersKey
.HeartbeatInterval
,
407 payload
.interval
.toString(),
409 { overwrite
: true, save
: true }
413 OCPP16StandardParametersKey
.HeartBeatInterval
,
414 payload
.interval
.toString(),
416 { overwrite
: true, save
: true }
418 OCPP16ServiceUtils
.startHeartbeatInterval(chargingStation
, payload
.interval
)
420 if (Object.values(RegistrationStatusEnumType
).includes(payload
.status)) {
421 const logMsg
= `${chargingStation.logPrefix()} Charging station in '${
423 }' state on the central server`
424 payload
.status === RegistrationStatusEnumType
.REJECTED
425 ? logger
.warn(logMsg
)
426 : logger
.info(logMsg
)
429 `${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
435 private handleResponseAuthorize (
436 chargingStation
: ChargingStation
,
437 payload
: OCPP16AuthorizeResponse
,
438 requestPayload
: OCPP16AuthorizeRequest
440 let authorizeConnectorId
: number | undefined
441 if (chargingStation
.hasEvses
) {
442 for (const [evseId
, evseStatus
] of chargingStation
.evses
) {
444 for (const [connectorId
, connectorStatus
] of evseStatus
.connectors
) {
445 if (connectorStatus
.authorizeIdTag
=== requestPayload
.idTag
) {
446 authorizeConnectorId
= connectorId
453 for (const connectorId
of chargingStation
.connectors
.keys()) {
456 chargingStation
.getConnectorStatus(connectorId
)?.authorizeIdTag
=== requestPayload
.idTag
458 authorizeConnectorId
= connectorId
463 if (authorizeConnectorId
!= null) {
464 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
465 const authorizeConnectorStatus
= chargingStation
.getConnectorStatus(authorizeConnectorId
)!
466 if (payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
467 authorizeConnectorStatus
.idTagAuthorized
= true
469 `${chargingStation.logPrefix()} idTag '${
471 }' accepted on connector id ${authorizeConnectorId}`
474 authorizeConnectorStatus
.idTagAuthorized
= false
475 delete authorizeConnectorStatus
.authorizeIdTag
477 `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' rejected with status '${
478 payload.idTagInfo.status
484 `${chargingStation.logPrefix()} idTag '${
486 }' has no authorize request pending`
491 private async handleResponseStartTransaction (
492 chargingStation
: ChargingStation
,
493 payload
: OCPP16StartTransactionResponse
,
494 requestPayload
: OCPP16StartTransactionRequest
496 const { connectorId
} = requestPayload
497 if (connectorId
=== 0 || !chargingStation
.hasConnector(connectorId
)) {
499 `${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector id ${connectorId}`
503 const connectorStatus
= chargingStation
.getConnectorStatus(connectorId
)
505 connectorStatus
?.transactionRemoteStarted
=== true &&
506 chargingStation
.getAuthorizeRemoteTxRequests() &&
507 chargingStation
.getLocalAuthListEnabled() &&
508 chargingStation
.hasIdTags() &&
509 connectorStatus
.idTagLocalAuthorized
=== false
512 `${chargingStation.logPrefix()} Trying to start a transaction with a not local authorized idTag ${
513 connectorStatus.localAuthorizeIdTag
514 } on connector id ${connectorId}`
516 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
520 connectorStatus
?.transactionRemoteStarted
=== true &&
521 chargingStation
.getAuthorizeRemoteTxRequests() &&
522 chargingStation
.stationInfo
?.remoteAuthorization
=== true &&
523 connectorStatus
.idTagLocalAuthorized
=== false &&
524 connectorStatus
.idTagAuthorized
=== false
527 `${chargingStation.logPrefix()} Trying to start a transaction with a not authorized idTag ${
528 connectorStatus.authorizeIdTag
529 } on connector id ${connectorId}`
531 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
535 connectorStatus
?.idTagAuthorized
=== true &&
536 connectorStatus
.authorizeIdTag
!== requestPayload
.idTag
539 `${chargingStation.logPrefix()} Trying to start a transaction with an idTag ${
541 } different from the authorize request one ${
542 connectorStatus.authorizeIdTag
543 } on connector id ${connectorId}`
545 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
549 connectorStatus
?.idTagLocalAuthorized
=== true &&
550 connectorStatus
.localAuthorizeIdTag
!== requestPayload
.idTag
553 `${chargingStation.logPrefix()} Trying to start a transaction with an idTag ${
555 } different from the local authorized one ${
556 connectorStatus.localAuthorizeIdTag
557 } on connector id ${connectorId}`
559 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
562 if (connectorStatus
?.transactionStarted
=== true) {
564 `${chargingStation.logPrefix()} Trying to start a transaction on an already used connector id ${connectorId} by idTag ${
565 connectorStatus.transactionIdTag
570 if (chargingStation
.hasEvses
) {
571 for (const [evseId
, evseStatus
] of chargingStation
.evses
) {
572 if (evseStatus
.connectors
.size
> 1) {
573 for (const [id
, status] of evseStatus
.connectors
) {
574 if (id
!== connectorId
&& status.transactionStarted
=== true) {
576 `${chargingStation.logPrefix()} Trying to start a transaction on an already used evse id ${evseId} by connector id ${id} with idTag ${
577 status.transactionIdTag
580 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
588 connectorStatus
?.status !== OCPP16ChargePointStatus
.Available
&&
589 connectorStatus
?.status !== OCPP16ChargePointStatus
.Preparing
592 `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with status ${connectorStatus?.status}`
596 if (!Number.isSafeInteger(payload
.transactionId
)) {
598 `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${connectorId} with a non integer transaction id ${
599 payload.transactionId
600 }, converting to integer`
602 payload
.transactionId
= convertToInt(payload
.transactionId
)
605 if (payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
606 connectorStatus
.transactionStarted
= true
607 connectorStatus
.transactionStart
= requestPayload
.timestamp
608 connectorStatus
.transactionId
= payload
.transactionId
609 connectorStatus
.transactionIdTag
= requestPayload
.idTag
610 connectorStatus
.transactionEnergyActiveImportRegisterValue
= 0
611 connectorStatus
.transactionBeginMeterValue
=
612 OCPP16ServiceUtils
.buildTransactionBeginMeterValue(
615 requestPayload
.meterStart
617 if (requestPayload
.reservationId
!= null) {
618 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
619 const reservation
= chargingStation
.getReservationBy(
621 requestPayload
.reservationId
623 if (reservation
.idTag
!== requestPayload
.idTag
) {
625 `${chargingStation.logPrefix()} Reserved transaction ${
626 payload.transactionId
627 } started with a different idTag ${requestPayload.idTag} than the reservation one ${
632 if (hasReservationExpired(reservation
)) {
634 `${chargingStation.logPrefix()} Reserved transaction ${
635 payload.transactionId
636 } started with expired reservation ${
637 requestPayload.reservationId
638 } (expiry date: ${reservation.expiryDate.toISOString()}))`
641 await chargingStation
.removeReservation(
643 ReservationTerminationReason
.TRANSACTION_STARTED
646 chargingStation
.stationInfo
?.beginEndMeterValues
=== true &&
647 (await chargingStation
.ocppRequestService
.requestHandler
<
648 OCPP16MeterValuesRequest
,
649 OCPP16MeterValuesResponse
650 >(chargingStation
, OCPP16RequestCommand
.METER_VALUES
, {
652 transactionId
: payload
.transactionId
,
653 meterValue
: [connectorStatus
.transactionBeginMeterValue
]
654 } satisfies OCPP16MeterValuesRequest
))
655 await OCPP16ServiceUtils
.sendAndSetConnectorStatus(
658 OCPP16ChargePointStatus
.Charging
661 `${chargingStation.logPrefix()} Transaction with id ${
662 payload.transactionId
663 } STARTED on ${chargingStation.stationInfo?.chargingStationId}#${connectorId} for idTag '${
667 if (chargingStation
.stationInfo
?.powerSharedByConnectors
=== true) {
668 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
669 ++chargingStation
.powerDivider
!
671 const configuredMeterValueSampleInterval
= getConfigurationKey(
673 OCPP16StandardParametersKey
.MeterValueSampleInterval
675 chargingStation
.startMeterValues(
677 configuredMeterValueSampleInterval
!= null
678 ? secondsToMilliseconds(convertToInt(configuredMeterValueSampleInterval
.value
))
679 : Constants
.DEFAULT_METER_VALUES_INTERVAL
683 `${chargingStation.logPrefix()} Starting transaction with id ${
684 payload.transactionId
686 chargingStation.stationInfo?.chargingStationId
687 }#${connectorId} with status '${payload.idTagInfo.status}', idTag '${
690 OCPP16ServiceUtils.hasReservation(chargingStation, connectorId, requestPayload.idTag)
691 ? `, reservationId
'${requestPayload.reservationId}'`
695 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
)
699 private async resetConnectorOnStartTransactionError (
700 chargingStation
: ChargingStation
,
703 const connectorStatus
= chargingStation
.getConnectorStatus(connectorId
)
704 resetConnectorStatus(connectorStatus
)
705 chargingStation
.stopMeterValues(connectorId
)
706 if (connectorStatus
?.status !== OCPP16ChargePointStatus
.Available
) {
707 await OCPP16ServiceUtils
.sendAndSetConnectorStatus(
710 OCPP16ChargePointStatus
.Available
715 private async handleResponseStopTransaction (
716 chargingStation
: ChargingStation
,
717 payload
: OCPP16StopTransactionResponse
,
718 requestPayload
: OCPP16StopTransactionRequest
720 const transactionConnectorId
= chargingStation
.getConnectorIdByTransactionId(
721 requestPayload
.transactionId
723 if (transactionConnectorId
== null) {
725 `${chargingStation.logPrefix()} Trying to stop a non existing transaction with id ${
726 requestPayload.transactionId
731 chargingStation
.stationInfo
?.beginEndMeterValues
=== true &&
732 chargingStation
.stationInfo
.ocppStrictCompliance
=== false &&
733 chargingStation
.stationInfo
.outOfOrderEndMeterValues
=== true &&
734 (await chargingStation
.ocppRequestService
.requestHandler
<
735 OCPP16MeterValuesRequest
,
736 OCPP16MeterValuesResponse
737 >(chargingStation
, OCPP16RequestCommand
.METER_VALUES
, {
738 connectorId
: transactionConnectorId
,
739 transactionId
: requestPayload
.transactionId
,
741 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
743 transactionConnectorId
,
744 requestPayload
.meterStop
749 !chargingStation
.isChargingStationAvailable() ||
750 !chargingStation
.isConnectorAvailable(transactionConnectorId
)
752 await OCPP16ServiceUtils
.sendAndSetConnectorStatus(
754 transactionConnectorId
,
755 OCPP16ChargePointStatus
.Unavailable
758 await OCPP16ServiceUtils
.sendAndSetConnectorStatus(
760 transactionConnectorId
,
761 OCPP16ChargePointStatus
.Available
764 if (chargingStation
.stationInfo
?.powerSharedByConnectors
=== true) {
765 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
766 chargingStation
.powerDivider
!--
768 resetConnectorStatus(chargingStation
.getConnectorStatus(transactionConnectorId
))
769 chargingStation
.stopMeterValues(transactionConnectorId
)
770 const logMsg
= `${chargingStation.logPrefix()} Transaction with id ${
771 requestPayload.transactionId
773 chargingStation.stationInfo?.chargingStationId
774 }#${transactionConnectorId} with status '${payload.idTagInfo?.status}'`
776 payload
.idTagInfo
== null ||
777 payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED