Check for cp + unit test preperation
MODIFY
src/server/ocpp/utils/OCPPUtils.ts
src/server/ocpp/utils/OCPPUtils.ts
@@ -626,6 +626,10 @@ export default class OCPPUtils {
userID: transaction.userID,
endedAt: Utils.convertToDate(meterValue.timestamp),
} as Consumption;
+ // Handle current Connector limitation
+ await OCPPUtils.addConnectorLimitationToConsumption(tenantID, chargingStation, transaction.connectorId, consumption);
+ // Handle current Site Area limitation
+ await OCPPUtils.addSiteLimitationToConsumption(tenantID, chargingStation.siteArea, consumption);
// Handle SoC (%)
if (OCPPUtils.isSocMeterValue(meterValue)) {
consumption.stateOfCharge = Utils.convertToFloat(meterValue.value);
@@ -729,20 +733,19 @@ export default class OCPPUtils {
} else {
consumption.consumptionWh = 0;
consumption.consumptionAmps = 0;
+ // Check if charging plan is ongoing
+ if (consumption.limitSource != ConnectorCurrentLimitSource.CHARGING_PROFILE || consumption.limitAmps > 13 * chargingStation.chargePoints[chargingStation.connectors[transaction.connectorId - 1].connectorId - 1].numberOfConnectedPhase) {
// Update inactivity
transaction.currentTotalInactivitySecs += diffSecs;
consumption.totalInactivitySecs = transaction.currentTotalInactivitySecs;
}
+ }
consumption.cumulatedConsumptionWh = transaction.currentTotalConsumptionWh;
consumption.cumulatedConsumptionAmps = Utils.convertWattToAmp(chargingStation, null, transaction.connectorId, transaction.currentTotalConsumptionWh);
consumption.totalDurationSecs = !transaction.stop ?
moment.duration(moment(meterValue.timestamp).diff(moment(transaction.timestamp))).asSeconds() :
moment.duration(moment(transaction.stop.timestamp).diff(moment(transaction.timestamp))).asSeconds();
consumption.toPrice = true;
- // Handle current Connector limitation
- await OCPPUtils.addConnectorLimitationToConsumption(tenantID, chargingStation, transaction.connectorId, consumption);
- // Handle current Site Area limitation
- await OCPPUtils.addSiteLimitationToConsumption(tenantID, chargingStation.siteArea, consumption);
// Keep last one
transaction.lastConsumption = {
value: Utils.convertToFloat(meterValue.value),

MODIFY
test/api/OCPPAllVersionsTest.ts
test/api/OCPPAllVersionsTest.ts
+import ChargingProfileFactory from '../factories/ChargingProfileFactory';
import ChargingStationContext from './context/ChargingStationContext';
+import ChargingStationStorage from '../storage/mongodb/ChargingStationStorage';
import ContextDefinition from './context/ContextDefinition';
import ContextProvider from './context/ContextProvider';
import OCPPCommonTests from './OCPPCommonTests';
@@ -1099,6 +1101,38 @@ describe('OCPP tests (all versions)', function() {
it('Start user should not be able to delete his transaction (with SignedData)', async () => {
await testData.ocppCommonTests.testDeleteTransaction(true);
});
+ });
+
+ describe('Users should be able to perform a complete transaction with ongoing charging profile', () => {
+
+ before(async () => {
+ const chargingProfile = ChargingProfileFactory.build();
+ await ChargingStationStorage.saveChargingProfile(testData.tenantContext.getTenant().id, chargingProfile);
+ });
+
+ after(async () => {
+ await testData.chargingStationContext.cleanUpCreatedData();
+ });
+
+ it('Start user should be able to start a new transaction (with charging profile)', async () => {
+ await testData.ocppCommonTests.testStartTransaction();
+ });
+
+ it('Charging station should send meter values (with charging profile)', async () => {
+ await testData.ocppCommonTests.testSendMeterValues(false, true);
+ });
+
+ it('Stop user should be able to stop the transaction (with charging profile)', async () => {
+ await testData.ocppCommonTests.testStopTransaction();
+ });
+
+ it('Transaction must have the right consumption metrics, pricing and inactivity (with charging profile)', async () => {
+ await testData.ocppCommonTests.testTransactionMetrics(false, true, true);
+ });
+
+ it('Start user should not be able to delete his transaction (with charging profile)', async () => {
+ await testData.ocppCommonTests.testDeleteTransaction(true);
+ });
});

MODIFY
test/api/OCPPCommonTests.ts
test/api/OCPPCommonTests.ts
@@ -4,6 +4,7 @@ import chai, { expect } from 'chai';
import CentralServerService from './client/CentralServerService';
import ChargingStationContext from './context/ChargingStationContext';
+import ChargingStationStorage from '../storage/mongodb/ChargingStationStorage';
import Constants from '../../src/utils/Constants';
import Factory from '../factories/Factory';
import { OCPPStatus } from '../../src/types/ocpp/OCPPClient';
@@ -605,7 +606,7 @@ export default class OCPPCommonTests {
});
}
- public async testTransactionMetrics(withSoC = false, withSignedData = false, checkNewMeterValues = false) {
+ public async testTransactionMetrics(withSoC = false, withSignedData = false, checkNewMeterValues = false, withChargingProfile = false) {
// Check on Transaction
expect(this.newTransaction).to.not.be.null;
const response = await this.centralUserService.transactionApi.readAllConsumption({ TransactionId: this.newTransaction.id });
@@ -1077,6 +1078,10 @@ export default class OCPPCommonTests {
return createdUser;
}
+ private async createChargingProfile(chargingProfile = Factory.chargingProfile.build()) {
+ ChargingStationStorage.saveChargingProfile(this.tenantContext.getTenant().id, chargingProfile);
+ }
+
private async testAuthorize(tagId, expectedStatus) {
const response = await this.chargingStationContext.authorize(tagId);
// Check

ADD
test/factories/ChargingProfileFactory.ts
+import { Factory } from 'rosie';
+import { attempt } from 'bluebird';
+import faker from 'faker';
+
+
+const chargingScheduleFactory = Factory.define('chargingSchedule')
+ .attr('chargingRateUnit', () => 'A')
+ .attr('startSchedule', () => new Date)
+ .attr('duration', () => 2700)
+ .attr('chargingSchedulePeriod', () => [
+ {
+ startPeriod: 0,
+ limit: 96
+ },
+ {
+ startPeriod: 900,
+ limit: 96
+ },
+ {
+ startPeriod: 1800,
+ limit: 96
+ }
+ ]);
+
+const profileFactory = Factory.define('profile')
+ .attr('chargingProfileId', () => 1)
+ .attr('chargingProfileKind', () => 'Absolute')
+ .attr('chargingProfilePurpose', () => 'TxProfile')
+ .attr('transactionId', () => '')
+ .attr('stackLevel', () => 2)
+ .attr('chargingSchedule', () => chargingScheduleFactory.build());
+
+export default Factory.define('chargingProfile')
+ .attr('chargePointID', () => 1)
+ .attr('chargingStationID', () => faker.random.alphaNumeric(25))
+ .attr('connectorID', () => 1)
+ .attr('profile', () => profileFactory.build());

MODIFY
test/factories/Factory.ts
test/factories/Factory.ts
import AddressFactory from './AddressFactory';
import AssetFactory from './AssetFactory';
import CarFactory from './CarFactory';
+import ChargingProfileFactory from './ChargingProfileFactory';
import ChargingStationFactory from './ChargingStationFactory';
import CompanyFactory from './CompanyFactory';
import OcpiEndpointsFactory from './OcpiEndpointsFactory';
@@ -16,6 +17,7 @@ export default abstract class Factory {
public static asset = AssetFactory;
public static user = UserFactory;
public static chargingStation = ChargingStationFactory;
+ public static chargingProfile = ChargingProfileFactory;
public static address = AddressFactory;
public static siteArea = SiteAreaFactory;
public static tenant = TenantFactory;

Check for cp + unit test preperation