]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
refactor(ocpp): consolidate meter value builders into RequestBuilders
authorJérôme Benoit <jerome.benoit@sap.com>
Wed, 1 Apr 2026 16:17:13 +0000 (18:17 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Wed, 1 Apr 2026 16:17:13 +0000 (18:17 +0200)
Merge OCPP16MeterValueBuilders.ts and OCPP20MeterValueBuilders.ts
into their respective OCPP16RequestBuilders.ts and OCPP20RequestBuilders.ts
files. Version-specific pure builders belong in a single leaf module
per stack, not separate files per builder type.

src/charging-station/ocpp/1.6/OCPP16MeterValueBuilders.ts [deleted file]
src/charging-station/ocpp/1.6/OCPP16RequestBuilders.ts
src/charging-station/ocpp/2.0/OCPP20MeterValueBuilders.ts [deleted file]
src/charging-station/ocpp/2.0/OCPP20RequestBuilders.ts
src/charging-station/ocpp/OCPPServiceUtils.ts

diff --git a/src/charging-station/ocpp/1.6/OCPP16MeterValueBuilders.ts b/src/charging-station/ocpp/1.6/OCPP16MeterValueBuilders.ts
deleted file mode 100644 (file)
index c51ab48..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-import type { ChargingStation } from '../../../charging-station/index.js'
-
-import { OCPPError } from '../../../exception/index.js'
-import {
-  type ConfigurationKeyType,
-  CurrentType,
-  ErrorType,
-  type MeasurandPerPhaseSampledValueTemplates,
-  type MeasurandValues,
-  type MeterValueContext,
-  type MeterValuePhase,
-  MeterValueUnit,
-  type OCPP16MeterValue,
-  type OCPP16SampledValue,
-  OCPPVersion,
-  RequestCommand,
-  type SampledValueTemplate,
-} from '../../../types/index.js'
-import { ACElectricUtils, DCElectricUtils, roundTo } from '../../../utils/index.js'
-import {
-  addLineToLineVoltageToMeterValue,
-  addMainVoltageToMeterValue,
-  addPhaseVoltageToMeterValue,
-  buildCurrentMeasurandValue,
-  buildEmptyMeterValue,
-  buildEnergyMeasurandValue,
-  buildPowerMeasurandValue,
-  buildSampledValue,
-  buildSocMeasurandValue,
-  buildVoltageMeasurandValue,
-  updateConnectorEnergyValues,
-  validateCurrentMeasurandPhaseValue,
-  validateCurrentMeasurandValue,
-  validateEnergyMeasurandValue,
-  validatePowerMeasurandValue,
-  validateSocMeasurandValue,
-} from '../OCPPServiceUtils.js'
-
-export const buildMeterValueForOCPP16 = (
-  chargingStation: ChargingStation,
-  transactionId: number | string,
-  interval: number,
-  measurandsKey?: ConfigurationKeyType,
-  context?: MeterValueContext,
-  debug = false
-): OCPP16MeterValue => {
-  const connectorId = chargingStation.getConnectorIdByTransactionId(transactionId)
-  if (connectorId == null) {
-    throw new OCPPError(
-      ErrorType.INTERNAL_ERROR,
-      `Cannot build MeterValues: no connector found for transaction ${String(transactionId)}`,
-      RequestCommand.METER_VALUES
-    )
-  }
-  const connectorStatus = chargingStation.getConnectorStatus(connectorId)
-  const meterValue = buildEmptyMeterValue() as OCPP16MeterValue
-  const buildVersionedSampledValue = (
-    sampledValueTemplate: SampledValueTemplate,
-    value: number,
-    context?: MeterValueContext,
-    phase?: MeterValuePhase
-  ): OCPP16SampledValue => {
-    return buildSampledValueForOCPP16(sampledValueTemplate, value, context, phase)
-  }
-  // SoC measurand
-  const socMeasurand = buildSocMeasurandValue(
-    chargingStation,
-    connectorId,
-    undefined,
-    measurandsKey
-  )
-  if (socMeasurand != null) {
-    const socSampledValue = buildVersionedSampledValue(socMeasurand.template, socMeasurand.value)
-    meterValue.sampledValue.push(socSampledValue)
-    validateSocMeasurandValue(
-      chargingStation,
-      connectorId,
-      socSampledValue,
-      socMeasurand.template.minimumValue ?? 0,
-      100,
-      debug
-    )
-  }
-  // Voltage measurand
-  const voltageMeasurand = buildVoltageMeasurandValue(
-    chargingStation,
-    connectorId,
-    undefined,
-    measurandsKey
-  )
-  if (voltageMeasurand != null) {
-    addMainVoltageToMeterValue(
-      chargingStation,
-      meterValue,
-      voltageMeasurand,
-      buildVersionedSampledValue
-    )
-    for (
-      let phase = 1;
-      chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
-      phase++
-    ) {
-      addPhaseVoltageToMeterValue(
-        chargingStation,
-        connectorId,
-        meterValue,
-        voltageMeasurand,
-        phase,
-        buildVersionedSampledValue
-      )
-      addLineToLineVoltageToMeterValue(
-        chargingStation,
-        connectorId,
-        meterValue,
-        voltageMeasurand,
-        phase,
-        buildVersionedSampledValue
-      )
-    }
-  }
-  // Power.Active.Import measurand
-  const powerMeasurand = buildPowerMeasurandValue(
-    chargingStation,
-    connectorId,
-    undefined,
-    measurandsKey
-  )
-  if (powerMeasurand != null) {
-    const unitDivider = powerMeasurand.template.unit === MeterValueUnit.KILO_WATT ? 1000 : 1
-    const connectorMaximumAvailablePower =
-      chargingStation.getConnectorMaximumAvailablePower(connectorId)
-    const connectorMaximumPower = Math.round(connectorMaximumAvailablePower)
-    const connectorMinimumPower = Math.round(powerMeasurand.template.minimumValue ?? 0)
-
-    meterValue.sampledValue.push(
-      buildVersionedSampledValue(powerMeasurand.template, powerMeasurand.values.allPhases)
-    )
-    const sampledValuesIndex = meterValue.sampledValue.length - 1
-    validatePowerMeasurandValue(
-      chargingStation,
-      connectorId,
-      connectorStatus,
-      meterValue.sampledValue[sampledValuesIndex],
-      connectorMaximumPower / unitDivider,
-      connectorMinimumPower / unitDivider,
-      debug
-    )
-    if (chargingStation.getNumberOfPhases() === 3) {
-      const connectorMaximumPowerPerPhase = Math.round(
-        connectorMaximumAvailablePower / chargingStation.getNumberOfPhases()
-      )
-      const connectorMinimumPowerPerPhase = Math.round(
-        connectorMinimumPower / chargingStation.getNumberOfPhases()
-      )
-      for (let phase = 1; phase <= chargingStation.getNumberOfPhases(); phase++) {
-        const phaseTemplate =
-          powerMeasurand.perPhaseTemplates[
-            `L${phase.toString()}` as keyof MeasurandPerPhaseSampledValueTemplates
-          ]
-        if (phaseTemplate != null) {
-          const phaseValue = `L${phase.toString()}-N` as MeterValuePhase
-          const phasePowerValue =
-            powerMeasurand.values[`L${phase.toString()}` as keyof MeasurandValues]
-          meterValue.sampledValue.push(
-            buildVersionedSampledValue(phaseTemplate, phasePowerValue, undefined, phaseValue)
-          )
-          const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1
-          validatePowerMeasurandValue(
-            chargingStation,
-            connectorId,
-            connectorStatus,
-            meterValue.sampledValue[sampledValuesPerPhaseIndex],
-            connectorMaximumPowerPerPhase / unitDivider,
-            connectorMinimumPowerPerPhase / unitDivider,
-            debug
-          )
-        }
-      }
-    }
-  }
-  // Current.Import measurand
-  const currentMeasurand = buildCurrentMeasurandValue(
-    chargingStation,
-    connectorId,
-    undefined,
-    measurandsKey
-  )
-  if (currentMeasurand != null) {
-    const connectorMaximumAvailablePower =
-      chargingStation.getConnectorMaximumAvailablePower(connectorId)
-    const connectorMaximumAmperage =
-      chargingStation.stationInfo?.currentOutType === CurrentType.AC
-        ? ACElectricUtils.amperagePerPhaseFromPower(
-          chargingStation.getNumberOfPhases(),
-          connectorMaximumAvailablePower,
-          chargingStation.getVoltageOut()
-        )
-        : DCElectricUtils.amperage(connectorMaximumAvailablePower, chargingStation.getVoltageOut())
-    const connectorMinimumAmperage = currentMeasurand.template.minimumValue ?? 0
-
-    meterValue.sampledValue.push(
-      buildVersionedSampledValue(currentMeasurand.template, currentMeasurand.values.allPhases)
-    )
-    const sampledValuesIndex = meterValue.sampledValue.length - 1
-    validateCurrentMeasurandValue(
-      chargingStation,
-      connectorId,
-      connectorStatus,
-      meterValue.sampledValue[sampledValuesIndex],
-      connectorMaximumAmperage,
-      connectorMinimumAmperage,
-      debug
-    )
-    for (
-      let phase = 1;
-      chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
-      phase++
-    ) {
-      const phaseValue = `L${phase.toString()}` as MeterValuePhase
-      meterValue.sampledValue.push(
-        buildVersionedSampledValue(
-          currentMeasurand.perPhaseTemplates[
-            phaseValue as keyof MeasurandPerPhaseSampledValueTemplates
-          ] ?? currentMeasurand.template,
-          currentMeasurand.values[phaseValue as keyof MeasurandPerPhaseSampledValueTemplates],
-          undefined,
-          phaseValue
-        )
-      )
-      const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1
-      validateCurrentMeasurandPhaseValue(
-        chargingStation,
-        connectorId,
-        connectorStatus,
-        meterValue.sampledValue[sampledValuesPerPhaseIndex],
-        connectorMaximumAmperage,
-        connectorMinimumAmperage,
-        debug
-      )
-    }
-  }
-  // Energy.Active.Import.Register measurand (default)
-  const energyMeasurand = buildEnergyMeasurandValue(
-    chargingStation,
-    connectorId,
-    interval,
-    undefined,
-    measurandsKey
-  )
-  if (energyMeasurand != null) {
-    updateConnectorEnergyValues(connectorStatus, energyMeasurand.value)
-    const unitDivider = energyMeasurand.template.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1
-    const energySampledValue = buildVersionedSampledValue(
-      energyMeasurand.template,
-      roundTo(
-        chargingStation.getEnergyActiveImportRegisterByTransactionId(transactionId) / unitDivider,
-        2
-      )
-    )
-    meterValue.sampledValue.push(energySampledValue)
-    const connectorMaximumAvailablePower =
-      chargingStation.getConnectorMaximumAvailablePower(connectorId)
-    const connectorMaximumEnergyRounded = roundTo(
-      (connectorMaximumAvailablePower * interval) / (3600 * 1000),
-      2
-    )
-    const connectorMinimumEnergyRounded = roundTo(energyMeasurand.template.minimumValue ?? 0, 2)
-    validateEnergyMeasurandValue(
-      chargingStation,
-      connectorId,
-      energySampledValue,
-      energyMeasurand.value,
-      connectorMinimumEnergyRounded,
-      connectorMaximumEnergyRounded,
-      interval,
-      debug
-    )
-  }
-  return meterValue
-}
-
-/**
- * Builds an OCPP 1.6 sampled value from a template and measurement data.
- * @param sampledValueTemplate - The sampled value template to use.
- * @param value - The measured value.
- * @param context - The reading context.
- * @param phase - The phase of the measurement.
- * @returns The built OCPP 1.6 sampled value.
- */
-export function buildSampledValueForOCPP16 (
-  sampledValueTemplate: SampledValueTemplate,
-  value: number,
-  context?: MeterValueContext,
-  phase?: MeterValuePhase
-): OCPP16SampledValue {
-  return buildSampledValue(
-    OCPPVersion.VERSION_16,
-    sampledValueTemplate,
-    value,
-    context,
-    phase
-  ) as OCPP16SampledValue
-}
index 28cf8eee6fb05e39a64935bd19f5387258780693..6f6894faf26efff9fc1f5da1ed7f4857ce089951 100644 (file)
@@ -1,4 +1,42 @@
-import type { ChargingStationInfo, OCPP16BootNotificationRequest } from '../../../types/index.js'
+import type { ChargingStation } from '../../../charging-station/index.js'
+
+import { OCPPError } from '../../../exception/index.js'
+import {
+  type ChargingStationInfo,
+  type ConfigurationKeyType,
+  CurrentType,
+  ErrorType,
+  type MeasurandPerPhaseSampledValueTemplates,
+  type MeasurandValues,
+  type MeterValueContext,
+  type MeterValuePhase,
+  MeterValueUnit,
+  type OCPP16BootNotificationRequest,
+  type OCPP16MeterValue,
+  type OCPP16SampledValue,
+  OCPPVersion,
+  RequestCommand,
+  type SampledValueTemplate,
+} from '../../../types/index.js'
+import { ACElectricUtils, DCElectricUtils, roundTo } from '../../../utils/index.js'
+import {
+  addLineToLineVoltageToMeterValue,
+  addMainVoltageToMeterValue,
+  addPhaseVoltageToMeterValue,
+  buildCurrentMeasurandValue,
+  buildEmptyMeterValue,
+  buildEnergyMeasurandValue,
+  buildPowerMeasurandValue,
+  buildSampledValue,
+  buildSocMeasurandValue,
+  buildVoltageMeasurandValue,
+  updateConnectorEnergyValues,
+  validateCurrentMeasurandPhaseValue,
+  validateCurrentMeasurandValue,
+  validateEnergyMeasurandValue,
+  validatePowerMeasurandValue,
+  validateSocMeasurandValue,
+} from '../OCPPServiceUtils.js'
 
 export const buildOCPP16BootNotificationRequest = (
   stationInfo: ChargingStationInfo
@@ -23,3 +61,269 @@ export const buildOCPP16BootNotificationRequest = (
     meterType: stationInfo.meterType,
   }),
 })
+
+export const buildMeterValueForOCPP16 = (
+  chargingStation: ChargingStation,
+  transactionId: number | string,
+  interval: number,
+  measurandsKey?: ConfigurationKeyType,
+  context?: MeterValueContext,
+  debug = false
+): OCPP16MeterValue => {
+  const connectorId = chargingStation.getConnectorIdByTransactionId(transactionId)
+  if (connectorId == null) {
+    throw new OCPPError(
+      ErrorType.INTERNAL_ERROR,
+      `Cannot build MeterValues: no connector found for transaction ${String(transactionId)}`,
+      RequestCommand.METER_VALUES
+    )
+  }
+  const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+  const meterValue = buildEmptyMeterValue() as OCPP16MeterValue
+  const buildVersionedSampledValue = (
+    sampledValueTemplate: SampledValueTemplate,
+    value: number,
+    context?: MeterValueContext,
+    phase?: MeterValuePhase
+  ): OCPP16SampledValue => {
+    return buildSampledValueForOCPP16(sampledValueTemplate, value, context, phase)
+  }
+  // SoC measurand
+  const socMeasurand = buildSocMeasurandValue(
+    chargingStation,
+    connectorId,
+    undefined,
+    measurandsKey
+  )
+  if (socMeasurand != null) {
+    const socSampledValue = buildVersionedSampledValue(socMeasurand.template, socMeasurand.value)
+    meterValue.sampledValue.push(socSampledValue)
+    validateSocMeasurandValue(
+      chargingStation,
+      connectorId,
+      socSampledValue,
+      socMeasurand.template.minimumValue ?? 0,
+      100,
+      debug
+    )
+  }
+  // Voltage measurand
+  const voltageMeasurand = buildVoltageMeasurandValue(
+    chargingStation,
+    connectorId,
+    undefined,
+    measurandsKey
+  )
+  if (voltageMeasurand != null) {
+    addMainVoltageToMeterValue(
+      chargingStation,
+      meterValue,
+      voltageMeasurand,
+      buildVersionedSampledValue
+    )
+    for (
+      let phase = 1;
+      chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
+      phase++
+    ) {
+      addPhaseVoltageToMeterValue(
+        chargingStation,
+        connectorId,
+        meterValue,
+        voltageMeasurand,
+        phase,
+        buildVersionedSampledValue
+      )
+      addLineToLineVoltageToMeterValue(
+        chargingStation,
+        connectorId,
+        meterValue,
+        voltageMeasurand,
+        phase,
+        buildVersionedSampledValue
+      )
+    }
+  }
+  // Power.Active.Import measurand
+  const powerMeasurand = buildPowerMeasurandValue(
+    chargingStation,
+    connectorId,
+    undefined,
+    measurandsKey
+  )
+  if (powerMeasurand != null) {
+    const unitDivider = powerMeasurand.template.unit === MeterValueUnit.KILO_WATT ? 1000 : 1
+    const connectorMaximumAvailablePower =
+      chargingStation.getConnectorMaximumAvailablePower(connectorId)
+    const connectorMaximumPower = Math.round(connectorMaximumAvailablePower)
+    const connectorMinimumPower = Math.round(powerMeasurand.template.minimumValue ?? 0)
+
+    meterValue.sampledValue.push(
+      buildVersionedSampledValue(powerMeasurand.template, powerMeasurand.values.allPhases)
+    )
+    const sampledValuesIndex = meterValue.sampledValue.length - 1
+    validatePowerMeasurandValue(
+      chargingStation,
+      connectorId,
+      connectorStatus,
+      meterValue.sampledValue[sampledValuesIndex],
+      connectorMaximumPower / unitDivider,
+      connectorMinimumPower / unitDivider,
+      debug
+    )
+    if (chargingStation.getNumberOfPhases() === 3) {
+      const connectorMaximumPowerPerPhase = Math.round(
+        connectorMaximumAvailablePower / chargingStation.getNumberOfPhases()
+      )
+      const connectorMinimumPowerPerPhase = Math.round(
+        connectorMinimumPower / chargingStation.getNumberOfPhases()
+      )
+      for (let phase = 1; phase <= chargingStation.getNumberOfPhases(); phase++) {
+        const phaseTemplate =
+          powerMeasurand.perPhaseTemplates[
+            `L${phase.toString()}` as keyof MeasurandPerPhaseSampledValueTemplates
+          ]
+        if (phaseTemplate != null) {
+          const phaseValue = `L${phase.toString()}-N` as MeterValuePhase
+          const phasePowerValue =
+            powerMeasurand.values[`L${phase.toString()}` as keyof MeasurandValues]
+          meterValue.sampledValue.push(
+            buildVersionedSampledValue(phaseTemplate, phasePowerValue, undefined, phaseValue)
+          )
+          const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1
+          validatePowerMeasurandValue(
+            chargingStation,
+            connectorId,
+            connectorStatus,
+            meterValue.sampledValue[sampledValuesPerPhaseIndex],
+            connectorMaximumPowerPerPhase / unitDivider,
+            connectorMinimumPowerPerPhase / unitDivider,
+            debug
+          )
+        }
+      }
+    }
+  }
+  // Current.Import measurand
+  const currentMeasurand = buildCurrentMeasurandValue(
+    chargingStation,
+    connectorId,
+    undefined,
+    measurandsKey
+  )
+  if (currentMeasurand != null) {
+    const connectorMaximumAvailablePower =
+      chargingStation.getConnectorMaximumAvailablePower(connectorId)
+    const connectorMaximumAmperage =
+      chargingStation.stationInfo?.currentOutType === CurrentType.AC
+        ? ACElectricUtils.amperagePerPhaseFromPower(
+          chargingStation.getNumberOfPhases(),
+          connectorMaximumAvailablePower,
+          chargingStation.getVoltageOut()
+        )
+        : DCElectricUtils.amperage(connectorMaximumAvailablePower, chargingStation.getVoltageOut())
+    const connectorMinimumAmperage = currentMeasurand.template.minimumValue ?? 0
+
+    meterValue.sampledValue.push(
+      buildVersionedSampledValue(currentMeasurand.template, currentMeasurand.values.allPhases)
+    )
+    const sampledValuesIndex = meterValue.sampledValue.length - 1
+    validateCurrentMeasurandValue(
+      chargingStation,
+      connectorId,
+      connectorStatus,
+      meterValue.sampledValue[sampledValuesIndex],
+      connectorMaximumAmperage,
+      connectorMinimumAmperage,
+      debug
+    )
+    for (
+      let phase = 1;
+      chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
+      phase++
+    ) {
+      const phaseValue = `L${phase.toString()}` as MeterValuePhase
+      meterValue.sampledValue.push(
+        buildVersionedSampledValue(
+          currentMeasurand.perPhaseTemplates[
+            phaseValue as keyof MeasurandPerPhaseSampledValueTemplates
+          ] ?? currentMeasurand.template,
+          currentMeasurand.values[phaseValue as keyof MeasurandPerPhaseSampledValueTemplates],
+          undefined,
+          phaseValue
+        )
+      )
+      const sampledValuesPerPhaseIndex = meterValue.sampledValue.length - 1
+      validateCurrentMeasurandPhaseValue(
+        chargingStation,
+        connectorId,
+        connectorStatus,
+        meterValue.sampledValue[sampledValuesPerPhaseIndex],
+        connectorMaximumAmperage,
+        connectorMinimumAmperage,
+        debug
+      )
+    }
+  }
+  // Energy.Active.Import.Register measurand (default)
+  const energyMeasurand = buildEnergyMeasurandValue(
+    chargingStation,
+    connectorId,
+    interval,
+    undefined,
+    measurandsKey
+  )
+  if (energyMeasurand != null) {
+    updateConnectorEnergyValues(connectorStatus, energyMeasurand.value)
+    const unitDivider = energyMeasurand.template.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1
+    const energySampledValue = buildVersionedSampledValue(
+      energyMeasurand.template,
+      roundTo(
+        chargingStation.getEnergyActiveImportRegisterByTransactionId(transactionId) / unitDivider,
+        2
+      )
+    )
+    meterValue.sampledValue.push(energySampledValue)
+    const connectorMaximumAvailablePower =
+      chargingStation.getConnectorMaximumAvailablePower(connectorId)
+    const connectorMaximumEnergyRounded = roundTo(
+      (connectorMaximumAvailablePower * interval) / (3600 * 1000),
+      2
+    )
+    const connectorMinimumEnergyRounded = roundTo(energyMeasurand.template.minimumValue ?? 0, 2)
+    validateEnergyMeasurandValue(
+      chargingStation,
+      connectorId,
+      energySampledValue,
+      energyMeasurand.value,
+      connectorMinimumEnergyRounded,
+      connectorMaximumEnergyRounded,
+      interval,
+      debug
+    )
+  }
+  return meterValue
+}
+
+/**
+ * Builds an OCPP 1.6 sampled value from a template and measurement data.
+ * @param sampledValueTemplate - The sampled value template to use.
+ * @param value - The measured value.
+ * @param context - The reading context.
+ * @param phase - The phase of the measurement.
+ * @returns The built OCPP 1.6 sampled value.
+ */
+export function buildSampledValueForOCPP16 (
+  sampledValueTemplate: SampledValueTemplate,
+  value: number,
+  context?: MeterValueContext,
+  phase?: MeterValuePhase
+): OCPP16SampledValue {
+  return buildSampledValue(
+    OCPPVersion.VERSION_16,
+    sampledValueTemplate,
+    value,
+    context,
+    phase
+  ) as OCPP16SampledValue
+}
diff --git a/src/charging-station/ocpp/2.0/OCPP20MeterValueBuilders.ts b/src/charging-station/ocpp/2.0/OCPP20MeterValueBuilders.ts
deleted file mode 100644 (file)
index 2bfe856..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-import type { ChargingStation } from '../../../charging-station/index.js'
-
-import { OCPPError } from '../../../exception/index.js'
-import {
-  type ConfigurationKeyType,
-  ErrorType,
-  type MeterValueContext,
-  type MeterValuePhase,
-  MeterValueUnit,
-  type OCPP20MeterValue,
-  type OCPP20SampledValue,
-  OCPPVersion,
-  RequestCommand,
-  type SampledValueTemplate,
-} from '../../../types/index.js'
-import { roundTo } from '../../../utils/index.js'
-import {
-  addLineToLineVoltageToMeterValue,
-  addMainVoltageToMeterValue,
-  addPhaseVoltageToMeterValue,
-  buildCurrentMeasurandValue,
-  buildEmptyMeterValue,
-  buildEnergyMeasurandValue,
-  buildPowerMeasurandValue,
-  buildSampledValue,
-  buildSocMeasurandValue,
-  buildVoltageMeasurandValue,
-  updateConnectorEnergyValues,
-  validateEnergyMeasurandValue,
-  validateSocMeasurandValue,
-} from '../OCPPServiceUtils.js'
-
-export const buildMeterValueForOCPP20 = (
-  chargingStation: ChargingStation,
-  transactionId: number | string,
-  interval: number,
-  measurandsKey?: ConfigurationKeyType,
-  context?: MeterValueContext,
-  debug = false
-): OCPP20MeterValue => {
-  const connectorId = chargingStation.getConnectorIdByTransactionId(transactionId)
-  const evseId = chargingStation.getEvseIdByTransactionId(transactionId)
-  if (connectorId == null || evseId == null) {
-    throw new OCPPError(
-      ErrorType.INTERNAL_ERROR,
-      `Cannot build MeterValues: no connector/EVSE found for transaction ${String(transactionId)}`,
-      RequestCommand.METER_VALUES
-    )
-  }
-  const connectorStatus = chargingStation.getConnectorStatus(connectorId)
-  const meterValue = buildEmptyMeterValue() as OCPP20MeterValue
-  const buildVersionedSampledValue = (
-    sampledValueTemplate: SampledValueTemplate,
-    value: number,
-    context?: MeterValueContext,
-    phase?: MeterValuePhase
-  ): OCPP20SampledValue => {
-    return buildSampledValueForOCPP20(sampledValueTemplate, value, context, phase)
-  }
-  // SoC measurand
-  const socMeasurand = buildSocMeasurandValue(chargingStation, connectorId, evseId, measurandsKey)
-  if (socMeasurand != null) {
-    const socSampledValue = buildVersionedSampledValue(
-      socMeasurand.template,
-      socMeasurand.value,
-      context
-    )
-    meterValue.sampledValue.push(socSampledValue)
-    validateSocMeasurandValue(
-      chargingStation,
-      connectorId,
-      socSampledValue,
-      socMeasurand.template.minimumValue ?? 0,
-      100,
-      debug
-    )
-  }
-  // Voltage measurand
-  const voltageMeasurand = buildVoltageMeasurandValue(
-    chargingStation,
-    connectorId,
-    evseId,
-    measurandsKey
-  )
-  if (voltageMeasurand != null) {
-    addMainVoltageToMeterValue(
-      chargingStation,
-      meterValue,
-      voltageMeasurand,
-      buildVersionedSampledValue,
-      context
-    )
-    for (
-      let phase = 1;
-      chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
-      phase++
-    ) {
-      addPhaseVoltageToMeterValue(
-        chargingStation,
-        connectorId,
-        meterValue,
-        voltageMeasurand,
-        phase,
-        buildVersionedSampledValue,
-        measurandsKey,
-        context
-      )
-      addLineToLineVoltageToMeterValue(
-        chargingStation,
-        connectorId,
-        meterValue,
-        voltageMeasurand,
-        phase,
-        buildVersionedSampledValue,
-        measurandsKey,
-        context
-      )
-    }
-  }
-  // Energy.Active.Import.Register measurand
-  const energyMeasurand = buildEnergyMeasurandValue(
-    chargingStation,
-    connectorId,
-    interval,
-    evseId,
-    measurandsKey
-  )
-  if (energyMeasurand != null) {
-    updateConnectorEnergyValues(connectorStatus, energyMeasurand.value)
-    const unitDivider = energyMeasurand.template.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1
-    const energySampledValue = buildVersionedSampledValue(
-      energyMeasurand.template,
-      roundTo(
-        chargingStation.getEnergyActiveImportRegisterByTransactionId(transactionId) / unitDivider,
-        2
-      ),
-      context
-    )
-    meterValue.sampledValue.push(energySampledValue)
-    const connectorMaximumAvailablePower =
-      chargingStation.getConnectorMaximumAvailablePower(connectorId)
-    const connectorMaximumEnergyRounded = roundTo(
-      (connectorMaximumAvailablePower * interval) / (3600 * 1000),
-      2
-    )
-    const connectorMinimumEnergyRounded = roundTo(energyMeasurand.template.minimumValue ?? 0, 2)
-    validateEnergyMeasurandValue(
-      chargingStation,
-      connectorId,
-      energySampledValue,
-      energyMeasurand.value,
-      connectorMinimumEnergyRounded,
-      connectorMaximumEnergyRounded,
-      interval,
-      debug
-    )
-  }
-  // Power.Active.Import measurand
-  const powerMeasurand = buildPowerMeasurandValue(
-    chargingStation,
-    connectorId,
-    evseId,
-    measurandsKey
-  )
-  if (powerMeasurand?.values.allPhases != null) {
-    const powerSampledValue = buildVersionedSampledValue(
-      powerMeasurand.template,
-      powerMeasurand.values.allPhases,
-      context
-    )
-    meterValue.sampledValue.push(powerSampledValue)
-  }
-  // Current.Import measurand
-  const currentMeasurand = buildCurrentMeasurandValue(
-    chargingStation,
-    connectorId,
-    evseId,
-    measurandsKey
-  )
-  if (currentMeasurand?.values.allPhases != null) {
-    const currentSampledValue = buildVersionedSampledValue(
-      currentMeasurand.template,
-      currentMeasurand.values.allPhases,
-      context
-    )
-    meterValue.sampledValue.push(currentSampledValue)
-  }
-  return meterValue
-}
-
-/**
- * Builds an OCPP 2.0 sampled value from a template and measurement data.
- * @param sampledValueTemplate - The sampled value template to use.
- * @param value - The measured value.
- * @param context - The reading context.
- * @param phase - The phase of the measurement.
- * @returns The built OCPP 2.0 sampled value.
- */
-export function buildSampledValueForOCPP20 (
-  sampledValueTemplate: SampledValueTemplate,
-  value: number,
-  context?: MeterValueContext,
-  phase?: MeterValuePhase
-): OCPP20SampledValue {
-  return buildSampledValue(
-    OCPPVersion.VERSION_20,
-    sampledValueTemplate,
-    value,
-    context,
-    phase
-  ) as OCPP20SampledValue
-}
index 83ad669b284f4319e7b9417d9cc8f59beebe0fbb..5457e870217801e68028180f0e86dd3e03b7b6af 100644 (file)
@@ -1,8 +1,37 @@
+import type { ChargingStation } from '../../../charging-station/index.js'
+
+import { OCPPError } from '../../../exception/index.js'
 import {
   BootReasonEnumType,
   type ChargingStationInfo,
+  type ConfigurationKeyType,
+  ErrorType,
+  type MeterValueContext,
+  type MeterValuePhase,
+  MeterValueUnit,
   type OCPP20BootNotificationRequest,
+  type OCPP20MeterValue,
+  type OCPP20SampledValue,
+  OCPPVersion,
+  RequestCommand,
+  type SampledValueTemplate,
 } from '../../../types/index.js'
+import { roundTo } from '../../../utils/index.js'
+import {
+  addLineToLineVoltageToMeterValue,
+  addMainVoltageToMeterValue,
+  addPhaseVoltageToMeterValue,
+  buildCurrentMeasurandValue,
+  buildEmptyMeterValue,
+  buildEnergyMeasurandValue,
+  buildPowerMeasurandValue,
+  buildSampledValue,
+  buildSocMeasurandValue,
+  buildVoltageMeasurandValue,
+  updateConnectorEnergyValues,
+  validateEnergyMeasurandValue,
+  validateSocMeasurandValue,
+} from '../OCPPServiceUtils.js'
 
 export const buildOCPP20BootNotificationRequest = (
   stationInfo: ChargingStationInfo,
@@ -26,3 +55,184 @@ export const buildOCPP20BootNotificationRequest = (
   },
   reason: bootReason,
 })
+
+export const buildMeterValueForOCPP20 = (
+  chargingStation: ChargingStation,
+  transactionId: number | string,
+  interval: number,
+  measurandsKey?: ConfigurationKeyType,
+  context?: MeterValueContext,
+  debug = false
+): OCPP20MeterValue => {
+  const connectorId = chargingStation.getConnectorIdByTransactionId(transactionId)
+  const evseId = chargingStation.getEvseIdByTransactionId(transactionId)
+  if (connectorId == null || evseId == null) {
+    throw new OCPPError(
+      ErrorType.INTERNAL_ERROR,
+      `Cannot build MeterValues: no connector/EVSE found for transaction ${String(transactionId)}`,
+      RequestCommand.METER_VALUES
+    )
+  }
+  const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+  const meterValue = buildEmptyMeterValue() as OCPP20MeterValue
+  const buildVersionedSampledValue = (
+    sampledValueTemplate: SampledValueTemplate,
+    value: number,
+    context?: MeterValueContext,
+    phase?: MeterValuePhase
+  ): OCPP20SampledValue => {
+    return buildSampledValueForOCPP20(sampledValueTemplate, value, context, phase)
+  }
+  // SoC measurand
+  const socMeasurand = buildSocMeasurandValue(chargingStation, connectorId, evseId, measurandsKey)
+  if (socMeasurand != null) {
+    const socSampledValue = buildVersionedSampledValue(
+      socMeasurand.template,
+      socMeasurand.value,
+      context
+    )
+    meterValue.sampledValue.push(socSampledValue)
+    validateSocMeasurandValue(
+      chargingStation,
+      connectorId,
+      socSampledValue,
+      socMeasurand.template.minimumValue ?? 0,
+      100,
+      debug
+    )
+  }
+  // Voltage measurand
+  const voltageMeasurand = buildVoltageMeasurandValue(
+    chargingStation,
+    connectorId,
+    evseId,
+    measurandsKey
+  )
+  if (voltageMeasurand != null) {
+    addMainVoltageToMeterValue(
+      chargingStation,
+      meterValue,
+      voltageMeasurand,
+      buildVersionedSampledValue,
+      context
+    )
+    for (
+      let phase = 1;
+      chargingStation.getNumberOfPhases() === 3 && phase <= chargingStation.getNumberOfPhases();
+      phase++
+    ) {
+      addPhaseVoltageToMeterValue(
+        chargingStation,
+        connectorId,
+        meterValue,
+        voltageMeasurand,
+        phase,
+        buildVersionedSampledValue,
+        measurandsKey,
+        context
+      )
+      addLineToLineVoltageToMeterValue(
+        chargingStation,
+        connectorId,
+        meterValue,
+        voltageMeasurand,
+        phase,
+        buildVersionedSampledValue,
+        measurandsKey,
+        context
+      )
+    }
+  }
+  // Energy.Active.Import.Register measurand
+  const energyMeasurand = buildEnergyMeasurandValue(
+    chargingStation,
+    connectorId,
+    interval,
+    evseId,
+    measurandsKey
+  )
+  if (energyMeasurand != null) {
+    updateConnectorEnergyValues(connectorStatus, energyMeasurand.value)
+    const unitDivider = energyMeasurand.template.unit === MeterValueUnit.KILO_WATT_HOUR ? 1000 : 1
+    const energySampledValue = buildVersionedSampledValue(
+      energyMeasurand.template,
+      roundTo(
+        chargingStation.getEnergyActiveImportRegisterByTransactionId(transactionId) / unitDivider,
+        2
+      ),
+      context
+    )
+    meterValue.sampledValue.push(energySampledValue)
+    const connectorMaximumAvailablePower =
+      chargingStation.getConnectorMaximumAvailablePower(connectorId)
+    const connectorMaximumEnergyRounded = roundTo(
+      (connectorMaximumAvailablePower * interval) / (3600 * 1000),
+      2
+    )
+    const connectorMinimumEnergyRounded = roundTo(energyMeasurand.template.minimumValue ?? 0, 2)
+    validateEnergyMeasurandValue(
+      chargingStation,
+      connectorId,
+      energySampledValue,
+      energyMeasurand.value,
+      connectorMinimumEnergyRounded,
+      connectorMaximumEnergyRounded,
+      interval,
+      debug
+    )
+  }
+  // Power.Active.Import measurand
+  const powerMeasurand = buildPowerMeasurandValue(
+    chargingStation,
+    connectorId,
+    evseId,
+    measurandsKey
+  )
+  if (powerMeasurand?.values.allPhases != null) {
+    const powerSampledValue = buildVersionedSampledValue(
+      powerMeasurand.template,
+      powerMeasurand.values.allPhases,
+      context
+    )
+    meterValue.sampledValue.push(powerSampledValue)
+  }
+  // Current.Import measurand
+  const currentMeasurand = buildCurrentMeasurandValue(
+    chargingStation,
+    connectorId,
+    evseId,
+    measurandsKey
+  )
+  if (currentMeasurand?.values.allPhases != null) {
+    const currentSampledValue = buildVersionedSampledValue(
+      currentMeasurand.template,
+      currentMeasurand.values.allPhases,
+      context
+    )
+    meterValue.sampledValue.push(currentSampledValue)
+  }
+  return meterValue
+}
+
+/**
+ * Builds an OCPP 2.0 sampled value from a template and measurement data.
+ * @param sampledValueTemplate - The sampled value template to use.
+ * @param value - The measured value.
+ * @param context - The reading context.
+ * @param phase - The phase of the measurement.
+ * @returns The built OCPP 2.0 sampled value.
+ */
+export function buildSampledValueForOCPP20 (
+  sampledValueTemplate: SampledValueTemplate,
+  value: number,
+  context?: MeterValueContext,
+  phase?: MeterValuePhase
+): OCPP20SampledValue {
+  return buildSampledValue(
+    OCPPVersion.VERSION_20,
+    sampledValueTemplate,
+    value,
+    context,
+    phase
+  ) as OCPP20SampledValue
+}
index ba61ce421ed23de7b32eeb8b1f53257303193fb6..e277e39f1838afa003e06d563e1d0deb369d8a6b 100644 (file)
@@ -57,10 +57,14 @@ import {
   min,
   roundTo,
 } from '../../utils/index.js'
-import { buildMeterValueForOCPP16 } from './1.6/OCPP16MeterValueBuilders.js'
-import { buildOCPP16BootNotificationRequest } from './1.6/OCPP16RequestBuilders.js'
-import { buildMeterValueForOCPP20 } from './2.0/OCPP20MeterValueBuilders.js'
-import { buildOCPP20BootNotificationRequest } from './2.0/OCPP20RequestBuilders.js'
+import {
+  buildMeterValueForOCPP16,
+  buildOCPP16BootNotificationRequest,
+} from './1.6/OCPP16RequestBuilders.js'
+import {
+  buildMeterValueForOCPP20,
+  buildOCPP20BootNotificationRequest,
+} from './2.0/OCPP20RequestBuilders.js'
 import { OCPPConstants } from './OCPPConstants.js'
 
 const moduleName = 'OCPPServiceUtils'