feat: add initial support to evses handling
authorJérôme Benoit <jerome.benoit@sap.com>
Thu, 27 Apr 2023 18:21:31 +0000 (20:21 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Thu, 27 Apr 2023 18:21:31 +0000 (20:21 +0200)
Reference: https://github.com/SAP/e-mobility-charging-stations-simulator/issues/349

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/assets/station-templates/schneider-evses.station-template.json
src/charging-station/ChargingStation.ts
src/charging-station/ocpp/1.6/OCPP16ResponseService.ts

index 6d62c52800d47f340fe722e92fee621841e0febb..7017f1e427f1382bf0cebee8ce4c87cc1175a364 100644 (file)
     "idTagDistribution": "round-robin"
   },
   "Evses": {
-    "0": {},
+    "0": {
+      "Connectors": {
+        "0": {}
+      }
+    },
     "1": {
       "Connectors": {
         "1": {
index b3d4bdd98016cbf5d35288c15bff552417859497..9d87153a3e0437cd5f767b96fcee39e4edb2333b 100644 (file)
@@ -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<void> {
-    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);
+        }
       }
     }
   }
index c83c83eff5b6b421c2d46582d870ffbfcfaa2638..a082653d7de498eb31b63d5ec34ef32863afe2fb 100644 (file)
@@ -441,14 +441,7 @@ export class OCPP16ResponseService extends OCPPResponseService {
   ): Promise<void> {
     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()}`
       );