package com.yablochkov.ocppstub; import eu.chargetime.ocpp.NotConnectedException; import eu.chargetime.ocpp.OccurenceConstraintException; import eu.chargetime.ocpp.UnsupportedFeatureException; import eu.chargetime.ocpp.model.Confirmation; import eu.chargetime.ocpp.model.core.AuthorizationStatus; import eu.chargetime.ocpp.model.core.IdTagInfo; import eu.chargetime.ocpp.model.core.RemoteStartStopStatus; import eu.chargetime.ocpp.model.core.RemoteStartTransactionConfirmation; import eu.chargetime.ocpp.model.core.RemoteStartTransactionRequest; import eu.chargetime.ocpp.model.core.RemoteStopTransactionConfirmation; import eu.chargetime.ocpp.model.core.RemoteStopTransactionRequest; import eu.chargetime.ocpp.model.core.StartTransactionConfirmation; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicInteger; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @Service @Slf4j public class TransactionService { private final AtomicInteger transactionNumber = new AtomicInteger(); private final Map transactionMap = new HashMap<>(); @Autowired private SessionService sessionService; @Autowired private AuthService authService; @Lazy @Autowired private OcppStub ocppStub; public StartTransactionConfirmation startByRequest(UUID sessionIndex, Integer connectorId, String idTag) { var identity = sessionService.getIdentityBySessionId(sessionIndex); log.info("Try to start transaction for {}, connector {}, tag {}", identity, connectorId, idTag); if(Objects.nonNull(identity)) { int transactionId = transactionNumber.incrementAndGet(); var oldTransactionId = transactionMap.put(identity, transactionId); if (Objects.nonNull(oldTransactionId)) { log.warn("Already have transaction {}, continue", oldTransactionId); } return new StartTransactionConfirmation(authService.authorize(idTag), transactionId); } log.error("Can't start transaction, identity not found"); return new StartTransactionConfirmation(new IdTagInfo(AuthorizationStatus.Invalid), null); } public void stopByRequest(UUID sessionIndex, Integer transactionId) { var identity = sessionService.getIdentityBySessionId(sessionIndex); log.info("Try to stop transaction for {}, with id {}", identity, transactionId); if (Objects.nonNull(identity)) { transactionMap.remove(identity); } } public RemoteStartTransactionConfirmation remoteStart(String id) { log.info("Try to start transaction for {}", id); var session = sessionService.getSessionByIdentity(id); log.info("Found session {}", session); if (Objects.nonNull(session)) { try { var future = ocppStub.send(session, new RemoteStartTransactionRequest(UUID.randomUUID().toString())); Confirmation confirmation = future.toCompletableFuture().get(); if (confirmation instanceof RemoteStartTransactionConfirmation startConfirmation) { RemoteStartStopStatus status = startConfirmation.getStatus(); log.info("Start transaction status {}", status); if (RemoteStartStopStatus.Accepted.equals(status)) { transactionMap.remove(id); } return startConfirmation; } } catch (InterruptedException | ExecutionException | OccurenceConstraintException | UnsupportedFeatureException | NotConnectedException e) { log.error("Caught exception on transaction start", e); } } throw new RuntimeException("Can't start transaction"); } public RemoteStopTransactionConfirmation remoteStop(String identity) { log.info("Try to stop transaction for {}", identity); var session = sessionService.getSessionByIdentity(identity); log.info("Found session {}", session); if (Objects.nonNull(session)) { Integer transactionId = transactionMap.get(identity); log.info("Found transaction id {}", transactionId); if (Objects.nonNull(transactionId)) { try { var future = ocppStub.send(session, new RemoteStopTransactionRequest(transactionId)); Confirmation confirmation = future.toCompletableFuture().get(); if (confirmation instanceof RemoteStopTransactionConfirmation stopConfirmation) { RemoteStartStopStatus status = stopConfirmation.getStatus(); log.info("Stop transaction status {}", status); if (RemoteStartStopStatus.Accepted.equals(status)) { transactionMap.remove(identity); } return stopConfirmation; } } catch (InterruptedException | ExecutionException | OccurenceConstraintException | UnsupportedFeatureException | NotConnectedException e) { log.error("Caught exception on transaction stop", e); } } } throw new RuntimeException("Can't stop transaction"); } }