+++ /dev/null
-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
-}
-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
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
+}
+++ /dev/null
-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
-}
+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,
},
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
+}
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'