+ { errorResponse: OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_REJECTED },
+ )!;
+ }
+ }
+
+ private async handleRequestReserveNow(
+ chargingStation: ChargingStation,
+ commandPayload: OCPP16ReserveNowRequest,
+ ): Promise<OCPP16ReserveNowResponse> {
+ if (
+ !OCPP16ServiceUtils.checkFeatureProfile(
+ chargingStation,
+ OCPP16SupportedFeatureProfiles.Reservation,
+ OCPP16IncomingRequestCommand.RESERVE_NOW,
+ )
+ ) {
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED;
+ }
+ const { reservationId, idTag, connectorId } = commandPayload;
+ let response: OCPP16ReserveNowResponse;
+ try {
+ if (connectorId > 0 && !chargingStation.isConnectorAvailable(connectorId)) {
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED;
+ }
+ if (connectorId === 0 && !chargingStation.getReserveConnectorZeroSupported()) {
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED;
+ }
+ if (!(await OCPP16ServiceUtils.isIdTagAuthorized(chargingStation, connectorId, idTag))) {
+ return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED;
+ }
+ await removeExpiredReservations(chargingStation);
+ switch (chargingStation.getConnectorStatus(connectorId)!.status) {
+ case OCPP16ChargePointStatus.Faulted:
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED;
+ break;
+ case OCPP16ChargePointStatus.Preparing:
+ case OCPP16ChargePointStatus.Charging:
+ case OCPP16ChargePointStatus.SuspendedEV:
+ case OCPP16ChargePointStatus.SuspendedEVSE:
+ case OCPP16ChargePointStatus.Finishing:
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED;
+ break;
+ case OCPP16ChargePointStatus.Unavailable:
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_UNAVAILABLE;
+ break;
+ case OCPP16ChargePointStatus.Reserved:
+ if (!chargingStation.isConnectorReservable(reservationId, idTag, connectorId)) {
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED;
+ break;
+ }
+ // eslint-disable-next-line no-fallthrough
+ default:
+ if (!chargingStation.isConnectorReservable(reservationId, idTag)) {
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_OCCUPIED;
+ break;
+ }
+ await chargingStation.addReservation({
+ id: commandPayload.reservationId,
+ ...commandPayload,
+ });
+ response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_ACCEPTED;
+ break;
+ }
+ return response;
+ } catch (error) {
+ chargingStation.getConnectorStatus(connectorId)!.status = OCPP16ChargePointStatus.Available;
+ return this.handleIncomingRequestError<OCPP16ReserveNowResponse>(
+ chargingStation,
+ OCPP16IncomingRequestCommand.RESERVE_NOW,
+ error as Error,
+ { errorResponse: OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED },
+ )!;
+ }
+ }
+
+ private async handleRequestCancelReservation(
+ chargingStation: ChargingStation,
+ commandPayload: OCPP16CancelReservationRequest,
+ ): Promise<GenericResponse> {
+ if (
+ !OCPP16ServiceUtils.checkFeatureProfile(
+ chargingStation,
+ OCPP16SupportedFeatureProfiles.Reservation,
+ OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
+ )
+ ) {
+ return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED;
+ }
+ try {
+ const { reservationId } = commandPayload;
+ const reservation = chargingStation.getReservationBy('reservationId', reservationId);
+ if (isUndefined(reservation)) {
+ logger.debug(
+ `${chargingStation.logPrefix()} Reservation with id ${reservationId} does not exist on charging station`,
+ );
+ return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED;
+ }
+ await chargingStation.removeReservation(
+ reservation!,
+ ReservationTerminationReason.RESERVATION_CANCELED,