From a2653482348f1183b4f8852d43f23dbff711bd83 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Wed, 6 Oct 2021 16:30:04 +0200 Subject: [PATCH] Add more sanity checks at remote start transaction MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- src/charging-station/ChargingStation.ts | 15 ++++--- .../ocpp/1.6/OCPP16IncomingRequestService.ts | 8 ++-- .../ocpp/1.6/OCPP16ResponseService.ts | 42 +++++++++++++++---- src/types/Connectors.ts | 5 ++- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 6e57931b..49c95d1e 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -400,9 +400,12 @@ export default class ChargingStation { !cpReplaced && this.getConnectorStatus(connectorId).chargingProfiles?.push(cp); } - public resetTransactionOnConnector(connectorId: number): void { - this.getConnectorStatus(connectorId).authorized = false; + public resetConnectorStatus(connectorId: number): void { + this.getConnectorStatus(connectorId).idTagLocalAuthorized = false; + this.getConnectorStatus(connectorId).idTagAuthorized = false; + this.getConnectorStatus(connectorId).transactionRemoteStarted = false; this.getConnectorStatus(connectorId).transactionStarted = false; + delete this.getConnectorStatus(connectorId).localAuthorizeIdTag; delete this.getConnectorStatus(connectorId).authorizeIdTag; delete this.getConnectorStatus(connectorId).transactionId; delete this.getConnectorStatus(connectorId).transactionIdTag; @@ -533,7 +536,7 @@ export default class ChargingStation { // Initialize transaction attributes on connectors for (const connectorId of this.connectors.keys()) { if (connectorId > 0 && !this.getConnectorStatus(connectorId)?.transactionStarted) { - this.initTransactionAttributesOnConnector(connectorId); + this.initializeConnectorStatus(connectorId); } } switch (this.getOCPPVersion()) { @@ -1050,8 +1053,10 @@ export default class ChargingStation { } } - private initTransactionAttributesOnConnector(connectorId: number): void { - this.getConnectorStatus(connectorId).authorized = false; + private initializeConnectorStatus(connectorId: number): void { + this.getConnectorStatus(connectorId).idTagLocalAuthorized = false; + this.getConnectorStatus(connectorId).idTagAuthorized = false; + this.getConnectorStatus(connectorId).transactionRemoteStarted = false; this.getConnectorStatus(connectorId).transactionStarted = false; this.getConnectorStatus(connectorId).energyActiveImportRegisterValue = 0; this.getConnectorStatus(connectorId).transactionEnergyActiveImportRegisterValue = 0; diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 94f98e8b..1aa5a9bb 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -293,19 +293,20 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer let authorized = false; if (this.chargingStation.getLocalAuthListEnabled() && this.chargingStation.hasAuthorizedTags() && this.chargingStation.authorizedTags.find((value) => value === commandPayload.idTag)) { + this.chargingStation.getConnectorStatus(transactionConnectorId).localAuthorizeIdTag = commandPayload.idTag; + this.chargingStation.getConnectorStatus(transactionConnectorId).idTagLocalAuthorized = true; authorized = true; } - if (!authorized || (authorized && this.chargingStation.getMayAuthorizeAtRemoteStart())) { + if (!authorized && this.chargingStation.getMayAuthorizeAtRemoteStart()) { const authorizeResponse = await this.chargingStation.ocppRequestService.sendAuthorize(transactionConnectorId, commandPayload.idTag); if (authorizeResponse?.idTagInfo?.status === OCPP16AuthorizationStatus.ACCEPTED) { authorized = true; - } else { - authorized = false; } } if (authorized) { // Authorization successful, start transaction if (this.setRemoteStartTransactionChargingProfile(transactionConnectorId, commandPayload.chargingProfile)) { + this.chargingStation.getConnectorStatus(transactionConnectorId).transactionRemoteStarted = true; if ((await this.chargingStation.ocppRequestService.sendStartTransaction(transactionConnectorId, commandPayload.idTag)).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED) { logger.debug(this.chargingStation.logPrefix() + ' Transaction remotely STARTED on ' + this.chargingStation.stationInfo.chargingStationId + '#' + transactionConnectorId.toString() + ' for idTag ' + commandPayload.idTag); return Constants.OCPP_RESPONSE_ACCEPTED; @@ -318,6 +319,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer } // No authorization check required, start transaction if (this.setRemoteStartTransactionChargingProfile(transactionConnectorId, commandPayload.chargingProfile)) { + this.chargingStation.getConnectorStatus(transactionConnectorId).transactionRemoteStarted = true; if ((await this.chargingStation.ocppRequestService.sendStartTransaction(transactionConnectorId, commandPayload.idTag)).idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED) { logger.debug(this.chargingStation.logPrefix() + ' Transaction remotely STARTED on ' + this.chargingStation.stationInfo.chargingStationId + '#' + transactionConnectorId.toString() + ' for idTag ' + commandPayload.idTag); return Constants.OCPP_RESPONSE_ACCEPTED; diff --git a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts index cc334aee..2c2b8048 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts @@ -67,10 +67,10 @@ export default class OCPP16ResponseService extends OCPPResponseService { } } if (payload.idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED) { - this.chargingStation.getConnectorStatus(authorizeConnectorId).authorized = true; + this.chargingStation.getConnectorStatus(authorizeConnectorId).idTagAuthorized = true; logger.debug(`${this.chargingStation.logPrefix()} IdTag ${requestPayload.idTag} authorized on connector ${authorizeConnectorId}`); } else { - this.chargingStation.getConnectorStatus(authorizeConnectorId).authorized = false; + this.chargingStation.getConnectorStatus(authorizeConnectorId).idTagAuthorized = false; delete this.chargingStation.getConnectorStatus(authorizeConnectorId).authorizeIdTag; logger.debug(`${this.chargingStation.logPrefix()} IdTag ${requestPayload.idTag} refused with status ${payload.idTagInfo.status} on connector ${authorizeConnectorId}`); } @@ -90,8 +90,28 @@ export default class OCPP16ResponseService extends OCPPResponseService { logger.error(this.chargingStation.logPrefix() + ' Trying to start a transaction on a non existing connector Id ' + connectorId.toString()); return; } - if (this.chargingStation.getConnectorStatus(connectorId).authorized && this.chargingStation.getConnectorStatus(connectorId).authorizeIdTag !== requestPayload.idTag) { + if (this.chargingStation.getConnectorStatus(connectorId).transactionRemoteStarted && this.chargingStation.getAuthorizeRemoteTxRequests() + && this.chargingStation.getLocalAuthListEnabled() && this.chargingStation.hasAuthorizedTags() && !this.chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized) { + logger.error(this.chargingStation.logPrefix() + ' Trying to start a transaction with a not local authorized idTag ' + this.chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag + ' on connector Id ' + connectorId.toString()); + await this.resetConnectorOnStartTransactionError(connectorId); + return; + } + if (this.chargingStation.getConnectorStatus(connectorId).transactionRemoteStarted && this.chargingStation.getAuthorizeRemoteTxRequests() + && this.chargingStation.getMayAuthorizeAtRemoteStart() && !this.chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized + && !this.chargingStation.getConnectorStatus(connectorId).idTagAuthorized) { + logger.error(this.chargingStation.logPrefix() + ' Trying to start a transaction with a not authorized idTag ' + this.chargingStation.getConnectorStatus(connectorId).authorizeIdTag + ' on connector Id ' + connectorId.toString()); + await this.resetConnectorOnStartTransactionError(connectorId); + return; + } + if (this.chargingStation.getConnectorStatus(connectorId).idTagAuthorized && this.chargingStation.getConnectorStatus(connectorId).authorizeIdTag !== requestPayload.idTag) { logger.error(this.chargingStation.logPrefix() + ' Trying to start a transaction with an idTag ' + requestPayload.idTag + ' different from the authorize request one ' + this.chargingStation.getConnectorStatus(connectorId).authorizeIdTag + ' on connector Id ' + connectorId.toString()); + await this.resetConnectorOnStartTransactionError(connectorId); + return; + } + if (this.chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized + && this.chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag !== requestPayload.idTag) { + logger.error(this.chargingStation.logPrefix() + ' Trying to start a transaction with an idTag ' + requestPayload.idTag + ' different from the local authorized one ' + this.chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag + ' on connector Id ' + connectorId.toString()); + await this.resetConnectorOnStartTransactionError(connectorId); return; } if (this.chargingStation.getConnectorStatus(connectorId)?.transactionStarted) { @@ -127,11 +147,15 @@ export default class OCPP16ResponseService extends OCPPResponseService { this.chargingStation.startMeterValues(connectorId, configuredMeterValueSampleInterval ? Utils.convertToInt(configuredMeterValueSampleInterval.value) * 1000 : 60000); } else { logger.warn(this.chargingStation.logPrefix() + ' Starting transaction id ' + payload.transactionId.toString() + ' REJECTED with status ' + payload?.idTagInfo?.status + ', idTag ' + requestPayload.idTag); - this.chargingStation.resetTransactionOnConnector(connectorId); - if (this.chargingStation.getConnectorStatus(connectorId).status !== OCPP16ChargePointStatus.AVAILABLE) { - await this.chargingStation.ocppRequestService.sendStatusNotification(connectorId, OCPP16ChargePointStatus.AVAILABLE); - this.chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.AVAILABLE; - } + await this.resetConnectorOnStartTransactionError(connectorId); + } + } + + private async resetConnectorOnStartTransactionError(connectorId: number): Promise { + this.chargingStation.resetConnectorStatus(connectorId); + if (this.chargingStation.getConnectorStatus(connectorId).status !== OCPP16ChargePointStatus.AVAILABLE) { + await this.chargingStation.ocppRequestService.sendStatusNotification(connectorId, OCPP16ChargePointStatus.AVAILABLE); + this.chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.AVAILABLE; } } @@ -162,7 +186,7 @@ export default class OCPP16ResponseService extends OCPPResponseService { this.chargingStation.stationInfo.powerDivider--; } logger.info(this.chargingStation.logPrefix() + ' Transaction ' + requestPayload.transactionId.toString() + ' STOPPED on ' + this.chargingStation.stationInfo.chargingStationId + '#' + transactionConnectorId.toString()); - this.chargingStation.resetTransactionOnConnector(transactionConnectorId); + this.chargingStation.resetConnectorStatus(transactionConnectorId); } else { logger.warn(this.chargingStation.logPrefix() + ' Stopping transaction id ' + requestPayload.transactionId.toString() + ' REJECTED with status ' + payload.idTagInfo?.status); } diff --git a/src/types/Connectors.ts b/src/types/Connectors.ts index d2c26240..027ac645 100644 --- a/src/types/Connectors.ts +++ b/src/types/Connectors.ts @@ -14,7 +14,10 @@ export interface ConnectorStatus { status?: ChargePointStatus; MeterValues: SampledValueTemplate[]; authorizeIdTag?: string; - authorized?: boolean; + idTagAuthorized?: boolean; + localAuthorizeIdTag?: string; + idTagLocalAuthorized?: boolean; + transactionRemoteStarted?: boolean; transactionStarted?: boolean; transactionId?: number; transactionSetInterval?: NodeJS.Timeout; -- 2.34.1