Skip to content

Commit 65fbeb6

Browse files
committed
Added StatusNotification feature to core profile.
1 parent 0078f16 commit 65fbeb6

File tree

10 files changed

+906
-0
lines changed

10 files changed

+906
-0
lines changed

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ public boolean hasReceivedStartTransactionRequest() {
130130
return receivedMessage != null && "StartTransaction".equals(getAction());
131131
}
132132

133+
public boolean hasReceivedStatusNotificationRequest() {
134+
return receivedMessage != null && "StatusNotification".equals(getAction());
135+
}
136+
133137
private JSONObject getCallPayload()
134138
{
135139
return (JSONObject)receivedMessage[3];
@@ -251,6 +255,7 @@ public void sendResetRequest(String type) {
251255
public enum AvailabilityType {
252256
Inoperative, Operative
253257
}
258+
254259
public void sendChangeAvailabilityRequest(int connectorId, AvailabilityType type)
255260
{
256261
String payload = "\"connectorId\":%d,\"type\":\"%s\"";
@@ -265,6 +270,10 @@ public void sendHeartbeatConfirmation() {
265270
sendConfirmation(String.format(payload, now()));
266271
}
267272

273+
public void sendStatusNotificationConfirmation() {
274+
sendConfirmation("");
275+
}
276+
268277
public void sendStartTransactionConfirmation() {
269278
String payload = "\"idTagInfo\": {\"status\": \"Accepted\"}, \"transactionId\": 42";
270279
sendConfirmation(payload);

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,15 @@ public void sendDataTransferRequest(String vendorId, String messageId, String da
154154
}
155155
}
156156

157+
public void sendStatusNotificationRequest() {
158+
try {
159+
StatusNotificationRequest request = core.createStatusNotificationRequest(42, "NoError", "Available");
160+
send(request);
161+
} catch (Exception ex) {
162+
ex.printStackTrace();
163+
}
164+
}
165+
157166
private void send(Request request) {
158167
try {
159168
client.send(request).whenComplete((s, ex) -> receivedConfirmation = s);
@@ -189,6 +198,10 @@ public void hasReceivedStartTransactionConfirmation() {
189198
assertThat(receivedConfirmation, instanceOf(StartTransactionConfirmation.class));
190199
}
191200

201+
public void hasReceivedStatusNotificationConfirmation() {
202+
assertThat(receivedConfirmation, instanceOf(StatusNotificationConfirmation.class));
203+
}
204+
192205
public void disconnect() {
193206
client.disconnect();
194207
}
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 StatusNotification 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 StatusNotification request and receives a response"() {
29+
def conditions = new PollingConditions(timeout: 1);
30+
when:
31+
chargePoint.sendStatusNotificationRequest();
32+
33+
then:
34+
conditions.eventually {
35+
centralSystem.hasReceivedStatusNotificationRequest();
36+
}
37+
38+
when:
39+
centralSystem.sendStatusNotificationConfirmation();
40+
41+
then:
42+
conditions.eventually {
43+
chargePoint.hasReceivedStatusNotificationConfirmation();
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.StatusNotificationConfirmation;
7+
import eu.chargetime.ocpp.model.StatusNotificationRequest;
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 StatusNotificationFeature extends Feature {
35+
public StatusNotificationFeature(Profile ownerProfile) {
36+
super(ownerProfile);
37+
}
38+
39+
@Override
40+
public Class<? extends Request> getRequestType() {
41+
return StatusNotificationRequest.class;
42+
}
43+
44+
@Override
45+
public Class<? extends Confirmation> getConfirmationType() {
46+
return StatusNotificationConfirmation.class;
47+
}
48+
49+
@Override
50+
public String getAction() {
51+
return "StatusNotification";
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
@@ -55,6 +55,7 @@ public CoreProfile(ClientCoreEventHandler handler) {
5555
features.add(new RemoteStopTransactionFeature(this));
5656
features.add(new ResetFeature(this));
5757
features.add(new StartTransactionFeature(this));
58+
features.add(new StatusNotificationFeature(this));
5859
}
5960

6061
public AuthorizeRequest createAuthorizeRequest(String idToken) throws PropertyConstraintException {
@@ -104,6 +105,14 @@ public StartTransactionRequest createStartTransactionRequest(Integer connectorId
104105
return request;
105106
}
106107

108+
public StatusNotificationRequest createStatusNotificationRequest(Integer connectorId, String errorCode, String status) throws PropertyConstraintException {
109+
StatusNotificationRequest request = new StatusNotificationRequest();
110+
request.setConnectorId(connectorId);
111+
request.setErrorCode(errorCode);
112+
request.setStatus(status);
113+
return request;
114+
}
115+
107116
@Override
108117
public Feature[] getFeatureList() {
109118
return features.toArray(new Feature[0]);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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 StatusNotificationConfirmation implements Confirmation {
29+
@Override
30+
public boolean validate() {
31+
return true;
32+
}
33+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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 StatusNotificationRequest implements Request {
36+
private Integer connectorId;
37+
private String errorCode;
38+
private String info;
39+
private String status;
40+
private Calendar timestamp;
41+
private String vendorId;
42+
private String vendorErrorCode;
43+
44+
@Override
45+
public boolean validate() {
46+
boolean valid = true;
47+
valid &= isValidConnectorId(connectorId);
48+
valid &= isValidErrorCode(errorCode);
49+
valid &= isValidStatus(status);
50+
return valid;
51+
}
52+
53+
public void setConnectorId(Integer connectorId) throws PropertyConstraintException {
54+
if (!isValidConnectorId(connectorId))
55+
throw new PropertyConstraintException("connectorId", connectorId);
56+
57+
this.connectorId = connectorId;
58+
}
59+
60+
private boolean isValidConnectorId(Integer connectorId) {
61+
return connectorId != null && connectorId >= 0;
62+
}
63+
64+
public Integer getConnectorId() {
65+
return connectorId;
66+
}
67+
68+
public void setErrorCode(String errorCode) throws PropertyConstraintException {
69+
if (!isValidErrorCode(errorCode))
70+
throw new PropertyConstraintException("errorCode", errorCode);
71+
this.errorCode = errorCode;
72+
}
73+
74+
private boolean isValidErrorCode(String errorCode) {
75+
String[] chargePointErrorCode = {"ConnectorLockFailure", "EVCommunicationError", "GroundFailure", "HighTemperature", "InternalError", "LocalListConflict", "NoError", "OtherError", "OverCurrentFailure", "OverVoltage", "PowerMeterFailure", "PowerSwitchFailure", "ReaderFailure", "ResetFailure", "UnderVoltage", "WeakSignal"};
76+
return ModelUtil.isAmong(errorCode, chargePointErrorCode);
77+
}
78+
79+
public String getErrorCode() {
80+
return errorCode;
81+
}
82+
83+
public void setInfo(String info) throws PropertyConstraintException {
84+
if (!ModelUtil.validate(info, 50))
85+
throw new PropertyConstraintException("info", info);
86+
87+
this.info = info;
88+
}
89+
90+
public String getInfo() {
91+
return info;
92+
}
93+
94+
public void setStatus(String status) throws PropertyConstraintException {
95+
if (!isValidStatus(status))
96+
throw new PropertyConstraintException("status", status);
97+
98+
this.status = status;
99+
}
100+
101+
private boolean isValidStatus(String status) {
102+
Object[] chargePointStatus = {"Available", "Preparing", "Charging", "SuspendedEVSE", "SuspendedEV", "Finishing", "Reserved", "Unavailable", "Faulted"};
103+
return ModelUtil.isAmong(status, chargePointStatus);
104+
}
105+
106+
public String getStatus() {
107+
return status;
108+
}
109+
110+
public void setTimestamp(Calendar timestamp) {
111+
this.timestamp = timestamp;
112+
}
113+
114+
public String getTimestamp() {
115+
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
116+
formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
117+
return formatter.format(timestamp.getTime());
118+
}
119+
120+
public Calendar objTimestamp() {
121+
return timestamp;
122+
}
123+
124+
public void setVendorId(String vendorId) throws PropertyConstraintException {
125+
if (!ModelUtil.validate(vendorId, 255))
126+
throw new PropertyConstraintException("vendorId", vendorId);
127+
128+
this.vendorId = vendorId;
129+
}
130+
131+
public String getVendorId() {
132+
return vendorId;
133+
}
134+
135+
public void setVendorErrorCode(String vendorErrorCode) throws PropertyConstraintException {
136+
if (!ModelUtil.validate(vendorErrorCode, 50))
137+
throw new PropertyConstraintException("vendorErrorCode", vendorErrorCode);
138+
139+
this.vendorErrorCode = vendorErrorCode;
140+
}
141+
142+
public String getVendorErrorCode() {
143+
return vendorErrorCode;
144+
}
145+
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,15 @@ public void createStartTransactionRequest_returnsStartTransactionRequest() throw
106106
assertThat(result, instanceOf(StartTransactionRequest.class));
107107
}
108108

109+
@Test
110+
public void createStatusNotificationRequest_returnsStatusNotificationRequest() throws Exception {
111+
// When
112+
Request result = core.createStatusNotificationRequest(42, "NoError", "Available");
113+
114+
// Then
115+
assertThat(result, instanceOf(StatusNotificationRequest.class));
116+
}
117+
109118
@Test
110119
public void getFeatureList_containsBootNotificationFeature() {
111120
// When
@@ -178,6 +187,14 @@ public void getFeatureList_containsStartTransactionFeature() {
178187
assertThat(findFeature(features, "StartTransaction"), is(instanceOf(StartTransactionFeature.class)));
179188
}
180189

190+
@Test
191+
public void getFeatureList_containsStatusNotificationFeature() {
192+
// When
193+
Feature[] features = core.getFeatureList();
194+
195+
// Then
196+
assertThat(findFeature(features, "StatusNotification"), is(instanceOf(StatusNotificationFeature.class)));
197+
}
181198

182199
@Test
183200
public void handleRequest_aChangeAvailabilityRequest_callsHandleChangeAvailabilityRequest() {

0 commit comments

Comments
 (0)