refactor(simulator): make OCPPIncomingRequestService class inherit from
[e-mobility-charging-stations-simulator.git] / src / charging-station / ocpp / 1.6 / OCPP16ServiceUtils.ts
index f3f22e45c8ff8f1456c9d9be4ebb3cc153e34495..d0d46c25d50df40ae9fb3f1f4bed5d9fbe196d5d 100644 (file)
@@ -1,7 +1,13 @@
-// Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
+// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
+
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+import type { JSONSchemaType } from 'ajv';
 
 import OCPPError from '../../../exception/OCPPError';
 import { CurrentType, Voltage } from '../../../types/ChargingStationTemplate';
+import type { JsonType } from '../../../types/JsonType';
 import type {
   MeasurandPerPhaseSampledValueTemplates,
   SampledValueTemplate,
@@ -26,6 +32,7 @@ import {
   OCPP16RequestCommand,
 } from '../../../types/ocpp/1.6/Requests';
 import { ErrorType } from '../../../types/ocpp/ErrorType';
+import { OCPPVersion } from '../../../types/ocpp/OCPPVersion';
 import Constants from '../../../utils/Constants';
 import { ACElectricUtils, DCElectricUtils } from '../../../utils/ElectricUtils';
 import logger from '../../../utils/Logger';
@@ -58,7 +65,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     debug = false
   ): OCPP16MeterValue {
     const meterValue: OCPP16MeterValue = {
-      timestamp: new Date().toISOString(),
+      timestamp: new Date(),
       sampledValue: [],
     };
     const connector = chargingStation.getConnectorStatus(connectorId);
@@ -84,7 +91,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
           `${chargingStation.logPrefix()} MeterValues measurand ${
             meterValue.sampledValue[sampledValuesIndex].measurand ??
             OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
-          }: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+          }: connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
             meterValue.sampledValue[sampledValuesIndex].value
           }/100`
         );
@@ -145,7 +152,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
           OCPP16ServiceUtils.buildSampledValue(
             voltagePhaseLineToNeutralSampledValueTemplate ?? voltageSampledValueTemplate,
             voltagePhaseLineToNeutralMeasurandValue ?? voltageMeasurandValue,
-            null,
+            undefined,
             phaseLineToNeutralValue as OCPP16MeterValuePhase
           )
         );
@@ -184,7 +191,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             OCPP16ServiceUtils.buildSampledValue(
               voltagePhaseLineToLineSampledValueTemplate ?? voltageSampledValueTemplate,
               voltagePhaseLineToLineMeasurandValue ?? defaultVoltagePhaseLineToLineMeasurandValue,
-              null,
+              undefined,
               phaseLineToLineValue as OCPP16MeterValuePhase
             )
           );
@@ -355,7 +362,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
           `${chargingStation.logPrefix()} MeterValues measurand ${
             meterValue.sampledValue[sampledValuesIndex].measurand ??
             OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
-          }: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+          }: connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
             meterValue.sampledValue[sampledValuesIndex].value
           }/${connectorMaximumPowerRounded}`
         );
@@ -371,7 +378,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             (powerPerPhaseSampledValueTemplates[`L${phase}`] as SampledValueTemplate) ??
               powerSampledValueTemplate,
             powerMeasurandValues[`L${phase}`] as number,
-            null,
+            undefined,
             phaseValue as OCPP16MeterValuePhase
           )
         );
@@ -391,7 +398,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
             }: phase ${
               meterValue.sampledValue[sampledValuesPerPhaseIndex].phase
-            }, connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+            }, connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
               meterValue.sampledValue[sampledValuesPerPhaseIndex].value
             }/${connectorMaximumPowerPerPhaseRounded}`
           );
@@ -567,7 +574,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
           `${chargingStation.logPrefix()} MeterValues measurand ${
             meterValue.sampledValue[sampledValuesIndex].measurand ??
             OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
-          }: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+          }: connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
             meterValue.sampledValue[sampledValuesIndex].value
           }/${connectorMaximumAmperage}`
         );
@@ -583,7 +590,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             (currentPerPhaseSampledValueTemplates[phaseValue] as SampledValueTemplate) ??
               currentSampledValueTemplate,
             currentMeasurandValues[phaseValue] as number,
-            null,
+            undefined,
             phaseValue as OCPP16MeterValuePhase
           )
         );
@@ -599,7 +606,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
               OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
             }: phase ${
               meterValue.sampledValue[sampledValuesPerPhaseIndex].phase
-            }, connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+            }, connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
               meterValue.sampledValue[sampledValuesPerPhaseIndex].value
             }/${connectorMaximumAmperage}`
           );
@@ -669,7 +676,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
             meterValue.sampledValue[sampledValuesIndex].measurand ??
             OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
           }: connectorId ${connectorId}, transaction ${
-            connector.transactionId
+            connector?.transactionId
           }, value: ${energyValueRounded}/${connectorMaximumEnergyRounded}, duration: ${Utils.roundTo(
             interval / (3600 * 1000),
             4
@@ -686,7 +693,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     meterStart: number
   ): OCPP16MeterValue {
     const meterValue: OCPP16MeterValue = {
-      timestamp: new Date().toISOString(),
+      timestamp: new Date(),
       sampledValue: [],
     };
     // Energy.Active.Import.Register measurand (default)
@@ -711,7 +718,7 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     meterStop: number
   ): OCPP16MeterValue {
     const meterValue: OCPP16MeterValue = {
-      timestamp: new Date().toISOString(),
+      timestamp: new Date(),
       sampledValue: [],
     };
     // Energy.Active.Import.Register measurand (default)
@@ -745,23 +752,27 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
     connectorId: number,
     cp: OCPP16ChargingProfile
   ): void {
-    if (Utils.isNullOrUndefined(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) {
+    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) {
+    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)) {
+    if (!Utils.isEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
       chargingStation
         .getConnectorStatus(connectorId)
-        .chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
+        ?.chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
           if (
             chargingProfile.chargingProfileId === cp.chargingProfileId ||
             (chargingProfile.stackLevel === cp.stackLevel &&
@@ -772,7 +783,20 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils {
           }
         });
     }
-    !cpReplaced && chargingStation.getConnectorStatus(connectorId).chargingProfiles?.push(cp);
+    !cpReplaced && chargingStation.getConnectorStatus(connectorId)?.chargingProfiles?.push(cp);
+  }
+
+  public static parseJsonSchemaFile<T extends JsonType>(
+    relativePath: string,
+    moduleName?: string,
+    methodName?: string
+  ): JSONSchemaType<T> {
+    return super.parseJsonSchemaFile<T>(
+      path.resolve(path.dirname(fileURLToPath(import.meta.url)), relativePath),
+      OCPPVersion.VERSION_16,
+      moduleName,
+      methodName
+    );
   }
 
   private static buildSampledValue(