From a1875e1f06b8944b21b335947652cc5775853886 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 9 Jan 2025 14:02:29 +0100 Subject: [PATCH 1/4] Enhancing and refactoring `ExtCoSimulation`. --- CHANGELOG.md | 4 + .../ExtInputDataConnectionWithMapping.java | 86 +++++++++++++++++ .../api/data/em/ExtEmDataConnection.java | 62 ++++-------- .../primarydata/ExtPrimaryDataConnection.java | 62 ++++-------- .../api/simulation/ExtCoSimulation.java | 96 +++++++++++++------ .../data/em/ExtEmDataConnectionTest.groovy | 2 +- .../ExtPrimaryDataConnectionTest.groovy | 2 +- .../api/simulation/ExtCoSimulationTest.groovy | 10 +- 8 files changed, 201 insertions(+), 123 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 841c859a..97957fea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Bao and Staudt to the list of reviewers [#216](https://github.com/ie3-institute/simonaAPI/issues/216) - Documentation for this API [#230](https://github.com/ie3-institute/simonaAPI/issues/230) + +### Changed +- Refactoring `ExtCoSimulation` [#237](https://github.com/ie3-institute/simonaAPI/issues/237) + ## [0.6.0] - 2024-12-02 ### Added diff --git a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java new file mode 100644 index 00000000..12781b0b --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java @@ -0,0 +1,86 @@ +/* + * © 2025. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.api.data; + +import edu.ie3.datamodel.models.value.Value; +import edu.ie3.simona.api.data.ontology.DataMessageFromExt; +import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; +import java.util.*; +import org.apache.pekko.actor.ActorRef; +import org.slf4j.Logger; + +public abstract class ExtInputDataConnectionWithMapping< + M extends DataMessageFromExt, V extends Value> + implements ExtInputDataConnection { + + /** Actor reference to service that handles data within SIMONA */ + private ActorRef dataService; + + /** Actor reference to adapter that handles scheduler control flow in SIMONA */ + private ActorRef extSimAdapter; + + /** Assets that provide data to SIMONA */ + private final Map extDataMapping; + + protected ExtInputDataConnectionWithMapping(Map extDataMapping) { + this.extDataMapping = extDataMapping; + } + + @Override + public void setActorRefs(ActorRef dataService, ActorRef extSimAdapter) { + this.dataService = dataService; + this.extSimAdapter = extSimAdapter; + } + + /** + * Converts the data and sends them to SIMONA. + * + * @param tick current tick + * @param data to be converted and send + * @param maybeNextTick option for the next tick in the simulation + * @param log logger + */ + public abstract void convertAndSend( + long tick, Map data, Optional maybeNextTick, Logger log); + + /** Provide data from an external simulation for one tick. */ + public abstract void provideData(long tick, Map data, Optional maybeNextTick); + + /** + * Send information from the external simulation to SIMONA's external primary data service. + * Furthermore, ExtSimAdapter within SIMONA is instructed to activate the ev data service with the + * current tick. + * + * @param msg the data/information that is sent to SIMONA's external primary data service + */ + public void sendExtMsg(M msg) { + dataService.tell(msg, ActorRef.noSender()); + // we need to schedule data receiver activation with scheduler + extSimAdapter.tell(new ScheduleDataServiceMessage(dataService), ActorRef.noSender()); + } + + /** Returns a list of the uuids of the assets that expect external data */ + protected List getDataAssets() { + return extDataMapping.values().stream().toList(); + } + + /** + * Method to remap the data from the externally used {@link String} to {@link UUID} used by + * SIMONA. + * + * @param inputMap map: string to value + * @return map: uuid to value + */ + @SuppressWarnings("unchecked") + protected Map convert(Map inputMap) { + Map valueMap = new HashMap<>(); + inputMap.entrySet().stream() + .filter(e -> extDataMapping.containsKey(e.getKey())) + .forEach(e -> valueMap.put(extDataMapping.get(e.getKey()), (V) e.getValue())); + return valueMap; + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/em/ExtEmDataConnection.java index 5a0bbaa6..ad1a801b 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ExtEmDataConnection.java @@ -8,74 +8,48 @@ import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; -import edu.ie3.simona.api.data.ExtInputDataConnection; +import edu.ie3.simona.api.data.ExtInputDataConnectionWithMapping; import edu.ie3.simona.api.data.em.ontology.EmDataMessageFromExt; import edu.ie3.simona.api.data.em.ontology.ProvideEmSetPointData; -import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; import java.util.*; -import java.util.stream.Collectors; -import org.apache.pekko.actor.ActorRef; import org.slf4j.Logger; /** Enables data connection of em data between SIMONA and SimonaAPI */ -public class ExtEmDataConnection implements ExtInputDataConnection { - - /** Actor reference to service that handles ev data within SIMONA */ - private ActorRef emDataService; - - /** Actor reference to adapter that handles scheduler control flow in SIMONA */ - private ActorRef extSimAdapter; - - /** Assets that provide primary data to SIMONA */ - private final Map extEmMapping; +public class ExtEmDataConnection + extends ExtInputDataConnectionWithMapping { public ExtEmDataConnection(Map extEmMapping) { - this.extEmMapping = extEmMapping; + super(extEmMapping); } - @Override - public void setActorRefs(ActorRef emDataService, ActorRef extSimAdapter) { - this.emDataService = emDataService; - this.extSimAdapter = extSimAdapter; + /** Returns a list of the uuids of the em agents that expect external set points */ + public List getControlledEms() { + return getDataAssets(); } + /** + * Converts the data and sends them to SIMONA. + * + * @param tick current tick + * @param data to be converted and send + * @param maybeNextTick option for the next tick in the simulation + * @param log logger + */ public void convertAndSend( long tick, Map data, Optional maybeNextTick, Logger log) { // filtering the data and converting the keys - Map convertedMap = - data.entrySet().stream() - .filter(e -> extEmMapping.containsKey(e.getKey())) - .collect( - Collectors.toMap(e -> extEmMapping.get(e.getKey()), e -> (PValue) e.getValue())); + Map convertedMap = convert(data); if (convertedMap.isEmpty()) { log.warn("No em data found! Sending no em data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with em data."); - provideEmData(tick, convertedMap, maybeNextTick); + provideData(tick, convertedMap, maybeNextTick); } } - /** Returns a list of the uuids of the em agents that expect external set points */ - public List getControlledEms() { - return extEmMapping.values().stream().toList(); - } - /** Provide primary data from an external simulation for one tick. */ - public void provideEmData(Long tick, Map emData, Optional maybeNextTick) { + public void provideData(long tick, Map emData, Optional maybeNextTick) { sendExtMsg(new ProvideEmSetPointData(tick, emData, maybeNextTick)); } - - /** - * Send information from the external simulation to SIMONA's external primary data service. - * Furthermore, ExtSimAdapter within SIMONA is instructed to activate the ev data service with the - * current tick. - * - * @param msg the data/information that is sent to SIMONA's external primary data service - */ - public void sendExtMsg(EmDataMessageFromExt msg) { - emDataService.tell(msg, ActorRef.noSender()); - // we need to schedule data receiver activation with scheduler - extSimAdapter.tell(new ScheduleDataServiceMessage(emDataService), ActorRef.noSender()); - } } diff --git a/src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java b/src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java index 10fe1842..969cead3 100644 --- a/src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java @@ -7,75 +7,45 @@ package edu.ie3.simona.api.data.primarydata; import edu.ie3.datamodel.models.value.Value; -import edu.ie3.simona.api.data.ExtInputDataConnection; -import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; +import edu.ie3.simona.api.data.ExtInputDataConnectionWithMapping; import edu.ie3.simona.api.data.primarydata.ontology.PrimaryDataMessageFromExt; import edu.ie3.simona.api.data.primarydata.ontology.ProvidePrimaryData; -import java.util.*; -import java.util.stream.Collectors; -import org.apache.pekko.actor.ActorRef; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; import org.slf4j.Logger; /** Enables data connection of primary data between SIMONA and SimonaAPI */ -public class ExtPrimaryDataConnection implements ExtInputDataConnection { - - /** Actor reference to service that handles primary data within SIMONA */ - private ActorRef dataService; - - /** Actor reference to adapter that handles scheduler control flow in SIMONA */ - private ActorRef extSimAdapter; - - /** Assets that provide primary data to SIMONA */ - private final Map extPrimaryDataMapping; +public class ExtPrimaryDataConnection + extends ExtInputDataConnectionWithMapping { public ExtPrimaryDataConnection(Map extPrimaryDataMapping) { - this.extPrimaryDataMapping = extPrimaryDataMapping; + super(extPrimaryDataMapping); } - @Override - public void setActorRefs(ActorRef dataService, ActorRef extSimAdapter) { - this.dataService = dataService; - this.extSimAdapter = extSimAdapter; + /** Returns a list of the uuids of the system participants that expect external primary data */ + public List getPrimaryDataAssets() { + return getDataAssets(); } + @Override public void convertAndSend( long tick, Map data, Optional maybeNextTick, Logger log) { // filtering the data and converting the keys - Map convertedMap = - data.entrySet().stream() - .filter(e -> extPrimaryDataMapping.containsKey(e.getKey())) - .collect( - Collectors.toMap(e -> extPrimaryDataMapping.get(e.getKey()), Map.Entry::getValue)); + Map convertedMap = convert(data); if (convertedMap.isEmpty()) { log.warn("No primary data found! Sending no primary data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with primary data."); - providePrimaryData(tick, convertedMap, maybeNextTick); + provideData(tick, convertedMap, maybeNextTick); } } - /** Returns a list of the uuids of the system participants that expect external primary data */ - public List getPrimaryDataAssets() { - return extPrimaryDataMapping.values().stream().toList(); - } - /** Provide primary data from an external simulation in one tick. */ - public void providePrimaryData( - Long tick, Map primaryData, Optional maybeNextTick) { + @Override + public void provideData(long tick, Map primaryData, Optional maybeNextTick) { sendExtMsg(new ProvidePrimaryData(tick, primaryData, maybeNextTick)); } - - /** - * Send information from the external simulation to SIMONA's external primary data service. - * Furthermore, ExtSimAdapter within SIMONA is instructed to activate the ev data service with the - * current tick. - * - * @param msg the data/information that is sent to SIMONA's external primary data service - */ - public void sendExtMsg(PrimaryDataMessageFromExt msg) { - dataService.tell(msg, ActorRef.noSender()); - // we need to schedule data receiver activation with scheduler - extSimAdapter.tell(new ScheduleDataServiceMessage(dataService), ActorRef.noSender()); - } } diff --git a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java index f07ec9bd..1aba5c79 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -9,6 +9,8 @@ import edu.ie3.datamodel.models.result.ModelResultEntity; import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.DataQueueExtSimulationExtSimulator; +import edu.ie3.simona.api.data.ExtDataConnection; +import edu.ie3.simona.api.data.ExtInputDataConnectionWithMapping; import edu.ie3.simona.api.data.ExtInputDataContainer; import edu.ie3.simona.api.data.em.ExtEmDataConnection; import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; @@ -16,15 +18,16 @@ import edu.ie3.simona.api.data.results.ExtResultDataConnection; import edu.ie3.simona.api.simulation.mapping.DataType; import edu.ie3.simona.api.simulation.mapping.ExtEntityMapping; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; +import java.util.stream.Collectors; import org.slf4j.Logger; /** * Abstract class for an external co-simulation with the structure: external api - ext-co-simulation - * - extsimulation - simonaAPI - simona It contains all function to transfer primary data and em - * data to SIMONA and results to the external co-simulation. + * - ext-simulation - simonaAPI - simona + * + *

It contains all function to transfer primary data and em data to SIMONA and results to the + * external co-simulation. */ public abstract class ExtCoSimulation extends ExtSimulation { @@ -46,26 +49,32 @@ protected ExtCoSimulation(String simulationName, String extSimulatorName) { this.dataQueueSimonaApiToExtCoSimulator = new DataQueueExtSimulationExtSimulator<>(); } + @SafeVarargs + protected static Set flat(Optional... optionals) { + return Arrays.stream(optionals) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toSet()); + } + /** * Builds an {@link ExtPrimaryDataConnection}. * * @param mapping between the external simulation and SIMONA. * @param log logger - * @return an ext primary data connection + * @return an option for an ext primary data connection */ - protected static ExtPrimaryDataConnection buildPrimaryConnection( + public static Optional buildPrimaryConnection( ExtEntityMapping mapping, Logger log) { Map primaryMapping = mapping.getExtId2UuidMapping(DataType.EXT_PRIMARY_INPUT); - ExtPrimaryDataConnection extPrimaryDataConnection = - new ExtPrimaryDataConnection(primaryMapping); if (primaryMapping.isEmpty()) { - log.warn("Primary with 0 entities created."); + log.warn("No primary data connection was created."); + return Optional.empty(); } else { - log.info("Primary connection with {} entities created.", primaryMapping.size()); + log.info("Primary data connection with {} entities created.", primaryMapping.size()); + return Optional.of(new ExtPrimaryDataConnection(primaryMapping)); } - - return extPrimaryDataConnection; } /** @@ -73,19 +82,19 @@ protected static ExtPrimaryDataConnection buildPrimaryConnection( * * @param mapping between the external simulation and SIMONA. * @param log logger - * @return an ext em data connection + * @return an option for an ext em data connection */ - protected static ExtEmDataConnection buildEmConnection(ExtEntityMapping mapping, Logger log) { + public static Optional buildEmConnection( + ExtEntityMapping mapping, Logger log) { Map emMapping = mapping.getExtId2UuidMapping(DataType.EXT_EM_INPUT); - ExtEmDataConnection extEmDataConnection = new ExtEmDataConnection(emMapping); if (emMapping.isEmpty()) { - log.warn("Em connection with 0 entities created."); + log.warn("No em data connection was created."); + return Optional.empty(); } else { - log.info("Em connection with {} entities created.", emMapping.size()); + log.info("Em data connection with {} entities created.", emMapping.size()); + return Optional.of(new ExtEmDataConnection(emMapping)); } - - return extEmDataConnection; } /** @@ -93,26 +102,24 @@ protected static ExtEmDataConnection buildEmConnection(ExtEntityMapping mapping, * * @param mapping between the external simulation and SIMONA. * @param log logger - * @return an ext result data connection + * @return an option for an ext result data connection */ - protected static ExtResultDataConnection buildResultConnection( + public static Optional buildResultConnection( ExtEntityMapping mapping, Logger log) { Map resultParticipantMapping = mapping.getExtUuid2IdMapping(DataType.EXT_PARTICIPANT_RESULT); Map resultGridMapping = mapping.getExtUuid2IdMapping(DataType.EXT_GRID_RESULT); - ExtResultDataConnection extResultDataConnection = - new ExtResultDataConnection(resultParticipantMapping, resultGridMapping); if (resultParticipantMapping.isEmpty() && resultGridMapping.isEmpty()) { - log.warn("Result connection with 0 participants and 0 grid assets created."); + log.warn("No result connection was created."); + return Optional.empty(); } else { log.info( "Result connection with {} participants and {} grid assets created.", resultParticipantMapping.size(), resultGridMapping.size()); + return Optional.of(new ExtResultDataConnection(resultParticipantMapping, resultGridMapping)); } - - return extResultDataConnection; } /** @@ -157,6 +164,41 @@ protected void sendEmDataToSimona( log.debug("Provided EmData to SIMONA!"); } + /** + * Function to send external data to SIMONA using {@link ExtInputDataConnectionWithMapping}s. This + * method will automatically take the next {@link ExtInputDataContainer} from the queue. + * + * @param dataConnections the connections to SIMONA + * @param log logger + */ + protected void sendDataToSIMONA( + Set> dataConnections, Logger log) + throws InterruptedException { + sendDataToSIMONA(dataConnections, dataQueueExtCoSimulatorToSimonaApi.takeData(), log); + } + + /** + * Function to send external data to SIMONA using {@link ExtInputDataConnectionWithMapping}s. + * + * @param dataConnections the connections to SIMONA + * @param dataContainer contains all necessary inormation + * @param log logger + */ + protected void sendDataToSIMONA( + Set> dataConnections, + ExtInputDataContainer dataContainer, + Logger log) { + log.debug("Received data from {}", extSimulatorName); + + Map data = dataContainer.getSimonaInputMap(); + long tick = dataContainer.getTick(); + Optional maybeNextTick = dataContainer.getMaybeNextTick(); + + dataConnections.forEach(con -> con.convertAndSend(tick, data, maybeNextTick, log)); + + log.debug("Provided all data from {} to SIMONA", extSimulatorName); + } + /** * Function to get result data from SIMONA using the available {@link ExtResultDataConnection} * diff --git a/src/test/groovy/edu/ie3/simona/api/data/em/ExtEmDataConnectionTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/em/ExtEmDataConnectionTest.groovy index d8f798f5..29a3ae2d 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/em/ExtEmDataConnectionTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/em/ExtEmDataConnectionTest.groovy @@ -51,7 +51,7 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa def convertedEmData = Map.of(uuid, pValue as PValue) when: - extEmDataConnection.provideEmData(0L, convertedEmData, Optional.of(900L)) + extEmDataConnection.provideData(0L, convertedEmData, Optional.of(900L)) then: dataService.expectMsg(new ProvideEmSetPointData(0, convertedEmData, Optional.of(900L))) diff --git a/src/test/groovy/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnectionTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnectionTest.groovy index 5aba77d4..93031445 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnectionTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnectionTest.groovy @@ -47,7 +47,7 @@ class ExtPrimaryDataConnectionTest extends Specification implements DataServiceT def convertedPrimaryData = Map.of(uuid, pValue as Value) when: - extPrimaryDataConnection.providePrimaryData(0L, convertedPrimaryData, Optional.of(900L)) + extPrimaryDataConnection.provideData(0L, convertedPrimaryData, Optional.of(900L)) then: dataService.expectMsg(new ProvidePrimaryData(0L, convertedPrimaryData, Optional.of(900L))) diff --git a/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy b/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy index 2903384c..ac92fce8 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy @@ -30,7 +30,7 @@ class ExtCoSimulationTest extends Specification { def actual = ExtCoSimulation.buildPrimaryConnection(mapping, log) then: - actual.getPrimaryDataAssets() == [uuid3, uuid1] + actual.get().primaryDataAssets == [uuid3, uuid1] } def "An ExtCoSimulation can build an em data connection correctly"() { @@ -49,7 +49,7 @@ class ExtCoSimulationTest extends Specification { def actual = ExtCoSimulation.buildEmConnection(mapping, log) then: - actual.getControlledEms() == [uuid1, uuid2] + actual.get().controlledEms == [uuid1, uuid2] } def "An ExtCoSimulation can build a result data connection correctly"() { @@ -68,7 +68,9 @@ class ExtCoSimulationTest extends Specification { def actual = ExtCoSimulation.buildResultConnection(mapping, log) then: - actual.getGridResultDataAssets() == [uuid1] - actual.getParticipantResultDataAssets() == [uuid2] + actual.isPresent() + + actual.get().gridResultDataAssets == [uuid1] + actual.get().participantResultDataAssets == [uuid2] } } From 2b64fa541b45f4397f2542cfe1ee6c1ec5b6e675 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 21 Jan 2025 11:22:06 +0100 Subject: [PATCH 2/4] Enhancing API. --- .../api/data/results/ExtResultContainer.java | 34 ++++++- .../data/results/ExtResultDataConnection.java | 44 ++++++++- .../ontology/RequestResultEntities.java | 8 +- .../api/simulation/ExtCoSimulation.java | 94 ++++++++++++++----- .../api/simulation/mapping/DataType.java | 4 +- .../simulation/mapping/ExtEntityEntry.java | 12 ++- .../simulation/mapping/ExtEntityFactory.java | 3 +- .../data/em/ExtEmDataConnectionTest.groovy | 3 - 8 files changed, 163 insertions(+), 39 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java index 531faf7c..8c73b6c2 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java @@ -10,6 +10,7 @@ import edu.ie3.datamodel.models.result.ModelResultEntity; import edu.ie3.datamodel.models.result.NodeResult; +import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.result.connector.LineResult; import edu.ie3.datamodel.models.result.system.SystemParticipantResult; import edu.ie3.simona.api.data.ExtDataContainer; @@ -56,6 +57,8 @@ public Map getResults() { return simonaResultsMap; } + public String getResultsAsString() { return resultMapToString(simonaResultsMap); } + public Long getTick() { return tick; } @@ -65,7 +68,14 @@ public Optional getNextTick() { } /** - * Returns the voltage deviation for certain asset, if this asset provided a {@link NodeResult} + * Returns the result for a certain asset. + */ + public ResultEntity getResult(String assetId) { + return simonaResultsMap.get(assetId); + } + + /** + * Returns the voltage deviation in pu for certain asset, if this asset provided a {@link NodeResult} */ public double getVoltageDeviation(String assetId) { if (simonaResultsMap.get(assetId) instanceof NodeResult nodeResult) { @@ -77,6 +87,17 @@ public double getVoltageDeviation(String assetId) { } } + /** + * Returns the voltage deviation for certain asset, if this asset provided a {@link NodeResult} + */ + public double getVoltage(String assetId) { + if (simonaResultsMap.get(assetId) instanceof NodeResult nodeResult) { + return nodeResult.getvMag().getValue().doubleValue(); + } else { + throw new IllegalArgumentException("VOLTAGE is only available for NodeResult's!"); + } + } + /** * Returns the active power in kW for certain asset, if this asset provided a {@link * SystemParticipantResult} @@ -107,4 +128,15 @@ public double getReactivePower(String assetId) { public double getLineLoading(String assetId) { throw new IllegalArgumentException("LINE LOADING is not implemented yet!"); } + + + private String resultMapToString( + Map results + ) { + StringBuilder resultString = new StringBuilder(); + for (String key : results.keySet()) { + resultString.append("id = ").append(key).append(", time = ").append(results.get(key).getTime()).append(", result = ").append(results.get(key).getClass().getSimpleName()).append("\n"); + } + return resultString.toString(); + } } diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java b/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java index de90fa41..1c9ee27c 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java @@ -8,6 +8,7 @@ import edu.ie3.datamodel.models.result.ModelResultEntity; import edu.ie3.datamodel.models.result.NodeResult; +import edu.ie3.datamodel.models.result.system.FlexOptionsResult; import edu.ie3.datamodel.models.result.system.SystemParticipantResult; import edu.ie3.simona.api.data.ExtOutputDataConnection; import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; @@ -20,6 +21,8 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.LinkedBlockingQueue; +import java.util.stream.Stream; + import org.apache.pekko.actor.ActorRef; /** Enables data connection of results between SIMONA and SimonaAPI */ @@ -44,10 +47,17 @@ public class ExtResultDataConnection implements ExtOutputDataConnection { /** Map uuid to external id of system participants */ private final Map participantResultAssetMapping; + /** Map uuid to external id of participant flex options */ + private final Map flexOptionsMapping; + public ExtResultDataConnection( - Map participantResultAssetMapping, Map gridResultAssetMapping) { + Map participantResultAssetMapping, + Map gridResultAssetMapping, + Map flexOptionsMapping + ) { this.participantResultAssetMapping = participantResultAssetMapping; this.gridResultAssetMapping = gridResultAssetMapping; + this.flexOptionsMapping = flexOptionsMapping; } /** @@ -73,9 +83,24 @@ public List getParticipantResultDataAssets() { return participantResultAssetMapping.keySet().stream().toList(); } + public List getFlexOptionAssets() { + return flexOptionsMapping.keySet().stream().toList(); + } + /** Method that an external simulation can request results from SIMONA as a list. */ private List requestResultList(long tick) throws InterruptedException { - sendExtMsg(new RequestResultEntities(tick)); + List allExtEntities = Stream.concat(Stream.concat(getFlexOptionAssets().stream(), getGridResultDataAssets().stream()), getParticipantResultDataAssets().stream()).toList(); + sendExtMsg(new RequestResultEntities(tick, allExtEntities)); + return receiveWithType(ProvideResultEntities.class).results(); + } + + private List requestFlexOptionResultsList(long tick) throws InterruptedException { + sendExtMsg(new RequestResultEntities(tick, getFlexOptionAssets())); + return receiveWithType(ProvideResultEntities.class).results(); + } + + private List requestGridResultsList(long tick) throws InterruptedException { + sendExtMsg(new RequestResultEntities(tick, getGridResultDataAssets())); return receiveWithType(ProvideResultEntities.class).results(); } @@ -86,6 +111,14 @@ public Map requestResults(long tick) throws Interrupt return createResultMap(requestResultList(tick)); } + public Map requestFlexOptionResults(long tick) throws InterruptedException { + return createResultMap(requestFlexOptionResultsList(tick)); + } + + public Map requestGridResults(long tick) throws InterruptedException { + return createResultMap(requestGridResultsList(tick)); + } + protected Map createResultMap(List results) { Map resultMap = new HashMap<>(); results.forEach( @@ -96,9 +129,14 @@ protected Map createResultMap(List resultMap.put( participantResultAssetMapping.get(systemParticipantResult.getInputModel()), systemParticipantResult); + } else if (result instanceof FlexOptionsResult flexOptionsResult) { + resultMap.put( + flexOptionsMapping.get(flexOptionsResult.getInputModel()), + flexOptionsResult + ); } else { throw new IllegalArgumentException( - "ExtResultData can only handle NodeResult's and SystemParticipantResult's!"); + "ExtResultData can only handle NodeResult's, FlexOptionResult's and SystemParticipantResult's!"); } }); return resultMap; diff --git a/src/main/java/edu/ie3/simona/api/data/results/ontology/RequestResultEntities.java b/src/main/java/edu/ie3/simona/api/data/results/ontology/RequestResultEntities.java index 8ef656b0..021d2cfd 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ontology/RequestResultEntities.java +++ b/src/main/java/edu/ie3/simona/api/data/results/ontology/RequestResultEntities.java @@ -6,5 +6,11 @@ package edu.ie3.simona.api.data.results.ontology; +import java.util.List; +import java.util.UUID; + /** Request calculated results from SIMONA in the current tick */ -public record RequestResultEntities(Long tick) implements ResultDataMessageFromExt {} +public record RequestResultEntities( + Long tick, + List requestedResults +) implements ResultDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java index 1aba5c79..4fb60fbb 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -50,7 +50,7 @@ protected ExtCoSimulation(String simulationName, String extSimulatorName) { } @SafeVarargs - protected static Set flat(Optional... optionals) { + protected static Set toSet(Optional... optionals) { return Arrays.stream(optionals) .filter(Optional::isPresent) .map(Optional::get) @@ -109,6 +109,7 @@ public static Optional buildResultConnection( Map resultParticipantMapping = mapping.getExtUuid2IdMapping(DataType.EXT_PARTICIPANT_RESULT); Map resultGridMapping = mapping.getExtUuid2IdMapping(DataType.EXT_GRID_RESULT); + Map resultFlexOptionsMapping = mapping.getExtUuid2IdMapping(DataType.EXT_FLEX_OPTIONS_RESULT); if (resultParticipantMapping.isEmpty() && resultGridMapping.isEmpty()) { log.warn("No result connection was created."); @@ -118,7 +119,13 @@ public static Optional buildResultConnection( "Result connection with {} participants and {} grid assets created.", resultParticipantMapping.size(), resultGridMapping.size()); - return Optional.of(new ExtResultDataConnection(resultParticipantMapping, resultGridMapping)); + return Optional.of( + new ExtResultDataConnection( + resultParticipantMapping, + resultGridMapping, + resultFlexOptionsMapping + ) + ); } } @@ -165,50 +172,81 @@ protected void sendEmDataToSimona( } /** - * Function to send external data to SIMONA using {@link ExtInputDataConnectionWithMapping}s. This + * Function to send all external data to SIMONA using {@link ExtInputDataConnectionWithMapping}s. This * method will automatically take the next {@link ExtInputDataContainer} from the queue. * * @param dataConnections the connections to SIMONA * @param log logger + * @return an option for the next tick simona expects data */ - protected void sendDataToSIMONA( - Set> dataConnections, Logger log) + protected Optional sendDataToSIMONA( + Set>> dataConnections, + Logger log) throws InterruptedException { - sendDataToSIMONA(dataConnections, dataQueueExtCoSimulatorToSimonaApi.takeData(), log); - } - - /** - * Function to send external data to SIMONA using {@link ExtInputDataConnectionWithMapping}s. - * - * @param dataConnections the connections to SIMONA - * @param dataContainer contains all necessary inormation - * @param log logger - */ - protected void sendDataToSIMONA( - Set> dataConnections, - ExtInputDataContainer dataContainer, - Logger log) { log.debug("Received data from {}", extSimulatorName); + ExtInputDataContainer dataContainer = dataQueueExtCoSimulatorToSimonaApi.takeData(); + Map data = dataContainer.getSimonaInputMap(); long tick = dataContainer.getTick(); Optional maybeNextTick = dataContainer.getMaybeNextTick(); - dataConnections.forEach(con -> con.convertAndSend(tick, data, maybeNextTick, log)); + dataConnections.stream() + .filter(Optional::isPresent) + .map(Optional::get) + .forEach(con -> con.convertAndSend(tick, data, maybeNextTick, log)); log.debug("Provided all data from {} to SIMONA", extSimulatorName); + + return maybeNextTick; + } + + + /** Function to get result data from SIMONA using ExtResultData */ + protected void sendGridResultsToExt( + ExtResultDataConnection connection, + long tick, + Optional nextTick, + Logger log + ) + throws InterruptedException { + log.info("Request results from SIMONA for grid entities for tick {}!", tick); + Map resultsToBeSend = connection.requestGridResults(tick); + log.debug("[{}] Received grid results from SIMONA!\n{}", tick, resultMapToString(resultsToBeSend)); + dataQueueSimonaApiToExtCoSimulator.queueData( + new ExtResultContainer(tick, resultsToBeSend, nextTick)); + log.info("Sent grid results for tick {} to {}", tick, extSimulatorName); + } + + + /** Function to get result data from SIMONA using ExtResultData */ + protected void sendFlexOptionResultsToExt( + ExtResultDataConnection connection, + long tick, + Optional nextTick, + Logger log) + throws InterruptedException { + log.info("Request results from SIMONA for flex options for tick {}!", tick); + Map resultsToBeSend = connection.requestFlexOptionResults(tick); + log.debug("[{}] Received flex option results from SIMONA!\n{}", tick, resultMapToString(resultsToBeSend)); + dataQueueSimonaApiToExtCoSimulator.queueData( + new ExtResultContainer(tick, resultsToBeSend, nextTick)); + log.info("Sent flex option results for tick {} to {}", tick, extSimulatorName); } /** - * Function to get result data from SIMONA using the available {@link ExtResultDataConnection} + * Function to get all result data from SIMONA using the available {@link ExtResultDataConnection} * * @param connection the connection to SIMONA * @param tick for which data is received * @param maybeNextTick option for the next tick data is received * @param log logger */ - protected void sendDataToExt( - ExtResultDataConnection connection, long tick, Optional maybeNextTick, Logger log) + protected void sendResultDataToExt( + ExtResultDataConnection connection, + long tick, + Optional maybeNextTick, + Logger log) throws InterruptedException { log.debug("Request results from SIMONA!"); Map resultsToBeSend = connection.requestResults(tick); @@ -217,4 +255,14 @@ protected void sendDataToExt( new ExtResultContainer(tick, resultsToBeSend, maybeNextTick)); log.debug("Sent results to {}", extSimulatorName); } + + private String resultMapToString( + Map results + ) { + StringBuilder resultString = new StringBuilder(); + for (String key : results.keySet()) { + resultString.append("id = ").append(key).append(", time = ").append(results.get(key).getTime()).append(", result = ").append(results.get(key).getClass().getSimpleName()).append("\n"); + } + return resultString.toString(); + } } diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/DataType.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/DataType.java index 67bfaa12..04d17497 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/DataType.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/DataType.java @@ -12,7 +12,8 @@ public enum DataType { EXT_PRIMARY_INPUT("primary_input"), EXT_EM_INPUT("em_input"), EXT_GRID_RESULT("grid_result"), - EXT_PARTICIPANT_RESULT("participant_result"); + EXT_PARTICIPANT_RESULT("participant_result"), + EXT_FLEX_OPTIONS_RESULT("flex_options_result"); public final String type; @@ -26,6 +27,7 @@ public static DataType parse(String type) throws ParsingException { case "em_input" -> EXT_EM_INPUT; case "grid_result" -> EXT_GRID_RESULT; case "participant_result" -> EXT_PARTICIPANT_RESULT; + case "flex_options_result" -> EXT_FLEX_OPTIONS_RESULT; default -> throw new ParsingException("Data type " + type + " is not supported!"); }; } diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java index 1444c3e1..efeb91f3 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java @@ -8,6 +8,8 @@ import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; import edu.ie3.datamodel.models.input.InputEntity; + +import java.util.Optional; import java.util.UUID; /** @@ -15,14 +17,14 @@ * * @param uuid SIMONA uuid * @param id external id - * @param columnScheme data types the external asset expects + * @param columnScheme option for data types the external asset expects * @param dataType data types the external asset expects */ public record ExtEntityEntry( - UUID uuid, - String id, - ColumnScheme columnScheme, // FIXME: placeholder -> ColumnScheme should handle more data types - DataType dataType) + UUID uuid, + String id, + Optional columnScheme, // FIXME: placeholder -> ColumnScheme should handle more data types + DataType dataType) implements InputEntity { public String toString() { diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java index 9a820258..ce896b61 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java @@ -49,8 +49,7 @@ protected ExtEntityEntry buildModel(EntityData data) { return new ExtEntityEntry( simonaUuid, extId, - columnScheme - .orElseThrow(), // FIXME: Interim version -> ColumnScheme should handle more data types + columnScheme, // FIXME: Interim version -> ColumnScheme should handle more data types inputType); } } diff --git a/src/test/groovy/edu/ie3/simona/api/data/em/ExtEmDataConnectionTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/em/ExtEmDataConnectionTest.groovy index 29a3ae2d..a2d1096b 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/em/ExtEmDataConnectionTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/em/ExtEmDataConnectionTest.groovy @@ -4,13 +4,10 @@ import edu.ie3.datamodel.models.value.PValue import edu.ie3.datamodel.models.value.Value import edu.ie3.simona.api.data.em.ontology.ProvideEmSetPointData import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage -import edu.ie3.simona.api.data.primarydata.ontology.ProvidePrimaryData import edu.ie3.simona.api.test.common.DataServiceTestData import org.apache.pekko.actor.ActorSystem import org.apache.pekko.testkit.TestProbe import org.apache.pekko.testkit.javadsl.TestKit -import org.slf4j.Logger -import org.slf4j.LoggerFactory import spock.lang.Shared import spock.lang.Specification From dfd6900ff7235334db4bfa34e64831bb901d033e Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 24 Feb 2025 14:45:05 +0100 Subject: [PATCH 3/4] Adapting some parts. --- .../primarydata/ExtPrimaryDataConnection.java | 14 ++ .../api/data/results/ExtResultContainer.java | 25 +- .../data/results/ExtResultDataConnection.java | 31 ++- .../ontology/RequestResultEntities.java | 6 +- .../ExtDataConnectionException.java | 23 ++ .../exceptions/NoExtSimulationException.java | 5 +- .../api/simulation/ExtCoSimulation.java | 237 +++++++++++------- .../simulation/mapping/ExtEntityEntry.java | 10 +- .../simulation/mapping/ExtEntityMapping.java | 15 ++ .../ExtResultDataConnectionTest.groovy | 15 +- .../api/simulation/ExtCoSimulationTest.groovy | 35 +-- .../mapping/ExtEntityMappingTest.groovy | 4 +- 12 files changed, 276 insertions(+), 144 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/exceptions/ExtDataConnectionException.java diff --git a/src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java b/src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java index 969cead3..d65eaa39 100644 --- a/src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java @@ -20,15 +20,29 @@ public class ExtPrimaryDataConnection extends ExtInputDataConnectionWithMapping { + private Map> valueClasses; + public ExtPrimaryDataConnection(Map extPrimaryDataMapping) { super(extPrimaryDataMapping); } + public void setValueClasses(Map> valueClasses) { + this.valueClasses = valueClasses; + } + /** Returns a list of the uuids of the system participants that expect external primary data */ public List getPrimaryDataAssets() { return getDataAssets(); } + /** + * @param uuid of the model + * @return an option for the value class associated with the model. + */ + public Optional> getValueClass(UUID uuid) { + return Optional.ofNullable(valueClasses.get(uuid)); + } + @Override public void convertAndSend( long tick, Map data, Optional maybeNextTick, Logger log) { diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java index 8c73b6c2..e73d1f2d 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java @@ -57,7 +57,9 @@ public Map getResults() { return simonaResultsMap; } - public String getResultsAsString() { return resultMapToString(simonaResultsMap); } + public String getResultsAsString() { + return resultMapToString(simonaResultsMap); + } public Long getTick() { return tick; @@ -67,15 +69,14 @@ public Optional getNextTick() { return maybeNextTick; } - /** - * Returns the result for a certain asset. - */ + /** Returns the result for a certain asset. */ public ResultEntity getResult(String assetId) { return simonaResultsMap.get(assetId); } /** - * Returns the voltage deviation in pu for certain asset, if this asset provided a {@link NodeResult} + * Returns the voltage deviation in pu for certain asset, if this asset provided a {@link + * NodeResult} */ public double getVoltageDeviation(String assetId) { if (simonaResultsMap.get(assetId) instanceof NodeResult nodeResult) { @@ -129,13 +130,17 @@ public double getLineLoading(String assetId) { throw new IllegalArgumentException("LINE LOADING is not implemented yet!"); } - - private String resultMapToString( - Map results - ) { + private String resultMapToString(Map results) { StringBuilder resultString = new StringBuilder(); for (String key : results.keySet()) { - resultString.append("id = ").append(key).append(", time = ").append(results.get(key).getTime()).append(", result = ").append(results.get(key).getClass().getSimpleName()).append("\n"); + resultString + .append("id = ") + .append(key) + .append(", time = ") + .append(results.get(key).getTime()) + .append(", result = ") + .append(results.get(key).getClass().getSimpleName()) + .append("\n"); } return resultString.toString(); } diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java b/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java index 1c9ee27c..ba99766a 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java @@ -22,7 +22,6 @@ import java.util.UUID; import java.util.concurrent.LinkedBlockingQueue; import java.util.stream.Stream; - import org.apache.pekko.actor.ActorRef; /** Enables data connection of results between SIMONA and SimonaAPI */ @@ -53,8 +52,7 @@ public class ExtResultDataConnection implements ExtOutputDataConnection { public ExtResultDataConnection( Map participantResultAssetMapping, Map gridResultAssetMapping, - Map flexOptionsMapping - ) { + Map flexOptionsMapping) { this.participantResultAssetMapping = participantResultAssetMapping; this.gridResultAssetMapping = gridResultAssetMapping; this.flexOptionsMapping = flexOptionsMapping; @@ -89,12 +87,17 @@ public List getFlexOptionAssets() { /** Method that an external simulation can request results from SIMONA as a list. */ private List requestResultList(long tick) throws InterruptedException { - List allExtEntities = Stream.concat(Stream.concat(getFlexOptionAssets().stream(), getGridResultDataAssets().stream()), getParticipantResultDataAssets().stream()).toList(); + List allExtEntities = + Stream.concat( + Stream.concat(getFlexOptionAssets().stream(), getGridResultDataAssets().stream()), + getParticipantResultDataAssets().stream()) + .toList(); sendExtMsg(new RequestResultEntities(tick, allExtEntities)); return receiveWithType(ProvideResultEntities.class).results(); } - private List requestFlexOptionResultsList(long tick) throws InterruptedException { + private List requestFlexOptionResultsList(long tick) + throws InterruptedException { sendExtMsg(new RequestResultEntities(tick, getFlexOptionAssets())); return receiveWithType(ProvideResultEntities.class).results(); } @@ -104,6 +107,12 @@ private List requestGridResultsList(long tick) throws Interru return receiveWithType(ProvideResultEntities.class).results(); } + private List requestParticiapntResultsList(long tick) + throws InterruptedException { + sendExtMsg(new RequestResultEntities(tick, getParticipantResultDataAssets())); + return receiveWithType(ProvideResultEntities.class).results(); + } + /** * Method that an external simulation can request results from SIMONA as a map string to object. */ @@ -111,7 +120,8 @@ public Map requestResults(long tick) throws Interrupt return createResultMap(requestResultList(tick)); } - public Map requestFlexOptionResults(long tick) throws InterruptedException { + public Map requestFlexOptionResults(long tick) + throws InterruptedException { return createResultMap(requestFlexOptionResultsList(tick)); } @@ -119,6 +129,11 @@ public Map requestGridResults(long tick) throws Inter return createResultMap(requestGridResultsList(tick)); } + public Map requestParticipantResults(long tick) + throws InterruptedException { + return createResultMap(requestGridResultsList(tick)); + } + protected Map createResultMap(List results) { Map resultMap = new HashMap<>(); results.forEach( @@ -131,9 +146,7 @@ protected Map createResultMap(List systemParticipantResult); } else if (result instanceof FlexOptionsResult flexOptionsResult) { resultMap.put( - flexOptionsMapping.get(flexOptionsResult.getInputModel()), - flexOptionsResult - ); + flexOptionsMapping.get(flexOptionsResult.getInputModel()), flexOptionsResult); } else { throw new IllegalArgumentException( "ExtResultData can only handle NodeResult's, FlexOptionResult's and SystemParticipantResult's!"); diff --git a/src/main/java/edu/ie3/simona/api/data/results/ontology/RequestResultEntities.java b/src/main/java/edu/ie3/simona/api/data/results/ontology/RequestResultEntities.java index 021d2cfd..9f72ab7b 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ontology/RequestResultEntities.java +++ b/src/main/java/edu/ie3/simona/api/data/results/ontology/RequestResultEntities.java @@ -10,7 +10,5 @@ import java.util.UUID; /** Request calculated results from SIMONA in the current tick */ -public record RequestResultEntities( - Long tick, - List requestedResults -) implements ResultDataMessageFromExt {} +public record RequestResultEntities(Long tick, List requestedResults) + implements ResultDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/exceptions/ExtDataConnectionException.java b/src/main/java/edu/ie3/simona/api/exceptions/ExtDataConnectionException.java new file mode 100644 index 00000000..cfa54bc1 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/exceptions/ExtDataConnectionException.java @@ -0,0 +1,23 @@ +/* + * © 2024. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.api.exceptions; + +import edu.ie3.simona.api.data.ExtDataConnection; + +public class ExtDataConnectionException extends RuntimeException { + + public ExtDataConnectionException(Class connectionClass) { + this( + "The external data connection '" + + connectionClass.getSimpleName() + + "' could not be build!"); + } + + public ExtDataConnectionException(final String message) { + super(message); + } +} diff --git a/src/main/java/edu/ie3/simona/api/exceptions/NoExtSimulationException.java b/src/main/java/edu/ie3/simona/api/exceptions/NoExtSimulationException.java index f4a242b3..9c403556 100644 --- a/src/main/java/edu/ie3/simona/api/exceptions/NoExtSimulationException.java +++ b/src/main/java/edu/ie3/simona/api/exceptions/NoExtSimulationException.java @@ -11,7 +11,10 @@ public class NoExtSimulationException extends RuntimeException { public NoExtSimulationException(Class linkClass) { - this("No external simulation was set up in ExtLinkInterface: ." + linkClass.getSimpleName()); + this( + "No external simulation was set up in ExtLinkInterface: " + + linkClass.getSimpleName() + + "."); } public NoExtSimulationException(final String message) { diff --git a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java index 4fb60fbb..def80428 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -10,13 +10,14 @@ import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.DataQueueExtSimulationExtSimulator; import edu.ie3.simona.api.data.ExtDataConnection; -import edu.ie3.simona.api.data.ExtInputDataConnectionWithMapping; import edu.ie3.simona.api.data.ExtInputDataContainer; import edu.ie3.simona.api.data.em.ExtEmDataConnection; import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; import edu.ie3.simona.api.data.results.ExtResultContainer; import edu.ie3.simona.api.data.results.ExtResultDataConnection; +import edu.ie3.simona.api.exceptions.ExtDataConnectionException; import edu.ie3.simona.api.simulation.mapping.DataType; +import edu.ie3.simona.api.simulation.mapping.ExtEntityEntry; import edu.ie3.simona.api.simulation.mapping.ExtEntityMapping; import java.util.*; import java.util.stream.Collectors; @@ -50,7 +51,8 @@ protected ExtCoSimulation(String simulationName, String extSimulatorName) { } @SafeVarargs - protected static Set toSet(Optional... optionals) { + protected static Set toSet( + Optional... optionals) { return Arrays.stream(optionals) .filter(Optional::isPresent) .map(Optional::get) @@ -62,18 +64,33 @@ protected static Set toSet(Optional buildPrimaryConnection( + @SuppressWarnings("unchecked") + public static ExtPrimaryDataConnection buildPrimaryConnection( ExtEntityMapping mapping, Logger log) { - Map primaryMapping = mapping.getExtId2UuidMapping(DataType.EXT_PRIMARY_INPUT); + List entries = mapping.getExtEntityEntries(DataType.EXT_PRIMARY_INPUT); - if (primaryMapping.isEmpty()) { + if (entries.isEmpty()) { log.warn("No primary data connection was created."); - return Optional.empty(); + throw new ExtDataConnectionException(ExtPrimaryDataConnection.class); } else { - log.info("Primary data connection with {} entities created.", primaryMapping.size()); - return Optional.of(new ExtPrimaryDataConnection(primaryMapping)); + log.info("Primary data connection with {} entities created.", entries.size()); + + Map primaryMapping = + entries.stream().collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); + Map> valueClasses = new HashMap<>(); + entries.stream() + .filter(e -> e.columnScheme().isPresent()) + .forEach( + e -> + valueClasses.put( + e.uuid(), (Class) e.columnScheme().get().getValueClass())); + + ExtPrimaryDataConnection primaryDataConnection = new ExtPrimaryDataConnection(primaryMapping); + primaryDataConnection.setValueClasses(valueClasses); + + return primaryDataConnection; } } @@ -82,18 +99,17 @@ public static Optional buildPrimaryConnection( * * @param mapping between the external simulation and SIMONA. * @param log logger - * @return an option for an ext em data connection + * @return an ext em data connection */ - public static Optional buildEmConnection( - ExtEntityMapping mapping, Logger log) { + public static ExtEmDataConnection buildEmConnection(ExtEntityMapping mapping, Logger log) { Map emMapping = mapping.getExtId2UuidMapping(DataType.EXT_EM_INPUT); if (emMapping.isEmpty()) { log.warn("No em data connection was created."); - return Optional.empty(); + throw new ExtDataConnectionException(ExtEmDataConnection.class); } else { log.info("Em data connection with {} entities created.", emMapping.size()); - return Optional.of(new ExtEmDataConnection(emMapping)); + return new ExtEmDataConnection(emMapping); } } @@ -102,35 +118,57 @@ public static Optional buildEmConnection( * * @param mapping between the external simulation and SIMONA. * @param log logger - * @return an option for an ext result data connection + * @return an ext result data connection */ - public static Optional buildResultConnection( + public static ExtResultDataConnection buildResultConnection( ExtEntityMapping mapping, Logger log) { Map resultParticipantMapping = mapping.getExtUuid2IdMapping(DataType.EXT_PARTICIPANT_RESULT); Map resultGridMapping = mapping.getExtUuid2IdMapping(DataType.EXT_GRID_RESULT); - Map resultFlexOptionsMapping = mapping.getExtUuid2IdMapping(DataType.EXT_FLEX_OPTIONS_RESULT); + Map resultFlexOptionsMapping = + mapping.getExtUuid2IdMapping(DataType.EXT_FLEX_OPTIONS_RESULT); - if (resultParticipantMapping.isEmpty() && resultGridMapping.isEmpty()) { + if (resultParticipantMapping.isEmpty() + && resultGridMapping.isEmpty() + && resultFlexOptionsMapping.isEmpty()) { log.warn("No result connection was created."); - return Optional.empty(); + throw new ExtDataConnectionException(ExtResultDataConnection.class); } else { log.info( - "Result connection with {} participants and {} grid assets created.", + "Result connection with {} participants, {} grid assets and {} flex option mappings created.", resultParticipantMapping.size(), - resultGridMapping.size()); - return Optional.of( - new ExtResultDataConnection( - resultParticipantMapping, - resultGridMapping, - resultFlexOptionsMapping - ) - ); + resultGridMapping.size(), + resultFlexOptionsMapping.size()); + return new ExtResultDataConnection( + resultParticipantMapping, resultGridMapping, resultFlexOptionsMapping); } } /** - * Function to send primary data to SIMONA using ExtPrimaryData + * Function to send primary data to SIMONA using the given {@link ExtPrimaryDataConnection}. This + * method will take a value from the {@link #dataQueueExtCoSimulatorToSimonaApi}. + * + * @param extPrimaryDataConnection the connection to SIMONA + * @param tick for which data is sent + * @param maybeNextTick option for the next tick data is sent + * @param log logger + */ + protected void sendPrimaryDataToSimona( + ExtPrimaryDataConnection extPrimaryDataConnection, + long tick, + Optional maybeNextTick, + Logger log) + throws InterruptedException { + sendPrimaryDataToSimona( + extPrimaryDataConnection, + tick, + dataQueueExtCoSimulatorToSimonaApi.takeData().getSimonaInputMap(), + maybeNextTick, + log); + } + + /** + * Function to send primary data to SIMONA using the given {@link ExtPrimaryDataConnection}. * * @param extPrimaryDataConnection the connection to SIMONA * @param tick for which data is sent @@ -151,8 +189,33 @@ protected void sendPrimaryDataToSimona( } /** - * Function to send em data to SIMONA using ExtPrimaryData nextTick is necessary, because the em - * agents have an own scheduler that should know, when the next set point arrives. + * Function to send em data to SIMONA using the given {@link ExtEmDataConnection}. This method + * will take a value from the * {@link #dataQueueExtCoSimulatorToSimonaApi}. + * + *

{@code nextTick} is necessary, because the em agents have an own scheduler that should know, + * when the next set point arrives. + * + * @param extEmDataConnection the connection to SIMONA + * @param tick for which data is sent + * @param maybeNextTick option for the next tick data is sent + * @param log logger + */ + protected void sendEmDataToSimona( + ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) + throws InterruptedException { + sendEmDataToSimona( + extEmDataConnection, + tick, + dataQueueExtCoSimulatorToSimonaApi.takeData().getSimonaInputMap(), + maybeNextTick, + log); + } + + /** + * Function to send em data to SIMONA using the given {@link ExtEmDataConnection}. + * + *

{@code nextTick} is necessary, because the em agents have an own scheduler that should know, + * when the next set point arrives. * * @param extEmDataConnection the connection to SIMONA * @param tick for which data is sent @@ -172,81 +235,66 @@ protected void sendEmDataToSimona( } /** - * Function to send all external data to SIMONA using {@link ExtInputDataConnectionWithMapping}s. This - * method will automatically take the next {@link ExtInputDataContainer} from the queue. - * - * @param dataConnections the connections to SIMONA - * @param log logger - * @return an option for the next tick simona expects data + * Function to send only participant result data from SIMONA to the external simulation using the + * given {@link ExtResultDataConnection} */ - protected Optional sendDataToSIMONA( - Set>> dataConnections, - Logger log) + protected void sendParticipantResultsToExt( + ExtResultDataConnection connection, long tick, Optional nextTick, Logger log) throws InterruptedException { - log.debug("Received data from {}", extSimulatorName); - - ExtInputDataContainer dataContainer = dataQueueExtCoSimulatorToSimonaApi.takeData(); - - Map data = dataContainer.getSimonaInputMap(); - long tick = dataContainer.getTick(); - Optional maybeNextTick = dataContainer.getMaybeNextTick(); - - dataConnections.stream() - .filter(Optional::isPresent) - .map(Optional::get) - .forEach(con -> con.convertAndSend(tick, data, maybeNextTick, log)); - - log.debug("Provided all data from {} to SIMONA", extSimulatorName); - - return maybeNextTick; + sendSingleResultType( + "participant", connection.requestParticipantResults(tick), tick, nextTick, log); } - - /** Function to get result data from SIMONA using ExtResultData */ + /** + * Function to send only grid result data from SIMONA to the external simulation using the given + * {@link ExtResultDataConnection} + */ protected void sendGridResultsToExt( - ExtResultDataConnection connection, - long tick, - Optional nextTick, - Logger log - ) - throws InterruptedException { - log.info("Request results from SIMONA for grid entities for tick {}!", tick); - Map resultsToBeSend = connection.requestGridResults(tick); - log.debug("[{}] Received grid results from SIMONA!\n{}", tick, resultMapToString(resultsToBeSend)); - dataQueueSimonaApiToExtCoSimulator.queueData( - new ExtResultContainer(tick, resultsToBeSend, nextTick)); - log.info("Sent grid results for tick {} to {}", tick, extSimulatorName); + ExtResultDataConnection connection, long tick, Optional nextTick, Logger log) + throws InterruptedException { + sendSingleResultType("grid", connection.requestGridResults(tick), tick, nextTick, log); } - - /** Function to get result data from SIMONA using ExtResultData */ + /** + * Function to send only flex option result data from SIMONA to the external simulation using the + * given {@link ExtResultDataConnection} + */ protected void sendFlexOptionResultsToExt( - ExtResultDataConnection connection, - long tick, - Optional nextTick, - Logger log) - throws InterruptedException { - log.info("Request results from SIMONA for flex options for tick {}!", tick); - Map resultsToBeSend = connection.requestFlexOptionResults(tick); - log.debug("[{}] Received flex option results from SIMONA!\n{}", tick, resultMapToString(resultsToBeSend)); + ExtResultDataConnection connection, long tick, Optional nextTick, Logger log) + throws InterruptedException { + sendSingleResultType( + "flex option", connection.requestFlexOptionResults(tick), tick, nextTick, log); + } + + private void sendSingleResultType( + String type, + Map resultsToBeSend, + long tick, + Optional nextTick, + Logger log) + throws InterruptedException { + log.info("Request results from SIMONA for {} for tick {}!", type, tick); + log.debug( + "[{}] Received {} results from SIMONA!\n{}", + tick, + type, + resultMapToString(resultsToBeSend)); dataQueueSimonaApiToExtCoSimulator.queueData( - new ExtResultContainer(tick, resultsToBeSend, nextTick)); - log.info("Sent flex option results for tick {} to {}", tick, extSimulatorName); + new ExtResultContainer(tick, resultsToBeSend, nextTick)); + log.info("Sent {} results for tick {} to {}", type, tick, extSimulatorName); } /** - * Function to get all result data from SIMONA using the available {@link ExtResultDataConnection} + * Function to send all result data from SIMONA to the external simulation using the given {@link + * ExtResultDataConnection} * * @param connection the connection to SIMONA * @param tick for which data is received * @param maybeNextTick option for the next tick data is received * @param log logger */ - protected void sendResultDataToExt( - ExtResultDataConnection connection, - long tick, - Optional maybeNextTick, - Logger log) + protected void sendResultToExt( + ExtResultDataConnection connection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { log.debug("Request results from SIMONA!"); Map resultsToBeSend = connection.requestResults(tick); @@ -256,12 +304,17 @@ protected void sendResultDataToExt( log.debug("Sent results to {}", extSimulatorName); } - private String resultMapToString( - Map results - ) { + private String resultMapToString(Map results) { StringBuilder resultString = new StringBuilder(); for (String key : results.keySet()) { - resultString.append("id = ").append(key).append(", time = ").append(results.get(key).getTime()).append(", result = ").append(results.get(key).getClass().getSimpleName()).append("\n"); + resultString + .append("id = ") + .append(key) + .append(", time = ") + .append(results.get(key).getTime()) + .append(", result = ") + .append(results.get(key).getClass().getSimpleName()) + .append("\n"); } return resultString.toString(); } diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java index efeb91f3..223d3913 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java @@ -8,7 +8,6 @@ import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; import edu.ie3.datamodel.models.input.InputEntity; - import java.util.Optional; import java.util.UUID; @@ -21,10 +20,11 @@ * @param dataType data types the external asset expects */ public record ExtEntityEntry( - UUID uuid, - String id, - Optional columnScheme, // FIXME: placeholder -> ColumnScheme should handle more data types - DataType dataType) + UUID uuid, + String id, + Optional + columnScheme, // FIXME: placeholder -> ColumnScheme should handle more data types + DataType dataType) implements InputEntity { public String toString() { diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java index 8fd033e6..9fe43371 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java @@ -19,6 +19,21 @@ public ExtEntityMapping(List extEntityEntryList) { extEntityEntryList.stream().collect(Collectors.groupingBy(ExtEntityEntry::dataType)); } + /** Returns the data types of this mapping. */ + public Set getDataTypes() { + return extEntities.keySet(); + } + + /** + * Method for getting the external entity entries for a specific data type. + * + * @param dataType for which entries should be returned + * @return a list containing all entries or an empty list + */ + public List getExtEntityEntries(DataType dataType) { + return extEntities.getOrDefault(dataType, Collections.emptyList()); + } + /** * Mapping external id to SIMONA uuid * diff --git a/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultDataConnectionTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultDataConnectionTest.groovy index 7dc0dc22..f49f99ca 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultDataConnectionTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultDataConnectionTest.groovy @@ -30,6 +30,9 @@ class ExtResultDataConnectionTest extends Specification implements DataServiceTe @Shared Map gridResultAssetMapping = [:] + @Shared + Map flexResultAssetMapping = [:] + class WrongResultDataResponseMessageToExt implements ResultDataResponseMessageToExt {} def setupSpec() { @@ -46,7 +49,7 @@ class ExtResultDataConnectionTest extends Specification implements DataServiceTe def dataService = new TestProbe(actorSystem) def dataServiceActivation = new TestProbe(actorSystem) def extSimAdapter = new TestProbe(actorSystem) - def extResultDataConnection = new ExtResultDataConnection(participantResultAssetMapping, gridResultAssetMapping) + def extResultDataConnection = new ExtResultDataConnection(participantResultAssetMapping, gridResultAssetMapping, flexResultAssetMapping) extResultDataConnection.setActorRefs( dataService.ref(), dataServiceActivation.ref(), @@ -61,7 +64,7 @@ class ExtResultDataConnectionTest extends Specification implements DataServiceTe def receivedResults = extResultDataConnection.requestResults(0L) then: - dataService.expectMsg(new RequestResultEntities(0L)) + dataService.expectMsg(new RequestResultEntities(0L, [inputUuid])) extSimAdapter.expectMsg(new ScheduleDataServiceMessage(dataServiceActivation.ref())) receivedResults.get("Load") == loadResult } @@ -71,7 +74,7 @@ class ExtResultDataConnectionTest extends Specification implements DataServiceTe def dataService = new TestProbe(actorSystem) def dataServiceActivation = new TestProbe(actorSystem) def extSimAdapter = new TestProbe(actorSystem) - def extResultDataConnection = new ExtResultDataConnection(participantResultAssetMapping, gridResultAssetMapping) + def extResultDataConnection = new ExtResultDataConnection(participantResultAssetMapping, gridResultAssetMapping, flexResultAssetMapping) extResultDataConnection.setActorRefs( dataService.ref(), dataServiceActivation.ref(), @@ -86,14 +89,14 @@ class ExtResultDataConnectionTest extends Specification implements DataServiceTe extResultDataConnection.requestResults(0L) then: - dataService.expectMsg(new RequestResultEntities(0L)) + dataService.expectMsg(new RequestResultEntities(0L, [inputUuid])) extSimAdapter.expectMsg(new ScheduleDataServiceMessage(dataServiceActivation.ref())) thrown RuntimeException } def "ExtResultData should convert a list of result entities correctly to a map of resultAssetMappingId to result entity"() { given: - def extResultDataConnection = new ExtResultDataConnection(participantResultAssetMapping, gridResultAssetMapping) + def extResultDataConnection = new ExtResultDataConnection(participantResultAssetMapping, gridResultAssetMapping, flexResultAssetMapping) when: def mapOfResults = extResultDataConnection.createResultMap([loadResult]) @@ -105,7 +108,7 @@ class ExtResultDataConnectionTest extends Specification implements DataServiceTe def "ExtResultData should throw an exception, if a result with a wrong data type was provided"() { given: - def extResultDataConnection = new ExtResultDataConnection(participantResultAssetMapping, gridResultAssetMapping) + def extResultDataConnection = new ExtResultDataConnection(participantResultAssetMapping, gridResultAssetMapping, flexResultAssetMapping) Quantity iAMag = Quantities.getQuantity(100, StandardUnits.ELECTRIC_CURRENT_MAGNITUDE) Quantity iAAng = Quantities.getQuantity(45, StandardUnits.ELECTRIC_CURRENT_ANGLE) Quantity iBMag = Quantities.getQuantity(150, StandardUnits.ELECTRIC_CURRENT_MAGNITUDE) diff --git a/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy b/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy index ac92fce8..f12eeaab 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy @@ -20,17 +20,19 @@ class ExtCoSimulationTest extends Specification { UUID uuid2 = UUID.randomUUID() UUID uuid3 = UUID.randomUUID() + Optional columnScheme = Optional.of(ColumnScheme.ACTIVE_POWER) + ExtEntityMapping mapping = new ExtEntityMapping([ - new ExtEntityEntry(uuid1, "primary1", ColumnScheme.ACTIVE_POWER, DataType.EXT_PRIMARY_INPUT), - new ExtEntityEntry(uuid2, "em1", ColumnScheme.ACTIVE_POWER, DataType.EXT_EM_INPUT), - new ExtEntityEntry(uuid3, "primary2", ColumnScheme.ACTIVE_POWER, DataType.EXT_PRIMARY_INPUT), + new ExtEntityEntry(uuid1, "primary1", columnScheme, DataType.EXT_PRIMARY_INPUT), + new ExtEntityEntry(uuid2, "em1", columnScheme, DataType.EXT_EM_INPUT), + new ExtEntityEntry(uuid3, "primary2", columnScheme, DataType.EXT_PRIMARY_INPUT), ]) when: def actual = ExtCoSimulation.buildPrimaryConnection(mapping, log) then: - actual.get().primaryDataAssets == [uuid3, uuid1] + actual.primaryDataAssets == [uuid3, uuid1] } def "An ExtCoSimulation can build an em data connection correctly"() { @@ -39,17 +41,19 @@ class ExtCoSimulationTest extends Specification { UUID uuid2 = UUID.randomUUID() UUID uuid3 = UUID.randomUUID() + Optional columnScheme = Optional.of(ColumnScheme.ACTIVE_POWER) + ExtEntityMapping mapping = new ExtEntityMapping([ - new ExtEntityEntry(uuid1, "em1", ColumnScheme.ACTIVE_POWER, DataType.EXT_EM_INPUT), - new ExtEntityEntry(uuid2, "em2", ColumnScheme.ACTIVE_POWER, DataType.EXT_EM_INPUT), - new ExtEntityEntry(uuid3, "primary1", ColumnScheme.ACTIVE_POWER, DataType.EXT_PRIMARY_INPUT), + new ExtEntityEntry(uuid1, "em1", columnScheme, DataType.EXT_EM_INPUT), + new ExtEntityEntry(uuid2, "em2", columnScheme, DataType.EXT_EM_INPUT), + new ExtEntityEntry(uuid3, "primary1", columnScheme, DataType.EXT_PRIMARY_INPUT), ]) when: def actual = ExtCoSimulation.buildEmConnection(mapping, log) then: - actual.get().controlledEms == [uuid1, uuid2] + actual.controlledEms == [uuid1, uuid2] } def "An ExtCoSimulation can build a result data connection correctly"() { @@ -58,19 +62,20 @@ class ExtCoSimulationTest extends Specification { UUID uuid2 = UUID.randomUUID() UUID uuid3 = UUID.randomUUID() + Optional columnScheme = Optional.of(ColumnScheme.ACTIVE_POWER) + ExtEntityMapping mapping = new ExtEntityMapping([ - new ExtEntityEntry(uuid1, "grid_result", ColumnScheme.ACTIVE_POWER, DataType.EXT_GRID_RESULT), - new ExtEntityEntry(uuid2, "participant_result", ColumnScheme.ACTIVE_POWER, DataType.EXT_PARTICIPANT_RESULT), - new ExtEntityEntry(uuid3, "primary1", ColumnScheme.ACTIVE_POWER, DataType.EXT_PRIMARY_INPUT), + new ExtEntityEntry(uuid1, "grid_result", columnScheme, DataType.EXT_GRID_RESULT), + new ExtEntityEntry(uuid2, "participant_result", columnScheme, DataType.EXT_PARTICIPANT_RESULT), + new ExtEntityEntry(uuid3, "primary1", columnScheme, DataType.EXT_PRIMARY_INPUT), ]) when: def actual = ExtCoSimulation.buildResultConnection(mapping, log) then: - actual.isPresent() - - actual.get().gridResultDataAssets == [uuid1] - actual.get().participantResultDataAssets == [uuid2] + actual.gridResultDataAssets == [uuid1] + actual.participantResultDataAssets == [uuid2] + actual.flexOptionAssets == [] } } diff --git a/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingTest.groovy b/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingTest.groovy index 9f49f614..87818c68 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingTest.groovy @@ -12,7 +12,7 @@ class ExtEntityMappingTest extends Specification { ExtEntityEntry extResultEntry = new ExtEntityEntry( loadUuid, "Load", - ColumnScheme.parse("p").get(), + ColumnScheme.parse("p"), DataType.EXT_PARTICIPANT_RESULT ) @@ -20,7 +20,7 @@ class ExtEntityMappingTest extends Specification { ExtEntityEntry extInputEntry = new ExtEntityEntry( loadUuid, "Load", - ColumnScheme.parse("p").get(), + ColumnScheme.parse("p"), DataType.EXT_PRIMARY_INPUT ) From 6eb6b6643806f77c92d964ea228786e83164482d Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 24 Feb 2025 15:04:32 +0100 Subject: [PATCH 4/4] Fixing `sonarqube` issues. --- .../api/data/results/ExtResultContainer.java | 19 ------------------- .../data/results/ExtResultDataConnection.java | 2 +- .../api/simulation/ExtCoSimulation.java | 18 ++++++++++-------- .../simulation/mapping/ExtEntityEntry.java | 6 +----- .../simulation/mapping/ExtEntityFactory.java | 6 +----- 5 files changed, 13 insertions(+), 38 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java index e73d1f2d..4379905e 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java @@ -57,10 +57,6 @@ public Map getResults() { return simonaResultsMap; } - public String getResultsAsString() { - return resultMapToString(simonaResultsMap); - } - public Long getTick() { return tick; } @@ -129,19 +125,4 @@ public double getReactivePower(String assetId) { public double getLineLoading(String assetId) { throw new IllegalArgumentException("LINE LOADING is not implemented yet!"); } - - private String resultMapToString(Map results) { - StringBuilder resultString = new StringBuilder(); - for (String key : results.keySet()) { - resultString - .append("id = ") - .append(key) - .append(", time = ") - .append(results.get(key).getTime()) - .append(", result = ") - .append(results.get(key).getClass().getSimpleName()) - .append("\n"); - } - return resultString.toString(); - } } diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java b/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java index ba99766a..535927e1 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java @@ -131,7 +131,7 @@ public Map requestGridResults(long tick) throws Inter public Map requestParticipantResults(long tick) throws InterruptedException { - return createResultMap(requestGridResultsList(tick)); + return createResultMap(requestParticiapntResultsList(tick)); } protected Map createResultMap(List results) { diff --git a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java index def80428..15a749ef 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -274,11 +274,9 @@ private void sendSingleResultType( Logger log) throws InterruptedException { log.info("Request results from SIMONA for {} for tick {}!", type, tick); - log.debug( - "[{}] Received {} results from SIMONA!\n{}", - tick, - type, - resultMapToString(resultsToBeSend)); + + String resultString = resultMapToString(resultsToBeSend); + log.debug("[{}] Received {} results from SIMONA!\n{}", tick, type, resultString); dataQueueSimonaApiToExtCoSimulator.queueData( new ExtResultContainer(tick, resultsToBeSend, nextTick)); log.info("Sent {} results for tick {} to {}", type, tick, extSimulatorName); @@ -306,14 +304,18 @@ protected void sendResultToExt( private String resultMapToString(Map results) { StringBuilder resultString = new StringBuilder(); - for (String key : results.keySet()) { + + for (Map.Entry entry : results.entrySet()) { + String key = entry.getKey(); + ModelResultEntity value = entry.getValue(); + resultString .append("id = ") .append(key) .append(", time = ") - .append(results.get(key).getTime()) + .append(value.getTime()) .append(", result = ") - .append(results.get(key).getClass().getSimpleName()) + .append(value.getClass().getSimpleName()) .append("\n"); } return resultString.toString(); diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java index 223d3913..1df4987b 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java @@ -20,11 +20,7 @@ * @param dataType data types the external asset expects */ public record ExtEntityEntry( - UUID uuid, - String id, - Optional - columnScheme, // FIXME: placeholder -> ColumnScheme should handle more data types - DataType dataType) + UUID uuid, String id, Optional columnScheme, DataType dataType) implements InputEntity { public String toString() { diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java index ce896b61..49718d13 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java @@ -46,10 +46,6 @@ protected ExtEntityEntry buildModel(EntityData data) { throw new FactoryException(e); } - return new ExtEntityEntry( - simonaUuid, - extId, - columnScheme, // FIXME: Interim version -> ColumnScheme should handle more data types - inputType); + return new ExtEntityEntry(simonaUuid, extId, columnScheme, inputType); } }