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.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
, isNullOrUndefined
, 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 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
464 const authorizeConnectorStatus
= chargingStation
.getConnectorStatus(authorizeConnectorId
!)
465 const authorizeConnectorIdDefined
= !isNullOrUndefined(authorizeConnectorId
)
466 if (payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
467 if (authorizeConnectorIdDefined
) {
468 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
469 authorizeConnectorStatus
!.idTagAuthorized
= true
472 `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' accepted${
473 authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}
` : ''
477 if (authorizeConnectorIdDefined
) {
478 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
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)) {
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() &&
506 chargingStation.getLocalAuthListEnabled() &&
507 chargingStation.hasIdTags() &&
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() &&
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 === true &&
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 === true &&
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 != null) {
605 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
606 const reservation = chargingStation.getReservationBy(
608 requestPayload.reservationId
610 if (reservation.idTag !== requestPayload.idTag) {
612 `${chargingStation.logPrefix()} Reserved transaction $
{
613 payload
.transactionId
614 } started
with a different idTag ${requestPayload.idTag} than the reservation one $
{
619 if (hasReservationExpired(reservation)) {
621 `${chargingStation.logPrefix()} Reserved transaction $
{
622 payload
.transactionId
623 } started
with expired reservation $
{
624 requestPayload
.reservationId
625 } (expiry date
: ${reservation.expiryDate.toISOString()}
))`
628 await chargingStation.removeReservation(
630 ReservationTerminationReason.TRANSACTION_STARTED
633 chargingStation.stationInfo?.beginEndMeterValues === true &&
634 (await chargingStation.ocppRequestService.requestHandler<
635 OCPP16MeterValuesRequest,
636 OCPP16MeterValuesResponse
637 >(chargingStation, OCPP16RequestCommand.METER_VALUES, {
639 transactionId: payload.transactionId,
640 meterValue: [connectorStatus.transactionBeginMeterValue]
641 } satisfies OCPP16MeterValuesRequest))
642 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
645 OCPP16ChargePointStatus.Charging
648 `${chargingStation.logPrefix()} Transaction
with id ${payload.transactionId} STARTED on $
{
649 chargingStation
.stationInfo
.chargingStationId
650 }#${connectorId}
for idTag
'${requestPayload.idTag}'`
652 if (chargingStation.stationInfo.powerSharedByConnectors === true) {
653 ++chargingStation.powerDivider
655 const configuredMeterValueSampleInterval = getConfigurationKey(
657 OCPP16StandardParametersKey.MeterValueSampleInterval
659 chargingStation.startMeterValues(
661 configuredMeterValueSampleInterval !== undefined
662 ? secondsToMilliseconds(convertToInt(configuredMeterValueSampleInterval.value))
663 : Constants.DEFAULT_METER_VALUES_INTERVAL
667 `${chargingStation.logPrefix()} Starting transaction
with id $
{
668 payload
.transactionId
670 chargingStation
.stationInfo
.chargingStationId
671 }#${connectorId}
with status '${payload.idTagInfo?.status}', idTag
'${
674 OCPP16ServiceUtils
.hasReservation(chargingStation
, connectorId
, requestPayload
.idTag
)
675 ? `, reservationId '${requestPayload.reservationId}'`
679 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId)
683 private async resetConnectorOnStartTransactionError (
684 chargingStation: ChargingStation,
687 const connectorStatus = chargingStation.getConnectorStatus(connectorId)
688 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
689 resetConnectorStatus(connectorStatus!)
690 chargingStation.stopMeterValues(connectorId)
691 if (connectorStatus?.status !== OCPP16ChargePointStatus.Available) {
692 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
695 OCPP16ChargePointStatus.Available
700 private async handleResponseStopTransaction (
701 chargingStation: ChargingStation,
702 payload: OCPP16StopTransactionResponse,
703 requestPayload: OCPP16StopTransactionRequest
705 const transactionConnectorId = chargingStation.getConnectorIdByTransactionId(
706 requestPayload.transactionId
708 if (isNullOrUndefined(transactionConnectorId)) {
710 `${chargingStation.logPrefix()} Trying to stop a non existing transaction
with id $
{
711 requestPayload
.transactionId
716 chargingStation.stationInfo?.beginEndMeterValues === true &&
717 chargingStation.stationInfo?.ocppStrictCompliance === false &&
718 chargingStation.stationInfo?.outOfOrderEndMeterValues === true &&
719 (await chargingStation.ocppRequestService.requestHandler<
720 OCPP16MeterValuesRequest,
721 OCPP16MeterValuesResponse
722 >(chargingStation, OCPP16RequestCommand.METER_VALUES, {
723 connectorId: transactionConnectorId,
724 transactionId: requestPayload.transactionId,
726 OCPP16ServiceUtils.buildTransactionEndMeterValue(
728 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
729 transactionConnectorId!,
730 requestPayload.meterStop
735 !chargingStation.isChargingStationAvailable() ||
736 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
737 !chargingStation.isConnectorAvailable(transactionConnectorId!)
739 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
741 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
742 transactionConnectorId!,
743 OCPP16ChargePointStatus.Unavailable
746 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
748 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
749 transactionConnectorId!,
750 OCPP16ChargePointStatus.Available
753 if (chargingStation.stationInfo.powerSharedByConnectors === true) {
754 chargingStation.powerDivider--
756 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
757 resetConnectorStatus(chargingStation.getConnectorStatus(transactionConnectorId!)!)
758 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
759 chargingStation.stopMeterValues(transactionConnectorId!)
760 const logMsg = `${chargingStation.logPrefix()} Transaction
with id $
{
761 requestPayload
.transactionId
763 chargingStation
.stationInfo
.chargingStationId
764 }#${transactionConnectorId}
with status '${payload.idTagInfo?.status}'`
766 isNullOrUndefined(payload.idTagInfo) ||
767 payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED