Free the Connector's runtime data of already stopped Transaction
MODIFY
src/server/ocpp/services/OCPPService.ts
src/server/ocpp/services/OCPPService.ts
@@ -444,7 +444,7 @@ export default class OCPPService {
// Save it
await TransactionStorage.saveTransaction(tenant.id, transaction);
// Clean up
- await this.clearChargingStationConnectorRuntimeData(tenant, transaction, chargingStation, user);
+ await this.updateChargingStationConnectorWithTransaction(tenant, transaction, chargingStation, user);
// Save
await ChargingStationStorage.saveChargingStation(tenant.id, chargingStation);
// Notify
@@ -545,7 +545,7 @@ export default class OCPPService {
const { user, alternateUser } = await this.checkAuthorizeStopTransactionAndGetUsers(
tenant, chargingStation, transaction, tagID, isStoppedByCentralSystem);
// Free the connector
- OCPPUtils.checkAndFreeChargingStationConnector(chargingStation, transaction.connectorId);
+ OCPPUtils.clearChargingStationConnector(chargingStation, transaction.connectorId);
// Save Charging Station
await ChargingStationStorage.saveChargingStation(tenant.id, chargingStation);
// Soft Stop
@@ -1202,7 +1202,7 @@ export default class OCPPService {
});
// Cleanup connector transaction data
} else if (foundConnector) {
- OCPPUtils.checkAndFreeChargingStationConnector(chargingStation, foundConnector.connectorId);
+ OCPPUtils.clearChargingStationConnector(chargingStation, foundConnector.connectorId);
}
}
@@ -1605,7 +1605,7 @@ export default class OCPPService {
}
}
- private async clearChargingStationConnectorRuntimeData(tenant: Tenant, transaction: Transaction, chargingStation: ChargingStation, user: User): Promise<void> {
+ private async updateChargingStationConnectorWithTransaction(tenant: Tenant, transaction: Transaction, chargingStation: ChargingStation, user: User): Promise<void> {
const foundConnector = Utils.getConnectorFromID(chargingStation, transaction.connectorId);
if (foundConnector) {
foundConnector.currentInstantWatts = 0;

MODIFY
src/server/ocpp/utils/OCPPUtils.ts
src/server/ocpp/utils/OCPPUtils.ts
@@ -1772,9 +1772,9 @@ export default class OCPPUtils {
return result;
}
- public static checkAndFreeChargingStationConnector(chargingStation: ChargingStation, connectorId: number): void {
+ public static clearChargingStationConnector(chargingStation: ChargingStation, connectorID: number): void {
// Cleanup connector transaction data
- const foundConnector = Utils.getConnectorFromID(chargingStation, connectorId);
+ const foundConnector = Utils.getConnectorFromID(chargingStation, connectorID);
if (foundConnector) {
foundConnector.currentInstantWatts = 0;
foundConnector.currentTotalConsumptionWh = 0;

MODIFY
src/server/rest/v1/service/ChargingStationService.ts
src/server/rest/v1/service/ChargingStationService.ts
@@ -832,7 +832,7 @@ export default class ChargingStationService {
user: req.user
});
} else {
- OCPPUtils.checkAndFreeChargingStationConnector(chargingStation, connector.connectorId);
+ OCPPUtils.clearChargingStationConnector(chargingStation, connector.connectorId);
}
}
}

MODIFY
src/server/rest/v1/service/TransactionService.ts
src/server/rest/v1/service/TransactionService.ts
@@ -18,6 +18,7 @@ import { DataResult } from '../../../../types/DataResult';
import LockingHelper from '../../../../locking/LockingHelper';
import LockingManager from '../../../../locking/LockingManager';
import Logging from '../../../../utils/Logging';
+import { OCPPAuthorizationStatus } from '../../../../types/ocpp/OCPPServer';
import OCPPService from '../../../../server/ocpp/services/OCPPService';
import OCPPUtils from '../../../ocpp/utils/OCPPUtils';
import RefundFactory from '../../../../integration/refund/RefundFactory';
@@ -478,6 +479,21 @@ export default class TransactionService {
const chargingStation = await ChargingStationStorage.getChargingStation(req.user.tenantID, transaction.chargeBoxID);
UtilsService.assertObjectExists(action, chargingStation, `Charging Station ID '${transaction.chargeBoxID}' does not exist`,
MODULE_NAME, 'handleTransactionSoftStop', req.user);
+ // Check if already stopped
+ if (transaction.stop) {
+ // Clear Connector
+ OCPPUtils.clearChargingStationConnector(chargingStation, transaction.connectorId);
+ // Save Connectors
+ await ChargingStationStorage.saveChargingStationConnectors(req.tenant.id, chargingStation.id, chargingStation.connectors);
+ await Logging.logSecurityInfo({
+ tenantID: req.user.tenantID,
+ source: chargingStation.id,
+ user: req.user, actionOnUser: transaction.userID,
+ module: MODULE_NAME, method: 'handleTransactionSoftStop',
+ message: `${OCPPUtils.buildConnectorInfo(transaction.connectorId, transaction.id)} Transaction has already been stopped and connector has been cleaned`,
+ action: action,
+ });
+ } else {
// Stop Transaction
const result = await new OCPPService(Configuration.getChargingStationConfig()).handleStopTransaction(
{
@@ -493,7 +509,15 @@ export default class TransactionService {
},
true
);
- // Log
+ if (result.idTagInfo?.status !== OCPPAuthorizationStatus.ACCEPTED) {
+ throw new AppError({
+ source: Constants.CENTRAL_SERVER,
+ errorCode: HTTPError.GENERAL_ERROR,
+ message: `${OCPPUtils.buildConnectorInfo(transaction.connectorId, transaction.id)} Transaction cannot be stopped`,
+ module: MODULE_NAME, method: 'handleTransactionSoftStop',
+ user: req.user, action: action
+ });
+ }
await Logging.logSecurityInfo({
tenantID: req.user.tenantID,
source: chargingStation.id,
@@ -503,8 +527,8 @@ export default class TransactionService {
action: action,
detailedMessages: { result }
});
- // Ok
- res.json(result);
+ }
+ res.json(Constants.REST_RESPONSE_SUCCESS);
next();
}
@@ -1027,7 +1051,7 @@ export default class TransactionService {
// Check connector
const foundConnector = Utils.getConnectorFromID(transaction.chargeBox, transaction.connectorId);
if (foundConnector && transaction.id === foundConnector.currentTransactionID) {
- OCPPUtils.checkAndFreeChargingStationConnector(transaction.chargeBox, transaction.connectorId);
+ OCPPUtils.clearChargingStationConnector(transaction.chargeBox, transaction.connectorId);
await ChargingStationStorage.saveChargingStationConnectors(loggedUser.tenantID, transaction.chargeBox.id, transaction.chargeBox.connectors);
}
// To Delete

MODIFY
src/storage/mongodb/ChargingStationStorage.ts
src/storage/mongodb/ChargingStationStorage.ts
@@ -636,27 +636,6 @@ export default class ChargingStationStorage {
await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingStationConnectors', uniqueTimerID, connectors);
}
- public static async saveChargingStationBackupConnectors(tenantID: string, id: string, backupConnectors: Connector[]): Promise<void> {
- // Debug
- const uniqueTimerID = Logging.traceStart(tenantID, MODULE_NAME, 'saveChargingStationBackupConnectors');
- // Check Tenant
- await DatabaseUtils.checkTenant(tenantID);
- // Ensure good typing
- const backupConnectorsMDB = backupConnectors.map((connector) =>
- ChargingStationStorage.filterConnectorMDB(connector));
- // Modify document
- await global.database.getCollection<any>(tenantID, 'chargingstations').findOneAndUpdate(
- { '_id': id },
- {
- $set: {
- backupConnectors: backupConnectorsMDB
- }
- },
- { upsert: true });
- // Debug
- await Logging.traceEnd(tenantID, MODULE_NAME, 'saveChargingStationBackupConnectors', uniqueTimerID, backupConnectors);
- }
-
public static async saveChargingStationCFApplicationIDAndInstanceIndex(tenantID: string, id: string,
cfApplicationIDAndInstanceIndex: string): Promise<void> {
// Debug

Free the Connector's runtime data of already stopped Transaction