Move hashId to stationInfo
[e-mobility-charging-stations-simulator.git] / src / charging-station / ChargingStationUtils.ts
index 7208fb80fe383fa916836306d63c33d9405f634a..60e143faaa51c55a470b453fe623d3379dc12370 100644 (file)
@@ -1,31 +1,42 @@
-import { ChargingProfile, ChargingSchedulePeriod } from '../types/ocpp/ChargingProfile';
-import { ChargingProfileKindType, RecurrencyKindType } from '../types/ocpp/1.6/ChargingProfile';
+import crypto from 'crypto';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+import moment from 'moment';
+
+import BaseError from '../exception/BaseError';
+import type ChargingStationInfo from '../types/ChargingStationInfo';
 import ChargingStationTemplate, {
   AmpereUnits,
   CurrentType,
   Voltage,
 } from '../types/ChargingStationTemplate';
-import { MeterValueMeasurand, MeterValuePhase } from '../types/ocpp/MeterValues';
-
-import BaseError from '../exception/BaseError';
-import { BootNotificationRequest } from '../types/ocpp/Requests';
-import ChargingStation from './ChargingStation';
-import { ChargingStationConfigurationUtils } from './ChargingStationConfigurationUtils';
-import ChargingStationInfo from '../types/ChargingStationInfo';
-import Configuration from '../utils/Configuration';
-import Constants from '../utils/Constants';
-import { SampledValueTemplate } from '../types/MeasurandPerPhaseSampledValueTemplates';
+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 Utils from '../utils/Utils';
+import { MeterValueMeasurand, MeterValuePhase } from '../types/ocpp/MeterValues';
+import {
+  BootNotificationRequest,
+  IncomingRequestCommand,
+  RequestCommand,
+} from '../types/ocpp/Requests';
 import { WebSocketCloseEventStatusString } from '../types/WebSocket';
 import { WorkerProcessType } from '../types/Worker';
-import crypto from 'crypto';
-import { fileURLToPath } from 'url';
+import Configuration from '../utils/Configuration';
+import Constants from '../utils/Constants';
 import logger from '../utils/Logger';
-import moment from 'moment';
-import path from 'path';
+import Utils from '../utils/Utils';
+import type ChargingStation from './ChargingStation';
+import { ChargingStationConfigurationUtils } from './ChargingStationConfigurationUtils';
+
+const moduleName = 'ChargingStationUtils';
 
 export class ChargingStationUtils {
+  private constructor() {
+    // This is intentional
+  }
+
   public static getChargingStationId(
     index: number,
     stationTemplate: ChargingStationTemplate
@@ -229,7 +240,7 @@ export class ChargingStationUtils {
     delete stationTemplate.chargeBoxSerialNumberPrefix;
     delete stationTemplate.chargePointSerialNumberPrefix;
     delete stationTemplate.meterSerialNumberPrefix;
-    return stationTemplate;
+    return stationTemplate as unknown as ChargingStationInfo;
   }
 
   public static createStationInfoHash(stationInfo: ChargingStationInfo): void {
@@ -321,6 +332,7 @@ export class ChargingStationUtils {
     limit: number;
     matchingChargingProfile: ChargingProfile;
   } | null {
+    const debugLogMsg = `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Matching charging profile found for power limitation: %j`;
     for (const chargingProfile of chargingProfiles) {
       // Set helpers
       const currentMoment = moment();
@@ -364,10 +376,7 @@ export class ChargingStationUtils {
               limit: schedulePeriod.limit,
               matchingChargingProfile: chargingProfile,
             };
-            logger.debug(
-              `${logPrefix} Matching charging profile found for power limitation: %j`,
-              result
-            );
+            logger.debug(debugLogMsg, result);
             return result;
           }
           // Find the right schedule period
@@ -381,10 +390,7 @@ export class ChargingStationUtils {
               limit: lastButOneSchedule.limit,
               matchingChargingProfile: chargingProfile,
             };
-            logger.debug(
-              `${logPrefix} Matching charging profile found for power limitation: %j`,
-              result
-            );
+            logger.debug(debugLogMsg, result);
             return result;
           }
           // Keep it
@@ -400,10 +406,7 @@ export class ChargingStationUtils {
               limit: lastButOneSchedule.limit,
               matchingChargingProfile: chargingProfile,
             };
-            logger.debug(
-              `${logPrefix} Matching charging profile found for power limitation: %j`,
-              result
-            );
+            logger.debug(debugLogMsg, result);
             return result;
           }
         }
@@ -417,7 +420,7 @@ export class ChargingStationUtils {
     templateFile: string,
     logPrefix: string
   ): Voltage {
-    const errMsg = `${logPrefix} Unknown ${currentType} currentOutType in template file ${templateFile}, cannot define default voltage out`;
+    const errMsg = `Unknown ${currentType} currentOutType in template file ${templateFile}, cannot define default voltage out`;
     let defaultVoltageOut: number;
     switch (currentType) {
       case CurrentType.AC:
@@ -427,8 +430,8 @@ export class ChargingStationUtils {
         defaultVoltageOut = Voltage.VOLTAGE_400;
         break;
       default:
-        logger.error(errMsg);
-        throw new Error(errMsg);
+        logger.error(`${logPrefix} ${errMsg}`);
+        throw new BaseError(errMsg);
     }
     return defaultVoltageOut;
   }
@@ -505,9 +508,9 @@ export class ChargingStationUtils {
       }
     }
     if (measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) {
-      const errorMsg = `${chargingStation.logPrefix()} Missing MeterValues for default measurand '${measurand}' in template on connectorId ${connectorId}`;
-      logger.error(errorMsg);
-      throw new Error(errorMsg);
+      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}`
@@ -525,6 +528,40 @@ export class ChargingStationUtils {
     );
   }
 
+  public static isRequestCommandSupported(
+    command: RequestCommand,
+    chargingStation: ChargingStation
+  ): boolean {
+    const isRequestCommand = Object.values(RequestCommand).includes(command);
+    if (isRequestCommand && !chargingStation.stationInfo?.commandsSupport?.outgoingCommands) {
+      return true;
+    } else if (isRequestCommand && 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 &&
+      !chargingStation.stationInfo?.commandsSupport?.incomingCommands
+    ) {
+      return true;
+    } else if (
+      isIncomingRequestCommand &&
+      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;