1 // Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
3 import { parentPort
} from
'node:worker_threads';
5 import type { JSONSchemaType
} from
'ajv';
6 import { secondsToMilliseconds
} from
'date-fns';
8 import { OCPP16ServiceUtils
} from
'./OCPP16ServiceUtils';
14 } from
'../../../charging-station';
15 import { OCPPError
} from
'../../../exception';
17 type ChangeAvailabilityResponse
,
18 type ChangeConfigurationResponse
,
19 type ClearChargingProfileResponse
,
22 type GetConfigurationResponse
,
23 type GetDiagnosticsResponse
,
26 OCPP16AuthorizationStatus
,
27 type OCPP16AuthorizeRequest
,
28 type OCPP16AuthorizeResponse
,
29 type OCPP16BootNotificationResponse
,
30 OCPP16ChargePointStatus
,
31 type OCPP16DataTransferResponse
,
32 type OCPP16DiagnosticsStatusNotificationResponse
,
33 type OCPP16FirmwareStatusNotificationResponse
,
34 type OCPP16GetCompositeScheduleResponse
,
35 type OCPP16HeartbeatResponse
,
36 OCPP16IncomingRequestCommand
,
37 type OCPP16MeterValuesRequest
,
38 type OCPP16MeterValuesResponse
,
40 type OCPP16ReserveNowResponse
,
41 OCPP16StandardParametersKey
,
42 type OCPP16StartTransactionRequest
,
43 type OCPP16StartTransactionResponse
,
44 type OCPP16StatusNotificationResponse
,
45 type OCPP16StopTransactionRequest
,
46 type OCPP16StopTransactionResponse
,
47 type OCPP16TriggerMessageResponse
,
48 type OCPP16UpdateFirmwareResponse
,
50 RegistrationStatusEnumType
,
51 ReservationTerminationReason
,
53 type SetChargingProfileResponse
,
54 type UnlockConnectorResponse
,
55 } from
'../../../types';
62 } from
'../../../utils';
63 import { OCPPResponseService
} from
'../OCPPResponseService';
65 const moduleName
= 'OCPP16ResponseService';
67 export 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
>([
83 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
84 this.handleResponseBootNotification
.bind(this) as ResponseHandler
,
86 [OCPP16RequestCommand
.HEARTBEAT
, this.emptyResponseHandler
.bind(this) as ResponseHandler
],
87 [OCPP16RequestCommand
.AUTHORIZE
, this.handleResponseAuthorize
.bind(this) as ResponseHandler
],
89 OCPP16RequestCommand
.START_TRANSACTION
,
90 this.handleResponseStartTransaction
.bind(this) as ResponseHandler
,
93 OCPP16RequestCommand
.STOP_TRANSACTION
,
94 this.handleResponseStopTransaction
.bind(this) as ResponseHandler
,
97 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
98 this.emptyResponseHandler
.bind(this) as ResponseHandler
,
100 [OCPP16RequestCommand
.METER_VALUES
, this.emptyResponseHandler
.bind(this) as ResponseHandler
],
102 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
103 this.emptyResponseHandler
.bind(this) as ResponseHandler
,
105 [OCPP16RequestCommand
.DATA_TRANSFER
, this.emptyResponseHandler
.bind(this) as ResponseHandler
],
107 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
108 this.emptyResponseHandler
.bind(this) as ResponseHandler
,
111 this.jsonSchemas
= new Map
<OCPP16RequestCommand
, JSONSchemaType
<JsonObject
>>([
113 OCPP16RequestCommand
.BOOT_NOTIFICATION
,
114 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16BootNotificationResponse
>(
115 'assets/json-schemas/ocpp/1.6/BootNotificationResponse.json',
121 OCPP16RequestCommand
.HEARTBEAT
,
122 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16HeartbeatResponse
>(
123 'assets/json-schemas/ocpp/1.6/HeartbeatResponse.json',
129 OCPP16RequestCommand
.AUTHORIZE
,
130 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16AuthorizeResponse
>(
131 'assets/json-schemas/ocpp/1.6/AuthorizeResponse.json',
137 OCPP16RequestCommand
.START_TRANSACTION
,
138 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StartTransactionResponse
>(
139 'assets/json-schemas/ocpp/1.6/StartTransactionResponse.json',
145 OCPP16RequestCommand
.STOP_TRANSACTION
,
146 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StopTransactionResponse
>(
147 'assets/json-schemas/ocpp/1.6/StopTransactionResponse.json',
153 OCPP16RequestCommand
.STATUS_NOTIFICATION
,
154 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16StatusNotificationResponse
>(
155 'assets/json-schemas/ocpp/1.6/StatusNotificationResponse.json',
161 OCPP16RequestCommand
.METER_VALUES
,
162 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16MeterValuesResponse
>(
163 'assets/json-schemas/ocpp/1.6/MeterValuesResponse.json',
169 OCPP16RequestCommand
.DIAGNOSTICS_STATUS_NOTIFICATION
,
170 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DiagnosticsStatusNotificationResponse
>(
171 'assets/json-schemas/ocpp/1.6/DiagnosticsStatusNotificationResponse.json',
177 OCPP16RequestCommand
.DATA_TRANSFER
,
178 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DataTransferResponse
>(
179 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
185 OCPP16RequestCommand
.FIRMWARE_STATUS_NOTIFICATION
,
186 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16FirmwareStatusNotificationResponse
>(
187 'assets/json-schemas/ocpp/1.6/FirmwareStatusNotificationResponse.json',
193 this.jsonIncomingRequestResponseSchemas
= new Map([
195 OCPP16IncomingRequestCommand
.RESET
,
196 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
197 'assets/json-schemas/ocpp/1.6/ResetResponse.json',
203 OCPP16IncomingRequestCommand
.CLEAR_CACHE
,
204 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
205 'assets/json-schemas/ocpp/1.6/ClearCacheResponse.json',
211 OCPP16IncomingRequestCommand
.CHANGE_AVAILABILITY
,
212 OCPP16ServiceUtils
.parseJsonSchemaFile
<ChangeAvailabilityResponse
>(
213 'assets/json-schemas/ocpp/1.6/ChangeAvailabilityResponse.json',
219 OCPP16IncomingRequestCommand
.UNLOCK_CONNECTOR
,
220 OCPP16ServiceUtils
.parseJsonSchemaFile
<UnlockConnectorResponse
>(
221 'assets/json-schemas/ocpp/1.6/UnlockConnectorResponse.json',
227 OCPP16IncomingRequestCommand
.GET_CONFIGURATION
,
228 OCPP16ServiceUtils
.parseJsonSchemaFile
<GetConfigurationResponse
>(
229 'assets/json-schemas/ocpp/1.6/GetConfigurationResponse.json',
235 OCPP16IncomingRequestCommand
.CHANGE_CONFIGURATION
,
236 OCPP16ServiceUtils
.parseJsonSchemaFile
<ChangeConfigurationResponse
>(
237 'assets/json-schemas/ocpp/1.6/ChangeConfigurationResponse.json',
243 OCPP16IncomingRequestCommand
.GET_COMPOSITE_SCHEDULE
,
244 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16GetCompositeScheduleResponse
>(
245 'assets/json-schemas/ocpp/1.6/GetCompositeScheduleResponse.json',
251 OCPP16IncomingRequestCommand
.SET_CHARGING_PROFILE
,
252 OCPP16ServiceUtils
.parseJsonSchemaFile
<SetChargingProfileResponse
>(
253 'assets/json-schemas/ocpp/1.6/SetChargingProfileResponse.json',
259 OCPP16IncomingRequestCommand
.CLEAR_CHARGING_PROFILE
,
260 OCPP16ServiceUtils
.parseJsonSchemaFile
<ClearChargingProfileResponse
>(
261 'assets/json-schemas/ocpp/1.6/ClearChargingProfileResponse.json',
267 OCPP16IncomingRequestCommand
.REMOTE_START_TRANSACTION
,
268 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
269 'assets/json-schemas/ocpp/1.6/RemoteStartTransactionResponse.json',
275 OCPP16IncomingRequestCommand
.REMOTE_STOP_TRANSACTION
,
276 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
277 'assets/json-schemas/ocpp/1.6/RemoteStopTransactionResponse.json',
283 OCPP16IncomingRequestCommand
.GET_DIAGNOSTICS
,
284 OCPP16ServiceUtils
.parseJsonSchemaFile
<GetDiagnosticsResponse
>(
285 'assets/json-schemas/ocpp/1.6/GetDiagnosticsResponse.json',
291 OCPP16IncomingRequestCommand
.TRIGGER_MESSAGE
,
292 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16TriggerMessageResponse
>(
293 'assets/json-schemas/ocpp/1.6/TriggerMessageResponse.json',
299 OCPP16IncomingRequestCommand
.DATA_TRANSFER
,
300 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16DataTransferResponse
>(
301 'assets/json-schemas/ocpp/1.6/DataTransferResponse.json',
307 OCPP16IncomingRequestCommand
.UPDATE_FIRMWARE
,
308 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16UpdateFirmwareResponse
>(
309 'assets/json-schemas/ocpp/1.6/UpdateFirmwareResponse.json',
315 OCPP16IncomingRequestCommand
.RESERVE_NOW
,
316 OCPP16ServiceUtils
.parseJsonSchemaFile
<OCPP16ReserveNowResponse
>(
317 'assets/json-schemas/ocpp/1.6/ReserveNowResponse.json',
323 OCPP16IncomingRequestCommand
.CANCEL_RESERVATION
,
324 OCPP16ServiceUtils
.parseJsonSchemaFile
<GenericResponse
>(
325 'assets/json-schemas/ocpp/1.6/CancelReservationResponse.json',
331 this.validatePayload
= this.validatePayload
.bind(this) as (
332 chargingStation
: ChargingStation
,
333 commandName
: OCPP16RequestCommand
,
338 public async responseHandler
<ReqType
extends JsonType
, ResType
extends JsonType
>(
339 chargingStation
: ChargingStation
,
340 commandName
: OCPP16RequestCommand
,
342 requestPayload
: ReqType
,
345 chargingStation
.isRegistered() === true ||
346 commandName
=== OCPP16RequestCommand
.BOOT_NOTIFICATION
349 this.responseHandlers
.has(commandName
) === true &&
350 OCPP16ServiceUtils
.isRequestCommandSupported(chargingStation
, commandName
) === true
353 this.validatePayload(chargingStation
, commandName
, payload
);
354 await this.responseHandlers
.get(commandName
)!(chargingStation
, payload
, requestPayload
);
357 `${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handle response error:`,
365 ErrorType
.NOT_IMPLEMENTED
,
366 `${commandName} is not implemented to handle response PDU ${JSON.stringify(
377 ErrorType
.SECURITY_ERROR
,
378 `${commandName} cannot be issued to handle response PDU ${JSON.stringify(
382 )} while the charging station is not registered on the central server.`,
389 private validatePayload(
390 chargingStation
: ChargingStation
,
391 commandName
: OCPP16RequestCommand
,
394 if (this.jsonSchemas
.has(commandName
) === true) {
395 return this.validateResponsePayload(
398 this.jsonSchemas
.get(commandName
)!,
403 `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`,
408 private handleResponseBootNotification(
409 chargingStation
: ChargingStation
,
410 payload
: OCPP16BootNotificationResponse
,
412 if (payload
.status === RegistrationStatusEnumType
.ACCEPTED
) {
415 OCPP16StandardParametersKey
.HeartbeatInterval
,
416 payload
.interval
.toString(),
418 { overwrite
: true, save
: true },
422 OCPP16StandardParametersKey
.HeartBeatInterval
,
423 payload
.interval
.toString(),
425 { overwrite
: true, save
: true },
427 OCPP16ServiceUtils
.startHeartbeatInterval(chargingStation
, payload
.interval
);
429 if (Object.values(RegistrationStatusEnumType
).includes(payload
.status)) {
430 const logMsg
= `${chargingStation.logPrefix()} Charging station in '${
432 }' state on the central server`;
433 payload
.status === RegistrationStatusEnumType
.REJECTED
434 ? logger
.warn(logMsg
)
435 : logger
.info(logMsg
);
438 `${chargingStation.logPrefix()} Charging station boot notification response received: %j with undefined registration status`,
444 private handleResponseAuthorize(
445 chargingStation
: ChargingStation
,
446 payload
: OCPP16AuthorizeResponse
,
447 requestPayload
: OCPP16AuthorizeRequest
,
449 let authorizeConnectorId
: number | undefined;
450 if (chargingStation
.hasEvses
) {
451 for (const [evseId
, evseStatus
] of chargingStation
.evses
) {
453 for (const [connectorId
, connectorStatus
] of evseStatus
.connectors
) {
454 if (connectorStatus
?.authorizeIdTag
=== requestPayload
.idTag
) {
455 authorizeConnectorId
= connectorId
;
462 for (const connectorId
of chargingStation
.connectors
.keys()) {
465 chargingStation
.getConnectorStatus(connectorId
)?.authorizeIdTag
=== requestPayload
.idTag
467 authorizeConnectorId
= connectorId
;
472 const authorizeConnectorIdDefined
= !isNullOrUndefined(authorizeConnectorId
);
473 if (payload
.idTagInfo
.status === OCPP16AuthorizationStatus
.ACCEPTED
) {
474 if (authorizeConnectorIdDefined
) {
475 chargingStation
.getConnectorStatus(authorizeConnectorId
!)!.authorizeIdTag
=
476 requestPayload
.idTag
;
477 chargingStation
.getConnectorStatus(authorizeConnectorId
!)!.idTagAuthorized
= true;
480 `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' accepted${
481 authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}
` : ''
485 if (authorizeConnectorIdDefined
) {
486 chargingStation
.getConnectorStatus(authorizeConnectorId
!)!.idTagAuthorized
= false;
487 delete chargingStation
.getConnectorStatus(authorizeConnectorId
!)?.authorizeIdTag
;
490 `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' rejected with status '${
491 payload.idTagInfo.status
492 }'${authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}` : ''}`,
497 private async handleResponseStartTransaction(
498 chargingStation: ChargingStation,
499 payload: OCPP16StartTransactionResponse,
500 requestPayload: OCPP16StartTransactionRequest,
502 const transactionConnectorId = requestPayload.connectorId;
504 transactionConnectorId === 0 ||
505 chargingStation.hasConnector(transactionConnectorId) === false
508 `${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector id ${transactionConnectorId.toString()}
`,
513 chargingStation.getConnectorStatus(transactionConnectorId)?.transactionRemoteStarted ===
515 chargingStation.getAuthorizeRemoteTxRequests() === true &&
516 chargingStation.getLocalAuthListEnabled() === true &&
517 chargingStation.hasIdTags() === true &&
518 chargingStation.getConnectorStatus(transactionConnectorId)?.idTagLocalAuthorized === false
521 `${chargingStation.logPrefix()} Trying to start a transaction
with a not local authorized idTag $
{chargingStation
.getConnectorStatus(
522 transactionConnectorId
,
523 )?.localAuthorizeIdTag
} on connector id ${transactionConnectorId.toString()}
`,
525 await this.resetConnectorOnStartTransactionError(chargingStation, transactionConnectorId);
529 chargingStation.getConnectorStatus(transactionConnectorId)?.transactionRemoteStarted ===
531 chargingStation.getAuthorizeRemoteTxRequests() === true &&
532 chargingStation.getMustAuthorizeAtRemoteStart() === true &&
533 chargingStation.getConnectorStatus(transactionConnectorId)?.idTagLocalAuthorized === false &&
534 chargingStation.getConnectorStatus(transactionConnectorId)?.idTagAuthorized === false
537 `${chargingStation.logPrefix()} Trying to start a transaction
with a not authorized idTag $
{chargingStation
.getConnectorStatus(
538 transactionConnectorId
,
539 )?.authorizeIdTag
} on connector id ${transactionConnectorId.toString()}
`,
541 await this.resetConnectorOnStartTransactionError(chargingStation, transactionConnectorId);
545 chargingStation.getConnectorStatus(transactionConnectorId)?.idTagAuthorized &&
546 chargingStation.getConnectorStatus(transactionConnectorId)?.authorizeIdTag !==
550 `${chargingStation.logPrefix()} Trying to start a transaction
with an idTag $
{
552 } different from the authorize request one $
{chargingStation
.getConnectorStatus(
553 transactionConnectorId
,
554 )?.authorizeIdTag
} on connector id ${transactionConnectorId.toString()}
`,
556 await this.resetConnectorOnStartTransactionError(chargingStation, transactionConnectorId);
560 chargingStation.getConnectorStatus(transactionConnectorId)?.idTagLocalAuthorized &&
561 chargingStation.getConnectorStatus(transactionConnectorId)?.localAuthorizeIdTag !==
565 `${chargingStation.logPrefix()} Trying to start a transaction
with an idTag $
{
567 } different from the local authorized one $
{chargingStation
.getConnectorStatus(
568 transactionConnectorId
,
569 )?.localAuthorizeIdTag
} on connector id ${transactionConnectorId.toString()}
`,
571 await this.resetConnectorOnStartTransactionError(chargingStation, transactionConnectorId);
574 if (chargingStation.getConnectorStatus(transactionConnectorId)?.transactionStarted === true) {
576 `${chargingStation.logPrefix()} Trying to start a transaction on an already used connector id ${transactionConnectorId.toString()}
:`,
577 chargingStation.getConnectorStatus(transactionConnectorId),
581 if (chargingStation.hasEvses) {
582 for (const [evseId, evseStatus] of chargingStation.evses) {
583 if (evseStatus.connectors.size > 1) {
584 for (const [connectorId, connectorStatus] of evseStatus.connectors) {
586 transactionConnectorId !== connectorId &&
587 connectorStatus?.transactionStarted === true
590 `${chargingStation.logPrefix()} Trying to start a transaction on an already used evse id ${evseId.toString()}
:`,
593 await this.resetConnectorOnStartTransactionError(
595 transactionConnectorId,
604 chargingStation.getConnectorStatus(transactionConnectorId)?.status !==
605 OCPP16ChargePointStatus.Available &&
606 chargingStation.getConnectorStatus(transactionConnectorId)?.status !==
607 OCPP16ChargePointStatus.Preparing
610 `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${transactionConnectorId.toString()}
with status $
{chargingStation
.getConnectorStatus(
611 transactionConnectorId
,
616 if (!Number.isInteger(payload.transactionId)) {
618 `${chargingStation.logPrefix()} Trying to start a transaction on connector id ${transactionConnectorId.toString()}
with a non integer transaction id $
{
619 payload
.transactionId
620 }, converting to integer
`,
622 payload.transactionId = convertToInt(payload.transactionId);
625 if (payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) {
626 chargingStation.getConnectorStatus(transactionConnectorId)!.transactionStarted = true;
627 chargingStation.getConnectorStatus(transactionConnectorId)!.transactionStart =
628 requestPayload.timestamp;
629 chargingStation.getConnectorStatus(transactionConnectorId)!.transactionId =
630 payload.transactionId;
631 chargingStation.getConnectorStatus(transactionConnectorId)!.transactionIdTag =
632 requestPayload.idTag;
633 chargingStation.getConnectorStatus(
634 transactionConnectorId,
635 )!.transactionEnergyActiveImportRegisterValue = 0;
636 chargingStation.getConnectorStatus(transactionConnectorId)!.transactionBeginMeterValue =
637 OCPP16ServiceUtils.buildTransactionBeginMeterValue(
639 transactionConnectorId,
640 requestPayload.meterStart,
642 const reservedOnConnectorZero =
643 chargingStation.getConnectorStatus(0)?.status === OCPP16ChargePointStatus.Reserved;
645 chargingStation.getConnectorStatus(transactionConnectorId)?.status ===
646 OCPP16ChargePointStatus.Reserved ||
647 reservedOnConnectorZero
649 await chargingStation.removeReservation(
650 chargingStation.getReservationBy(
652 reservedOnConnectorZero ? 0 : transactionConnectorId,
654 ReservationTerminationReason.TRANSACTION_STARTED,
657 chargingStation.getBeginEndMeterValues() &&
658 (await chargingStation.ocppRequestService.requestHandler<
659 OCPP16MeterValuesRequest,
660 OCPP16MeterValuesResponse
661 >(chargingStation, OCPP16RequestCommand.METER_VALUES, {
662 connectorId: transactionConnectorId,
663 transactionId: payload.transactionId,
665 chargingStation.getConnectorStatus(transactionConnectorId)!.transactionBeginMeterValue,
667 } as OCPP16MeterValuesRequest));
668 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
670 transactionConnectorId,
671 OCPP16ChargePointStatus.Charging,
674 `${chargingStation.logPrefix()} Transaction
with id ${payload.transactionId.toString()} STARTED on $
{
675 chargingStation
.stationInfo
.chargingStationId
676 }#${transactionConnectorId.toString()}
for idTag
'${requestPayload.idTag}'`,
678 if (chargingStation.stationInfo.powerSharedByConnectors) {
679 ++chargingStation.powerDivider;
681 const configuredMeterValueSampleInterval = getConfigurationKey(
683 OCPP16StandardParametersKey.MeterValueSampleInterval,
685 chargingStation.startMeterValues(
686 transactionConnectorId,
687 configuredMeterValueSampleInterval
688 ? secondsToMilliseconds(convertToInt(configuredMeterValueSampleInterval.value))
689 : Constants.DEFAULT_METER_VALUES_INTERVAL,
693 `${chargingStation.logPrefix()} Starting transaction
with id ${payload.transactionId.toString()} REJECTED
with status '${payload
694 .idTagInfo?.status}', idTag
'${requestPayload.idTag}'`,
696 await this.resetConnectorOnStartTransactionError(chargingStation, transactionConnectorId);
700 private async resetConnectorOnStartTransactionError(
701 chargingStation: ChargingStation,
704 resetConnectorStatus(chargingStation.getConnectorStatus(connectorId)!);
705 chargingStation.stopMeterValues(connectorId);
706 parentPort?.postMessage(buildUpdatedMessage(chargingStation));
708 chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.Available
710 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
713 OCPP16ChargePointStatus.Available,
718 private async handleResponseStopTransaction(
719 chargingStation: ChargingStation,
720 payload: OCPP16StopTransactionResponse,
721 requestPayload: OCPP16StopTransactionRequest,
723 const transactionConnectorId = chargingStation.getConnectorIdByTransactionId(
724 requestPayload.transactionId,
726 if (isNullOrUndefined(transactionConnectorId)) {
728 `${chargingStation.logPrefix()} Trying to stop a non existing transaction
with id ${requestPayload.transactionId.toString()}
`,
732 chargingStation.getBeginEndMeterValues() === true &&
733 chargingStation.getOcppStrictCompliance() === false &&
734 chargingStation.getOutOfOrderEndMeterValues() === true &&
735 (await chargingStation.ocppRequestService.requestHandler<
736 OCPP16MeterValuesRequest,
737 OCPP16MeterValuesResponse
738 >(chargingStation, OCPP16RequestCommand.METER_VALUES, {
739 connectorId: transactionConnectorId,
740 transactionId: requestPayload.transactionId,
742 OCPP16ServiceUtils.buildTransactionEndMeterValue(
744 transactionConnectorId!,
745 requestPayload.meterStop,
750 chargingStation.isChargingStationAvailable() === false ||
751 chargingStation.isConnectorAvailable(transactionConnectorId!) === false
753 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
755 transactionConnectorId!,
756 OCPP16ChargePointStatus.Unavailable,
759 await OCPP16ServiceUtils.sendAndSetConnectorStatus(
761 transactionConnectorId!,
762 OCPP16ChargePointStatus.Available,
765 if (chargingStation.stationInfo.powerSharedByConnectors) {
766 chargingStation.powerDivider--;
768 resetConnectorStatus(chargingStation.getConnectorStatus(transactionConnectorId!)!);
769 chargingStation.stopMeterValues(transactionConnectorId!);
770 parentPort?.postMessage(buildUpdatedMessage(chargingStation));
771 const logMsg = `${chargingStation.logPrefix()} Transaction
with id ${requestPayload.transactionId.toString()} STOPPED on $
{
772 chargingStation
.stationInfo
.chargingStationId
773 }#${transactionConnectorId?.toString()}
with status '${
774 payload.idTagInfo?.status ?? 'undefined'
777 isNullOrUndefined(payload.idTagInfo) ||
778 payload.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED