+ !cpReplaced && chargingStation.getConnectorStatus(connectorId)?.chargingProfiles?.push(cp);
+ }
+
+ public static clearChargingProfiles = (
+ chargingStation: ChargingStation,
+ commandPayload: ClearChargingProfileRequest,
+ chargingProfiles: OCPP16ChargingProfile[] | undefined,
+ ): boolean => {
+ const { id, chargingProfilePurpose, stackLevel } = commandPayload;
+ let clearedCP = false;
+ if (isNotEmptyArray(chargingProfiles)) {
+ chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
+ let clearCurrentCP = false;
+ if (chargingProfile.chargingProfileId === id) {
+ clearCurrentCP = true;
+ }
+ if (!chargingProfilePurpose && chargingProfile.stackLevel === stackLevel) {
+ clearCurrentCP = true;
+ }
+ if (!stackLevel && chargingProfile.chargingProfilePurpose === chargingProfilePurpose) {
+ clearCurrentCP = true;
+ }
+ if (
+ chargingProfile.stackLevel === stackLevel &&
+ chargingProfile.chargingProfilePurpose === chargingProfilePurpose
+ ) {
+ clearCurrentCP = true;
+ }
+ if (clearCurrentCP) {
+ chargingProfiles.splice(index, 1);
+ logger.debug(
+ `${chargingStation.logPrefix()} Matching charging profile(s) cleared: %j`,
+ chargingProfile,
+ );
+ clearedCP = true;
+ }
+ });
+ }
+ return clearedCP;
+ };
+
+ public static composeChargingSchedules = (
+ chargingSchedule1: OCPP16ChargingSchedule | undefined,
+ chargingSchedule2: OCPP16ChargingSchedule | undefined,
+ targetInterval: Interval,
+ ): OCPP16ChargingSchedule | undefined => {
+ if (!chargingSchedule1 && !chargingSchedule2) {
+ return undefined;
+ }
+ if (chargingSchedule1 && !chargingSchedule2) {
+ return OCPP16ServiceUtils.composeChargingSchedule(chargingSchedule1, targetInterval);
+ }
+ if (!chargingSchedule1 && chargingSchedule2) {
+ return OCPP16ServiceUtils.composeChargingSchedule(chargingSchedule2, targetInterval);
+ }
+ const compositeChargingSchedule1: OCPP16ChargingSchedule | undefined =
+ OCPP16ServiceUtils.composeChargingSchedule(chargingSchedule1!, targetInterval);
+ const compositeChargingSchedule2: OCPP16ChargingSchedule | undefined =
+ OCPP16ServiceUtils.composeChargingSchedule(chargingSchedule2!, targetInterval);
+ const compositeChargingScheduleInterval1: Interval = {
+ start: compositeChargingSchedule1!.startSchedule!,
+ end: addSeconds(
+ compositeChargingSchedule1!.startSchedule!,
+ compositeChargingSchedule1!.duration!,
+ ),
+ };
+ const compositeChargingScheduleInterval2: Interval = {
+ start: compositeChargingSchedule2!.startSchedule!,
+ end: addSeconds(
+ compositeChargingSchedule2!.startSchedule!,
+ compositeChargingSchedule2!.duration!,
+ ),
+ };
+ if (
+ !areIntervalsOverlapping(
+ compositeChargingScheduleInterval1,
+ compositeChargingScheduleInterval2,
+ )
+ ) {
+ return {
+ ...OCPP16ServiceUtils.composeChargingSchedule(chargingSchedule1!, targetInterval)!,
+ ...OCPP16ServiceUtils.composeChargingSchedule(chargingSchedule2!, targetInterval)!,
+ };
+ }
+ // FIXME: Handle overlapping intervals
+ };
+
+ public static hasReservation = (
+ chargingStation: ChargingStation,
+ connectorId: number,
+ idTag: string,
+ ): boolean => {
+ const connectorReservation = chargingStation.getReservationBy('connectorId', connectorId);
+ const chargingStationReservation = chargingStation.getReservationBy('connectorId', 0);
+ if (
+ (chargingStation.getConnectorStatus(connectorId)?.status ===
+ OCPP16ChargePointStatus.Reserved &&
+ connectorReservation &&
+ !hasReservationExpired(connectorReservation) &&
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ connectorReservation?.idTag === idTag) ||
+ (chargingStation.getConnectorStatus(0)?.status === OCPP16ChargePointStatus.Reserved &&
+ chargingStationReservation &&
+ !hasReservationExpired(chargingStationReservation) &&
+ chargingStationReservation?.idTag === idTag)
+ ) {
+ logger.debug(
+ `${chargingStation.logPrefix()} Connector id ${connectorId} has a valid reservation for idTag ${idTag}: %j`,
+ connectorReservation ?? chargingStationReservation,
+ );
+ return true;
+ }
+ return false;
+ };
+
+ public static parseJsonSchemaFile<T extends JsonType>(
+ relativePath: string,
+ moduleName?: string,
+ methodName?: string,
+ ): JSONSchemaType<T> {
+ return super.parseJsonSchemaFile<T>(
+ relativePath,
+ OCPPVersion.VERSION_16,
+ moduleName,
+ methodName,
+ );