Added handling of current meter values
MODIFY
src/server/ocpp/services/OCPPService.ts
src/server/ocpp/services/OCPPService.ts
@@ -424,6 +424,11 @@ export default class OCPPService {
transaction.currentVoltageL2 = Utils.convertToFloat(consumption.voltageL2);
transaction.currentVoltageL3 = Utils.convertToFloat(consumption.voltageL3);
transaction.currentVoltageDC = Utils.convertToFloat(consumption.voltageDC);
+ transaction.currentAmperage = Utils.convertToFloat(consumption.amperage);
+ transaction.currentAmperageL1 = Utils.convertToFloat(consumption.amperageL1);
+ transaction.currentAmperageL2 = Utils.convertToFloat(consumption.amperageL2);
+ transaction.currentAmperageL3 = Utils.convertToFloat(consumption.amperageL3);
+ transaction.currentAmperageDC = Utils.convertToFloat(consumption.amperageDC);
transaction.currentTimestamp = Utils.convertToDate(consumption.endedAt);
transaction.currentStateOfCharge = Utils.convertToInt(consumption.stateOfCharge);
// If Transaction.Begin not provided (Cahors)
@@ -948,6 +953,42 @@ export default class OCPPService {
attribute: Constants.OCPP_VOLTAGE_L3_ATTRIBUTE
});
}
+ // Add Amperage
+ if (transaction.currentAmperage > 0 || transaction.currentAmperageDC > 0) {
+ stopMeterValues.push({
+ id: (id++).toString(),
+ ...meterValueBasedProps,
+ value: (transaction.currentAmperage ? transaction.currentAmperage : transaction.currentAmperageDC),
+ attribute: Constants.OCPP_CURRENT_ATTRIBUTE
+ });
+ }
+ // Add Amperage L1
+ if (transaction.currentAmperageL1 > 0) {
+ stopMeterValues.push({
+ id: (id++).toString(),
+ ...meterValueBasedProps,
+ value: transaction.currentAmperageL1,
+ attribute: Constants.OCPP_CURRENT_L1_ATTRIBUTE
+ });
+ }
+ // Add Amperage L2
+ if (transaction.currentAmperageL2 > 0) {
+ stopMeterValues.push({
+ id: (id++).toString(),
+ ...meterValueBasedProps,
+ value: transaction.currentAmperageL2,
+ attribute: Constants.OCPP_CURRENT_L2_ATTRIBUTE
+ });
+ }
+ // Add Amperage L3
+ if (transaction.currentAmperageL3 > 0) {
+ stopMeterValues.push({
+ id: (id++).toString(),
+ ...meterValueBasedProps,
+ value: transaction.currentAmperageL3,
+ attribute: Constants.OCPP_CURRENT_L3_ATTRIBUTE
+ });
+ }
return stopMeterValues;
}
@@ -1263,6 +1304,32 @@ export default class OCPPService {
}
break;
}
+ // Handle Amperage (A)
+ } else if (OCPPUtils.isCurrentImportMeterValue(meterValue)) {
+ const amperage = Utils.convertToFloat(meterValue.value);
+ const currentType = Utils.getChargingStationCurrentType(chargingStation, null, transaction.connectorId);
+ // AC Charging Station
+ switch (currentType) {
+ case CurrentType.DC:
+ consumption.amperageDC = amperage;
+ break;
+ case CurrentType.AC:
+ switch (meterValue.attribute.phase) {
+ case OCPPPhase.L1:
+ consumption.amperageL1 = amperage;
+ break;
+ case OCPPPhase.L2:
+ consumption.amperageL2 = amperage;
+ break;
+ case OCPPPhase.L3:
+ consumption.amperageL3 = amperage;
+ break;
+ default:
+ consumption.amperage = amperage;
+ break;
+ }
+ break;
+ }
// Handle Consumption (Wh/kWh)
} else if (OCPPUtils.isEnergyActiveImportMeterValue(meterValue)) {
// Complete consumption
@@ -1413,6 +1480,37 @@ export default class OCPPService {
continue;
}
}
+ // Amperage
+ if (meterValue.attribute.measurand === OCPPMeasurand.CURRENT_IMPORT) {
+ // Set only the last Amperage (used in the last consumtion)
+ if (meterValue.attribute.context === OCPPReadingContext.TRANSACTION_END) {
+ const amperage = Utils.convertToFloat(meterValue.value);
+ const currentType = Utils.getChargingStationCurrentType(chargingStation, null, transaction.connectorId);
+ // AC Charging Station
+ switch (currentType) {
+ case CurrentType.DC:
+ transaction.currentAmperageDC = amperage;
+ break;
+ case CurrentType.AC:
+ switch (meterValue.attribute.phase) {
+ case OCPPPhase.L1:
+ transaction.currentAmperageL1 = amperage;
+ break;
+ case OCPPPhase.L2:
+ transaction.currentAmperageL2 = amperage;
+ break;
+ case OCPPPhase.L3:
+ transaction.currentAmperageL3 = amperage;
+ break;
+ default:
+ transaction.currentAmperage = amperage;
+ break;
+ }
+ break;
+ }
+ continue;
+ }
+ }
// Consumption
if (OCPPUtils.isEnergyActiveImportMeterValue(meterValue)) {
transaction.numberOfMeterValues++;

MODIFY
src/server/rest/service/security/TransactionSecurity.ts
src/server/rest/service/security/TransactionSecurity.ts
@@ -152,6 +152,11 @@ export default class TransactionSecurity {
filteredTransaction.currentVoltageL2 = transaction.currentVoltageL2;
filteredTransaction.currentVoltageL3 = transaction.currentVoltageL3;
filteredTransaction.currentVoltageDC = transaction.currentVoltageDC;
+ filteredTransaction.currentAmperage = transaction.currentAmperage;
+ filteredTransaction.currentAmperageL1 = transaction.currentAmperageL1;
+ filteredTransaction.currentAmperageL2 = transaction.currentAmperageL2;
+ filteredTransaction.currentAmperageL3 = transaction.currentAmperageL3;
+ filteredTransaction.currentAmperageDC = transaction.currentAmperageDC;
}
if (!transaction.stop && transaction.chargeBox && transaction.chargeBox.connectors) {
const foundConnector = Utils.getConnectorFromID(transaction.chargeBox, transaction.connectorId);
@@ -333,6 +338,11 @@ export default class TransactionSecurity {
voltageL2: consumption.voltageL2,
voltageL3: consumption.voltageL3,
voltageDC: consumption.voltageDC,
+ amperage: consumption.amperage,
+ amperageL1: consumption.amperageL1,
+ amperageL2: consumption.amperageL2,
+ amperageL3: consumption.amperageL3,
+ amperageDC: consumption.amperageDC,
};
return newConsumption;
});

MODIFY
src/storage/mongodb/ConsumptionStorage.ts
src/storage/mongodb/ConsumptionStorage.ts
@@ -39,6 +39,11 @@ export default class ConsumptionStorage {
voltageL2: Utils.convertToFloat(consumptionToSave.voltageL2),
voltageL3: Utils.convertToFloat(consumptionToSave.voltageL3),
voltageDC: Utils.convertToFloat(consumptionToSave.voltageDC),
+ amperage: Utils.convertToFloat(consumptionToSave.amperage),
+ amperageL1: Utils.convertToFloat(consumptionToSave.amperageL1),
+ amperageL2: Utils.convertToFloat(consumptionToSave.amperageL2),
+ amperageL3: Utils.convertToFloat(consumptionToSave.amperageL3),
+ amperageDC: Utils.convertToFloat(consumptionToSave.amperageDC),
pricingSource: consumptionToSave.pricingSource,
amount: Utils.convertToFloat(consumptionToSave.amount),
roundedAmount: Utils.convertToFloat(consumptionToSave.roundedAmount),

MODIFY
src/storage/mongodb/TransactionStorage.ts
src/storage/mongodb/TransactionStorage.ts
@@ -83,6 +83,11 @@ export default class TransactionStorage {
currentVoltageL2: Utils.convertToInt(transactionToSave.currentVoltageL2),
currentVoltageL3: Utils.convertToInt(transactionToSave.currentVoltageL3),
currentVoltageDC: Utils.convertToInt(transactionToSave.currentVoltageDC),
+ currentAmperage: Utils.convertToFloat(transactionToSave.currentAmperage),
+ currentAmperageL1: Utils.convertToInt(transactionToSave.currentAmperageL1),
+ currentAmperageL2: Utils.convertToInt(transactionToSave.currentAmperageL2),
+ currentAmperageL3: Utils.convertToInt(transactionToSave.currentAmperageL3),
+ currentAmperageDC: Utils.convertToInt(transactionToSave.currentAmperageDC),
};
if (transactionToSave.stop) {
// Add stop
@@ -121,6 +126,11 @@ export default class TransactionStorage {
delete transactionMDB.currentVoltageL2;
delete transactionMDB.currentVoltageL3;
delete transactionMDB.currentVoltageDC;
+ delete transactionMDB.currentAmperage;
+ delete transactionMDB.currentAmperageL1;
+ delete transactionMDB.currentAmperageL2;
+ delete transactionMDB.currentAmperageL3;
+ delete transactionMDB.currentAmperageDC;
}
if (transactionToSave.remotestop) {
transactionMDB.remotestop = {

MODIFY
src/types/Consumption.ts
src/types/Consumption.ts
@@ -25,6 +25,11 @@ export default interface Consumption {
voltageL2: number;
voltageL3: number;
voltageDC: number;
+ amperage: number;
+ amperageL1: number;
+ amperageL2: number;
+ amperageL3: number;
+ amperageDC: number;
totalInactivitySecs: number;
totalDurationSecs: number;
stateOfCharge: number;

MODIFY
src/types/Transaction.ts
src/types/Transaction.ts
@@ -85,6 +85,11 @@ export default interface Transaction {
currentVoltageL2?: number;
currentVoltageL3?: number;
currentVoltageDC?: number;
+ currentAmperage?: number;
+ currentAmperageL1?: number;
+ currentAmperageL2?: number;
+ currentAmperageL3?: number;
+ currentAmperageDC?: number;
currentConsumptionWh?: number;
currentCumulatedPrice?: number;
currentTotalConsumptionWh: number;
@@ -117,4 +122,9 @@ export interface TransactionConsumption {
voltageL2: number;
voltageL3: number;
voltageDC: number;
+ amperage: number;
+ amperageL1: number;
+ amperageL2: number;
+ amperageL3: number;
+ amperageDC: number;
}

MODIFY
src/utils/Constants.ts
src/utils/Constants.ts
@@ -188,6 +188,29 @@ export default class Constants {
phase: OCPPPhase.L3,
};
+ public static readonly OCPP_CURRENT_ATTRIBUTE: OCPPAttribute = {
+ format: OCPPValueFormat.RAW,
+ measurand: OCPPMeasurand.CURRENT_IMPORT,
+ unit: OCPPUnitOfMeasure.AMP,
+ location: OCPPLocation.OUTLET,
+ context: OCPPReadingContext.SAMPLE_PERIODIC
+ };
+
+ public static readonly OCPP_CURRENT_L1_ATTRIBUTE: OCPPAttribute = {
+ ...Constants.OCPP_CURRENT_ATTRIBUTE,
+ phase: OCPPPhase.L1,
+ };
+
+ public static readonly OCPP_CURRENT_L2_ATTRIBUTE: OCPPAttribute = {
+ ...Constants.OCPP_CURRENT_ATTRIBUTE,
+ phase: OCPPPhase.L2,
+ };
+
+ public static readonly OCPP_CURRENT_L3_ATTRIBUTE: OCPPAttribute = {
+ ...Constants.OCPP_CURRENT_ATTRIBUTE,
+ phase: OCPPPhase.L3,
+ };
+
public static readonly OCPP_POWER_ATTRIBUTE: OCPPAttribute = {
format: OCPPValueFormat.RAW,
measurand: OCPPMeasurand.POWER_ACTIVE_IMPORT,

MODIFY
test/api/OCPPCommonTests.ts
test/api/OCPPCommonTests.ts
@@ -49,6 +49,11 @@ export default class OCPPCommonTests {
public voltageL2MeterValues: number[];
public voltageL3MeterValues: number[];
+ public amperageMeterValues: number[];
+ public amperageL1MeterValues: number[];
+ public amperageL2MeterValues: number[];
+ public amperageL3MeterValues: number[];
+
public transactionStartSignedData: string;
public transactionEndSignedData: string;
@@ -166,6 +171,20 @@ export default class OCPPCommonTests {
this.voltageL3MeterValues = Array.from({ length: 14 }, () => faker.random.number({
min: 220, max: 240
}));
+ // Amperage (14 values)
+ this.amperageL1MeterValues = Array.from({ length: 14 }, () => faker.random.number({
+ min: 16, max: 32
+ }));
+ this.amperageL2MeterValues = Array.from({ length: 14 }, () => faker.random.number({
+ min: 16, max: 32
+ }));
+ this.amperageL3MeterValues = Array.from({ length: 14 }, () => faker.random.number({
+ min: 16, max: 32
+ }));
+ this.amperageMeterValues = [];
+ for (let i = 0; i < this.amperageL1MeterValues.length; i++) {
+ this.amperageMeterValues.push(this.amperageL1MeterValues[i] + this.amperageL2MeterValues[i] + this.amperageL3MeterValues[i]);
+ }
// Total Inactivity (14 values)
this.totalInactivities = [];
let lastInactivity = 0;
@@ -413,6 +432,10 @@ export default class OCPPCommonTests {
voltageL1MeterValue: this.voltageL1MeterValues[0],
voltageL2MeterValue: this.voltageL2MeterValues[0],
voltageL3MeterValue: this.voltageL3MeterValues[0],
+ amperageMeterValue: this.amperageMeterValues[0],
+ amperageL1MeterValue: this.amperageL1MeterValues[0],
+ amperageL2MeterValue: this.amperageL2MeterValues[0],
+ amperageL3MeterValue: this.amperageL3MeterValues[0],
signedDataMeterValue: withSignedData ? this.transactionStartSignedData : null,
}
);
@@ -442,6 +465,10 @@ export default class OCPPCommonTests {
voltageL1MeterValue: this.voltageL1MeterValues[index],
voltageL2MeterValue: this.voltageL2MeterValues[index],
voltageL3MeterValue: this.voltageL3MeterValues[index],
+ amperageMeterValue: this.amperageMeterValues[index],
+ amperageL1MeterValue: this.amperageL1MeterValues[index],
+ amperageL2MeterValue: this.amperageL2MeterValues[index],
+ amperageL3MeterValue: this.amperageL3MeterValues[index],
socMeterValue: withSoC ? this.socMeterValues[index] : 0,
}
);
@@ -482,6 +509,10 @@ export default class OCPPCommonTests {
voltageL1MeterValue: this.voltageL1MeterValues[this.voltageL1MeterValues.length - 1],
voltageL2MeterValue: this.voltageL2MeterValues[this.voltageL2MeterValues.length - 1],
voltageL3MeterValue: this.voltageL3MeterValues[this.voltageL3MeterValues.length - 1],
+ amperageMeterValue: this.amperageMeterValues[this.amperageMeterValues.length - 1],
+ amperageL1MeterValue: this.amperageL1MeterValues[this.amperageL1MeterValues.length - 1],
+ amperageL2MeterValue: this.amperageL2MeterValues[this.amperageL2MeterValues.length - 1],
+ amperageL3MeterValue: this.amperageL3MeterValues[this.amperageL3MeterValues.length - 1],
socMeterValue: withSoC ? this.socMeterValues[this.socMeterValues.length - 1] : 0,
signedDataMeterValue: withSignedData ? this.transactionEndSignedData : null
}
@@ -596,6 +627,10 @@ export default class OCPPCommonTests {
'voltageL1': checkNewMeterValues ? this.voltageL1MeterValues[i] : 0,
'voltageL2': checkNewMeterValues ? this.voltageL2MeterValues[i] : 0,
'voltageL3': checkNewMeterValues ? this.voltageL3MeterValues[i] : 0,
+ 'amperage': checkNewMeterValues ? this.amperageMeterValues[i] : 0,
+ 'amperageL1': checkNewMeterValues ? this.amperageL1MeterValues[i] : 0,
+ 'amperageL2': checkNewMeterValues ? this.amperageL2MeterValues[i] : 0,
+ 'amperageL3': checkNewMeterValues ? this.amperageL3MeterValues[i] : 0,
'instantWatts': this.powerImportMeterValues[i],
'instantAmps': Utils.convertWattToAmp(this.chargingStationContext.getChargingStation(),
null, this.newTransaction.connectorId, this.powerImportMeterValues[i]),

MODIFY
test/api/context/ChargingStationContext.ts
test/api/context/ChargingStationContext.ts
@@ -16,6 +16,10 @@ interface MeterValueParams {
voltageL1MeterValue?: number;
voltageL2MeterValue?: number;
voltageL3MeterValue?: number;
+ amperageMeterValue?: number;
+ amperageL1MeterValue?: number;
+ amperageL2MeterValue?: number;
+ amperageL3MeterValue?: number;
socMeterValue?: number;
signedDataMeterValue?: string;
}
@@ -169,6 +173,34 @@ export default class ChargingStationContext {
...Constants.OCPP_VOLTAGE_L3_ATTRIBUTE,
});
}
+ // Amperage
+ if (meterValues.amperageMeterValue) {
+ meterValueRequest.meterValue[0].sampledValue.push({
+ value: meterValues.amperageMeterValue.toString(),
+ ...Constants.OCPP_CURRENT_ATTRIBUTE,
+ });
+ }
+ // Amperage L1
+ if (meterValues.amperageL1MeterValue) {
+ meterValueRequest.meterValue[0].sampledValue.push({
+ value: meterValues.amperageL1MeterValue.toString(),
+ ...Constants.OCPP_CURRENT_L1_ATTRIBUTE,
+ });
+ }
+ // Amperage L2
+ if (meterValues.amperageL2MeterValue) {
+ meterValueRequest.meterValue[0].sampledValue.push({
+ value: meterValues.amperageL2MeterValue.toString(),
+ ...Constants.OCPP_CURRENT_L2_ATTRIBUTE,
+ });
+ }
+ // Amperage L3
+ if (meterValues.amperageL3MeterValue) {
+ meterValueRequest.meterValue[0].sampledValue.push({
+ value: meterValues.amperageL3MeterValue.toString(),
+ ...Constants.OCPP_CURRENT_L3_ATTRIBUTE,
+ });
+ }
// Soc
if (meterValues.socMeterValue > 0) {
meterValueRequest.meterValue[0].sampledValue.push({
@@ -273,6 +305,38 @@ export default class ChargingStationContext {
context,
});
}
+ // Amperage
+ if (meterValues.amperageMeterValue > 0) {
+ meterValueRequest.meterValue[0].sampledValue.push({
+ value: meterValues.amperageMeterValue.toString(),
+ ...Constants.OCPP_CURRENT_ATTRIBUTE,
+ context,
+ });
+ }
+ // Amperage L1
+ if (meterValues.amperageL1MeterValue > 0) {
+ meterValueRequest.meterValue[0].sampledValue.push({
+ value: meterValues.amperageL1MeterValue.toString(),
+ ...Constants.OCPP_CURRENT_L1_ATTRIBUTE,
+ context,
+ });
+ }
+ // Amperage L2
+ if (meterValues.amperageL2MeterValue > 0) {
+ meterValueRequest.meterValue[0].sampledValue.push({
+ value: meterValues.amperageL2MeterValue.toString(),
+ ...Constants.OCPP_CURRENT_L2_ATTRIBUTE,
+ context,
+ });
+ }
+ // Amperage L3
+ if (meterValues.amperageL3MeterValue > 0) {
+ meterValueRequest.meterValue[0].sampledValue.push({
+ value: meterValues.amperageL3MeterValue.toString(),
+ ...Constants.OCPP_CURRENT_L3_ATTRIBUTE,
+ context,
+ });
+ }
// Signed Data
if (meterValues.signedDataMeterValue) {
meterValueRequest.meterValue[0].sampledValue.push({

Added handling of current meter values