package de.rwth.idsg.steve.service;
import de.rwth.idsg.steve.handler.ocpp15.CancelReservationResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.ChangeAvailabilityResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.ChangeConfigurationResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.ClearCacheResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.DataTransferResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.GetConfigurationResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.GetDiagnosticsResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.GetLocalListVersionResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.RemoteStartTransactionResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.RemoteStopTransactionResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.ReserveNowResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.ResetResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.SendLocalListResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.UnlockConnectorResponseHandler;
import de.rwth.idsg.steve.handler.ocpp15.UpdateFirmwareResponseHandler;
import de.rwth.idsg.steve.ocpp.OcppVersion;
import de.rwth.idsg.steve.repository.OcppTagRepository;
import de.rwth.idsg.steve.repository.RequestTaskStore;
import de.rwth.idsg.steve.repository.ReservationRepository;
import de.rwth.idsg.steve.repository.dto.ChargePointSelect;
import de.rwth.idsg.steve.repository.dto.InsertReservationParams;
import de.rwth.idsg.steve.web.dto.common.GetDiagnosticsParams;
import de.rwth.idsg.steve.web.dto.common.MultipleChargePointSelect;
import de.rwth.idsg.steve.web.dto.common.RemoteStartTransactionParams;
import de.rwth.idsg.steve.web.dto.common.RemoteStopTransactionParams;
import de.rwth.idsg.steve.web.dto.common.UnlockConnectorParams;
import de.rwth.idsg.steve.web.dto.common.UpdateFirmwareParams;
import de.rwth.idsg.steve.web.dto.ocpp15.CancelReservationParams;
import de.rwth.idsg.steve.web.dto.ocpp15.ChangeAvailabilityParams;
import de.rwth.idsg.steve.web.dto.ocpp15.ChangeConfigurationParams;
import de.rwth.idsg.steve.web.dto.ocpp15.ConfigurationKeyEnum;
import de.rwth.idsg.steve.web.dto.ocpp15.DataTransferParams;
import de.rwth.idsg.steve.web.dto.ocpp15.GetConfigurationParams;
import de.rwth.idsg.steve.web.dto.ocpp15.ReserveNowParams;
import de.rwth.idsg.steve.web.dto.ocpp15.ResetParams;
import de.rwth.idsg.steve.web.dto.ocpp15.SendLocalListParams;
import de.rwth.idsg.steve.web.dto.task.RequestTask;
import lombok.extern.slf4j.Slf4j;
import ocpp.cp._2012._06.AuthorisationData;
import ocpp.cp._2012._06.CancelReservationRequest;
import ocpp.cp._2012._06.ChangeAvailabilityRequest;
import ocpp.cp._2012._06.ChangeConfigurationRequest;
import ocpp.cp._2012._06.ClearCacheRequest;
import ocpp.cp._2012._06.DataTransferRequest;
import ocpp.cp._2012._06.GetConfigurationRequest;
import ocpp.cp._2012._06.GetDiagnosticsRequest;
import ocpp.cp._2012._06.GetLocalListVersionRequest;
import ocpp.cp._2012._06.RemoteStartTransactionRequest;
import ocpp.cp._2012._06.RemoteStopTransactionRequest;
import ocpp.cp._2012._06.ReserveNowRequest;
import ocpp.cp._2012._06.ResetRequest;
import ocpp.cp._2012._06.SendLocalListRequest;
import ocpp.cp._2012._06.UnlockConnectorRequest;
import ocpp.cp._2012._06.UpdateFirmwareRequest;
import ocpp.cp._2012._06.UpdateType;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static de.rwth.idsg.steve.utils.DateTimeUtils.toDateTime;
/**
* Transport-level agnostic client implementation of OCPP V1.5
* which builds the request payloads and delegates to an invoker.
*
* @author Sevket Goekay <goekay@dbis.rwth-aachen.de>
*/
@Slf4j
@Service
public class ChargePointService15_Client {
private static final OcppVersion VERSION = OcppVersion.V_15;
@Autowired private ScheduledExecutorService executorService;
@Autowired private OcppTagRepository userRepository;
@Autowired private OcppTagService ocppTagService;
@Autowired private ReservationRepository reservationRepository;
@Autowired private RequestTaskStore requestTaskStore;
@Autowired private ChargePointService15_Dispatcher dispatcher;
// -------------------------------------------------------------------------
// Create Request Payloads
// -------------------------------------------------------------------------
private static ChangeAvailabilityRequest prepareChangeAvailability(ChangeAvailabilityParams params) {
return new ChangeAvailabilityRequest()
.withConnectorId(params.getConnectorId())
.withType(params.getAvailType());
}
private static ChangeConfigurationRequest prepareChangeConfiguration(ChangeConfigurationParams params) {
return new ChangeConfigurationRequest()
.withKey(params.getKey())
.withValue(params.getValue());
}
private static ClearCacheRequest prepareClearCache() {
return new ClearCacheRequest();
}
private static GetDiagnosticsRequest prepareGetDiagnostics(GetDiagnosticsParams params) {
return new GetDiagnosticsRequest()
.withLocation(params.getLocation())
.withRetries(params.getRetries())
.withRetryInterval(params.getRetryInterval())
.withStartTime(toDateTime(params.getStart()))
.withStopTime(toDateTime(params.getStop()));
}
private static RemoteStartTransactionRequest prepareRemoteStartTransaction(RemoteStartTransactionParams params) {
return new RemoteStartTransactionRequest()
.withIdTag(params.getIdTag())
.withConnectorId(params.getConnectorId());
}
private static RemoteStopTransactionRequest prepareRemoteStopTransaction(RemoteStopTransactionParams params) {
return new RemoteStopTransactionRequest()
.withTransactionId(params.getTransactionId());
}
private static ResetRequest prepareReset(ResetParams params) {
return new ResetRequest()
.withType(params.getResetType());
}
private static UnlockConnectorRequest prepareUnlockConnector(UnlockConnectorParams params) {
return new UnlockConnectorRequest()
.withConnectorId(params.getConnectorId());
}
private static UpdateFirmwareRequest prepareUpdateFirmware(UpdateFirmwareParams params) {
return new UpdateFirmwareRequest()
.withLocation(params.getLocation())
.withRetrieveDate(toDateTime(params.getRetrieve()))
.withRetries(params.getRetries())
.withRetryInterval(params.getRetryInterval());
}
/**
* Dummy implementation. It must be vendor-specific.
*/
private static DataTransferRequest prepareDataTransfer(DataTransferParams params) {
return new DataTransferRequest()
.withVendorId(params.getVendorId())
.withMessageId(params.getMessageId())
.withData(params.getData());
}
private static GetConfigurationRequest prepareGetConfiguration(GetConfigurationParams params) {
if (params.isSetConfKeyList()) {
List<String> stringList = params.getConfKeyList()
.stream()
.map(ConfigurationKeyEnum::value)
.collect(Collectors.toList());
return new GetConfigurationRequest().withKey(stringList);
} else {
return new GetConfigurationRequest();
}
}
private static GetLocalListVersionRequest prepareGetLocalListVersion() {
return new GetLocalListVersionRequest();
}
private SendLocalListRequest prepareSendLocalList(SendLocalListParams params) {
// DIFFERENTIAL update
if (UpdateType.DIFFERENTIAL.equals(params.getUpdateType())) {
List<AuthorisationData> auths = new ArrayList<>();
// Step 1: For the idTags to be deleted, insert only the idTag
for (String idTag : params.getDeleteList()) {
auths.add(new AuthorisationData().withIdTag(idTag));
}
// Step 2: For the idTags to be added or updated, insert them with their IdTagInfos
auths.addAll(ocppTagService.getAuthData(params.getAddUpdateList()));
return new SendLocalListRequest()
.withListVersion(params.getListVersion())
.withUpdateType(UpdateType.DIFFERENTIAL)
.withLocalAuthorisationList(auths);
// FULL update
} else {
return new SendLocalListRequest()
.withListVersion(params.getListVersion())
.withUpdateType(UpdateType.FULL)
.withLocalAuthorisationList(ocppTagService.getAuthDataOfAllTags());
}
}
private ReserveNowRequest prepareReserveNow(ReserveNowParams params, int reservationId) {
String idTag = params.getIdTag();
return new ReserveNowRequest()
.withConnectorId(params.getConnectorId())
.withReservationId(reservationId)
.withExpiryDate(params.getExpiry().toDateTime())
.withIdTag(idTag)
.withParentIdTag(userRepository.getParentIdtag(idTag));
}
private static CancelReservationRequest prepareCancelReservation(CancelReservationParams params) {
return new CancelReservationRequest()
.withReservationId(params.getReservationId());
}
// -------------------------------------------------------------------------
// Multiple Execution
// -------------------------------------------------------------------------
public int changeAvailability(ChangeAvailabilityParams params) {
ChangeAvailabilityRequest req = prepareChangeAvailability(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<ChangeAvailabilityRequest> task = new RequestTask<>(VERSION, req, list);
execute(list,
c -> dispatcher.changeAvailability(
c, new ChangeAvailabilityResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int changeConfiguration(ChangeConfigurationParams params) {
ChangeConfigurationRequest req = prepareChangeConfiguration(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<ChangeConfigurationRequest> task = new RequestTask<>(VERSION, req, list);
execute(list,
c -> dispatcher.changeConfiguration(
c, new ChangeConfigurationResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int clearCache(MultipleChargePointSelect params) {
ClearCacheRequest req = prepareClearCache();
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<ClearCacheRequest> task = new RequestTask<>(VERSION, req, list);
execute(list,
c -> dispatcher.clearCache(
c, new ClearCacheResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int getDiagnostics(GetDiagnosticsParams params) {
GetDiagnosticsRequest req = prepareGetDiagnostics(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<GetDiagnosticsRequest> task = new RequestTask<>(VERSION, req, list);
execute(list,
c -> dispatcher.getDiagnostics(
c, new GetDiagnosticsResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int reset(ResetParams params) {
ResetRequest req = prepareReset(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<ResetRequest> task = new RequestTask<>(VERSION, req, list);
execute(list,
c -> dispatcher.reset(
c, new ResetResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int updateFirmware(UpdateFirmwareParams params) {
UpdateFirmwareRequest req = prepareUpdateFirmware(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<UpdateFirmwareRequest> task = new RequestTask<>(VERSION, req, list);
execute(list,
c -> dispatcher.updateFirmware(
c, new UpdateFirmwareResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int dataTransfer(DataTransferParams params) {
DataTransferRequest req = prepareDataTransfer(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<DataTransferRequest> task = new RequestTask<>(VERSION, req, list);
execute(list,
c -> dispatcher.dataTransfer(
c, new DataTransferResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int getConfiguration(GetConfigurationParams params) {
GetConfigurationRequest req = prepareGetConfiguration(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<GetConfigurationRequest> task = new RequestTask<>(VERSION, req, list);
execute(list,
c -> dispatcher.getConfiguration(
c, new GetConfigurationResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int getLocalListVersion(MultipleChargePointSelect params) {
GetLocalListVersionRequest req = prepareGetLocalListVersion();
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<GetLocalListVersionRequest> task = new RequestTask<>(VERSION, req, list);
execute(list,
c -> dispatcher.getLocalListVersion(
c, new GetLocalListVersionResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int sendLocalList(SendLocalListParams params) {
SendLocalListRequest req = prepareSendLocalList(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<SendLocalListRequest> task = new RequestTask<>(VERSION, req, list);
execute(list,
c -> dispatcher.sendLocalList(
c, new SendLocalListResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
/**
* Executes the requests
*/
private void execute(List<ChargePointSelect> list, Consumer<ChargePointSelect> consumer) {
executorService.execute(() -> list.forEach(consumer));
}
// -------------------------------------------------------------------------
// Single Execution
// -------------------------------------------------------------------------
public int remoteStartTransaction(RemoteStartTransactionParams params) {
RemoteStartTransactionRequest req = prepareRemoteStartTransaction(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<RemoteStartTransactionRequest> task = new RequestTask<>(VERSION, req, list);
ChargePointSelect c = list.get(0);
execute(() -> dispatcher.remoteStartTransaction(
c, new RemoteStartTransactionResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int remoteStopTransaction(RemoteStopTransactionParams params) {
RemoteStopTransactionRequest req = prepareRemoteStopTransaction(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<RemoteStopTransactionRequest> task = new RequestTask<>(VERSION, req, list);
ChargePointSelect c = list.get(0);
execute(() -> dispatcher.remoteStopTransaction(
c, new RemoteStopTransactionResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int unlockConnector(UnlockConnectorParams params) {
UnlockConnectorRequest req = prepareUnlockConnector(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<UnlockConnectorRequest> task = new RequestTask<>(VERSION, req, list);
ChargePointSelect c = list.get(0);
execute(() -> dispatcher.unlockConnector(
c, new UnlockConnectorResponseHandler(task, c.getChargeBoxId())));
return requestTaskStore.add(task);
}
public int reserveNow(ReserveNowParams params) {
List<ChargePointSelect> list = params.getChargePointSelectList();
ChargePointSelect c = list.get(0);
String chargeBoxId = c.getChargeBoxId();
InsertReservationParams res = InsertReservationParams.builder()
.idTag(params.getIdTag())
.chargeBoxId(chargeBoxId)
.connectorId(params.getConnectorId())
.startTimestamp(DateTime.now())
.expiryTimestamp(params.getExpiry().toDateTime())
.build();
int reservationId = reservationRepository.insert(res);
ReserveNowRequest req = this.prepareReserveNow(params, reservationId);
RequestTask<ReserveNowRequest> task = new RequestTask<>(VERSION, req, list);
execute(() -> dispatcher.reserveNow(
c, new ReserveNowResponseHandler(task, chargeBoxId, reservationRepository)));
return requestTaskStore.add(task);
}
public int cancelReservation(CancelReservationParams params) {
CancelReservationRequest req = prepareCancelReservation(params);
List<ChargePointSelect> list = params.getChargePointSelectList();
RequestTask<CancelReservationRequest> task = new RequestTask<>(VERSION, req, list);
ChargePointSelect c = list.get(0);
execute(() -> dispatcher.cancelReservation(
c, new CancelReservationResponseHandler(task, c.getChargeBoxId(), reservationRepository)));
return requestTaskStore.add(task);
}
/**
* Executes the requests for single charge point invocation
*/
private void execute(Runnable r) {
executorService.execute(r);
}
}