+ return OCPP16Constants.OCPP_RESPONSE_REJECTED;
+ }
+ const currentDate = new Date();
+ const compositeScheduleInterval: Interval = {
+ start: currentDate,
+ end: addSeconds(currentDate, duration),
+ };
+ // Get charging profiles sorted by connector id then stack level
+ const chargingProfiles: OCPP16ChargingProfile[] = getConnectorChargingProfiles(
+ chargingStation,
+ connectorId,
+ );
+ let previousCompositeSchedule: OCPP16ChargingSchedule | undefined;
+ let compositeSchedule: OCPP16ChargingSchedule | undefined;
+ for (const chargingProfile of chargingProfiles) {
+ if (
+ isNullOrUndefined(chargingProfile.chargingSchedule?.startSchedule) &&
+ connectorStatus?.transactionStarted
+ ) {
+ logger.debug(
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: 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
+ chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart;
+ }
+ if (
+ !isNullOrUndefined(chargingProfile.chargingSchedule?.startSchedule) &&
+ !isDate(chargingProfile.chargingSchedule?.startSchedule)
+ ) {
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${
+ chargingProfile.chargingProfileId
+ } startSchedule property is not a Date instance. Trying to convert it to a Date instance`,
+ );
+ chargingProfile.chargingSchedule.startSchedule = convertToDate(
+ chargingProfile.chargingSchedule?.startSchedule,
+ )!;
+ }
+ if (
+ !isNullOrUndefined(chargingProfile.chargingSchedule?.startSchedule) &&
+ isNullOrUndefined(chargingProfile.chargingSchedule?.duration)
+ ) {
+ logger.debug(
+ `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: 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
+ chargingProfile.chargingSchedule.duration = differenceInSeconds(
+ maxTime,
+ chargingProfile.chargingSchedule.startSchedule!,
+ );
+ }
+ if (
+ !prepareChargingProfileKind(
+ connectorStatus,
+ chargingProfile,
+ compositeScheduleInterval.start as Date,
+ chargingStation.logPrefix(),
+ )
+ ) {
+ continue;
+ }
+ if (
+ !canProceedChargingProfile(
+ chargingProfile,
+ compositeScheduleInterval.start as Date,
+ chargingStation.logPrefix(),
+ )
+ ) {
+ continue;
+ }
+ compositeSchedule = OCPP16ServiceUtils.composeChargingSchedules(
+ previousCompositeSchedule,
+ chargingProfile.chargingSchedule,
+ compositeScheduleInterval,
+ );
+ previousCompositeSchedule = compositeSchedule;
+ }
+ if (compositeSchedule) {
+ return {
+ status: GenericStatus.Accepted,
+ scheduleStart: compositeSchedule.startSchedule!,
+ connectorId,
+ chargingSchedule: compositeSchedule,
+ };
+ }
+ return OCPP16Constants.OCPP_RESPONSE_REJECTED;
+ }
+
+ private handleRequestClearChargingProfile(
+ chargingStation: ChargingStation,
+ commandPayload: ClearChargingProfileRequest,
+ ): ClearChargingProfileResponse {
+ if (
+ OCPP16ServiceUtils.checkFeatureProfile(
+ chargingStation,
+ OCPP16SupportedFeatureProfiles.SmartCharging,
+ OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
+ ) === false
+ ) {
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
+ }
+ const { connectorId } = commandPayload;
+ if (chargingStation.hasConnector(connectorId!) === false) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to clear a charging profile(s) to a non existing connector id ${connectorId}`,
+ );
+ return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
+ }
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId!);
+ if (!isNullOrUndefined(connectorId) && isNotEmptyArray(connectorStatus?.chargingProfiles)) {
+ connectorStatus!.chargingProfiles = [];