Do not exclude cs permanetly when smart charging fails
MODIFY
src/assets/server/notification/email/en_US/compute-and-apply-charging-profiles-failed.json
src/assets/server/notification/email/en_US/compute-and-apply-charging-profiles-failed.json
"",
"Applying the charging profiles for <strong>'<%- chargeBoxID %>'</strong> failed three times.",
"",
- "The charging station was excluded from smart charging management automatically."
+ "The charging station was excluded from this smart charging run automatically."
],
"action": {
"title": "e-Mobility",

MODIFY
src/integration/smart-charging/SmartChargingIntegration.ts
src/integration/smart-charging/SmartChargingIntegration.ts
import { ActionsResponse } from '../../types/GlobalType';
import BackendError from '../../exception/BackendError';
import { ChargingProfile } from '../../types/ChargingProfile';
+import ChargingStation from '../../types/ChargingStation';
import ChargingStationStorage from '../../storage/mongodb/ChargingStationStorage';
import Constants from '../../utils/Constants';
import Logging from '../../utils/Logging';
@@ -16,6 +17,7 @@ const MODULE_NAME = 'SmartChargingIntegration';
export default abstract class SmartChargingIntegration<T extends SmartChargingSetting> {
protected readonly tenantID: string;
protected readonly setting: T;
+ private excludedChargingStations: ChargingStation[] = [];
protected constructor(tenantID: string, setting: T) {
this.tenantID = tenantID;
@@ -57,7 +59,7 @@ export default abstract class SmartChargingIntegration<T extends SmartChargingSe
source: chargingProfile.chargingStationID,
action: ServerAction.CHARGING_PROFILE_UPDATE,
module: MODULE_NAME, method: 'computeAndApplyChargingProfiles',
- message: `Setting Charging Profiles for Site Area '${siteArea.name}' failed, because of '${chargingProfile.chargingStationID}'. It has been excluded from smart charging automatically`,
+ message: `Setting Charging Profiles for Site Area '${siteArea.name}' failed, because of '${chargingProfile.chargingStationID}'. It has been excluded from this smart charging run automatically`,
detailedMessages: { error: error.message, stack: error.stack }
});
}
@@ -72,6 +74,11 @@ export default abstract class SmartChargingIntegration<T extends SmartChargingSe
);
if (actionsResponse.inError > 0 && retry === false) {
await this.computeAndApplyChargingProfiles(siteArea, retry = true);
+ // Including the excluded Charging Stations for the next smart charging run again
+ for (const chargingStation of this.excludedChargingStations) {
+ chargingStation.excludeFromSmartCharging = false;
+ await ChargingStationStorage.saveChargingStation(this.tenantID, chargingStation);
+ }
}
return actionsResponse;
}
@@ -135,8 +142,10 @@ export default abstract class SmartChargingIntegration<T extends SmartChargingSe
const chargingStation = await ChargingStationStorage.getChargingStation(tenantID, chargingProfile.chargingStationID);
chargingStation.excludeFromSmartCharging = true;
await ChargingStationStorage.saveChargingStation(tenantID, chargingStation);
+ // Remember Charging Stations which were removed from Smart Charging
+ this.excludedChargingStations.push(chargingStation);
// Notify Admins
- await NotificationHandler.sendComputeAndApplyChargingProfilesFailed(tenantID,
+ await NotificationHandler.sendComputeAndApplyChargingProfilesFailed(tenantID, chargingStation,
{ chargeBoxID: chargingProfile.chargingStationID,
siteAreaName: siteAreaName,
evseDashboardURL: Utils.buildEvseURL()

MODIFY
src/notification/NotificationHandler.ts
src/notification/NotificationHandler.ts
@@ -823,7 +823,7 @@ export default class NotificationHandler {
}
}
- static async sendComputeAndApplyChargingProfilesFailed(tenantID: string, sourceData: ComputeAndApplyChargingProfilesFailedNotification): Promise<void> {
+ static async sendComputeAndApplyChargingProfilesFailed(tenantID: string, chargingStation: ChargingStation, sourceData: ComputeAndApplyChargingProfilesFailedNotification): Promise<void> {
if (tenantID !== Constants.DEFAULT_TENANT) {
// Get the Tenant
const tenant = await TenantStorage.getTenant(tenantID);
@@ -835,9 +835,15 @@ export default class NotificationHandler {
// Active?
if (notificationSource.enabled) {
try {
+ // Check notification
+ const hasBeenNotified = await NotificationHandler.hasNotifiedSource(
+ tenantID, notificationSource.channel, ServerAction.COMPUTE_AND_APPLY_CHARGING_PROFILES_FAILED,
+ sourceData.chargeBoxID, null, { intervalMins: 60 * 24 });
+ // Notified?
+ if (!hasBeenNotified) {
// Save
await NotificationHandler.saveNotification(
- tenantID, notificationSource.channel, null, ServerAction.CHECK_AND_APPLY_SMART_CHARGING_FAILED);
+ tenantID, notificationSource.channel, null, ServerAction.COMPUTE_AND_APPLY_CHARGING_PROFILES_FAILED, { chargingStation: chargingStation });
// Send
for (const adminUser of adminUsers) {
// Enabled?
@@ -846,8 +852,10 @@ export default class NotificationHandler {
sourceData, adminUser, tenant, NotificationSeverity.ERROR);
}
}
+ }
+
} catch (error) {
- Logging.logActionExceptionMessage(tenantID, ServerAction.CHECK_AND_APPLY_SMART_CHARGING_FAILED, error);
+ Logging.logActionExceptionMessage(tenantID, ServerAction.COMPUTE_AND_APPLY_CHARGING_PROFILES_FAILED, error);
}
}
}

MODIFY
src/types/Server.ts
src/types/Server.ts
@@ -371,7 +371,7 @@ export enum ServerAction {
MONGO_DB = 'MongoDB',
CHECK_AND_APPLY_SMART_CHARGING = 'CheckAndApplySmartCharging',
- CHECK_AND_APPLY_SMART_CHARGING_FAILED = 'ComputeAndApplyChargingProfilesFailed',
+ COMPUTE_AND_APPLY_CHARGING_PROFILES_FAILED = 'ComputeAndApplyChargingProfilesFailed',
SMART_CHARGING = 'SmartCharging',
INSTANTIATE_DUMMY_MODULE = 'InstantiateDummyModule',

MODIFY
test/api/SmartChargingTest.ts
test/api/SmartChargingTest.ts
@@ -535,7 +535,7 @@ describe('Smart Charging Service', function() {
});
- it('Check if charging station will be excluded from smart charging, when pushing fails', async () => {
+ it('Check if charging station will be included again, when pushing the charging profiles fails', async () => {
testData.siteAreaContext.getSiteArea().maximumPower = 200000;
testData.siteAreaContext.getSiteArea().smartCharging = true;
await testData.userService.siteAreaApi.update(testData.siteAreaContext.getSiteArea());
@@ -545,7 +545,7 @@ describe('Smart Charging Service', function() {
const chargingStationResponse = await testData.userService.chargingStationApi.readById(testData.chargingStationContext.getChargingStation().id);
expect(chargingStationResponse.status).to.be.eq(200);
const chargingStation = chargingStationResponse.data;
- expect(chargingStation.excludeFromSmartCharging).to.be.eq(true);
+ expect(chargingStation.excludeFromSmartCharging).to.be.eq(false);
});
});
});

Do not exclude cs permanetly when smart charging fails