Skip to content

Commit be45b68

Browse files
committed
Added StopTransaction feature to core profile.
1 parent 65fbeb6 commit be45b68

File tree

10 files changed

+716
-2
lines changed

10 files changed

+716
-2
lines changed

ocpp-test/src/main/java/eu/chargetime/ocpp/test/FakeCentralSystem.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ public boolean hasReceivedStatusNotificationRequest() {
134134
return receivedMessage != null && "StatusNotification".equals(getAction());
135135
}
136136

137+
public boolean hasReceivedStopTransactionRequest() {
138+
return receivedMessage != null && "StopTransaction".equals(getAction());
139+
}
140+
137141
private JSONObject getCallPayload()
138142
{
139143
return (JSONObject)receivedMessage[3];
@@ -255,7 +259,6 @@ public void sendResetRequest(String type) {
255259
public enum AvailabilityType {
256260
Inoperative, Operative
257261
}
258-
259262
public void sendChangeAvailabilityRequest(int connectorId, AvailabilityType type)
260263
{
261264
String payload = "\"connectorId\":%d,\"type\":\"%s\"";
@@ -269,7 +272,6 @@ public void sendHeartbeatConfirmation() {
269272
String payload = "\"currentTime\": \"%s\"";
270273
sendConfirmation(String.format(payload, now()));
271274
}
272-
273275
public void sendStatusNotificationConfirmation() {
274276
sendConfirmation("");
275277
}
@@ -279,6 +281,11 @@ public void sendStartTransactionConfirmation() {
279281
sendConfirmation(payload);
280282
}
281283

284+
public void sendStopTransactionConfirmation() {
285+
String payload = "\"idTagInfo\": {\"status\": \"Accepted\"}";
286+
sendConfirmation(payload);
287+
}
288+
282289
public void sendMeterValuesConfirmation() {
283290
sendConfirmation("");
284291
}

ocpp-test/src/main/java/eu/chargetime/ocpp/test/FakeChargePoint.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ public void sendStartTransactionRequest() {
142142
}
143143
}
144144

145+
public void sendStopTransactionRequest() {
146+
StopTransactionRequest request = core.createStopTransactionRequest(42, Calendar.getInstance(), 42);
147+
send(request);
148+
}
149+
145150
public void sendDataTransferRequest(String vendorId, String messageId, String data) {
146151
try {
147152
DataTransferRequest request = core.createDataTransferRequest(vendorId);
@@ -202,6 +207,10 @@ public void hasReceivedStatusNotificationConfirmation() {
202207
assertThat(receivedConfirmation, instanceOf(StatusNotificationConfirmation.class));
203208
}
204209

210+
public void hasReceivedStopTransactionConfirmation() {
211+
assertThat(receivedConfirmation, instanceOf(StopTransactionConfirmation.class));
212+
}
213+
205214
public void disconnect() {
206215
client.disconnect();
207216
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package core_features
2+
3+
import eu.chargetime.ocpp.test.FakeCentralSystem
4+
import eu.chargetime.ocpp.test.FakeChargePoint
5+
import spock.lang.Shared
6+
import spock.lang.Specification
7+
import spock.util.concurrent.PollingConditions;
8+
9+
class StopTransaction extends Specification {
10+
@Shared
11+
FakeCentralSystem centralSystem = FakeCentralSystem.getInstance();
12+
@Shared
13+
FakeChargePoint chargePoint = new FakeChargePoint();
14+
15+
def setupSpec() {
16+
// When a Central System is running
17+
centralSystem.started();
18+
}
19+
20+
def setup() {
21+
chargePoint.connect();
22+
}
23+
24+
def cleanup() {
25+
chargePoint.disconnect();
26+
}
27+
28+
def "Charge point sends StopTransaction request and receives a response"() {
29+
def conditions = new PollingConditions(timeout: 1);
30+
when:
31+
chargePoint.sendStopTransactionRequest();
32+
33+
then:
34+
conditions.eventually {
35+
centralSystem.hasReceivedStopTransactionRequest();
36+
}
37+
38+
when:
39+
centralSystem.sendStopTransactionConfirmation();
40+
41+
then:
42+
conditions.eventually {
43+
chargePoint.hasReceivedStopTransactionConfirmation();
44+
}
45+
46+
}
47+
48+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package eu.chargetime.ocpp.feature;
2+
3+
import eu.chargetime.ocpp.feature.profile.Profile;
4+
import eu.chargetime.ocpp.model.Confirmation;
5+
import eu.chargetime.ocpp.model.Request;
6+
import eu.chargetime.ocpp.model.StopTransactionConfirmation;
7+
import eu.chargetime.ocpp.model.StopTransactionRequest;
8+
9+
/**
10+
* ChargeTime.eu - Java-OCA-OCPP
11+
* <p>
12+
* MIT License
13+
* <p>
14+
* Copyright (C) 2016 Thomas Volden <[email protected]>
15+
* <p>
16+
* Permission is hereby granted, free of charge, to any person obtaining a copy
17+
* of this software and associated documentation files (the "Software"), to deal
18+
* in the Software without restriction, including without limitation the rights
19+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20+
* copies of the Software, and to permit persons to whom the Software is
21+
* furnished to do so, subject to the following conditions:
22+
* <p>
23+
* The above copyright notice and this permission notice shall be included in all
24+
* copies or substantial portions of the Software.
25+
* <p>
26+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32+
* SOFTWARE.
33+
*/
34+
public class StopTransactionFeature extends Feature {
35+
public StopTransactionFeature(Profile ownerProfile) {
36+
super(ownerProfile);
37+
}
38+
39+
@Override
40+
public Class<? extends Request> getRequestType() {
41+
return StopTransactionRequest.class;
42+
}
43+
44+
@Override
45+
public Class<? extends Confirmation> getConfirmationType() {
46+
return StopTransactionConfirmation.class;
47+
}
48+
49+
@Override
50+
public String getAction() {
51+
return "StopTransaction";
52+
}
53+
}

ocpp-v1_6/src/main/java/eu/chargetime/ocpp/feature/profile/CoreProfile.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public CoreProfile(ClientCoreEventHandler handler) {
5656
features.add(new ResetFeature(this));
5757
features.add(new StartTransactionFeature(this));
5858
features.add(new StatusNotificationFeature(this));
59+
features.add(new StopTransactionFeature(this));
5960
}
6061

6162
public AuthorizeRequest createAuthorizeRequest(String idToken) throws PropertyConstraintException {
@@ -113,6 +114,14 @@ public StatusNotificationRequest createStatusNotificationRequest(Integer connect
113114
return request;
114115
}
115116

117+
public StopTransactionRequest createStopTransactionRequest(int meterStop, Calendar timestamp, int transactionId) {
118+
StopTransactionRequest request = new StopTransactionRequest();
119+
request.setMeterStop(meterStop);
120+
request.setTimestamp(timestamp);
121+
request.setTransactionId(transactionId);
122+
return request;
123+
}
124+
116125
@Override
117126
public Feature[] getFeatureList() {
118127
return features.toArray(new Feature[0]);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package eu.chargetime.ocpp.model;
2+
3+
/**
4+
* ChargeTime.eu - Java-OCA-OCPP
5+
* <p>
6+
* MIT License
7+
* <p>
8+
* Copyright (C) 2016 Thomas Volden <[email protected]>
9+
* <p>
10+
* Permission is hereby granted, free of charge, to any person obtaining a copy
11+
* of this software and associated documentation files (the "Software"), to deal
12+
* in the Software without restriction, including without limitation the rights
13+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14+
* copies of the Software, and to permit persons to whom the Software is
15+
* furnished to do so, subject to the following conditions:
16+
* <p>
17+
* The above copyright notice and this permission notice shall be included in all
18+
* copies or substantial portions of the Software.
19+
* <p>
20+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26+
* SOFTWARE.
27+
*/
28+
public class StopTransactionConfirmation implements Confirmation {
29+
private IdTagInfo idTagInfo;
30+
31+
@Override
32+
public boolean validate() {
33+
boolean valid = true;
34+
if (idTagInfo != null)
35+
valid &= idTagInfo.validate();
36+
return valid;
37+
}
38+
39+
public void setIdTagInfo(IdTagInfo idTagInfo) {
40+
this.idTagInfo = idTagInfo;
41+
}
42+
43+
public IdTagInfo getIdTagInfo() {
44+
return idTagInfo;
45+
}
46+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package eu.chargetime.ocpp.model;
2+
3+
import eu.chargetime.ocpp.PropertyConstraintException;
4+
import eu.chargetime.ocpp.utilities.ModelUtil;
5+
6+
import java.text.SimpleDateFormat;
7+
import java.util.Calendar;
8+
import java.util.TimeZone;
9+
10+
/**
11+
* ChargeTime.eu - Java-OCA-OCPP
12+
* <p>
13+
* MIT License
14+
* <p>
15+
* Copyright (C) 2016 Thomas Volden <[email protected]>
16+
* <p>
17+
* Permission is hereby granted, free of charge, to any person obtaining a copy
18+
* of this software and associated documentation files (the "Software"), to deal
19+
* in the Software without restriction, including without limitation the rights
20+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21+
* copies of the Software, and to permit persons to whom the Software is
22+
* furnished to do so, subject to the following conditions:
23+
* <p>
24+
* The above copyright notice and this permission notice shall be included in all
25+
* copies or substantial portions of the Software.
26+
* <p>
27+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33+
* SOFTWARE.
34+
*/
35+
public class StopTransactionRequest implements Request {
36+
private IdToken idTag;
37+
private Integer meterStop;
38+
private Calendar timestamp;
39+
private Integer transactionId;
40+
private String reason;
41+
private MeterValue[] transactionData;
42+
43+
@Override
44+
public boolean validate() {
45+
boolean valid = true;
46+
valid &= meterStop != null;
47+
valid &= timestamp != null;
48+
valid &= transactionId != null;
49+
if (transactionData != null) {
50+
for (MeterValue meterValue : transactionData) {
51+
valid &= meterValue.validate();
52+
}
53+
}
54+
return valid;
55+
}
56+
57+
public void setIdTag(IdToken idTag) {
58+
this.idTag = idTag;
59+
}
60+
61+
public IdToken getIdTag() {
62+
return idTag;
63+
}
64+
65+
public void setMeterStop(Integer meterStop) {
66+
this.meterStop = meterStop;
67+
}
68+
69+
public Integer getMeterStop() {
70+
return meterStop;
71+
}
72+
73+
public void setTimestamp(Calendar timestamp) {
74+
this.timestamp = timestamp;
75+
}
76+
77+
public String getTimestamp() {
78+
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
79+
formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
80+
return formatter.format(timestamp.getTime());
81+
}
82+
83+
public Calendar objTimestamp() {
84+
return timestamp;
85+
}
86+
87+
public void setTransactionId(Integer transactionId) {
88+
this.transactionId = transactionId;
89+
}
90+
91+
public Integer getTransactionId() {
92+
return transactionId;
93+
}
94+
95+
public void setReason(String reason) throws PropertyConstraintException {
96+
if (!isValidReason(reason))
97+
throw new PropertyConstraintException("reason", reason);
98+
99+
this.reason = reason;
100+
}
101+
102+
private boolean isValidReason(String reason) {
103+
String[] reasons = {"EmergencyStop", "EVDisconnected", "HardReset", "Local", "Other", "PowerLoss", "Reboot", "Remote", "SoftReset", "UnlockCommand", "DeAuthorized"};
104+
return ModelUtil.isAmong(reason, reasons);
105+
}
106+
107+
public String getReason() {
108+
return reason;
109+
}
110+
111+
public void setTransactionData(MeterValue[] transactionData) {
112+
this.transactionData = transactionData;
113+
}
114+
115+
public MeterValue[] getTransactionData() {
116+
return transactionData;
117+
}
118+
}

ocpp-v1_6/src/test/java/eu/chargetime/ocpp/feature/profile/test/CoreProfileTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,15 @@ public void createStatusNotificationRequest_returnsStatusNotificationRequest() t
115115
assertThat(result, instanceOf(StatusNotificationRequest.class));
116116
}
117117

118+
@Test
119+
public void createStopTransactionRequest_returnsStopTransactionRequest() throws Exception {
120+
// When
121+
Request result = core.createStopTransactionRequest(42, Calendar.getInstance(), 42);
122+
123+
// Then
124+
assertThat(result, instanceOf(StopTransactionRequest.class));
125+
}
126+
118127
@Test
119128
public void getFeatureList_containsBootNotificationFeature() {
120129
// When
@@ -196,6 +205,15 @@ public void getFeatureList_containsStatusNotificationFeature() {
196205
assertThat(findFeature(features, "StatusNotification"), is(instanceOf(StatusNotificationFeature.class)));
197206
}
198207

208+
@Test
209+
public void getFeatureList_containsStopTransactionFeature() {
210+
// When
211+
Feature[] features = core.getFeatureList();
212+
213+
// Then
214+
assertThat(findFeature(features, "StopTransaction"), is(instanceOf(StopTransactionFeature.class)));
215+
}
216+
199217
@Test
200218
public void handleRequest_aChangeAvailabilityRequest_callsHandleChangeAvailabilityRequest() {
201219
// Given

0 commit comments

Comments
 (0)