Cleanup shared helpers structure
authorJérôme Benoit <jerome.benoit@sap.com>
Sun, 2 Oct 2022 05:36:54 +0000 (07:36 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Sun, 2 Oct 2022 05:36:54 +0000 (07:36 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
src/charging-station/ChargingStationUtils.ts
src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
src/charging-station/ocpp/1.6/OCPP16RequestService.ts
src/charging-station/ocpp/1.6/OCPP16ResponseService.ts
src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts
src/charging-station/ocpp/OCPPServiceUtils.ts
src/charging-station/ui-server/UIHttpServer.ts
src/charging-station/ui-server/UIServerFactory.ts
src/charging-station/ui-server/UIServerUtils.ts [moved from src/charging-station/ui-server/ui-services/UIServiceUtils.ts with 82% similarity]
src/charging-station/ui-server/UIWebSocketServer.ts

index e378fdec87bd26832ce1abf4ebe2cddd53b8a1b9..1670fb00e09a4f133b7ea51e88d9db9bde422490 100644 (file)
@@ -12,23 +12,14 @@ import {
   CurrentType,
   Voltage,
 } from '../types/ChargingStationTemplate';
-import type { SampledValueTemplate } from '../types/MeasurandPerPhaseSampledValueTemplates';
 import { ChargingProfileKindType, RecurrencyKindType } from '../types/ocpp/1.6/ChargingProfile';
 import type { ChargingProfile, ChargingSchedulePeriod } from '../types/ocpp/ChargingProfile';
-import { StandardParametersKey } from '../types/ocpp/Configuration';
-import { MeterValueMeasurand, MeterValuePhase } from '../types/ocpp/MeterValues';
-import {
-  type BootNotificationRequest,
-  IncomingRequestCommand,
-  RequestCommand,
-} from '../types/ocpp/Requests';
+import type { BootNotificationRequest } from '../types/ocpp/Requests';
 import { WorkerProcessType } from '../types/Worker';
 import Configuration from '../utils/Configuration';
 import Constants from '../utils/Constants';
 import logger from '../utils/Logger';
 import Utils from '../utils/Utils';
-import type ChargingStation from './ChargingStation';
-import { ChargingStationConfigurationUtils } from './ChargingStationConfigurationUtils';
 
 const moduleName = 'ChargingStationUtils';
 
@@ -289,41 +280,6 @@ export class ChargingStationUtils {
     return unitDivider;
   }
 
-  public static setChargingProfile(
-    chargingStation: ChargingStation,
-    connectorId: number,
-    cp: ChargingProfile
-  ): 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: ChargingProfile, 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);
-  }
-
   /**
    * Charging profiles should already be sorted by connectorId and stack level (highest stack level has priority)
    *
@@ -442,87 +398,6 @@ export class ChargingStationUtils {
     return defaultVoltageOut;
   }
 
-  public static getSampledValueTemplate(
-    chargingStation: ChargingStation,
-    connectorId: number,
-    measurand: MeterValueMeasurand = MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
-    phase?: MeterValuePhase
-  ): SampledValueTemplate | undefined {
-    const onPhaseStr = phase ? `on phase ${phase} ` : '';
-    if (Constants.SUPPORTED_MEASURANDS.includes(measurand) === false) {
-      logger.warn(
-        `${chargingStation.logPrefix()} Trying to get unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connectorId ${connectorId}`
-      );
-      return;
-    }
-    if (
-      measurand !== MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER &&
-      !ChargingStationConfigurationUtils.getConfigurationKey(
-        chargingStation,
-        StandardParametersKey.MeterValuesSampledData
-      )?.value.includes(measurand)
-    ) {
-      logger.debug(
-        `${chargingStation.logPrefix()} Trying to get MeterValues measurand '${measurand}' ${onPhaseStr}in template on connectorId ${connectorId} not found in '${
-          StandardParametersKey.MeterValuesSampledData
-        }' OCPP parameter`
-      );
-      return;
-    }
-    const sampledValueTemplates: SampledValueTemplate[] =
-      chargingStation.getConnectorStatus(connectorId).MeterValues;
-    for (
-      let index = 0;
-      !Utils.isEmptyArray(sampledValueTemplates) && index < sampledValueTemplates.length;
-      index++
-    ) {
-      if (
-        Constants.SUPPORTED_MEASURANDS.includes(
-          sampledValueTemplates[index]?.measurand ??
-            MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
-        ) === false
-      ) {
-        logger.warn(
-          `${chargingStation.logPrefix()} Unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connectorId ${connectorId}`
-        );
-      } else if (
-        phase &&
-        sampledValueTemplates[index]?.phase === phase &&
-        sampledValueTemplates[index]?.measurand === measurand &&
-        ChargingStationConfigurationUtils.getConfigurationKey(
-          chargingStation,
-          StandardParametersKey.MeterValuesSampledData
-        )?.value.includes(measurand) === true
-      ) {
-        return sampledValueTemplates[index];
-      } else if (
-        !phase &&
-        !sampledValueTemplates[index].phase &&
-        sampledValueTemplates[index]?.measurand === measurand &&
-        ChargingStationConfigurationUtils.getConfigurationKey(
-          chargingStation,
-          StandardParametersKey.MeterValuesSampledData
-        )?.value.includes(measurand) === true
-      ) {
-        return sampledValueTemplates[index];
-      } else if (
-        measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER &&
-        (!sampledValueTemplates[index].measurand ||
-          sampledValueTemplates[index].measurand === measurand)
-      ) {
-        return sampledValueTemplates[index];
-      }
-    }
-    if (measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) {
-      const errorMsg = `Missing MeterValues for default measurand '${measurand}' in template on connectorId ${connectorId}`;
-      logger.error(`${chargingStation.logPrefix()} ${errorMsg}`);
-      throw new BaseError(errorMsg);
-    }
-    logger.debug(
-      `${chargingStation.logPrefix()} No MeterValues for measurand '${measurand}' ${onPhaseStr}in template on connectorId ${connectorId}`
-    );
-  }
-
   public static getAuthorizationFile(stationInfo: ChargingStationInfo): string | undefined {
     return (
       stationInfo.authorizationFile &&
@@ -534,46 +409,6 @@ export class ChargingStationUtils {
     );
   }
 
-  public static isRequestCommandSupported(
-    command: RequestCommand,
-    chargingStation: ChargingStation
-  ): boolean {
-    const isRequestCommand = Object.values(RequestCommand).includes(command);
-    if (
-      isRequestCommand === true &&
-      !chargingStation.stationInfo?.commandsSupport?.outgoingCommands
-    ) {
-      return true;
-    } else if (
-      isRequestCommand === true &&
-      chargingStation.stationInfo?.commandsSupport?.outgoingCommands
-    ) {
-      return chargingStation.stationInfo?.commandsSupport?.outgoingCommands[command] ?? false;
-    }
-    logger.error(`${chargingStation.logPrefix()} Unknown outgoing OCPP command '${command}'`);
-    return false;
-  }
-
-  public static isIncomingRequestCommandSupported(
-    command: IncomingRequestCommand,
-    chargingStation: ChargingStation
-  ): boolean {
-    const isIncomingRequestCommand = Object.values(IncomingRequestCommand).includes(command);
-    if (
-      isIncomingRequestCommand === true &&
-      !chargingStation.stationInfo?.commandsSupport?.incomingCommands
-    ) {
-      return true;
-    } else if (
-      isIncomingRequestCommand === true &&
-      chargingStation.stationInfo?.commandsSupport?.incomingCommands
-    ) {
-      return chargingStation.stationInfo?.commandsSupport?.incomingCommands[command] ?? false;
-    }
-    logger.error(`${chargingStation.logPrefix()} Unknown incoming OCPP command '${command}'`);
-    return false;
-  }
-
   private static getRandomSerialNumberSuffix(params?: {
     randomBytesLength?: number;
     upperCase?: boolean;
index 7c449ca55e82fadccba0956b95c6ebf4ba953f87..0597e5cef6c95af84b0300fbaac0b4bd8e70ec43 100644 (file)
@@ -303,7 +303,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer
     ) {
       if (
         this.incomingRequestHandlers.has(commandName) &&
-        ChargingStationUtils.isIncomingRequestCommandSupported(commandName, chargingStation)
+        OCPP16ServiceUtils.isIncomingRequestCommandSupported(commandName, chargingStation)
       ) {
         try {
           this.validatePayload(chargingStation, commandName, commandPayload);
@@ -569,7 +569,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer
     ) {
       return Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED;
     }
-    ChargingStationUtils.setChargingProfile(
+    OCPP16ServiceUtils.setChargingProfile(
       chargingStation,
       commandPayload.connectorId,
       commandPayload.csChargingProfiles
@@ -912,7 +912,7 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer
     cp: OCPP16ChargingProfile
   ): boolean {
     if (cp && cp.chargingProfilePurpose === ChargingProfilePurposeType.TX_PROFILE) {
-      ChargingStationUtils.setChargingProfile(chargingStation, connectorId, cp);
+      OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, cp);
       logger.debug(
         `${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction on connector id ${connectorId}, dump their stack: %j`,
         chargingStation.getConnectorStatus(connectorId).chargingProfiles
index e0628496bdf8096b0392c49195c53a848883d934..d840e5e97a23ca788d7a922697e471215ae60755 100644 (file)
@@ -150,7 +150,7 @@ export default class OCPP16RequestService extends OCPPRequestService {
     commandParams?: JsonType,
     params?: RequestParams
   ): Promise<ResponseType> {
-    if (ChargingStationUtils.isRequestCommandSupported(commandName, chargingStation)) {
+    if (OCPP16ServiceUtils.isRequestCommandSupported(commandName, chargingStation)) {
       const requestPayload = this.buildRequestPayload<RequestType>(
         chargingStation,
         commandName,
index 8f8d0bae9f6a8be426fee0d2f20519a3795b6af0..041122c5fffd2880045860597092e03a0b82814b 100644 (file)
@@ -178,7 +178,7 @@ export default class OCPP16ResponseService extends OCPPResponseService {
     if (chargingStation.isRegistered() || commandName === OCPP16RequestCommand.BOOT_NOTIFICATION) {
       if (
         this.responseHandlers.has(commandName) &&
-        ChargingStationUtils.isRequestCommandSupported(commandName, chargingStation)
+        OCPP16ServiceUtils.isRequestCommandSupported(commandName, chargingStation)
       ) {
         try {
           this.validatePayload(chargingStation, commandName, payload);
index f5c4df7321b7a8c60be62ead9b9df9bf0d5a125c..2dc498e82a28a5071a8cc0ce48449ce7509afefa 100644 (file)
@@ -1,5 +1,6 @@
 // Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
 
+import BaseError from '../../../exception/BaseError';
 import OCPPError from '../../../exception/OCPPError';
 import { CurrentType, Voltage } from '../../../types/ChargingStationTemplate';
 import type {
@@ -24,13 +25,16 @@ import {
   OCPP16IncomingRequestCommand,
   OCPP16RequestCommand,
 } from '../../../types/ocpp/1.6/Requests';
+import type { ChargingProfile } from '../../../types/ocpp/ChargingProfile';
+import { StandardParametersKey } from '../../../types/ocpp/Configuration';
 import { ErrorType } from '../../../types/ocpp/ErrorType';
+import { MeterValueMeasurand, type MeterValuePhase } from '../../../types/ocpp/MeterValues';
 import Constants from '../../../utils/Constants';
 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 { ChargingStationConfigurationUtils } from '../../ChargingStationConfigurationUtils';
 import { OCPPServiceUtils } from '../OCPPServiceUtils';
 
 export class OCPP16ServiceUtils extends OCPPServiceUtils {
@@ -63,7 +67,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
@@ -91,7 +95,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       }
     }
     // Voltage measurand
-    const voltageSampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const voltageSampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId,
       OCPP16MeterValueMeasurand.VOLTAGE
@@ -121,7 +125,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       ) {
         const phaseLineToNeutralValue = `L${phase}-N`;
         const voltagePhaseLineToNeutralSampledValueTemplate =
-          ChargingStationUtils.getSampledValueTemplate(
+          OCPP16ServiceUtils.getSampledValueTemplate(
             chargingStation,
             connectorId,
             OCPP16MeterValueMeasurand.VOLTAGE,
@@ -156,7 +160,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               : chargingStation.getNumberOfPhases()
           }`;
           const voltagePhaseLineToLineSampledValueTemplate =
-            ChargingStationUtils.getSampledValueTemplate(
+            OCPP16ServiceUtils.getSampledValueTemplate(
               chargingStation,
               connectorId,
               OCPP16MeterValueMeasurand.VOLTAGE,
@@ -192,7 +196,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       }
     }
     // Power.Active.Import measurand
-    const powerSampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const powerSampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId,
       OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT
@@ -200,19 +204,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,
@@ -399,7 +403,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       }
     }
     // Current.Import measurand
-    const currentSampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const currentSampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId,
       OCPP16MeterValueMeasurand.CURRENT_IMPORT
@@ -407,19 +411,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,
@@ -607,7 +611,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       }
     }
     // Energy.Active.Import.Register measurand (default)
-    const energySampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const energySampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId
     );
@@ -690,7 +694,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       sampledValue: [],
     };
     // Energy.Active.Import.Register measurand (default)
-    const sampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const sampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId
     );
@@ -715,7 +719,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
       sampledValue: [],
     };
     // Energy.Active.Import.Register measurand (default)
-    const sampledValueTemplate = ChargingStationUtils.getSampledValueTemplate(
+    const sampledValueTemplate = OCPP16ServiceUtils.getSampledValueTemplate(
       chargingStation,
       connectorId
     );
@@ -740,6 +744,122 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     return meterValues;
   }
 
+  public static setChargingProfile(
+    chargingStation: ChargingStation,
+    connectorId: number,
+    cp: ChargingProfile
+  ): 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: ChargingProfile, 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 getSampledValueTemplate(
+    chargingStation: ChargingStation,
+    connectorId: number,
+    measurand: MeterValueMeasurand = MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
+    phase?: MeterValuePhase
+  ): SampledValueTemplate | undefined {
+    const onPhaseStr = phase ? `on phase ${phase} ` : '';
+    if (Constants.SUPPORTED_MEASURANDS.includes(measurand) === false) {
+      logger.warn(
+        `${chargingStation.logPrefix()} Trying to get unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connectorId ${connectorId}`
+      );
+      return;
+    }
+    if (
+      measurand !== MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER &&
+      !ChargingStationConfigurationUtils.getConfigurationKey(
+        chargingStation,
+        StandardParametersKey.MeterValuesSampledData
+      )?.value.includes(measurand)
+    ) {
+      logger.debug(
+        `${chargingStation.logPrefix()} Trying to get MeterValues measurand '${measurand}' ${onPhaseStr}in template on connectorId ${connectorId} not found in '${
+          StandardParametersKey.MeterValuesSampledData
+        }' OCPP parameter`
+      );
+      return;
+    }
+    const sampledValueTemplates: SampledValueTemplate[] =
+      chargingStation.getConnectorStatus(connectorId).MeterValues;
+    for (
+      let index = 0;
+      !Utils.isEmptyArray(sampledValueTemplates) && index < sampledValueTemplates.length;
+      index++
+    ) {
+      if (
+        Constants.SUPPORTED_MEASURANDS.includes(
+          sampledValueTemplates[index]?.measurand ??
+            MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
+        ) === false
+      ) {
+        logger.warn(
+          `${chargingStation.logPrefix()} Unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connectorId ${connectorId}`
+        );
+      } else if (
+        phase &&
+        sampledValueTemplates[index]?.phase === phase &&
+        sampledValueTemplates[index]?.measurand === measurand &&
+        ChargingStationConfigurationUtils.getConfigurationKey(
+          chargingStation,
+          StandardParametersKey.MeterValuesSampledData
+        )?.value.includes(measurand) === true
+      ) {
+        return sampledValueTemplates[index];
+      } else if (
+        !phase &&
+        !sampledValueTemplates[index].phase &&
+        sampledValueTemplates[index]?.measurand === measurand &&
+        ChargingStationConfigurationUtils.getConfigurationKey(
+          chargingStation,
+          StandardParametersKey.MeterValuesSampledData
+        )?.value.includes(measurand) === true
+      ) {
+        return sampledValueTemplates[index];
+      } else if (
+        measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER &&
+        (!sampledValueTemplates[index].measurand ||
+          sampledValueTemplates[index].measurand === measurand)
+      ) {
+        return sampledValueTemplates[index];
+      }
+    }
+    if (measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) {
+      const errorMsg = `Missing MeterValues for default measurand '${measurand}' in template on connectorId ${connectorId}`;
+      logger.error(`${chargingStation.logPrefix()} ${errorMsg}`);
+      throw new BaseError(errorMsg);
+    }
+    logger.debug(
+      `${chargingStation.logPrefix()} No MeterValues for measurand '${measurand}' ${onPhaseStr}in template on connectorId ${connectorId}`
+    );
+  }
+
   private static buildSampledValue(
     sampledValueTemplate: SampledValueTemplate,
     value: number,
index 96b34218bae93f78a595545a29b2969fc91000fc..dcf3a9997f1345e3a576e473f93198486676e784 100644 (file)
@@ -1,6 +1,9 @@
 import type { DefinedError, ErrorObject } from 'ajv';
 
 import { ErrorType } from '../../types/ocpp/ErrorType';
+import { IncomingRequestCommand, RequestCommand } from '../../types/ocpp/Requests';
+import logger from '../../utils/Logger';
+import type ChargingStation from '../ChargingStation';
 
 export class OCPPServiceUtils {
   protected constructor() {
@@ -23,6 +26,46 @@ export class OCPPServiceUtils {
     return ErrorType.FORMAT_VIOLATION;
   }
 
+  public static isRequestCommandSupported(
+    command: RequestCommand,
+    chargingStation: ChargingStation
+  ): boolean {
+    const isRequestCommand = Object.values(RequestCommand).includes(command);
+    if (
+      isRequestCommand === true &&
+      !chargingStation.stationInfo?.commandsSupport?.outgoingCommands
+    ) {
+      return true;
+    } else if (
+      isRequestCommand === true &&
+      chargingStation.stationInfo?.commandsSupport?.outgoingCommands
+    ) {
+      return chargingStation.stationInfo?.commandsSupport?.outgoingCommands[command] ?? false;
+    }
+    logger.error(`${chargingStation.logPrefix()} Unknown outgoing OCPP command '${command}'`);
+    return false;
+  }
+
+  public static isIncomingRequestCommandSupported(
+    command: IncomingRequestCommand,
+    chargingStation: ChargingStation
+  ): boolean {
+    const isIncomingRequestCommand = Object.values(IncomingRequestCommand).includes(command);
+    if (
+      isIncomingRequestCommand === true &&
+      !chargingStation.stationInfo?.commandsSupport?.incomingCommands
+    ) {
+      return true;
+    } else if (
+      isIncomingRequestCommand === true &&
+      chargingStation.stationInfo?.commandsSupport?.incomingCommands
+    ) {
+      return chargingStation.stationInfo?.commandsSupport?.incomingCommands[command] ?? false;
+    }
+    logger.error(`${chargingStation.logPrefix()} Unknown incoming OCPP command '${command}'`);
+    return false;
+  }
+
   protected static getLimitFromSampledValueTemplateCustomValue(
     value: string,
     limit: number,
index 7b777b86040c3cba972d886da3df9a11dbab999a..223c5bbbff1664dc111b0e62508436c726168673 100644 (file)
@@ -16,7 +16,7 @@ import {
 import logger from '../../utils/Logger';
 import Utils from '../../utils/Utils';
 import { AbstractUIServer } from './AbstractUIServer';
-import { UIServiceUtils } from './ui-services/UIServiceUtils';
+import { UIServerUtils } from './UIServerUtils';
 
 const moduleName = 'UIHttpServer';
 
@@ -90,7 +90,7 @@ export default class UIHttpServer extends AbstractUIServer {
     this.responseHandlers.set(uuid, res);
     try {
       const fullProtocol = `${protocol}${version}`;
-      if (UIServiceUtils.isProtocolAndVersionSupported(fullProtocol) === false) {
+      if (UIServerUtils.isProtocolAndVersionSupported(fullProtocol) === false) {
         throw new BaseError(`Unsupported UI protocol version: '${fullProtocol}'`);
       }
       this.registerProtocolVersionUIService(version);
index e7b341d1b0e62260b8156f239171da5d890b10b9..2a125af07971fe9b724a06f45cf8c04b5e03c040 100644 (file)
@@ -4,8 +4,8 @@ import type { UIServerConfiguration } from '../../types/ConfigurationData';
 import { ApplicationProtocol } from '../../types/UIProtocol';
 import Configuration from '../../utils/Configuration';
 import type { AbstractUIServer } from './AbstractUIServer';
-import { UIServiceUtils } from './ui-services/UIServiceUtils';
 import UIHttpServer from './UIHttpServer';
+import { UIServerUtils } from './UIServerUtils';
 import UIWebSocketServer from './UIWebSocketServer';
 
 export default class UIServerFactory {
@@ -16,7 +16,7 @@ export default class UIServerFactory {
   public static getUIServerImplementation(
     uiServerConfiguration?: UIServerConfiguration
   ): AbstractUIServer | null {
-    if (UIServiceUtils.isLoopback(uiServerConfiguration.options?.host) === false) {
+    if (UIServerUtils.isLoopback(uiServerConfiguration.options?.host) === false) {
       console.warn(
         chalk.yellow(
           'Loopback address not detected in UI server configuration. This is not recommended.'
similarity index 82%
rename from src/charging-station/ui-server/ui-services/UIServiceUtils.ts
rename to src/charging-station/ui-server/UIServerUtils.ts
index b6137886d76c105fda10f5cd667f7c37e7e94dc5..fc37ddc6cd89e82be004f7ff6deecf0d13425f3f 100644 (file)
@@ -1,10 +1,10 @@
 import type { IncomingMessage } from 'http';
 
-import { Protocol, ProtocolVersion } from '../../../types/UIProtocol';
-import logger from '../../../utils/Logger';
-import Utils from '../../../utils/Utils';
+import { Protocol, ProtocolVersion } from '../../types/UIProtocol';
+import logger from '../../utils/Logger';
+import Utils from '../../utils/Utils';
 
-export class UIServiceUtils {
+export class UIServerUtils {
   private constructor() {
     // This is intentional
   }
@@ -20,7 +20,7 @@ export class UIServiceUtils {
       return false;
     }
     for (const fullProtocol of protocols) {
-      if (UIServiceUtils.isProtocolAndVersionSupported(fullProtocol) === true) {
+      if (UIServerUtils.isProtocolAndVersionSupported(fullProtocol) === true) {
         return fullProtocol;
       }
     }
@@ -33,7 +33,7 @@ export class UIServiceUtils {
   };
 
   public static isProtocolAndVersionSupported = (protocolStr: string): boolean => {
-    const [protocol, version] = UIServiceUtils.getProtocolAndVersion(protocolStr);
+    const [protocol, version] = UIServerUtils.getProtocolAndVersion(protocolStr);
     return (
       Object.values(Protocol).includes(protocol) === true &&
       Object.values(ProtocolVersion).includes(version) === true
index 4ac5d23561abcdd9e25a29a8fd12d22d37ba18d8..cf1bfa65bddfc4f415f46feb0acdc73646ddcf96 100644 (file)
@@ -11,7 +11,7 @@ import { WebSocketCloseEventStatusCode } from '../../types/WebSocket';
 import logger from '../../utils/Logger';
 import Utils from '../../utils/Utils';
 import { AbstractUIServer } from './AbstractUIServer';
-import { UIServiceUtils } from './ui-services/UIServiceUtils';
+import { UIServerUtils } from './UIServerUtils';
 
 const moduleName = 'UIWebSocketServer';
 
@@ -21,14 +21,14 @@ export default class UIWebSocketServer extends AbstractUIServer {
   public constructor(protected readonly uiServerConfiguration: UIServerConfiguration) {
     super(uiServerConfiguration);
     this.webSocketServer = new WebSocketServer({
-      handleProtocols: UIServiceUtils.handleProtocols,
+      handleProtocols: UIServerUtils.handleProtocols,
       noServer: true,
     });
   }
 
   public start(): void {
     this.webSocketServer.on('connection', (ws: WebSocket, req: IncomingMessage): void => {
-      if (UIServiceUtils.isProtocolAndVersionSupported(ws.protocol) === false) {
+      if (UIServerUtils.isProtocolAndVersionSupported(ws.protocol) === false) {
         logger.error(
           `${this.logPrefix(
             moduleName,
@@ -37,7 +37,7 @@ export default class UIWebSocketServer extends AbstractUIServer {
         );
         ws.close(WebSocketCloseEventStatusCode.CLOSE_PROTOCOL_ERROR);
       }
-      const [, version] = UIServiceUtils.getProtocolAndVersion(ws.protocol);
+      const [, version] = UIServerUtils.getProtocolAndVersion(ws.protocol);
       this.registerProtocolVersionUIService(version);
       ws.on('message', (rawData) => {
         const request = this.validateRawDataRequest(rawData);