Improved car conenctor performance + cleaned up code
MODIFY
src/integration/car-connector/CarConnectorFactory.ts
src/integration/car-connector/CarConnectorFactory.ts
import { CarConnectorConnectionType, CarConnectorSetting } from '../../types/Setting';
+import { Car } from '../../types/Car';
import CarConnectorIntegration from './CarConnectorIntegration';
import MercedesCarConnectorIntegration from './mercedes-connector/MercedesCarConnectorIntegration';
import SettingStorage from '../../storage/mongodb/SettingStorage';
@@ -8,13 +9,14 @@ import TenantComponents from '../../types/TenantComponents';
import Utils from '../../utils/Utils';
export default class CarConnectorFactory {
- static async getCarConnectorImpl(tenant: Tenant, connectorId: string): Promise<CarConnectorIntegration<CarConnectorSetting>> {
+ static async getCarConnectorImpl(tenant: Tenant, connectorId: string, car?: Car): Promise<CarConnectorIntegration<CarConnectorSetting>> {
// Check if car connector component is active
if (Utils.isTenantComponentActive(tenant, TenantComponents.CAR_CONNECTOR)) {
const settings = await SettingStorage.getCarConnectorSettings(tenant);
if (settings?.carConnector?.connections) {
// Find connection
- const foundConnection = settings.carConnector.connections.find((connection) => connection.type === connectorId);
+ // Vehicle make will be replaced with specific car information in the car object --> coming with Tronity
+ const foundConnection = settings.carConnector.connections.find((connection) => connection.type === connectorId ?? car.carCatalog.vehicleMake.toLowerCase());
if (foundConnection) {
let carConnectorIntegrationImpl: CarConnectorIntegration<CarConnectorSetting> = null;
switch (foundConnection.type) {

MODIFY
src/integration/car-connector/CarConnectorIntegration.ts
src/integration/car-connector/CarConnectorIntegration.ts
import { CarConnectorConnectionSetting, CarConnectorSetting } from '../../types/Setting';
+import { Car } from '../../types/Car';
import Connection from '../../types/Connection';
import Tenant from '../../types/Tenant';
@@ -16,5 +17,5 @@ export default abstract class CarConnectorIntegration<T extends CarConnectorSett
public abstract createConnection(userID: string, data: unknown): Promise<Connection>;
- public abstract getCurrentSoC(userID: string, vin: string): Promise<number>;
+ public abstract getCurrentSoC(userID: string, car: Car): Promise<number>;
}

MODIFY
src/integration/car-connector/mercedes-connector/MercedesCarConnectorIntegration.ts
src/integration/car-connector/mercedes-connector/MercedesCarConnectorIntegration.ts
@@ -4,6 +4,7 @@ import axiosRetry, { IAxiosRetryConfig } from 'axios-retry';
import AxiosFactory from '../../../utils/AxiosFactory';
import BackendError from '../../../exception/BackendError';
+import { Car } from '../../../types/Car';
import CarConnectorIntegration from '../CarConnectorIntegration';
import Connection from '../../../types/Connection';
import ConnectionStorage from '../../../storage/mongodb/ConnectionStorage';
@@ -137,9 +138,9 @@ export default class MercedesCarConnectorIntegration extends CarConnectorIntegra
}
}
- public async getCurrentSoC(userID: string, vin: string): Promise<number> {
+ public async getCurrentSoC(userID: string, car: Car): Promise<number> {
const connection = await this.getRefreshedConnection(userID);
- const request = `${this.connection.mercedesConnection.apiUrl}/vehicledata/v2/vehicles/${vin}/resources/soc`;
+ const request = `${this.connection.mercedesConnection.apiUrl}/vehicledata/v2/vehicles/${car.vin}/resources/soc`;
try {
// Get consumption
const response = await this.axiosInstance.get(
@@ -152,7 +153,7 @@ export default class MercedesCarConnectorIntegration extends CarConnectorIntegra
tenantID: this.tenant.id,
source: Constants.CENTRAL_SERVER,
action: ServerAction.CAR_CONNECTOR,
- message: `${vin} > Mercedes web service has been called successfully`,
+ message: `${car.vin} > Mercedes web service has been called successfully`,
module: MODULE_NAME, method: 'getCurrentSoC',
detailedMessages: { response: response.data }
});

MODIFY
src/server/ocpp/services/OCPPService.ts
src/server/ocpp/services/OCPPService.ts
@@ -15,6 +15,7 @@ import ChargingStationConfiguration from '../../../types/configuration/ChargingS
import ChargingStationStorage from '../../../storage/mongodb/ChargingStationStorage';
import Configuration from '../../../utils/Configuration';
import Constants from '../../../utils/Constants';
+import Consumption from '../../../types/Consumption';
import ConsumptionStorage from '../../../storage/mongodb/ConsumptionStorage';
import CpoOCPIClient from '../../../client/ocpi/CpoOCPIClient';
import CpoOICPClient from '../../../client/oicp/CpoOICPClient';
@@ -254,10 +255,7 @@ export default class OCPPService {
// Create Consumptions
const consumptions = await OCPPUtils.createConsumptionsFromMeterValues(tenant, chargingStation, transaction, normalizedMeterValues.values);
// Handle current SOC
- const currentStateOfCharge = await this.getCurrentSoC(tenant, transaction, chargingStation);
- if (!Utils.isNullOrUndefined(currentStateOfCharge)) {
- consumptions[consumptions.length - 1].stateOfCharge = currentStateOfCharge;
- }
+ await this.processTransactionSoC(tenant, transaction, chargingStation, consumptions[consumptions.length - 1], TransactionAction.UPDATE);
// Price/Bill Transaction and Save them
for (const consumption of consumptions) {
// Update Transaction with Consumption
@@ -463,10 +461,7 @@ export default class OCPPService {
// Roaming
await OCPPUtils.processTransactionRoaming(tenant, newTransaction, chargingStation, tag, TransactionAction.START);
// Handle current SOC
- const currentStateOfCharge = await this.getCurrentSoC(tenant, newTransaction, chargingStation);
- if (!Utils.isNullOrUndefined(currentStateOfCharge)) {
- newTransaction.stateOfCharge = currentStateOfCharge;
- }
+ await this.processTransactionSoC(tenant, newTransaction, chargingStation, null, TransactionAction.START);
// Save it
await TransactionStorage.saveTransaction(tenant, newTransaction);
// Clean up
@@ -1684,47 +1679,49 @@ export default class OCPPService {
transaction.carID = user.lastSelectedCarID;
} else {
// Get default car if any
- const defaultCar = await CarStorage.getDefaultUserCar(tenant, user.id, {}, ['id', 'carCatalogID']);
+ const defaultCar = await CarStorage.getDefaultUserCar(tenant, user.id, {}, ['id', 'carCatalogID', 'vin', 'carCatalog.vehicleMake']);
if (defaultCar) {
transaction.carID = defaultCar.id;
transaction.carCatalogID = defaultCar.carCatalogID;
+ transaction.car = defaultCar;
}
}
// Set Car Catalog ID
if (transaction.carID && !transaction.carCatalogID) {
- const car = await CarStorage.getCar(tenant, transaction.carID, {}, ['id', 'carCatalogID']);
+ const car = await CarStorage.getCar(tenant, transaction.carID, {}, ['id', 'carCatalogID', 'vin', 'carCatalog.vehicleMake']);
transaction.carCatalogID = car?.carCatalogID;
+ transaction.car = car;
}
// Clear
await UserStorage.saveUserLastSelectedCarID(tenant, user.id, null);
}
}
- private async getCurrentSoC(tenant: Tenant, transaction: Transaction, chargingStation: ChargingStation): Promise<number> {
- if (Utils.isTenantComponentActive(tenant, TenantComponents.CAR_CONNECTOR) && transaction.carID && transaction.carCatalogID &&
+ private async processTransactionSoC(tenant: Tenant, transaction: Transaction, chargingStation: ChargingStation, consumption: Consumption,
+ action: TransactionAction): Promise<void> {
+ if (Utils.isTenantComponentActive(tenant, TenantComponents.CAR_CONNECTOR) && !Utils.isNullOrUndefined(transaction.car) &&
Utils.getChargingStationCurrentType(chargingStation, null, transaction.connectorId) === CurrentType.AC) {
- const car = await CarStorage.getCar(tenant, transaction.carID, {}, ['vin', 'carCatalogID']);
- const carCatalog = await CarStorage.getCarCatalog(car.carCatalogID, {}, ['vehicleMake']);
- // TBD: Instead of using make --> change the identification of the car connector to specific connector data in the car object
- // Will be implemented with the Tronity integration
- if (!Utils.isNullOrUndefined(car) && !Utils.isNullOrUndefined(carCatalog)) {
- switch (carCatalog.vehicleMake) {
- case 'Mercedes': {
- const carImplementation = await CarConnectorFactory.getCarConnectorImpl(tenant, CarConnectorConnectionType.MERCEDES);
+ let currentStateOfCharge = null;
+ const carImplementation = await CarConnectorFactory.getCarConnectorImpl(tenant, null, transaction.car);
if (carImplementation) {
try {
- return await carImplementation.getCurrentSoC(transaction.userID, car.vin);
+ currentStateOfCharge = await carImplementation.getCurrentSoC(transaction.userID, transaction.car);
} catch {
- return null;
+ return;
}
}
+ if (!Utils.isNullOrUndefined(currentStateOfCharge)) {
+ switch (action) {
+ case TransactionAction.START:
+ transaction.stateOfCharge = currentStateOfCharge;
+ break;
+ case TransactionAction.UPDATE:
+ consumption.stateOfCharge = currentStateOfCharge;
break;
}
}
}
}
- return null;
- }
private addChargingStationToException(error: BackendError, chargingStationID: string): void {
if (error.params) {
@@ -2051,7 +2048,7 @@ export default class OCPPService {
detailedMessages: { headers, meterValues }
});
}
- const transaction = await TransactionStorage.getTransaction(tenant, meterValues.transactionId, { withUser: true, withTag: true });
+ const transaction = await TransactionStorage.getTransaction(tenant, meterValues.transactionId, { withUser: true, withTag: true, withCar: true });
if (!transaction) {
// Try a Remote Stop the Transaction
if (meterValues.transactionId) {

Improved car conenctor performance + cleaned up code