From: Jérôme Benoit Date: Wed, 2 Aug 2023 18:16:55 +0000 (+0200) Subject: fix: avoid gaps in get composite schedule X-Git-Tag: v1.2.20~36 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;ds=sidebyside;h=da332e702310d2a717d759040727e4e2a3f3fe87;p=e-mobility-charging-stations-simulator.git fix: avoid gaps in get composite schedule Signed-off-by: Jérôme Benoit --- diff --git a/src/charging-station/Helpers.ts b/src/charging-station/Helpers.ts index 63cc0f63..b7229262 100644 --- a/src/charging-station/Helpers.ts +++ b/src/charging-station/Helpers.ts @@ -16,6 +16,7 @@ import { isDate, isPast, isWithinInterval, + maxTime, toDate, } from 'date-fns'; @@ -753,13 +754,23 @@ const getLimitFromChargingProfiles = ( const connectorStatus = chargingStation.getConnectorStatus(connectorId)!; for (const chargingProfile of chargingProfiles) { const chargingSchedule = chargingProfile.chargingSchedule; - if (connectorStatus?.transactionStarted && isNullOrUndefined(chargingSchedule?.startSchedule)) { + if (isNullOrUndefined(chargingSchedule?.startSchedule) && connectorStatus?.transactionStarted) { logger.debug( `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} has no startSchedule defined. Trying to set it to the connector current transaction start date`, ); // OCPP specifies that if startSchedule is not defined, it should be relative to start of the connector transaction chargingSchedule.startSchedule = connectorStatus?.transactionStart; } + if ( + !isNullOrUndefined(chargingSchedule?.startSchedule) && + isNullOrUndefined(chargingSchedule?.duration) + ) { + logger.debug( + `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} has no duration defined and will be set to the maximum time allowed`, + ); + // OCPP specifies that if duration is not defined, it should be infinite + chargingSchedule.duration = differenceInSeconds(maxTime, chargingSchedule.startSchedule!); + } if (!isDate(chargingSchedule?.startSchedule)) { logger.warn( `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} startSchedule property is not a Date object. Trying to convert it to a Date object`, @@ -796,7 +807,7 @@ const getLimitFromChargingProfiles = ( ); chargingSchedule.chargingSchedulePeriod.sort(chargingSchedulePeriodCompareFn); } - // Check if the first schedule period start period is equal to 0 + // Check if the first schedule period startPeriod property is equal to 0 if (chargingSchedule.chargingSchedulePeriod[0].startPeriod !== 0) { logger.error( `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${chargingProfile.chargingProfileId} first schedule period start period ${chargingSchedule.chargingSchedulePeriod[0].startPeriod} is not equal to 0`, @@ -910,12 +921,6 @@ export const canProceedChargingProfile = ( ); return false; } - if (isNullOrUndefined(chargingSchedule?.duration)) { - logger.error( - `${logPrefix} ${moduleName}.canProceedChargingProfile: Charging profile id ${chargingProfile.chargingProfileId} has no duration defined, not yet supported`, - ); - return false; - } return true; }; diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 66a6ee59..d24a2d4c 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -712,8 +712,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const chargingProfiles: OCPP16ChargingProfile[] = []; for (const storedChargingProfile of storedChargingProfiles) { if ( - connectorStatus?.transactionStarted && - isNullOrUndefined(storedChargingProfile.chargingSchedule?.startSchedule) + isNullOrUndefined(storedChargingProfile.chargingSchedule?.startSchedule) && + connectorStatus?.transactionStarted ) { logger.debug( `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${ @@ -723,6 +723,21 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { // OCPP specifies that if startSchedule is not defined, it should be relative to start of the connector transaction storedChargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart; } + if ( + !isNullOrUndefined(storedChargingProfile.chargingSchedule?.startSchedule) && + isNullOrUndefined(storedChargingProfile.chargingSchedule?.duration) + ) { + logger.debug( + `${chargingStation.logPrefix()} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${ + storedChargingProfile.chargingProfileId + } has no duration defined and will be set to the maximum time allowed`, + ); + // OCPP specifies that if duration is not defined, it should be infinite + storedChargingProfile.chargingSchedule.duration = differenceInSeconds( + maxTime, + storedChargingProfile.chargingSchedule.startSchedule!, + ); + } if (!isDate(storedChargingProfile.chargingSchedule?.startSchedule)) { logger.warn( `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${ @@ -837,20 +852,52 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ) ) { // Remove charging schedule periods that are before the end of the active profiles interval - // FIXME: can lead to a gap in the charging schedule: chargingProfilesInterval.end -> first matching schedulePeriod.startPeriod storedChargingProfile.chargingSchedule.chargingSchedulePeriod = storedChargingProfile.chargingSchedule.chargingSchedulePeriod.filter( - (schedulePeriod) => - isWithinInterval( - addSeconds( - storedChargingProfile.chargingSchedule.startSchedule!, - schedulePeriod.startPeriod, - ), - { - start: chargingProfilesInterval.end, - end: interval.end, - }, - ), + (schedulePeriod, index) => { + if ( + isWithinInterval( + addSeconds( + storedChargingProfile.chargingSchedule.startSchedule!, + schedulePeriod.startPeriod, + ), + { + start: chargingProfilesInterval.end, + end: interval.end, + }, + ) + ) { + return true; + } + if ( + !isWithinInterval( + addSeconds( + storedChargingProfile.chargingSchedule.startSchedule!, + schedulePeriod.startPeriod, + ), + { + start: chargingProfilesInterval.end, + end: interval.end, + }, + ) && + index < + storedChargingProfile.chargingSchedule.chargingSchedulePeriod.length - 1 && + isWithinInterval( + addSeconds( + storedChargingProfile.chargingSchedule.startSchedule!, + storedChargingProfile.chargingSchedule.chargingSchedulePeriod[index + 1] + .startPeriod, + ), + { + start: chargingProfilesInterval.end, + end: interval.end, + }, + ) + ) { + return true; + } + return false; + }, ); addChargingProfile = true; }