+ logger.error(
+ `${chargingStation.logPrefix()} Unsupported protocol ${
+ uri.protocol
+ } to transfer the diagnostic logs archive`
+ )
+ await chargingStation.ocppRequestService.requestHandler<
+ OCPP16DiagnosticsStatusNotificationRequest,
+ OCPP16DiagnosticsStatusNotificationResponse
+ >(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
+ status: OCPP16DiagnosticsStatus.UploadFailed
+ })
+ return OCPP16Constants.OCPP_RESPONSE_EMPTY
+ }
+ }
+
+ private handleRequestTriggerMessage (
+ chargingStation: ChargingStation,
+ commandPayload: OCPP16TriggerMessageRequest
+ ): OCPP16TriggerMessageResponse {
+ const { requestedMessage, connectorId } = commandPayload
+ if (
+ !OCPP16ServiceUtils.checkFeatureProfile(
+ chargingStation,
+ OCPP16SupportedFeatureProfiles.RemoteTrigger,
+ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
+ ) ||
+ !OCPP16ServiceUtils.isMessageTriggerSupported(chargingStation, requestedMessage)
+ ) {
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED
+ }
+ if (
+ !OCPP16ServiceUtils.isConnectorIdValid(
+ chargingStation,
+ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ connectorId!
+ )
+ ) {
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED
+ }
+ try {
+ switch (requestedMessage) {
+ case OCPP16MessageTrigger.BootNotification:
+ setTimeout(() => {
+ chargingStation.ocppRequestService
+ .requestHandler<OCPP16BootNotificationRequest, OCPP16BootNotificationResponse>(
+ chargingStation,
+ OCPP16RequestCommand.BOOT_NOTIFICATION,
+ chargingStation.bootNotificationRequest,
+ { skipBufferingOnError: true, triggerMessage: true }
+ )
+ .then(response => {
+ chargingStation.bootNotificationResponse = response
+ })
+ .catch(Constants.EMPTY_FUNCTION)
+ }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY)
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
+ case OCPP16MessageTrigger.Heartbeat:
+ setTimeout(() => {
+ chargingStation.ocppRequestService
+ .requestHandler<OCPP16HeartbeatRequest, OCPP16HeartbeatResponse>(
+ chargingStation,
+ OCPP16RequestCommand.HEARTBEAT,
+ undefined,
+ {
+ triggerMessage: true
+ }
+ )
+ .catch(Constants.EMPTY_FUNCTION)
+ }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY)
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
+ case OCPP16MessageTrigger.StatusNotification:
+ setTimeout(() => {
+ if (connectorId != null) {
+ chargingStation.ocppRequestService
+ .requestHandler<OCPP16StatusNotificationRequest, OCPP16StatusNotificationResponse>(
+ chargingStation,
+ OCPP16RequestCommand.STATUS_NOTIFICATION,
+ {
+ connectorId,
+ errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
+ status: chargingStation.getConnectorStatus(connectorId)?.status
+ },
+ {
+ triggerMessage: true
+ }
+ )
+ .catch(Constants.EMPTY_FUNCTION)
+ } else if (chargingStation.hasEvses) {
+ for (const evseStatus of chargingStation.evses.values()) {
+ for (const [id, connectorStatus] of evseStatus.connectors) {
+ chargingStation.ocppRequestService
+ .requestHandler<
+ OCPP16StatusNotificationRequest,
+ OCPP16StatusNotificationResponse
+ >(
+ chargingStation,
+ OCPP16RequestCommand.STATUS_NOTIFICATION,
+ {
+ connectorId: id,
+ errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
+ status: connectorStatus.status
+ },
+ {
+ triggerMessage: true
+ }
+ )
+ .catch(Constants.EMPTY_FUNCTION)
+ }
+ }
+ } else {
+ for (const [id, connectorStatus] of chargingStation.connectors) {
+ chargingStation.ocppRequestService
+ .requestHandler<
+ OCPP16StatusNotificationRequest,
+ OCPP16StatusNotificationResponse
+ >(
+ chargingStation,
+ OCPP16RequestCommand.STATUS_NOTIFICATION,
+ {
+ connectorId: id,
+ errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
+ status: connectorStatus.status
+ },
+ {
+ triggerMessage: true
+ }
+ )
+ .catch(Constants.EMPTY_FUNCTION)
+ }
+ }
+ }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY)
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED
+ default:
+ return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED
+ }
+ } catch (error) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.handleIncomingRequestError<OCPP16TriggerMessageResponse>(
+ chargingStation,
+ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
+ error as Error,
+ { errorResponse: OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED }
+ )!
+ }
+ }
+
+ private handleRequestDataTransfer (
+ chargingStation: ChargingStation,
+ commandPayload: OCPP16DataTransferRequest
+ ): OCPP16DataTransferResponse {
+ const { vendorId } = commandPayload
+ try {
+ if (Object.values(OCPP16DataTransferVendorId).includes(vendorId)) {
+ return OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_ACCEPTED
+ }
+ return OCPP16Constants.OCPP_DATA_TRANSFER_RESPONSE_UNKNOWN_VENDOR_ID
+ } catch (error) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.handleIncomingRequestError<OCPP16DataTransferResponse>(
+ chargingStation,
+ OCPP16IncomingRequestCommand.DATA_TRANSFER,
+ error as Error,
+ { 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
+ }
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ commandPayload.expiryDate = convertToDate(commandPayload.expiryDate)!
+ 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) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ chargingStation.getConnectorStatus(connectorId)!.status = OCPP16ChargePointStatus.Available
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ 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 (reservation == null) {
+ 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
+ )
+ return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_ACCEPTED
+ } catch (error) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return this.handleIncomingRequestError<GenericResponse>(
+ chargingStation,
+ OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
+ error as Error,
+ { errorResponse: OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED }
+ )!