Skip to content

Commit 11ba5d4

Browse files
committed
Added RemoteStartTransaction feature to core profile.
1 parent e1f82ad commit 11ba5d4

26 files changed

+1661
-7
lines changed

ocpp-common/src/main/java/eu/chargetime/ocpp/model/Confirmation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ of this software and associated documentation files (the "Software"), to deal
2626
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2727
SOFTWARE.
2828
*/
29-
public interface Confirmation extends validatable {
29+
public interface Confirmation extends Validatable {
3030
}

ocpp-common/src/main/java/eu/chargetime/ocpp/model/Request.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ of this software and associated documentation files (the "Software"), to deal
2626
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2727
SOFTWARE.
2828
*/
29-
public interface Request extends validatable {
29+
public interface Request extends Validatable {
3030
}

ocpp-common/src/main/java/eu/chargetime/ocpp/model/validatable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ of this software and associated documentation files (the "Software"), to deal
2626
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2727
SOFTWARE.
2828
*/
29-
public interface validatable {
29+
public interface Validatable {
3030
boolean validate();
3131
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ public void hasReceivedDataTransferConfirmation() {
188188
assertThat(getUniqueId(), equalTo("DataTransfer"));
189189
}
190190

191+
public void hasReceivedRemoteStartTransactionConfirmation(String status) {
192+
assertThat(getUniqueId(), equalTo("RemoteStartTransaction"));
193+
assertThat(getCallResultPayload().getString("status"), equalTo(status));
194+
}
195+
191196
public void sendGetConfigurationRequest(String... keys) {
192197
String payload = "\"key\":%s";
193198
sendRequest("GetConfiguration", String.format(payload, formatList(keys)));
@@ -214,6 +219,11 @@ public void sendDataTransferRequest(String vendorId, String messageId, String da
214219
sendRequest("DataTransfer", String.format(payload, vendorId, messageId, data));
215220
}
216221

222+
public void sendRemoteStartTransactionRequest(String idTag) {
223+
String payload = "\"idTag\": { \"idToken\": \"%s\"}";
224+
sendRequest("RemoteStartTransaction", String.format(payload, idTag));
225+
}
226+
217227
public enum AvailabilityType {
218228
Inoperative, Operative
219229
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ public DataTransferConfirmation handleDataTransferRequest(DataTransferRequest re
7474
receivedRequest = request;
7575
return new DataTransferConfirmation();
7676
}
77+
78+
@Override
79+
public RemoteStartTransactionConfirmation handleRemoteStartTransactionRequest(RemoteStartTransactionRequest request) {
80+
receivedRequest = request;
81+
return new RemoteStartTransactionConfirmation("Accepted");
82+
}
7783
});
7884
client = new Client(new Session(new JSONCommunicator(new WebSocketTransmitter()), new Queue()));
7985
client.addFeatureProfile(core);
@@ -181,4 +187,8 @@ public void hasHandledClearCacheRequest() {
181187
public void hasHandledDataTransferRequest() {
182188
confirmRequest(DataTransferRequest.class);
183189
}
190+
191+
public void hasHandledRemoteStartTransactionRequest() {
192+
confirmRequest(RemoteStartTransactionRequest.class);
193+
}
184194
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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 RemoteStartTransaction 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 "Central System sends a RemoteStartTransaction request and receives a response"() {
29+
def conditions = new PollingConditions(timeout: 1)
30+
when:
31+
centralSystem.sendRemoteStartTransactionRequest("some id");
32+
33+
then:
34+
conditions.eventually {
35+
chargePoint.hasHandledRemoteStartTransactionRequest();
36+
centralSystem.hasReceivedRemoteStartTransactionConfirmation("Accepted");
37+
}
38+
}
39+
}
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.RemoteStartTransactionConfirmation;
6+
import eu.chargetime.ocpp.model.RemoteStartTransactionRequest;
7+
import eu.chargetime.ocpp.model.Request;
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 RemoteStartTransactionFeature extends Feature {
35+
public RemoteStartTransactionFeature(Profile ownerProfile) {
36+
super(ownerProfile);
37+
}
38+
39+
@Override
40+
public Class<? extends Request> getRequestType() {
41+
return RemoteStartTransactionRequest.class;
42+
}
43+
44+
@Override
45+
public Class<? extends Confirmation> getConfirmationType() {
46+
return RemoteStartTransactionConfirmation.class;
47+
}
48+
49+
@Override
50+
public String getAction() {
51+
return "RemoteStartTransaction";
52+
}
53+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@ public interface ClientCoreEventHandler {
3434
ChangeConfigurationConfirmation handleChangeConfigurationRequest(ChangeConfigurationRequest request);
3535
ClearCacheConfirmation handleClearCacheRequest(ClearCacheRequest request);
3636
DataTransferConfirmation handleDataTransferRequest(DataTransferRequest request);
37+
38+
RemoteStartTransactionConfirmation handleRemoteStartTransactionRequest(RemoteStartTransactionRequest request);
3739
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public CoreProfile(ClientCoreEventHandler handler) {
5151
features.add(new DataTransferFeature(this));
5252
features.add(new HeartbeatFeature(this));
5353
features.add(new MeterValuesFeature(this));
54+
features.add(new RemoteStartTransactionFeature(this));
5455
}
5556

5657
public AuthorizeRequest createAuthorizeRequest(String idToken) throws PropertyConstraintException {
@@ -112,6 +113,8 @@ else if (request instanceof ClearCacheRequest) {
112113
}
113114
else if (request instanceof DataTransferRequest) {
114115
result = eventHandler.handleDataTransferRequest((DataTransferRequest)request);
116+
} else if (request instanceof RemoteStartTransactionRequest) {
117+
result = eventHandler.handleRemoteStartTransactionRequest((RemoteStartTransactionRequest) request);
115118
}
116119

117120
return result;
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
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 ChargingProfile implements Validatable {
36+
private Integer chargingProfileId;
37+
private Integer transactionId;
38+
private Integer stackLevel;
39+
private String chargingProfilePurpose;
40+
private String chargingProfileKind;
41+
private String recurrencyKind;
42+
private Calendar validFrom;
43+
private Calendar validTo;
44+
private ChargingSchedule chargingSchedule;
45+
46+
@Override
47+
public boolean validate() {
48+
boolean valid = true;
49+
valid &= chargingProfileId != null;
50+
valid &= stackLevel >= 0;
51+
valid &= isValidChargingProfilePurpose(chargingProfilePurpose);
52+
valid &= transactionId == null || "TxProfile".equals(chargingProfilePurpose);
53+
valid &= isValidChargingProfileKind(chargingProfileKind);
54+
valid &= chargingSchedule != null && chargingSchedule.validate();
55+
return valid;
56+
}
57+
58+
public void setChargingProfileId(Integer chargingProfileId) throws PropertyConstraintException {
59+
if (chargingProfileId == null)
60+
throw new PropertyConstraintException("chargingProfileId", chargingProfileId);
61+
62+
this.chargingProfileId = chargingProfileId;
63+
}
64+
65+
public Integer getChargingProfileId() {
66+
return chargingProfileId;
67+
}
68+
69+
public void setTransactionId(Integer transactionId) {
70+
this.transactionId = transactionId;
71+
}
72+
73+
public Integer getTransactionId() {
74+
return transactionId;
75+
}
76+
77+
public void setStackLevel(Integer stackLevel) throws PropertyConstraintException {
78+
if (stackLevel < 0)
79+
throw new PropertyConstraintException("stackLevel", stackLevel);
80+
81+
this.stackLevel = stackLevel;
82+
}
83+
84+
public Integer getStackLevel() {
85+
return stackLevel;
86+
}
87+
88+
public void setChargingProfilePurpose(String chargingProfilePurpose) throws PropertyConstraintException {
89+
if (!isValidChargingProfilePurpose(chargingProfilePurpose))
90+
throw new PropertyConstraintException("chargingProfilePurpose", chargingProfilePurpose);
91+
92+
this.chargingProfilePurpose = chargingProfilePurpose;
93+
}
94+
95+
private boolean isValidChargingProfilePurpose(String chargingProfilePurpose) {
96+
return ModelUtil.isAmong(chargingProfilePurpose, "ChargePointMaxProfile", "TxDefaultProfile", "TxProfile");
97+
}
98+
99+
public String getChargingProfilePurpose() {
100+
return chargingProfilePurpose;
101+
}
102+
103+
public void setChargingProfileKind(String chargingProfileKind) throws PropertyConstraintException {
104+
if (!isValidChargingProfileKind(chargingProfileKind))
105+
throw new PropertyConstraintException("chargingProfileKind", chargingProfileKind);
106+
107+
this.chargingProfileKind = chargingProfileKind;
108+
}
109+
110+
private boolean isValidChargingProfileKind(String chargingProfileKind) {
111+
return ModelUtil.isAmong(chargingProfileKind, "Absolute", "Recurring", "Relative");
112+
}
113+
114+
public String getChargingProfileKind() {
115+
return chargingProfileKind;
116+
}
117+
118+
public void setRecurrencyKind(String recurrencyKind) throws PropertyConstraintException {
119+
if (!isValidRecurrencyKind(recurrencyKind))
120+
throw new PropertyConstraintException("recurrencyKind", recurrencyKind);
121+
122+
this.recurrencyKind = recurrencyKind;
123+
}
124+
125+
private boolean isValidRecurrencyKind(String recurrencyKind) {
126+
return ModelUtil.isAmong(recurrencyKind, "Daily", "Weekly");
127+
}
128+
129+
public String getRecurrencyKind() {
130+
return recurrencyKind;
131+
}
132+
133+
public void setValidFrom(Calendar validFrom) {
134+
this.validFrom = validFrom;
135+
}
136+
137+
public String getValidFrom() {
138+
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
139+
formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
140+
return formatter.format(validFrom.getTime());
141+
}
142+
143+
public Calendar objValidFrom() {
144+
return this.validFrom;
145+
}
146+
147+
public void setValidTo(Calendar validTo) {
148+
this.validTo = validTo;
149+
}
150+
151+
public String getValidTo() {
152+
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
153+
formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
154+
return formatter.format(validTo.getTime());
155+
}
156+
157+
public Calendar objValidTo() {
158+
return validTo;
159+
}
160+
161+
public void setChargingSchedule(ChargingSchedule chargingSchedule) {
162+
this.chargingSchedule = chargingSchedule;
163+
}
164+
165+
public ChargingSchedule getChargingSchedule() {
166+
return chargingSchedule;
167+
}
168+
}

0 commit comments

Comments
 (0)