+ return isUndefined(foundReservation) ? [false, undefined] : [true, foundReservation];
+ }
+
+ public startReservationExpirationSetInterval(customInterval?: number): void {
+ const interval =
+ customInterval ?? Constants.DEFAULT_RESERVATION_EXPIRATION_OBSERVATION_INTERVAL;
+ if (interval > 0) {
+ logger.info(
+ `${this.logPrefix()} Reservation expiration date checks started every ${formatDurationMilliSeconds(
+ interval,
+ )}`,
+ );
+ this.reservationExpirationSetInterval = setInterval((): void => {
+ const currentDate = new Date();
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ for (const connectorStatus of evseStatus.connectors.values()) {
+ if (
+ connectorStatus.reservation &&
+ connectorStatus.reservation.expiryDate < currentDate
+ ) {
+ this.removeReservation(
+ connectorStatus.reservation,
+ ReservationTerminationReason.EXPIRED,
+ ).catch(Constants.EMPTY_FUNCTION);
+ }
+ }
+ }
+ } else {
+ for (const connectorStatus of this.connectors.values()) {
+ if (
+ connectorStatus.reservation &&
+ connectorStatus.reservation.expiryDate < currentDate
+ ) {
+ this.removeReservation(
+ connectorStatus.reservation,
+ ReservationTerminationReason.EXPIRED,
+ ).catch(Constants.EMPTY_FUNCTION);
+ }
+ }
+ }
+ }, interval);
+ }
+ }
+
+ public restartReservationExpiryDateSetInterval(): void {
+ this.stopReservationExpirationSetInterval();
+ this.startReservationExpirationSetInterval();
+ }
+
+ public validateIncomingRequestWithReservation(connectorId: number, idTag: string): boolean {
+ return this.getReservationBy(ReservationFilterKey.CONNECTOR_ID, connectorId)?.idTag === idTag;
+ }
+
+ public isConnectorReservable(
+ reservationId: number,
+ idTag?: string,
+ connectorId?: number,
+ ): boolean {
+ const [alreadyExists] = this.doesReservationExists({ id: reservationId });
+ if (alreadyExists) {
+ return alreadyExists;
+ }
+ const userReservedAlready = isUndefined(
+ this.getReservationBy(ReservationFilterKey.ID_TAG, idTag!),
+ )
+ ? false
+ : true;
+ const notConnectorZero = isUndefined(connectorId) ? true : connectorId! > 0;
+ const freeConnectorsAvailable = this.getNumberOfReservableConnectors() > 0;
+ return !alreadyExists && !userReservedAlready && notConnectorZero && freeConnectorsAvailable;
+ }
+
+ private getNumberOfReservableConnectors(): number {
+ let reservableConnectors = 0;
+ if (this.hasEvses) {
+ for (const evseStatus of this.evses.values()) {
+ reservableConnectors += countReservableConnectors(evseStatus.connectors);
+ }
+ } else {
+ reservableConnectors = countReservableConnectors(this.connectors);
+ }
+ return reservableConnectors - this.getNumberOfReservationsOnConnectorZero();
+ }
+
+ private getNumberOfReservationsOnConnectorZero(): number {
+ let numberOfReservations = 0;
+ if (
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ (this.hasEvses && this.evses.get(0)?.connectors.get(0)?.reservation) ||
+ (!this.hasEvses && this.connectors.get(0)?.reservation)
+ ) {
+ ++numberOfReservations;
+ }
+ return numberOfReservations;