--- /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
+}
--- /dev/null
+import type { ChargingStationInfo, OCPP16BootNotificationRequest } from '../../../types/index.js'
+
+export const buildOCPP16BootNotificationRequest = (
+ stationInfo: ChargingStationInfo
+): OCPP16BootNotificationRequest => ({
+ chargePointModel: stationInfo.chargePointModel,
+ chargePointVendor: stationInfo.chargePointVendor,
+ ...(stationInfo.chargeBoxSerialNumber != null && {
+ chargeBoxSerialNumber: stationInfo.chargeBoxSerialNumber,
+ }),
+ ...(stationInfo.chargePointSerialNumber != null && {
+ chargePointSerialNumber: stationInfo.chargePointSerialNumber,
+ }),
+ ...(stationInfo.firmwareVersion != null && {
+ firmwareVersion: stationInfo.firmwareVersion,
+ }),
+ ...(stationInfo.iccid != null && { iccid: stationInfo.iccid }),
+ ...(stationInfo.imsi != null && { imsi: stationInfo.imsi }),
+ ...(stationInfo.meterSerialNumber != null && {
+ meterSerialNumber: stationInfo.meterSerialNumber,
+ }),
+ ...(stationInfo.meterType != null && {
+ meterType: stationInfo.meterType,
+ }),
+})
import { BaseError } from '../../../exception/index.js'
import {
ChargePointErrorCode,
- type ChargingStationInfo,
type ConfigurationKey,
type GenericResponse,
type MeterValuesRequest,
type MeterValuesResponse,
OCPP16AuthorizationStatus,
type OCPP16AvailabilityType,
- type OCPP16BootNotificationRequest,
type OCPP16ChangeAvailabilityResponse,
OCPP16ChargePointStatus,
type OCPP16ChargingProfile,
[OCPP16RequestCommand.STOP_TRANSACTION, 'StopTransaction'],
]
- /**
- * Builds an OCPP 1.6 BootNotification request payload from station info.
- * @param stationInfo - Charging station information
- * @returns Formatted OCPP 1.6 BootNotification request payload
- */
- public static buildBootNotificationRequest (
- stationInfo: ChargingStationInfo
- ): OCPP16BootNotificationRequest {
- return {
- chargePointModel: stationInfo.chargePointModel,
- chargePointVendor: stationInfo.chargePointVendor,
- ...(stationInfo.chargeBoxSerialNumber != null && {
- chargeBoxSerialNumber: stationInfo.chargeBoxSerialNumber,
- }),
- ...(stationInfo.chargePointSerialNumber != null && {
- chargePointSerialNumber: stationInfo.chargePointSerialNumber,
- }),
- ...(stationInfo.firmwareVersion != null && {
- firmwareVersion: stationInfo.firmwareVersion,
- }),
- ...(stationInfo.iccid != null && { iccid: stationInfo.iccid }),
- ...(stationInfo.imsi != null && { imsi: stationInfo.imsi }),
- ...(stationInfo.meterSerialNumber != null && {
- meterSerialNumber: stationInfo.meterSerialNumber,
- }),
- ...(stationInfo.meterType != null && {
- meterType: stationInfo.meterType,
- }),
- } satisfies OCPP16BootNotificationRequest
- }
-
/**
* @param commandParams - Status notification parameters
* @returns Formatted OCPP 1.6 StatusNotification request payload
--- /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
+}
--- /dev/null
+import {
+ BootReasonEnumType,
+ type ChargingStationInfo,
+ type OCPP20BootNotificationRequest,
+} from '../../../types/index.js'
+
+export const buildOCPP20BootNotificationRequest = (
+ stationInfo: ChargingStationInfo,
+ bootReason: BootReasonEnumType = BootReasonEnumType.PowerUp
+): OCPP20BootNotificationRequest => ({
+ chargingStation: {
+ model: stationInfo.chargePointModel,
+ vendorName: stationInfo.chargePointVendor,
+ ...(stationInfo.firmwareVersion != null && {
+ firmwareVersion: stationInfo.firmwareVersion,
+ }),
+ ...(stationInfo.chargeBoxSerialNumber != null && {
+ serialNumber: stationInfo.chargeBoxSerialNumber,
+ }),
+ ...((stationInfo.iccid != null || stationInfo.imsi != null) && {
+ modem: {
+ ...(stationInfo.iccid != null && { iccid: stationInfo.iccid }),
+ ...(stationInfo.imsi != null && { imsi: stationInfo.imsi }),
+ },
+ }),
+ },
+ reason: bootReason,
+})
import { type ChargingStation, resetConnectorStatus } from '../../../charging-station/index.js'
import { OCPPError } from '../../../exception/index.js'
import {
- BootReasonEnumType,
- type ChargingStationInfo,
type ConnectorStatus,
ConnectorStatusEnum,
ErrorType,
- type OCPP20BootNotificationRequest,
+ OCPP20AuthorizationStatusEnumType,
OCPP20ChargingStateEnumType,
OCPP20ComponentName,
type OCPP20ConnectorStatusEnumType,
type OCPP20EVSEType,
+ OCPP20IdTokenEnumType,
type OCPP20IdTokenInfoType,
type OCPP20IdTokenType,
OCPP20IncomingRequestCommand,
OCPPVersion,
ReasonCodeEnumType,
RequestCommand,
+ type StartTransactionResult,
+ type StopTransactionReason,
+ type StopTransactionResult,
type UUIDv4,
} from '../../../types/index.js'
import {
import {
buildMeterValue,
createPayloadConfigs,
+ mapStopReasonToOCPP20,
PayloadValidatorOptions,
} from '../OCPPServiceUtils.js'
import { OCPP20VariableManager } from './OCPP20VariableManager.js'
[OCPP20RequestCommand.TRANSACTION_EVENT, 'TransactionEvent'],
]
- /**
- * Builds an OCPP 2.0 BootNotification request payload from station info.
- * @param stationInfo - Charging station information
- * @param bootReason - Reason for the boot notification
- * @returns Formatted OCPP 2.0 BootNotification request payload
- */
- public static buildBootNotificationRequest (
- stationInfo: ChargingStationInfo,
- bootReason: BootReasonEnumType = BootReasonEnumType.PowerUp
- ): OCPP20BootNotificationRequest {
- return {
- chargingStation: {
- model: stationInfo.chargePointModel,
- vendorName: stationInfo.chargePointVendor,
- ...(stationInfo.firmwareVersion != null && {
- firmwareVersion: stationInfo.firmwareVersion,
- }),
- ...(stationInfo.chargeBoxSerialNumber != null && {
- serialNumber: stationInfo.chargeBoxSerialNumber,
- }),
- ...((stationInfo.iccid != null || stationInfo.imsi != null) && {
- modem: {
- ...(stationInfo.iccid != null && { iccid: stationInfo.iccid }),
- ...(stationInfo.imsi != null && { imsi: stationInfo.imsi }),
- },
- }),
- },
- reason: bootReason,
- } satisfies OCPP20BootNotificationRequest
- }
-
/**
* @param chargingStation - Target charging station for EVSE resolution
* @param commandParams - Status notification parameters
)
}
+ public static async startTransactionOnConnector (
+ chargingStation: ChargingStation,
+ connectorId: number,
+ idTag?: string
+ ): Promise<StartTransactionResult> {
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+ let transactionId = connectorStatus?.transactionId as string | undefined
+ if (transactionId == null) {
+ transactionId = generateUUID()
+ if (connectorStatus != null) {
+ connectorStatus.transactionId = transactionId
+ }
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(chargingStation, connectorId)
+ }
+ const startedMeterValues = OCPP20ServiceUtils.buildTransactionStartedMeterValues(
+ chargingStation,
+ transactionId
+ )
+ const response = await OCPP20ServiceUtils.sendTransactionEvent(
+ chargingStation,
+ OCPP20TransactionEventEnumType.Started,
+ OCPP20TriggerReasonEnumType.Authorized,
+ connectorId,
+ transactionId,
+ {
+ idToken:
+ idTag != null ? { idToken: idTag, type: OCPP20IdTokenEnumType.ISO14443 } : undefined,
+ ...(startedMeterValues.length > 0 && { meterValue: startedMeterValues }),
+ }
+ )
+ return {
+ accepted:
+ response.idTokenInfo == null ||
+ response.idTokenInfo.status === OCPP20AuthorizationStatusEnumType.Accepted,
+ }
+ }
+
/**
* Start periodic TransactionEvent(Updated) with meter values for a connector.
* @param chargingStation - Target charging station
}
}
+ public static async stopTransactionOnConnector (
+ chargingStation: ChargingStation,
+ connectorId: number,
+ reason?: StopTransactionReason
+ ): Promise<StopTransactionResult> {
+ const evseId = chargingStation.getEvseIdByConnectorId(connectorId)
+ if (evseId == null) {
+ logger.warn(
+ `${chargingStation.logPrefix()} stopTransactionOnConnector: cannot resolve EVSE ID for connector ${connectorId.toString()}, skipping`
+ )
+ return { accepted: false }
+ }
+ const { stoppedReason, triggerReason } = mapStopReasonToOCPP20(reason)
+ const response = await OCPP20ServiceUtils.requestStopTransaction(
+ chargingStation,
+ connectorId,
+ evseId,
+ triggerReason,
+ stoppedReason
+ )
+ return {
+ accepted:
+ response.idTokenInfo == null ||
+ response.idTokenInfo.status === OCPP20AuthorizationStatusEnumType.Accepted,
+ }
+ }
+
/**
* Stop periodic TransactionEvent(Updated) sending for a connector.
* @param chargingStation - Target charging station
-import type { BootReasonEnumType, StopTransactionReason } from '../../types/index.js'
+import type { StopTransactionReason } from '../../types/index.js'
import { type ChargingStation } from '../../charging-station/index.js'
import { OCPPError } from '../../exception/index.js'
import {
AuthorizationStatus,
- type BootNotificationRequest,
- type ChargingStationInfo,
ErrorType,
- OCPP20AuthorizationStatusEnumType,
- OCPP20IdTokenEnumType,
- OCPP20TransactionEventEnumType,
- OCPP20TriggerReasonEnumType,
OCPPVersion,
type StartTransactionResult,
type StopTransactionResult,
} from '../../types/index.js'
-import { generateUUID, logger, truncateId } from '../../utils/index.js'
+import { logger, truncateId } from '../../utils/index.js'
import { OCPP16ServiceUtils } from './1.6/OCPP16ServiceUtils.js'
import { OCPP20ServiceUtils } from './2.0/OCPP20ServiceUtils.js'
import {
return { accepted: response.idTagInfo.status === AuthorizationStatus.ACCEPTED }
}
case OCPPVersion.VERSION_20:
- case OCPPVersion.VERSION_201: {
- const connectorStatus = chargingStation.getConnectorStatus(connectorId)
- let transactionId = connectorStatus?.transactionId as string | undefined
- if (transactionId == null) {
- transactionId = generateUUID()
- if (connectorStatus != null) {
- connectorStatus.transactionId = transactionId
- }
- OCPP20ServiceUtils.resetTransactionSequenceNumber(chargingStation, connectorId)
- }
- const startedMeterValues = OCPP20ServiceUtils.buildTransactionStartedMeterValues(
- chargingStation,
- transactionId
- )
- const response = await OCPP20ServiceUtils.sendTransactionEvent(
- chargingStation,
- OCPP20TransactionEventEnumType.Started,
- OCPP20TriggerReasonEnumType.Authorized,
- connectorId,
- transactionId,
- {
- idToken:
- idTag != null ? { idToken: idTag, type: OCPP20IdTokenEnumType.ISO14443 } : undefined,
- ...(startedMeterValues.length > 0 && { meterValue: startedMeterValues }),
- }
- )
- return {
- accepted:
- response.idTokenInfo == null ||
- response.idTokenInfo.status === OCPP20AuthorizationStatusEnumType.Accepted,
- }
- }
+ case OCPPVersion.VERSION_201:
+ return OCPP20ServiceUtils.startTransactionOnConnector(chargingStation, connectorId, idTag)
default:
throw new OCPPError(
ErrorType.INTERNAL_ERROR,
return { accepted: response.idTagInfo?.status === AuthorizationStatus.ACCEPTED }
}
case OCPPVersion.VERSION_20:
- case OCPPVersion.VERSION_201: {
- const evseId = chargingStation.getEvseIdByConnectorId(connectorId)
- if (evseId == null) {
- logger.warn(
- `${chargingStation.logPrefix()} stopTransactionOnConnector: cannot resolve EVSE ID for connector ${connectorId.toString()}, skipping`
- )
- return { accepted: false }
- }
- const { stoppedReason, triggerReason } = mapStopReasonToOCPP20(reason)
- const response = await OCPP20ServiceUtils.requestStopTransaction(
- chargingStation,
- connectorId,
- evseId,
- triggerReason,
- stoppedReason
- )
- return {
- accepted:
- response.idTokenInfo == null ||
- response.idTokenInfo.status === OCPP20AuthorizationStatusEnumType.Accepted,
- }
- }
+ case OCPPVersion.VERSION_201:
+ return OCPP20ServiceUtils.stopTransactionOnConnector(chargingStation, connectorId, reason)
default:
throw new OCPPError(
ErrorType.INTERNAL_ERROR,
}
}
-/**
- * Builds an OCPP BootNotification request using the appropriate version-specific handler.
- * @param stationInfo - Charging station information
- * @param bootReason - Optional boot reason (OCPP 2.0 only)
- * @returns The BootNotification request payload, or undefined if the OCPP version is unsupported
- */
-export const buildBootNotificationRequest = (
- stationInfo: ChargingStationInfo,
- bootReason?: BootReasonEnumType
-): BootNotificationRequest | undefined => {
- switch (stationInfo.ocppVersion) {
- case OCPPVersion.VERSION_16:
- return OCPP16ServiceUtils.buildBootNotificationRequest(stationInfo)
- case OCPPVersion.VERSION_20:
- case OCPPVersion.VERSION_201:
- return OCPP20ServiceUtils.buildBootNotificationRequest(stationInfo, bootReason)
- default:
- return undefined
- }
-}
-
export const isIdTagAuthorized = async (
chargingStation: ChargingStation,
connectorId: number,
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
-import type { StopTransactionReason } from '../../types/index.js'
+import type { BootReasonEnumType, StopTransactionReason } from '../../types/index.js'
import { type ChargingStation, getConfigurationKey } from '../../charging-station/index.js'
import { BaseError, OCPPError } from '../../exception/index.js'
import {
+ type BootNotificationRequest,
+ type ChargingStationInfo,
type ConfigurationKeyType,
type ConnectorStatus,
CurrentType,
MeterValueMeasurand,
MeterValuePhase,
MeterValueUnit,
- type OCPP16MeterValue,
type OCPP16SampledValue,
OCPP16StopTransactionReason,
- type OCPP20MeterValue,
OCPP20ReasonEnumType,
type OCPP20SampledValue,
OCPP20TriggerReasonEnumType,
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 { OCPPConstants } from './OCPPConstants.js'
const moduleName = 'OCPPServiceUtils'
value: number
}
+export const buildBootNotificationRequest = (
+ stationInfo: ChargingStationInfo,
+ bootReason?: BootReasonEnumType
+): BootNotificationRequest | undefined => {
+ switch (stationInfo.ocppVersion) {
+ case OCPPVersion.VERSION_16:
+ return buildOCPP16BootNotificationRequest(stationInfo)
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201:
+ return buildOCPP20BootNotificationRequest(stationInfo, bootReason)
+ default:
+ return undefined
+ }
+}
+
/**
* Maps an OCPP 1.6 or generic stop transaction reason to OCPP 2.0 stopped and trigger reasons.
* @param reason - Stop transaction reason to map
}
}
-const buildSocMeasurandValue = (
+export const buildSocMeasurandValue = (
chargingStation: ChargingStation,
connectorId: number,
evseId?: number,
}
}
-const validateSocMeasurandValue = (
+export const validateSocMeasurandValue = (
chargingStation: ChargingStation,
connectorId: number,
sampledValue: SampledValue,
}
}
-const buildVoltageMeasurandValue = (
+export const buildVoltageMeasurandValue = (
chargingStation: ChargingStation,
connectorId: number,
evseId?: number,
}
}
-const addMainVoltageToMeterValue = <TSampledValue extends SampledValue>(
+export const addMainVoltageToMeterValue = <TSampledValue extends SampledValue>(
chargingStation: ChargingStation,
meterValue: { sampledValue: TSampledValue[] },
voltageData: { template: SampledValueTemplate; value: number },
}
}
-const addPhaseVoltageToMeterValue = <TSampledValue extends SampledValue>(
+export const addPhaseVoltageToMeterValue = <TSampledValue extends SampledValue>(
chargingStation: ChargingStation,
connectorId: number,
meterValue: { sampledValue: TSampledValue[] },
)
}
-const addLineToLineVoltageToMeterValue = <TSampledValue extends SampledValue>(
+export const addLineToLineVoltageToMeterValue = <TSampledValue extends SampledValue>(
chargingStation: ChargingStation,
connectorId: number,
meterValue: { sampledValue: TSampledValue[] },
)
}
-const buildEnergyMeasurandValue = (
+export const buildEnergyMeasurandValue = (
chargingStation: ChargingStation,
connectorId: number,
interval: number,
}
}
-const updateConnectorEnergyValues = (
+export const updateConnectorEnergyValues = (
connectorStatus: ConnectorStatus | undefined,
energyValue: number
): void => {
}
}
-const validateEnergyMeasurandValue = (
+export const validateEnergyMeasurandValue = (
chargingStation: ChargingStation,
connectorId: number,
sampledValue: SampledValue,
}
}
-const buildPowerMeasurandValue = (
+export const buildPowerMeasurandValue = (
chargingStation: ChargingStation,
connectorId: number,
evseId?: number,
}
}
-const validatePowerMeasurandValue = (
+export const validatePowerMeasurandValue = (
chargingStation: ChargingStation,
connectorId: number,
connectorStatus: ConnectorStatus | undefined,
}
}
-const validateCurrentMeasurandValue = (
+export const validateCurrentMeasurandValue = (
chargingStation: ChargingStation,
connectorId: number,
connectorStatus: ConnectorStatus | undefined,
}
}
-const validateCurrentMeasurandPhaseValue = (
+export const validateCurrentMeasurandPhaseValue = (
chargingStation: ChargingStation,
connectorId: number,
connectorStatus: ConnectorStatus | undefined,
}
}
-const buildCurrentMeasurandValue = (
+export const buildCurrentMeasurandValue = (
chargingStation: ChargingStation,
connectorId: number,
evseId?: number,
}
}
-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
-}
-
-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
-}
-
const checkMeasurandPowerDivider = (
chargingStation: ChargingStation,
measurandType: MeterValueMeasurand | undefined
}
}
-/**
- * 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.
- */
-function buildSampledValueForOCPP16 (
- sampledValueTemplate: SampledValueTemplate,
- value: number,
- context?: MeterValueContext,
- phase?: MeterValuePhase
-): OCPP16SampledValue {
- return buildSampledValue(
- OCPPVersion.VERSION_16,
- sampledValueTemplate,
- value,
- context,
- phase
- ) as OCPP16SampledValue
-}
-
-/**
- * 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.
- */
-function buildSampledValueForOCPP20 (
- sampledValueTemplate: SampledValueTemplate,
- value: number,
- context?: MeterValueContext,
- phase?: MeterValuePhase
-): OCPP20SampledValue {
- return buildSampledValue(
- OCPPVersion.VERSION_20,
- sampledValueTemplate,
- value,
- context,
- phase
- ) as OCPP20SampledValue
-}
-
const getMeasurandDefaultContext = (measurandType: MeterValueMeasurand): MeterValueContext => {
return MeterValueContext.SAMPLE_PERIODIC
}
export { OCPPRequestService } from './OCPPRequestService.js'
export { createOCPPServices } from './OCPPServiceFactory.js'
export {
- buildBootNotificationRequest,
flushQueuedTransactionMessages,
isIdTagAuthorized,
startTransactionOnConnector,
stopRunningTransactions,
stopTransactionOnConnector,
} from './OCPPServiceOperations.js'
-export { buildMeterValue } from './OCPPServiceUtils.js'
+export { buildBootNotificationRequest, buildMeterValue } from './OCPPServiceUtils.js'
import type { MockChargingStationOptions } from '../helpers/StationHelpers.js'
import {
- buildBootNotificationRequest,
flushQueuedTransactionMessages,
startTransactionOnConnector,
stopRunningTransactions,
stopTransactionOnConnector,
} from '../../../src/charging-station/ocpp/OCPPServiceOperations.js'
+import { buildBootNotificationRequest } from '../../../src/charging-station/ocpp/OCPPServiceUtils.js'
import {
BootReasonEnumType,
type OCPP20TransactionEventRequest,