feat: Reset testing suite

master
Terekhin Alexandr 2 years ago
parent 4c7cb52703
commit 3680a1ce2b
Signed by: didinst
GPG Key ID: D2EF94423C23BF12
  1. 6
      build.gradle
  2. 17
      src/main/java/com/yablochkov/ocppstub/AuthService.java
  3. 12
      src/main/java/com/yablochkov/ocppstub/EventHandler.java
  4. 4
      src/main/java/com/yablochkov/ocppstub/OcppStub.java
  5. 27
      src/main/java/com/yablochkov/ocppstub/SessionService.java
  6. 122
      src/main/java/com/yablochkov/ocppstub/TransactionService.java
  7. 26
      src/main/java/com/yablochkov/ocppstub/rest/ResetController.java
  8. 3
      src/main/resources/application.yaml
  9. 6
      src/main/resources/application.yml

@ -1,7 +1,7 @@
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.4'
id 'io.spring.dependency-management' version '1.0.14.RELEASE'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}
group 'org.example'
@ -22,7 +22,7 @@ dependencies {
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
implementation group: 'eu.chargetime.ocpp', name: 'v1_6', version: '1.0.1'
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.3.0'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

@ -0,0 +1,17 @@
package com.yablochkov.ocppstub;
import eu.chargetime.ocpp.model.core.AuthorizationStatus;
import eu.chargetime.ocpp.model.core.AuthorizeConfirmation;
import eu.chargetime.ocpp.model.core.IdTagInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class AuthService {
public IdTagInfo authorize(String idTag) {
log.info("Authorize id tag {}", idTag);
return new IdTagInfo(AuthorizationStatus.Accepted);
}
}

@ -20,10 +20,12 @@ public class EventHandler implements ServerCoreEventHandler, ServerEvents {
private final ConfigService configService;
private final ConnectorStatusService connectorService;
private final Communicator communicator;
private final AuthService authService;
private final TransactionService transactionService;
@Override
public AuthorizeConfirmation handleAuthorizeRequest(UUID sessionIndex, AuthorizeRequest request) {
return null;
return new AuthorizeConfirmation(authService.authorize(request.getIdTag()));
}
@Override
@ -49,12 +51,12 @@ public class EventHandler implements ServerCoreEventHandler, ServerEvents {
@Override
public MeterValuesConfirmation handleMeterValuesRequest(UUID sessionIndex, MeterValuesRequest request) {
return null;
return new MeterValuesConfirmation();
}
@Override
public StartTransactionConfirmation handleStartTransactionRequest(UUID sessionIndex, StartTransactionRequest request) {
return null;
return transactionService.startByRequest(sessionIndex, request.getConnectorId(), request.getIdTag());
}
@Override
@ -65,7 +67,9 @@ public class EventHandler implements ServerCoreEventHandler, ServerEvents {
@Override
public StopTransactionConfirmation handleStopTransactionRequest(UUID sessionIndex, StopTransactionRequest request) {
return null;
log.info("Stop transaction request {}", request);
transactionService.stopByRequest(sessionIndex, request.getTransactionId());
return new StopTransactionConfirmation();
}
@Override

@ -6,10 +6,10 @@ import eu.chargetime.ocpp.UnsupportedFeatureException;
import eu.chargetime.ocpp.YablJSONServer;
import eu.chargetime.ocpp.model.Confirmation;
import eu.chargetime.ocpp.model.Request;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.UUID;
import java.util.concurrent.CompletionStage;
@ -21,7 +21,7 @@ public class OcppStub {
@PostConstruct
private void Init() {
server.open("0.0.0.0", 8080, eventHandler);
server.open("0.0.0.0", 8081, eventHandler);
}
public CompletionStage<Confirmation> send(UUID sessionIndex, Request request)

@ -2,6 +2,8 @@ package com.yablochkov.ocppstub;
import eu.chargetime.ocpp.YablSessionInformation;
import eu.chargetime.ocpp.model.SessionInformation;
import java.util.Map.Entry;
import java.util.Objects;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.handshake.ClientHandshake;
@ -27,8 +29,7 @@ public class SessionService {
public String getAuthBySessionId(UUID sessionId) {
SessionInformation sessionInformation = cache.get(sessionId);
if (sessionInformation instanceof YablSessionInformation) {
YablSessionInformation session = (YablSessionInformation) sessionInformation;
if (sessionInformation instanceof YablSessionInformation session) {
ClientHandshake clientHandshake = session.getClientHandshake();
if (clientHandshake != null) {
@ -39,4 +40,26 @@ public class SessionService {
log.debug("Session {} auth status not found", sessionId);
return null;
}
public String getIdentityBySessionId(UUID sessionId) {
SessionInformation sessionInformation = cache.get(sessionId);
if (Objects.nonNull(sessionInformation)) {
return sessionInformation.getIdentifier();
}
return null;
}
public UUID getSessionByIdentity(String identity) {
return cache.entrySet().stream()
.filter((entry) -> {
var entryValue = entry.getValue();
if (Objects.nonNull(entryValue)) {
return Objects.equals(entryValue.getIdentifier(), identity);
}
return false;
})
.findFirst()
.map(Entry::getKey)
.orElseThrow();
}
}

@ -0,0 +1,122 @@
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<String,Integer> 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");
}
}

@ -4,11 +4,14 @@ import static eu.chargetime.ocpp.model.core.ResetStatus.Rejected;
import com.yablochkov.ocppstub.OcppStub;
import com.yablochkov.ocppstub.SessionService;
import com.yablochkov.ocppstub.TransactionService;
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.SessionInformation;
import eu.chargetime.ocpp.model.core.RemoteStartTransactionConfirmation;
import eu.chargetime.ocpp.model.core.RemoteStopTransactionConfirmation;
import eu.chargetime.ocpp.model.core.ResetConfirmation;
import eu.chargetime.ocpp.model.core.ResetRequest;
import java.util.Map;
@ -20,8 +23,10 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@ -33,19 +38,22 @@ import org.springframework.web.bind.annotation.RestController;
@Slf4j
public class ResetController {
@Autowired private SessionService sessionService;
@Autowired private TransactionService transactionService;
@Lazy @Autowired private OcppStub ocppStub;
@GetMapping("/list")
public Map<UUID, SessionInformation> findClients() {
return sessionService.getCache();
}
@PutMapping("/{id}")
@PutMapping("/reset/{identity}")
@ResponseStatus(HttpStatus.OK)
public ResetConfirmation updateBook(
@PathVariable("id") final String id, @RequestBody final ResetRequest request) {
public ResetConfirmation reset(
@PathVariable("identity") final String identity, @RequestBody final ResetRequest request) {
// TODO REFACTOR THIS
log.info("Send reset to {}, parameters {}", identity, request);
var session = sessionService.getCache()
.entrySet().stream()
.filter((entry) -> Objects.equals(entry.getValue().getIdentifier(), id))
.filter((entry) -> Objects.equals(entry.getValue().getIdentifier(), identity))
.map(Entry::getKey)
.findFirst()
.orElseThrow();
@ -65,4 +73,14 @@ public class ResetController {
return new ResetConfirmation(Rejected);
}
@PostMapping("/start/{identity}")
public RemoteStartTransactionConfirmation startTransaction(@PathVariable("identity") final String identity) {
return transactionService.remoteStart(identity);
}
@DeleteMapping("/stop/{identity}")
public RemoteStopTransactionConfirmation stopTransaction(@PathVariable("identity") final String identity) {
return transactionService.remoteStop(identity);
}
}

@ -1,3 +0,0 @@
springdoc:
swagger-ui:
path: "/api-docs.html"

@ -0,0 +1,6 @@
server:
port: 8080
springdoc:
swagger-ui:
path: "/api/docs.html"
Loading…
Cancel
Save