feat: Reset testing suite
This commit is contained in:
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'org.springframework.boot' version '2.7.4'
|
id 'org.springframework.boot' version '3.2.0'
|
||||||
id 'io.spring.dependency-management' version '1.0.14.RELEASE'
|
id 'io.spring.dependency-management' version '1.1.4'
|
||||||
}
|
}
|
||||||
|
|
||||||
group 'org.example'
|
group 'org.example'
|
||||||
@@ -22,7 +22,7 @@ dependencies {
|
|||||||
compileOnly 'org.projectlombok:lombok'
|
compileOnly 'org.projectlombok:lombok'
|
||||||
annotationProcessor 'org.projectlombok:lombok'
|
annotationProcessor 'org.projectlombok:lombok'
|
||||||
implementation group: 'eu.chargetime.ocpp', name: 'v1_6', version: '1.0.1'
|
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'
|
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.3.0'
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
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 ConfigService configService;
|
||||||
private final ConnectorStatusService connectorService;
|
private final ConnectorStatusService connectorService;
|
||||||
private final Communicator communicator;
|
private final Communicator communicator;
|
||||||
|
private final AuthService authService;
|
||||||
|
private final TransactionService transactionService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AuthorizeConfirmation handleAuthorizeRequest(UUID sessionIndex, AuthorizeRequest request) {
|
public AuthorizeConfirmation handleAuthorizeRequest(UUID sessionIndex, AuthorizeRequest request) {
|
||||||
return null;
|
return new AuthorizeConfirmation(authService.authorize(request.getIdTag()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -49,12 +51,12 @@ public class EventHandler implements ServerCoreEventHandler, ServerEvents {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MeterValuesConfirmation handleMeterValuesRequest(UUID sessionIndex, MeterValuesRequest request) {
|
public MeterValuesConfirmation handleMeterValuesRequest(UUID sessionIndex, MeterValuesRequest request) {
|
||||||
return null;
|
return new MeterValuesConfirmation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StartTransactionConfirmation handleStartTransactionRequest(UUID sessionIndex, StartTransactionRequest request) {
|
public StartTransactionConfirmation handleStartTransactionRequest(UUID sessionIndex, StartTransactionRequest request) {
|
||||||
return null;
|
return transactionService.startByRequest(sessionIndex, request.getConnectorId(), request.getIdTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -65,7 +67,9 @@ public class EventHandler implements ServerCoreEventHandler, ServerEvents {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StopTransactionConfirmation handleStopTransactionRequest(UUID sessionIndex, StopTransactionRequest request) {
|
public StopTransactionConfirmation handleStopTransactionRequest(UUID sessionIndex, StopTransactionRequest request) {
|
||||||
return null;
|
log.info("Stop transaction request {}", request);
|
||||||
|
transactionService.stopByRequest(sessionIndex, request.getTransactionId());
|
||||||
|
return new StopTransactionConfirmation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import eu.chargetime.ocpp.UnsupportedFeatureException;
|
|||||||
import eu.chargetime.ocpp.YablJSONServer;
|
import eu.chargetime.ocpp.YablJSONServer;
|
||||||
import eu.chargetime.ocpp.model.Confirmation;
|
import eu.chargetime.ocpp.model.Confirmation;
|
||||||
import eu.chargetime.ocpp.model.Request;
|
import eu.chargetime.ocpp.model.Request;
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletionStage;
|
import java.util.concurrent.CompletionStage;
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ public class OcppStub {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
private void Init() {
|
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)
|
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.YablSessionInformation;
|
||||||
import eu.chargetime.ocpp.model.SessionInformation;
|
import eu.chargetime.ocpp.model.SessionInformation;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Objects;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.java_websocket.handshake.ClientHandshake;
|
import org.java_websocket.handshake.ClientHandshake;
|
||||||
@@ -27,8 +29,7 @@ public class SessionService {
|
|||||||
public String getAuthBySessionId(UUID sessionId) {
|
public String getAuthBySessionId(UUID sessionId) {
|
||||||
SessionInformation sessionInformation = cache.get(sessionId);
|
SessionInformation sessionInformation = cache.get(sessionId);
|
||||||
|
|
||||||
if (sessionInformation instanceof YablSessionInformation) {
|
if (sessionInformation instanceof YablSessionInformation session) {
|
||||||
YablSessionInformation session = (YablSessionInformation) sessionInformation;
|
|
||||||
|
|
||||||
ClientHandshake clientHandshake = session.getClientHandshake();
|
ClientHandshake clientHandshake = session.getClientHandshake();
|
||||||
if (clientHandshake != null) {
|
if (clientHandshake != null) {
|
||||||
@@ -39,4 +40,26 @@ public class SessionService {
|
|||||||
log.debug("Session {} auth status not found", sessionId);
|
log.debug("Session {} auth status not found", sessionId);
|
||||||
return null;
|
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.OcppStub;
|
||||||
import com.yablochkov.ocppstub.SessionService;
|
import com.yablochkov.ocppstub.SessionService;
|
||||||
|
import com.yablochkov.ocppstub.TransactionService;
|
||||||
import eu.chargetime.ocpp.NotConnectedException;
|
import eu.chargetime.ocpp.NotConnectedException;
|
||||||
import eu.chargetime.ocpp.OccurenceConstraintException;
|
import eu.chargetime.ocpp.OccurenceConstraintException;
|
||||||
import eu.chargetime.ocpp.UnsupportedFeatureException;
|
import eu.chargetime.ocpp.UnsupportedFeatureException;
|
||||||
import eu.chargetime.ocpp.model.Confirmation;
|
import eu.chargetime.ocpp.model.Confirmation;
|
||||||
import eu.chargetime.ocpp.model.SessionInformation;
|
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.ResetConfirmation;
|
||||||
import eu.chargetime.ocpp.model.core.ResetRequest;
|
import eu.chargetime.ocpp.model.core.ResetRequest;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -20,8 +23,10 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.http.HttpStatus;
|
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.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
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.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -33,19 +38,22 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class ResetController {
|
public class ResetController {
|
||||||
@Autowired private SessionService sessionService;
|
@Autowired private SessionService sessionService;
|
||||||
|
@Autowired private TransactionService transactionService;
|
||||||
@Lazy @Autowired private OcppStub ocppStub;
|
@Lazy @Autowired private OcppStub ocppStub;
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
public Map<UUID, SessionInformation> findClients() {
|
public Map<UUID, SessionInformation> findClients() {
|
||||||
return sessionService.getCache();
|
return sessionService.getCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/{id}")
|
@PutMapping("/reset/{identity}")
|
||||||
@ResponseStatus(HttpStatus.OK)
|
@ResponseStatus(HttpStatus.OK)
|
||||||
public ResetConfirmation updateBook(
|
public ResetConfirmation reset(
|
||||||
@PathVariable("id") final String id, @RequestBody final ResetRequest request) {
|
@PathVariable("identity") final String identity, @RequestBody final ResetRequest request) {
|
||||||
|
// TODO REFACTOR THIS
|
||||||
|
log.info("Send reset to {}, parameters {}", identity, request);
|
||||||
var session = sessionService.getCache()
|
var session = sessionService.getCache()
|
||||||
.entrySet().stream()
|
.entrySet().stream()
|
||||||
.filter((entry) -> Objects.equals(entry.getValue().getIdentifier(), id))
|
.filter((entry) -> Objects.equals(entry.getValue().getIdentifier(), identity))
|
||||||
.map(Entry::getKey)
|
.map(Entry::getKey)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
.orElseThrow();
|
.orElseThrow();
|
||||||
@@ -65,4 +73,14 @@ public class ResetController {
|
|||||||
|
|
||||||
return new ResetConfirmation(Rejected);
|
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"
|
||||||
Reference in New Issue
Block a user