Conversation
a546c1b to
11dd575
Compare
11dd575 to
c76a84d
Compare
Add Java classes for all OCPP 2.1 messages and types as well as client and server event handler interfaces and function classes corresponding to the OCPP 2.1 "functional blocks." Add OCPP 2.1 to the ProtocolVersion enum. Specify UTF-8 encoding for the Java source files in build.gradle and pom.xml to avoid compiler warnings about the UTF-8 sequences in the source files.
c76a84d to
febd153
Compare
Implement the CALLRESULTERROR RPC as a response to a CALLRESULT, in case that failed internal validation, or if the completion action last added to the CompletionStage returned by send() using .whenComplete[Async]() throws any exception. Add an optional confirmationError() callback method to the ClientEvents and ServerEvents interfaces to allow the application to get notified about an incoming CALLRESULTERROR. The application may use the uniqueId parameter to match it to the Request#getOcppMessageId() of one of the requests it last responded to, provided it keeps track of them. Implement the SEND RPC as requests which do not have a confirmation type. These are sent through the existing send() method, returning a CompletableFuture which is already completed when the method returns, to which a completion action can be added to check whether a local exception prevented the request from being sent. Fix the only OCPP message using the SEND RPC, NotifyPeriodicEventStream, and add its missing Feature and Function handlers. The handler for this message is a void method, as it has no response. Remove sending CALLERROR in response to anything other than a CALL, except for the RpcFrameworkError when the message could not be parsed. Simplify the pendingPromises synchronization in Session by using the ConcurrentHashMap class rather than HashMap. Fix a few typos encountered along the way.
Add multi-protocol integration tests for OCPP 1.6/2.0.1/2.1 protocol selection and exchanging BootNotification messages. Add integration tests for the OCPP 2.1 CALLRESULTERROR and SEND RPCs.
Bug: ReportDERControl message direction is reversedWhile integrating this PR, I found that IssuePer OCPP 2.1 spec, However, the current implementation has it backwards:
Cross-reference with correct pattern
Affected files
Happy to submit a PR with the fix if helpful. |
Spec reference for the ReportDERControl direction fixConfirmed against OCPP 2.1 Edition 2 (2025-12-03), Part 2 - Specification: R04 Requirements (p.561) — GetDERControl section:
All three requirements explicitly state that the Charging Station (CS) sends Message definitions (p.607-608):
GetDERControl definition (p.592):
This matches the |
Patch for the ReportDERControl direction fixHere is the patch to fix the reversed message ownership. Apply with Click to expand patchdiff --git a/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ClientDERControlEventHandler.java b/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ClientDERControlEventHandler.java
index fbf62591..6cb24543 100644
--- a/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ClientDERControlEventHandler.java
+++ b/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ClientDERControlEventHandler.java
@@ -44,14 +44,6 @@ public interface ClientDERControlEventHandler {
*/
GetDERControlResponse handleGetDERControlRequest(GetDERControlRequest request);
- /**
- * Handle a {@link ReportDERControlRequest} and return a {@link ReportDERControlResponse}.
- *
- * @param request incoming {@link ReportDERControlRequest} to handle.
- * @return outgoing {@link ReportDERControlResponse} to reply with.
- */
- ReportDERControlResponse handleReportDERControlRequest(ReportDERControlRequest request);
-
/**
* Handle a {@link SetDERControlRequest} and return a {@link SetDERControlResponse}.
*
diff --git a/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ClientDERControlFunction.java b/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ClientDERControlFunction.java
index c22bf8ec..5bc842de 100644
--- a/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ClientDERControlFunction.java
+++ b/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ClientDERControlFunction.java
@@ -48,7 +48,7 @@ public class ClientDERControlFunction implements Function {
features.add(new GetDERControlFeature(this));
features.add(new NotifyDERAlarmFeature(null));
features.add(new NotifyDERStartStopFeature(null));
- features.add(new ReportDERControlFeature(this));
+ features.add(new ReportDERControlFeature(null));
features.add(new SetDERControlFeature(this));
}
@@ -63,8 +63,6 @@ public class ClientDERControlFunction implements Function {
return eventHandler.handleClearDERControlRequest((ClearDERControlRequest) request);
} else if (request instanceof GetDERControlRequest) {
return eventHandler.handleGetDERControlRequest((GetDERControlRequest) request);
- } else if (request instanceof ReportDERControlRequest) {
- return eventHandler.handleReportDERControlRequest((ReportDERControlRequest) request);
} else if (request instanceof SetDERControlRequest) {
return eventHandler.handleSetDERControlRequest((SetDERControlRequest) request);
}
@@ -96,4 +94,14 @@ public class ClientDERControlFunction implements Function {
String controlId, Boolean started, ZonedDateTime timestamp) {
return new NotifyDERStartStopRequest(controlId, started, timestamp);
}
+
+ /**
+ * Create a client {@link ReportDERControlRequest} with all required fields.
+ *
+ * @param requestId RequestId from GetDERControlRequest.
+ * @return an instance of {@link ReportDERControlRequest}
+ */
+ public ReportDERControlRequest createReportDERControlRequest(Integer requestId) {
+ return new ReportDERControlRequest(requestId);
+ }
}
diff --git a/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ServerDERControlEventHandler.java b/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ServerDERControlEventHandler.java
index 875b053b..d4dd0ad6 100644
--- a/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ServerDERControlEventHandler.java
+++ b/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ServerDERControlEventHandler.java
@@ -48,4 +48,14 @@ public interface ServerDERControlEventHandler {
*/
NotifyDERStartStopResponse handleNotifyDERStartStopRequest(
UUID sessionIndex, NotifyDERStartStopRequest request);
+
+ /**
+ * Handle a {@link ReportDERControlRequest} and return a {@link ReportDERControlResponse}.
+ *
+ * @param sessionIndex identifier of the session on which the request was received.
+ * @param request incoming {@link ReportDERControlRequest} to handle.
+ * @return outgoing {@link ReportDERControlResponse} to reply with.
+ */
+ ReportDERControlResponse handleReportDERControlRequest(
+ UUID sessionIndex, ReportDERControlRequest request);
}
diff --git a/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ServerDERControlFunction.java b/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ServerDERControlFunction.java
index 5614d63e..10d543d3 100644
--- a/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ServerDERControlFunction.java
+++ b/ocpp-v2/src/main/java/eu/chargetime/ocpp/v21/feature/function/ServerDERControlFunction.java
@@ -47,7 +47,7 @@ public class ServerDERControlFunction implements Function {
features.add(new GetDERControlFeature(null));
features.add(new NotifyDERAlarmFeature(this));
features.add(new NotifyDERStartStopFeature(this));
- features.add(new ReportDERControlFeature(null));
+ features.add(new ReportDERControlFeature(this));
features.add(new SetDERControlFeature(null));
}
@@ -64,6 +64,9 @@ public class ServerDERControlFunction implements Function {
} else if (request instanceof NotifyDERStartStopRequest) {
return eventHandler.handleNotifyDERStartStopRequest(
sessionIndex, (NotifyDERStartStopRequest) request);
+ } else if (request instanceof ReportDERControlRequest) {
+ return eventHandler.handleReportDERControlRequest(
+ sessionIndex, (ReportDERControlRequest) request);
}
return null;
}
@@ -88,16 +91,6 @@ public class ServerDERControlFunction implements Function {
return new GetDERControlRequest(requestId);
}
- /**
- * Create a server {@link ReportDERControlRequest} with all required fields.
- *
- * @param requestId RequestId from GetDERControlRequest.
- * @return an instance of {@link ReportDERControlRequest}
- */
- public ReportDERControlRequest createReportDERControlRequest(Integer requestId) {
- return new ReportDERControlRequest(requestId);
- }
-
/**
* Create a server {@link SetDERControlRequest} with all required fields.
*Summary of changes:
|
|
Hi @neinhart, thank you very much for pointing this out! I took another look at all the new messages added in OCPP 2.1 and found that I got the direction wrong on three messages:
I'll prepare a commit to fix all these. |
Fix the direction of these OCPP 2.1 messages which were reversed: 1. ClosePeriodicEventStreamRequest is CS to CSMS 2. ReportDERControlRequest is CS to CSMS 3. RequestBatterySwapRequest is CSMS to CS
Move the handleClosePeriodicEventStreamRequest() implementation from the client side to the server side in the test code.
|
@neinhart these two commits incorporate your fix (thank you very much for so diligently preparing this!) and fix the other two messages as well. Please let me know if you run into any further issues. |
Move the Battery Swapping messages to a dedicated function, in line with the OCPP 2.1 specification which has a dedicated chapter for these.
|
I noticed that the Battery Swapping messages have a dedicated chapter in OCPP 2.1, so they belong in a dedicated function (functions mirror OCPP chapters) as well. Added a commit which adds the "BatterySwapping" function and moves these messages there. |
Add Java classes for all OCPP 2.1 messages and types as well as client and server event handler interfaces and function classes corresponding to the OCPP 2.1 "functional blocks."
Add OCPP 2.1 to the ProtocolVersion enum.
Specify UTF-8 encoding for the Java source files in build.gradle and pom.xml to avoid compiler warnings about the UTF-8 sequences in the source files.