From 28e78158b290b14a09f64adbff0ddb3daf8c5588 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Thu, 27 Apr 2023 20:21:31 +0200 Subject: [PATCH] feat: add initial support to evses handling MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Reference: https://github.com/SAP/e-mobility-charging-stations-simulator/issues/349 Signed-off-by: Jérôme Benoit --- .../schneider-evses.station-template.json | 6 +- src/charging-station/ChargingStation.ts | 152 ++++++++++++++---- .../ocpp/1.6/OCPP16ResponseService.ts | 9 +- 3 files changed, 125 insertions(+), 42 deletions(-) diff --git a/src/assets/station-templates/schneider-evses.station-template.json b/src/assets/station-templates/schneider-evses.station-template.json index 6d62c528..7017f1e4 100644 --- a/src/assets/station-templates/schneider-evses.station-template.json +++ b/src/assets/station-templates/schneider-evses.station-template.json @@ -59,7 +59,11 @@ "idTagDistribution": "round-robin" }, "Evses": { - "0": {}, + "0": { + "Connectors": { + "0": {} + } + }, "1": { "Connectors": { "1": { diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index b3d4bdd9..9d87153a 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -165,6 +165,10 @@ export class ChargingStation { ); } + private get hasEvses(): boolean { + return this.connectors.size === 0 && this.evses.size > 0; + } + public logPrefix = (): string => { return Utils.logPrefix( ` ${ @@ -240,16 +244,40 @@ export class ChargingStation { return this.getConnectorStatus(0)?.availability === AvailabilityType.Operative; } - public isConnectorAvailable(id: number): boolean { - return id > 0 && this.getConnectorStatus(id)?.availability === AvailabilityType.Operative; + public isConnectorAvailable(connectorId: number): boolean { + return ( + connectorId > 0 && + this.getConnectorStatus(connectorId)?.availability === AvailabilityType.Operative + ); } public getNumberOfConnectors(): number { + if (this.hasEvses) { + let numberOfConnectors = 0; + for (const [evseId, evseStatus] of this.evses) { + if (evseId === 0) { + continue; + } + numberOfConnectors += evseStatus.connectors.size; + } + return numberOfConnectors; + } return this.connectors.get(0) ? this.connectors.size - 1 : this.connectors.size; } - public getConnectorStatus(id: number): ConnectorStatus | undefined { - return this.connectors.get(id); + public getNumberOfEvses(): number { + return this.evses.size; + } + + public getConnectorStatus(connectorId: number): ConnectorStatus | undefined { + if (this.hasEvses) { + for (const evseStatus of this.evses.values()) { + if (evseStatus.connectors.has(connectorId)) { + return evseStatus.connectors.get(connectorId); + } + } + } + return this.connectors.get(connectorId); } public getCurrentOutType(stationInfo?: ChargingStationInfo): CurrentType { @@ -306,12 +334,22 @@ export class ChargingStation { } public getTransactionIdTag(transactionId: number): string | undefined { - for (const connectorId of this.connectors.keys()) { - if ( - connectorId > 0 && - this.getConnectorStatus(connectorId)?.transactionId === transactionId - ) { - return this.getConnectorStatus(connectorId)?.transactionIdTag; + if (this.hasEvses) { + for (const evseStatus of this.evses.values()) { + for (const connectorStatus of evseStatus.connectors.values()) { + if (connectorStatus.transactionId === transactionId) { + return connectorStatus.transactionIdTag; + } + } + } + } else { + for (const connectorId of this.connectors.keys()) { + if ( + connectorId > 0 && + this.getConnectorStatus(connectorId)?.transactionId === transactionId + ) { + return this.getConnectorStatus(connectorId)?.transactionIdTag; + } } } } @@ -345,12 +383,22 @@ export class ChargingStation { } public getConnectorIdByTransactionId(transactionId: number): number | undefined { - for (const connectorId of this.connectors.keys()) { - if ( - connectorId > 0 && - this.getConnectorStatus(connectorId)?.transactionId === transactionId - ) { - return connectorId; + if (this.hasEvses) { + for (const evseStatus of this.evses.values()) { + for (const [connectorId, connectorStatus] of evseStatus.connectors) { + if (connectorStatus.transactionId === transactionId) { + return connectorId; + } + } + } + } else { + for (const connectorId of this.connectors.keys()) { + if ( + connectorId > 0 && + this.getConnectorStatus(connectorId)?.transactionId === transactionId + ) { + return connectorId; + } } } } @@ -1149,17 +1197,35 @@ export class ChargingStation { ) ) { const connectorPhaseRotation = []; - for (const connectorId of this.connectors.keys()) { - // AC/DC - if (connectorId === 0 && this.getNumberOfPhases() === 0) { - connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.RST}`); - } else if (connectorId > 0 && this.getNumberOfPhases() === 0) { - connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.NotApplicable}`); - // AC - } else if (connectorId > 0 && this.getNumberOfPhases() === 1) { - connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.NotApplicable}`); - } else if (connectorId > 0 && this.getNumberOfPhases() === 3) { - connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.RST}`); + if (this.hasEvses) { + for (const evseStatus of this.evses.values()) { + for (const connectorId of evseStatus.connectors.keys()) { + // AC/DC + if (connectorId === 0 && this.getNumberOfPhases() === 0) { + connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.RST}`); + } else if (connectorId > 0 && this.getNumberOfPhases() === 0) { + connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.NotApplicable}`); + // AC + } else if (connectorId > 0 && this.getNumberOfPhases() === 1) { + connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.NotApplicable}`); + } else if (connectorId > 0 && this.getNumberOfPhases() === 3) { + connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.RST}`); + } + } + } + } else { + for (const connectorId of this.connectors.keys()) { + // AC/DC + if (connectorId === 0 && this.getNumberOfPhases() === 0) { + connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.RST}`); + } else if (connectorId > 0 && this.getNumberOfPhases() === 0) { + connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.NotApplicable}`); + // AC + } else if (connectorId > 0 && this.getNumberOfPhases() === 1) { + connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.NotApplicable}`); + } else if (connectorId > 0 && this.getNumberOfPhases() === 3) { + connectorPhaseRotation.push(`${connectorId}.${ConnectorPhaseRotation.RST}`); + } } } ChargingStationConfigurationUtils.addConfigurationKey( @@ -1758,18 +1824,38 @@ export class ChargingStation { private getNumberOfRunningTransactions(): number { let trxCount = 0; - for (const connectorId of this.connectors.keys()) { - if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) { - trxCount++; + if (this.hasEvses) { + for (const evseStatus of this.evses.values()) { + for (const connectorStatus of evseStatus.connectors.values()) { + if (connectorStatus.transactionStarted === true) { + trxCount++; + } + } + } + } else { + for (const connectorId of this.connectors.keys()) { + if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) { + trxCount++; + } } } return trxCount; } private async stopRunningTransactions(reason = StopTransactionReason.NONE): Promise { - for (const connectorId of this.connectors.keys()) { - if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) { - await this.stopTransactionOnConnector(connectorId, reason); + if (this.hasEvses) { + for (const evseStatus of this.evses.values()) { + for (const [connectorId, connectorStatus] of evseStatus.connectors) { + if (connectorStatus.transactionStarted === true) { + await this.stopTransactionOnConnector(connectorId, reason); + } + } + } + } else { + for (const connectorId of this.connectors.keys()) { + if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) { + await this.stopTransactionOnConnector(connectorId, reason); + } } } } diff --git a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts index c83c83ef..a082653d 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts @@ -441,14 +441,7 @@ export class OCPP16ResponseService extends OCPPResponseService { ): Promise { const connectorId = requestPayload.connectorId; - let transactionConnectorId: number; - for (const id of chargingStation.connectors.keys()) { - if (id > 0 && id === connectorId) { - transactionConnectorId = id; - break; - } - } - if (Utils.isNullOrUndefined(transactionConnectorId)) { + if (connectorId === 0 || !chargingStation.connectors.has(connectorId)) { logger.error( `${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector id ${connectorId.toString()}` ); -- 2.34.1