Remove now useless Date conversions to string
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / OCPPServiceUtils.ts
index dcf3a9997f1345e3a576e473f93198486676e784..33637c65a9e7501ea045cee9fd521863b27c1f0a 100644 (file)
@@ -1,9 +1,16 @@
 import type { DefinedError, ErrorObject } from 'ajv';
 
+import BaseError from '../../exception/BaseError';
+import type { SampledValueTemplate } from '../../types/MeasurandPerPhaseSampledValueTemplates';
+import { StandardParametersKey } from '../../types/ocpp/Configuration';
 import { ErrorType } from '../../types/ocpp/ErrorType';
-import { IncomingRequestCommand, RequestCommand } from '../../types/ocpp/Requests';
+import { MeterValueMeasurand, type MeterValuePhase } from '../../types/ocpp/MeterValues';
+import { IncomingRequestCommand, MessageTrigger, RequestCommand } from '../../types/ocpp/Requests';
+import Constants from '../../utils/Constants';
 import logger from '../../utils/Logger';
+import Utils from '../../utils/Utils';
 import type ChargingStation from '../ChargingStation';
+import { ChargingStationConfigurationUtils } from '../ChargingStationConfigurationUtils';
 
 export class OCPPServiceUtils {
   protected constructor() {
@@ -27,10 +34,10 @@ export class OCPPServiceUtils {
   }
 
   public static isRequestCommandSupported(
-    command: RequestCommand,
-    chargingStation: ChargingStation
+    chargingStation: ChargingStation,
+    command: RequestCommand
   ): boolean {
-    const isRequestCommand = Object.values(RequestCommand).includes(command);
+    const isRequestCommand = Object.values<RequestCommand>(RequestCommand).includes(command);
     if (
       isRequestCommand === true &&
       !chargingStation.stationInfo?.commandsSupport?.outgoingCommands
@@ -47,10 +54,11 @@ export class OCPPServiceUtils {
   }
 
   public static isIncomingRequestCommandSupported(
-    command: IncomingRequestCommand,
-    chargingStation: ChargingStation
+    chargingStation: ChargingStation,
+    command: IncomingRequestCommand
   ): boolean {
-    const isIncomingRequestCommand = Object.values(IncomingRequestCommand).includes(command);
+    const isIncomingRequestCommand =
+      Object.values<IncomingRequestCommand>(IncomingRequestCommand).includes(command);
     if (
       isIncomingRequestCommand === true &&
       !chargingStation.stationInfo?.commandsSupport?.incomingCommands
@@ -66,6 +74,117 @@ export class OCPPServiceUtils {
     return false;
   }
 
+  public static isMessageTriggerSupported(
+    chargingStation: ChargingStation,
+    messageTrigger: MessageTrigger
+  ): boolean {
+    const isMessageTrigger = Object.values(MessageTrigger).includes(messageTrigger);
+    if (isMessageTrigger === true && !chargingStation.stationInfo?.messageTriggerSupport) {
+      return true;
+    } else if (isMessageTrigger === true && chargingStation.stationInfo?.messageTriggerSupport) {
+      return chargingStation.stationInfo?.messageTriggerSupport[messageTrigger] ?? false;
+    }
+    logger.error(
+      `${chargingStation.logPrefix()} Unknown incoming OCPP message trigger '${messageTrigger}'`
+    );
+    return false;
+  }
+
+  public static isConnectorIdValid(
+    chargingStation: ChargingStation,
+    ocppCommand: IncomingRequestCommand,
+    connectorId: number
+  ): boolean {
+    if (connectorId < 0) {
+      logger.error(
+        `${chargingStation.logPrefix()} ${ocppCommand} incoming request received with invalid connector Id ${connectorId}`
+      );
+      return false;
+    }
+    return true;
+  }
+
+  protected 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) === false
+    ) {
+      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) === false && 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}`
+    );
+  }
+
   protected static getLimitFromSampledValueTemplateCustomValue(
     value: string,
     limit: number,
@@ -76,7 +195,8 @@ export class OCPPServiceUtils {
   ): number {
     options.limitationEnabled = options?.limitationEnabled ?? true;
     options.unitMultiplier = options?.unitMultiplier ?? 1;
-    const numberValue = isNaN(parseInt(value)) ? Infinity : parseInt(value);
+    const parsedInt = parseInt(value);
+    const numberValue = isNaN(parsedInt) ? Infinity : parsedInt;
     return options?.limitationEnabled
       ? Math.min(numberValue * options.unitMultiplier, limit)
       : numberValue * options.unitMultiplier;