1 // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
4 import path from
'path';
5 import { fileURLToPath
} from
'url';
7 import type { JSONSchemaType
} from
'ajv';
9 import OCPPError from
'../../../exception/OCPPError';
10 import type { JsonObject
, JsonType
} from
'../../../types/JsonType';
11 import { OCPP16ChargePointErrorCode
} from
'../../../types/ocpp/1.6/ChargePointErrorCode';
12 import { OCPP16ChargePointStatus
} from
'../../../types/ocpp/1.6/ChargePointStatus';
13 import { OCPP16StandardParametersKey
} from
'../../../types/ocpp/1.6/Configuration';
15 OCPP16MeterValuesRequest
,
16 OCPP16MeterValuesResponse
,
17 } from
'../../../types/ocpp/1.6/MeterValues';
19 type OCPP16BootNotificationRequest
,
20 OCPP16IncomingRequestCommand
,
22 type OCPP16StatusNotificationRequest
,
23 } from
'../../../types/ocpp/1.6/Requests';
25 ChangeAvailabilityResponse
,
26 ChangeConfigurationResponse
,
27 ClearChargingProfileResponse
,
28 GetConfigurationResponse
,
29 GetDiagnosticsResponse
,
30 OCPP16BootNotificationResponse
,
31 OCPP16DataTransferResponse
,
32 OCPP16DiagnosticsStatusNotificationResponse
,
33 OCPP16FirmwareStatusNotificationResponse
,
34 OCPP16HeartbeatResponse
,
35 OCPP16StatusNotificationResponse
,
36 OCPP16TriggerMessageResponse
,
37 OCPP16UpdateFirmwareResponse
,
38 SetChargingProfileResponse
,
39 UnlockConnectorResponse
,
40 } from
'../../../types/ocpp/1.6/Responses';
42 OCPP16AuthorizationStatus
,
43 type OCPP16AuthorizeRequest
,
44 type OCPP16AuthorizeResponse
,
45 type OCPP16StartTransactionRequest
,
46 type OCPP16StartTransactionResponse
,
47 type OCPP16StopTransactionRequest
,
48 type OCPP16StopTransactionResponse
,
49 } from
'../../../types/ocpp/1.6/Transaction';
50 import { ErrorType
} from
'../../../types/ocpp/ErrorType';
51 import { OCPPVersion
} from
'../../../types/ocpp/OCPPVersion';
54 RegistrationStatusEnumType
,
56 } from
'../../../types/ocpp/Responses';
57 import Constants from
'../../../utils/Constants';
58 import logger from
'../../../utils/Logger';
59 import Utils from
'../../../utils/Utils';
60 import type ChargingStation from
'../../ChargingStation';
61 import { ChargingStationConfigurationUtils
} from
'../../ChargingStationConfigurationUtils';
62 import OCPPResponseService from
'../OCPPResponseService';
63 import { OCPP16ServiceUtils
} from
'./OCPP16ServiceUtils';
65 const moduleName
= 'OCPP16ResponseService';
67 export default class OCPP16ResponseService
extends OCPPResponseService
{
68 public jsonIncomingRequestResponseSchemas
: Map
<
69 OCPP16IncomingRequestCommand
,
70 JSONSchemaType
<JsonObject
>
73 private responseHandlers
: Map
<OCPP16RequestCommand
, ResponseHandler
>;
74 private jsonSchemas
: Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonObject
>>;
76 public constructor() {
77 if (new.target
?.name
=== moduleName
) {
78 throw new TypeError(`Cannot construct ${new.target?.name} instances directly`);
80 super(OCPPVersion
.VERSION_16
);
81 this.responseHandlers
= new Map
<OCPP16RequestCommand
, ResponseHandler
>([
82 [OCPP16RequestCommand
.BOOT_NOTIFICATION
, this.handleResponseBootNotification
.bind(this)],
83 [OCPP16RequestCommand
.HEARTBEAT
, this.emptyResponseHandler
.bind(this)],
84 [OCPP16RequestCommand
.AUTHORIZE
, this.handleResponseAuthorize
.bind(this)],
85 [OCPP16RequestCommand
.START_TRANSACTION
, this.handleResponseStartTransaction
.bind(this)],
86 [OCPP16RequestCommand
.STOP_TRANSACTION
, this.handleResponseStopTransaction
.bind(this)],
87 [OCPP16RequestCommand
.STATUS_NOTIFICATION
, this.emptyResponseHandler
.bind(this)],
88 [OCPP16RequestCommand
.METER_VALUES
, this.emptyResponseHandler
.bind(this)],
89 [OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
, this.emptyResponseHandler
.bind(this)],
90 [OCPP16RequestCommand
.DATA_TRANSFER
, this.emptyResponseHandler
.bind(this)],
91 [OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
, this.emptyResponseHandler
.bind(this)],
93 this.jsonSchemas
= new Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonObject
>>([
95 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
99 path
.dirname(fileURLToPath(import.meta
.url
)),
100 '../../../assets/json-schemas/ocpp/1.6/BootNotificationResponse.json'
104 ) as JSONSchemaType
<OCPP16BootNotificationResponse
>,
107 OCPP16RequestCommand
.HEARTBEAT
,
111 path
.dirname(fileURLToPath(import.meta
.url
)),
112 '../../../assets/json-schemas/ocpp/1.6/HeartbeatResponse.json'
116 ) as JSONSchemaType
<OCPP16HeartbeatResponse
>,
119 OCPP16RequestCommand
.AUTHORIZE
,
123 path
.dirname(fileURLToPath(import.meta
.url
)),
124 '../../../assets/json-schemas/ocpp/1.6/AuthorizeResponse.json'
128 ) as JSONSchemaType
<OCPP16AuthorizeResponse
>,
131 OCPP16RequestCommand
.START_TRANSACTION
,
135 path
.dirname(fileURLToPath(import.meta
.url
)),
136 '../../../assets/json-schemas/ocpp/1.6/StartTransactionResponse.json'
140 ) as JSONSchemaType
<OCPP16StartTransactionResponse
>,
143 OCPP16RequestCommand
.STOP_TRANSACTION
,
147 path
.dirname(fileURLToPath(import.meta
.url
)),
148 '../../../assets/json-schemas/ocpp/1.6/StopTransactionResponse.json'
152 ) as JSONSchemaType
<OCPP16StopTransactionResponse
>,
155 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
159 path
.dirname(fileURLToPath(import.meta
.url
)),
160 '../../../assets/json-schemas/ocpp/1.6/StatusNotificationResponse.json'
164 ) as JSONSchemaType
<OCPP16StatusNotificationResponse
>,
167 OCPP16RequestCommand
.METER_VALUES
,
171 path
.dirname(fileURLToPath(import.meta
.url
)),
172 '../../../assets/json-schemas/ocpp/1.6/MeterValuesResponse.json'
176 ) as JSONSchemaType
<OCPP16MeterValuesResponse
>,
179 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
183 path
.dirname(fileURLToPath(import.meta
.url
)),
184 '../../../assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotificationResponse.json'
188 ) as JSONSchemaType
<OCPP16DiagnosticsStatusNotificationResponse
>,
191 OCPP16RequestCommand
.DATA_TRANSFER
,
195 path
.dirname(fileURLToPath(import.meta
.url
)),
196 '../../../assets/json-schemas/ocpp/1.6/DataTransferResponse.json'
200 ) as JSONSchemaType
<OCPP16DataTransferResponse
>,
203 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
207 path
.dirname(fileURLToPath(import.meta
.url
)),
208 '../../../assets/json-schemas/ocpp/1.6/FirmwareStatusNotificationResponse.json'
212 ) as JSONSchemaType
<OCPP16FirmwareStatusNotificationResponse
>,
215 this.jsonIncomingRequestResponseSchemas
= new Map([
217 OCPP16IncomingRequestCommand
.RESET
,
221 path
.dirname(fileURLToPath(import.meta
.url
)),
222 '../../../assets/json-schemas/ocpp/1.6/ResetResponse.json'
226 ) as JSONSchemaType
<DefaultResponse
>,
229 OCPP16IncomingRequestCommand
.CLEAR_CACHE
,
233 path
.dirname(fileURLToPath(import.meta
.url
)),
234 '../../../assets/json-schemas/ocpp/1.6/ClearCacheResponse.json'
238 ) as JSONSchemaType
<DefaultResponse
>,
241 OCPP16IncomingRequestCommand
.CHANGE_AVAILABILITY
,
245 path
.dirname(fileURLToPath(import.meta
.url
)),
246 '../../../assets/json-schemas/ocpp/1.6/ChangeAvailabilityResponse.json'
250 ) as JSONSchemaType
<ChangeAvailabilityResponse
>,
253 OCPP16IncomingRequestCommand
.UNLOCK_CONNECTOR
,
257 path
.dirname(fileURLToPath(import.meta
.url
)),
258 '../../../assets/json-schemas/ocpp/1.6/UnlockConnectorResponse.json'
262 ) as JSONSchemaType
<UnlockConnectorResponse
>,
265 OCPP16IncomingRequestCommand
.GET_CONFIGURATION
,
269 path
.dirname(fileURLToPath(import.meta
.url
)),
270 '../../../assets/json-schemas/ocpp/1.6/GetConfigurationResponse.json'
274 ) as JSONSchemaType
<GetConfigurationResponse
>,
277 OCPP16IncomingRequestCommand
.CHANGE_CONFIGURATION
,
281 path
.dirname(fileURLToPath(import.meta
.url
)),
282 '../../../assets/json-schemas/ocpp/1.6/ChangeConfigurationResponse.json'
286 ) as JSONSchemaType
<ChangeConfigurationResponse
>,
289 OCPP16IncomingRequestCommand
.SET_CHARGING_PROFILE
,
293 path
.dirname(fileURLToPath(import.meta
.url
)),
294 '../../../assets/json-schemas/ocpp/1.6/SetChargingProfileResponse.json'
298 ) as JSONSchemaType
<SetChargingProfileResponse
>,
301 OCPP16IncomingRequestCommand
.CLEAR_CHARGING_PROFILE
,
305 path
.dirname(fileURLToPath(import.meta
.url
)),
306 '../../../assets/json-schemas/ocpp/1.6/ClearChargingProfileResponse.json'
310 ) as JSONSchemaType
<ClearChargingProfileResponse
>,
313 OCPP16IncomingRequestCommand
.REMOTE_START_TRANSACTION
,
317 path
.dirname(fileURLToPath(import.meta
.url
)),
318 '../../../assets/json-schemas/ocpp/1.6/RemoteStartTransactionResponse.json'
322 ) as JSONSchemaType
<DefaultResponse
>,
325 OCPP16IncomingRequestCommand
.REMOTE_STOP_TRANSACTION
,
329 path
.dirname(fileURLToPath(import.meta
.url
)),
330 '../../../assets/json-schemas/ocpp/1.6/RemoteStopTransactionResponse.json'
334 ) as JSONSchemaType
<DefaultResponse
>,
337 OCPP16IncomingRequestCommand
.GET_DIAGNOSTICS
,
341 path
.dirname(fileURLToPath(import.meta
.url
)),
342 '../../../assets/json-schemas/ocpp/1.6/GetDiagnosticsResponse.json'
346 ) as JSONSchemaType
<GetDiagnosticsResponse
>,
349 OCPP16IncomingRequestCommand
.TRIGGER_MESSAGE
,
353 path
.dirname(fileURLToPath(import.meta
.url
)),
354 '../../../assets/json-schemas/ocpp/1.6/TriggerMessageResponse.json'
358 ) as JSONSchemaType
<OCPP16TriggerMessageResponse
>,
361 OCPP16IncomingRequestCommand
.DATA_TRANSFER
,
365 path
.dirname(fileURLToPath(import.meta
.url
)),
366 '../../../assets/json-schemas/ocpp/1.6/DataTransferResponse.json'
370 ) as JSONSchemaType
<OCPP16DataTransferResponse
>,
373 OCPP16IncomingRequestCommand
.UPDATE_FIRMWARE
,
377 path
.dirname(fileURLToPath(import.meta
.url
)),
378 '../../../assets/json-schemas/ocpp/1.6/UpdateFirmwareResponse.json'
382 ) as JSONSchemaType
<OCPP16UpdateFirmwareResponse
>,
385 this.validatePayload
.bind(this);
388 public async responseHandler(
389 chargingStation
: ChargingStation
,
390 commandName
: OCPP16RequestCommand
,
392 requestPayload
: JsonType
395 chargingStation
.isRegistered() === true ||
396 commandName
=== OCPP16RequestCommand
.BOOT_NOTIFICATION
399 this.responseHandlers
.has(commandName
) === true &&
400 OCPP16ServiceUtils
.isRequestCommandSupported(chargingStation
, commandName
) === true
403 this.validatePayload(chargingStation
, commandName
, payload
);
404 await this.responseHandlers
.get(commandName
)(chargingStation
, payload
, requestPayload
);
407 `${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handle response error:`,
415 ErrorType
.NOT_IMPLEMENTED
,
416 `${commandName} is not implemented to handle response PDU ${JSON.stringify(
427 ErrorType
.SECURITY_ERROR
,
428 `${commandName} cannot be issued to handle response PDU ${JSON.stringify(
432 )} while the charging station is not registered on the central server.`,
439 private validatePayload(
440 chargingStation
: ChargingStation
,
441 commandName
: OCPP16RequestCommand
,
444 if (this.jsonSchemas
.has(commandName
) === true) {
445 return this.validateResponsePayload(
448 this.jsonSchemas
.get(commandName
),
453 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`
458 private handleResponseBootNotification(
459 chargingStation
: ChargingStation
,
460 payload
: OCPP16BootNotificationResponse
462 if (payload
.status === RegistrationStatusEnumType
.ACCEPTED
) {
463 ChargingStationConfigurationUtils
.addConfigurationKey(
465 OCPP16StandardParametersKey
.HeartbeatInterval
,
466 payload
.interval
.toString(),
468 { overwrite
: true, save
: true }
470 ChargingStationConfigurationUtils
.addConfigurationKey(
472 OCPP16StandardParametersKey
.HeartBeatInterval
,
473 payload
.interval
.toString(),
475 { overwrite
: true, save
: true }
477 chargingStation
.heartbeatSetInterval
478 ? chargingStation
.restartHeartbeat()
479 : chargingStation
.startHeartbeat();
481 if (Object.values(RegistrationStatusEnumType
).includes(payload
.status)) {
482 const logMsg
= `${chargingStation.logPrefix()} Charging station in '${
484 }' state on the central server`;
485 payload
.status === RegistrationStatusEnumType
.REJECTED
486 ? logger
.warn(logMsg
)
487 : logger
.info(logMsg
);
490 chargingStation
.logPrefix() +
491 ' Charging station boot notification response received: %j with undefined registration status',
497 private handleResponseAuthorize(
498 chargingStation
: ChargingStation
,
499 payload
: OCPP16AuthorizeResponse
,
500 requestPayload
: OCPP16AuthorizeRequest
502 let authorizeConnectorId
: number;
503 for (const connectorId
of chargingStation
.connectors
.keys()) {
506 chargingStation
.getConnectorStatus(connectorId
)?.authorizeIdTag
=== requestPayload
.idTag
508 authorizeConnectorId
= connectorId
;
512 const isAuthorizeConnectorIdDefined
= authorizeConnectorId
!== undefined;
513 if (payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
514 isAuthorizeConnectorIdDefined
&&
515 (chargingStation
.getConnectorStatus(authorizeConnectorId
).idTagAuthorized
= true);
517 `${chargingStation.logPrefix()} IdTag '${requestPayload.idTag}' accepted${
518 isAuthorizeConnectorIdDefined ? ` on connector ${authorizeConnectorId}
` : ''
522 if (isAuthorizeConnectorIdDefined
) {
523 chargingStation
.getConnectorStatus(authorizeConnectorId
).idTagAuthorized
= false;
524 delete chargingStation
.getConnectorStatus(authorizeConnectorId
).authorizeIdTag
;
527 `${chargingStation.logPrefix()} IdTag '${requestPayload.idTag}' rejected with status '${
528 payload.idTagInfo.status
529 }'${isAuthorizeConnectorIdDefined ? ` on connector ${authorizeConnectorId}` : ''}`
534 private async handleResponseStartTransaction(
535 chargingStation: ChargingStation,
536 payload: OCPP16StartTransactionResponse,
537 requestPayload: OCPP16StartTransactionRequest
539 const connectorId = requestPayload.connectorId;
541 let transactionConnectorId: number;
542 for (const id of chargingStation.connectors.keys()) {
543 if (id > 0 && id === connectorId) {
544 transactionConnectorId = id;
548 if (!transactionConnectorId) {
550 chargingStation.logPrefix() +
551 ' Trying to start a transaction on a non existing connector Id ' +
552 connectorId.toString()
557 chargingStation.getConnectorStatus(connectorId).transactionRemoteStarted === true &&
558 chargingStation.getAuthorizeRemoteTxRequests() === true &&
559 chargingStation.getLocalAuthListEnabled() === true &&
560 chargingStation.hasAuthorizedTags() &&
561 chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized === false
564 chargingStation.logPrefix() +
565 ' Trying to start a transaction with a not local authorized idTag ' +
566 chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag +
567 ' on connector Id ' +
568 connectorId.toString()
570 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
574 chargingStation.getConnectorStatus(connectorId).transactionRemoteStarted === true &&
575 chargingStation.getAuthorizeRemoteTxRequests() === true &&
576 chargingStation.getMustAuthorizeAtRemoteStart() === true &&
577 chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized === false &&
578 chargingStation.getConnectorStatus(connectorId).idTagAuthorized === false
581 chargingStation.logPrefix() +
582 ' Trying to start a transaction with a not authorized idTag ' +
583 chargingStation.getConnectorStatus(connectorId).authorizeIdTag +
584 ' on connector Id ' +
585 connectorId.toString()
587 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
591 chargingStation.getConnectorStatus(connectorId).idTagAuthorized &&
592 chargingStation.getConnectorStatus(connectorId).authorizeIdTag !== requestPayload.idTag
595 chargingStation.logPrefix() +
596 ' Trying to start a transaction with an idTag ' +
597 requestPayload.idTag +
598 ' different from the authorize request one ' +
599 chargingStation.getConnectorStatus(connectorId).authorizeIdTag +
600 ' on connector Id ' +
601 connectorId.toString()
603 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
607 chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized &&
608 chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag !== requestPayload.idTag
611 chargingStation.logPrefix() +
612 ' Trying to start a transaction with an idTag ' +
613 requestPayload.idTag +
614 ' different from the local authorized one ' +
615 chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag +
616 ' on connector Id ' +
617 connectorId.toString()
619 await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
622 if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) {
624 chargingStation.logPrefix() +
625 ' Trying to start a transaction on an already used connector ' +
626 connectorId.toString() +
628 chargingStation.getConnectorStatus(connectorId)
633 chargingStation.getConnectorStatus(connectorId)?.status !==
634 OCPP16ChargePointStatus.AVAILABLE &&
635 chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.PREPARING
638 `${chargingStation.logPrefix()} Trying to start a transaction on connector ${connectorId.toString()}
with status $
{
639 chargingStation
.getConnectorStatus(connectorId
)?.status
644 // if (!Number.isInteger(payload.transactionId)) {
646 // `${chargingStation.logPrefix()} Trying to start a transaction on connector ${connectorId.toString()}
with a non integer transaction Id $
{
647 // payload.transactionId
648 // }, converting to integer`
650 // payload.transactionId = Utils.convertToInt(payload.transactionId);
653 if (payload
.idTagInfo
?.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
654 chargingStation
.getConnectorStatus(connectorId
).transactionStarted
= true;
655 chargingStation
.getConnectorStatus(connectorId
).transactionId
= payload
.transactionId
;
656 chargingStation
.getConnectorStatus(connectorId
).transactionIdTag
= requestPayload
.idTag
;
657 chargingStation
.getConnectorStatus(
659 ).transactionEnergyActiveImportRegisterValue
= 0;
660 chargingStation
.getConnectorStatus(connectorId
).transactionBeginMeterValue
=
661 OCPP16ServiceUtils
.buildTransactionBeginMeterValue(
664 requestPayload
.meterStart
666 chargingStation
.getBeginEndMeterValues() &&
667 (await chargingStation
.ocppRequestService
.requestHandler
<
668 OCPP16MeterValuesRequest
,
669 OCPP16MeterValuesResponse
670 >(chargingStation
, OCPP16RequestCommand
.METER_VALUES
, {
672 transactionId
: payload
.transactionId
,
673 meterValue
: [chargingStation
.getConnectorStatus(connectorId
).transactionBeginMeterValue
],
675 await chargingStation
.ocppRequestService
.requestHandler
<
676 OCPP16StatusNotificationRequest
,
677 OCPP16StatusNotificationResponse
678 >(chargingStation
, OCPP16RequestCommand
.STATUS_NOTIFICATION
, {
680 status: OCPP16ChargePointStatus
.CHARGING
,
681 errorCode
: OCPP16ChargePointErrorCode
.NO_ERROR
,
683 chargingStation
.getConnectorStatus(connectorId
).status = OCPP16ChargePointStatus
.CHARGING
;
685 chargingStation
.logPrefix() +
687 payload
.transactionId
.toString() +
689 chargingStation
.stationInfo
.chargingStationId
+
691 connectorId
.toString() +
693 requestPayload
.idTag
+
696 if (chargingStation
.stationInfo
.powerSharedByConnectors
) {
697 chargingStation
.powerDivider
++;
699 const configuredMeterValueSampleInterval
=
700 ChargingStationConfigurationUtils
.getConfigurationKey(
702 OCPP16StandardParametersKey
.MeterValueSampleInterval
704 chargingStation
.startMeterValues(
706 configuredMeterValueSampleInterval
707 ? Utils
.convertToInt(configuredMeterValueSampleInterval
.value
) * 1000
708 : Constants
.DEFAULT_METER_VALUES_INTERVAL
712 chargingStation
.logPrefix() +
713 ' Starting transaction id ' +
714 payload
.transactionId
.toString() +
715 " REJECTED with status '" +
716 payload
?.idTagInfo
?.status +
718 requestPayload
.idTag
+
721 await this.resetConnectorOnStartTransactionError(chargingStation
, connectorId
);
725 private async resetConnectorOnStartTransactionError(
726 chargingStation
: ChargingStation
,
729 chargingStation
.resetConnectorStatus(connectorId
);
731 chargingStation
.getConnectorStatus(connectorId
).status !== OCPP16ChargePointStatus
.AVAILABLE
733 await chargingStation
.ocppRequestService
.requestHandler
<
734 OCPP16StatusNotificationRequest
,
735 OCPP16StatusNotificationResponse
736 >(chargingStation
, OCPP16RequestCommand
.STATUS_NOTIFICATION
, {
738 status: OCPP16ChargePointStatus
.AVAILABLE
,
739 errorCode
: OCPP16ChargePointErrorCode
.NO_ERROR
,
741 chargingStation
.getConnectorStatus(connectorId
).status = OCPP16ChargePointStatus
.AVAILABLE
;
745 private async handleResponseStopTransaction(
746 chargingStation
: ChargingStation
,
747 payload
: OCPP16StopTransactionResponse
,
748 requestPayload
: OCPP16StopTransactionRequest
750 const transactionConnectorId
= chargingStation
.getConnectorIdByTransactionId(
751 requestPayload
.transactionId
753 if (!transactionConnectorId
) {
755 chargingStation
.logPrefix() +
756 ' Trying to stop a non existing transaction ' +
757 requestPayload
.transactionId
.toString()
761 if (payload
.idTagInfo
?.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
762 chargingStation
.getBeginEndMeterValues() === true &&
763 chargingStation
.getOcppStrictCompliance() === false &&
764 chargingStation
.getOutOfOrderEndMeterValues() === true &&
765 (await chargingStation
.ocppRequestService
.requestHandler
<
766 OCPP16MeterValuesRequest
,
767 OCPP16MeterValuesResponse
768 >(chargingStation
, OCPP16RequestCommand
.METER_VALUES
, {
769 connectorId
: transactionConnectorId
,
770 transactionId
: requestPayload
.transactionId
,
772 OCPP16ServiceUtils
.buildTransactionEndMeterValue(
774 transactionConnectorId
,
775 requestPayload
.meterStop
780 chargingStation
.isChargingStationAvailable() === false ||
781 chargingStation
.isConnectorAvailable(transactionConnectorId
) === false
783 await chargingStation
.ocppRequestService
.requestHandler
<
784 OCPP16StatusNotificationRequest
,
785 OCPP16StatusNotificationResponse
786 >(chargingStation
, OCPP16RequestCommand
.STATUS_NOTIFICATION
, {
787 connectorId
: transactionConnectorId
,
788 status: OCPP16ChargePointStatus
.UNAVAILABLE
,
789 errorCode
: OCPP16ChargePointErrorCode
.NO_ERROR
,
791 chargingStation
.getConnectorStatus(transactionConnectorId
).status =
792 OCPP16ChargePointStatus
.UNAVAILABLE
;
794 await chargingStation
.ocppRequestService
.requestHandler
<
795 OCPP16BootNotificationRequest
,
796 OCPP16BootNotificationResponse
797 >(chargingStation
, OCPP16RequestCommand
.STATUS_NOTIFICATION
, {
798 connectorId
: transactionConnectorId
,
799 status: OCPP16ChargePointStatus
.AVAILABLE
,
800 errorCode
: OCPP16ChargePointErrorCode
.NO_ERROR
,
802 chargingStation
.getConnectorStatus(transactionConnectorId
).status =
803 OCPP16ChargePointStatus
.AVAILABLE
;
805 if (chargingStation
.stationInfo
.powerSharedByConnectors
) {
806 chargingStation
.powerDivider
--;
808 chargingStation
.resetConnectorStatus(transactionConnectorId
);
810 chargingStation
.logPrefix() +
812 requestPayload
.transactionId
.toString() +
814 chargingStation
.stationInfo
.chargingStationId
+
816 transactionConnectorId
.toString()
820 chargingStation
.logPrefix() +
821 ' Stopping transaction id ' +
822 requestPayload
.transactionId
.toString() +
823 " REJECTED with status '" +
824 payload
.idTagInfo
?.status +