package de.rwth.idsg.steve.service;
import de.rwth.idsg.steve.ocpp.OcppProtocol;
import de.rwth.idsg.steve.ocpp.OcppTransport;
import de.rwth.idsg.steve.ocpp.OcppVersion;
import de.rwth.idsg.steve.ocpp.ws.data.SessionContext;
import de.rwth.idsg.steve.ocpp.ws.ocpp12.Ocpp12WebSocketEndpoint;
import de.rwth.idsg.steve.ocpp.ws.ocpp15.Ocpp15WebSocketEndpoint;
import de.rwth.idsg.steve.repository.ChargePointRepository;
import de.rwth.idsg.steve.repository.GenericRepository;
import de.rwth.idsg.steve.repository.dto.ChargePointSelect;
import de.rwth.idsg.steve.repository.dto.ConnectorStatus;
import de.rwth.idsg.steve.utils.ConnectorStatusCountFilter;
import de.rwth.idsg.steve.utils.DateTimeUtils;
import de.rwth.idsg.steve.web.dto.OcppJsonStatus;
import de.rwth.idsg.steve.web.dto.Statistics;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.Map;
/**
* @author Sevket Goekay <goekay@dbis.rwth-aachen.de>
* @since 24.03.2015
*/
@Service
public class ChargePointHelperServiceImpl implements ChargePointHelperService {
@Autowired private GenericRepository genericRepository;
// SOAP-based charge points are stored in DB with an endpoint address
@Autowired private ChargePointRepository chargePointRepository;
// For WebSocket-based charge points, the active sessions are stored in memory
@Autowired private Ocpp12WebSocketEndpoint ocpp12WebSocketEndpoint;
@Autowired private Ocpp15WebSocketEndpoint ocpp15WebSocketEndpoint;
@Override
public Statistics getStats() {
Statistics stats = genericRepository.getStats();
stats.setNumOcpp12JChargeBoxes(ocpp12WebSocketEndpoint.getNumberOfChargeBoxes());
stats.setNumOcpp15JChargeBoxes(ocpp15WebSocketEndpoint.getNumberOfChargeBoxes());
List<ConnectorStatus> latestList = chargePointRepository.getChargePointConnectorStatus();
stats.setStatusCountMap(ConnectorStatusCountFilter.getStatusCountMap(latestList));
return stats;
}
@Override
public List<OcppJsonStatus> getOcppJsonStatus() {
Map<String, Deque<SessionContext>> ocpp12Map = ocpp12WebSocketEndpoint.getACopy();
Map<String, Deque<SessionContext>> ocpp15Map = ocpp15WebSocketEndpoint.getACopy();
Map<String, Integer> primaryKeyLookup = getPrimaryKeyLookup(ocpp12Map, ocpp15Map);
DateTime now = DateTime.now();
List<OcppJsonStatus> returnList = new ArrayList<>();
appendList(ocpp12Map, returnList, now, OcppVersion.V_12, primaryKeyLookup);
appendList(ocpp15Map, returnList, now, OcppVersion.V_15, primaryKeyLookup);
return returnList;
}
@Override
public List<ChargePointSelect> getChargePointsV12() {
List<ChargePointSelect> returnList = chargePointRepository.getChargePointSelect(OcppProtocol.V_12_SOAP);
for (String chargeBoxId : ocpp12WebSocketEndpoint.getChargeBoxIdList()) {
returnList.add(new ChargePointSelect(OcppTransport.JSON, chargeBoxId));
}
return returnList;
}
@Override
public List<ChargePointSelect> getChargePointsV15() {
List<ChargePointSelect> returnList = chargePointRepository.getChargePointSelect(OcppProtocol.V_15_SOAP);
for (String chargeBoxId : ocpp15WebSocketEndpoint.getChargeBoxIdList()) {
returnList.add(new ChargePointSelect(OcppTransport.JSON, chargeBoxId));
}
return returnList;
}
// -------------------------------------------------------------------------
// Helpers
// -------------------------------------------------------------------------
private Map<String, Integer> getPrimaryKeyLookup(Map<String, Deque<SessionContext>> ocpp12Map,
Map<String, Deque<SessionContext>> ocpp15Map) {
ArrayList<String> idList = new ArrayList<>(ocpp12Map.keySet());
idList.addAll(ocpp15Map.keySet());
return chargePointRepository.getChargeBoxIdPkPair(idList);
}
private static void appendList(Map<String, Deque<SessionContext>> map, List<OcppJsonStatus> returnList,
DateTime now, OcppVersion version, Map<String, Integer> primaryKeyLookup) {
for (Map.Entry<String, Deque<SessionContext>> entry : map.entrySet()) {
String chargeBoxId = entry.getKey();
Deque<SessionContext> endpointDeque = entry.getValue();
for (SessionContext ctx : endpointDeque) {
DateTime openSince = ctx.getOpenSince();
OcppJsonStatus status = OcppJsonStatus.builder()
.chargeBoxPk(primaryKeyLookup.get(chargeBoxId))
.chargeBoxId(chargeBoxId)
.connectedSinceDT(openSince)
.connectedSince(DateTimeUtils.humanize(openSince))
.connectionDuration(DateTimeUtils.timeElapsed(openSince, now))
.version(version)
.build();
returnList.add(status);
}
}
}
}