OCPP: Cleanup helpers
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16ServiceUtils.ts
index 0915aa462b3fa70deefacd04cdcdc9918063c2fc..741db1d32a948a910ae5a968dc24a7316014dd97 100644 (file)
@@ -2,10 +2,12 @@
 
 import OCPPError from '../../../exception/OCPPError';
 import { CurrentType, Voltage } from '../../../types/ChargingStationTemplate';
-import type MeasurandPerPhaseSampledValueTemplates from '../../../types/MeasurandPerPhaseSampledValueTemplates';
-// eslint-disable-next-line no-duplicate-imports
-import type { SampledValueTemplate } from '../../../types/MeasurandPerPhaseSampledValueTemplates';
-import type MeasurandValues from '../../../types/MeasurandValues';
+import type {
+  MeasurandPerPhaseSampledValueTemplates,
+  SampledValueTemplate,
+} from '../../../types/MeasurandPerPhaseSampledValueTemplates';
+import type { MeasurandValues } from '../../../types/MeasurandValues';
+import type { OCPP16ChargingProfile } from '../../../types/ocpp/1.6/ChargingProfile';
 import {
   OCPP16StandardParametersKey,
   OCPP16SupportedFeatureProfiles,
@@ -29,7 +31,6 @@ import { ACElectricUtils, DCElectricUtils } from '../../../utils/ElectricUtils';
 import logger from '../../../utils/Logger';
 import Utils from '../../../utils/Utils';
 import type ChargingStation from '../../ChargingStation';
-import { ChargingStationUtils } from '../../ChargingStationUtils';
 import { OCPPServiceUtils } from '../OCPPServiceUtils';
 
 export class OCPP16ServiceUtils extends OCPPServiceUtils {
@@ -62,7 +63,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     };
     const connector = chargingStation.getConnectorStatus(connectorId);
     // SoC measurand
-    const socSampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const socSampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId,
       OCPP16MeterValueMeasurand.STATE_OF_CHARGE
@@ -90,7 +91,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       }
     }
     // Voltage measurand
-    const voltageSampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const voltageSampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId,
       OCPP16MeterValueMeasurand.VOLTAGE
@@ -120,7 +121,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       ) {
         const phaseLineToNeutralValue = `L${phase}-N`;
         const voltagePhaseLineToNeutralSampledValueTemplate =
-          ChargingStationUtils.getSampledValueTemplate(
+          OCPP16ServiceUtils.getSampledValueTemplate(
             chargingStation,
             connectorId,
             OCPP16MeterValueMeasurand.VOLTAGE,
@@ -155,7 +156,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               : chargingStation.getNumberOfPhases()
           }`;
           const voltagePhaseLineToLineSampledValueTemplate =
-            ChargingStationUtils.getSampledValueTemplate(
+            OCPP16ServiceUtils.getSampledValueTemplate(
               chargingStation,
               connectorId,
               OCPP16MeterValueMeasurand.VOLTAGE,
@@ -191,7 +192,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       }
     }
     // Power.Active.Import measurand
-    const powerSampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const powerSampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId,
       OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT
@@ -199,19 +200,19 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     let powerPerPhaseSampledValueTemplates: MeasurandPerPhaseSampledValueTemplates = {};
     if (chargingStation.getNumberOfPhases() === 3) {
       powerPerPhaseSampledValueTemplates = {
-        L1: ChargingStationUtils.getSampledValueTemplate(
+        L1: OCPP16ServiceUtils.getSampledValueTemplate(
           chargingStation,
           connectorId,
           OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT,
           OCPP16MeterValuePhase.L1_N
         ),
-        L2: ChargingStationUtils.getSampledValueTemplate(
+        L2: OCPP16ServiceUtils.getSampledValueTemplate(
           chargingStation,
           connectorId,
           OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT,
           OCPP16MeterValuePhase.L2_N
         ),
-        L3: ChargingStationUtils.getSampledValueTemplate(
+        L3: OCPP16ServiceUtils.getSampledValueTemplate(
           chargingStation,
           connectorId,
           OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT,
@@ -224,7 +225,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
         chargingStation,
         powerSampledValueTemplate.measurand
       );
-      const errMsg = `${chargingStation.logPrefix()} MeterValues measurand ${
+      const errMsg = `MeterValues measurand ${
         powerSampledValueTemplate.measurand ??
         OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
       }: Unknown ${chargingStation.getCurrentOutType()} currentOutType in template file ${
@@ -334,7 +335,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             : Utils.getRandomFloatRounded(connectorMaximumPower / unitDivider);
           break;
         default:
-          logger.error(errMsg);
+          logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
           throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, OCPP16RequestCommand.METER_VALUES);
       }
       meterValue.sampledValue.push(
@@ -398,7 +399,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       }
     }
     // Current.Import measurand
-    const currentSampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const currentSampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId,
       OCPP16MeterValueMeasurand.CURRENT_IMPORT
@@ -406,19 +407,19 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     let currentPerPhaseSampledValueTemplates: MeasurandPerPhaseSampledValueTemplates = {};
     if (chargingStation.getNumberOfPhases() === 3) {
       currentPerPhaseSampledValueTemplates = {
-        L1: ChargingStationUtils.getSampledValueTemplate(
+        L1: OCPP16ServiceUtils.getSampledValueTemplate(
           chargingStation,
           connectorId,
           OCPP16MeterValueMeasurand.CURRENT_IMPORT,
           OCPP16MeterValuePhase.L1
         ),
-        L2: ChargingStationUtils.getSampledValueTemplate(
+        L2: OCPP16ServiceUtils.getSampledValueTemplate(
           chargingStation,
           connectorId,
           OCPP16MeterValueMeasurand.CURRENT_IMPORT,
           OCPP16MeterValuePhase.L2
         ),
-        L3: ChargingStationUtils.getSampledValueTemplate(
+        L3: OCPP16ServiceUtils.getSampledValueTemplate(
           chargingStation,
           connectorId,
           OCPP16MeterValueMeasurand.CURRENT_IMPORT,
@@ -431,7 +432,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
         chargingStation,
         currentSampledValueTemplate.measurand
       );
-      const errMsg = `${chargingStation.logPrefix()} MeterValues measurand ${
+      const errMsg = `MeterValues measurand ${
         currentSampledValueTemplate.measurand ??
         OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
       }: Unknown ${chargingStation.getCurrentOutType()} currentOutType in template file ${
@@ -547,7 +548,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             : Utils.getRandomFloatRounded(connectorMaximumAmperage);
           break;
         default:
-          logger.error(errMsg);
+          logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
           throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, OCPP16RequestCommand.METER_VALUES);
       }
       meterValue.sampledValue.push(
@@ -606,7 +607,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       }
     }
     // Energy.Active.Import.Register measurand (default)
-    const energySampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const energySampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId
     );
@@ -689,7 +690,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       sampledValue: [],
     };
     // Energy.Active.Import.Register measurand (default)
-    const sampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const sampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId
     );
@@ -714,7 +715,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       sampledValue: [],
     };
     // Energy.Active.Import.Register measurand (default)
-    const sampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const sampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId
     );
@@ -739,6 +740,41 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     return meterValues;
   }
 
+  public static setChargingProfile(
+    chargingStation: ChargingStation,
+    connectorId: number,
+    cp: OCPP16ChargingProfile
+  ): void {
+    if (Utils.isNullOrUndefined(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) {
+      logger.error(
+        `${chargingStation.logPrefix()} Trying to set a charging profile on connectorId ${connectorId} with an uninitialized charging profiles array attribute, applying deferred initialization`
+      );
+      chargingStation.getConnectorStatus(connectorId).chargingProfiles = [];
+    }
+    if (Array.isArray(chargingStation.getConnectorStatus(connectorId).chargingProfiles) === false) {
+      logger.error(
+        `${chargingStation.logPrefix()} Trying to set a charging profile on connectorId ${connectorId} with an improper attribute type for the charging profiles array, applying proper type initialization`
+      );
+      chargingStation.getConnectorStatus(connectorId).chargingProfiles = [];
+    }
+    let cpReplaced = false;
+    if (!Utils.isEmptyArray(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) {
+      chargingStation
+        .getConnectorStatus(connectorId)
+        .chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
+          if (
+            chargingProfile.chargingProfileId === cp.chargingProfileId ||
+            (chargingProfile.stackLevel === cp.stackLevel &&
+              chargingProfile.chargingProfilePurpose === cp.chargingProfilePurpose)
+          ) {
+            chargingStation.getConnectorStatus(connectorId).chargingProfiles[index] = cp;
+            cpReplaced = true;
+          }
+        });
+    }
+    !cpReplaced && chargingStation.getConnectorStatus(connectorId).chargingProfiles?.push(cp);
+  }
+
   private static buildSampledValue(
     sampledValueTemplate: SampledValueTemplate,
     value: number,
@@ -770,16 +806,16 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     measurandType: OCPP16MeterValueMeasurand
   ): void {
     if (Utils.isUndefined(chargingStation.powerDivider)) {
-      const errMsg = `${chargingStation.logPrefix()} MeterValues measurand ${
+      const errMsg = `MeterValues measurand ${
         measurandType ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
       }: powerDivider is undefined`;
-      logger.error(errMsg);
+      logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
       throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, OCPP16RequestCommand.METER_VALUES);
     } else if (chargingStation?.powerDivider <= 0) {
-      const errMsg = `${chargingStation.logPrefix()} MeterValues measurand ${
+      const errMsg = `MeterValues measurand ${
         measurandType ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
       }: powerDivider have zero or below value ${chargingStation.powerDivider}`;
-      logger.error(errMsg);
+      logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
       throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, OCPP16RequestCommand.METER_VALUES);
     }
   }