From a1875e1f06b8944b21b335947652cc5775853886 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 9 Jan 2025 14:02:29 +0100 Subject: [PATCH 01/80] 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 02/80] 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 44f52d910ff81792e74f2f133a01333d58092d98 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 21 Jan 2025 12:25:27 +0100 Subject: [PATCH 03/80] fmt --- .../api/data/results/ExtResultContainer.java | 25 ++++--- .../data/results/ExtResultDataConnection.java | 20 ++--- .../ontology/RequestResultEntities.java | 6 +- .../api/simulation/ExtCoSimulation.java | 74 +++++++++---------- .../simulation/mapping/ExtEntityEntry.java | 10 +-- 5 files changed, 67 insertions(+), 68 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 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..02ab982c 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(); } @@ -111,7 +114,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)); } @@ -131,9 +135,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/simulation/ExtCoSimulation.java b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java index 4fb60fbb..b00fb700 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,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) @@ -109,7 +110,8 @@ 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); + Map resultFlexOptionsMapping = + mapping.getExtUuid2IdMapping(DataType.EXT_FLEX_OPTIONS_RESULT); if (resultParticipantMapping.isEmpty() && resultGridMapping.isEmpty()) { log.warn("No result connection was created."); @@ -120,12 +122,8 @@ public static Optional buildResultConnection( resultParticipantMapping.size(), resultGridMapping.size()); return Optional.of( - new ExtResultDataConnection( - resultParticipantMapping, - resultGridMapping, - resultFlexOptionsMapping - ) - ); + new ExtResultDataConnection( + resultParticipantMapping, resultGridMapping, resultFlexOptionsMapping)); } } @@ -172,16 +170,15 @@ 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. + * 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 Optional sendDataToSIMONA( - Set>> dataConnections, - Logger log) + Set>> dataConnections, Logger log) throws InterruptedException { log.debug("Received data from {}", extSimulatorName); @@ -192,45 +189,40 @@ protected Optional sendDataToSIMONA( Optional maybeNextTick = dataContainer.getMaybeNextTick(); dataConnections.stream() - .filter(Optional::isPresent) - .map(Optional::get) - .forEach(con -> con.convertAndSend(tick, data, maybeNextTick, log)); + .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 { + 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)); + log.debug( + "[{}] Received grid results from SIMONA!\n{}", tick, resultMapToString(resultsToBeSend)); dataQueueSimonaApiToExtCoSimulator.queueData( - new ExtResultContainer(tick, resultsToBeSend, nextTick)); + 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 { + 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)); + log.debug( + "[{}] Received flex option results from SIMONA!\n{}", + tick, + resultMapToString(resultsToBeSend)); dataQueueSimonaApiToExtCoSimulator.queueData( - new ExtResultContainer(tick, resultsToBeSend, nextTick)); + new ExtResultContainer(tick, resultsToBeSend, nextTick)); log.info("Sent flex option results for tick {} to {}", tick, extSimulatorName); } @@ -243,10 +235,7 @@ protected void sendFlexOptionResultsToExt( * @param log logger */ protected void sendResultDataToExt( - ExtResultDataConnection connection, - long tick, - Optional maybeNextTick, - Logger log) + ExtResultDataConnection connection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { log.debug("Request results from SIMONA!"); Map resultsToBeSend = connection.requestResults(tick); @@ -256,12 +245,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() { From e171bf5585aa9dd57eef71a19f906286eb2d91b2 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 24 Jan 2025 10:37:59 +0100 Subject: [PATCH 04/80] Update `simosaik`. --- .../data/results/ExtResultDataConnection.java | 11 ++ .../ExtDataConnectionException.java | 23 +++ .../exceptions/NoExtSimulationException.java | 5 +- .../api/simulation/ExtCoSimulation.java | 165 +++++++++++------- .../simulation/mapping/ExtEntityMapping.java | 5 + 5 files changed, 147 insertions(+), 62 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/results/ExtResultDataConnection.java b/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java index 02ab982c..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 @@ -107,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. */ @@ -123,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( 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 b00fb700..27a4af64 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -10,12 +10,12 @@ 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.ExtEntityMapping; import java.util.*; @@ -63,18 +63,18 @@ protected static Set toSet( * * @param mapping between the external simulation and SIMONA. * @param log logger - * @return an option for an ext primary data connection + * @return an ext primary data connection */ - public static Optional buildPrimaryConnection( + public static ExtPrimaryDataConnection buildPrimaryConnection( ExtEntityMapping mapping, Logger log) { Map primaryMapping = mapping.getExtId2UuidMapping(DataType.EXT_PRIMARY_INPUT); if (primaryMapping.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)); + return new ExtPrimaryDataConnection(primaryMapping); } } @@ -83,18 +83,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); } } @@ -103,9 +102,9 @@ 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); @@ -113,22 +112,47 @@ public static Optional buildResultConnection( 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 @@ -149,8 +173,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 @@ -170,71 +219,65 @@ 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); + 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); + 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 flex option results from SIMONA!\n{}", + "[{}] 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); + 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( + protected void sendResultToExt( ExtResultDataConnection connection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { log.debug("Request results from SIMONA!"); 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..b70367fa 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,11 @@ public ExtEntityMapping(List extEntityEntryList) { extEntityEntryList.stream().collect(Collectors.groupingBy(ExtEntityEntry::dataType)); } + /** Returns the data types of this mapping. */ + public Set getDataTypes() { + return extEntities.keySet(); + } + /** * Mapping external id to SIMONA uuid * From 821479fd5ac19abcb7f6304af1337087e2d2a889 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 24 Feb 2025 13:33:59 +0100 Subject: [PATCH 05/80] Some enhancements. --- .../primarydata/ExtPrimaryDataConnection.java | 14 +++++++++++ .../api/simulation/ExtCoSimulation.java | 24 +++++++++++++++---- .../simulation/mapping/ExtEntityMapping.java | 10 ++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) 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/simulation/ExtCoSimulation.java b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java index 27a4af64..def80428 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -17,6 +17,7 @@ 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; @@ -65,16 +66,31 @@ protected static Set toSet( * @param log logger * @return an ext primary data connection */ + @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."); throw new ExtDataConnectionException(ExtPrimaryDataConnection.class); } else { - log.info("Primary data connection with {} entities created.", primaryMapping.size()); - return 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; } } 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 b70367fa..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 @@ -24,6 +24,16 @@ 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 * From dfd6900ff7235334db4bfa34e64831bb901d033e Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 24 Feb 2025 14:45:05 +0100 Subject: [PATCH 06/80] 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 8323f56e1dd7f4d9790d6509718cc1183f75b5f7 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 24 Feb 2025 14:54:40 +0100 Subject: [PATCH 07/80] Adding some classes. --- .../simona/api/data/em/NoSetPointValue.java | 17 ++++++ .../model/DesaggFlexOptionsResult.java | 57 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/main/java/edu/ie3/simona/api/data/em/NoSetPointValue.java create mode 100644 src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java diff --git a/src/main/java/edu/ie3/simona/api/data/em/NoSetPointValue.java b/src/main/java/edu/ie3/simona/api/data/em/NoSetPointValue.java new file mode 100644 index 00000000..368cfd8a --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/NoSetPointValue.java @@ -0,0 +1,17 @@ +/* + * © 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.em; + +import edu.ie3.datamodel.models.value.PValue; +import javax.measure.quantity.Power; +import tech.units.indriya.ComparableQuantity; + +public class NoSetPointValue extends PValue { + public NoSetPointValue(ComparableQuantity p) { + super(p); + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java new file mode 100644 index 00000000..da779e67 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java @@ -0,0 +1,57 @@ +/* + * © 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.results.model; + +import edu.ie3.datamodel.models.result.system.FlexOptionsResult; +import java.time.ZonedDateTime; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; +import javax.measure.quantity.Power; +import tech.units.indriya.ComparableQuantity; + +public class DesaggFlexOptionsResult extends FlexOptionsResult { + + private final Map connectedFlexOptionResults; + + public DesaggFlexOptionsResult( + ZonedDateTime time, + UUID inputModel, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax, + Map connectedFlexOptionResults) { + super(time, inputModel, pRef, pMin, pMax); + this.connectedFlexOptionResults = connectedFlexOptionResults; + } + + public DesaggFlexOptionsResult( + FlexOptionsResult flexOptionsResult, + Map connectedFlexOptionResults) { + super( + flexOptionsResult.getTime(), + flexOptionsResult.getInputModel(), + flexOptionsResult.getpRef(), + flexOptionsResult.getpMin(), + flexOptionsResult.getpMax()); + this.connectedFlexOptionResults = connectedFlexOptionResults; + } + + public DesaggFlexOptionsResult(FlexOptionsResult flexOptionsResult) { + super( + flexOptionsResult.getTime(), + flexOptionsResult.getInputModel(), + flexOptionsResult.getpRef(), + flexOptionsResult.getpMin(), + flexOptionsResult.getpMax()); + this.connectedFlexOptionResults = Collections.emptyMap(); + } + + public Map getConnectedFlexOptionResults() { + return connectedFlexOptionResults; + } +} From 6eb6b6643806f77c92d964ea228786e83164482d Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 24 Feb 2025 15:04:32 +0100 Subject: [PATCH 08/80] 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); } } From ca89b0be8f7baa3bbb51020e7eadf463157c263c Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 25 Feb 2025 10:38:24 +0100 Subject: [PATCH 09/80] Fixing bugs. --- .../edu/ie3/simona/api/data/results/ExtResultContainer.java | 2 +- .../simona/api/data/results/ExtResultDataConnection.java | 6 ------ 2 files changed, 1 insertion(+), 7 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 4379905e..d83bb83e 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 @@ -80,7 +80,7 @@ public double getVoltageDeviation(String assetId) { Quantities.getQuantity(-1.0, PU).add(nodeResult.getvMag()); return vMagDev.getValue().doubleValue(); } else { - throw new IllegalArgumentException("VOLTAGE DEVIATION is only available for NodeResult's!"); + throw new IllegalArgumentException("VOLTAGE DEVIATION is only available for NodeResult's! AssetId: "+ assetId); } } 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 01b1c088..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 @@ -113,12 +113,6 @@ private List requestParticiapntResultsList(long tick) 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. */ From 601e55380ba210e2e4d5be98cd09d4c72b0f30da Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 27 Feb 2025 13:55:11 +0100 Subject: [PATCH 10/80] Some Enhancements. --- .../model/DesaggFlexOptionsResult.java | 57 ------------------- .../api/simulation/ExtCoSimulation.java | 33 +++++++---- 2 files changed, 22 insertions(+), 68 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java diff --git a/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java deleted file mode 100644 index da779e67..00000000 --- a/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * © 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.results.model; - -import edu.ie3.datamodel.models.result.system.FlexOptionsResult; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.Map; -import java.util.UUID; -import javax.measure.quantity.Power; -import tech.units.indriya.ComparableQuantity; - -public class DesaggFlexOptionsResult extends FlexOptionsResult { - - private final Map connectedFlexOptionResults; - - public DesaggFlexOptionsResult( - ZonedDateTime time, - UUID inputModel, - ComparableQuantity pRef, - ComparableQuantity pMin, - ComparableQuantity pMax, - Map connectedFlexOptionResults) { - super(time, inputModel, pRef, pMin, pMax); - this.connectedFlexOptionResults = connectedFlexOptionResults; - } - - public DesaggFlexOptionsResult( - FlexOptionsResult flexOptionsResult, - Map connectedFlexOptionResults) { - super( - flexOptionsResult.getTime(), - flexOptionsResult.getInputModel(), - flexOptionsResult.getpRef(), - flexOptionsResult.getpMin(), - flexOptionsResult.getpMax()); - this.connectedFlexOptionResults = connectedFlexOptionResults; - } - - public DesaggFlexOptionsResult(FlexOptionsResult flexOptionsResult) { - super( - flexOptionsResult.getTime(), - flexOptionsResult.getInputModel(), - flexOptionsResult.getpRef(), - flexOptionsResult.getpMin(), - flexOptionsResult.getpMax()); - this.connectedFlexOptionResults = Collections.emptyMap(); - } - - public Map getConnectedFlexOptionResults() { - return connectedFlexOptionResults; - } -} 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 15a749ef..f8ca934d 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -50,15 +50,6 @@ protected ExtCoSimulation(String simulationName, String extSimulatorName) { this.dataQueueSimonaApiToExtCoSimulator = new DataQueueExtSimulationExtSimulator<>(); } - @SafeVarargs - protected static Set toSet( - Optional... optionals) { - return Arrays.stream(optionals) - .filter(Optional::isPresent) - .map(Optional::get) - .collect(Collectors.toSet()); - } - /** * Builds an {@link ExtPrimaryDataConnection}. * @@ -159,10 +150,19 @@ protected void sendPrimaryDataToSimona( Optional maybeNextTick, Logger log) throws InterruptedException { + ExtInputDataContainer inputData = dataQueueExtCoSimulatorToSimonaApi.takeData(); + + if (inputData.getTick() != tick) { + throw new RuntimeException( + String.format( + "Provided input data for tick %d, but SIMONA expects input data for tick %d", + inputData.getTick(), tick)); + } + sendPrimaryDataToSimona( extPrimaryDataConnection, tick, - dataQueueExtCoSimulatorToSimonaApi.takeData().getSimonaInputMap(), + inputData.getSimonaInputMap(), maybeNextTick, log); } @@ -203,10 +203,19 @@ protected void sendPrimaryDataToSimona( protected void sendEmDataToSimona( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { + ExtInputDataContainer inputData = dataQueueExtCoSimulatorToSimonaApi.takeData(); + + if (inputData.getTick() != tick) { + throw new RuntimeException( + String.format( + "Provided input data for tick %d, but SIMONA expects input data for tick %d", + inputData.getTick(), tick)); + } + sendEmDataToSimona( extEmDataConnection, tick, - dataQueueExtCoSimulatorToSimonaApi.takeData().getSimonaInputMap(), + inputData.getSimonaInputMap(), maybeNextTick, log); } @@ -302,6 +311,8 @@ protected void sendResultToExt( log.debug("Sent results to {}", extSimulatorName); } + // helper methods + private String resultMapToString(Map results) { StringBuilder resultString = new StringBuilder(); From 65d10b8736019682fc0239141b57c11976afbc47 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 27 Feb 2025 14:07:12 +0100 Subject: [PATCH 11/80] Some refactoring. --- .../model/DesaggFlexOptionsResult.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java diff --git a/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java new file mode 100644 index 00000000..f87507c5 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java @@ -0,0 +1,52 @@ +package edu.ie3.simona.api.data.results.model; + +import edu.ie3.datamodel.models.result.system.FlexOptionsResult; +import tech.units.indriya.ComparableQuantity; + +import javax.measure.quantity.Power; +import java.time.ZonedDateTime; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + +public class DesaggFlexOptionsResult extends FlexOptionsResult { + + private final Map connectedFlexOptionResults; + + public DesaggFlexOptionsResult( + ZonedDateTime time, + UUID inputModel, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax, + Map connectedFlexOptionResults) { + super(time, inputModel, pRef, pMin, pMax); + this.connectedFlexOptionResults = connectedFlexOptionResults; + } + + public DesaggFlexOptionsResult( + FlexOptionsResult flexOptionsResult, + Map connectedFlexOptionResults) { + super( + flexOptionsResult.getTime(), + flexOptionsResult.getInputModel(), + flexOptionsResult.getpRef(), + flexOptionsResult.getpMin(), + flexOptionsResult.getpMax()); + this.connectedFlexOptionResults = connectedFlexOptionResults; + } + + public DesaggFlexOptionsResult(FlexOptionsResult flexOptionsResult) { + super( + flexOptionsResult.getTime(), + flexOptionsResult.getInputModel(), + flexOptionsResult.getpRef(), + flexOptionsResult.getpMin(), + flexOptionsResult.getpMax()); + this.connectedFlexOptionResults = Collections.emptyMap(); + } + + public Map getConnectedFlexOptionResults() { + return connectedFlexOptionResults; + } +} From 1bb0ad85cc769a95268c5ba2eef07cac1751dcb2 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 4 Mar 2025 14:09:33 +0100 Subject: [PATCH 12/80] Updating to PSDM version `6.0.0`. --- build.gradle | 2 +- .../api/data/results/ExtResultContainer.java | 11 +++++----- .../data/results/ExtResultDataConnection.java | 22 +++++++++---------- .../ontology/ProvideResultEntities.java | 6 ++--- .../api/simulation/ExtCoSimulation.java | 16 +++++++------- 5 files changed, 28 insertions(+), 29 deletions(-) diff --git a/build.gradle b/build.gradle index 9998f852..e1b5309f 100644 --- a/build.gradle +++ b/build.gradle @@ -61,7 +61,7 @@ dependencies{ } //PSDM - implementation('com.github.ie3-institute:PowerSystemDataModel:5.1.0') { + implementation('com.github.ie3-institute:PowerSystemDataModel:6.0.0') { exclude group: 'org.apache.logging.log4j' exclude group: 'org.slf4j' /* Exclude our own nested dependencies */ 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 d83bb83e..cc339956 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 @@ -8,9 +8,8 @@ import static edu.ie3.util.quantities.PowerSystemUnits.PU; -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.NodeResult; import edu.ie3.datamodel.models.result.connector.LineResult; import edu.ie3.datamodel.models.result.system.SystemParticipantResult; import edu.ie3.simona.api.data.ExtDataContainer; @@ -33,7 +32,7 @@ public class ExtResultContainer implements ExtDataContainer { * Map external id to result from SIMONA ATTENTION: The time stamp of the result entities is not * necessarily corresponding to the tick */ - private final Map simonaResultsMap; + private final Map simonaResultsMap; /** * Container class for result data from SIMONA @@ -43,17 +42,17 @@ public class ExtResultContainer implements ExtDataContainer { * @param nextTick tick the external simulation can expect the next results */ public ExtResultContainer( - long tick, Map simonaResultsMap, Optional nextTick) { + long tick, Map simonaResultsMap, Optional nextTick) { this.tick = tick; this.simonaResultsMap = simonaResultsMap; this.maybeNextTick = nextTick; } - public ExtResultContainer(long tick, Map simonaResultsMap) { + public ExtResultContainer(long tick, Map simonaResultsMap) { this(tick, simonaResultsMap, Optional.empty()); } - public Map getResults() { + public Map getResults() { return simonaResultsMap; } 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 535927e1..cc58f9bc 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 @@ -6,7 +6,7 @@ package edu.ie3.simona.api.data.results; -import edu.ie3.datamodel.models.result.ModelResultEntity; +import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.result.NodeResult; import edu.ie3.datamodel.models.result.system.FlexOptionsResult; import edu.ie3.datamodel.models.result.system.SystemParticipantResult; @@ -86,7 +86,7 @@ public List getFlexOptionAssets() { } /** Method that an external simulation can request results from SIMONA as a list. */ - private List requestResultList(long tick) throws InterruptedException { + private List requestResultList(long tick) throws InterruptedException { List allExtEntities = Stream.concat( Stream.concat(getFlexOptionAssets().stream(), getGridResultDataAssets().stream()), @@ -96,18 +96,18 @@ private List requestResultList(long tick) throws InterruptedE return receiveWithType(ProvideResultEntities.class).results(); } - private List requestFlexOptionResultsList(long tick) + private List requestFlexOptionResultsList(long tick) throws InterruptedException { sendExtMsg(new RequestResultEntities(tick, getFlexOptionAssets())); return receiveWithType(ProvideResultEntities.class).results(); } - private List requestGridResultsList(long tick) throws InterruptedException { + private List requestGridResultsList(long tick) throws InterruptedException { sendExtMsg(new RequestResultEntities(tick, getGridResultDataAssets())); return receiveWithType(ProvideResultEntities.class).results(); } - private List requestParticiapntResultsList(long tick) + private List requestParticiapntResultsList(long tick) throws InterruptedException { sendExtMsg(new RequestResultEntities(tick, getParticipantResultDataAssets())); return receiveWithType(ProvideResultEntities.class).results(); @@ -116,26 +116,26 @@ private List requestParticiapntResultsList(long tick) /** * Method that an external simulation can request results from SIMONA as a map string to object. */ - public Map requestResults(long tick) throws InterruptedException { + public Map requestResults(long tick) throws InterruptedException { return createResultMap(requestResultList(tick)); } - public Map requestFlexOptionResults(long tick) + public Map requestFlexOptionResults(long tick) throws InterruptedException { return createResultMap(requestFlexOptionResultsList(tick)); } - public Map requestGridResults(long tick) throws InterruptedException { + public Map requestGridResults(long tick) throws InterruptedException { return createResultMap(requestGridResultsList(tick)); } - public Map requestParticipantResults(long tick) + public Map requestParticipantResults(long tick) throws InterruptedException { return createResultMap(requestParticiapntResultsList(tick)); } - protected Map createResultMap(List results) { - Map resultMap = new HashMap<>(); + protected Map createResultMap(List results) { + Map resultMap = new HashMap<>(); results.forEach( result -> { if (result instanceof NodeResult nodeResult) { diff --git a/src/main/java/edu/ie3/simona/api/data/results/ontology/ProvideResultEntities.java b/src/main/java/edu/ie3/simona/api/data/results/ontology/ProvideResultEntities.java index 525d702c..0c0d003f 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ontology/ProvideResultEntities.java +++ b/src/main/java/edu/ie3/simona/api/data/results/ontology/ProvideResultEntities.java @@ -6,15 +6,15 @@ package edu.ie3.simona.api.data.results.ontology; -import edu.ie3.datamodel.models.result.ModelResultEntity; +import edu.ie3.datamodel.models.result.ResultEntity; import java.util.List; import java.util.Map; import java.util.UUID; /** Provides a list of results from SIMONA to an external simulation. */ -public record ProvideResultEntities(List results) +public record ProvideResultEntities(List results) implements ResultDataResponseMessageToExt { - public ProvideResultEntities(Map resultMap) { + public ProvideResultEntities(Map resultMap) { this(resultMap.values().stream().toList()); } } 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 f8ca934d..5235e4eb 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -6,10 +6,9 @@ package edu.ie3.simona.api.simulation; -import edu.ie3.datamodel.models.result.ModelResultEntity; +import edu.ie3.datamodel.models.result.ResultEntity; 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.ExtInputDataContainer; import edu.ie3.simona.api.data.em.ExtEmDataConnection; import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; @@ -19,9 +18,10 @@ 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 org.slf4j.Logger; + 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 @@ -277,7 +277,7 @@ protected void sendFlexOptionResultsToExt( private void sendSingleResultType( String type, - Map resultsToBeSend, + Map resultsToBeSend, long tick, Optional nextTick, Logger log) @@ -304,7 +304,7 @@ protected void sendResultToExt( ExtResultDataConnection connection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { log.debug("Request results from SIMONA!"); - Map resultsToBeSend = connection.requestResults(tick); + Map resultsToBeSend = connection.requestResults(tick); log.debug("Received results from SIMONA!"); dataQueueSimonaApiToExtCoSimulator.queueData( new ExtResultContainer(tick, resultsToBeSend, maybeNextTick)); @@ -313,12 +313,12 @@ protected void sendResultToExt( // helper methods - private String resultMapToString(Map results) { + private String resultMapToString(Map results) { StringBuilder resultString = new StringBuilder(); - for (Map.Entry entry : results.entrySet()) { + for (Map.Entry entry : results.entrySet()) { String key = entry.getKey(); - ModelResultEntity value = entry.getValue(); + ResultEntity value = entry.getValue(); resultString .append("id = ") From 850564e5da85be28320615fd8e7f49c7bae2a607 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 6 Mar 2025 15:30:12 +0100 Subject: [PATCH 13/80] Refactoring external data connections. --- .../ie3/simona/api/data/BiDirectional.java | 41 ++++ .../api/data/ExtInputDataConnection.java | 12 +- .../ExtInputDataConnectionWithMapping.java | 11 +- .../api/data/ExtOutputDataConnection.java | 12 +- .../api/data/WithDataResponseToExt.java | 53 +++++ .../api/data/em/ExtEmDataConnection.java | 91 +++++++-- .../api/data/em/model/EmSetPointResult.java | 33 ++++ .../api/data/em/model/FlexOptionValue.java | 15 ++ .../ontology/EmDataResponseMessageToExt.java | 11 ++ .../em/ontology/EmSetPointDataResponse.java | 15 ++ .../data/em/ontology/FlexOptionsResponse.java | 15 ++ .../em/ontology/ProvideEmSetPointData.java | 2 +- .../data/em/ontology/ProvideFlexOptions.java | 17 ++ .../em/ontology/RequestEmFlexResults.java | 14 ++ .../data/em/ontology/RequestEmSetPoints.java | 14 ++ .../api/data/ev/ExtEvDataConnection.java | 2 +- .../primarydata/ExtPrimaryDataConnection.java | 3 +- .../api/data/results/ExtResultContainer.java | 5 +- .../data/results/ExtResultDataConnection.java | 55 +----- .../model/DesaggFlexOptionsResult.java | 87 +++++---- .../api/simulation/ExtCoSimulation.java | 183 ++++++++++++++---- .../simulation/mapping/ExtEntityMapping.java | 55 ++++++ 22 files changed, 583 insertions(+), 163 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/data/BiDirectional.java create mode 100644 src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataResponseMessageToExt.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexOptions.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmSetPoints.java diff --git a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java new file mode 100644 index 00000000..637b516a --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java @@ -0,0 +1,41 @@ +/* + * © 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.simona.api.data.ontology.DataMessageFromExt; +import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; +import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; +import org.apache.pekko.actor.ActorRef; + +/** + * Enables bidirectional communication when extended by an external data connection. + * + * @param type of message to SIMONA + * @param type of response messages to ext + */ +public class BiDirectional + extends WithDataResponseToExt 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; + + @Override + public void setActorRefs(ActorRef dataService, ActorRef extSimAdapter) { + this.dataService = dataService; + this.extSimAdapter = extSimAdapter; + } + + @Override + 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()); + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java index d8a29a75..aca40936 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java @@ -6,9 +6,10 @@ package edu.ie3.simona.api.data; +import edu.ie3.simona.api.data.ontology.DataMessageFromExt; import org.apache.pekko.actor.ActorRef; -public interface ExtInputDataConnection extends ExtDataConnection { +public interface ExtInputDataConnection extends ExtDataConnection { /** * Sets the actor refs for data and control flow. @@ -18,4 +19,13 @@ public interface ExtInputDataConnection extends ExtDataConnection { * @param extSimAdapter actor ref to the extSimAdapter */ void setActorRefs(ActorRef dataService, ActorRef extSimAdapter); + + /** + * Send information from the external simulation to SIMONA's external data service. Furthermore, + * ExtSimAdapter within SIMONA is instructed to activate the external data service with the + * current tick. + * + * @param msg the data/information that is sent to SIMONA's result data service + */ + void sendExtMsg(M msg); } diff --git a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java index 12781b0b..9da67568 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java @@ -15,7 +15,7 @@ public abstract class ExtInputDataConnectionWithMapping< M extends DataMessageFromExt, V extends Value> - implements ExtInputDataConnection { + implements ExtInputDataConnection { /** Actor reference to service that handles data within SIMONA */ private ActorRef dataService; @@ -24,7 +24,7 @@ public abstract class ExtInputDataConnectionWithMapping< private ActorRef extSimAdapter; /** Assets that provide data to SIMONA */ - private final Map extDataMapping; + protected final Map extDataMapping; protected ExtInputDataConnectionWithMapping(Map extDataMapping) { this.extDataMapping = extDataMapping; @@ -50,13 +50,6 @@ public abstract void convertAndSend( /** 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 diff --git a/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java index 6ac15e75..34716d16 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java @@ -6,13 +6,14 @@ package edu.ie3.simona.api.data; +import edu.ie3.simona.api.data.ontology.DataMessageFromExt; import org.apache.pekko.actor.ActorRef; /** * Interface for a connection between SIMONA and an external simulation with data flow from SIMONA * to external */ -public interface ExtOutputDataConnection extends ExtDataConnection { +public interface ExtOutputDataConnection extends ExtDataConnection { /** * Sets the actor refs for data and control flow @@ -24,4 +25,13 @@ public interface ExtOutputDataConnection extends ExtDataConnection { */ void setActorRefs( ActorRef extResultDataService, ActorRef dataServiceActivation, ActorRef extSimAdapter); + + /** + * Send information from the external simulation to SIMONA's external data service. Furthermore, + * ExtSimAdapter within SIMONA is instructed to activate the external data service with the + * current tick. + * + * @param msg the data/information that is sent to SIMONA's result data service + */ + void sendExtMsg(M msg); } diff --git a/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java b/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java new file mode 100644 index 00000000..71ffb853 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java @@ -0,0 +1,53 @@ +/* + * © 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.simona.api.data.ontology.DataResponseMessageToExt; +import java.util.concurrent.LinkedBlockingQueue; + +/** + * Enables receiving data responses form SIMONA. + * + * @param type of response messages to ext + */ +public class WithDataResponseToExt { + + /** Data message queue containing messages from SIMONA */ + private final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); + + /** Queues message from SIMONA that should be handled by the external simulation. */ + public void queueExtResponseMsg(T msg) throws InterruptedException { + receiveTriggerQueue.put(msg); + } + + /** + * Waits until a message of given type is added to the queue. If the message has a different type, + * a RuntimeException is thrown. This method blocks until having received a response from SIMONA. + * + * @param expectedMessageClass the expected class of the message to be received + * @return a message of the expected type once it has been received + * @param the type of the expected message + * @throws InterruptedException if the thread running this has been interrupted during the + * blocking operation + */ + @SuppressWarnings("unchecked") + protected R receiveWithType(Class expectedMessageClass) + throws InterruptedException { + // blocks until actor puts something here + T msg = receiveTriggerQueue.take(); + + if (msg.getClass().equals(expectedMessageClass)) { + return (R) msg; + } else + throw new RuntimeException( + "Received unexpected message '" + + msg + + "', expected type '" + + expectedMessageClass + + "'"); + } +} 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 ad1a801b..1719ada3 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 @@ -6,50 +6,109 @@ package edu.ie3.simona.api.data.em; +import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; -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.BiDirectional; +import edu.ie3.simona.api.data.em.model.FlexOptionValue; +import edu.ie3.simona.api.data.em.ontology.*; +import edu.ie3.simona.api.simulation.mapping.ExtEntityMapping; import java.util.*; +import java.util.stream.Collectors; import org.slf4j.Logger; /** Enables data connection of em data between SIMONA and SimonaAPI */ public class ExtEmDataConnection - extends ExtInputDataConnectionWithMapping { + extends BiDirectional { + + /** Assets that provide data to SIMONA */ + private final Map extEmMapping; + + /** Assets that provide data to ext */ + private final Map mosaikMapping; public ExtEmDataConnection(Map extEmMapping) { - super(extEmMapping); + this.extEmMapping = extEmMapping; + + this.mosaikMapping = + extEmMapping.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); } /** Returns a list of the uuids of the em agents that expect external set points */ public List getControlledEms() { - return getDataAssets(); + return new ArrayList<>(extEmMapping.values()); } /** - * Converts the data and sends them to SIMONA. + * Converts the em flex options 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( + public void convertAndSendFlexOptions( long tick, Map data, Optional maybeNextTick, Logger log) { // filtering the data and converting the keys - Map convertedMap = convert(data); + Map emFlexOptions = ExtEntityMapping.mapToSimona(data, extEmMapping); - if (convertedMap.isEmpty()) { - log.warn("No em data found! Sending no em data to SIMONA for tick {}.", tick); + if (emFlexOptions.isEmpty()) { + log.warn("No em flex options found! Sending no em data to SIMONA for tick {}.", tick); } else { - log.debug("Provided SIMONA with em data."); - provideData(tick, convertedMap, maybeNextTick); + log.debug("Provided SIMONA with em flex options."); + sendExtMsg(new ProvideFlexOptions(tick, emFlexOptions, maybeNextTick)); } } - /** Provide primary data from an external simulation for one tick. */ - public void provideData(long tick, Map emData, Optional maybeNextTick) { - sendExtMsg(new ProvideEmSetPointData(tick, emData, maybeNextTick)); + /** + * Converts the em set points 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 convertAndSendSetPoints( + long tick, Map data, Optional maybeNextTick, Logger log) { + // filtering the data and converting the keys + Map emSetPoints = ExtEntityMapping.mapToSimona(data, extEmMapping); + + if (emSetPoints.isEmpty()) { + log.warn("No em set points found! Sending no em data to SIMONA for tick {}.", tick); + } else { + log.debug("Provided SIMONA with em set points."); + sendExtMsg(new ProvideEmSetPointData(tick, emSetPoints, maybeNextTick)); + } + } + + /** + * Method to request em flexibility options from SIMONA. + * + * @param tick for which set points are requested + * @param emEntities for which set points are requested + * @return an {@link EmSetPointDataResponse} message + * @throws InterruptedException - on interruptions + */ + public Map requestEmFlexResults(long tick, List emEntities) + throws InterruptedException { + sendExtMsg(new RequestEmFlexResults(tick, emEntities)); + return ExtEntityMapping.mapToExt( + receiveWithType(FlexOptionsResponse.class).flexOptions(), mosaikMapping); + } + + /** + * Method to request em set points from SIMONA. + * + * @param tick for which set points are requested + * @param emEntities for which set points are requested + * @return an {@link EmSetPointDataResponse} message + * @throws InterruptedException - on interruptions + */ + public Map requestEmSetPoints(long tick, List emEntities) + throws InterruptedException { + sendExtMsg(new RequestEmSetPoints(tick, emEntities)); + return ExtEntityMapping.mapToExt( + receiveWithType(EmSetPointDataResponse.class).emData(), mosaikMapping); } } diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java new file mode 100644 index 00000000..e4259c3c --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java @@ -0,0 +1,33 @@ +/* + * © 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.em.model; + +import edu.ie3.datamodel.models.result.ResultEntity; +import edu.ie3.datamodel.models.value.PValue; +import java.time.ZonedDateTime; +import java.util.UUID; + +/** Em set point result. */ +public class EmSetPointResult extends ResultEntity { + + private final PValue setPoint; + + /** + * Standard constructor which includes auto generation of the resulting output models uuid. + * + * @param time date and time when the result is produced + * @param inputModel uuid of the input model that produces the result + */ + protected EmSetPointResult(ZonedDateTime time, UUID inputModel, PValue setPoint) { + super(time, inputModel); + this.setPoint = setPoint; + } + + public PValue getSetPoint() { + return setPoint; + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java new file mode 100644 index 00000000..b95126d1 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java @@ -0,0 +1,15 @@ +/* + * © 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.em.model; + +import edu.ie3.datamodel.models.value.Value; +import javax.measure.quantity.Power; +import tech.units.indriya.ComparableQuantity; + +public record FlexOptionValue( + ComparableQuantity pMin, ComparableQuantity pRef, ComparableQuantity pMax) + implements Value {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataResponseMessageToExt.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataResponseMessageToExt.java new file mode 100644 index 00000000..470a6483 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataResponseMessageToExt.java @@ -0,0 +1,11 @@ +/* + * © 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.em.ontology; + +import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; + +public interface EmDataResponseMessageToExt extends DataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java new file mode 100644 index 00000000..90a48976 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java @@ -0,0 +1,15 @@ +/* + * © 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.data.em.ontology; + +import edu.ie3.simona.api.data.em.model.EmSetPointResult; +import java.util.Map; +import java.util.UUID; + +/** Message that provides em data (set points) to an external simulation. */ +public record EmSetPointDataResponse(long tick, Map emData) + implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java new file mode 100644 index 00000000..7c7a039a --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java @@ -0,0 +1,15 @@ +/* + * © 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.em.ontology; + +import edu.ie3.datamodel.models.result.system.FlexOptionsResult; +import java.util.Map; +import java.util.UUID; + +/** Message that provides em data (flexibility options) to an external simulation. */ +public record FlexOptionsResponse(long tick, Map flexOptions) + implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java index dc505dca..d3dc699a 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java @@ -11,7 +11,7 @@ import java.util.Optional; import java.util.UUID; -/** Message that provides em data (set points) from an external simulation */ +/** Message that provides em data (set points) from an external simulation. */ public record ProvideEmSetPointData( long tick, Map emData, Optional maybeNextTick) implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexOptions.java new file mode 100644 index 00000000..51e21412 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexOptions.java @@ -0,0 +1,17 @@ +/* + * © 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.em.ontology; + +import edu.ie3.simona.api.data.em.model.FlexOptionValue; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +/** Message that provides em data (flexibility options) from an external simulation. */ +public record ProvideFlexOptions( + long tick, Map flexOptions, Optional maybeNextTick) + implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java new file mode 100644 index 00000000..925164d1 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java @@ -0,0 +1,14 @@ +/* + * © 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.em.ontology; + +import java.util.List; +import java.util.UUID; + +/** Request em set points from SIMONA in the given tick. */ +public record RequestEmFlexResults(long tick, List emEntities) + implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmSetPoints.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmSetPoints.java new file mode 100644 index 00000000..ac78126d --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmSetPoints.java @@ -0,0 +1,14 @@ +/* + * © 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.em.ontology; + +import java.util.List; +import java.util.UUID; + +/** Request em set points from SIMONA in the given tick. */ +public record RequestEmSetPoints(long tick, List emEntities) + implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java b/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java index 53a71e87..7d6eb536 100644 --- a/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java @@ -17,7 +17,7 @@ import java.util.concurrent.LinkedBlockingQueue; import org.apache.pekko.actor.ActorRef; -public class ExtEvDataConnection implements ExtInputDataConnection { +public class ExtEvDataConnection implements ExtInputDataConnection { /** Data message queue containing messages from SIMONA */ public final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); 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 d65eaa39..134c4001 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 @@ -10,6 +10,7 @@ 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 edu.ie3.simona.api.simulation.mapping.ExtEntityMapping; import java.util.List; import java.util.Map; import java.util.Optional; @@ -47,7 +48,7 @@ public Optional> getValueClass(UUID uuid) { public void convertAndSend( long tick, Map data, Optional maybeNextTick, Logger log) { // filtering the data and converting the keys - Map convertedMap = convert(data); + Map convertedMap = ExtEntityMapping.mapToSimona(data, extDataMapping); if (convertedMap.isEmpty()) { log.warn("No primary data found! Sending no primary data to SIMONA for tick {}.", tick); 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 cc339956..d3c26b34 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 @@ -8,8 +8,8 @@ import static edu.ie3.util.quantities.PowerSystemUnits.PU; -import edu.ie3.datamodel.models.result.ResultEntity; 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; @@ -79,7 +79,8 @@ public double getVoltageDeviation(String assetId) { Quantities.getQuantity(-1.0, PU).add(nodeResult.getvMag()); return vMagDev.getValue().doubleValue(); } else { - throw new IllegalArgumentException("VOLTAGE DEVIATION is only available for NodeResult's! AssetId: "+ assetId); + throw new IllegalArgumentException( + "VOLTAGE DEVIATION is only available for NodeResult's! AssetId: " + assetId); } } 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 cc58f9bc..319b027e 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 @@ -6,11 +6,12 @@ package edu.ie3.simona.api.data.results; -import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.result.NodeResult; +import edu.ie3.datamodel.models.result.ResultEntity; 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.WithDataResponseToExt; import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; import edu.ie3.simona.api.data.results.ontology.ProvideResultEntities; import edu.ie3.simona.api.data.results.ontology.RequestResultEntities; @@ -20,16 +21,12 @@ import java.util.List; 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 */ -public class ExtResultDataConnection implements ExtOutputDataConnection { - - /** Data message queue containing messages from SIMONA */ - public final LinkedBlockingQueue receiveTriggerQueue = - new LinkedBlockingQueue<>(); +public class ExtResultDataConnection extends WithDataResponseToExt + implements ExtOutputDataConnection { /** Actor reference to service that handles result data within SIMONA */ private ActorRef extResultDataService; @@ -96,8 +93,7 @@ private List requestResultList(long tick) throws InterruptedExcept 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(); } @@ -107,8 +103,7 @@ private List requestGridResultsList(long tick) throws InterruptedE return receiveWithType(ProvideResultEntities.class).results(); } - private List requestParticiapntResultsList(long tick) - throws InterruptedException { + private List requestParticipantResultsList(long tick) throws InterruptedException { sendExtMsg(new RequestResultEntities(tick, getParticipantResultDataAssets())); return receiveWithType(ProvideResultEntities.class).results(); } @@ -120,8 +115,7 @@ public Map requestResults(long tick) throws InterruptedExc return createResultMap(requestResultList(tick)); } - public Map requestFlexOptionResults(long tick) - throws InterruptedException { + public Map requestFlexOptionResults(long tick) throws InterruptedException { return createResultMap(requestFlexOptionResultsList(tick)); } @@ -131,7 +125,7 @@ public Map requestGridResults(long tick) throws Interrupte public Map requestParticipantResults(long tick) throws InterruptedException { - return createResultMap(requestParticiapntResultsList(tick)); + return createResultMap(requestParticipantResultsList(tick)); } protected Map createResultMap(List results) { @@ -167,37 +161,4 @@ public void sendExtMsg(ResultDataMessageFromExt msg) { // we need to schedule data receiver activation with scheduler extSimAdapter.tell(new ScheduleDataServiceMessage(dataServiceActivation), ActorRef.noSender()); } - - /** Queues message from SIMONA that should be handled by the external simulation. */ - public void queueExtResponseMsg(ResultDataResponseMessageToExt msg) throws InterruptedException { - receiveTriggerQueue.put(msg); - } - - /** - * Waits until a message of given type is added to the queue. If the message has a different type, - * a RuntimeException is thrown. This method blocks until having received a response from SIMONA. - * - * @param expectedMessageClass the expected class of the message to be received - * @return a message of the expected type once it has been received - * @param the type of the expected message - * @throws InterruptedException if the thread running this has been interrupted during the - * blocking operation - */ - @SuppressWarnings("unchecked") - private T receiveWithType( - Class expectedMessageClass) throws InterruptedException { - - // blocks until actor puts something here - ResultDataResponseMessageToExt msg = receiveTriggerQueue.take(); - - if (msg.getClass().equals(expectedMessageClass)) { - return (T) msg; - } else - throw new RuntimeException( - "Received unexpected message '" - + msg - + "', expected type '" - + expectedMessageClass - + "'"); - } } diff --git a/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java index f87507c5..da779e67 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java +++ b/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java @@ -1,52 +1,57 @@ +/* + * © 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.results.model; import edu.ie3.datamodel.models.result.system.FlexOptionsResult; -import tech.units.indriya.ComparableQuantity; - -import javax.measure.quantity.Power; import java.time.ZonedDateTime; import java.util.Collections; import java.util.Map; import java.util.UUID; +import javax.measure.quantity.Power; +import tech.units.indriya.ComparableQuantity; public class DesaggFlexOptionsResult extends FlexOptionsResult { - private final Map connectedFlexOptionResults; - - public DesaggFlexOptionsResult( - ZonedDateTime time, - UUID inputModel, - ComparableQuantity pRef, - ComparableQuantity pMin, - ComparableQuantity pMax, - Map connectedFlexOptionResults) { - super(time, inputModel, pRef, pMin, pMax); - this.connectedFlexOptionResults = connectedFlexOptionResults; - } - - public DesaggFlexOptionsResult( - FlexOptionsResult flexOptionsResult, - Map connectedFlexOptionResults) { - super( - flexOptionsResult.getTime(), - flexOptionsResult.getInputModel(), - flexOptionsResult.getpRef(), - flexOptionsResult.getpMin(), - flexOptionsResult.getpMax()); - this.connectedFlexOptionResults = connectedFlexOptionResults; - } - - public DesaggFlexOptionsResult(FlexOptionsResult flexOptionsResult) { - super( - flexOptionsResult.getTime(), - flexOptionsResult.getInputModel(), - flexOptionsResult.getpRef(), - flexOptionsResult.getpMin(), - flexOptionsResult.getpMax()); - this.connectedFlexOptionResults = Collections.emptyMap(); - } - - public Map getConnectedFlexOptionResults() { - return connectedFlexOptionResults; - } + private final Map connectedFlexOptionResults; + + public DesaggFlexOptionsResult( + ZonedDateTime time, + UUID inputModel, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax, + Map connectedFlexOptionResults) { + super(time, inputModel, pRef, pMin, pMax); + this.connectedFlexOptionResults = connectedFlexOptionResults; + } + + public DesaggFlexOptionsResult( + FlexOptionsResult flexOptionsResult, + Map connectedFlexOptionResults) { + super( + flexOptionsResult.getTime(), + flexOptionsResult.getInputModel(), + flexOptionsResult.getpRef(), + flexOptionsResult.getpMin(), + flexOptionsResult.getpMax()); + this.connectedFlexOptionResults = connectedFlexOptionResults; + } + + public DesaggFlexOptionsResult(FlexOptionsResult flexOptionsResult) { + super( + flexOptionsResult.getTime(), + flexOptionsResult.getInputModel(), + flexOptionsResult.getpRef(), + flexOptionsResult.getpMin(), + flexOptionsResult.getpMax()); + this.connectedFlexOptionResults = Collections.emptyMap(); + } + + public Map getConnectedFlexOptionResults() { + return connectedFlexOptionResults; + } } 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 5235e4eb..391dc9ef 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -18,10 +18,9 @@ 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 org.slf4j.Logger; - 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 @@ -50,6 +49,8 @@ protected ExtCoSimulation(String simulationName, String extSimulatorName) { this.dataQueueSimonaApiToExtCoSimulator = new DataQueueExtSimulationExtSimulator<>(); } + // connection helper methods + /** * Builds an {@link ExtPrimaryDataConnection}. * @@ -135,6 +136,8 @@ public static ExtResultDataConnection buildResultConnection( } } + // primary data methods + /** * Function to send primary data to SIMONA using the given {@link ExtPrimaryDataConnection}. This * method will take a value from the {@link #dataQueueExtCoSimulatorToSimonaApi}. @@ -154,17 +157,13 @@ protected void sendPrimaryDataToSimona( if (inputData.getTick() != tick) { throw new RuntimeException( - String.format( - "Provided input data for tick %d, but SIMONA expects input data for tick %d", - inputData.getTick(), tick)); + String.format( + "Provided input data for tick %d, but SIMONA expects input data for tick %d", + inputData.getTick(), tick)); } sendPrimaryDataToSimona( - extPrimaryDataConnection, - tick, - inputData.getSimonaInputMap(), - maybeNextTick, - log); + extPrimaryDataConnection, tick, inputData.getSimonaInputMap(), maybeNextTick, log); } /** @@ -188,9 +187,55 @@ protected void sendPrimaryDataToSimona( log.debug("Provided Primary Data to SIMONA!"); } + // energy management data methods + + /** + * Function to send em flex options from SIMONA to the external simulation using the given {@link + * ExtEmDataConnection}. This method will provide values to the {@link + * #dataQueueSimonaApiToExtCoSimulator}. + * + * @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 + * @throws InterruptedException if the fetching of data is interrupted + */ + protected void sendEmFlexResultsToExt( + ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) + throws InterruptedException { + sendSingleResultType( + "em flexibility option", + extEmDataConnection.requestEmFlexResults(tick, extEmDataConnection.getControlledEms()), + tick, + maybeNextTick, + log); + } + + /** + * Function to send em set points from SIMONA to the external simulation using the given {@link + * ExtEmDataConnection}. This method will provide values to the {@link + * #dataQueueSimonaApiToExtCoSimulator}. + * + * @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 + * @throws InterruptedException if the fetching of data is interrupted + */ + protected void sendEmSetPointsToExt( + ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) + throws InterruptedException { + sendSingleResultType( + "em set point", + extEmDataConnection.requestEmSetPoints(tick, extEmDataConnection.getControlledEms()), + tick, + maybeNextTick, + log); + } + /** - * Function to send em data to SIMONA using the given {@link ExtEmDataConnection}. This method - * will take a value from the * {@link #dataQueueExtCoSimulatorToSimonaApi}. + * Function to send em flex options 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. @@ -199,29 +244,26 @@ protected void sendPrimaryDataToSimona( * @param tick for which data is sent * @param maybeNextTick option for the next tick data is sent * @param log logger + * @throws InterruptedException if the fetching of data is interrupted */ - protected void sendEmDataToSimona( + protected void sendEmFlexOptionsToSimona( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { ExtInputDataContainer inputData = dataQueueExtCoSimulatorToSimonaApi.takeData(); if (inputData.getTick() != tick) { throw new RuntimeException( - String.format( - "Provided input data for tick %d, but SIMONA expects input data for tick %d", - inputData.getTick(), tick)); + String.format( + "Provided input data for tick %d, but SIMONA expects input data for tick %d", + inputData.getTick(), tick)); } - sendEmDataToSimona( - extEmDataConnection, - tick, - inputData.getSimonaInputMap(), - maybeNextTick, - log); + sendEmFlexOptionsToSimona( + extEmDataConnection, tick, inputData.getSimonaInputMap(), maybeNextTick, log); } /** - * Function to send em data to SIMONA using the given {@link ExtEmDataConnection}. + * Function to send em flex options 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. @@ -232,17 +274,71 @@ protected void sendEmDataToSimona( * @param maybeNextTick option for the next tick data is sent * @param log logger */ - protected void sendEmDataToSimona( + protected void sendEmFlexOptionsToSimona( ExtEmDataConnection extEmDataConnection, long tick, Map dataMap, Optional maybeNextTick, Logger log) { - log.debug("Received EmData from {}", extSimulatorName); - extEmDataConnection.convertAndSend(tick, dataMap, maybeNextTick, log); - log.debug("Provided EmData to SIMONA!"); + log.debug("Received em flex options from {}", extSimulatorName); + extEmDataConnection.convertAndSendFlexOptions(tick, dataMap, maybeNextTick, log); + log.debug("Provided em flex options to SIMONA!"); } + /** + * Function to send em set point 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 + * @throws InterruptedException if the fetching of data is interrupted + */ + protected void sendEmSetPointsToSimona( + ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) + throws InterruptedException { + ExtInputDataContainer inputData = dataQueueExtCoSimulatorToSimonaApi.takeData(); + + if (inputData.getTick() != tick) { + throw new RuntimeException( + String.format( + "Provided input data for tick %d, but SIMONA expects input data for tick %d", + inputData.getTick(), tick)); + } + + sendEmSetPointsToSimona( + extEmDataConnection, tick, inputData.getSimonaInputMap(), maybeNextTick, log); + } + + /** + * Function to send em set point 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 + * @param dataMap map: id to value + * @param maybeNextTick option for the next tick data is sent + * @param log logger + */ + protected void sendEmSetPointsToSimona( + ExtEmDataConnection extEmDataConnection, + long tick, + Map dataMap, + Optional maybeNextTick, + Logger log) { + log.debug("Received em set points from {}", extSimulatorName); + extEmDataConnection.convertAndSendSetPoints(tick, dataMap, maybeNextTick, log); + log.debug("Provided em set points to SIMONA!"); + } + + // result data methods + /** * Function to send only participant result data from SIMONA to the external simulation using the * given {@link ExtResultDataConnection} @@ -275,22 +371,6 @@ protected void sendFlexOptionResultsToExt( "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); - - 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); - } - /** * Function to send all result data from SIMONA to the external simulation using the given {@link * ExtResultDataConnection} @@ -299,6 +379,7 @@ private void sendSingleResultType( * @param tick for which data is received * @param maybeNextTick option for the next tick data is received * @param log logger + * @throws InterruptedException if the fetching of data is interrupted */ protected void sendResultToExt( ExtResultDataConnection connection, long tick, Optional maybeNextTick, Logger log) @@ -311,6 +392,22 @@ protected void sendResultToExt( log.debug("Sent results to {}", extSimulatorName); } + 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); + + 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); + } + // helper methods private String resultMapToString(Map results) { 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 9fe43371..0e74ee18 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 @@ -8,10 +8,14 @@ import java.util.*; import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** Contains the mapping between SIMONA uuid, the external id and the data type the assets hold */ public class ExtEntityMapping { + private static final Logger log = LoggerFactory.getLogger(ExtEntityMapping.class); + private final Map> extEntities; public ExtEntityMapping(List extEntityEntryList) { @@ -55,4 +59,55 @@ public Map getExtUuid2IdMapping(DataType dataType) { return extEntities.getOrDefault(dataType, Collections.emptyList()).stream() .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); } + + /** + * Maps a map: ids to value to a map: uuids to value. + * + * @param valueMap that should be remapped + * @param mapping that is used + * @return a map: uuids to value + * @param type of output values + * @param type of input values + */ + @SuppressWarnings("unchecked") + public static Map mapToSimona( + Map valueMap, Map mapping) { + Map convertedMap = new HashMap<>(); + + for (String key : valueMap.keySet()) { + V value = valueMap.get(key); + + try { + convertedMap.put(mapping.get(key), (T) value); + } catch (ClassCastException e) { + log.warn("Could not convert value {} for key {}", value, key, e); + } + } + return convertedMap; + } + + /** + * Maps a map: uuids to value to a map: ids to value. + * + * @param valueMap that should be remapped + * @param mapping that is used + * @return a map: id to value + * @param type of output values + * @param type of input values + */ + @SuppressWarnings("unchecked") + public static Map mapToExt(Map valueMap, Map mapping) { + Map convertedMap = new HashMap<>(); + + for (UUID key : valueMap.keySet()) { + V value = valueMap.get(key); + + try { + convertedMap.put(mapping.get(key), (T) value); + } catch (ClassCastException e) { + log.warn("Could not convert value {} for key {}", value, key, e); + } + } + return convertedMap; + } } From b88d128f65e4d0d4d9b64fcb7128dfd7a6b55192 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 7 Mar 2025 14:48:59 +0100 Subject: [PATCH 14/80] Adding `EmDataService` to `EmAgent`. --- .../simona/api/data/em/ExtEmDataConnection.java | 2 +- .../api/data/em/model/EmSetPointResult.java | 15 +++++---------- .../simona/api/data/em/model/FlexOptionValue.java | 6 +++++- .../data/em/ontology/EmSetPointDataResponse.java | 2 +- .../api/data/em/ontology/FlexOptionsResponse.java | 2 +- ...xOptions.java => ProvideEmFlexOptionData.java} | 2 +- 6 files changed, 14 insertions(+), 15 deletions(-) rename src/main/java/edu/ie3/simona/api/data/em/ontology/{ProvideFlexOptions.java => ProvideEmFlexOptionData.java} (93%) 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 1719ada3..eddc19d8 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 @@ -57,7 +57,7 @@ public void convertAndSendFlexOptions( log.warn("No em flex options found! Sending no em data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with em flex options."); - sendExtMsg(new ProvideFlexOptions(tick, emFlexOptions, maybeNextTick)); + sendExtMsg(new ProvideEmFlexOptionData(tick, emFlexOptions, maybeNextTick)); } } diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java index e4259c3c..8bae0c02 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java @@ -9,6 +9,7 @@ import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.PValue; import java.time.ZonedDateTime; +import java.util.Optional; import java.util.UUID; /** Em set point result. */ @@ -16,18 +17,12 @@ public class EmSetPointResult extends ResultEntity { private final PValue setPoint; - /** - * Standard constructor which includes auto generation of the resulting output models uuid. - * - * @param time date and time when the result is produced - * @param inputModel uuid of the input model that produces the result - */ - protected EmSetPointResult(ZonedDateTime time, UUID inputModel, PValue setPoint) { + public EmSetPointResult(ZonedDateTime time, UUID inputModel, Optional setPoint) { super(time, inputModel); - this.setPoint = setPoint; + this.setPoint = setPoint.orElse(null); } - public PValue getSetPoint() { - return setPoint; + public Optional getSetPoint() { + return Optional.ofNullable(setPoint); } } diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java index b95126d1..ff08ab7b 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java @@ -7,9 +7,13 @@ package edu.ie3.simona.api.data.em.model; import edu.ie3.datamodel.models.value.Value; +import java.util.UUID; import javax.measure.quantity.Power; import tech.units.indriya.ComparableQuantity; public record FlexOptionValue( - ComparableQuantity pMin, ComparableQuantity pRef, ComparableQuantity pMax) + UUID sender, + ComparableQuantity pMin, + ComparableQuantity pRef, + ComparableQuantity pMax) implements Value {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java index 90a48976..3e16ae2f 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java @@ -11,5 +11,5 @@ import java.util.UUID; /** Message that provides em data (set points) to an external simulation. */ -public record EmSetPointDataResponse(long tick, Map emData) +public record EmSetPointDataResponse(Map emData) implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java index 7c7a039a..2b3220cb 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java @@ -11,5 +11,5 @@ import java.util.UUID; /** Message that provides em data (flexibility options) to an external simulation. */ -public record FlexOptionsResponse(long tick, Map flexOptions) +public record FlexOptionsResponse(Map flexOptions) implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java similarity index 93% rename from src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexOptions.java rename to src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java index 51e21412..1a4eaea2 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java @@ -12,6 +12,6 @@ import java.util.UUID; /** Message that provides em data (flexibility options) from an external simulation. */ -public record ProvideFlexOptions( +public record ProvideEmFlexOptionData( long tick, Map flexOptions, Optional maybeNextTick) implements EmDataMessageFromExt {} From e7cc903354fe5f057daef8f6adb3584f30d16d22 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 10 Mar 2025 15:01:44 +0100 Subject: [PATCH 15/80] Adding test for `ExtEmDataService`. Fixing some issues. --- .../java/edu/ie3/simona/api/data/WithDataResponseToExt.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java b/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java index 71ffb853..a183640f 100644 --- a/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java +++ b/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java @@ -14,10 +14,10 @@ * * @param type of response messages to ext */ -public class WithDataResponseToExt { +public abstract class WithDataResponseToExt { /** Data message queue containing messages from SIMONA */ - private final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); + public final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); /** Queues message from SIMONA that should be handled by the external simulation. */ public void queueExtResponseMsg(T msg) throws InterruptedException { From e6c6de3785add79f6850013aaeddf3b93461f07c Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 18 Mar 2025 12:55:34 +0100 Subject: [PATCH 16/80] Saving changes. --- .../edu/ie3/simona/api/data/em/ExtEmDataConnection.java | 6 ++++++ .../simona/api/data/em/model/FlexOptionRequestValue.java | 9 +++++++++ .../data/em/ontology/RequestControlledEmFlexResults.java | 7 +++++++ .../api/data/primarydata/ExtPrimaryDataConnection.java | 1 + .../simona/api/simulation/mapping/ExtEntityMapping.java | 8 ++++++++ 5 files changed, 31 insertions(+) create mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java 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 eddc19d8..91559999 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 @@ -26,6 +26,8 @@ public class ExtEmDataConnection /** Assets that provide data to ext */ private final Map mosaikMapping; + public final Map simonaMapping; + public ExtEmDataConnection(Map extEmMapping) { this.extEmMapping = extEmMapping; @@ -33,6 +35,10 @@ public ExtEmDataConnection(Map extEmMapping) { this.mosaikMapping = extEmMapping.entrySet().stream() .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + + this.simonaMapping = + extEmMapping.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } /** Returns a list of the uuids of the em agents that expect external set points */ diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java new file mode 100644 index 00000000..d9a73c94 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java @@ -0,0 +1,9 @@ +package edu.ie3.simona.api.data.em.model; + +import edu.ie3.datamodel.models.value.Value; + +import java.util.List; + +public record FlexOptionRequestValue( + List emEntities +) implements Value {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java new file mode 100644 index 00000000..8b780a21 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java @@ -0,0 +1,7 @@ +package edu.ie3.simona.api.data.em.ontology; + +import java.util.Set; +import java.util.UUID; + +/** Request em set flex options from SIMONA via external simulation. */ +public record RequestControlledEmFlexResults(Set emEntities) implements EmDataResponseMessageToExt { } 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 134c4001..cd577ba7 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 @@ -54,6 +54,7 @@ public void convertAndSend( log.warn("No primary data found! Sending no primary data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with primary data."); + log.info("Data: {}", convertedMap); provideData(tick, convertedMap, maybeNextTick); } } 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 0e74ee18..09fd3bc1 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 @@ -60,6 +60,14 @@ public Map getExtUuid2IdMapping(DataType dataType) { .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); } + + public static List toSimona(List list, Map mapping) { + return list.stream().map(str -> Optional.ofNullable(mapping.get(str))) + .filter(Optional::isPresent) + .map(Optional::get).toList(); + } + + /** * Maps a map: ids to value to a map: uuids to value. * From d20c1d16aa477d6e750b3d1f1e5e5fe688ac093a Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 19 Mar 2025 16:54:28 +0100 Subject: [PATCH 17/80] Saving changes. --- .../api/data/em/ExtEmDataConnection.java | 28 ++++++++++++++----- .../data/em/model/FlexOptionRequestValue.java | 2 +- .../em/ontology/RequestEmFlexResults.java | 3 +- .../api/simulation/ExtCoSimulation.java | 14 +++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) 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 91559999..68d2782c 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 @@ -26,7 +26,6 @@ public class ExtEmDataConnection /** Assets that provide data to ext */ private final Map mosaikMapping; - public final Map simonaMapping; public ExtEmDataConnection(Map extEmMapping) { @@ -35,10 +34,6 @@ public ExtEmDataConnection(Map extEmMapping) { this.mosaikMapping = extEmMapping.entrySet().stream() .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); - - this.simonaMapping = - extEmMapping.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } /** Returns a list of the uuids of the em agents that expect external set points */ @@ -88,15 +83,34 @@ public void convertAndSendSetPoints( } } + /** + * Converts and requests em flexibility options from SIMONA. + * + * @param tick for which set points are requested + * @param emEntities for which set points are requested + * @return an {@link FlexOptionsResponse} message + * @throws InterruptedException - on interruptions + */ + public Map convertAndSendRequestFlexResults(long tick, Map> emEntities, Logger log) throws InterruptedException { + Map> m = emEntities.entrySet().stream() + .map(e -> Map.entry(e.getKey(), ExtEntityMapping.toSimona(e.getValue(), extEmMapping))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + Map> map = ExtEntityMapping.mapToSimona(m, extEmMapping); + log.info("Provided SIMONA with em flex request: {}", map); + + return requestEmFlexResults(tick, map); + } + /** * Method to request em flexibility options from SIMONA. * * @param tick for which set points are requested * @param emEntities for which set points are requested - * @return an {@link EmSetPointDataResponse} message + * @return an {@link FlexOptionsResponse} message * @throws InterruptedException - on interruptions */ - public Map requestEmFlexResults(long tick, List emEntities) + public Map requestEmFlexResults(long tick, Map> emEntities) throws InterruptedException { sendExtMsg(new RequestEmFlexResults(tick, emEntities)); return ExtEntityMapping.mapToExt( diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java index d9a73c94..7306945d 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java @@ -5,5 +5,5 @@ import java.util.List; public record FlexOptionRequestValue( - List emEntities + String requester, List emEntities ) implements Value {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java index 925164d1..436c86dd 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java @@ -7,8 +7,9 @@ package edu.ie3.simona.api.data.em.ontology; import java.util.List; +import java.util.Map; import java.util.UUID; /** Request em set points from SIMONA in the given tick. */ -public record RequestEmFlexResults(long tick, List emEntities) +public record RequestEmFlexResults(long tick, Map> emEntities) implements EmDataMessageFromExt {} 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 391dc9ef..d218da40 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -11,6 +11,7 @@ import edu.ie3.simona.api.data.DataQueueExtSimulationExtSimulator; import edu.ie3.simona.api.data.ExtInputDataContainer; import edu.ie3.simona.api.data.em.ExtEmDataConnection; +import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; import edu.ie3.simona.api.data.results.ExtResultContainer; import edu.ie3.simona.api.data.results.ExtResultDataConnection; @@ -189,6 +190,7 @@ protected void sendPrimaryDataToSimona( // energy management data methods + /** * Function to send em flex options from SIMONA to the external simulation using the given {@link * ExtEmDataConnection}. This method will provide values to the {@link @@ -203,9 +205,19 @@ protected void sendPrimaryDataToSimona( protected void sendEmFlexResultsToExt( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { + // sending flex request to simona + ExtInputDataContainer container = dataQueueExtCoSimulatorToSimonaApi.takeData(); + + Map> map = container.getSimonaInputMap().entrySet().stream().map(e -> + Map.entry(e.getKey(), ((FlexOptionRequestValue) e.getValue()).emEntities()) + ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + log.info("Request flex options for: {}", map); + Map results = extEmDataConnection.convertAndSendRequestFlexResults(tick, map, log); + sendSingleResultType( "em flexibility option", - extEmDataConnection.requestEmFlexResults(tick, extEmDataConnection.getControlledEms()), + results, tick, maybeNextTick, log); From 1fe90ec65451b2521be7f12e975d551329d79cc5 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 20 Mar 2025 14:50:05 +0100 Subject: [PATCH 18/80] Saving changes. --- .../api/data/em/ExtEmDataConnection.java | 3 ++- .../api/data/em/model/FlexOptionValue.java | 12 +++-------- .../simona/api/data/em/model/FlexOptions.java | 20 +++++++++++++++++++ .../data/em/ontology/FlexOptionsResponse.java | 3 ++- .../em/ontology/ProvideEmFlexOptionData.java | 3 ++- .../api/simulation/ExtCoSimulation.java | 6 ++++-- 6 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java 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 68d2782c..9c7ec06d 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 @@ -13,9 +13,10 @@ import edu.ie3.simona.api.data.em.model.FlexOptionValue; import edu.ie3.simona.api.data.em.ontology.*; import edu.ie3.simona.api.simulation.mapping.ExtEntityMapping; +import org.slf4j.Logger; + import java.util.*; import java.util.stream.Collectors; -import org.slf4j.Logger; /** Enables data connection of em data between SIMONA and SimonaAPI */ public class ExtEmDataConnection diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java index ff08ab7b..4b3ced71 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java @@ -7,13 +7,7 @@ package edu.ie3.simona.api.data.em.model; import edu.ie3.datamodel.models.value.Value; -import java.util.UUID; -import javax.measure.quantity.Power; -import tech.units.indriya.ComparableQuantity; -public record FlexOptionValue( - UUID sender, - ComparableQuantity pMin, - ComparableQuantity pRef, - ComparableQuantity pMax) - implements Value {} +import java.util.List; + +public record FlexOptionValue(List flexOptions) implements Value {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java new file mode 100644 index 00000000..8f4fd27a --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java @@ -0,0 +1,20 @@ +/* + * © 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.em.model; + +import tech.units.indriya.ComparableQuantity; + +import javax.measure.quantity.Power; +import java.util.UUID; + +public record FlexOptions( + UUID sender, + ComparableQuantity pMin, + ComparableQuantity pRef, + ComparableQuantity pMax) { + +} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java index 2b3220cb..2d1888e4 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java @@ -7,9 +7,10 @@ package edu.ie3.simona.api.data.em.ontology; import edu.ie3.datamodel.models.result.system.FlexOptionsResult; + import java.util.Map; import java.util.UUID; /** Message that provides em data (flexibility options) to an external simulation. */ -public record FlexOptionsResponse(Map flexOptions) +public record FlexOptionsResponse(Map> flexOptions) implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java index 1a4eaea2..5b5fe3b3 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java @@ -7,11 +7,12 @@ package edu.ie3.simona.api.data.em.ontology; import edu.ie3.simona.api.data.em.model.FlexOptionValue; + import java.util.Map; import java.util.Optional; import java.util.UUID; /** Message that provides em data (flexibility options) from an external simulation. */ public record ProvideEmFlexOptionData( - long tick, Map flexOptions, Optional maybeNextTick) + long tick, Map flexOptions, Optional maybeNextTick) implements EmDataMessageFromExt {} 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 d218da40..1363d826 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -215,6 +215,8 @@ protected void sendEmFlexResultsToExt( log.info("Request flex options for: {}", map); Map results = extEmDataConnection.convertAndSendRequestFlexResults(tick, map, log); + log.warn("Flex results to ext : {}", results); + sendSingleResultType( "em flexibility option", results, @@ -413,8 +415,8 @@ private void sendSingleResultType( throws InterruptedException { log.info("Request results from SIMONA for {} for tick {}!", type, tick); - String resultString = resultMapToString(resultsToBeSend); - log.debug("[{}] Received {} results from SIMONA!\n{}", tick, type, resultString); + //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); From f16a6d9e5581bd390759f2218941b89a71bd244c Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 21 Mar 2025 11:36:12 +0100 Subject: [PATCH 19/80] Saving changes. --- .../DataQueueExtSimulationExtSimulator.java | 22 ---- .../ie3/simona/api/data/ExtDataContainer.java | 10 -- .../api/data/ExtDataContainerQueue.java | 36 ++++++ .../api/data/ExtInputDataContainer.java | 69 ---------- .../data/datacontainer/ExtDataContainer.java | 23 ++++ .../datacontainer/ExtInputDataContainer.java | 121 ++++++++++++++++++ .../ExtResultContainer.java | 18 ++- .../api/data/em/ExtEmDataConnection.java | 14 +- .../em/ontology/ProvideEmFlexOptionData.java | 5 +- .../api/simulation/ExtCoSimulation.java | 109 +++++++--------- .../results/ExtResultContainerTest.groovy | 1 + 11 files changed, 251 insertions(+), 177 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/data/DataQueueExtSimulationExtSimulator.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/ExtDataContainer.java create mode 100644 src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/ExtInputDataContainer.java create mode 100644 src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.java create mode 100644 src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java rename src/main/java/edu/ie3/simona/api/data/{results => datacontainer}/ExtResultContainer.java (89%) diff --git a/src/main/java/edu/ie3/simona/api/data/DataQueueExtSimulationExtSimulator.java b/src/main/java/edu/ie3/simona/api/data/DataQueueExtSimulationExtSimulator.java deleted file mode 100644 index 67d8cb0e..00000000 --- a/src/main/java/edu/ie3/simona/api/data/DataQueueExtSimulationExtSimulator.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * © 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.data; - -import java.util.concurrent.LinkedBlockingQueue; - -/** Data queue to allow data flow between SimonaAPI and an external simulation */ -public class DataQueueExtSimulationExtSimulator { - private final LinkedBlockingQueue receiverTriggerQueue = new LinkedBlockingQueue<>(); - - public void queueData(V data) throws InterruptedException { - this.receiverTriggerQueue.put(data); - } - - public V takeData() throws InterruptedException { - return this.receiverTriggerQueue.take(); - } -} diff --git a/src/main/java/edu/ie3/simona/api/data/ExtDataContainer.java b/src/main/java/edu/ie3/simona/api/data/ExtDataContainer.java deleted file mode 100644 index 224b9de7..00000000 --- a/src/main/java/edu/ie3/simona/api/data/ExtDataContainer.java +++ /dev/null @@ -1,10 +0,0 @@ -/* - * © 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.data; - -/** Interface for data that are exchanged between an external simulation and SimonaAPI */ -public interface ExtDataContainer {} diff --git a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java new file mode 100644 index 00000000..07b55221 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java @@ -0,0 +1,36 @@ +/* + * © 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.data; + +import edu.ie3.simona.api.data.datacontainer.ExtDataContainer; + +import java.util.concurrent.LinkedBlockingDeque; +import java.util.function.Function; + +/** Data queue to allow data flow between SimonaAPI and an external simulation */ +public class ExtDataContainerQueue { + private final LinkedBlockingDeque receiverTriggerDeque = new LinkedBlockingDeque<>(); + + public void queueData(V data) throws InterruptedException { + receiverTriggerDeque.putLast(data); + } + + public V takeAll() throws InterruptedException { + return receiverTriggerDeque.takeFirst(); + } + + public R takeData(Function extractor) throws InterruptedException { + V data = receiverTriggerDeque.takeFirst(); + R result = extractor.apply(data); + + if (!data.isEmpty()) { + receiverTriggerDeque.putFirst(data); + } + + return result; + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/ExtInputDataContainer.java deleted file mode 100644 index bec23e59..00000000 --- a/src/main/java/edu/ie3/simona/api/data/ExtInputDataContainer.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * © 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.data; - -import edu.ie3.datamodel.models.value.Value; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -/** Contains all inputs for SIMONA for a certain tick */ -public class ExtInputDataContainer implements ExtDataContainer { - - /** The tick, the input data is meant for */ - private final long tick; - - /** Map external id to an input value for SIMONA */ - private final Map dataMap; - - /** The next tick, when data will be provided, if available */ - private final Optional maybeNextTick; - - /** - * Container class for input data for SIMONA which can be read by SimonaAPI - * - * @param tick The tick, the input data is meant for - * @param dataMap data to be provided to SIMONA - * @param nextTick tick, when the next data will be provided - */ - public ExtInputDataContainer(long tick, Map dataMap, long nextTick) { - this.tick = tick; - this.dataMap = dataMap; - this.maybeNextTick = Optional.of(nextTick); - } - - public ExtInputDataContainer(long tick, Map dataMap) { - this.tick = tick; - this.dataMap = dataMap; - this.maybeNextTick = Optional.empty(); - } - - public ExtInputDataContainer(long tick) { - this(tick, new HashMap<>()); - } - - public ExtInputDataContainer(long tick, long nextTick) { - this(tick, new HashMap<>(), nextTick); - } - - public long getTick() { - return tick; - } - - public Map getSimonaInputMap() { - return dataMap; - } - - public Optional getMaybeNextTick() { - return maybeNextTick; - } - - /** Adds a value to the input map */ - public void addValue(String id, Value value) { - dataMap.put(id, value); - } -} diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.java b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.java new file mode 100644 index 00000000..319fb82e --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.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.data.datacontainer; + +import java.util.HashMap; +import java.util.Map; + +/** Interface for data that are exchanged between an external simulation and SimonaAPI */ +public interface ExtDataContainer { + boolean isEmpty(); + + + // private helper methods + default Map copyAndClear(Map map) { + Map result = new HashMap<>(map); + map.clear(); + return result; + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java new file mode 100644 index 00000000..b74fa4f8 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java @@ -0,0 +1,121 @@ +/* + * © 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.data.datacontainer; + +import edu.ie3.datamodel.models.value.PValue; +import edu.ie3.datamodel.models.value.Value; +import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; +import edu.ie3.simona.api.data.em.model.FlexOptions; + +import java.util.*; + +/** Contains all inputs for SIMONA for a certain tick */ +public final class ExtInputDataContainer implements ExtDataContainer { + + /** The tick, the input data is meant for */ + private final long tick; + + /** The next tick, when data will be provided, if available */ + private final Optional maybeNextTick; + + // primary map + /** Map external id to primary input value for SIMONA */ + private final Map primaryData = new HashMap<>(); + + // em maps + private final Map flexRequests = new HashMap<>(); + private final Map> flexOptions = new HashMap<>(); + private final Map setPoints = new HashMap<>(); + + /** + * Container class for input data for SIMONA which can be read by SimonaAPI + * + * @param tick The tick, the input data is meant for + * @param nextTick tick, when the next data will be provided + */ + public ExtInputDataContainer(long tick, long nextTick) { + this.tick = tick; + this.maybeNextTick = Optional.of(nextTick); + } + + public ExtInputDataContainer(long tick) { + this.tick = tick; + this.maybeNextTick = Optional.empty(); + } + + @Override + public boolean isEmpty() { + return primaryData.isEmpty() && flexRequests.isEmpty() && flexOptions.isEmpty() && setPoints.isEmpty(); + } + + public long getTick() { + return tick; + } + + public Optional getMaybeNextTick() { + return maybeNextTick; + } + + // add data + public void addPrimaryValue(String id, Value value) { + primaryData.put(id, value); + } + + public void addRequest(String requester, List emEntities) { + flexRequests.put(requester, new FlexOptionRequestValue(requester, emEntities)); + } + + public void addFlexOptions(String id, FlexOptions flexOption) { + if (!flexOptions.containsKey(id)) { + List flexOptionValues = new ArrayList<>(); + flexOptionValues.add(flexOption); + flexOptions.put(id, flexOptionValues); + } else { + flexOptions.get(id).add(flexOption); + } + } + + public void addSetPoint(String id, PValue setPoint) { + setPoints.put(id, setPoint); + } + + public Map extractPrimaryData() { + return copyAndClear(primaryData); + } + + + // extract and delete data + public Map extractFlexRequests() { + return copyAndClear(flexRequests); + } + + public Map> extractFlexOptions() { + return copyAndClear(flexOptions); + } + + public Map extractSetPoints() { + return copyAndClear(setPoints); + } + + + // data to string + public String primaryDataString() { + return primaryData.toString(); + } + + public String flexRequestsString() { + return flexRequests.toString(); + } + + public String flexOptionsString() { + return flexOptions.toString(); + } + + public String setPointsString() { + return setPoints.toString(); + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java similarity index 89% rename from src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java rename to src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java index d3c26b34..91dcb2c6 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.results; +package edu.ie3.simona.api.data.datacontainer; import static edu.ie3.util.quantities.PowerSystemUnits.PU; @@ -12,10 +12,14 @@ 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; + +import java.util.HashMap; import java.util.Map; import java.util.Optional; import javax.measure.quantity.Dimensionless; + +import edu.ie3.simona.api.data.em.model.EmSetPointResult; +import edu.ie3.simona.api.data.em.model.FlexOptions; import tech.units.indriya.ComparableQuantity; import tech.units.indriya.quantity.Quantities; @@ -34,6 +38,11 @@ public class ExtResultContainer implements ExtDataContainer { */ private final Map simonaResultsMap; + // em maps + private final Map flexOptions = new HashMap<>(); + private final Map setPoints = new HashMap<>(); + + /** * Container class for result data from SIMONA * @@ -52,6 +61,11 @@ public ExtResultContainer(long tick, Map simonaResultsMap) this(tick, simonaResultsMap, Optional.empty()); } + @Override + public boolean isEmpty() { + return simonaResultsMap.isEmpty() && flexOptions.isEmpty() && setPoints.isEmpty(); + } + public Map getResults() { return simonaResultsMap; } 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 9c7ec06d..76f2426f 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,9 +8,9 @@ import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.PValue; -import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.BiDirectional; -import edu.ie3.simona.api.data.em.model.FlexOptionValue; +import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; +import edu.ie3.simona.api.data.em.model.FlexOptions; import edu.ie3.simona.api.data.em.ontology.*; import edu.ie3.simona.api.simulation.mapping.ExtEntityMapping; import org.slf4j.Logger; @@ -51,9 +51,9 @@ public List getControlledEms() { * @param log logger */ public void convertAndSendFlexOptions( - long tick, Map data, Optional maybeNextTick, Logger log) { + long tick, Map> data, Optional maybeNextTick, Logger log) { // filtering the data and converting the keys - Map emFlexOptions = ExtEntityMapping.mapToSimona(data, extEmMapping); + Map> emFlexOptions = ExtEntityMapping.mapToSimona(data, extEmMapping); if (emFlexOptions.isEmpty()) { log.warn("No em flex options found! Sending no em data to SIMONA for tick {}.", tick); @@ -72,7 +72,7 @@ public void convertAndSendFlexOptions( * @param log logger */ public void convertAndSendSetPoints( - long tick, Map data, Optional maybeNextTick, Logger log) { + long tick, Map data, Optional maybeNextTick, Logger log) { // filtering the data and converting the keys Map emSetPoints = ExtEntityMapping.mapToSimona(data, extEmMapping); @@ -92,9 +92,9 @@ public void convertAndSendSetPoints( * @return an {@link FlexOptionsResponse} message * @throws InterruptedException - on interruptions */ - public Map convertAndSendRequestFlexResults(long tick, Map> emEntities, Logger log) throws InterruptedException { + public Map convertAndSendRequestFlexResults(long tick, Map emEntities, Logger log) throws InterruptedException { Map> m = emEntities.entrySet().stream() - .map(e -> Map.entry(e.getKey(), ExtEntityMapping.toSimona(e.getValue(), extEmMapping))) + .map(e -> Map.entry(e.getKey(), ExtEntityMapping.toSimona(e.getValue().emEntities(), extEmMapping))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); Map> map = ExtEntityMapping.mapToSimona(m, extEmMapping); diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java index 5b5fe3b3..f6c580f8 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java @@ -6,13 +6,14 @@ package edu.ie3.simona.api.data.em.ontology; -import edu.ie3.simona.api.data.em.model.FlexOptionValue; +import edu.ie3.simona.api.data.em.model.FlexOptions; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; /** Message that provides em data (flexibility options) from an external simulation. */ public record ProvideEmFlexOptionData( - long tick, Map flexOptions, Optional maybeNextTick) + long tick, Map> flexOptions, Optional maybeNextTick) implements EmDataMessageFromExt {} 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 1363d826..bfb3ad25 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -7,21 +7,24 @@ package edu.ie3.simona.api.simulation; import edu.ie3.datamodel.models.result.ResultEntity; +import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; -import edu.ie3.simona.api.data.DataQueueExtSimulationExtSimulator; -import edu.ie3.simona.api.data.ExtInputDataContainer; +import edu.ie3.simona.api.data.ExtDataContainerQueue; +import edu.ie3.simona.api.data.datacontainer.ExtInputDataContainer; +import edu.ie3.simona.api.data.datacontainer.ExtResultContainer; import edu.ie3.simona.api.data.em.ExtEmDataConnection; import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; +import edu.ie3.simona.api.data.em.model.FlexOptions; 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 org.slf4j.Logger; + 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 @@ -33,12 +36,10 @@ public abstract class ExtCoSimulation extends ExtSimulation { /** Queue for the data connection from the external co-simulation to SimonaAPI */ - protected final DataQueueExtSimulationExtSimulator - dataQueueExtCoSimulatorToSimonaApi; + protected final ExtDataContainerQueue queueToSimona; /** Queue for the data connection from SimonaAPI to the external co-simulation */ - protected final DataQueueExtSimulationExtSimulator - dataQueueSimonaApiToExtCoSimulator; + protected final ExtDataContainerQueue queueToExt; /** Name of the external co-simulation */ protected final String extSimulatorName; @@ -46,8 +47,8 @@ public abstract class ExtCoSimulation extends ExtSimulation { protected ExtCoSimulation(String simulationName, String extSimulatorName) { super(simulationName); this.extSimulatorName = extSimulatorName; - this.dataQueueExtCoSimulatorToSimonaApi = new DataQueueExtSimulationExtSimulator<>(); - this.dataQueueSimonaApiToExtCoSimulator = new DataQueueExtSimulationExtSimulator<>(); + this.queueToSimona = new ExtDataContainerQueue<>(); + this.queueToExt = new ExtDataContainerQueue<>(); } // connection helper methods @@ -137,11 +138,22 @@ public static ExtResultDataConnection buildResultConnection( } } + private void checkTick(long expectedTick) throws InterruptedException { + long dataTick = queueToSimona.takeData(ExtInputDataContainer::getTick); + + if (dataTick != expectedTick) { + throw new RuntimeException( + String.format( + "Provided input data for tick %d, but SIMONA expects input data for tick %d", + dataTick, expectedTick)); + } + } + // primary data methods /** * Function to send primary data to SIMONA using the given {@link ExtPrimaryDataConnection}. This - * method will take a value from the {@link #dataQueueExtCoSimulatorToSimonaApi}. + * method will take a value from the {@link #queueToSimona}. * * @param extPrimaryDataConnection the connection to SIMONA * @param tick for which data is sent @@ -154,17 +166,9 @@ protected void sendPrimaryDataToSimona( Optional maybeNextTick, Logger log) throws InterruptedException { - ExtInputDataContainer inputData = dataQueueExtCoSimulatorToSimonaApi.takeData(); - - if (inputData.getTick() != tick) { - throw new RuntimeException( - String.format( - "Provided input data for tick %d, but SIMONA expects input data for tick %d", - inputData.getTick(), tick)); - } - - sendPrimaryDataToSimona( - extPrimaryDataConnection, tick, inputData.getSimonaInputMap(), maybeNextTick, log); + checkTick(tick); + Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractPrimaryData); + sendPrimaryDataToSimona(extPrimaryDataConnection, tick, inputData, maybeNextTick, log); } /** @@ -194,7 +198,7 @@ protected void sendPrimaryDataToSimona( /** * Function to send em flex options from SIMONA to the external simulation using the given {@link * ExtEmDataConnection}. This method will provide values to the {@link - * #dataQueueSimonaApiToExtCoSimulator}. + * #queueToExt}. * * @param extEmDataConnection the connection to SIMONA * @param tick for which data is sent @@ -206,29 +210,19 @@ protected void sendEmFlexResultsToExt( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { // sending flex request to simona - ExtInputDataContainer container = dataQueueExtCoSimulatorToSimonaApi.takeData(); - - Map> map = container.getSimonaInputMap().entrySet().stream().map(e -> - Map.entry(e.getKey(), ((FlexOptionRequestValue) e.getValue()).emEntities()) - ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - log.info("Request flex options for: {}", map); - Map results = extEmDataConnection.convertAndSendRequestFlexResults(tick, map, log); + Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractFlexRequests); + log.info("Request flex options for: {}", inputData); + Map results = extEmDataConnection.convertAndSendRequestFlexResults(tick, inputData, log); log.warn("Flex results to ext : {}", results); - sendSingleResultType( - "em flexibility option", - results, - tick, - maybeNextTick, - log); + sendSingleResultType("em flexibility option", results, tick, maybeNextTick, log); } /** * Function to send em set points from SIMONA to the external simulation using the given {@link * ExtEmDataConnection}. This method will provide values to the {@link - * #dataQueueSimonaApiToExtCoSimulator}. + * #queueToExt}. * * @param extEmDataConnection the connection to SIMONA * @param tick for which data is sent @@ -249,7 +243,7 @@ protected void sendEmSetPointsToExt( /** * Function to send em flex options to SIMONA using the given {@link ExtEmDataConnection}. This - * method will take a value from the {@link #dataQueueExtCoSimulatorToSimonaApi}. + * method will take a value from the {@link #queueToSimona}. * *

{@code nextTick} is necessary, because the em agents have an own scheduler that should know, * when the next set point arrives. @@ -263,17 +257,9 @@ protected void sendEmSetPointsToExt( protected void sendEmFlexOptionsToSimona( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { - ExtInputDataContainer inputData = dataQueueExtCoSimulatorToSimonaApi.takeData(); - - if (inputData.getTick() != tick) { - throw new RuntimeException( - String.format( - "Provided input data for tick %d, but SIMONA expects input data for tick %d", - inputData.getTick(), tick)); - } - - sendEmFlexOptionsToSimona( - extEmDataConnection, tick, inputData.getSimonaInputMap(), maybeNextTick, log); + checkTick(tick); + Map> inputData = queueToSimona.takeData(ExtInputDataContainer::extractFlexOptions); + sendEmFlexOptionsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); } /** @@ -291,7 +277,7 @@ protected void sendEmFlexOptionsToSimona( protected void sendEmFlexOptionsToSimona( ExtEmDataConnection extEmDataConnection, long tick, - Map dataMap, + Map> dataMap, Optional maybeNextTick, Logger log) { log.debug("Received em flex options from {}", extSimulatorName); @@ -301,7 +287,7 @@ protected void sendEmFlexOptionsToSimona( /** * Function to send em set point data to SIMONA using the given {@link ExtEmDataConnection}. This - * method will take a value from the {@link #dataQueueExtCoSimulatorToSimonaApi}. + * method will take a value from the {@link #queueToSimona}. * *

{@code nextTick} is necessary, because the em agents have an own scheduler that should know, * when the next set point arrives. @@ -315,17 +301,10 @@ protected void sendEmFlexOptionsToSimona( protected void sendEmSetPointsToSimona( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { - ExtInputDataContainer inputData = dataQueueExtCoSimulatorToSimonaApi.takeData(); + checkTick(tick); + Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractSetPoints); - if (inputData.getTick() != tick) { - throw new RuntimeException( - String.format( - "Provided input data for tick %d, but SIMONA expects input data for tick %d", - inputData.getTick(), tick)); - } - - sendEmSetPointsToSimona( - extEmDataConnection, tick, inputData.getSimonaInputMap(), maybeNextTick, log); + sendEmSetPointsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); } /** @@ -343,7 +322,7 @@ protected void sendEmSetPointsToSimona( protected void sendEmSetPointsToSimona( ExtEmDataConnection extEmDataConnection, long tick, - Map dataMap, + Map dataMap, Optional maybeNextTick, Logger log) { log.debug("Received em set points from {}", extSimulatorName); @@ -401,7 +380,7 @@ protected void sendResultToExt( log.debug("Request results from SIMONA!"); Map resultsToBeSend = connection.requestResults(tick); log.debug("Received results from SIMONA!"); - dataQueueSimonaApiToExtCoSimulator.queueData( + queueToExt.queueData( new ExtResultContainer(tick, resultsToBeSend, maybeNextTick)); log.debug("Sent results to {}", extSimulatorName); } @@ -417,7 +396,7 @@ private void sendSingleResultType( //String resultString = resultMapToString(resultsToBeSend); //log.debug("[{}] Received {} results from SIMONA!\n{}", tick, type, resultString); - dataQueueSimonaApiToExtCoSimulator.queueData( + queueToExt.queueData( new ExtResultContainer(tick, resultsToBeSend, nextTick)); log.info("Sent {} results for tick {} to {}", type, tick, extSimulatorName); } diff --git a/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy index b86f6aef..d3c6d764 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy @@ -2,6 +2,7 @@ package edu.ie3.simona.api.data.results import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.result.NodeResult +import edu.ie3.simona.api.data.datacontainer.ExtResultContainer import edu.ie3.simona.api.test.common.DataServiceTestData import edu.ie3.util.quantities.PowerSystemUnits import spock.lang.Shared From 96c21440642bf03a6d5bd698d9311684dbc3d3e8 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 21 Mar 2025 14:20:06 +0100 Subject: [PATCH 20/80] Saving changes. --- .../api/data/ExtDataContainerQueue.java | 3 +- .../data/datacontainer/ExtDataContainer.java | 15 +++--- .../datacontainer/ExtInputDataContainer.java | 26 +++++----- .../datacontainer/ExtResultContainer.java | 50 +++++++++++-------- .../api/data/em/ExtEmDataConnection.java | 19 ++++--- .../data/em/model/FlexOptionRequestValue.java | 11 ++-- .../api/data/em/model/FlexOptionValue.java | 1 - .../simona/api/data/em/model/FlexOptions.java | 9 ++-- .../data/em/ontology/FlexOptionsResponse.java | 3 +- .../em/ontology/ProvideEmFlexOptionData.java | 3 +- .../RequestControlledEmFlexResults.java | 9 +++- .../api/simulation/ExtCoSimulation.java | 42 +++++++--------- .../simulation/mapping/ExtEntityMapping.java | 10 ++-- 13 files changed, 105 insertions(+), 96 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java index 07b55221..d41fe293 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java @@ -7,12 +7,11 @@ package edu.ie3.simona.api.data; import edu.ie3.simona.api.data.datacontainer.ExtDataContainer; - import java.util.concurrent.LinkedBlockingDeque; import java.util.function.Function; /** Data queue to allow data flow between SimonaAPI and an external simulation */ -public class ExtDataContainerQueue { +public final class ExtDataContainerQueue { private final LinkedBlockingDeque receiverTriggerDeque = new LinkedBlockingDeque<>(); public void queueData(V data) throws InterruptedException { diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.java b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.java index 319fb82e..c5d9e33b 100644 --- a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.java @@ -11,13 +11,12 @@ /** Interface for data that are exchanged between an external simulation and SimonaAPI */ public interface ExtDataContainer { - boolean isEmpty(); + boolean isEmpty(); - - // private helper methods - default Map copyAndClear(Map map) { - Map result = new HashMap<>(map); - map.clear(); - return result; - } + // private helper methods + default Map copyAndClear(Map map) { + Map result = new HashMap<>(map); + map.clear(); + return result; + } } diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java index b74fa4f8..8c6e2116 100644 --- a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java @@ -10,7 +10,6 @@ import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; import edu.ie3.simona.api.data.em.model.FlexOptions; - import java.util.*; /** Contains all inputs for SIMONA for a certain tick */ @@ -49,7 +48,10 @@ public ExtInputDataContainer(long tick) { @Override public boolean isEmpty() { - return primaryData.isEmpty() && flexRequests.isEmpty() && flexOptions.isEmpty() && setPoints.isEmpty(); + return primaryData.isEmpty() + && flexRequests.isEmpty() + && flexOptions.isEmpty() + && setPoints.isEmpty(); } public long getTick() { @@ -87,7 +89,6 @@ public Map extractPrimaryData() { return copyAndClear(primaryData); } - // extract and delete data public Map extractFlexRequests() { return copyAndClear(flexRequests); @@ -101,21 +102,20 @@ public Map extractSetPoints() { return copyAndClear(setPoints); } - // data to string public String primaryDataString() { - return primaryData.toString(); - } + return primaryData.toString(); + } - public String flexRequestsString() { + public String flexRequestsString() { return flexRequests.toString(); } - public String flexOptionsString() { - return flexOptions.toString(); - } + public String flexOptionsString() { + return flexOptions.toString(); + } - public String setPointsString() { - return setPoints.toString(); - } + public String setPointsString() { + return setPoints.toString(); + } } diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java index 91dcb2c6..c684efec 100644 --- a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java @@ -12,14 +12,10 @@ import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.result.connector.LineResult; import edu.ie3.datamodel.models.result.system.SystemParticipantResult; - import java.util.HashMap; import java.util.Map; import java.util.Optional; import javax.measure.quantity.Dimensionless; - -import edu.ie3.simona.api.data.em.model.EmSetPointResult; -import edu.ie3.simona.api.data.em.model.FlexOptions; import tech.units.indriya.ComparableQuantity; import tech.units.indriya.quantity.Quantities; @@ -36,38 +32,48 @@ public class ExtResultContainer implements ExtDataContainer { * Map external id to result from SIMONA ATTENTION: The time stamp of the result entities is not * necessarily corresponding to the tick */ - private final Map simonaResultsMap; - - // em maps - private final Map flexOptions = new HashMap<>(); - private final Map setPoints = new HashMap<>(); - + private final Map resultMap; /** * Container class for result data from SIMONA * * @param tick current tick - * @param simonaResultsMap results from SIMONA with external id as key + * @param resultMap results from SIMONA with external id as key * @param nextTick tick the external simulation can expect the next results */ public ExtResultContainer( - long tick, Map simonaResultsMap, Optional nextTick) { + long tick, Map resultMap, Optional nextTick) { this.tick = tick; - this.simonaResultsMap = simonaResultsMap; + this.resultMap = resultMap; this.maybeNextTick = nextTick; } - public ExtResultContainer(long tick, Map simonaResultsMap) { - this(tick, simonaResultsMap, Optional.empty()); + public ExtResultContainer(long tick, Map resultMap) { + this(tick, resultMap, Optional.empty()); } @Override public boolean isEmpty() { - return simonaResultsMap.isEmpty() && flexOptions.isEmpty() && setPoints.isEmpty(); + return resultMap.isEmpty(); } public Map getResults() { - return simonaResultsMap; + return resultMap; + } + + @SuppressWarnings("unchecked") + public Map getResults(Class clazz) { + Map result = new HashMap<>(); + + for (Map.Entry entry : resultMap.entrySet()) { + ResultEntity resultEntity = entry.getValue(); + + if (entry.getValue().getClass().equals(clazz)) { + result.put(entry.getKey(), (R) resultEntity); + } + } + + return result; } public Long getTick() { @@ -80,7 +86,7 @@ public Optional getNextTick() { /** Returns the result for a certain asset. */ public ResultEntity getResult(String assetId) { - return simonaResultsMap.get(assetId); + return resultMap.get(assetId); } /** @@ -88,7 +94,7 @@ public ResultEntity getResult(String assetId) { * NodeResult} */ public double getVoltageDeviation(String assetId) { - if (simonaResultsMap.get(assetId) instanceof NodeResult nodeResult) { + if (resultMap.get(assetId) instanceof NodeResult nodeResult) { ComparableQuantity vMagDev = Quantities.getQuantity(-1.0, PU).add(nodeResult.getvMag()); return vMagDev.getValue().doubleValue(); @@ -102,7 +108,7 @@ 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) { + if (resultMap.get(assetId) instanceof NodeResult nodeResult) { return nodeResult.getvMag().getValue().doubleValue(); } else { throw new IllegalArgumentException("VOLTAGE is only available for NodeResult's!"); @@ -114,7 +120,7 @@ public double getVoltage(String assetId) { * SystemParticipantResult} */ public double getActivePower(String assetId) { - if (simonaResultsMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { + if (resultMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { return systemParticipantResult.getP().getValue().doubleValue(); } else { throw new IllegalArgumentException( @@ -127,7 +133,7 @@ public double getActivePower(String assetId) { * SystemParticipantResult} */ public double getReactivePower(String assetId) { - if (simonaResultsMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { + if (resultMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { return systemParticipantResult.getQ().getValue().doubleValue(); } else { throw new IllegalArgumentException( 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 76f2426f..e3777c8a 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 @@ -13,10 +13,9 @@ import edu.ie3.simona.api.data.em.model.FlexOptions; import edu.ie3.simona.api.data.em.ontology.*; import edu.ie3.simona.api.simulation.mapping.ExtEntityMapping; -import org.slf4j.Logger; - import java.util.*; import java.util.stream.Collectors; +import org.slf4j.Logger; /** Enables data connection of em data between SIMONA and SimonaAPI */ public class ExtEmDataConnection @@ -28,7 +27,6 @@ public class ExtEmDataConnection /** Assets that provide data to ext */ private final Map mosaikMapping; - public ExtEmDataConnection(Map extEmMapping) { this.extEmMapping = extEmMapping; @@ -51,7 +49,7 @@ public List getControlledEms() { * @param log logger */ public void convertAndSendFlexOptions( - long tick, Map> data, Optional maybeNextTick, Logger log) { + long tick, Map> data, Optional maybeNextTick, Logger log) { // filtering the data and converting the keys Map> emFlexOptions = ExtEntityMapping.mapToSimona(data, extEmMapping); @@ -92,9 +90,16 @@ public void convertAndSendSetPoints( * @return an {@link FlexOptionsResponse} message * @throws InterruptedException - on interruptions */ - public Map convertAndSendRequestFlexResults(long tick, Map emEntities, Logger log) throws InterruptedException { - Map> m = emEntities.entrySet().stream() - .map(e -> Map.entry(e.getKey(), ExtEntityMapping.toSimona(e.getValue().emEntities(), extEmMapping))) + public Map convertAndSendRequestFlexResults( + long tick, Map emEntities, Logger log) + throws InterruptedException { + Map> m = + emEntities.entrySet().stream() + .map( + e -> + Map.entry( + e.getKey(), + ExtEntityMapping.toSimona(e.getValue().emEntities(), extEmMapping))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); Map> map = ExtEntityMapping.mapToSimona(m, extEmMapping); diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java index 7306945d..759bd97f 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java @@ -1,9 +1,12 @@ +/* + * © 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.em.model; import edu.ie3.datamodel.models.value.Value; - import java.util.List; -public record FlexOptionRequestValue( - String requester, List emEntities -) implements Value {} +public record FlexOptionRequestValue(String requester, List emEntities) implements Value {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java index 4b3ced71..99342d10 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java @@ -7,7 +7,6 @@ package edu.ie3.simona.api.data.em.model; import edu.ie3.datamodel.models.value.Value; - import java.util.List; public record FlexOptionValue(List flexOptions) implements Value {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java index 8f4fd27a..95d93944 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java @@ -6,15 +6,12 @@ package edu.ie3.simona.api.data.em.model; -import tech.units.indriya.ComparableQuantity; - -import javax.measure.quantity.Power; import java.util.UUID; +import javax.measure.quantity.Power; +import tech.units.indriya.ComparableQuantity; public record FlexOptions( UUID sender, ComparableQuantity pMin, ComparableQuantity pRef, - ComparableQuantity pMax) { - -} + ComparableQuantity pMax) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java index 2d1888e4..2b3220cb 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java @@ -7,10 +7,9 @@ package edu.ie3.simona.api.data.em.ontology; import edu.ie3.datamodel.models.result.system.FlexOptionsResult; - import java.util.Map; import java.util.UUID; /** Message that provides em data (flexibility options) to an external simulation. */ -public record FlexOptionsResponse(Map> flexOptions) +public record FlexOptionsResponse(Map flexOptions) implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java index f6c580f8..856fbcd5 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java @@ -7,7 +7,6 @@ package edu.ie3.simona.api.data.em.ontology; import edu.ie3.simona.api.data.em.model.FlexOptions; - import java.util.List; import java.util.Map; import java.util.Optional; @@ -15,5 +14,5 @@ /** Message that provides em data (flexibility options) from an external simulation. */ public record ProvideEmFlexOptionData( - long tick, Map> flexOptions, Optional maybeNextTick) + long tick, Map> flexOptions, Optional maybeNextTick) implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java index 8b780a21..0612ab61 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java @@ -1,7 +1,14 @@ +/* + * © 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.em.ontology; import java.util.Set; import java.util.UUID; /** Request em set flex options from SIMONA via external simulation. */ -public record RequestControlledEmFlexResults(Set emEntities) implements EmDataResponseMessageToExt { } +public record RequestControlledEmFlexResults(Set emEntities) + implements EmDataResponseMessageToExt {} 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 bfb3ad25..eeed0051 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -21,10 +21,9 @@ 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 org.slf4j.Logger; - 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 @@ -141,12 +140,12 @@ public static ExtResultDataConnection buildResultConnection( private void checkTick(long expectedTick) throws InterruptedException { long dataTick = queueToSimona.takeData(ExtInputDataContainer::getTick); - if (dataTick != expectedTick) { - throw new RuntimeException( - String.format( - "Provided input data for tick %d, but SIMONA expects input data for tick %d", - dataTick, expectedTick)); - } + if (dataTick != expectedTick) { + throw new RuntimeException( + String.format( + "Provided input data for tick %d, but SIMONA expects input data for tick %d", + dataTick, expectedTick)); + } } // primary data methods @@ -167,7 +166,8 @@ protected void sendPrimaryDataToSimona( Logger log) throws InterruptedException { checkTick(tick); - Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractPrimaryData); + Map inputData = + queueToSimona.takeData(ExtInputDataContainer::extractPrimaryData); sendPrimaryDataToSimona(extPrimaryDataConnection, tick, inputData, maybeNextTick, log); } @@ -194,11 +194,9 @@ protected void sendPrimaryDataToSimona( // energy management data methods - /** * Function to send em flex options from SIMONA to the external simulation using the given {@link - * ExtEmDataConnection}. This method will provide values to the {@link - * #queueToExt}. + * ExtEmDataConnection}. This method will provide values to the {@link #queueToExt}. * * @param extEmDataConnection the connection to SIMONA * @param tick for which data is sent @@ -210,10 +208,12 @@ protected void sendEmFlexResultsToExt( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { // sending flex request to simona - Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractFlexRequests); + Map inputData = + queueToSimona.takeData(ExtInputDataContainer::extractFlexRequests); log.info("Request flex options for: {}", inputData); - Map results = extEmDataConnection.convertAndSendRequestFlexResults(tick, inputData, log); + Map results = + extEmDataConnection.convertAndSendRequestFlexResults(tick, inputData, log); log.warn("Flex results to ext : {}", results); sendSingleResultType("em flexibility option", results, tick, maybeNextTick, log); @@ -221,8 +221,7 @@ protected void sendEmFlexResultsToExt( /** * Function to send em set points from SIMONA to the external simulation using the given {@link - * ExtEmDataConnection}. This method will provide values to the {@link - * #queueToExt}. + * ExtEmDataConnection}. This method will provide values to the {@link #queueToExt}. * * @param extEmDataConnection the connection to SIMONA * @param tick for which data is sent @@ -258,7 +257,8 @@ protected void sendEmFlexOptionsToSimona( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { checkTick(tick); - Map> inputData = queueToSimona.takeData(ExtInputDataContainer::extractFlexOptions); + Map> inputData = + queueToSimona.takeData(ExtInputDataContainer::extractFlexOptions); sendEmFlexOptionsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); } @@ -380,8 +380,7 @@ protected void sendResultToExt( log.debug("Request results from SIMONA!"); Map resultsToBeSend = connection.requestResults(tick); log.debug("Received results from SIMONA!"); - queueToExt.queueData( - new ExtResultContainer(tick, resultsToBeSend, maybeNextTick)); + queueToExt.queueData(new ExtResultContainer(tick, resultsToBeSend, maybeNextTick)); log.debug("Sent results to {}", extSimulatorName); } @@ -394,10 +393,7 @@ private void sendSingleResultType( throws InterruptedException { log.info("Request results from SIMONA for {} for tick {}!", type, tick); - //String resultString = resultMapToString(resultsToBeSend); - //log.debug("[{}] Received {} results from SIMONA!\n{}", tick, type, resultString); - queueToExt.queueData( - new ExtResultContainer(tick, resultsToBeSend, nextTick)); + queueToExt.queueData(new ExtResultContainer(tick, resultsToBeSend, nextTick)); log.info("Sent {} results for tick {} to {}", type, tick, extSimulatorName); } 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 09fd3bc1..cd84c6ae 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 @@ -60,14 +60,14 @@ public Map getExtUuid2IdMapping(DataType dataType) { .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); } - public static List toSimona(List list, Map mapping) { - return list.stream().map(str -> Optional.ofNullable(mapping.get(str))) - .filter(Optional::isPresent) - .map(Optional::get).toList(); + return list.stream() + .map(str -> Optional.ofNullable(mapping.get(str))) + .filter(Optional::isPresent) + .map(Optional::get) + .toList(); } - /** * Maps a map: ids to value to a map: uuids to value. * From 2600b847519e3a341ce790fb98284d6392ea9ca9 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 25 Mar 2025 13:50:51 +0100 Subject: [PATCH 21/80] Saving changes. --- .../ie3/simona/api/data/BiDirectional.java | 9 ++++++ .../api/data/WithDataResponseToExt.java | 27 ++++++++++++++++++ .../datacontainer/ExtInputDataContainer.java | 7 ++--- .../api/data/em/ExtEmDataConnection.java | 28 ++++++++++++++++++- .../api/data/em/model/FlexOptionValue.java | 5 ++-- .../simona/api/data/em/model/FlexOptions.java | 3 +- .../api/data/em/model/FlexRequestResult.java | 19 +++++++++++++ .../api/data/em/ontology/EmCompletion.java | 3 ++ .../data/em/ontology/FlexRequestResponse.java | 16 +++++++++++ .../em/ontology/ProvideEmFlexOptionData.java | 2 +- .../em/ontology/ProvideFlexRequestData.java | 13 +++++++++ .../simulation/mapping/ExtEntityMapping.java | 8 ++++++ 12 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java diff --git a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java index 637b516a..844bd7d2 100644 --- a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java +++ b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java @@ -20,6 +20,15 @@ public class BiDirectional extends WithDataResponseToExt implements ExtInputDataConnection { + protected BiDirectional() { + super(); + } + + protected BiDirectional(R completionMsg) { + super(completionMsg); + } + + /** Actor reference to service that handles data within SIMONA */ private ActorRef dataService; diff --git a/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java b/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java index a183640f..10bd5d94 100644 --- a/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java +++ b/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java @@ -7,6 +7,8 @@ package edu.ie3.simona.api.data; import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; + +import java.util.Optional; import java.util.concurrent.LinkedBlockingQueue; /** @@ -16,14 +18,39 @@ */ public abstract class WithDataResponseToExt { + private final Optional completionMsg; + /** Data message queue containing messages from SIMONA */ public final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); + protected WithDataResponseToExt() { + this.completionMsg = Optional.empty(); + } + + protected WithDataResponseToExt(T completion) { + this.completionMsg = Optional.of(completion); + } + + /** Queues message from SIMONA that should be handled by the external simulation. */ public void queueExtResponseMsg(T msg) throws InterruptedException { receiveTriggerQueue.put(msg); } + public void queueExtResponseMsg(T msg, boolean finishedStep) throws InterruptedException { + receiveTriggerQueue.put(msg); + + if (finishedStep && completionMsg.isPresent()) { + receiveTriggerQueue.put(completionMsg.get()); + } + } + + + public T receiveAny() throws InterruptedException { + return receiveTriggerQueue.take(); + } + + /** * Waits until a message of given type is added to the queue. If the message has a different type, * a RuntimeException is thrown. This method blocks until having received a response from SIMONA. diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java index 8c6e2116..29c64ac4 100644 --- a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java @@ -71,13 +71,12 @@ public void addRequest(String requester, List emEntities) { flexRequests.put(requester, new FlexOptionRequestValue(requester, emEntities)); } - public void addFlexOptions(String id, FlexOptions flexOption) { + public void addFlexOptions(String id, List flexOption) { if (!flexOptions.containsKey(id)) { - List flexOptionValues = new ArrayList<>(); - flexOptionValues.add(flexOption); + List flexOptionValues = new ArrayList<>(flexOption); flexOptions.put(id, flexOptionValues); } else { - flexOptions.get(id).add(flexOption); + flexOptions.get(id).addAll(flexOption); } } 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 e3777c8a..b9bf733d 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 @@ -28,6 +28,8 @@ public class ExtEmDataConnection private final Map mosaikMapping; public ExtEmDataConnection(Map extEmMapping) { + super(new EmCompletion()); + this.extEmMapping = extEmMapping; this.mosaikMapping = @@ -40,6 +42,26 @@ public List getControlledEms() { return new ArrayList<>(extEmMapping.values()); } + + public void convertAndSendFlexRequests( + long tick, Map data, Optional maybeNextTick, Logger log) { + // filtering the data and converting the keys + Map> emFlexRequests = data.values().stream().map(value -> { + UUID requester = extEmMapping.get(value.requester()); + List emEntities = ExtEntityMapping.toSimona(value.emEntities(), extEmMapping); + + return Map.entry(requester, emEntities); + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + if (emFlexRequests.isEmpty()) { + log.warn("No em flex requests found! Sending no em data to SIMONA for tick {}.", tick); + } else { + log.debug("Provided SIMONA with em flex requests."); + sendExtMsg(new ProvideFlexRequestData(tick, emFlexRequests, maybeNextTick)); + } + } + + /** * Converts the em flex options and sends them to SIMONA. * @@ -51,7 +73,11 @@ public List getControlledEms() { public void convertAndSendFlexOptions( long tick, Map> data, Optional maybeNextTick, Logger log) { // filtering the data and converting the keys - Map> emFlexOptions = ExtEntityMapping.mapToSimona(data, extEmMapping); + Map> inputData = new HashMap<>(); + data.forEach((receiver, options) -> inputData.put(receiver, ExtEntityMapping.mapToSimona(options.stream().collect(Collectors.toMap(FlexOptions::sender, i -> i)), extEmMapping))); + + + Map> emFlexOptions = ExtEntityMapping.mapToSimona(inputData, extEmMapping); if (emFlexOptions.isEmpty()) { log.warn("No em flex options found! Sending no em data to SIMONA for tick {}.", tick); diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java index 99342d10..e715a781 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java @@ -7,6 +7,7 @@ package edu.ie3.simona.api.data.em.model; import edu.ie3.datamodel.models.value.Value; -import java.util.List; +import java.util.Map; +import java.util.UUID; -public record FlexOptionValue(List flexOptions) implements Value {} +public record FlexOptionValue(Map flexOptions) implements Value {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java index 95d93944..74493538 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java @@ -6,12 +6,11 @@ package edu.ie3.simona.api.data.em.model; -import java.util.UUID; import javax.measure.quantity.Power; import tech.units.indriya.ComparableQuantity; public record FlexOptions( - UUID sender, + String sender, ComparableQuantity pMin, ComparableQuantity pRef, ComparableQuantity pMax) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java new file mode 100644 index 00000000..652b057b --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java @@ -0,0 +1,19 @@ +package edu.ie3.simona.api.data.em.model; + +import edu.ie3.datamodel.models.result.ResultEntity; + +import java.time.ZonedDateTime; +import java.util.UUID; + +public class FlexRequestResult extends ResultEntity { + + /** + * Standard constructor which includes auto generation of the resulting output models uuid. + * + * @param time date and time when the result is produced + * @param inputModel uuid of the input model that produces the result + */ + public FlexRequestResult(ZonedDateTime time, UUID inputModel) { + super(time, inputModel); + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java new file mode 100644 index 00000000..324c00cc --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java @@ -0,0 +1,3 @@ +package edu.ie3.simona.api.data.em.ontology; + +public record EmCompletion() implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java new file mode 100644 index 00000000..039d94bb --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java @@ -0,0 +1,16 @@ +/* + * © 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.em.ontology; + +import edu.ie3.simona.api.data.em.model.FlexRequestResult; + +import java.util.Map; +import java.util.UUID; + +/** Message that provides em data (flexibility requests) to an external simulation. */ +public record FlexRequestResponse(Map flexRequests) + implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java index 856fbcd5..50cd4e97 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java @@ -14,5 +14,5 @@ /** Message that provides em data (flexibility options) from an external simulation. */ public record ProvideEmFlexOptionData( - long tick, Map> flexOptions, Optional maybeNextTick) + long tick, Map> flexOptions, Optional maybeNextTick) implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java new file mode 100644 index 00000000..91f86b83 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java @@ -0,0 +1,13 @@ +package edu.ie3.simona.api.data.em.ontology; + +import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +/** Message that provides em data (flex requests) from an external simulation. */ +public record ProvideFlexRequestData( + long tick, Map> flexRequests, Optional maybeNextTick) + implements EmDataMessageFromExt {} \ No newline at end of file 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 cd84c6ae..83abf08a 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 @@ -68,6 +68,14 @@ public static List toSimona(List list, Map mapping) .toList(); } + public static List toExt(List list, Map mapping) { + return list.stream() + .map(str -> Optional.ofNullable(mapping.get(str))) + .filter(Optional::isPresent) + .map(Optional::get) + .toList(); + } + /** * Maps a map: ids to value to a map: uuids to value. * From b61f4c4b4a4fd1a6e66ba999dcfe9d6290353109 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 27 Mar 2025 16:09:51 +0100 Subject: [PATCH 22/80] Saving changes. --- .../ie3/simona/api/data/BiDirectional.java | 7 +----- .../api/data/WithDataResponseToExt.java | 22 +------------------ .../api/data/em/ExtEmDataConnection.java | 6 ++++- .../data/em/ontology/RequestEmCompletion.java | 3 +++ 4 files changed, 10 insertions(+), 28 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmCompletion.java diff --git a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java index 844bd7d2..fe70056d 100644 --- a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java +++ b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java @@ -17,18 +17,13 @@ * @param type of message to SIMONA * @param type of response messages to ext */ -public class BiDirectional +public abstract class BiDirectional extends WithDataResponseToExt implements ExtInputDataConnection { protected BiDirectional() { super(); } - protected BiDirectional(R completionMsg) { - super(completionMsg); - } - - /** Actor reference to service that handles data within SIMONA */ private ActorRef dataService; diff --git a/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java b/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java index 10bd5d94..c8a79121 100644 --- a/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java +++ b/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java @@ -8,7 +8,6 @@ import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; -import java.util.Optional; import java.util.concurrent.LinkedBlockingQueue; /** @@ -18,39 +17,20 @@ */ public abstract class WithDataResponseToExt { - private final Optional completionMsg; - /** Data message queue containing messages from SIMONA */ public final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); - protected WithDataResponseToExt() { - this.completionMsg = Optional.empty(); - } - - protected WithDataResponseToExt(T completion) { - this.completionMsg = Optional.of(completion); - } - + protected WithDataResponseToExt() {} /** Queues message from SIMONA that should be handled by the external simulation. */ public void queueExtResponseMsg(T msg) throws InterruptedException { receiveTriggerQueue.put(msg); } - public void queueExtResponseMsg(T msg, boolean finishedStep) throws InterruptedException { - receiveTriggerQueue.put(msg); - - if (finishedStep && completionMsg.isPresent()) { - receiveTriggerQueue.put(completionMsg.get()); - } - } - - public T receiveAny() throws InterruptedException { return receiveTriggerQueue.take(); } - /** * Waits until a message of given type is added to the queue. If the message has a different type, * a RuntimeException is thrown. This method blocks until having received a response from SIMONA. 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 b9bf733d..35ed0377 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 @@ -28,7 +28,7 @@ public class ExtEmDataConnection private final Map mosaikMapping; public ExtEmDataConnection(Map extEmMapping) { - super(new EmCompletion()); + super(); this.extEmMapping = extEmMapping; @@ -163,4 +163,8 @@ public Map requestEmSetPoints(long tick, List emEnti return ExtEntityMapping.mapToExt( receiveWithType(EmSetPointDataResponse.class).emData(), mosaikMapping); } + + public void requestCompletion(long tick) { + sendExtMsg(new RequestEmCompletion(tick)); + } } diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmCompletion.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmCompletion.java new file mode 100644 index 00000000..09da599f --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmCompletion.java @@ -0,0 +1,3 @@ +package edu.ie3.simona.api.data.em.ontology; + +public record RequestEmCompletion(long tick) implements EmDataMessageFromExt { } From c9506a40bd0faf9d19b765c703674feb5e85b979 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 28 Mar 2025 20:43:53 +0100 Subject: [PATCH 23/80] Saving changes. --- .../ie3/simona/api/data/em/ExtEmDataConnection.java | 9 ++++++++- .../simona/api/data/em/model/EmSetPointResult.java | 13 +++++++++++-- .../ie3/simona/api/simulation/ExtCoSimulation.java | 4 ++-- 3 files changed, 21 insertions(+), 5 deletions(-) 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 35ed0377..664dc426 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 @@ -21,15 +21,19 @@ public class ExtEmDataConnection extends BiDirectional { + private final boolean useCommunication; + /** Assets that provide data to SIMONA */ private final Map extEmMapping; /** Assets that provide data to ext */ private final Map mosaikMapping; - public ExtEmDataConnection(Map extEmMapping) { + public ExtEmDataConnection(Map extEmMapping, boolean useCommunication) { super(); + this.useCommunication = useCommunication; + this.extEmMapping = extEmMapping; this.mosaikMapping = @@ -42,6 +46,9 @@ public List getControlledEms() { return new ArrayList<>(extEmMapping.values()); } + public boolean useCommunication() { + return useCommunication; + } public void convertAndSendFlexRequests( long tick, Map data, Optional maybeNextTick, Logger log) { diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java index 8bae0c02..7dfd0edb 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java @@ -17,12 +17,21 @@ public class EmSetPointResult extends ResultEntity { private final PValue setPoint; - public EmSetPointResult(ZonedDateTime time, UUID inputModel, Optional setPoint) { + public EmSetPointResult(ZonedDateTime time, UUID inputModel, PValue setPoint) { super(time, inputModel); - this.setPoint = setPoint.orElse(null); + this.setPoint = setPoint; } public Optional getSetPoint() { return Optional.ofNullable(setPoint); } + + @Override + public String toString() { + return "EmSetPointResult{" + + "time=" + getTime() + + ", inputModel=" + getInputModel() + + ", setPoint=" + getSetPoint() + + '}'; + } } 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 eeed0051..73faa0c2 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -94,7 +94,7 @@ public static ExtPrimaryDataConnection buildPrimaryConnection( * @param log logger * @return an ext em data connection */ - public static ExtEmDataConnection buildEmConnection(ExtEntityMapping mapping, Logger log) { + public static ExtEmDataConnection buildEmConnection(ExtEntityMapping mapping, boolean useCommunication, Logger log) { Map emMapping = mapping.getExtId2UuidMapping(DataType.EXT_EM_INPUT); if (emMapping.isEmpty()) { @@ -102,7 +102,7 @@ public static ExtEmDataConnection buildEmConnection(ExtEntityMapping mapping, Lo throw new ExtDataConnectionException(ExtEmDataConnection.class); } else { log.info("Em data connection with {} entities created.", emMapping.size()); - return new ExtEmDataConnection(emMapping); + return new ExtEmDataConnection(emMapping, useCommunication); } } From 4444f9a7eec3b8d6bc7a38f34721c115a2a851ff Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 31 Mar 2025 15:21:01 +0200 Subject: [PATCH 24/80] Saving changes. --- .../datacontainer/ExtInputDataContainer.java | 24 +-- .../datacontainer/ExtResultContainer.java | 27 +-- .../api/data/em/ExtEmDataConnection.java | 120 +++-------- .../data/em/model/FlexOptionRequestValue.java | 3 +- .../simona/api/data/em/model/FlexOptions.java | 4 +- .../em/ontology/ProvideEmFlexOptionData.java | 2 +- .../primarydata/ExtPrimaryDataConnection.java | 51 +++-- .../data/results/ExtResultDataConnection.java | 61 ++---- .../api/simulation/ExtCoSimulation.java | 193 ++++-------------- .../simulation/mapping/ExtEntityMapping.java | 8 + 10 files changed, 159 insertions(+), 334 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java index 29c64ac4..f27cea12 100644 --- a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java @@ -23,12 +23,12 @@ public final class ExtInputDataContainer implements ExtDataContainer { // primary map /** Map external id to primary input value for SIMONA */ - private final Map primaryData = new HashMap<>(); + private final Map primaryData = new HashMap<>(); // em maps - private final Map flexRequests = new HashMap<>(); - private final Map> flexOptions = new HashMap<>(); - private final Map setPoints = new HashMap<>(); + private final Map flexRequests = new HashMap<>(); + private final Map> flexOptions = new HashMap<>(); + private final Map setPoints = new HashMap<>(); /** * Container class for input data for SIMONA which can be read by SimonaAPI @@ -63,15 +63,15 @@ public Optional getMaybeNextTick() { } // add data - public void addPrimaryValue(String id, Value value) { + public void addPrimaryValue(UUID id, Value value) { primaryData.put(id, value); } - public void addRequest(String requester, List emEntities) { + public void addRequest(UUID requester, List emEntities) { flexRequests.put(requester, new FlexOptionRequestValue(requester, emEntities)); } - public void addFlexOptions(String id, List flexOption) { + public void addFlexOptions(UUID id, List flexOption) { if (!flexOptions.containsKey(id)) { List flexOptionValues = new ArrayList<>(flexOption); flexOptions.put(id, flexOptionValues); @@ -80,24 +80,24 @@ public void addFlexOptions(String id, List flexOption) { } } - public void addSetPoint(String id, PValue setPoint) { + public void addSetPoint(UUID id, PValue setPoint) { setPoints.put(id, setPoint); } - public Map extractPrimaryData() { + public Map extractPrimaryData() { return copyAndClear(primaryData); } // extract and delete data - public Map extractFlexRequests() { + public Map extractFlexRequests() { return copyAndClear(flexRequests); } - public Map> extractFlexOptions() { + public Map> extractFlexOptions() { return copyAndClear(flexOptions); } - public Map extractSetPoints() { + public Map extractSetPoints() { return copyAndClear(setPoints); } diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java index c684efec..97093925 100644 --- a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java @@ -15,6 +15,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.UUID; import javax.measure.quantity.Dimensionless; import tech.units.indriya.ComparableQuantity; import tech.units.indriya.quantity.Quantities; @@ -32,7 +33,7 @@ public class ExtResultContainer implements ExtDataContainer { * Map external id to result from SIMONA ATTENTION: The time stamp of the result entities is not * necessarily corresponding to the tick */ - private final Map resultMap; + private final Map resultMap; /** * Container class for result data from SIMONA @@ -42,13 +43,13 @@ public class ExtResultContainer implements ExtDataContainer { * @param nextTick tick the external simulation can expect the next results */ public ExtResultContainer( - long tick, Map resultMap, Optional nextTick) { + long tick, Map resultMap, Optional nextTick) { this.tick = tick; this.resultMap = resultMap; this.maybeNextTick = nextTick; } - public ExtResultContainer(long tick, Map resultMap) { + public ExtResultContainer(long tick, Map resultMap) { this(tick, resultMap, Optional.empty()); } @@ -57,15 +58,15 @@ public boolean isEmpty() { return resultMap.isEmpty(); } - public Map getResults() { + public Map getResults() { return resultMap; } @SuppressWarnings("unchecked") - public Map getResults(Class clazz) { - Map result = new HashMap<>(); + public Map getResults(Class clazz) { + Map result = new HashMap<>(); - for (Map.Entry entry : resultMap.entrySet()) { + for (Map.Entry entry : resultMap.entrySet()) { ResultEntity resultEntity = entry.getValue(); if (entry.getValue().getClass().equals(clazz)) { @@ -85,7 +86,7 @@ public Optional getNextTick() { } /** Returns the result for a certain asset. */ - public ResultEntity getResult(String assetId) { + public ResultEntity getResult(UUID assetId) { return resultMap.get(assetId); } @@ -93,7 +94,7 @@ public ResultEntity getResult(String assetId) { * Returns the voltage deviation in pu for certain asset, if this asset provided a {@link * NodeResult} */ - public double getVoltageDeviation(String assetId) { + public double getVoltageDeviation(UUID assetId) { if (resultMap.get(assetId) instanceof NodeResult nodeResult) { ComparableQuantity vMagDev = Quantities.getQuantity(-1.0, PU).add(nodeResult.getvMag()); @@ -107,7 +108,7 @@ public double getVoltageDeviation(String assetId) { /** * Returns the voltage deviation for certain asset, if this asset provided a {@link NodeResult} */ - public double getVoltage(String assetId) { + public double getVoltage(UUID assetId) { if (resultMap.get(assetId) instanceof NodeResult nodeResult) { return nodeResult.getvMag().getValue().doubleValue(); } else { @@ -119,7 +120,7 @@ public double getVoltage(String assetId) { * Returns the active power in kW for certain asset, if this asset provided a {@link * SystemParticipantResult} */ - public double getActivePower(String assetId) { + public double getActivePower(UUID assetId) { if (resultMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { return systemParticipantResult.getP().getValue().doubleValue(); } else { @@ -132,7 +133,7 @@ public double getActivePower(String assetId) { * Returns the reactive power in kVAr for certain asset, if this asset provided a {@link * SystemParticipantResult} */ - public double getReactivePower(String assetId) { + public double getReactivePower(UUID assetId) { if (resultMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { return systemParticipantResult.getQ().getValue().doubleValue(); } else { @@ -142,7 +143,7 @@ public double getReactivePower(String assetId) { } /** Returns the line loading for certain asset, if this asset provided a {@link LineResult} */ - public double getLineLoading(String assetId) { + public double getLineLoading(UUID assetId) { throw new IllegalArgumentException("LINE LOADING is not implemented yet!"); } } 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 664dc426..21e33c22 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 @@ -6,141 +6,89 @@ package edu.ie3.simona.api.data.em; -import edu.ie3.datamodel.models.result.ResultEntity; +import edu.ie3.datamodel.models.result.system.FlexOptionsResult; import edu.ie3.datamodel.models.value.PValue; import edu.ie3.simona.api.data.BiDirectional; import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; import edu.ie3.simona.api.data.em.model.FlexOptions; import edu.ie3.simona.api.data.em.ontology.*; -import edu.ie3.simona.api.simulation.mapping.ExtEntityMapping; -import java.util.*; -import java.util.stream.Collectors; import org.slf4j.Logger; +import java.util.*; + /** Enables data connection of em data between SIMONA and SimonaAPI */ public class ExtEmDataConnection extends BiDirectional { private final boolean useCommunication; - /** Assets that provide data to SIMONA */ - private final Map extEmMapping; + /** Assets that are controlled by external simulation */ + private final List controlled; - /** Assets that provide data to ext */ - private final Map mosaikMapping; - - public ExtEmDataConnection(Map extEmMapping, boolean useCommunication) { + public ExtEmDataConnection(List controlled, boolean useCommunication) { super(); this.useCommunication = useCommunication; - - this.extEmMapping = extEmMapping; - - this.mosaikMapping = - extEmMapping.entrySet().stream() - .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); + this.controlled = controlled; } /** Returns a list of the uuids of the em agents that expect external set points */ public List getControlledEms() { - return new ArrayList<>(extEmMapping.values()); + return new ArrayList<>(controlled); } public boolean useCommunication() { return useCommunication; } - public void convertAndSendFlexRequests( - long tick, Map data, Optional maybeNextTick, Logger log) { - // filtering the data and converting the keys - Map> emFlexRequests = data.values().stream().map(value -> { - UUID requester = extEmMapping.get(value.requester()); - List emEntities = ExtEntityMapping.toSimona(value.emEntities(), extEmMapping); - - return Map.entry(requester, emEntities); - }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - if (emFlexRequests.isEmpty()) { + public void sendFlexRequests(long tick, Map data, Optional maybeNextTick, Logger log) { + if (data.isEmpty()) { log.warn("No em flex requests found! Sending no em data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with em flex requests."); + + Map> emFlexRequests = new HashMap<>(); + data.forEach((receiver, requests) -> emFlexRequests.put(receiver, requests.emEntities())); + sendExtMsg(new ProvideFlexRequestData(tick, emFlexRequests, maybeNextTick)); } } - /** - * Converts the em flex options and sends them to SIMONA. + * Sends the em flex options and to SIMONA. * * @param tick current tick - * @param data to be converted and send + * @param data to be sent * @param maybeNextTick option for the next tick in the simulation * @param log logger */ - public void convertAndSendFlexOptions( - long tick, Map> data, Optional maybeNextTick, Logger log) { - // filtering the data and converting the keys - Map> inputData = new HashMap<>(); - data.forEach((receiver, options) -> inputData.put(receiver, ExtEntityMapping.mapToSimona(options.stream().collect(Collectors.toMap(FlexOptions::sender, i -> i)), extEmMapping))); - - - Map> emFlexOptions = ExtEntityMapping.mapToSimona(inputData, extEmMapping); - - if (emFlexOptions.isEmpty()) { + public void sendFlexOptions(long tick, Map> data, Optional maybeNextTick, Logger log) { + if (data.isEmpty()) { log.warn("No em flex options found! Sending no em data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with em flex options."); - sendExtMsg(new ProvideEmFlexOptionData(tick, emFlexOptions, maybeNextTick)); + sendExtMsg(new ProvideEmFlexOptionData(tick, data, maybeNextTick)); } } /** - * Converts the em set points and sends them to SIMONA. + * Sends the em set points to SIMONA. * * @param tick current tick - * @param data to be converted and send + * @param data to be sent * @param maybeNextTick option for the next tick in the simulation * @param log logger */ - public void convertAndSendSetPoints( - long tick, Map data, Optional maybeNextTick, Logger log) { - // filtering the data and converting the keys - Map emSetPoints = ExtEntityMapping.mapToSimona(data, extEmMapping); - - if (emSetPoints.isEmpty()) { + public void sendSetPoints(long tick, Map data, Optional maybeNextTick, Logger log) { + if (data.isEmpty()) { log.warn("No em set points found! Sending no em data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with em set points."); - sendExtMsg(new ProvideEmSetPointData(tick, emSetPoints, maybeNextTick)); + sendExtMsg(new ProvideEmSetPointData(tick, data, maybeNextTick)); } } - /** - * Converts and requests em flexibility options from SIMONA. - * - * @param tick for which set points are requested - * @param emEntities for which set points are requested - * @return an {@link FlexOptionsResponse} message - * @throws InterruptedException - on interruptions - */ - public Map convertAndSendRequestFlexResults( - long tick, Map emEntities, Logger log) - throws InterruptedException { - Map> m = - emEntities.entrySet().stream() - .map( - e -> - Map.entry( - e.getKey(), - ExtEntityMapping.toSimona(e.getValue().emEntities(), extEmMapping))) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - Map> map = ExtEntityMapping.mapToSimona(m, extEmMapping); - log.info("Provided SIMONA with em flex request: {}", map); - - return requestEmFlexResults(tick, map); - } - /** * Method to request em flexibility options from SIMONA. * @@ -149,26 +97,10 @@ public Map convertAndSendRequestFlexResults( * @return an {@link FlexOptionsResponse} message * @throws InterruptedException - on interruptions */ - public Map requestEmFlexResults(long tick, Map> emEntities) + public Map requestEmFlexResults(long tick, Map> emEntities) throws InterruptedException { sendExtMsg(new RequestEmFlexResults(tick, emEntities)); - return ExtEntityMapping.mapToExt( - receiveWithType(FlexOptionsResponse.class).flexOptions(), mosaikMapping); - } - - /** - * Method to request em set points from SIMONA. - * - * @param tick for which set points are requested - * @param emEntities for which set points are requested - * @return an {@link EmSetPointDataResponse} message - * @throws InterruptedException - on interruptions - */ - public Map requestEmSetPoints(long tick, List emEntities) - throws InterruptedException { - sendExtMsg(new RequestEmSetPoints(tick, emEntities)); - return ExtEntityMapping.mapToExt( - receiveWithType(EmSetPointDataResponse.class).emData(), mosaikMapping); + return receiveWithType(FlexOptionsResponse.class).flexOptions(); } public void requestCompletion(long tick) { diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java index 759bd97f..c45302d1 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java @@ -8,5 +8,6 @@ import edu.ie3.datamodel.models.value.Value; import java.util.List; +import java.util.UUID; -public record FlexOptionRequestValue(String requester, List emEntities) implements Value {} +public record FlexOptionRequestValue(UUID requester, List emEntities) implements Value {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java index 74493538..89fd55f4 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java @@ -9,8 +9,10 @@ import javax.measure.quantity.Power; import tech.units.indriya.ComparableQuantity; +import java.util.UUID; + public record FlexOptions( - String sender, + UUID sender, ComparableQuantity pMin, ComparableQuantity pRef, ComparableQuantity pMax) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java index 50cd4e97..856fbcd5 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java @@ -14,5 +14,5 @@ /** Message that provides em data (flexibility options) from an external simulation. */ public record ProvideEmFlexOptionData( - long tick, Map> flexOptions, Optional maybeNextTick) + long tick, Map> flexOptions, Optional maybeNextTick) implements EmDataMessageFromExt {} 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 cd577ba7..52fb000f 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,33 +7,42 @@ package edu.ie3.simona.api.data.primarydata; import edu.ie3.datamodel.models.value.Value; -import edu.ie3.simona.api.data.ExtInputDataConnectionWithMapping; +import edu.ie3.simona.api.data.ExtInputDataConnection; +import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; import edu.ie3.simona.api.data.primarydata.ontology.PrimaryDataMessageFromExt; import edu.ie3.simona.api.data.primarydata.ontology.ProvidePrimaryData; -import edu.ie3.simona.api.simulation.mapping.ExtEntityMapping; +import org.apache.pekko.actor.ActorRef; +import org.slf4j.Logger; + 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 - extends ExtInputDataConnectionWithMapping { +public class ExtPrimaryDataConnection implements ExtInputDataConnection { - private Map> valueClasses; + /** Actor reference to service that handles data within SIMONA */ + private ActorRef dataService; - public ExtPrimaryDataConnection(Map extPrimaryDataMapping) { - super(extPrimaryDataMapping); - } + /** Actor reference to adapter that handles scheduler control flow in SIMONA */ + private ActorRef extSimAdapter; - public void setValueClasses(Map> valueClasses) { + private final Map> valueClasses; + + public ExtPrimaryDataConnection(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(); + return valueClasses.keySet().stream().toList(); + } + + @Override + public void setActorRefs(ActorRef dataService, ActorRef extSimAdapter) { + this.dataService = dataService; + this.extSimAdapter = extSimAdapter; } /** @@ -44,24 +53,24 @@ public Optional> getValueClass(UUID uuid) { return Optional.ofNullable(valueClasses.get(uuid)); } - @Override - public void convertAndSend( - long tick, Map data, Optional maybeNextTick, Logger log) { - // filtering the data and converting the keys - Map convertedMap = ExtEntityMapping.mapToSimona(data, extDataMapping); - - if (convertedMap.isEmpty()) { + public void sendPrimaryData(long tick, Map data, Optional maybeNextTick, Logger log) { + if (data.isEmpty()) { log.warn("No primary data found! Sending no primary data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with primary data."); - log.info("Data: {}", convertedMap); - provideData(tick, convertedMap, maybeNextTick); + log.info("Data: {}", data); + provideData(tick, data, maybeNextTick); } } /** Provide primary data from an external simulation in one tick. */ - @Override public void provideData(long tick, Map primaryData, Optional maybeNextTick) { sendExtMsg(new ProvidePrimaryData(tick, primaryData, maybeNextTick)); } + + 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/data/results/ExtResultDataConnection.java b/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java index 319b027e..cbcf16f4 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 @@ -6,10 +6,7 @@ package edu.ie3.simona.api.data.results; -import edu.ie3.datamodel.models.result.NodeResult; import edu.ie3.datamodel.models.result.ResultEntity; -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.WithDataResponseToExt; import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; @@ -17,12 +14,13 @@ import edu.ie3.simona.api.data.results.ontology.RequestResultEntities; import edu.ie3.simona.api.data.results.ontology.ResultDataMessageFromExt; import edu.ie3.simona.api.data.results.ontology.ResultDataResponseMessageToExt; -import java.util.HashMap; +import org.apache.pekko.actor.ActorRef; + import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.pekko.actor.ActorRef; /** Enables data connection of results between SIMONA and SimonaAPI */ public class ExtResultDataConnection extends WithDataResponseToExt @@ -38,21 +36,21 @@ public class ExtResultDataConnection extends WithDataResponseToExt gridResultAssetMapping; + private final List gridResults; /** Map uuid to external id of system participants */ - private final Map participantResultAssetMapping; + private final List participantResults; /** Map uuid to external id of participant flex options */ - private final Map flexOptionsMapping; + private final List flexResults; public ExtResultDataConnection( - Map participantResultAssetMapping, - Map gridResultAssetMapping, - Map flexOptionsMapping) { - this.participantResultAssetMapping = participantResultAssetMapping; - this.gridResultAssetMapping = gridResultAssetMapping; - this.flexOptionsMapping = flexOptionsMapping; + List participantResults, + List gridResults, + List flexResults) { + this.participantResults = participantResults; + this.gridResults = gridResults; + this.flexResults = flexResults; } /** @@ -71,15 +69,15 @@ public void setActorRefs( } public List getGridResultDataAssets() { - return gridResultAssetMapping.keySet().stream().toList(); + return gridResults; } public List getParticipantResultDataAssets() { - return participantResultAssetMapping.keySet().stream().toList(); + return participantResults; } public List getFlexOptionAssets() { - return flexOptionsMapping.keySet().stream().toList(); + return flexResults; } /** Method that an external simulation can request results from SIMONA as a list. */ @@ -111,42 +109,25 @@ private List requestParticipantResultsList(long tick) throws Inter /** * Method that an external simulation can request results from SIMONA as a map string to object. */ - public Map requestResults(long tick) throws InterruptedException { + public Map requestResults(long tick) throws InterruptedException { return createResultMap(requestResultList(tick)); } - public Map requestFlexOptionResults(long tick) throws InterruptedException { + public Map requestFlexOptionResults(long tick) throws InterruptedException { return createResultMap(requestFlexOptionResultsList(tick)); } - public Map requestGridResults(long tick) throws InterruptedException { + public Map requestGridResults(long tick) throws InterruptedException { return createResultMap(requestGridResultsList(tick)); } - public Map requestParticipantResults(long tick) + public Map requestParticipantResults(long tick) throws InterruptedException { return createResultMap(requestParticipantResultsList(tick)); } - protected Map createResultMap(List results) { - Map resultMap = new HashMap<>(); - results.forEach( - result -> { - if (result instanceof NodeResult nodeResult) { - resultMap.put(gridResultAssetMapping.get(nodeResult.getInputModel()), nodeResult); - } else if (result instanceof SystemParticipantResult systemParticipantResult) { - 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, FlexOptionResult's and SystemParticipantResult's!"); - } - }); - return resultMap; + protected Map createResultMap(List results) { + return results.stream().collect(Collectors.toMap(ResultEntity::getInputModel, i -> i)); } /** 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 73faa0c2..d4ef41c6 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -13,18 +13,19 @@ import edu.ie3.simona.api.data.datacontainer.ExtInputDataContainer; import edu.ie3.simona.api.data.datacontainer.ExtResultContainer; import edu.ie3.simona.api.data.em.ExtEmDataConnection; -import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; -import edu.ie3.simona.api.data.em.model.FlexOptions; import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; 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; import org.slf4j.Logger; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import static java.util.Collections.emptyList; + /** * Abstract class for an external co-simulation with the structure: external api - ext-co-simulation * - ext-simulation - simonaAPI - simona @@ -55,55 +56,39 @@ protected ExtCoSimulation(String simulationName, String extSimulatorName) { /** * Builds an {@link ExtPrimaryDataConnection}. * - * @param mapping between the external simulation and SIMONA. + * @param assetToValueClasses between primary asset and its value class. * @param log logger * @return an ext primary data connection */ - @SuppressWarnings("unchecked") public static ExtPrimaryDataConnection buildPrimaryConnection( - ExtEntityMapping mapping, Logger log) { - List entries = mapping.getExtEntityEntries(DataType.EXT_PRIMARY_INPUT); + Map> assetToValueClasses, Logger log) { - if (entries.isEmpty()) { + if (assetToValueClasses.isEmpty()) { log.warn("No primary data connection was created."); throw new ExtDataConnectionException(ExtPrimaryDataConnection.class); } else { - 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; + log.info("Primary data connection with {} entities created.", assetToValueClasses.size()); + + return new ExtPrimaryDataConnection(assetToValueClasses); } } /** * Builds an {@link ExtEmDataConnection}. * - * @param mapping between the external simulation and SIMONA. + * @param controlled uuids for controlled em agents. * @param log logger * @return an ext em data connection */ - public static ExtEmDataConnection buildEmConnection(ExtEntityMapping mapping, boolean useCommunication, Logger log) { - Map emMapping = mapping.getExtId2UuidMapping(DataType.EXT_EM_INPUT); - - if (emMapping.isEmpty()) { - log.warn("No em data connection was created."); - throw new ExtDataConnectionException(ExtEmDataConnection.class); - } else { - log.info("Em data connection with {} entities created.", emMapping.size()); - return new ExtEmDataConnection(emMapping, useCommunication); + public static ExtEmDataConnection buildEmConnection(List controlled, boolean useCommunication, Logger log) { + if (!useCommunication) { + if (controlled.isEmpty()) { + log.warn("Em data connection with 0 controlled entities created. This might lead to errors!"); + } else { + log.info("Em data connection with {} controlled entities created.", controlled.size()); + } } + return new ExtEmDataConnection(controlled, useCommunication); } /** @@ -114,26 +99,23 @@ public static ExtEmDataConnection buildEmConnection(ExtEntityMapping mapping, bo * @return an ext result data connection */ 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); - - if (resultParticipantMapping.isEmpty() - && resultGridMapping.isEmpty() - && resultFlexOptionsMapping.isEmpty()) { + Map> mapping, Logger log) { + List participantResults = mapping.getOrDefault(DataType.EXT_PARTICIPANT_RESULT, emptyList()); + List gridResults = mapping.getOrDefault(DataType.EXT_GRID_RESULT, emptyList()); + List flexResults = mapping.getOrDefault(DataType.EXT_FLEX_OPTIONS_RESULT, emptyList()); + + if (participantResults.isEmpty() + && gridResults.isEmpty() + && flexResults.isEmpty()) { log.warn("No result connection was created."); throw new ExtDataConnectionException(ExtResultDataConnection.class); } else { log.info( "Result connection with {} participants, {} grid assets and {} flex option mappings created.", - resultParticipantMapping.size(), - resultGridMapping.size(), - resultFlexOptionsMapping.size()); - return new ExtResultDataConnection( - resultParticipantMapping, resultGridMapping, resultFlexOptionsMapping); + participantResults.size(), + gridResults.size(), + flexResults.size()); + return new ExtResultDataConnection(participantResults, gridResults, flexResults); } } @@ -166,7 +148,7 @@ protected void sendPrimaryDataToSimona( Logger log) throws InterruptedException { checkTick(tick); - Map inputData = + Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractPrimaryData); sendPrimaryDataToSimona(extPrimaryDataConnection, tick, inputData, maybeNextTick, log); } @@ -183,108 +165,17 @@ protected void sendPrimaryDataToSimona( protected void sendPrimaryDataToSimona( ExtPrimaryDataConnection extPrimaryDataConnection, long tick, - Map dataMap, + Map dataMap, Optional maybeNextTick, Logger log) { log.debug("Wait for Primary Data from {}", extSimulatorName); log.debug("Received Primary Data from {}", extSimulatorName); - extPrimaryDataConnection.convertAndSend(tick, dataMap, maybeNextTick, log); + extPrimaryDataConnection.sendPrimaryData(tick, dataMap, maybeNextTick, log); log.debug("Provided Primary Data to SIMONA!"); } // energy management data methods - /** - * Function to send em flex options from SIMONA to the external simulation using the given {@link - * ExtEmDataConnection}. This method will provide values to the {@link #queueToExt}. - * - * @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 - * @throws InterruptedException if the fetching of data is interrupted - */ - protected void sendEmFlexResultsToExt( - ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) - throws InterruptedException { - // sending flex request to simona - Map inputData = - queueToSimona.takeData(ExtInputDataContainer::extractFlexRequests); - - log.info("Request flex options for: {}", inputData); - Map results = - extEmDataConnection.convertAndSendRequestFlexResults(tick, inputData, log); - log.warn("Flex results to ext : {}", results); - - sendSingleResultType("em flexibility option", results, tick, maybeNextTick, log); - } - - /** - * Function to send em set points from SIMONA to the external simulation using the given {@link - * ExtEmDataConnection}. This method will provide values to the {@link #queueToExt}. - * - * @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 - * @throws InterruptedException if the fetching of data is interrupted - */ - protected void sendEmSetPointsToExt( - ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) - throws InterruptedException { - sendSingleResultType( - "em set point", - extEmDataConnection.requestEmSetPoints(tick, extEmDataConnection.getControlledEms()), - tick, - maybeNextTick, - log); - } - - /** - * Function to send em flex options to SIMONA using the given {@link ExtEmDataConnection}. This - * method will take a value from the {@link #queueToSimona}. - * - *

{@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 - * @throws InterruptedException if the fetching of data is interrupted - */ - protected void sendEmFlexOptionsToSimona( - ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) - throws InterruptedException { - checkTick(tick); - Map> inputData = - queueToSimona.takeData(ExtInputDataContainer::extractFlexOptions); - sendEmFlexOptionsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); - } - - /** - * Function to send em flex options 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 - * @param dataMap map: id to value - * @param maybeNextTick option for the next tick data is sent - * @param log logger - */ - protected void sendEmFlexOptionsToSimona( - ExtEmDataConnection extEmDataConnection, - long tick, - Map> dataMap, - Optional maybeNextTick, - Logger log) { - log.debug("Received em flex options from {}", extSimulatorName); - extEmDataConnection.convertAndSendFlexOptions(tick, dataMap, maybeNextTick, log); - log.debug("Provided em flex options to SIMONA!"); - } - /** * Function to send em set point data to SIMONA using the given {@link ExtEmDataConnection}. This * method will take a value from the {@link #queueToSimona}. @@ -302,7 +193,7 @@ protected void sendEmSetPointsToSimona( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { checkTick(tick); - Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractSetPoints); + Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractSetPoints); sendEmSetPointsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); } @@ -322,11 +213,11 @@ protected void sendEmSetPointsToSimona( protected void sendEmSetPointsToSimona( ExtEmDataConnection extEmDataConnection, long tick, - Map dataMap, + Map dataMap, Optional maybeNextTick, Logger log) { log.debug("Received em set points from {}", extSimulatorName); - extEmDataConnection.convertAndSendSetPoints(tick, dataMap, maybeNextTick, log); + extEmDataConnection.sendSetPoints(tick, dataMap, maybeNextTick, log); log.debug("Provided em set points to SIMONA!"); } @@ -378,7 +269,7 @@ protected void sendResultToExt( ExtResultDataConnection connection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { log.debug("Request results from SIMONA!"); - Map resultsToBeSend = connection.requestResults(tick); + Map resultsToBeSend = connection.requestResults(tick); log.debug("Received results from SIMONA!"); queueToExt.queueData(new ExtResultContainer(tick, resultsToBeSend, maybeNextTick)); log.debug("Sent results to {}", extSimulatorName); @@ -386,7 +277,7 @@ protected void sendResultToExt( private void sendSingleResultType( String type, - Map resultsToBeSend, + Map resultsToBeSend, long tick, Optional nextTick, Logger log) 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 83abf08a..44a004ea 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 @@ -18,6 +18,10 @@ public class ExtEntityMapping { private final Map> extEntities; + public ExtEntityMapping(Map> extEntities) { + this.extEntities = extEntities; + } + public ExtEntityMapping(List extEntityEntryList) { this.extEntities = extEntityEntryList.stream().collect(Collectors.groupingBy(ExtEntityEntry::dataType)); @@ -49,6 +53,10 @@ public Map getExtId2UuidMapping(DataType dataType) { .collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); } + public Map getFullMapping() { + return extEntities.values().stream().flatMap(Collection::stream).collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); + } + /** * Mapping SIMONA uuid to external id * From 6fcd05aadd7b0bfcf40fc5bf9181f7161e5b54da Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 31 Mar 2025 15:35:56 +0200 Subject: [PATCH 25/80] Saving changes. --- .../edu/ie3/simona/api/data/em/{ => model}/NoSetPointValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/edu/ie3/simona/api/data/em/{ => model}/NoSetPointValue.java (91%) diff --git a/src/main/java/edu/ie3/simona/api/data/em/NoSetPointValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/NoSetPointValue.java similarity index 91% rename from src/main/java/edu/ie3/simona/api/data/em/NoSetPointValue.java rename to src/main/java/edu/ie3/simona/api/data/em/model/NoSetPointValue.java index 368cfd8a..65c18498 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/NoSetPointValue.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/NoSetPointValue.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em; +package edu.ie3.simona.api.data.em.model; import edu.ie3.datamodel.models.value.PValue; import javax.measure.quantity.Power; From 5b07f8442386677bdf8e2834692b224bf12b2916 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 1 Apr 2025 15:09:49 +0200 Subject: [PATCH 26/80] Saving changes. --- .../ie3/simona/api/data/BiDirectional.java | 15 ++-- .../ExtInputDataConnectionWithMapping.java | 79 ------------------- .../api/data/ExtOutputDataConnection.java | 4 - .../data/results/ExtResultDataConnection.java | 16 +--- .../ontology/RequestResultEntities.java | 2 +- 5 files changed, 14 insertions(+), 102 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java diff --git a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java index fe70056d..336c1a67 100644 --- a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java +++ b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java @@ -9,7 +9,8 @@ import edu.ie3.simona.api.data.ontology.DataMessageFromExt; import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; -import org.apache.pekko.actor.ActorRef; +import edu.ie3.simona.api.simulation.ontology.ControlResponseMessageFromExt; +import org.apache.pekko.actor.typed.ActorRef; /** * Enables bidirectional communication when extended by an external data connection. @@ -25,21 +26,23 @@ protected BiDirectional() { } /** Actor reference to service that handles data within SIMONA */ - private ActorRef dataService; + private ActorRef dataService; /** Actor reference to adapter that handles scheduler control flow in SIMONA */ - private ActorRef extSimAdapter; + private ActorRef extSimAdapter; @Override - public void setActorRefs(ActorRef dataService, ActorRef extSimAdapter) { + public void setActorRefs( + ActorRef dataService, + ActorRef extSimAdapter) { this.dataService = dataService; this.extSimAdapter = extSimAdapter; } @Override public void sendExtMsg(M msg) { - dataService.tell(msg, ActorRef.noSender()); + dataService.tell(msg); // we need to schedule data receiver activation with scheduler - extSimAdapter.tell(new ScheduleDataServiceMessage(dataService), ActorRef.noSender()); + extSimAdapter.tell(new ScheduleDataServiceMessage(dataService)); } } diff --git a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java deleted file mode 100644 index 9da67568..00000000 --- a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnectionWithMapping.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * © 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 */ - protected 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); - - 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/ExtOutputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java index 11470c5e..dec3f7fb 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java @@ -9,7 +9,6 @@ import edu.ie3.simona.api.data.ontology.DataMessageFromExt; import edu.ie3.simona.api.simulation.ontology.ControlResponseMessageFromExt; import org.apache.pekko.actor.typed.ActorRef; -import edu.ie3.simona.api.data.ontology.DataMessageFromExt; /** * Interface for a connection between SIMONA and an external simulation with data flow from SIMONA @@ -21,13 +20,10 @@ public interface ExtOutputDataConnection extends E * Sets the actor refs for data and control flow * * @param extResultDataService actor ref to the adapter of the data service for data messages - * @param dataServiceActivation actor ref to the adapter of the data service for schedule - * activation messages * @param extSimAdapter actor ref to the extSimAdapter */ void setActorRefs( ActorRef extResultDataService, - ActorRef dataServiceActivation, ActorRef extSimAdapter); /** * Send information from the external simulation to SIMONA's external data service. Furthermore, 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 fb09ecf8..739f0925 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,20 +8,19 @@ import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.simona.api.data.ExtOutputDataConnection; -import edu.ie3.simona.api.data.ontology.DataMessageFromExt; import edu.ie3.simona.api.data.WithDataResponseToExt; +import edu.ie3.simona.api.data.ontology.DataMessageFromExt; import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; import edu.ie3.simona.api.data.results.ontology.ProvideResultEntities; import edu.ie3.simona.api.data.results.ontology.RequestResultEntities; import edu.ie3.simona.api.data.results.ontology.ResultDataMessageFromExt; import edu.ie3.simona.api.data.results.ontology.ResultDataResponseMessageToExt; import edu.ie3.simona.api.simulation.ontology.ControlResponseMessageFromExt; -import java.util.HashMap; +import org.apache.pekko.actor.typed.ActorRef; + import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.concurrent.LinkedBlockingQueue; -import org.apache.pekko.actor.typed.ActorRef; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -32,9 +31,6 @@ public class ExtResultDataConnection extends WithDataResponseToExt extResultDataService; - /** Actor reference to the dataServiceAdapter */ - private ActorRef dataServiceActivation; - /** Actor reference to adapter that handles scheduler control flow in SIMONA */ private ActorRef extSimAdapter; @@ -60,16 +56,12 @@ public ExtResultDataConnection( * Sets the actor refs for data and control flow * * @param extResultDataService actor ref to the adapter of the data service for data messages - * @param dataServiceActivation actor ref to the adapter of the data service for schedule - * activation messages * @param extSimAdapter actor ref to the extSimAdapter */ public void setActorRefs( ActorRef extResultDataService, - ActorRef dataServiceActivation, ActorRef extSimAdapter) { this.extResultDataService = extResultDataService; - this.dataServiceActivation = dataServiceActivation; this.extSimAdapter = extSimAdapter; } @@ -145,6 +137,6 @@ protected Map createResultMap(List results) { public void sendExtMsg(ResultDataMessageFromExt msg) { extResultDataService.tell(msg); // we need to schedule data receiver activation with scheduler - extSimAdapter.tell(new ScheduleDataServiceMessage(dataServiceActivation)); + extSimAdapter.tell(new ScheduleDataServiceMessage(extResultDataService)); } } 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 9f72ab7b..bc4dc37f 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,5 +10,5 @@ import java.util.UUID; /** Request calculated results from SIMONA in the current tick */ -public record RequestResultEntities(Long tick, List requestedResults) +public record RequestResultEntities(long tick, List requestedResults) implements ResultDataMessageFromExt {} From 0fb54523f60e2ac430694f59061e6cbb89e65e74 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 2 Apr 2025 15:41:10 +0200 Subject: [PATCH 27/80] Saving changes. --- .../ie3/simona/api/data/BiDirectional.java | 47 +++++---- .../api/data/ExtInputDataConnection.java | 39 +++++--- .../api/data/ExtOutputDataConnection.java | 35 ++++--- .../api/data/WithDataResponseToExt.java | 60 ----------- .../edu/ie3/simona/api/data/em/EmMode.java | 25 +++++ .../api/data/em/ExtEmDataConnection.java | 8 +- .../api/data/ev/ExtEvDataConnection.java | 74 ++------------ .../primarydata/ExtPrimaryDataConnection.java | 22 +---- .../data/results/ExtResultDataConnection.java | 42 +------- .../api/data/results/ExtResultListener.java | 44 +++++++++ .../api/simulation/ExtCoSimulation.java | 99 ++++++++++++++++--- .../api/simulation/mapping/DataType.java | 2 + .../simulation/mapping/ExtEntityMapping.java | 2 +- 13 files changed, 241 insertions(+), 258 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java create mode 100644 src/main/java/edu/ie3/simona/api/data/em/EmMode.java create mode 100644 src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java diff --git a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java index 336c1a67..040d346a 100644 --- a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java +++ b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java @@ -8,9 +8,8 @@ import edu.ie3.simona.api.data.ontology.DataMessageFromExt; import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; -import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; -import edu.ie3.simona.api.simulation.ontology.ControlResponseMessageFromExt; -import org.apache.pekko.actor.typed.ActorRef; + +import java.util.concurrent.LinkedBlockingQueue; /** * Enables bidirectional communication when extended by an external data connection. @@ -19,30 +18,38 @@ * @param type of response messages to ext */ public abstract class BiDirectional - extends WithDataResponseToExt implements ExtInputDataConnection { + extends ExtInputDataConnection implements ExtOutputDataConnection { + + /** Data message queue containing messages from SIMONA */ + public final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); protected BiDirectional() { super(); } - /** 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; + public final void queueExtResponseMsg(R msg) throws InterruptedException { + receiveTriggerQueue.put(msg); + } - @Override - public void setActorRefs( - ActorRef dataService, - ActorRef extSimAdapter) { - this.dataService = dataService; - this.extSimAdapter = extSimAdapter; + public final R receiveAny() throws InterruptedException { + return receiveTriggerQueue.take(); } - @Override - public void sendExtMsg(M msg) { - dataService.tell(msg); - // we need to schedule data receiver activation with scheduler - extSimAdapter.tell(new ScheduleDataServiceMessage(dataService)); + @SuppressWarnings("unchecked") + public final T receiveWithType(Class expectedMessageClass) + throws InterruptedException { + // blocks until actor puts something here + R msg = receiveTriggerQueue.take(); + + if (msg.getClass().equals(expectedMessageClass)) { + return (T) msg; + } else + throw new RuntimeException( + "Received unexpected message '" + + msg + + "', expected type '" + + expectedMessageClass + + "'"); } + } diff --git a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java index 07a6070a..c2667fe1 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java @@ -7,27 +7,34 @@ package edu.ie3.simona.api.data; import edu.ie3.simona.api.data.ontology.DataMessageFromExt; +import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; import edu.ie3.simona.api.simulation.ontology.ControlResponseMessageFromExt; import org.apache.pekko.actor.typed.ActorRef; -import edu.ie3.simona.api.data.ontology.DataMessageFromExt; /** - * Interface for a connection between SIMONA and an external simulation with data flow from external + * Abstract base class for a connection between SIMONA and an external simulation with data flow from external * to SIMONA. */ -public interface ExtInputDataConnection extends ExtDataConnection { +public abstract class ExtInputDataConnection implements ExtDataConnection { + + /** Actor reference to service that handles data within SIMONA */ + private ActorRef dataService; - /** - * Sets the actor refs for data and control flow. - * - * @param dataService actor ref to the adapter of the data service for schedule activation - * messages - * @param extSimAdapter actor ref to the extSimAdapter - */ - void setActorRefs( - ActorRef dataService, - ActorRef extSimAdapter); + /** Actor reference to adapter that handles scheduler control flow in SIMONA */ + private ActorRef extSimAdapter; + /** + * Sets the actor refs for data and control flow + * + * @param extResultDataService actor ref to the adapter of the data service for data messages + * @param extSimAdapter actor ref to the extSimAdapter + */ + public final void setActorRefs( + ActorRef extResultDataService, + ActorRef extSimAdapter) { + this.dataService = extResultDataService; + this.extSimAdapter = extSimAdapter; + } /** * Send information from the external simulation to SIMONA's external data service. Furthermore, * ExtSimAdapter within SIMONA is instructed to activate the external data service with the @@ -35,5 +42,9 @@ void setActorRefs( * * @param msg the data/information that is sent to SIMONA's result data service */ - void sendExtMsg(M msg); + public final void sendExtMsg(M msg) { + dataService.tell(msg); + // we need to schedule data receiver activation with scheduler + extSimAdapter.tell(new ScheduleDataServiceMessage(dataService)); + } } diff --git a/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java index dec3f7fb..2cb242e8 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java @@ -6,31 +6,30 @@ package edu.ie3.simona.api.data; -import edu.ie3.simona.api.data.ontology.DataMessageFromExt; -import edu.ie3.simona.api.simulation.ontology.ControlResponseMessageFromExt; -import org.apache.pekko.actor.typed.ActorRef; +import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; /** * Interface for a connection between SIMONA and an external simulation with data flow from SIMONA * to external. + * @param type of response messages to ext */ -public interface ExtOutputDataConnection extends ExtDataConnection { +public interface ExtOutputDataConnection { + + /** Queues message from SIMONA that should be handled by the external simulation. */ + void queueExtResponseMsg(T msg) throws InterruptedException; + + + T receiveAny() throws InterruptedException; /** - * Sets the actor refs for data and control flow - * - * @param extResultDataService actor ref to the adapter of the data service for data messages - * @param extSimAdapter actor ref to the extSimAdapter - */ - void setActorRefs( - ActorRef extResultDataService, - ActorRef extSimAdapter); - /** - * Send information from the external simulation to SIMONA's external data service. Furthermore, - * ExtSimAdapter within SIMONA is instructed to activate the external data service with the - * current tick. + * Waits until a message of given type is added to the queue. If the message has a different type, + * a RuntimeException is thrown. This method blocks until having received a response from SIMONA. * - * @param msg the data/information that is sent to SIMONA's result data service + * @param expectedMessageClass the expected class of the message to be received + * @return a message of the expected type once it has been received + * @param the type of the expected message + * @throws InterruptedException if the thread running this has been interrupted during the + * blocking operation */ - void sendExtMsg(M msg); + R receiveWithType(Class expectedMessageClass) throws InterruptedException; } diff --git a/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java b/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java deleted file mode 100644 index c8a79121..00000000 --- a/src/main/java/edu/ie3/simona/api/data/WithDataResponseToExt.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * © 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.simona.api.data.ontology.DataResponseMessageToExt; - -import java.util.concurrent.LinkedBlockingQueue; - -/** - * Enables receiving data responses form SIMONA. - * - * @param type of response messages to ext - */ -public abstract class WithDataResponseToExt { - - /** Data message queue containing messages from SIMONA */ - public final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); - - protected WithDataResponseToExt() {} - - /** Queues message from SIMONA that should be handled by the external simulation. */ - public void queueExtResponseMsg(T msg) throws InterruptedException { - receiveTriggerQueue.put(msg); - } - - public T receiveAny() throws InterruptedException { - return receiveTriggerQueue.take(); - } - - /** - * Waits until a message of given type is added to the queue. If the message has a different type, - * a RuntimeException is thrown. This method blocks until having received a response from SIMONA. - * - * @param expectedMessageClass the expected class of the message to be received - * @return a message of the expected type once it has been received - * @param the type of the expected message - * @throws InterruptedException if the thread running this has been interrupted during the - * blocking operation - */ - @SuppressWarnings("unchecked") - protected R receiveWithType(Class expectedMessageClass) - throws InterruptedException { - // blocks until actor puts something here - T msg = receiveTriggerQueue.take(); - - if (msg.getClass().equals(expectedMessageClass)) { - return (R) msg; - } else - throw new RuntimeException( - "Received unexpected message '" - + msg - + "', expected type '" - + expectedMessageClass - + "'"); - } -} diff --git a/src/main/java/edu/ie3/simona/api/data/em/EmMode.java b/src/main/java/edu/ie3/simona/api/data/em/EmMode.java new file mode 100644 index 00000000..e4606408 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/EmMode.java @@ -0,0 +1,25 @@ +package edu.ie3.simona.api.data.em; + +import edu.ie3.simona.api.simulation.mapping.DataType; + +public enum EmMode { + SET_POINT("setPoint"), + EM_COMMUNICATION("emCommunication"), + EM_OPTIMIZATION("emOptimization"),; + + + public final String mode; + + EmMode(String mode) { + this.mode = mode; + } + + public static EmMode fromDataType(DataType dataType) { + return switch (dataType) { + case EXT_EM_INPUT -> EmMode.SET_POINT; + case EXT_EM_COMMUNICATION -> EmMode.EM_COMMUNICATION; + case EXT_EM_OPTIMIZER -> EmMode.EM_OPTIMIZATION; + default -> throw new IllegalStateException("Unexpected data type: " + dataType); + }; + } +} 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 21e33c22..b6dfbba4 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 @@ -20,15 +20,15 @@ public class ExtEmDataConnection extends BiDirectional { - private final boolean useCommunication; + public final EmMode mode; /** Assets that are controlled by external simulation */ private final List controlled; - public ExtEmDataConnection(List controlled, boolean useCommunication) { + public ExtEmDataConnection(List controlled, EmMode mode) { super(); - this.useCommunication = useCommunication; + this.mode = mode; this.controlled = controlled; } @@ -38,7 +38,7 @@ public List getControlledEms() { } public boolean useCommunication() { - return useCommunication; + return mode == EmMode.EM_COMMUNICATION; } diff --git a/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java b/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java index b8c3bd59..ab17a5b7 100644 --- a/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java @@ -6,23 +6,22 @@ package edu.ie3.simona.api.data.ev; -import edu.ie3.simona.api.data.ExtInputDataConnection; +import edu.ie3.simona.api.data.BiDirectional; import edu.ie3.simona.api.data.ev.model.EvModel; import edu.ie3.simona.api.data.ev.ontology.*; import edu.ie3.simona.api.data.ontology.DataMessageFromExt; -import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; import edu.ie3.simona.api.simulation.ontology.ControlResponseMessageFromExt; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; -import java.util.concurrent.LinkedBlockingQueue; import org.apache.pekko.actor.typed.ActorRef; -public class ExtEvDataConnection implements ExtInputDataConnection { - /** Data message queue containing messages from SIMONA */ - public final LinkedBlockingQueue receiveTriggerQueue = - new LinkedBlockingQueue<>(); +public class ExtEvDataConnection extends BiDirectional { + + public ExtEvDataConnection() { + super(); + } /** Actor reference to service that handles ev data within SIMONA */ private ActorRef dataService; @@ -30,14 +29,6 @@ public class ExtEvDataConnection implements ExtInputDataConnection extSimAdapter; - @Override - public void setActorRefs( - ActorRef dataService, - ActorRef extSimAdapter) { - this.dataService = dataService; - this.extSimAdapter = extSimAdapter; - } - /** * Requests currently available evcs charging stations lots from SIMONA. This method blocks until * having received a response from SIMONA. @@ -94,57 +85,4 @@ public List requestDepartingEvs(Map> departures) public void provideArrivingEvs(Map> arrivals, Optional maybeNextTick) { sendExtMsg(new ProvideArrivingEvs(arrivals, maybeNextTick)); } - - /** - * Send information from the external ev simulation to SIMONA's ev 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 ev data service - */ - public void sendExtMsg(EvDataMessageFromExt msg) { - dataService.tell(msg); - // we need to schedule data receiver activation with scheduler - extSimAdapter.tell(new ScheduleDataServiceMessage(dataService)); - } - - /** - * Queues message from SIMONA that should be handled by the external ev simulation. - * - * @param extEvResponse the message to be handled - * @throws InterruptedException if the thread running this has been interrupted during waiting for - * the message to be queued - */ - public void queueExtResponseMsg(EvDataResponseMessageToExt extEvResponse) - throws InterruptedException { - receiveTriggerQueue.put(extEvResponse); - } - - /** - * Waits until a message of given type is added to the queue. If the message has a different type, - * a RuntimeException is thrown. This method blocks until having received a response from SIMONA. - * - * @param expectedMessageClass the expected class of the message to be received - * @return a message of the expected type once it has been received - * @param the type of the expected message - * @throws InterruptedException if the thread running this has been interrupted during the - * blocking operation - */ - @SuppressWarnings("unchecked") - private T receiveWithType(Class expectedMessageClass) - throws InterruptedException { - - // blocks until actor puts something here - EvDataResponseMessageToExt evMessage = receiveTriggerQueue.take(); - - if (evMessage.getClass().equals(expectedMessageClass)) { - return (T) evMessage; - } else - throw new RuntimeException( - "Received unexpected message '" - + evMessage - + "', expected type '" - + expectedMessageClass - + "'"); - } } 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 46a7f772..b72c375f 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 @@ -27,13 +27,7 @@ import java.util.UUID; /** Enables data connection of primary data between SIMONA and SimonaAPI */ -public class ExtPrimaryDataConnection 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; +public class ExtPrimaryDataConnection extends ExtInputDataConnection { private final Map> valueClasses; @@ -46,14 +40,6 @@ public List getPrimaryDataAssets() { return valueClasses.keySet().stream().toList(); } - @Override - public void setActorRefs( - ActorRef dataService, - ActorRef extSimAdapter) { - this.dataService = dataService; - this.extSimAdapter = extSimAdapter; - } - /** * @param uuid of the model * @return an option for the value class associated with the model. @@ -76,10 +62,4 @@ public void sendPrimaryData(long tick, Map data, Optional may public void provideData(long tick, Map primaryData, Optional maybeNextTick) { sendExtMsg(new ProvidePrimaryData(tick, primaryData, maybeNextTick)); } - - public void sendExtMsg(PrimaryDataMessageFromExt msg) { - dataService.tell(msg); - // we need to schedule data receiver activation with scheduler - extSimAdapter.tell(new ScheduleDataServiceMessage(dataService)); - } } 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 739f0925..289e8297 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 @@ -7,16 +7,11 @@ package edu.ie3.simona.api.data.results; import edu.ie3.datamodel.models.result.ResultEntity; -import edu.ie3.simona.api.data.ExtOutputDataConnection; -import edu.ie3.simona.api.data.WithDataResponseToExt; -import edu.ie3.simona.api.data.ontology.DataMessageFromExt; -import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; +import edu.ie3.simona.api.data.BiDirectional; import edu.ie3.simona.api.data.results.ontology.ProvideResultEntities; import edu.ie3.simona.api.data.results.ontology.RequestResultEntities; import edu.ie3.simona.api.data.results.ontology.ResultDataMessageFromExt; import edu.ie3.simona.api.data.results.ontology.ResultDataResponseMessageToExt; -import edu.ie3.simona.api.simulation.ontology.ControlResponseMessageFromExt; -import org.apache.pekko.actor.typed.ActorRef; import java.util.List; import java.util.Map; @@ -25,14 +20,7 @@ import java.util.stream.Stream; /** Enables data connection of results between SIMONA and SimonaAPI */ -public class ExtResultDataConnection extends WithDataResponseToExt - implements ExtOutputDataConnection { - - /** Actor reference to service that handles result data within SIMONA */ - private ActorRef extResultDataService; - - /** Actor reference to adapter that handles scheduler control flow in SIMONA */ - private ActorRef extSimAdapter; +public class ExtResultDataConnection extends BiDirectional { /** Map uuid to external id of grid related entities */ private final List gridResults; @@ -52,19 +40,6 @@ public ExtResultDataConnection( this.flexResults = flexResults; } - /** - * Sets the actor refs for data and control flow - * - * @param extResultDataService actor ref to the adapter of the data service for data messages - * @param extSimAdapter actor ref to the extSimAdapter - */ - public void setActorRefs( - ActorRef extResultDataService, - ActorRef extSimAdapter) { - this.extResultDataService = extResultDataService; - this.extSimAdapter = extSimAdapter; - } - public List getGridResultDataAssets() { return gridResults; } @@ -126,17 +101,4 @@ public Map requestParticipantResults(long tick) protected Map createResultMap(List results) { return results.stream().collect(Collectors.toMap(ResultEntity::getInputModel, i -> i)); } - - /** - * Send information from the external simulation to SIMONA's external data service. Furthermore, - * ExtSimAdapter within SIMONA is instructed to activate the external data service with the - * current tick. - * - * @param msg the data/information that is sent to SIMONA's result data service - */ - public void sendExtMsg(ResultDataMessageFromExt msg) { - extResultDataService.tell(msg); - // we need to schedule data receiver activation with scheduler - extSimAdapter.tell(new ScheduleDataServiceMessage(extResultDataService)); - } } diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java b/src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java new file mode 100644 index 00000000..54bfccb2 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java @@ -0,0 +1,44 @@ +package edu.ie3.simona.api.data.results; + +import edu.ie3.simona.api.data.ExtOutputDataConnection; +import edu.ie3.simona.api.data.results.ontology.ResultDataResponseMessageToExt; + +import java.util.concurrent.LinkedBlockingQueue; + +/** + * External result listener. This listener is similar to the {@link ExtResultDataConnection}, but is not able to request + * results from SIMONA. + */ +public class ExtResultListener implements ExtOutputDataConnection { + + /** Data message queue containing messages from SIMONA */ + public final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); + + public ExtResultListener() {} + + + public final void queueExtResponseMsg(ResultDataResponseMessageToExt msg) throws InterruptedException { + receiveTriggerQueue.put(msg); + } + + public final ResultDataResponseMessageToExt receiveAny() throws InterruptedException { + return receiveTriggerQueue.take(); + } + + @SuppressWarnings("unchecked") + public final T receiveWithType(Class expectedMessageClass) + throws InterruptedException { + // blocks until actor puts something here + ResultDataResponseMessageToExt msg = receiveTriggerQueue.take(); + + if (msg.getClass().equals(expectedMessageClass)) { + return (T) msg; + } else + throw new RuntimeException( + "Received unexpected message '" + + msg + + "', expected type '" + + expectedMessageClass + + "'"); + } +} 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 d4ef41c6..67a8af69 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -12,17 +12,16 @@ import edu.ie3.simona.api.data.ExtDataContainerQueue; import edu.ie3.simona.api.data.datacontainer.ExtInputDataContainer; import edu.ie3.simona.api.data.datacontainer.ExtResultContainer; +import edu.ie3.simona.api.data.em.EmMode; import edu.ie3.simona.api.data.em.ExtEmDataConnection; +import edu.ie3.simona.api.data.em.ontology.*; import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; import edu.ie3.simona.api.data.results.ExtResultDataConnection; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; import edu.ie3.simona.api.simulation.mapping.DataType; import org.slf4j.Logger; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import static java.util.Collections.emptyList; @@ -80,15 +79,16 @@ public static ExtPrimaryDataConnection buildPrimaryConnection( * @param log logger * @return an ext em data connection */ - public static ExtEmDataConnection buildEmConnection(List controlled, boolean useCommunication, Logger log) { - if (!useCommunication) { - if (controlled.isEmpty()) { - log.warn("Em data connection with 0 controlled entities created. This might lead to errors!"); - } else { - log.info("Em data connection with {} controlled entities created.", controlled.size()); - } + public static ExtEmDataConnection buildEmConnection(List controlled, EmMode mode, Logger log) { + if (controlled.isEmpty()) { + log.warn("Em data connection with 0 controlled entities created. This might lead to errors!"); + } else { + log.info("Em data connection with {} controlled entities created.", controlled.size()); } - return new ExtEmDataConnection(controlled, useCommunication); + + log.info("Em mode: {}", mode); + + return new ExtEmDataConnection(controlled, mode); } /** @@ -221,6 +221,81 @@ protected void sendEmSetPointsToSimona( log.debug("Provided em set points to SIMONA!"); } + + protected void useFlexCommunication(ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { + // handle flex requests + boolean notFinished = true; + + while (notFinished) { + + long extTick = queueToSimona.takeData(ExtInputDataContainer::getTick); + + log.warn("Current simulator tick: {}, SIMONA tick: {}", extTick, tick); + + if (tick == extTick) { + ExtInputDataContainer container = queueToSimona.takeAll(); + + log.warn("Flex requests: {}", container.flexRequestsString()); + log.warn("Flex options: {}", container.flexOptionsString()); + log.warn("Set points: {}", container.setPointsString()); + + // send received data to SIMONA + var requests = container.extractFlexRequests(); + var options = container.extractFlexOptions(); + var setPoints = container.extractSetPoints(); + + extEmDataConnection.sendFlexRequests(tick, requests, maybeNextTick, log); + + extEmDataConnection.sendFlexOptions(tick, options, maybeNextTick, log); + + extEmDataConnection.sendSetPoints(tick, setPoints, maybeNextTick, log); + + log.warn("Unhandled flex requests: {}", container.flexRequestsString()); + log.warn("Unhandled flex options: {}", container.flexOptionsString()); + log.warn("Unhandled set points: {}", container.setPointsString()); + + if (requests.isEmpty() && options.isEmpty() && setPoints.isEmpty()) { + log.info("Requesting a service completion for tick: {}.", tick); + extEmDataConnection.requestCompletion(tick); + } + + } else { + notFinished = false; + + log.info("External simulator finished tick {}. Request completion.", tick); + extEmDataConnection.requestCompletion(tick); + } + + EmDataResponseMessageToExt received = extEmDataConnection.receiveAny(); + + Map results = new HashMap<>(); + + if (received instanceof EmCompletion) { + notFinished = false; + log.info("Finished for tick: {}", tick); + + } else if (received instanceof FlexRequestResponse flexRequestResponse) { + results.putAll(flexRequestResponse.flexRequests()); + + } else if (received instanceof FlexOptionsResponse flexOptionsResponse) { + results.putAll(flexOptionsResponse.flexOptions()); + + } else if (received instanceof EmSetPointDataResponse setPointDataResponse) { + results.putAll(setPointDataResponse.emData()); + + } else { + log.warn("Received unsupported data response: {}", received); + } + + log.warn("Results to ext: {}", results); + + ExtResultContainer resultContainer = new ExtResultContainer(tick, results, maybeNextTick); + + queueToExt.queueData(resultContainer); + } + } + + // result data methods /** 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 04d17497..f76e51f0 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 @@ -11,6 +11,8 @@ public enum DataType { EXT_PRIMARY_INPUT("primary_input"), EXT_EM_INPUT("em_input"), + EXT_EM_COMMUNICATION("em_communication"), + EXT_EM_OPTIMIZER("em_optimizer"), EXT_GRID_RESULT("grid_result"), EXT_PARTICIPANT_RESULT("participant_result"), EXT_FLEX_OPTIONS_RESULT("flex_options_result"); 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 44a004ea..9533178b 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 @@ -38,7 +38,7 @@ public Set getDataTypes() { * @param dataType for which entries should be returned * @return a list containing all entries or an empty list */ - public List getExtEntityEntries(DataType dataType) { + public List getEntries(DataType dataType) { return extEntities.getOrDefault(dataType, Collections.emptyList()); } From 89d9d2910d3dde2dfc397c96e4e45ce1b485ddc7 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 3 Apr 2025 16:40:57 +0200 Subject: [PATCH 28/80] Saving changes. --- .../api/data/ExtDataContainerQueue.java | 2 +- .../ExtDataContainer.java | 2 +- .../ExtInputDataContainer.java | 2 +- .../ExtResultContainer.java | 2 +- .../edu/ie3/simona/api/data/em/EmMode.java | 2 +- .../mapping/DataType.java | 2 +- .../mapping/ExtEntityEntry.java | 2 +- .../mapping/ExtEntityFactory.java | 2 +- .../mapping/ExtEntityMapping.java | 2 +- .../mapping/ExtEntityMappingSource.java | 2 +- .../api/simulation/ExtCoSimulation.java | 27 +++---------------- .../results/ExtResultContainerTest.groovy | 2 +- .../api/simulation/ExtCoSimulationTest.groovy | 6 ++--- .../mapping/ExtEntityMappingSourceTest.groovy | 3 +++ .../mapping/ExtEntityMappingTest.groovy | 3 +++ 15 files changed, 23 insertions(+), 38 deletions(-) rename src/main/java/edu/ie3/simona/api/data/{datacontainer => container}/ExtDataContainer.java (92%) rename src/main/java/edu/ie3/simona/api/data/{datacontainer => container}/ExtInputDataContainer.java (98%) rename src/main/java/edu/ie3/simona/api/data/{datacontainer => container}/ExtResultContainer.java (99%) rename src/main/java/edu/ie3/simona/api/{simulation => data}/mapping/DataType.java (95%) rename src/main/java/edu/ie3/simona/api/{simulation => data}/mapping/ExtEntityEntry.java (95%) rename src/main/java/edu/ie3/simona/api/{simulation => data}/mapping/ExtEntityFactory.java (97%) rename src/main/java/edu/ie3/simona/api/{simulation => data}/mapping/ExtEntityMapping.java (98%) rename src/main/java/edu/ie3/simona/api/{simulation => data}/mapping/ExtEntityMappingSource.java (98%) diff --git a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java index d41fe293..a68c5d2f 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java @@ -6,7 +6,7 @@ package edu.ie3.simona.api.data; -import edu.ie3.simona.api.data.datacontainer.ExtDataContainer; +import edu.ie3.simona.api.data.container.ExtDataContainer; import java.util.concurrent.LinkedBlockingDeque; import java.util.function.Function; diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java similarity index 92% rename from src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.java rename to src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java index c5d9e33b..792dc0fe 100644 --- a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.datacontainer; +package edu.ie3.simona.api.data.container; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java similarity index 98% rename from src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java rename to src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java index f27cea12..fb64ce6f 100644 --- a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtInputDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.datacontainer; +package edu.ie3.simona.api.data.container; import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; diff --git a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java similarity index 99% rename from src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java rename to src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java index 97093925..35b54339 100644 --- a/src/main/java/edu/ie3/simona/api/data/datacontainer/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.datacontainer; +package edu.ie3.simona.api.data.container; import static edu.ie3.util.quantities.PowerSystemUnits.PU; diff --git a/src/main/java/edu/ie3/simona/api/data/em/EmMode.java b/src/main/java/edu/ie3/simona/api/data/em/EmMode.java index e4606408..5650fc1a 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/EmMode.java +++ b/src/main/java/edu/ie3/simona/api/data/em/EmMode.java @@ -1,6 +1,6 @@ package edu.ie3.simona.api.data.em; -import edu.ie3.simona.api.simulation.mapping.DataType; +import edu.ie3.simona.api.data.mapping.DataType; public enum EmMode { SET_POINT("setPoint"), diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/DataType.java b/src/main/java/edu/ie3/simona/api/data/mapping/DataType.java similarity index 95% rename from src/main/java/edu/ie3/simona/api/simulation/mapping/DataType.java rename to src/main/java/edu/ie3/simona/api/data/mapping/DataType.java index f76e51f0..740746b6 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/DataType.java +++ b/src/main/java/edu/ie3/simona/api/data/mapping/DataType.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.simulation.mapping; +package edu.ie3.simona.api.data.mapping; import edu.ie3.datamodel.exceptions.ParsingException; diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityEntry.java similarity index 95% rename from src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java rename to src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityEntry.java index 1df4987b..b986dac4 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java +++ b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityEntry.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.simulation.mapping; +package edu.ie3.simona.api.data.mapping; import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; import edu.ie3.datamodel.models.input.InputEntity; diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityFactory.java similarity index 97% rename from src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java rename to src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityFactory.java index 49718d13..cdbc2eef 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java +++ b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityFactory.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.simulation.mapping; +package edu.ie3.simona.api.data.mapping; import edu.ie3.datamodel.exceptions.FactoryException; import edu.ie3.datamodel.exceptions.ParsingException; diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java similarity index 98% rename from src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java rename to src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java index 9533178b..20e8e6b9 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.simulation.mapping; +package edu.ie3.simona.api.data.mapping; import java.util.*; import java.util.stream.Collectors; diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMappingSource.java similarity index 98% rename from src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java rename to src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMappingSource.java index 1d24d7ff..34c37d31 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java +++ b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMappingSource.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.simulation.mapping; +package edu.ie3.simona.api.data.mapping; import edu.ie3.datamodel.exceptions.SourceException; import edu.ie3.datamodel.io.factory.EntityData; 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 67a8af69..b0484d57 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -10,15 +10,15 @@ import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.ExtDataContainerQueue; -import edu.ie3.simona.api.data.datacontainer.ExtInputDataContainer; -import edu.ie3.simona.api.data.datacontainer.ExtResultContainer; +import edu.ie3.simona.api.data.container.ExtInputDataContainer; +import edu.ie3.simona.api.data.container.ExtResultContainer; import edu.ie3.simona.api.data.em.EmMode; import edu.ie3.simona.api.data.em.ExtEmDataConnection; import edu.ie3.simona.api.data.em.ontology.*; import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; 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.data.mapping.DataType; import org.slf4j.Logger; import java.util.*; @@ -362,25 +362,4 @@ private void sendSingleResultType( queueToExt.queueData(new ExtResultContainer(tick, resultsToBeSend, nextTick)); log.info("Sent {} results for tick {} to {}", type, tick, extSimulatorName); } - - // helper methods - - private String resultMapToString(Map results) { - StringBuilder resultString = new StringBuilder(); - - for (Map.Entry entry : results.entrySet()) { - String key = entry.getKey(); - ResultEntity value = entry.getValue(); - - resultString - .append("id = ") - .append(key) - .append(", time = ") - .append(value.getTime()) - .append(", result = ") - .append(value.getClass().getSimpleName()) - .append("\n"); - } - return resultString.toString(); - } } diff --git a/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy index d3c6d764..cd6e230b 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy @@ -2,7 +2,7 @@ package edu.ie3.simona.api.data.results import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.result.NodeResult -import edu.ie3.simona.api.data.datacontainer.ExtResultContainer +import edu.ie3.simona.api.data.container.ExtResultContainer import edu.ie3.simona.api.test.common.DataServiceTestData import edu.ie3.util.quantities.PowerSystemUnits import spock.lang.Shared 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 f12eeaab..07c25158 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy @@ -1,9 +1,9 @@ package edu.ie3.simona.api.simulation import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme -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 edu.ie3.simona.api.data.mapping.DataType +import edu.ie3.simona.api.data.mapping.ExtEntityEntry +import edu.ie3.simona.api.data.mapping.ExtEntityMapping import org.slf4j.Logger import org.slf4j.LoggerFactory import spock.lang.Shared diff --git a/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy b/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy index 2589e219..85b5591d 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy @@ -1,6 +1,9 @@ package edu.ie3.simona.api.simulation.mapping import edu.ie3.datamodel.models.input.NodeInput +import edu.ie3.simona.api.data.mapping.DataType +import edu.ie3.simona.api.data.mapping.ExtEntityEntry +import edu.ie3.simona.api.data.mapping.ExtEntityMappingSource import spock.lang.Specification import java.nio.file.Path 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 87818c68..73e87657 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 @@ -1,6 +1,9 @@ package edu.ie3.simona.api.simulation.mapping import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme +import edu.ie3.simona.api.data.mapping.DataType +import edu.ie3.simona.api.data.mapping.ExtEntityEntry +import edu.ie3.simona.api.data.mapping.ExtEntityMapping import spock.lang.Shared import spock.lang.Specification From 4477ff9b3e75ac4e86456f47d248eb66efdf3b0f Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 10 Apr 2025 11:38:53 +0200 Subject: [PATCH 29/80] Saving changes. --- .../data/container/ExtInputDataContainer.java | 10 +++---- .../api/data/em/ExtEmDataConnection.java | 8 +++--- ...questValue.java => FlexOptionRequest.java} | 5 ++-- .../simona/api/data/em/model/FlexOptions.java | 1 + .../api/data/em/model/FlexRequestResult.java | 28 ++++++++++++++----- .../em/ontology/ProvideFlexRequestData.java | 5 +--- .../api/data/mapping/ExtEntityMapping.java | 4 +++ .../primarydata/ExtPrimaryDataConnection.java | 9 ------ 8 files changed, 38 insertions(+), 32 deletions(-) rename src/main/java/edu/ie3/simona/api/data/em/model/{FlexOptionRequestValue.java => FlexOptionRequest.java} (59%) diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java index fb64ce6f..6d134c53 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java @@ -8,7 +8,7 @@ import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; -import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; +import edu.ie3.simona.api.data.em.model.FlexOptionRequest; import edu.ie3.simona.api.data.em.model.FlexOptions; import java.util.*; @@ -26,7 +26,7 @@ public final class ExtInputDataContainer implements ExtDataContainer { private final Map primaryData = new HashMap<>(); // em maps - private final Map flexRequests = new HashMap<>(); + private final Map flexRequests = new HashMap<>(); private final Map> flexOptions = new HashMap<>(); private final Map setPoints = new HashMap<>(); @@ -67,8 +67,8 @@ public void addPrimaryValue(UUID id, Value value) { primaryData.put(id, value); } - public void addRequest(UUID requester, List emEntities) { - flexRequests.put(requester, new FlexOptionRequestValue(requester, emEntities)); + public void addRequest(UUID receiver, Optional sender) { + flexRequests.put(receiver, new FlexOptionRequest(receiver, sender)); } public void addFlexOptions(UUID id, List flexOption) { @@ -89,7 +89,7 @@ public Map extractPrimaryData() { } // extract and delete data - public Map extractFlexRequests() { + public Map extractFlexRequests() { return copyAndClear(flexRequests); } 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 b6dfbba4..966f247c 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 @@ -9,7 +9,7 @@ import edu.ie3.datamodel.models.result.system.FlexOptionsResult; import edu.ie3.datamodel.models.value.PValue; import edu.ie3.simona.api.data.BiDirectional; -import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; +import edu.ie3.simona.api.data.em.model.FlexOptionRequest; import edu.ie3.simona.api.data.em.model.FlexOptions; import edu.ie3.simona.api.data.em.ontology.*; import org.slf4j.Logger; @@ -42,14 +42,14 @@ public boolean useCommunication() { } - public void sendFlexRequests(long tick, Map data, Optional maybeNextTick, Logger log) { + public void sendFlexRequests(long tick, Map data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No em flex requests found! Sending no em data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with em flex requests."); - Map> emFlexRequests = new HashMap<>(); - data.forEach((receiver, requests) -> emFlexRequests.put(receiver, requests.emEntities())); + Map> emFlexRequests = new HashMap<>(); + data.forEach((receiver, value) -> emFlexRequests.put(receiver, value.sender())); sendExtMsg(new ProvideFlexRequestData(tick, emFlexRequests, maybeNextTick)); } diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java similarity index 59% rename from src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java rename to src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java index c45302d1..de10287d 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequestValue.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java @@ -6,8 +6,7 @@ package edu.ie3.simona.api.data.em.model; -import edu.ie3.datamodel.models.value.Value; -import java.util.List; +import java.util.Optional; import java.util.UUID; -public record FlexOptionRequestValue(UUID requester, List emEntities) implements Value {} +public record FlexOptionRequest(UUID receiver, Optional sender) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java index 89fd55f4..e6aa6728 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java @@ -12,6 +12,7 @@ import java.util.UUID; public record FlexOptions( + UUID receiver, UUID sender, ComparableQuantity pMin, ComparableQuantity pRef, diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java index 652b057b..f1f47b3f 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java @@ -3,17 +3,31 @@ import edu.ie3.datamodel.models.result.ResultEntity; import java.time.ZonedDateTime; +import java.util.List; import java.util.UUID; public class FlexRequestResult extends ResultEntity { - /** - * Standard constructor which includes auto generation of the resulting output models uuid. - * - * @param time date and time when the result is produced - * @param inputModel uuid of the input model that produces the result - */ - public FlexRequestResult(ZonedDateTime time, UUID inputModel) { + private final List receivers; + + public FlexRequestResult(ZonedDateTime time, UUID inputModel, List receivers) { super(time, inputModel); + this.receivers = receivers; + } + + public List getReceivers() { + return receivers; + } + + @Override + public String toString() { + return "FlexRequestResult{" + + "time=" + + getTime() + + ", inputModel=" + + getInputModel() + + ", receivers=" + + receivers + + '}'; } } diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java index 91f86b83..503d4f02 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java @@ -1,13 +1,10 @@ package edu.ie3.simona.api.data.em.ontology; -import edu.ie3.simona.api.data.em.model.FlexOptionRequestValue; - -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; /** Message that provides em data (flex requests) from an external simulation. */ public record ProvideFlexRequestData( - long tick, Map> flexRequests, Optional maybeNextTick) + long tick, Map> flexRequests, Optional maybeNextTick) implements EmDataMessageFromExt {} \ No newline at end of file diff --git a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java index 20e8e6b9..720a1674 100644 --- a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java @@ -57,6 +57,10 @@ public Map getFullMapping() { return extEntities.values().stream().flatMap(Collection::stream).collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); } + public Map getFullMappingReverse() { + return extEntities.values().stream().flatMap(Collection::stream).collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); + } + /** * Mapping SIMONA uuid to external id * 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 b72c375f..df95f0e6 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 @@ -8,17 +8,8 @@ import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.ExtInputDataConnection; -import edu.ie3.simona.api.data.ontology.DataMessageFromExt; -import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; import edu.ie3.simona.api.data.primarydata.ontology.PrimaryDataMessageFromExt; import edu.ie3.simona.api.data.primarydata.ontology.ProvidePrimaryData; -import edu.ie3.simona.api.simulation.ontology.ControlResponseMessageFromExt; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.stream.Collectors; -import org.apache.pekko.actor.typed.ActorRef; import org.slf4j.Logger; import java.util.List; From 495e97b0f4cc3964dad6f85e7b98574df675c37c Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 10 Apr 2025 19:05:30 +0200 Subject: [PATCH 30/80] Saving changes. --- .../api/data/em/ExtEmDataConnection.java | 6 +-- .../em/model/ExtendedFlexOptionsResult.java | 54 +++++++++++++++++++ .../api/data/em/model/FlexOptionValue.java | 13 ----- .../api/data/em/model/FlexRequestResult.java | 6 ++- .../data/em/ontology/FlexOptionsResponse.java | 5 +- .../api/simulation/ExtCoSimulation.java | 2 +- 6 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java 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 966f247c..f3da9c08 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 @@ -6,9 +6,9 @@ package edu.ie3.simona.api.data.em; -import edu.ie3.datamodel.models.result.system.FlexOptionsResult; import edu.ie3.datamodel.models.value.PValue; import edu.ie3.simona.api.data.BiDirectional; +import edu.ie3.simona.api.data.em.model.ExtendedFlexOptionsResult; import edu.ie3.simona.api.data.em.model.FlexOptionRequest; import edu.ie3.simona.api.data.em.model.FlexOptions; import edu.ie3.simona.api.data.em.ontology.*; @@ -97,10 +97,10 @@ public void sendSetPoints(long tick, Map data, Optional mayb * @return an {@link FlexOptionsResponse} message * @throws InterruptedException - on interruptions */ - public Map requestEmFlexResults(long tick, Map> emEntities) + public Map requestEmFlexResults(long tick, Map> emEntities) throws InterruptedException { sendExtMsg(new RequestEmFlexResults(tick, emEntities)); - return receiveWithType(FlexOptionsResponse.class).flexOptions(); + return receiveWithType(FlexOptionsResponse.class).receiverToFlexOptions(); } public void requestCompletion(long tick) { diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java new file mode 100644 index 00000000..73da0b6f --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java @@ -0,0 +1,54 @@ +package edu.ie3.simona.api.data.em.model; + +import edu.ie3.datamodel.models.result.system.FlexOptionsResult; +import tech.units.indriya.ComparableQuantity; + +import javax.measure.quantity.Power; +import java.time.ZonedDateTime; +import java.util.UUID; + +public class ExtendedFlexOptionsResult extends FlexOptionsResult { + + private final UUID receiver; + + /** + * Standard constructor with automatic uuid generation. + * + * @param time date and time when the result is produced + * @param sender uuid of the input model that produces the result + * @param pRef active power that was suggested for regular usage by the system participant + * @param receiver uuid of the receiver that will receive this result + * @param pMin active minimal power that was determined by the system participant + * @param pMax active maximum power that was determined by the system participant + */ + public ExtendedFlexOptionsResult(ZonedDateTime time, UUID sender, UUID receiver, ComparableQuantity pRef, ComparableQuantity pMin, ComparableQuantity pMax) { + super(time, sender, pRef, pMin, pMax); + this.receiver = receiver; + } + + public UUID getSender() { + return getInputModel(); + } + + public UUID getReceiver() { + return receiver; + } + + @Override + public String toString() { + return "ExtendedFlexOptionsResult{" + + "time=" + + getTime() + + ", sender=" + + getSender() + + ", receiver=" + + receiver + + ", pRef=" + + getpRef() + + ", pMin=" + + getpMin() + + ", pMax=" + + getpMax() + + '}'; + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java deleted file mode 100644 index e715a781..00000000 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionValue.java +++ /dev/null @@ -1,13 +0,0 @@ -/* - * © 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.em.model; - -import edu.ie3.datamodel.models.value.Value; -import java.util.Map; -import java.util.UUID; - -public record FlexOptionValue(Map flexOptions) implements Value {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java index f1f47b3f..80950c78 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java @@ -3,6 +3,8 @@ import edu.ie3.datamodel.models.result.ResultEntity; import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.UUID; @@ -10,9 +12,9 @@ public class FlexRequestResult extends ResultEntity { private final List receivers; - public FlexRequestResult(ZonedDateTime time, UUID inputModel, List receivers) { + public FlexRequestResult(ZonedDateTime time, UUID inputModel, Collection receivers) { super(time, inputModel); - this.receivers = receivers; + this.receivers = new ArrayList<>(receivers); } public List getReceivers() { diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java index 2b3220cb..14161ce2 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java @@ -6,10 +6,11 @@ package edu.ie3.simona.api.data.em.ontology; -import edu.ie3.datamodel.models.result.system.FlexOptionsResult; +import edu.ie3.simona.api.data.em.model.ExtendedFlexOptionsResult; + import java.util.Map; import java.util.UUID; /** Message that provides em data (flexibility options) to an external simulation. */ -public record FlexOptionsResponse(Map flexOptions) +public record FlexOptionsResponse(Map receiverToFlexOptions) implements EmDataResponseMessageToExt {} 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 b0484d57..b66d09c2 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -278,7 +278,7 @@ protected void useFlexCommunication(ExtEmDataConnection extEmDataConnection, lon results.putAll(flexRequestResponse.flexRequests()); } else if (received instanceof FlexOptionsResponse flexOptionsResponse) { - results.putAll(flexOptionsResponse.flexOptions()); + results.putAll(flexOptionsResponse.receiverToFlexOptions()); } else if (received instanceof EmSetPointDataResponse setPointDataResponse) { results.putAll(setPointDataResponse.emData()); From d8277074988fb983699cc4f64e6bbacbe329b3b6 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 11 Apr 2025 17:45:02 +0200 Subject: [PATCH 31/80] Refactoring em messages. --- .../api/data/em/model/EmSetPointResult.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java index 7dfd0edb..6cfcfe41 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java @@ -9,29 +9,36 @@ import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.PValue; import java.time.ZonedDateTime; -import java.util.Optional; +import java.util.Map; import java.util.UUID; /** Em set point result. */ public class EmSetPointResult extends ResultEntity { - private final PValue setPoint; + private final Map receiverToSetPoints; - public EmSetPointResult(ZonedDateTime time, UUID inputModel, PValue setPoint) { - super(time, inputModel); - this.setPoint = setPoint; + public EmSetPointResult(ZonedDateTime time, UUID sender, Map receiverToSetPoints) { + super(time, sender); + this.receiverToSetPoints = receiverToSetPoints; } - public Optional getSetPoint() { - return Optional.ofNullable(setPoint); + public UUID getSender() { + return getInputModel(); + } + + public Map getReceiverToSetPoint() { + return receiverToSetPoints; } @Override public String toString() { - return "EmSetPointResult{" + - "time=" + getTime() + - ", inputModel=" + getInputModel() + - ", setPoint=" + getSetPoint() + - '}'; + return "EmSetPointResult{" + + "time=" + + getTime() + + ", sender=" + + getInputModel() + + ", receiverToSetPoints=" + + receiverToSetPoints + + '}'; } } From 046bd79fa27166d81929ca2f3409d404b3e2bb61 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 15 Apr 2025 09:09:39 +0200 Subject: [PATCH 32/80] Saving changes. --- .../api/data/primarydata/ExtPrimaryDataConnection.java | 6 +++--- .../java/edu/ie3/simona/api/simulation/ExtCoSimulation.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) 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 df95f0e6..7dc3bc02 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,9 +20,9 @@ /** Enables data connection of primary data between SIMONA and SimonaAPI */ public class ExtPrimaryDataConnection extends ExtInputDataConnection { - private final Map> valueClasses; + private final Map> valueClasses; - public ExtPrimaryDataConnection(Map> valueClasses) { + public ExtPrimaryDataConnection(Map> valueClasses) { this.valueClasses = valueClasses; } @@ -35,7 +35,7 @@ public List getPrimaryDataAssets() { * @param uuid of the model * @return an option for the value class associated with the model. */ - public Optional> getValueClass(UUID uuid) { + public Optional> getValueClass(UUID uuid) { return Optional.ofNullable(valueClasses.get(uuid)); } 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 b66d09c2..fa1f8681 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -60,7 +60,7 @@ protected ExtCoSimulation(String simulationName, String extSimulatorName) { * @return an ext primary data connection */ public static ExtPrimaryDataConnection buildPrimaryConnection( - Map> assetToValueClasses, Logger log) { + Map> assetToValueClasses, Logger log) { if (assetToValueClasses.isEmpty()) { log.warn("No primary data connection was created."); From 0c053450d73329daa66e8f65c904e013829a223e Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 16 Apr 2025 13:28:51 +0200 Subject: [PATCH 33/80] Saving changes. --- .../ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java index 73da0b6f..ce3ea179 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java @@ -16,8 +16,8 @@ public class ExtendedFlexOptionsResult extends FlexOptionsResult { * * @param time date and time when the result is produced * @param sender uuid of the input model that produces the result - * @param pRef active power that was suggested for regular usage by the system participant * @param receiver uuid of the receiver that will receive this result + * @param pRef active power that was suggested for regular usage by the system participant * @param pMin active minimal power that was determined by the system participant * @param pMax active maximum power that was determined by the system participant */ From 78049cb4d0c3b5787fdda1799e83edd081dd164e Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 24 Apr 2025 15:35:15 +0200 Subject: [PATCH 34/80] Refactoring handling of input and result data. --- .../ie3/simona/api/data/BiDirectional.java | 17 +-- .../api/data/ExtInputDataConnection.java | 64 ++++---- .../api/data/ExtOutputDataConnection.java | 2 +- .../data/container/ExtResultContainer.java | 8 +- .../edu/ie3/simona/api/data/em/EmMode.java | 38 +++-- .../api/data/em/ExtEmDataConnection.java | 17 ++- .../api/data/em/model/EmSetPointResult.java | 14 +- .../em/model/ExtendedFlexOptionsResult.java | 139 ++++++++++++------ .../simona/api/data/em/model/FlexOptions.java | 7 +- .../api/data/em/model/FlexRequestResult.java | 45 +++--- .../api/data/em/ontology/EmCompletion.java | 6 + .../data/em/ontology/FlexOptionsResponse.java | 1 - .../data/em/ontology/FlexRequestResponse.java | 1 - .../em/ontology/ProvideFlexRequestData.java | 10 +- .../data/em/ontology/RequestEmCompletion.java | 8 +- .../api/data/ev/ExtEvDataConnection.java | 3 +- .../api/data/mapping/ExtEntityMapping.java | 16 +- .../primarydata/ExtPrimaryDataConnection.java | 6 +- .../data/results/ExtResultDataConnection.java | 11 +- .../api/data/results/ExtResultListener.java | 72 ++++----- .../model/DesaggFlexOptionsResult.java | 57 ------- .../api/simulation/ExtCoSimulation.java | 34 ++--- 22 files changed, 303 insertions(+), 273 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java diff --git a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java index 040d346a..208c318e 100644 --- a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java +++ b/src/main/java/edu/ie3/simona/api/data/BiDirectional.java @@ -8,7 +8,6 @@ import edu.ie3.simona.api.data.ontology.DataMessageFromExt; import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; - import java.util.concurrent.LinkedBlockingQueue; /** @@ -17,7 +16,8 @@ * @param type of message to SIMONA * @param type of response messages to ext */ -public abstract class BiDirectional +public abstract class BiDirectional< + M extends DataMessageFromExt, R extends DataResponseMessageToExt> extends ExtInputDataConnection implements ExtOutputDataConnection { /** Data message queue containing messages from SIMONA */ @@ -37,7 +37,7 @@ public final R receiveAny() throws InterruptedException { @SuppressWarnings("unchecked") public final T receiveWithType(Class expectedMessageClass) - throws InterruptedException { + throws InterruptedException { // blocks until actor puts something here R msg = receiveTriggerQueue.take(); @@ -45,11 +45,10 @@ public final T receiveWithType(Class expectedMessageClass) return (T) msg; } else throw new RuntimeException( - "Received unexpected message '" - + msg - + "', expected type '" - + expectedMessageClass - + "'"); + "Received unexpected message '" + + msg + + "', expected type '" + + expectedMessageClass + + "'"); } - } diff --git a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java index c2667fe1..1b073f76 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java @@ -12,39 +12,41 @@ import org.apache.pekko.actor.typed.ActorRef; /** - * Abstract base class for a connection between SIMONA and an external simulation with data flow from external - * to SIMONA. + * Abstract base class for a connection between SIMONA and an external simulation with data flow + * from external to SIMONA. */ -public abstract class ExtInputDataConnection implements ExtDataConnection { +public abstract class ExtInputDataConnection + implements ExtDataConnection { - /** Actor reference to service that handles data within SIMONA */ - private ActorRef dataService; + /** 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; + /** Actor reference to adapter that handles scheduler control flow in SIMONA */ + private ActorRef extSimAdapter; - /** - * Sets the actor refs for data and control flow - * - * @param extResultDataService actor ref to the adapter of the data service for data messages - * @param extSimAdapter actor ref to the extSimAdapter - */ - public final void setActorRefs( - ActorRef extResultDataService, - ActorRef extSimAdapter) { - this.dataService = extResultDataService; - this.extSimAdapter = extSimAdapter; - } - /** - * Send information from the external simulation to SIMONA's external data service. Furthermore, - * ExtSimAdapter within SIMONA is instructed to activate the external data service with the - * current tick. - * - * @param msg the data/information that is sent to SIMONA's result data service - */ - public final void sendExtMsg(M msg) { - dataService.tell(msg); - // we need to schedule data receiver activation with scheduler - extSimAdapter.tell(new ScheduleDataServiceMessage(dataService)); - } + /** + * Sets the actor refs for data and control flow + * + * @param extResultDataService actor ref to the adapter of the data service for data messages + * @param extSimAdapter actor ref to the extSimAdapter + */ + public final void setActorRefs( + ActorRef extResultDataService, + ActorRef extSimAdapter) { + this.dataService = extResultDataService; + this.extSimAdapter = extSimAdapter; + } + + /** + * Send information from the external simulation to SIMONA's external data service. Furthermore, + * ExtSimAdapter within SIMONA is instructed to activate the external data service with the + * current tick. + * + * @param msg the data/information that is sent to SIMONA's result data service + */ + public final void sendExtMsg(M msg) { + dataService.tell(msg); + // we need to schedule data receiver activation with scheduler + extSimAdapter.tell(new ScheduleDataServiceMessage(dataService)); + } } diff --git a/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java index 2cb242e8..cc90641a 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java @@ -11,6 +11,7 @@ /** * Interface for a connection between SIMONA and an external simulation with data flow from SIMONA * to external. + * * @param type of response messages to ext */ public interface ExtOutputDataConnection { @@ -18,7 +19,6 @@ public interface ExtOutputDataConnection { /** Queues message from SIMONA that should be handled by the external simulation. */ void queueExtResponseMsg(T msg) throws InterruptedException; - T receiveAny() throws InterruptedException; /** diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java index 35b54339..785dbf65 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java @@ -42,8 +42,7 @@ public class ExtResultContainer implements ExtDataContainer { * @param resultMap results from SIMONA with external id as key * @param nextTick tick the external simulation can expect the next results */ - public ExtResultContainer( - long tick, Map resultMap, Optional nextTick) { + public ExtResultContainer(long tick, Map resultMap, Optional nextTick) { this.tick = tick; this.resultMap = resultMap; this.maybeNextTick = nextTick; @@ -94,6 +93,7 @@ public ResultEntity getResult(UUID assetId) { * Returns the voltage deviation in pu for certain asset, if this asset provided a {@link * NodeResult} */ + @Deprecated public double getVoltageDeviation(UUID assetId) { if (resultMap.get(assetId) instanceof NodeResult nodeResult) { ComparableQuantity vMagDev = @@ -108,6 +108,7 @@ public double getVoltageDeviation(UUID assetId) { /** * Returns the voltage deviation for certain asset, if this asset provided a {@link NodeResult} */ + @Deprecated public double getVoltage(UUID assetId) { if (resultMap.get(assetId) instanceof NodeResult nodeResult) { return nodeResult.getvMag().getValue().doubleValue(); @@ -120,6 +121,7 @@ public double getVoltage(UUID assetId) { * Returns the active power in kW for certain asset, if this asset provided a {@link * SystemParticipantResult} */ + @Deprecated public double getActivePower(UUID assetId) { if (resultMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { return systemParticipantResult.getP().getValue().doubleValue(); @@ -133,6 +135,7 @@ public double getActivePower(UUID assetId) { * Returns the reactive power in kVAr for certain asset, if this asset provided a {@link * SystemParticipantResult} */ + @Deprecated public double getReactivePower(UUID assetId) { if (resultMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { return systemParticipantResult.getQ().getValue().doubleValue(); @@ -143,6 +146,7 @@ public double getReactivePower(UUID assetId) { } /** Returns the line loading for certain asset, if this asset provided a {@link LineResult} */ + @Deprecated public double getLineLoading(UUID assetId) { throw new IllegalArgumentException("LINE LOADING is not implemented yet!"); } diff --git a/src/main/java/edu/ie3/simona/api/data/em/EmMode.java b/src/main/java/edu/ie3/simona/api/data/em/EmMode.java index 5650fc1a..e0628e4c 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/EmMode.java +++ b/src/main/java/edu/ie3/simona/api/data/em/EmMode.java @@ -1,25 +1,31 @@ +/* + * © 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.em; import edu.ie3.simona.api.data.mapping.DataType; public enum EmMode { - SET_POINT("setPoint"), - EM_COMMUNICATION("emCommunication"), - EM_OPTIMIZATION("emOptimization"),; - + SET_POINT("setPoint"), + EM_COMMUNICATION("emCommunication"), + EM_OPTIMIZATION("emOptimization"), + ; - public final String mode; + public final String mode; - EmMode(String mode) { - this.mode = mode; - } + EmMode(String mode) { + this.mode = mode; + } - public static EmMode fromDataType(DataType dataType) { - return switch (dataType) { - case EXT_EM_INPUT -> EmMode.SET_POINT; - case EXT_EM_COMMUNICATION -> EmMode.EM_COMMUNICATION; - case EXT_EM_OPTIMIZER -> EmMode.EM_OPTIMIZATION; - default -> throw new IllegalStateException("Unexpected data type: " + dataType); - }; - } + public static EmMode fromDataType(DataType dataType) { + return switch (dataType) { + case EXT_EM_INPUT -> EmMode.SET_POINT; + case EXT_EM_COMMUNICATION -> EmMode.EM_COMMUNICATION; + case EXT_EM_OPTIMIZER -> EmMode.EM_OPTIMIZATION; + default -> throw new IllegalStateException("Unexpected data type: " + dataType); + }; + } } 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 f3da9c08..fe7297c1 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 @@ -12,9 +12,8 @@ import edu.ie3.simona.api.data.em.model.FlexOptionRequest; import edu.ie3.simona.api.data.em.model.FlexOptions; import edu.ie3.simona.api.data.em.ontology.*; -import org.slf4j.Logger; - import java.util.*; +import org.slf4j.Logger; /** Enables data connection of em data between SIMONA and SimonaAPI */ public class ExtEmDataConnection @@ -41,8 +40,8 @@ public boolean useCommunication() { return mode == EmMode.EM_COMMUNICATION; } - - public void sendFlexRequests(long tick, Map data, Optional maybeNextTick, Logger log) { + public void sendFlexRequests( + long tick, Map data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No em flex requests found! Sending no em data to SIMONA for tick {}.", tick); } else { @@ -63,7 +62,8 @@ public void sendFlexRequests(long tick, Map data, Optio * @param maybeNextTick option for the next tick in the simulation * @param log logger */ - public void sendFlexOptions(long tick, Map> data, Optional maybeNextTick, Logger log) { + public void sendFlexOptions( + long tick, Map> data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No em flex options found! Sending no em data to SIMONA for tick {}.", tick); } else { @@ -80,7 +80,8 @@ public void sendFlexOptions(long tick, Map> data, Option * @param maybeNextTick option for the next tick in the simulation * @param log logger */ - public void sendSetPoints(long tick, Map data, Optional maybeNextTick, Logger log) { + public void sendSetPoints( + long tick, Map data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No em set points found! Sending no em data to SIMONA for tick {}.", tick); } else { @@ -97,8 +98,8 @@ public void sendSetPoints(long tick, Map data, Optional mayb * @return an {@link FlexOptionsResponse} message * @throws InterruptedException - on interruptions */ - public Map requestEmFlexResults(long tick, Map> emEntities) - throws InterruptedException { + public Map requestEmFlexResults( + long tick, Map> emEntities) throws InterruptedException { sendExtMsg(new RequestEmFlexResults(tick, emEntities)); return receiveWithType(FlexOptionsResponse.class).receiverToFlexOptions(); } diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java index 6cfcfe41..fb726884 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java @@ -33,12 +33,12 @@ public Map getReceiverToSetPoint() { @Override public String toString() { return "EmSetPointResult{" - + "time=" - + getTime() - + ", sender=" - + getInputModel() - + ", receiverToSetPoints=" - + receiverToSetPoints - + '}'; + + "time=" + + getTime() + + ", sender=" + + getInputModel() + + ", receiverToSetPoints=" + + receiverToSetPoints + + '}'; } } diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java index ce3ea179..e4855ac8 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java @@ -1,54 +1,103 @@ +/* + * © 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.em.model; import edu.ie3.datamodel.models.result.system.FlexOptionsResult; -import tech.units.indriya.ComparableQuantity; - -import javax.measure.quantity.Power; import java.time.ZonedDateTime; +import java.util.Collections; +import java.util.Map; import java.util.UUID; +import javax.measure.quantity.Power; +import tech.units.indriya.ComparableQuantity; public class ExtendedFlexOptionsResult extends FlexOptionsResult { - private final UUID receiver; - - /** - * Standard constructor with automatic uuid generation. - * - * @param time date and time when the result is produced - * @param sender uuid of the input model that produces the result - * @param receiver uuid of the receiver that will receive this result - * @param pRef active power that was suggested for regular usage by the system participant - * @param pMin active minimal power that was determined by the system participant - * @param pMax active maximum power that was determined by the system participant - */ - public ExtendedFlexOptionsResult(ZonedDateTime time, UUID sender, UUID receiver, ComparableQuantity pRef, ComparableQuantity pMin, ComparableQuantity pMax) { - super(time, sender, pRef, pMin, pMax); - this.receiver = receiver; - } - - public UUID getSender() { - return getInputModel(); - } - - public UUID getReceiver() { - return receiver; - } - - @Override - public String toString() { - return "ExtendedFlexOptionsResult{" - + "time=" - + getTime() - + ", sender=" - + getSender() - + ", receiver=" - + receiver - + ", pRef=" - + getpRef() - + ", pMin=" - + getpMin() - + ", pMax=" - + getpMax() - + '}'; - } + private final UUID receiver; + + private final Map disaggregated; + + /** + * Standard constructor for {@link ExtendedFlexOptionsResult}. + * + * @param time date and time when the result is produced + * @param sender uuid of the input model that produces the result + * @param receiver uuid of the receiver that will receive this result + * @param pRef active power that was suggested for regular usage by the system participant + * @param pMin active minimal power that was determined by the system participant + * @param pMax active maximum power that was determined by the system participant + */ + public ExtendedFlexOptionsResult( + ZonedDateTime time, + UUID sender, + UUID receiver, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax) { + super(time, sender, pRef, pMin, pMax); + this.receiver = receiver; + this.disaggregated = Collections.emptyMap(); + } + + /** + * Constructor for {@link ExtendedFlexOptionsResult} with disaggregated flex options. + * + * @param time date and time when the result is produced + * @param sender uuid of the input model that produces the result + * @param receiver uuid of the receiver that will receive this result + * @param pRef active power that was suggested for regular usage by the system participant + * @param pMin active minimal power that was determined by the system participant + * @param pMax active maximum power that was determined by the system participant + */ + public ExtendedFlexOptionsResult( + ZonedDateTime time, + UUID sender, + UUID receiver, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax, + Map disaggregated) { + super(time, sender, pRef, pMin, pMax); + this.receiver = receiver; + this.disaggregated = disaggregated; + } + + public UUID getSender() { + return getInputModel(); + } + + public UUID getReceiver() { + return receiver; + } + + public boolean hasDisaggregated() { + return !disaggregated.isEmpty(); + } + + public Map getDisaggregated() { + return Collections.unmodifiableMap(disaggregated); + } + + @Override + public String toString() { + return "ExtendedFlexOptionsResult{" + + "time=" + + getTime() + + ", sender=" + + getSender() + + ", receiver=" + + receiver + + ", pRef=" + + getpRef() + + ", pMin=" + + getpMin() + + ", pMax=" + + getpMax() + + ", disaggregated=" + + disaggregated + + '}'; + } } diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java index e6aa6728..7e272058 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java @@ -6,14 +6,13 @@ package edu.ie3.simona.api.data.em.model; +import java.util.UUID; import javax.measure.quantity.Power; import tech.units.indriya.ComparableQuantity; -import java.util.UUID; - public record FlexOptions( - UUID receiver, - UUID sender, + UUID receiver, + UUID sender, ComparableQuantity pMin, ComparableQuantity pRef, ComparableQuantity pMax) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java index 80950c78..dc83a39d 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java @@ -1,7 +1,12 @@ +/* + * © 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.em.model; import edu.ie3.datamodel.models.result.ResultEntity; - import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Collection; @@ -10,26 +15,26 @@ public class FlexRequestResult extends ResultEntity { - private final List receivers; + private final List receivers; - public FlexRequestResult(ZonedDateTime time, UUID inputModel, Collection receivers) { - super(time, inputModel); - this.receivers = new ArrayList<>(receivers); - } + public FlexRequestResult(ZonedDateTime time, UUID inputModel, Collection receivers) { + super(time, inputModel); + this.receivers = new ArrayList<>(receivers); + } - public List getReceivers() { - return receivers; - } + public List getReceivers() { + return receivers; + } - @Override - public String toString() { - return "FlexRequestResult{" - + "time=" - + getTime() - + ", inputModel=" - + getInputModel() - + ", receivers=" - + receivers - + '}'; - } + @Override + public String toString() { + return "FlexRequestResult{" + + "time=" + + getTime() + + ", inputModel=" + + getInputModel() + + ", receivers=" + + receivers + + '}'; + } } diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java index 324c00cc..b75cd851 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java @@ -1,3 +1,9 @@ +/* + * © 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.em.ontology; public record EmCompletion() implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java index 14161ce2..9c2e5c96 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java @@ -7,7 +7,6 @@ package edu.ie3.simona.api.data.em.ontology; import edu.ie3.simona.api.data.em.model.ExtendedFlexOptionsResult; - import java.util.Map; import java.util.UUID; diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java index 039d94bb..0cb8ceec 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java @@ -7,7 +7,6 @@ package edu.ie3.simona.api.data.em.ontology; import edu.ie3.simona.api.data.em.model.FlexRequestResult; - import java.util.Map; import java.util.UUID; diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java index 503d4f02..422ec555 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java @@ -1,3 +1,9 @@ +/* + * © 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.em.ontology; import java.util.Map; @@ -6,5 +12,5 @@ /** Message that provides em data (flex requests) from an external simulation. */ public record ProvideFlexRequestData( - long tick, Map> flexRequests, Optional maybeNextTick) - implements EmDataMessageFromExt {} \ No newline at end of file + long tick, Map> flexRequests, Optional maybeNextTick) + implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmCompletion.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmCompletion.java index 09da599f..0a5d5322 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmCompletion.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmCompletion.java @@ -1,3 +1,9 @@ +/* + * © 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.em.ontology; -public record RequestEmCompletion(long tick) implements EmDataMessageFromExt { } +public record RequestEmCompletion(long tick) implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java b/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java index ab17a5b7..4316a5de 100644 --- a/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java @@ -17,7 +17,8 @@ import java.util.UUID; import org.apache.pekko.actor.typed.ActorRef; -public class ExtEvDataConnection extends BiDirectional { +public class ExtEvDataConnection + extends BiDirectional { public ExtEvDataConnection() { super(); diff --git a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java index 720a1674..4cc90edd 100644 --- a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java @@ -54,11 +54,15 @@ public Map getExtId2UuidMapping(DataType dataType) { } public Map getFullMapping() { - return extEntities.values().stream().flatMap(Collection::stream).collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); + return extEntities.values().stream() + .flatMap(Collection::stream) + .collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); } public Map getFullMappingReverse() { - return extEntities.values().stream().flatMap(Collection::stream).collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); + return extEntities.values().stream() + .flatMap(Collection::stream) + .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); } /** @@ -82,10 +86,10 @@ public static List toSimona(List list, Map mapping) public static List toExt(List list, Map mapping) { return list.stream() - .map(str -> Optional.ofNullable(mapping.get(str))) - .filter(Optional::isPresent) - .map(Optional::get) - .toList(); + .map(str -> Optional.ofNullable(mapping.get(str))) + .filter(Optional::isPresent) + .map(Optional::get) + .toList(); } /** 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 7dc3bc02..e4ef47f4 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 @@ -10,12 +10,11 @@ import edu.ie3.simona.api.data.ExtInputDataConnection; import edu.ie3.simona.api.data.primarydata.ontology.PrimaryDataMessageFromExt; import edu.ie3.simona.api.data.primarydata.ontology.ProvidePrimaryData; -import org.slf4j.Logger; - 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 extends ExtInputDataConnection { @@ -39,7 +38,8 @@ public Optional> getValueClass(UUID uuid) { return Optional.ofNullable(valueClasses.get(uuid)); } - public void sendPrimaryData(long tick, Map data, Optional maybeNextTick, Logger log) { + public void sendPrimaryData( + long tick, Map data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No primary data found! Sending no primary data to SIMONA for tick {}.", tick); } else { 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 289e8297..9ce335a4 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 @@ -12,7 +12,6 @@ import edu.ie3.simona.api.data.results.ontology.RequestResultEntities; import edu.ie3.simona.api.data.results.ontology.ResultDataMessageFromExt; import edu.ie3.simona.api.data.results.ontology.ResultDataResponseMessageToExt; - import java.util.List; import java.util.Map; import java.util.UUID; @@ -20,7 +19,8 @@ import java.util.stream.Stream; /** Enables data connection of results between SIMONA and SimonaAPI */ -public class ExtResultDataConnection extends BiDirectional { +public class ExtResultDataConnection + extends BiDirectional { /** Map uuid to external id of grid related entities */ private final List gridResults; @@ -32,9 +32,7 @@ public class ExtResultDataConnection extends BiDirectional flexResults; public ExtResultDataConnection( - List participantResults, - List gridResults, - List flexResults) { + List participantResults, List gridResults, List flexResults) { this.participantResults = participantResults; this.gridResults = gridResults; this.flexResults = flexResults; @@ -93,8 +91,7 @@ public Map requestGridResults(long tick) throws InterruptedE return createResultMap(requestGridResultsList(tick)); } - public Map requestParticipantResults(long tick) - throws InterruptedException { + public Map requestParticipantResults(long tick) throws InterruptedException { return createResultMap(requestParticipantResultsList(tick)); } diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java b/src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java index 54bfccb2..2769c419 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java +++ b/src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java @@ -1,44 +1,50 @@ +/* + * © 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.results; import edu.ie3.simona.api.data.ExtOutputDataConnection; import edu.ie3.simona.api.data.results.ontology.ResultDataResponseMessageToExt; - import java.util.concurrent.LinkedBlockingQueue; /** - * External result listener. This listener is similar to the {@link ExtResultDataConnection}, but is not able to request - * results from SIMONA. + * External result listener. This listener is similar to the {@link ExtResultDataConnection}, but is + * not able to request results from SIMONA. */ public class ExtResultListener implements ExtOutputDataConnection { - /** Data message queue containing messages from SIMONA */ - public final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); - - public ExtResultListener() {} - - - public final void queueExtResponseMsg(ResultDataResponseMessageToExt msg) throws InterruptedException { - receiveTriggerQueue.put(msg); - } - - public final ResultDataResponseMessageToExt receiveAny() throws InterruptedException { - return receiveTriggerQueue.take(); - } - - @SuppressWarnings("unchecked") - public final T receiveWithType(Class expectedMessageClass) - throws InterruptedException { - // blocks until actor puts something here - ResultDataResponseMessageToExt msg = receiveTriggerQueue.take(); - - if (msg.getClass().equals(expectedMessageClass)) { - return (T) msg; - } else - throw new RuntimeException( - "Received unexpected message '" - + msg - + "', expected type '" - + expectedMessageClass - + "'"); - } + /** Data message queue containing messages from SIMONA */ + public final LinkedBlockingQueue receiveTriggerQueue = + new LinkedBlockingQueue<>(); + + public ExtResultListener() {} + + public final void queueExtResponseMsg(ResultDataResponseMessageToExt msg) + throws InterruptedException { + receiveTriggerQueue.put(msg); + } + + public final ResultDataResponseMessageToExt receiveAny() throws InterruptedException { + return receiveTriggerQueue.take(); + } + + @SuppressWarnings("unchecked") + public final T receiveWithType( + Class expectedMessageClass) throws InterruptedException { + // blocks until actor puts something here + ResultDataResponseMessageToExt msg = receiveTriggerQueue.take(); + + if (msg.getClass().equals(expectedMessageClass)) { + return (T) msg; + } else + throw new RuntimeException( + "Received unexpected message '" + + msg + + "', expected type '" + + expectedMessageClass + + "'"); + } } diff --git a/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java deleted file mode 100644 index da779e67..00000000 --- a/src/main/java/edu/ie3/simona/api/data/results/model/DesaggFlexOptionsResult.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * © 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.results.model; - -import edu.ie3.datamodel.models.result.system.FlexOptionsResult; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.Map; -import java.util.UUID; -import javax.measure.quantity.Power; -import tech.units.indriya.ComparableQuantity; - -public class DesaggFlexOptionsResult extends FlexOptionsResult { - - private final Map connectedFlexOptionResults; - - public DesaggFlexOptionsResult( - ZonedDateTime time, - UUID inputModel, - ComparableQuantity pRef, - ComparableQuantity pMin, - ComparableQuantity pMax, - Map connectedFlexOptionResults) { - super(time, inputModel, pRef, pMin, pMax); - this.connectedFlexOptionResults = connectedFlexOptionResults; - } - - public DesaggFlexOptionsResult( - FlexOptionsResult flexOptionsResult, - Map connectedFlexOptionResults) { - super( - flexOptionsResult.getTime(), - flexOptionsResult.getInputModel(), - flexOptionsResult.getpRef(), - flexOptionsResult.getpMin(), - flexOptionsResult.getpMax()); - this.connectedFlexOptionResults = connectedFlexOptionResults; - } - - public DesaggFlexOptionsResult(FlexOptionsResult flexOptionsResult) { - super( - flexOptionsResult.getTime(), - flexOptionsResult.getInputModel(), - flexOptionsResult.getpRef(), - flexOptionsResult.getpMin(), - flexOptionsResult.getpMax()); - this.connectedFlexOptionResults = Collections.emptyMap(); - } - - public Map getConnectedFlexOptionResults() { - return connectedFlexOptionResults; - } -} 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 fa1f8681..3911b1c0 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -6,6 +6,8 @@ package edu.ie3.simona.api.simulation; +import static java.util.Collections.emptyList; + import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; @@ -15,15 +17,12 @@ import edu.ie3.simona.api.data.em.EmMode; import edu.ie3.simona.api.data.em.ExtEmDataConnection; import edu.ie3.simona.api.data.em.ontology.*; +import edu.ie3.simona.api.data.mapping.DataType; import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; import edu.ie3.simona.api.data.results.ExtResultDataConnection; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; -import edu.ie3.simona.api.data.mapping.DataType; -import org.slf4j.Logger; - import java.util.*; - -import static java.util.Collections.emptyList; +import org.slf4j.Logger; /** * Abstract class for an external co-simulation with the structure: external api - ext-co-simulation @@ -79,7 +78,8 @@ public static ExtPrimaryDataConnection buildPrimaryConnection( * @param log logger * @return an ext em data connection */ - public static ExtEmDataConnection buildEmConnection(List controlled, EmMode mode, Logger log) { + public static ExtEmDataConnection buildEmConnection( + List controlled, EmMode mode, Logger log) { if (controlled.isEmpty()) { log.warn("Em data connection with 0 controlled entities created. This might lead to errors!"); } else { @@ -100,21 +100,20 @@ public static ExtEmDataConnection buildEmConnection(List controlled, EmMod */ public static ExtResultDataConnection buildResultConnection( Map> mapping, Logger log) { - List participantResults = mapping.getOrDefault(DataType.EXT_PARTICIPANT_RESULT, emptyList()); + List participantResults = + mapping.getOrDefault(DataType.EXT_PARTICIPANT_RESULT, emptyList()); List gridResults = mapping.getOrDefault(DataType.EXT_GRID_RESULT, emptyList()); List flexResults = mapping.getOrDefault(DataType.EXT_FLEX_OPTIONS_RESULT, emptyList()); - if (participantResults.isEmpty() - && gridResults.isEmpty() - && flexResults.isEmpty()) { + if (participantResults.isEmpty() && gridResults.isEmpty() && flexResults.isEmpty()) { log.warn("No result connection was created."); throw new ExtDataConnectionException(ExtResultDataConnection.class); } else { log.info( "Result connection with {} participants, {} grid assets and {} flex option mappings created.", - participantResults.size(), - gridResults.size(), - flexResults.size()); + participantResults.size(), + gridResults.size(), + flexResults.size()); return new ExtResultDataConnection(participantResults, gridResults, flexResults); } } @@ -148,8 +147,7 @@ protected void sendPrimaryDataToSimona( Logger log) throws InterruptedException { checkTick(tick); - Map inputData = - queueToSimona.takeData(ExtInputDataContainer::extractPrimaryData); + Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractPrimaryData); sendPrimaryDataToSimona(extPrimaryDataConnection, tick, inputData, maybeNextTick, log); } @@ -221,8 +219,9 @@ protected void sendEmSetPointsToSimona( log.debug("Provided em set points to SIMONA!"); } - - protected void useFlexCommunication(ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { + protected void useFlexCommunication( + ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) + throws InterruptedException { // handle flex requests boolean notFinished = true; @@ -295,7 +294,6 @@ protected void useFlexCommunication(ExtEmDataConnection extEmDataConnection, lon } } - // result data methods /** From 6336ee274020ca90f0c242a58c007e36fc48b85f Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 25 Apr 2025 13:11:05 +0200 Subject: [PATCH 35/80] Some refactoring. --- .../data/container/ExtResultContainer.java | 70 -------------- .../results/ExtResultContainerTest.groovy | 96 ------------------- 2 files changed, 166 deletions(-) delete mode 100644 src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java index 785dbf65..d22c1ab6 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java @@ -6,19 +6,11 @@ package edu.ie3.simona.api.data.container; -import static edu.ie3.util.quantities.PowerSystemUnits.PU; - -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 java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.UUID; -import javax.measure.quantity.Dimensionless; -import tech.units.indriya.ComparableQuantity; -import tech.units.indriya.quantity.Quantities; /** Contains all results from SIMONA for a certain tick */ public class ExtResultContainer implements ExtDataContainer { @@ -88,66 +80,4 @@ public Optional getNextTick() { public ResultEntity getResult(UUID assetId) { return resultMap.get(assetId); } - - /** - * Returns the voltage deviation in pu for certain asset, if this asset provided a {@link - * NodeResult} - */ - @Deprecated - public double getVoltageDeviation(UUID assetId) { - if (resultMap.get(assetId) instanceof NodeResult nodeResult) { - ComparableQuantity vMagDev = - Quantities.getQuantity(-1.0, PU).add(nodeResult.getvMag()); - return vMagDev.getValue().doubleValue(); - } else { - throw new IllegalArgumentException( - "VOLTAGE DEVIATION is only available for NodeResult's! AssetId: " + assetId); - } - } - - /** - * Returns the voltage deviation for certain asset, if this asset provided a {@link NodeResult} - */ - @Deprecated - public double getVoltage(UUID assetId) { - if (resultMap.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} - */ - @Deprecated - public double getActivePower(UUID assetId) { - if (resultMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { - return systemParticipantResult.getP().getValue().doubleValue(); - } else { - throw new IllegalArgumentException( - "ACTIVE POWER is only available for SystemParticipantResult's!"); - } - } - - /** - * Returns the reactive power in kVAr for certain asset, if this asset provided a {@link - * SystemParticipantResult} - */ - @Deprecated - public double getReactivePower(UUID assetId) { - if (resultMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { - return systemParticipantResult.getQ().getValue().doubleValue(); - } else { - throw new IllegalArgumentException( - "REACTIVE POWER is only available for SystemParticipantResult's!"); - } - } - - /** Returns the line loading for certain asset, if this asset provided a {@link LineResult} */ - @Deprecated - public double getLineLoading(UUID assetId) { - throw new IllegalArgumentException("LINE LOADING is not implemented yet!"); - } } diff --git a/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy deleted file mode 100644 index cd6e230b..00000000 --- a/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultContainerTest.groovy +++ /dev/null @@ -1,96 +0,0 @@ -package edu.ie3.simona.api.data.results - -import edu.ie3.datamodel.models.StandardUnits -import edu.ie3.datamodel.models.result.NodeResult -import edu.ie3.simona.api.data.container.ExtResultContainer -import edu.ie3.simona.api.test.common.DataServiceTestData -import edu.ie3.util.quantities.PowerSystemUnits -import spock.lang.Shared -import spock.lang.Specification -import tech.units.indriya.quantity.Quantities - -import java.time.ZonedDateTime - -class ExtResultContainerTest extends Specification implements DataServiceTestData { - - @Shared - UUID nodeUuid = UUID.fromString("55b97041-64be-4e6b-983a-72dbde6eddf4") - - @Shared - NodeResult nodeResult = new NodeResult( - ZonedDateTime.parse("2020-01-30T17:26:44Z"), - nodeUuid, - Quantities.getQuantity(0.95, PowerSystemUnits.PU), - Quantities.getQuantity(45, StandardUnits.VOLTAGE_ANGLE) - ) - - def "ExtResultContainer should return voltage deviation correctly"() { - given: - def resultMap = Map.of( - "Node", nodeResult - ) - def extResultContainer = new ExtResultContainer(0L, resultMap) - - when: - def calculatedVoltageDeviation = extResultContainer.getVoltageDeviation("Node") - - then: - calculatedVoltageDeviation == -0.05d - } - - def "ExtResultContainer should throw an exception, if voltage deviation was requested for a not NodeResult"() { - given: - def resultMap = Map.of( - "Load", loadResult - ) - def extResultContainer = new ExtResultContainer(0L, resultMap) - - when: - extResultContainer.getVoltageDeviation("Load") - - then: - thrown IllegalArgumentException - } - - def "ExtResultContainer should return active power correctly"() { - given: - def resultMap = Map.of( - "Load", loadResult - ) - def extResultContainer = new ExtResultContainer(0L, resultMap) - - when: - def returnedActivePower = extResultContainer.getActivePower("Load") - - then: - returnedActivePower == 10d - } - - def "ExtResultContainer should return reactive power correctly"() { - given: - def resultMap = Map.of( - "Load", loadResult - ) - def extResultContainer = new ExtResultContainer(0L, resultMap) - - when: - def returnedReactivePower = extResultContainer.getReactivePower("Load") - - then: - returnedReactivePower == 5d - } - - def "ExtResultContainer should throw an exception, if active power was requested for a not SystemParticipantResult"() { - given: - def resultMap = Map.of( - "Node", nodeResult - ) - def extResultContainer = new ExtResultContainer(0L, resultMap) - - when: - extResultContainer.getActivePower("Node") - - then: - thrown IllegalArgumentException - } -} \ No newline at end of file From fec755633f4fe80676cba2bb121d2065e56d835b Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 28 Apr 2025 12:30:37 +0200 Subject: [PATCH 36/80] Improving `EmServiceBaseCore`. --- .../edu/ie3/simona/api/data/em/ExtEmDataConnection.java | 6 +----- .../simona/api/data/em/ontology/RequestEmFlexResults.java | 3 +-- 2 files changed, 2 insertions(+), 7 deletions(-) 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 fe7297c1..fc1c13a4 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 @@ -36,10 +36,6 @@ public List getControlledEms() { return new ArrayList<>(controlled); } - public boolean useCommunication() { - return mode == EmMode.EM_COMMUNICATION; - } - public void sendFlexRequests( long tick, Map data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { @@ -99,7 +95,7 @@ public void sendSetPoints( * @throws InterruptedException - on interruptions */ public Map requestEmFlexResults( - long tick, Map> emEntities) throws InterruptedException { + long tick, List emEntities) throws InterruptedException { sendExtMsg(new RequestEmFlexResults(tick, emEntities)); return receiveWithType(FlexOptionsResponse.class).receiverToFlexOptions(); } diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java index 436c86dd..925164d1 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java @@ -7,9 +7,8 @@ package edu.ie3.simona.api.data.em.ontology; import java.util.List; -import java.util.Map; import java.util.UUID; /** Request em set points from SIMONA in the given tick. */ -public record RequestEmFlexResults(long tick, Map> emEntities) +public record RequestEmFlexResults(long tick, List emEntities) implements EmDataMessageFromExt {} From 0200ebcd105e6abd7bd020145d5ffce1ab77059b Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 28 Apr 2025 13:29:24 +0200 Subject: [PATCH 37/80] Refactoring flexibility optimizer. --- .../simona/api/data/em/ExtEmDataConnection.java | 4 ++-- .../data/em/ontology/RequestEmFlexResults.java | 2 +- .../simona/api/simulation/ExtCoSimulation.java | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) 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 fc1c13a4..44e618e7 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 @@ -95,8 +95,8 @@ public void sendSetPoints( * @throws InterruptedException - on interruptions */ public Map requestEmFlexResults( - long tick, List emEntities) throws InterruptedException { - sendExtMsg(new RequestEmFlexResults(tick, emEntities)); + long tick, List emEntities, boolean disaggregated) throws InterruptedException { + sendExtMsg(new RequestEmFlexResults(tick, emEntities, disaggregated)); return receiveWithType(FlexOptionsResponse.class).receiverToFlexOptions(); } diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java index 925164d1..c7c4f4fe 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmFlexResults.java @@ -10,5 +10,5 @@ import java.util.UUID; /** Request em set points from SIMONA in the given tick. */ -public record RequestEmFlexResults(long tick, List emEntities) +public record RequestEmFlexResults(long tick, List emEntities, boolean disaggregated) implements EmDataMessageFromExt {} 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 3911b1c0..4a97338e 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -22,6 +22,7 @@ import edu.ie3.simona.api.data.results.ExtResultDataConnection; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; import java.util.*; +import java.util.stream.Collectors; import org.slf4j.Logger; /** @@ -196,6 +197,21 @@ protected void sendEmSetPointsToSimona( sendEmSetPointsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); } + protected void sendFlexOptionsToExt( + ExtEmDataConnection extEmDataConnection, long tick, boolean disaggregated, Logger log) + throws InterruptedException { + log.debug("Request results from SIMONA!"); + Map results = + extEmDataConnection + .requestEmFlexResults(tick, extEmDataConnection.getControlledEms(), disaggregated) + .entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey, v -> (ResultEntity) v)); + log.debug("Received results from SIMONA!"); + queueToExt.queueData(new ExtResultContainer(tick, results)); + log.debug("Sent results to {}", extSimulatorName); + } + /** * Function to send em set point data to SIMONA using the given {@link ExtEmDataConnection}. * From f5b9351c916292ee193c2220e5911652edfca279 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 28 Apr 2025 15:54:52 +0200 Subject: [PATCH 38/80] Saving changes. --- .../simona/api/data/mapping/ExtEntityMapping.java | 13 +++++++++++++ .../ie3/simona/api/simulation/ExtCoSimulation.java | 11 +++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java index 4cc90edd..7cb84314 100644 --- a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java @@ -8,6 +8,7 @@ import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,6 +54,12 @@ public Map getExtId2UuidMapping(DataType dataType) { .collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); } + public Map getExtId2UuidMapping(DataType... dataType) { + return Stream.of(dataType) + .flatMap(type -> extEntities.getOrDefault(type, Collections.emptyList()).stream()) + .collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); + } + public Map getFullMapping() { return extEntities.values().stream() .flatMap(Collection::stream) @@ -76,6 +83,12 @@ public Map getExtUuid2IdMapping(DataType dataType) { .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); } + public Map getExtUuid2IdMapping(DataType... dataType) { + return Stream.of(dataType) + .flatMap(type -> extEntities.getOrDefault(type, Collections.emptyList()).stream()) + .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); + } + public static List toSimona(List list, Map mapping) { return list.stream() .map(str -> Optional.ofNullable(mapping.get(str))) 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 4a97338e..c0b504f2 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -22,7 +22,6 @@ import edu.ie3.simona.api.data.results.ExtResultDataConnection; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; import java.util.*; -import java.util.stream.Collectors; import org.slf4j.Logger; /** @@ -201,12 +200,12 @@ protected void sendFlexOptionsToExt( ExtEmDataConnection extEmDataConnection, long tick, boolean disaggregated, Logger log) throws InterruptedException { log.debug("Request results from SIMONA!"); + Map results = - extEmDataConnection - .requestEmFlexResults(tick, extEmDataConnection.getControlledEms(), disaggregated) - .entrySet() - .stream() - .collect(Collectors.toMap(Map.Entry::getKey, v -> (ResultEntity) v)); + new HashMap<>( + extEmDataConnection.requestEmFlexResults( + tick, extEmDataConnection.getControlledEms(), disaggregated)); + log.debug("Received results from SIMONA!"); queueToExt.queueData(new ExtResultContainer(tick, results)); log.debug("Sent results to {}", extSimulatorName); From 3d72b1d4fc2d3e1fbedaa0c68ddf2b27cf023d61 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 6 May 2025 14:50:31 +0200 Subject: [PATCH 39/80] Saving changes. --- .../java/edu/ie3/simona/api/data/em/EmMode.java | 17 ++--------------- .../ie3/simona/api/data/mapping/DataType.java | 2 +- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/em/EmMode.java b/src/main/java/edu/ie3/simona/api/data/em/EmMode.java index e0628e4c..6d098eca 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/EmMode.java +++ b/src/main/java/edu/ie3/simona/api/data/em/EmMode.java @@ -6,26 +6,13 @@ package edu.ie3.simona.api.data.em; -import edu.ie3.simona.api.data.mapping.DataType; - public enum EmMode { - SET_POINT("setPoint"), - EM_COMMUNICATION("emCommunication"), - EM_OPTIMIZATION("emOptimization"), - ; + BASE("base"), + EM_COMMUNICATION("emCommunication"); public final String mode; EmMode(String mode) { this.mode = mode; } - - public static EmMode fromDataType(DataType dataType) { - return switch (dataType) { - case EXT_EM_INPUT -> EmMode.SET_POINT; - case EXT_EM_COMMUNICATION -> EmMode.EM_COMMUNICATION; - case EXT_EM_OPTIMIZER -> EmMode.EM_OPTIMIZATION; - default -> throw new IllegalStateException("Unexpected data type: " + dataType); - }; - } } diff --git a/src/main/java/edu/ie3/simona/api/data/mapping/DataType.java b/src/main/java/edu/ie3/simona/api/data/mapping/DataType.java index 740746b6..cddc1626 100644 --- a/src/main/java/edu/ie3/simona/api/data/mapping/DataType.java +++ b/src/main/java/edu/ie3/simona/api/data/mapping/DataType.java @@ -12,7 +12,6 @@ public enum DataType { EXT_PRIMARY_INPUT("primary_input"), EXT_EM_INPUT("em_input"), EXT_EM_COMMUNICATION("em_communication"), - EXT_EM_OPTIMIZER("em_optimizer"), EXT_GRID_RESULT("grid_result"), EXT_PARTICIPANT_RESULT("participant_result"), EXT_FLEX_OPTIONS_RESULT("flex_options_result"); @@ -27,6 +26,7 @@ public static DataType parse(String type) throws ParsingException { return switch (type) { case "primary_input" -> EXT_PRIMARY_INPUT; case "em_input" -> EXT_EM_INPUT; + case "em_communication" -> EXT_EM_COMMUNICATION; case "grid_result" -> EXT_GRID_RESULT; case "participant_result" -> EXT_PARTICIPANT_RESULT; case "flex_options_result" -> EXT_FLEX_OPTIONS_RESULT; From b77e3c4b4f129f2054b132aed1a8266c0596d2f0 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 7 May 2025 16:27:01 +0200 Subject: [PATCH 40/80] Saving changes. --- .../api/data/em/model/ExtendedFlexOptionsResult.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java index e4855ac8..bff7980f 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java @@ -9,6 +9,7 @@ import edu.ie3.datamodel.models.result.system.FlexOptionsResult; import java.time.ZonedDateTime; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.measure.quantity.Power; @@ -39,7 +40,7 @@ public ExtendedFlexOptionsResult( ComparableQuantity pMax) { super(time, sender, pRef, pMin, pMax); this.receiver = receiver; - this.disaggregated = Collections.emptyMap(); + this.disaggregated = new HashMap<>(); } /** @@ -65,6 +66,10 @@ public ExtendedFlexOptionsResult( this.disaggregated = disaggregated; } + public void addDisaggregated(UUID uuid, FlexOptionsResult flexOptionsResult) { + this.disaggregated.put(uuid, flexOptionsResult); + } + public UUID getSender() { return getInputModel(); } From 6770dc613df853556807a75b4790248204669f9a Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 12 May 2025 14:08:13 +0200 Subject: [PATCH 41/80] Added parsing of flex message delay. --- .../data/container/ExtInputDataContainer.java | 16 +++-- .../api/data/em/ExtEmDataConnection.java | 13 ++-- .../simona/api/data/em/model/EmSetPoint.java | 34 +++++++++++ .../api/data/em/model/FlexOptionRequest.java | 5 +- .../simona/api/data/em/model/FlexOptions.java | 18 +++--- .../api/data/em/model/NoSetPointValue.java | 17 ------ .../em/ontology/ProvideEmSetPointData.java | 5 +- .../em/ontology/ProvideFlexRequestData.java | 4 +- .../api/simulation/ExtCoSimulation.java | 61 ++++++++++--------- 9 files changed, 102 insertions(+), 71 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/NoSetPointValue.java diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java index 6d134c53..56877848 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java @@ -8,8 +8,10 @@ import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; +import edu.ie3.simona.api.data.em.model.EmSetPoint; import edu.ie3.simona.api.data.em.model.FlexOptionRequest; import edu.ie3.simona.api.data.em.model.FlexOptions; + import java.util.*; /** Contains all inputs for SIMONA for a certain tick */ @@ -28,7 +30,7 @@ public final class ExtInputDataContainer implements ExtDataContainer { // em maps private final Map flexRequests = new HashMap<>(); private final Map> flexOptions = new HashMap<>(); - private final Map setPoints = new HashMap<>(); + private final Map setPoints = new HashMap<>(); /** * Container class for input data for SIMONA which can be read by SimonaAPI @@ -67,8 +69,8 @@ public void addPrimaryValue(UUID id, Value value) { primaryData.put(id, value); } - public void addRequest(UUID receiver, Optional sender) { - flexRequests.put(receiver, new FlexOptionRequest(receiver, sender)); + public void addRequest(UUID receiver, FlexOptionRequest request) { + flexRequests.put(receiver, request); } public void addFlexOptions(UUID id, List flexOption) { @@ -81,7 +83,11 @@ public void addFlexOptions(UUID id, List flexOption) { } public void addSetPoint(UUID id, PValue setPoint) { - setPoints.put(id, setPoint); + setPoints.put(id, EmSetPoint.from(id, setPoint)); + } + + public void addSetPoint(EmSetPoint setPoint) { + setPoints.put(setPoint.receiver(), setPoint); } public Map extractPrimaryData() { @@ -97,7 +103,7 @@ public Map> extractFlexOptions() { return copyAndClear(flexOptions); } - public Map extractSetPoints() { + public Map extractSetPoints() { return copyAndClear(setPoints); } 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 44e618e7..4bcf4967 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 @@ -6,15 +6,16 @@ package edu.ie3.simona.api.data.em; -import edu.ie3.datamodel.models.value.PValue; import edu.ie3.simona.api.data.BiDirectional; +import edu.ie3.simona.api.data.em.model.EmSetPoint; import edu.ie3.simona.api.data.em.model.ExtendedFlexOptionsResult; import edu.ie3.simona.api.data.em.model.FlexOptionRequest; import edu.ie3.simona.api.data.em.model.FlexOptions; import edu.ie3.simona.api.data.em.ontology.*; -import java.util.*; import org.slf4j.Logger; +import java.util.*; + /** Enables data connection of em data between SIMONA and SimonaAPI */ public class ExtEmDataConnection extends BiDirectional { @@ -42,11 +43,7 @@ public void sendFlexRequests( log.warn("No em flex requests found! Sending no em data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with em flex requests."); - - Map> emFlexRequests = new HashMap<>(); - data.forEach((receiver, value) -> emFlexRequests.put(receiver, value.sender())); - - sendExtMsg(new ProvideFlexRequestData(tick, emFlexRequests, maybeNextTick)); + sendExtMsg(new ProvideFlexRequestData(tick, data, maybeNextTick)); } } @@ -77,7 +74,7 @@ public void sendFlexOptions( * @param log logger */ public void sendSetPoints( - long tick, Map data, Optional maybeNextTick, Logger log) { + long tick, Map data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No em set points found! Sending no em data to SIMONA for tick {}.", tick); } else { diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java new file mode 100644 index 00000000..9c337377 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java @@ -0,0 +1,34 @@ +package edu.ie3.simona.api.data.em.model; + +import edu.ie3.datamodel.models.value.PValue; +import edu.ie3.datamodel.models.value.SValue; +import tech.units.indriya.ComparableQuantity; + +import javax.measure.quantity.Power; +import javax.measure.quantity.Time; +import java.util.Optional; +import java.util.UUID; + +public record EmSetPoint(UUID receiver, Optional> p, Optional> q, Optional> delay) { + + public static EmSetPoint empty(UUID receiver) { + return new EmSetPoint(receiver, Optional.empty(), Optional.empty(), Optional.empty()); + } + + public static EmSetPoint from(UUID receiver, PValue pValue) { + if (pValue instanceof SValue s) { + return new EmSetPoint(receiver, s.getP(), s.getQ(), Optional.empty()); + } else { + return new EmSetPoint(receiver, pValue.getP(), Optional.empty(), Optional.empty()); + } + } + + public static EmSetPoint from(UUID receiver, PValue pValue, Optional> delay) { + if (pValue instanceof SValue s) { + return new EmSetPoint(receiver, s.getP(), s.getQ(), delay); + } else { + return new EmSetPoint(receiver, pValue.getP(), Optional.empty(), delay); + } + } + +} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java index de10287d..b0e97cd0 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java @@ -6,7 +6,10 @@ package edu.ie3.simona.api.data.em.model; +import tech.units.indriya.ComparableQuantity; + +import javax.measure.quantity.Time; import java.util.Optional; import java.util.UUID; -public record FlexOptionRequest(UUID receiver, Optional sender) {} +public record FlexOptionRequest(UUID receiver, Optional sender, Optional> delay) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java index 7e272058..1b5516ed 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java @@ -6,13 +6,17 @@ package edu.ie3.simona.api.data.em.model; -import java.util.UUID; -import javax.measure.quantity.Power; import tech.units.indriya.ComparableQuantity; +import javax.measure.quantity.Power; +import javax.measure.quantity.Time; +import java.util.Optional; +import java.util.UUID; + public record FlexOptions( - UUID receiver, - UUID sender, - ComparableQuantity pMin, - ComparableQuantity pRef, - ComparableQuantity pMax) {} + UUID receiver, + UUID sender, + ComparableQuantity pMin, + ComparableQuantity pRef, + ComparableQuantity pMax, + Optional> delay) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/NoSetPointValue.java b/src/main/java/edu/ie3/simona/api/data/em/model/NoSetPointValue.java deleted file mode 100644 index 65c18498..00000000 --- a/src/main/java/edu/ie3/simona/api/data/em/model/NoSetPointValue.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * © 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.em.model; - -import edu.ie3.datamodel.models.value.PValue; -import javax.measure.quantity.Power; -import tech.units.indriya.ComparableQuantity; - -public class NoSetPointValue extends PValue { - public NoSetPointValue(ComparableQuantity p) { - super(p); - } -} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java index d3dc699a..656f1985 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java @@ -6,12 +6,13 @@ package edu.ie3.simona.api.data.em.ontology; -import edu.ie3.datamodel.models.value.PValue; +import edu.ie3.simona.api.data.em.model.EmSetPoint; + import java.util.Map; import java.util.Optional; import java.util.UUID; /** Message that provides em data (set points) from an external simulation. */ public record ProvideEmSetPointData( - long tick, Map emData, Optional maybeNextTick) + long tick, Map emSetPoints, Optional maybeNextTick) implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java index 422ec555..7871463e 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java @@ -6,11 +6,13 @@ package edu.ie3.simona.api.data.em.ontology; +import edu.ie3.simona.api.data.em.model.FlexOptionRequest; + import java.util.Map; import java.util.Optional; import java.util.UUID; /** Message that provides em data (flex requests) from an external simulation. */ public record ProvideFlexRequestData( - long tick, Map> flexRequests, Optional maybeNextTick) + long tick, Map flexRequests, Optional maybeNextTick) implements EmDataMessageFromExt {} 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 c0b504f2..959e4a65 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -6,24 +6,25 @@ package edu.ie3.simona.api.simulation; -import static java.util.Collections.emptyList; - import edu.ie3.datamodel.models.result.ResultEntity; -import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.ExtDataContainerQueue; import edu.ie3.simona.api.data.container.ExtInputDataContainer; import edu.ie3.simona.api.data.container.ExtResultContainer; import edu.ie3.simona.api.data.em.EmMode; import edu.ie3.simona.api.data.em.ExtEmDataConnection; +import edu.ie3.simona.api.data.em.model.EmSetPoint; import edu.ie3.simona.api.data.em.ontology.*; import edu.ie3.simona.api.data.mapping.DataType; import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; import edu.ie3.simona.api.data.results.ExtResultDataConnection; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; -import java.util.*; import org.slf4j.Logger; +import java.util.*; + +import static java.util.Collections.emptyList; + /** * Abstract class for an external co-simulation with the structure: external api - ext-co-simulation * - ext-simulation - simonaAPI - simona @@ -174,6 +175,21 @@ protected void sendPrimaryDataToSimona( // energy management data methods + protected void sendFlexOptionsToExt( + ExtEmDataConnection extEmDataConnection, long tick, boolean disaggregated, Logger log) + throws InterruptedException { + log.debug("Request results from SIMONA!"); + + Map results = + new HashMap<>( + extEmDataConnection.requestEmFlexResults( + tick, extEmDataConnection.getControlledEms(), disaggregated)); + + log.debug("Received results from SIMONA!"); + queueToExt.queueData(new ExtResultContainer(tick, results)); + log.debug("Sent results to {}", extSimulatorName); + } + /** * Function to send em set point data to SIMONA using the given {@link ExtEmDataConnection}. This * method will take a value from the {@link #queueToSimona}. @@ -191,26 +207,11 @@ protected void sendEmSetPointsToSimona( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { checkTick(tick); - Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractSetPoints); + Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractSetPoints); sendEmSetPointsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); } - protected void sendFlexOptionsToExt( - ExtEmDataConnection extEmDataConnection, long tick, boolean disaggregated, Logger log) - throws InterruptedException { - log.debug("Request results from SIMONA!"); - - Map results = - new HashMap<>( - extEmDataConnection.requestEmFlexResults( - tick, extEmDataConnection.getControlledEms(), disaggregated)); - - log.debug("Received results from SIMONA!"); - queueToExt.queueData(new ExtResultContainer(tick, results)); - log.debug("Sent results to {}", extSimulatorName); - } - /** * Function to send em set point data to SIMONA using the given {@link ExtEmDataConnection}. * @@ -219,18 +220,18 @@ protected void sendFlexOptionsToExt( * * @param extEmDataConnection the connection to SIMONA * @param tick for which data is sent - * @param dataMap map: id to value + * @param setPoints map: id to value * @param maybeNextTick option for the next tick data is sent * @param log logger */ protected void sendEmSetPointsToSimona( ExtEmDataConnection extEmDataConnection, long tick, - Map dataMap, + Map setPoints, Optional maybeNextTick, Logger log) { log.debug("Received em set points from {}", extSimulatorName); - extEmDataConnection.sendSetPoints(tick, dataMap, maybeNextTick, log); + extEmDataConnection.sendSetPoints(tick, setPoints, maybeNextTick, log); log.debug("Provided em set points to SIMONA!"); } @@ -244,14 +245,14 @@ protected void useFlexCommunication( long extTick = queueToSimona.takeData(ExtInputDataContainer::getTick); - log.warn("Current simulator tick: {}, SIMONA tick: {}", extTick, tick); + log.info("Current simulator tick: {}, SIMONA tick: {}", extTick, tick); if (tick == extTick) { ExtInputDataContainer container = queueToSimona.takeAll(); - log.warn("Flex requests: {}", container.flexRequestsString()); - log.warn("Flex options: {}", container.flexOptionsString()); - log.warn("Set points: {}", container.setPointsString()); + log.info("Flex requests: {}", container.flexRequestsString()); + log.info("Flex options: {}", container.flexOptionsString()); + log.info("Set points: {}", container.setPointsString()); // send received data to SIMONA var requests = container.extractFlexRequests(); @@ -264,9 +265,9 @@ protected void useFlexCommunication( extEmDataConnection.sendSetPoints(tick, setPoints, maybeNextTick, log); - log.warn("Unhandled flex requests: {}", container.flexRequestsString()); - log.warn("Unhandled flex options: {}", container.flexOptionsString()); - log.warn("Unhandled set points: {}", container.setPointsString()); + log.debug("Unhandled flex requests: {}", container.flexRequestsString()); + log.debug("Unhandled flex options: {}", container.flexOptionsString()); + log.debug("Unhandled set points: {}", container.setPointsString()); if (requests.isEmpty() && options.isEmpty() && setPoints.isEmpty()) { log.info("Requesting a service completion for tick: {}.", tick); From 33a6a1082071249bf72fead6d510089ff1a2385c Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 21 May 2025 11:50:32 +0200 Subject: [PATCH 42/80] Saving changes. --- .../data/container/ExtInputDataContainer.java | 4 +- .../simona/api/data/em/model/EmSetPoint.java | 61 +++++++++++++------ .../api/data/em/model/EmSetPointResult.java | 14 +++++ 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java index 56877848..fa90b941 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java @@ -83,11 +83,11 @@ public void addFlexOptions(UUID id, List flexOption) { } public void addSetPoint(UUID id, PValue setPoint) { - setPoints.put(id, EmSetPoint.from(id, setPoint)); + setPoints.put(id, new EmSetPoint(id, setPoint)); } public void addSetPoint(EmSetPoint setPoint) { - setPoints.put(setPoint.receiver(), setPoint); + setPoints.put(setPoint.receiver, setPoint); } public Map extractPrimaryData() { diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java index 9c337377..5802be88 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java @@ -1,34 +1,61 @@ package edu.ie3.simona.api.data.em.model; import edu.ie3.datamodel.models.value.PValue; -import edu.ie3.datamodel.models.value.SValue; import tech.units.indriya.ComparableQuantity; import javax.measure.quantity.Power; import javax.measure.quantity.Time; +import java.util.Objects; import java.util.Optional; import java.util.UUID; -public record EmSetPoint(UUID receiver, Optional> p, Optional> q, Optional> delay) { +public final class EmSetPoint { + public final UUID receiver; + public final Optional power; + public final Optional> delay; + + public EmSetPoint(UUID receiver) { + this.receiver = receiver; + this.power = Optional.empty(); + this.delay = Optional.empty(); + } + + public EmSetPoint(UUID receiver, ComparableQuantity p) { + this.receiver = receiver; + this.power = Optional.of(new PValue(p)); + this.delay = Optional.empty(); + } - public static EmSetPoint empty(UUID receiver) { - return new EmSetPoint(receiver, Optional.empty(), Optional.empty(), Optional.empty()); + public EmSetPoint(UUID receiver, PValue power) { + this.receiver = receiver; + this.power = Optional.of(power); + this.delay = Optional.empty(); } - public static EmSetPoint from(UUID receiver, PValue pValue) { - if (pValue instanceof SValue s) { - return new EmSetPoint(receiver, s.getP(), s.getQ(), Optional.empty()); - } else { - return new EmSetPoint(receiver, pValue.getP(), Optional.empty(), Optional.empty()); - } + public EmSetPoint(UUID receiver, Optional power, Optional> delay) { + this.receiver = receiver; + this.power = power; + this.delay = delay; } - public static EmSetPoint from(UUID receiver, PValue pValue, Optional> delay) { - if (pValue instanceof SValue s) { - return new EmSetPoint(receiver, s.getP(), s.getQ(), delay); - } else { - return new EmSetPoint(receiver, pValue.getP(), Optional.empty(), delay); - } + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + EmSetPoint that = (EmSetPoint) o; + return Objects.equals(receiver, that.receiver) && Objects.equals(power, that.power) && Objects.equals(delay, that.delay); + } + + @Override + public int hashCode() { + return Objects.hash(receiver, power, delay); + } + + @Override + public String toString() { + return "EmSetPoint{" + + "receiver=" + receiver + + ", power=" + power + + ", delay=" + delay + + '}'; } - } diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java index fb726884..9a9a3876 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java @@ -10,6 +10,7 @@ import edu.ie3.datamodel.models.value.PValue; import java.time.ZonedDateTime; import java.util.Map; +import java.util.Objects; import java.util.UUID; /** Em set point result. */ @@ -30,6 +31,19 @@ public Map getReceiverToSetPoint() { return receiverToSetPoints; } + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + EmSetPointResult that = (EmSetPointResult) o; + return Objects.equals(receiverToSetPoints, that.receiverToSetPoints); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), receiverToSetPoints); + } + @Override public String toString() { return "EmSetPointResult{" From 98fa444108bbba0b0d46198c92a03790c86a7642 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 22 May 2025 11:04:34 +0200 Subject: [PATCH 43/80] Clean up. --- .../data/container/ExtInputDataContainer.java | 1 - .../api/data/em/ExtEmDataConnection.java | 15 ++- .../simona/api/data/em/model/EmSetPoint.java | 108 +++++++++--------- .../api/data/em/model/FlexOptionRequest.java | 8 +- .../simona/api/data/em/model/FlexOptions.java | 19 ++- .../em/ontology/ProvideEmSetPointData.java | 3 +- .../em/ontology/ProvideFlexRequestData.java | 3 +- .../RequestControlledEmFlexResults.java | 14 --- .../data/em/ontology/RequestEmSetPoints.java | 14 --- .../api/simulation/ExtCoSimulation.java | 27 +++-- 10 files changed, 97 insertions(+), 115 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmSetPoints.java diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java index fa90b941..c5abd3d7 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java @@ -11,7 +11,6 @@ import edu.ie3.simona.api.data.em.model.EmSetPoint; import edu.ie3.simona.api.data.em.model.FlexOptionRequest; import edu.ie3.simona.api.data.em.model.FlexOptions; - import java.util.*; /** Contains all inputs for SIMONA for a certain tick */ 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 4bcf4967..37691033 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 @@ -12,9 +12,8 @@ import edu.ie3.simona.api.data.em.model.FlexOptionRequest; import edu.ie3.simona.api.data.em.model.FlexOptions; import edu.ie3.simona.api.data.em.ontology.*; -import org.slf4j.Logger; - import java.util.*; +import org.slf4j.Logger; /** Enables data connection of em data between SIMONA and SimonaAPI */ public class ExtEmDataConnection @@ -37,6 +36,14 @@ public List getControlledEms() { return new ArrayList<>(controlled); } + /** + * Sends the em flex requests to SIMONA. + * + * @param tick current tick + * @param data to be sent + * @param maybeNextTick option for the next tick in the simulation + * @param log logger + */ public void sendFlexRequests( long tick, Map data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { @@ -48,7 +55,7 @@ public void sendFlexRequests( } /** - * Sends the em flex options and to SIMONA. + * Sends the em flex options to SIMONA. * * @param tick current tick * @param data to be sent @@ -74,7 +81,7 @@ public void sendFlexOptions( * @param log logger */ public void sendSetPoints( - long tick, Map data, Optional maybeNextTick, Logger log) { + long tick, Map data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No em set points found! Sending no em data to SIMONA for tick {}.", tick); } else { diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java index 5802be88..2164401e 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java @@ -1,61 +1,65 @@ +/* + * © 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.em.model; import edu.ie3.datamodel.models.value.PValue; -import tech.units.indriya.ComparableQuantity; - -import javax.measure.quantity.Power; -import javax.measure.quantity.Time; import java.util.Objects; import java.util.Optional; import java.util.UUID; +import javax.measure.quantity.Power; +import javax.measure.quantity.Time; +import tech.units.indriya.ComparableQuantity; public final class EmSetPoint { - public final UUID receiver; - public final Optional power; - public final Optional> delay; - - public EmSetPoint(UUID receiver) { - this.receiver = receiver; - this.power = Optional.empty(); - this.delay = Optional.empty(); - } - - public EmSetPoint(UUID receiver, ComparableQuantity p) { - this.receiver = receiver; - this.power = Optional.of(new PValue(p)); - this.delay = Optional.empty(); - } - - public EmSetPoint(UUID receiver, PValue power) { - this.receiver = receiver; - this.power = Optional.of(power); - this.delay = Optional.empty(); - } - - public EmSetPoint(UUID receiver, Optional power, Optional> delay) { - this.receiver = receiver; - this.power = power; - this.delay = delay; - } - - @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; - EmSetPoint that = (EmSetPoint) o; - return Objects.equals(receiver, that.receiver) && Objects.equals(power, that.power) && Objects.equals(delay, that.delay); - } - - @Override - public int hashCode() { - return Objects.hash(receiver, power, delay); - } - - @Override - public String toString() { - return "EmSetPoint{" + - "receiver=" + receiver + - ", power=" + power + - ", delay=" + delay + - '}'; - } + public final UUID receiver; + public final Optional power; + public final Optional> delay; + + public EmSetPoint(UUID receiver) { + this.receiver = receiver; + this.power = Optional.empty(); + this.delay = Optional.empty(); + } + + public EmSetPoint(UUID receiver, ComparableQuantity p) { + this.receiver = receiver; + this.power = Optional.of(new PValue(p)); + this.delay = Optional.empty(); + } + + public EmSetPoint(UUID receiver, PValue power) { + this.receiver = receiver; + this.power = Optional.of(power); + this.delay = Optional.empty(); + } + + public EmSetPoint( + UUID receiver, Optional power, Optional> delay) { + this.receiver = receiver; + this.power = power; + this.delay = delay; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + EmSetPoint that = (EmSetPoint) o; + return Objects.equals(receiver, that.receiver) + && Objects.equals(power, that.power) + && Objects.equals(delay, that.delay); + } + + @Override + public int hashCode() { + return Objects.hash(receiver, power, delay); + } + + @Override + public String toString() { + return "EmSetPoint{" + "receiver=" + receiver + ", power=" + power + ", delay=" + delay + '}'; + } } diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java index b0e97cd0..73474236 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java @@ -6,10 +6,10 @@ package edu.ie3.simona.api.data.em.model; -import tech.units.indriya.ComparableQuantity; - -import javax.measure.quantity.Time; import java.util.Optional; import java.util.UUID; +import javax.measure.quantity.Time; +import tech.units.indriya.ComparableQuantity; -public record FlexOptionRequest(UUID receiver, Optional sender, Optional> delay) {} +public record FlexOptionRequest( + UUID receiver, Optional sender, Optional> delay) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java index 1b5516ed..35ff3512 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java @@ -6,17 +6,16 @@ package edu.ie3.simona.api.data.em.model; -import tech.units.indriya.ComparableQuantity; - -import javax.measure.quantity.Power; -import javax.measure.quantity.Time; import java.util.Optional; import java.util.UUID; +import javax.measure.quantity.Power; +import javax.measure.quantity.Time; +import tech.units.indriya.ComparableQuantity; public record FlexOptions( - UUID receiver, - UUID sender, - ComparableQuantity pMin, - ComparableQuantity pRef, - ComparableQuantity pMax, - Optional> delay) {} + UUID receiver, + UUID sender, + ComparableQuantity pMin, + ComparableQuantity pRef, + ComparableQuantity pMax, + Optional> delay) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java index 656f1985..074ecc3f 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java @@ -7,12 +7,11 @@ package edu.ie3.simona.api.data.em.ontology; import edu.ie3.simona.api.data.em.model.EmSetPoint; - import java.util.Map; import java.util.Optional; import java.util.UUID; /** Message that provides em data (set points) from an external simulation. */ public record ProvideEmSetPointData( - long tick, Map emSetPoints, Optional maybeNextTick) + long tick, Map emSetPoints, Optional maybeNextTick) implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java index 7871463e..fb1cd2ee 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java @@ -7,12 +7,11 @@ package edu.ie3.simona.api.data.em.ontology; import edu.ie3.simona.api.data.em.model.FlexOptionRequest; - import java.util.Map; import java.util.Optional; import java.util.UUID; /** Message that provides em data (flex requests) from an external simulation. */ public record ProvideFlexRequestData( - long tick, Map flexRequests, Optional maybeNextTick) + long tick, Map flexRequests, Optional maybeNextTick) implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java deleted file mode 100644 index 0612ab61..00000000 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestControlledEmFlexResults.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * © 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.em.ontology; - -import java.util.Set; -import java.util.UUID; - -/** Request em set flex options from SIMONA via external simulation. */ -public record RequestControlledEmFlexResults(Set emEntities) - implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmSetPoints.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmSetPoints.java deleted file mode 100644 index ac78126d..00000000 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/RequestEmSetPoints.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * © 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.em.ontology; - -import java.util.List; -import java.util.UUID; - -/** Request em set points from SIMONA in the given tick. */ -public record RequestEmSetPoints(long tick, List emEntities) - implements EmDataMessageFromExt {} 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 959e4a65..3628eff7 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -6,6 +6,8 @@ package edu.ie3.simona.api.simulation; +import static java.util.Collections.emptyList; + import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.ExtDataContainerQueue; @@ -19,11 +21,8 @@ import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; import edu.ie3.simona.api.data.results.ExtResultDataConnection; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; -import org.slf4j.Logger; - import java.util.*; - -import static java.util.Collections.emptyList; +import org.slf4j.Logger; /** * Abstract class for an external co-simulation with the structure: external api - ext-co-simulation @@ -188,8 +187,8 @@ protected void sendFlexOptionsToExt( log.debug("Received results from SIMONA!"); queueToExt.queueData(new ExtResultContainer(tick, results)); log.debug("Sent results to {}", extSimulatorName); - } - + } + /** * Function to send em set point data to SIMONA using the given {@link ExtEmDataConnection}. This * method will take a value from the {@link #queueToSimona}. @@ -207,7 +206,8 @@ protected void sendEmSetPointsToSimona( ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { checkTick(tick); - Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractSetPoints); + Map inputData = + queueToSimona.takeData(ExtInputDataContainer::extractSetPoints); sendEmSetPointsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); } @@ -259,11 +259,14 @@ protected void useFlexCommunication( var options = container.extractFlexOptions(); var setPoints = container.extractSetPoints(); - extEmDataConnection.sendFlexRequests(tick, requests, maybeNextTick, log); - - extEmDataConnection.sendFlexOptions(tick, options, maybeNextTick, log); - - extEmDataConnection.sendSetPoints(tick, setPoints, maybeNextTick, log); + if (!requests.isEmpty()) + extEmDataConnection.sendFlexRequests(tick, requests, maybeNextTick, log); + + if (!options.isEmpty()) + extEmDataConnection.sendFlexOptions(tick, options, maybeNextTick, log); + + if (!setPoints.isEmpty()) + extEmDataConnection.sendSetPoints(tick, setPoints, maybeNextTick, log); log.debug("Unhandled flex requests: {}", container.flexRequestsString()); log.debug("Unhandled flex options: {}", container.flexOptionsString()); From 22121ea721ff9bcaee482626d88919d6c4eec0ea Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 12 Jun 2025 16:32:29 +0200 Subject: [PATCH 44/80] Saving changes. --- .../api/data/em/ontology/EmCompletion.java | 4 +- .../api/simulation/ExtCoSimulation.java | 79 ------------------- 2 files changed, 3 insertions(+), 80 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java index b75cd851..d35f89f9 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmCompletion.java @@ -6,4 +6,6 @@ package edu.ie3.simona.api.data.em.ontology; -public record EmCompletion() implements EmDataResponseMessageToExt {} +import java.util.Optional; + +public record EmCompletion(Optional maybeNextTick) implements EmDataResponseMessageToExt {} 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 3628eff7..081448d7 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -16,7 +16,6 @@ import edu.ie3.simona.api.data.em.EmMode; import edu.ie3.simona.api.data.em.ExtEmDataConnection; import edu.ie3.simona.api.data.em.model.EmSetPoint; -import edu.ie3.simona.api.data.em.ontology.*; import edu.ie3.simona.api.data.mapping.DataType; import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; import edu.ie3.simona.api.data.results.ExtResultDataConnection; @@ -235,84 +234,6 @@ protected void sendEmSetPointsToSimona( log.debug("Provided em set points to SIMONA!"); } - protected void useFlexCommunication( - ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) - throws InterruptedException { - // handle flex requests - boolean notFinished = true; - - while (notFinished) { - - long extTick = queueToSimona.takeData(ExtInputDataContainer::getTick); - - log.info("Current simulator tick: {}, SIMONA tick: {}", extTick, tick); - - if (tick == extTick) { - ExtInputDataContainer container = queueToSimona.takeAll(); - - log.info("Flex requests: {}", container.flexRequestsString()); - log.info("Flex options: {}", container.flexOptionsString()); - log.info("Set points: {}", container.setPointsString()); - - // send received data to SIMONA - var requests = container.extractFlexRequests(); - var options = container.extractFlexOptions(); - var setPoints = container.extractSetPoints(); - - if (!requests.isEmpty()) - extEmDataConnection.sendFlexRequests(tick, requests, maybeNextTick, log); - - if (!options.isEmpty()) - extEmDataConnection.sendFlexOptions(tick, options, maybeNextTick, log); - - if (!setPoints.isEmpty()) - extEmDataConnection.sendSetPoints(tick, setPoints, maybeNextTick, log); - - log.debug("Unhandled flex requests: {}", container.flexRequestsString()); - log.debug("Unhandled flex options: {}", container.flexOptionsString()); - log.debug("Unhandled set points: {}", container.setPointsString()); - - if (requests.isEmpty() && options.isEmpty() && setPoints.isEmpty()) { - log.info("Requesting a service completion for tick: {}.", tick); - extEmDataConnection.requestCompletion(tick); - } - - } else { - notFinished = false; - - log.info("External simulator finished tick {}. Request completion.", tick); - extEmDataConnection.requestCompletion(tick); - } - - EmDataResponseMessageToExt received = extEmDataConnection.receiveAny(); - - Map results = new HashMap<>(); - - if (received instanceof EmCompletion) { - notFinished = false; - log.info("Finished for tick: {}", tick); - - } else if (received instanceof FlexRequestResponse flexRequestResponse) { - results.putAll(flexRequestResponse.flexRequests()); - - } else if (received instanceof FlexOptionsResponse flexOptionsResponse) { - results.putAll(flexOptionsResponse.receiverToFlexOptions()); - - } else if (received instanceof EmSetPointDataResponse setPointDataResponse) { - results.putAll(setPointDataResponse.emData()); - - } else { - log.warn("Received unsupported data response: {}", received); - } - - log.warn("Results to ext: {}", results); - - ExtResultContainer resultContainer = new ExtResultContainer(tick, results, maybeNextTick); - - queueToExt.queueData(resultContainer); - } - } - // result data methods /** From b74be209dd3f09a82c28338fb0dc9d8906648fb6 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 17 Jun 2025 11:50:18 +0200 Subject: [PATCH 45/80] Saving changes. --- .../edu/ie3/simona/api/data/ExtDataContainerQueue.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java index a68c5d2f..921e690f 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java @@ -7,7 +7,10 @@ package edu.ie3.simona.api.data; import edu.ie3.simona.api.data.container.ExtDataContainer; + +import java.util.Optional; import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.TimeUnit; import java.util.function.Function; /** Data queue to allow data flow between SimonaAPI and an external simulation */ @@ -22,6 +25,10 @@ public V takeAll() throws InterruptedException { return receiverTriggerDeque.takeFirst(); } + public Optional poll(long timeout, TimeUnit unit) throws InterruptedException { + return Optional.ofNullable(receiverTriggerDeque.pollFirst(timeout, unit)); + } + public R takeData(Function extractor) throws InterruptedException { V data = receiverTriggerDeque.takeFirst(); R result = extractor.apply(data); From 9765162f9e1e092036932b58d86ced0902779a8e Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 24 Jun 2025 17:38:44 +0200 Subject: [PATCH 46/80] Saving changes. --- CHANGELOG.md | 2 + docs/readthedocs/connections/connections.md | 39 ++++ .../simulations/externalsimulation.md | 17 ++ .../api/data/ExtDataContainerQueue.java | 81 ++++++- .../data/{ => connection}/BiDirectional.java | 10 +- .../{ => connection}/ExtDataConnection.java | 2 +- .../ExtEmDataConnection.java | 35 ++-- .../ExtEvDataConnection.java | 14 +- .../ExtInputDataConnection.java | 2 +- .../ExtOutputDataConnection.java | 15 +- .../ExtPrimaryDataConnection.java | 30 +-- .../ExtResultDataConnection.java | 21 +- .../ExtResultListener.java | 16 +- .../api/data/container/ExtDataContainer.java | 13 +- .../api/data/container/ExtInputContainer.java | 194 +++++++++++++++++ .../data/container/ExtInputDataContainer.java | 125 ----------- .../data/container/ExtResultContainer.java | 33 ++- .../edu/ie3/simona/api/data/em/EmMode.java | 18 -- .../api/data/em/model/FlexOptionRequest.java | 15 -- .../simona/api/data/em/model/FlexOptions.java | 21 -- .../em/ontology/EmDataMessageFromExt.java | 2 +- .../ontology/EmDataResponseMessageToExt.java | 1 + .../em/ontology/EmSetPointDataResponse.java | 2 +- .../data/em/ontology/FlexOptionsResponse.java | 2 +- .../data/em/ontology/FlexRequestResponse.java | 2 +- .../em/ontology/ProvideEmFlexOptionData.java | 2 +- .../em/ontology/ProvideEmSetPointData.java | 2 +- .../em/ontology/ProvideFlexRequestData.java | 2 +- .../api/data/mapping/ExtEntityMapping.java | 3 + .../{em/model => model/em}/EmSetPoint.java | 18 +- .../model => model/em}/EmSetPointResult.java | 2 +- .../em}/ExtendedFlexOptionsResult.java | 2 +- .../api/data/model/em/FlexOptionRequest.java | 54 +++++ .../simona/api/data/model/em/FlexOptions.java | 43 ++++ .../model => model/em}/FlexRequestResult.java | 2 +- .../ExtDataConnectionException.java | 2 +- .../UnexpectedResponseMessageException.java | 14 ++ .../api/{data => }/mapping/DataType.java | 2 +- .../api/simulation/ExtCoSimulation.java | 73 ++++--- .../simona/api/simulation/ExtSimulation.java | 2 +- .../mapping/ExtEntityEntry.java | 5 +- .../mapping/ExtEntityFactory.java | 3 +- .../simulation/mapping/ExtEntityMapping.java | 47 +++++ .../mapping/ExtEntityMappingSource.java | 2 +- .../api/data/ExtDataContainerQueueTest.groovy | 117 +++++++++++ .../connection/ExtEmDataConnectionTest.groovy | 68 ++++++ .../ExtEvDataConnectionTest.groovy | 2 +- .../ExtPrimaryDataConnectionTest.groovy | 47 +---- .../ExtResultDataConnectionTest.groovy | 60 ++---- .../connection/ExtResultListenerTest.groovy | 48 +++++ .../container/ExtInputContainerTest.groovy | 197 ++++++++++++++++++ .../container/ExtResultContainerTest.groovy | 122 +++++++++++ .../data/em/ExtEmDataConnectionTest.groovy | 94 --------- .../api/simulation/ExtCoSimulationTest.groovy | 79 ++++--- .../api/simulation/ExtSimulationSpec.groovy | 2 +- .../mapping/ExtEntityMappingSourceTest.groovy | 4 +- .../mapping/ExtEntityMappingTest.groovy | 4 +- .../test/common/DataServiceTestData.groovy | 4 +- 58 files changed, 1300 insertions(+), 540 deletions(-) rename src/main/java/edu/ie3/simona/api/data/{ => connection}/BiDirectional.java (86%) rename src/main/java/edu/ie3/simona/api/data/{ => connection}/ExtDataConnection.java (87%) rename src/main/java/edu/ie3/simona/api/data/{em => connection}/ExtEmDataConnection.java (73%) rename src/main/java/edu/ie3/simona/api/data/{ev => connection}/ExtEvDataConnection.java (83%) rename src/main/java/edu/ie3/simona/api/data/{ => connection}/ExtInputDataConnection.java (97%) rename src/main/java/edu/ie3/simona/api/data/{ => connection}/ExtOutputDataConnection.java (65%) rename src/main/java/edu/ie3/simona/api/data/{primarydata => connection}/ExtPrimaryDataConnection.java (61%) rename src/main/java/edu/ie3/simona/api/data/{results => connection}/ExtResultDataConnection.java (85%) rename src/main/java/edu/ie3/simona/api/data/{results => connection}/ExtResultListener.java (80%) create mode 100644 src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/em/EmMode.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java rename src/main/java/edu/ie3/simona/api/data/{em/model => model/em}/EmSetPoint.java (85%) rename src/main/java/edu/ie3/simona/api/data/{em/model => model/em}/EmSetPointResult.java (97%) rename src/main/java/edu/ie3/simona/api/data/{em/model => model/em}/ExtendedFlexOptionsResult.java (98%) create mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java create mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java rename src/main/java/edu/ie3/simona/api/data/{em/model => model/em}/FlexRequestResult.java (95%) create mode 100644 src/main/java/edu/ie3/simona/api/exceptions/UnexpectedResponseMessageException.java rename src/main/java/edu/ie3/simona/api/{data => }/mapping/DataType.java (96%) rename src/main/java/edu/ie3/simona/api/{data => simulation}/mapping/ExtEntityEntry.java (86%) rename src/main/java/edu/ie3/simona/api/{data => simulation}/mapping/ExtEntityFactory.java (94%) create mode 100644 src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java rename src/main/java/edu/ie3/simona/api/{data => simulation}/mapping/ExtEntityMappingSource.java (98%) create mode 100644 src/test/groovy/edu/ie3/simona/api/data/ExtDataContainerQueueTest.groovy create mode 100644 src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy rename src/test/groovy/edu/ie3/simona/api/data/{ev => connection}/ExtEvDataConnectionTest.groovy (99%) rename src/test/groovy/edu/ie3/simona/api/data/{primarydata => connection}/ExtPrimaryDataConnectionTest.groovy (53%) rename src/test/groovy/edu/ie3/simona/api/data/{results => connection}/ExtResultDataConnectionTest.groovy (55%) create mode 100644 src/test/groovy/edu/ie3/simona/api/data/connection/ExtResultListenerTest.groovy create mode 100644 src/test/groovy/edu/ie3/simona/api/data/container/ExtInputContainerTest.groovy create mode 100644 src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy delete mode 100644 src/test/groovy/edu/ie3/simona/api/data/em/ExtEmDataConnectionTest.groovy diff --git a/CHANGELOG.md b/CHANGELOG.md index ce2509a0..e32c140e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Removed Jenkinsfile [#290](https://github.com/ie3-institute/simonaAPI/issues/290) - Adapted dependabot workflow and added CODEOWNERS [#294](https://github.com/ie3-institute/simonaAPI/issues/294) +- Refactoring external data connection [#267](https://github.com/ie3-institute/simonaAPI/issues/267) +- Refactoring data containers [#268](https://github.com/ie3-institute/simonaAPI/issues/268) ## [0.9.0] - 2025-05-09 diff --git a/docs/readthedocs/connections/connections.md b/docs/readthedocs/connections/connections.md index a48fb91a..e9a43adc 100644 --- a/docs/readthedocs/connections/connections.md +++ b/docs/readthedocs/connections/connections.md @@ -1 +1,40 @@ # Data connections + +This API defines some data connections in order to exchange data between SIMONA and an external simulation. + +1. Input data connections +2. Output data connections +3. Bidirectional data connections + +## Input data connections + +These data connections are used to provide SIMONA with external data. Each input data connection contains two references +for SIMONA actors. The first reference specifies the SIMONA service that will receive the external data. The second +reference is for the external simulation adapter. This adapter receives a message to schedule the data service in SIMONA. + +The process of sending data to the service and requesting scheduling is handled by the `sendExtMsg` method. +To send a message, simply call the method with the message as input. + +Currently, the following input data connections are provided: +- ExtPrimaryDataConnection + + +## Output data connections + +These data connections are used to provide SIMONA response messages to the external simulation. Each output data connection +has a queue for messages sent by SIMONA. The result data connection itself cannot send messages to SIMONA. + +Currently, the following input data connections are provided: +- ExtResultListener + + +## Bidirectional data connections + +The bidirectional data connection combines the functionality of both input and output data connections. These data connections +can be used to send data to SIMONA and receive responses. One additional feature is that bidirectional data connections +can be used to request responses, e.g. SIMONA results. + +Currently, the following input data connections are provided: +- ExtEmDataConnection +- ExtEvDataConnection +- ExtResultDataConnection diff --git a/docs/readthedocs/simulations/externalsimulation.md b/docs/readthedocs/simulations/externalsimulation.md index d47f1054..feddcd9f 100644 --- a/docs/readthedocs/simulations/externalsimulation.md +++ b/docs/readthedocs/simulations/externalsimulation.md @@ -32,3 +32,20 @@ method should provide a new tick as long as there are future activities. The method `getDataConnections` returns all [data connections](/connections/connections) that are used to connect the external simulation to SIMONA. + + +## Communication between SIMONA and an external simulation + +Depending on the connections used by the external simulation, the following communication structures are used: + +- Input connections: external simulation -> simonaAPI -> SIMONA +- Output connections: SIMONA -> simonaAPI -> external simulation + +Bidirectional connections can use both structures. + + +## Co-simulations + +This API provides an extension to the class `edu.ie3.simona.api.simulation.ExtSimulation` in the form of +`edu.ie3.simona.api.simulation.ExtCoSimulation`. This class contains some methods to simplify the definition of external +co-simulations. diff --git a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java index 921e690f..cbc586c0 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java @@ -7,7 +7,6 @@ package edu.ie3.simona.api.data; import edu.ie3.simona.api.data.container.ExtDataContainer; - import java.util.Optional; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; @@ -17,26 +16,102 @@ public final class ExtDataContainerQueue { private final LinkedBlockingDeque receiverTriggerDeque = new LinkedBlockingDeque<>(); + /** Returns the number of elements in this queue. */ + public int size() { + return receiverTriggerDeque.size(); + } + + /** + * Method for adding an {@link ExtDataContainer} to the queue. + * + * @param data to be added + * @throws InterruptedException if the thread running this has been interrupted during the + * blocking operation + */ public void queueData(V data) throws InterruptedException { receiverTriggerDeque.putLast(data); } - public V takeAll() throws InterruptedException { + /** + * Method to retrieve and remove an {@link ExtDataContainer} from the queue. This method waits + * (blocks) until data is added to the queue. + * + * @return a data container + * @throws InterruptedException if the thread running this has been interrupted during the + * blocking operation + */ + public V takeContainer() throws InterruptedException { return receiverTriggerDeque.takeFirst(); } - public Optional poll(long timeout, TimeUnit unit) throws InterruptedException { + /** + * Method to retrieve and remove an {@link ExtDataContainer} from the queue. This method waits + * (blocks) until either data is added to the queue or the specified wait time is reached. + * + * @param timeout maximal time to wait for data + * @param unit unit of the timeout + * @return an option for a data container + * @throws InterruptedException if the thread running this has been interrupted during the + * blocking operation + */ + public Optional pollContainer(long timeout, TimeUnit unit) throws InterruptedException { return Optional.ofNullable(receiverTriggerDeque.pollFirst(timeout, unit)); } + /** + * Method to retrieve only a part of a container from the queue. This method waits (blocks) until + * data is added to the queue. + * + * @param extractor function to extract a part of the container + * @return the extracted part + * @param type of returned value + * @throws InterruptedException if the thread running this has been interrupted during the + * blocking operation + */ public R takeData(Function extractor) throws InterruptedException { + // removes the first container from the queue V data = receiverTriggerDeque.takeFirst(); R result = extractor.apply(data); + // if the container is not empty, it should remain in the queue. + // else the container needs to be removed if (!data.isEmpty()) { receiverTriggerDeque.putFirst(data); } return result; } + + /** + * Method to retrieve only a part of a container from the queue. This method waits (blocks) until + * either data is added to the queue or the specified wait time is reached. + * + * @param extractor function to extract a part of the container + * @param timeout maximal time to wait for data + * @param unit unit of the timeout + * @return an option for the extracted part + * @param type of returned value + * @throws InterruptedException if the thread running this has been interrupted during the + * blocking operation + */ + public Optional pollData(Function extractor, long timeout, TimeUnit unit) + throws InterruptedException { + // removes the first container from the queue + Optional containerOption = pollContainer(timeout, unit); + + if (containerOption.isPresent()) { + V data = containerOption.get(); + R result = extractor.apply(data); + + // if the container is not empty, it should remain in the queue. + // else the container needs to be removed + if (!data.isEmpty()) { + receiverTriggerDeque.putFirst(data); + } + + return Optional.of(result); + } + + return Optional.empty(); + } } diff --git a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java b/src/main/java/edu/ie3/simona/api/data/connection/BiDirectional.java similarity index 86% rename from src/main/java/edu/ie3/simona/api/data/BiDirectional.java rename to src/main/java/edu/ie3/simona/api/data/connection/BiDirectional.java index 208c318e..42dc2a0e 100644 --- a/src/main/java/edu/ie3/simona/api/data/BiDirectional.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/BiDirectional.java @@ -4,10 +4,11 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data; +package edu.ie3.simona.api.data.connection; import edu.ie3.simona.api.data.ontology.DataMessageFromExt; import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; +import edu.ie3.simona.api.exceptions.UnexpectedResponseMessageException; import java.util.concurrent.LinkedBlockingQueue; /** @@ -16,7 +17,7 @@ * @param type of message to SIMONA * @param type of response messages to ext */ -public abstract class BiDirectional< +public abstract non-sealed class BiDirectional< M extends DataMessageFromExt, R extends DataResponseMessageToExt> extends ExtInputDataConnection implements ExtOutputDataConnection { @@ -27,14 +28,17 @@ protected BiDirectional() { super(); } + @Override public final void queueExtResponseMsg(R msg) throws InterruptedException { receiveTriggerQueue.put(msg); } + @Override public final R receiveAny() throws InterruptedException { return receiveTriggerQueue.take(); } + @Override @SuppressWarnings("unchecked") public final T receiveWithType(Class expectedMessageClass) throws InterruptedException { @@ -44,7 +48,7 @@ public final T receiveWithType(Class expectedMessageClass) if (msg.getClass().equals(expectedMessageClass)) { return (T) msg; } else - throw new RuntimeException( + throw new UnexpectedResponseMessageException( "Received unexpected message '" + msg + "', expected type '" diff --git a/src/main/java/edu/ie3/simona/api/data/ExtDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtDataConnection.java similarity index 87% rename from src/main/java/edu/ie3/simona/api/data/ExtDataConnection.java rename to src/main/java/edu/ie3/simona/api/data/connection/ExtDataConnection.java index 9de5c6a3..7a2f53dd 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtDataConnection.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data; +package edu.ie3.simona.api.data.connection; /** Interface that defines a data connection between SIMONA and an external simulation. */ public interface ExtDataConnection {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java similarity index 73% rename from src/main/java/edu/ie3/simona/api/data/em/ExtEmDataConnection.java rename to src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index 37691033..20d66ba4 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java @@ -4,19 +4,18 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em; +package edu.ie3.simona.api.data.connection; -import edu.ie3.simona.api.data.BiDirectional; -import edu.ie3.simona.api.data.em.model.EmSetPoint; -import edu.ie3.simona.api.data.em.model.ExtendedFlexOptionsResult; -import edu.ie3.simona.api.data.em.model.FlexOptionRequest; -import edu.ie3.simona.api.data.em.model.FlexOptions; +import edu.ie3.simona.api.data.model.em.ExtendedFlexOptionsResult; +import edu.ie3.simona.api.data.model.em.FlexOptionRequest; +import edu.ie3.simona.api.data.model.em.FlexOptions; import edu.ie3.simona.api.data.em.ontology.*; +import edu.ie3.simona.api.data.model.em.EmSetPoint; import java.util.*; import org.slf4j.Logger; /** Enables data connection of em data between SIMONA and SimonaAPI */ -public class ExtEmDataConnection +public final class ExtEmDataConnection extends BiDirectional { public final EmMode mode; @@ -45,7 +44,7 @@ public List getControlledEms() { * @param log logger */ public void sendFlexRequests( - long tick, Map data, Optional maybeNextTick, Logger log) { + long tick, Map data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No em flex requests found! Sending no em data to SIMONA for tick {}.", tick); } else { @@ -63,7 +62,7 @@ public void sendFlexRequests( * @param log logger */ public void sendFlexOptions( - long tick, Map> data, Optional maybeNextTick, Logger log) { + long tick, Map> data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No em flex options found! Sending no em data to SIMONA for tick {}.", tick); } else { @@ -76,17 +75,17 @@ public void sendFlexOptions( * Sends the em set points to SIMONA. * * @param tick current tick - * @param data to be sent + * @param setPoints to be sent * @param maybeNextTick option for the next tick in the simulation * @param log logger */ public void sendSetPoints( - long tick, Map data, Optional maybeNextTick, Logger log) { - if (data.isEmpty()) { - log.warn("No em set points found! Sending no em data to SIMONA for tick {}.", tick); + long tick, Map setPoints, Optional maybeNextTick, Logger log) { + if (setPoints.isEmpty()) { + log.debug("No em set points found! Sending no em data to SIMONA for tick {}.", tick); } else { log.debug("Provided SIMONA with em set points."); - sendExtMsg(new ProvideEmSetPointData(tick, data, maybeNextTick)); + sendExtMsg(new ProvideEmSetPointData(tick, setPoints, maybeNextTick)); } } @@ -99,7 +98,7 @@ public void sendSetPoints( * @throws InterruptedException - on interruptions */ public Map requestEmFlexResults( - long tick, List emEntities, boolean disaggregated) throws InterruptedException { + long tick, List emEntities, boolean disaggregated) throws InterruptedException { sendExtMsg(new RequestEmFlexResults(tick, emEntities, disaggregated)); return receiveWithType(FlexOptionsResponse.class).receiverToFlexOptions(); } @@ -107,4 +106,10 @@ public Map requestEmFlexResults( public void requestCompletion(long tick) { sendExtMsg(new RequestEmCompletion(tick)); } + + /** Mode of the em connection */ + public enum EmMode { + BASE, + EM_COMMUNICATION + } } diff --git a/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEvDataConnection.java similarity index 83% rename from src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java rename to src/main/java/edu/ie3/simona/api/data/connection/ExtEvDataConnection.java index 4316a5de..36f4e652 100644 --- a/src/main/java/edu/ie3/simona/api/data/ev/ExtEvDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEvDataConnection.java @@ -4,32 +4,22 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.ev; +package edu.ie3.simona.api.data.connection; -import edu.ie3.simona.api.data.BiDirectional; import edu.ie3.simona.api.data.ev.model.EvModel; import edu.ie3.simona.api.data.ev.ontology.*; -import edu.ie3.simona.api.data.ontology.DataMessageFromExt; -import edu.ie3.simona.api.simulation.ontology.ControlResponseMessageFromExt; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; -import org.apache.pekko.actor.typed.ActorRef; -public class ExtEvDataConnection +public final class ExtEvDataConnection extends BiDirectional { public ExtEvDataConnection() { super(); } - /** Actor reference to service that handles ev data within SIMONA */ - private ActorRef dataService; - - /** Actor reference to adapter that handles scheduler control flow in SIMONA */ - private ActorRef extSimAdapter; - /** * Requests currently available evcs charging stations lots from SIMONA. This method blocks until * having received a response from SIMONA. diff --git a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtInputDataConnection.java similarity index 97% rename from src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java rename to src/main/java/edu/ie3/simona/api/data/connection/ExtInputDataConnection.java index 1b073f76..8d956292 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtInputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtInputDataConnection.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data; +package edu.ie3.simona.api.data.connection; import edu.ie3.simona.api.data.ontology.DataMessageFromExt; import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; diff --git a/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java similarity index 65% rename from src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java rename to src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java index cc90641a..ca632c2b 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtOutputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data; +package edu.ie3.simona.api.data.connection; import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; @@ -14,11 +14,22 @@ * * @param type of response messages to ext */ -public interface ExtOutputDataConnection { +public sealed interface ExtOutputDataConnection + permits BiDirectional, ExtResultListener { /** Queues message from SIMONA that should be handled by the external simulation. */ void queueExtResponseMsg(T msg) throws InterruptedException; + /** + * Waits until a message of given type is added to the queue. All messages that extends the given + * type can be received. This method blocks until having received a response from SIMONA. + * + *

To receive only specific types of messages, use {@link #receiveWithType(Class)} instead. + * + * @return a message of the given type + * @throws InterruptedException if the thread running this has been interrupted during the + * blocking operation + */ T receiveAny() throws InterruptedException; /** diff --git a/src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtPrimaryDataConnection.java similarity index 61% rename from src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java rename to src/main/java/edu/ie3/simona/api/data/connection/ExtPrimaryDataConnection.java index e4ef47f4..931e3f60 100644 --- a/src/main/java/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtPrimaryDataConnection.java @@ -4,10 +4,9 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.primarydata; +package edu.ie3.simona.api.data.connection; import edu.ie3.datamodel.models.value.Value; -import edu.ie3.simona.api.data.ExtInputDataConnection; import edu.ie3.simona.api.data.primarydata.ontology.PrimaryDataMessageFromExt; import edu.ie3.simona.api.data.primarydata.ontology.ProvidePrimaryData; import java.util.List; @@ -17,7 +16,8 @@ import org.slf4j.Logger; /** Enables data connection of primary data between SIMONA and SimonaAPI */ -public class ExtPrimaryDataConnection extends ExtInputDataConnection { +public final class ExtPrimaryDataConnection + extends ExtInputDataConnection { private final Map> valueClasses; @@ -38,19 +38,21 @@ public Optional> getValueClass(UUID uuid) { return Optional.ofNullable(valueClasses.get(uuid)); } + /** + * Sends primary data from an external simulation to SIMONA + * + * @param tick current tick + * @param primaryData to be sent + * @param maybeNextTick option for the next tick in the simulation + * @param log logger + */ public void sendPrimaryData( - long tick, Map data, Optional maybeNextTick, Logger log) { - if (data.isEmpty()) { - log.warn("No primary data found! Sending no primary data to SIMONA for tick {}.", tick); + long tick, Map primaryData, Optional maybeNextTick, Logger log) { + if (primaryData.isEmpty()) { + log.debug("No primary data found! Sending no primary data to SIMONA for tick {}.", tick); } else { - log.debug("Provided SIMONA with primary data."); - log.info("Data: {}", data); - provideData(tick, data, maybeNextTick); + log.debug("Provided SIMONA with primary data. Data: {}", primaryData); + sendExtMsg(new ProvidePrimaryData(tick, primaryData, maybeNextTick)); } } - - /** Provide primary data from an external simulation in one tick. */ - public void provideData(long tick, Map primaryData, Optional maybeNextTick) { - sendExtMsg(new ProvidePrimaryData(tick, primaryData, maybeNextTick)); - } } diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtResultDataConnection.java similarity index 85% rename from src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java rename to src/main/java/edu/ie3/simona/api/data/connection/ExtResultDataConnection.java index 9ce335a4..7d2a042b 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ExtResultDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtResultDataConnection.java @@ -4,10 +4,9 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.results; +package edu.ie3.simona.api.data.connection; import edu.ie3.datamodel.models.result.ResultEntity; -import edu.ie3.simona.api.data.BiDirectional; import edu.ie3.simona.api.data.results.ontology.ProvideResultEntities; import edu.ie3.simona.api.data.results.ontology.RequestResultEntities; import edu.ie3.simona.api.data.results.ontology.ResultDataMessageFromExt; @@ -18,17 +17,17 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -/** Enables data connection of results between SIMONA and SimonaAPI */ -public class ExtResultDataConnection +/** Enables data connection of results between SIMONA and SimonaAPI. */ +public final class ExtResultDataConnection extends BiDirectional { - /** Map uuid to external id of grid related entities */ + /** Map uuid to external id of grid related entities. */ private final List gridResults; - /** Map uuid to external id of system participants */ + /** Map uuid to external id of system participants. */ private final List participantResults; - /** Map uuid to external id of participant flex options */ + /** Map uuid to external id of participant flex options. */ private final List flexResults; public ExtResultDataConnection( @@ -50,7 +49,7 @@ public List getFlexOptionAssets() { return flexResults; } - /** Method that an external simulation can request results from SIMONA as a list. */ + /** Method for requesting SIMONA results as list from an external simulation. */ private List requestResultList(long tick) throws InterruptedException { List allExtEntities = Stream.concat( @@ -76,9 +75,7 @@ private List requestParticipantResultsList(long tick) throws Inter return receiveWithType(ProvideResultEntities.class).results(); } - /** - * Method that an external simulation can request results from SIMONA as a map string to object. - */ + /** Method for requesting SIMONA results as a map uuid to object from an external simulation. */ public Map requestResults(long tick) throws InterruptedException { return createResultMap(requestResultList(tick)); } @@ -95,7 +92,7 @@ public Map requestParticipantResults(long tick) throws Inter return createResultMap(requestParticipantResultsList(tick)); } - protected Map createResultMap(List results) { + private Map createResultMap(List results) { return results.stream().collect(Collectors.toMap(ResultEntity::getInputModel, i -> i)); } } diff --git a/src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtResultListener.java similarity index 80% rename from src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java rename to src/main/java/edu/ie3/simona/api/data/connection/ExtResultListener.java index 2769c419..0a75ac57 100644 --- a/src/main/java/edu/ie3/simona/api/data/results/ExtResultListener.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtResultListener.java @@ -4,33 +4,39 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.results; +package edu.ie3.simona.api.data.connection; -import edu.ie3.simona.api.data.ExtOutputDataConnection; import edu.ie3.simona.api.data.results.ontology.ResultDataResponseMessageToExt; +import edu.ie3.simona.api.exceptions.UnexpectedResponseMessageException; import java.util.concurrent.LinkedBlockingQueue; /** * External result listener. This listener is similar to the {@link ExtResultDataConnection}, but is * not able to request results from SIMONA. */ -public class ExtResultListener implements ExtOutputDataConnection { +public non-sealed class ExtResultListener + implements ExtOutputDataConnection { /** Data message queue containing messages from SIMONA */ public final LinkedBlockingQueue receiveTriggerQueue = new LinkedBlockingQueue<>(); - public ExtResultListener() {} + public ExtResultListener() { + super(); + } + @Override public final void queueExtResponseMsg(ResultDataResponseMessageToExt msg) throws InterruptedException { receiveTriggerQueue.put(msg); } + @Override public final ResultDataResponseMessageToExt receiveAny() throws InterruptedException { return receiveTriggerQueue.take(); } + @Override @SuppressWarnings("unchecked") public final T receiveWithType( Class expectedMessageClass) throws InterruptedException { @@ -40,7 +46,7 @@ public final T receiveWithType( if (msg.getClass().equals(expectedMessageClass)) { return (T) msg; } else - throw new RuntimeException( + throw new UnexpectedResponseMessageException( "Received unexpected message '" + msg + "', expected type '" diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java index 792dc0fe..96a18846 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java @@ -10,10 +10,19 @@ import java.util.Map; /** Interface for data that are exchanged between an external simulation and SimonaAPI */ -public interface ExtDataContainer { +public sealed interface ExtDataContainer permits ExtInputContainer, ExtResultContainer { + + /** Returns true, if the container is empty. */ boolean isEmpty(); - // private helper methods + /** + * Method to copy a given map and clear the original. + * + * @param map to be copied and cleared + * @return the copy + * @param type of key + * @param type of value + */ default Map copyAndClear(Map map) { Map result = new HashMap<>(map); map.clear(); diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java new file mode 100644 index 00000000..1f8f8d26 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java @@ -0,0 +1,194 @@ +/* + * © 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.data.container; + +import edu.ie3.datamodel.models.value.PValue; +import edu.ie3.datamodel.models.value.Value; +import edu.ie3.simona.api.data.model.em.EmSetPoint; +import edu.ie3.simona.api.data.model.em.FlexOptionRequest; +import edu.ie3.simona.api.data.model.em.FlexOptions; +import java.util.*; + +/** Contains all inputs for SIMONA for a certain tick */ +public final class ExtInputContainer implements ExtDataContainer { + + /** The tick, the input data is meant for. */ + private final long tick; + + /** The next tick, when data will be provided, if available. */ + private final Optional maybeNextTick; + + // mapping for primary data + /** Map uuid to primary input value for SIMONA. */ + private final Map primaryData = new HashMap<>(); + + // mapping for em data + /** Map uuid to flex option requests. */ + private final Map flexRequests = new HashMap<>(); + + /** Map uuid to flex options. */ + private final Map> flexOptions = new HashMap<>(); + + /** Map uuid to em set points. */ + private final Map setPoints = new HashMap<>(); + + /** + * Container class for input data for SIMONA which can be read by SimonaAPI + * + * @param tick The tick, the input data is meant for + * @param nextTick tick, when the next data will be provided + */ + public ExtInputContainer(long tick, long nextTick) { + this.tick = tick; + this.maybeNextTick = Optional.of(nextTick); + } + + public ExtInputContainer(long tick) { + this.tick = tick; + this.maybeNextTick = Optional.empty(); + } + + @Override + public boolean isEmpty() { + return primaryData.isEmpty() + && flexRequests.isEmpty() + && flexOptions.isEmpty() + && setPoints.isEmpty(); + } + + /** Returns the tick the data is provided for. */ + public long getTick() { + return tick; + } + + /** Returns an option for the next tick, when data will be provided. */ + public Optional getMaybeNextTick() { + return maybeNextTick; + } + + // add data + + /** + * Method for adding primary input values for a given asset. + * + * @param asset uuid, that will receive primary data + * @param value the received value + */ + public void addPrimaryValue(UUID asset, Value value) { + primaryData.put(asset, value); + } + + /** + * Method for adding flex option requests. + * + * @param receiver the uuid of the agent, that will receive the request + * @param sender option for the uuid of the sender + */ + public void addRequest(UUID receiver, Optional sender) { + flexRequests.put(receiver, new FlexOptionRequest(receiver, sender)); + } + + public void addRequest(UUID receiver, FlexOptionRequest request) { + flexRequests.put(receiver, request); + } + + /** + * Method for adding flex options to a given receiver. + * + * @param receiver that will receive the flex options + * @param flexOption that will be added + */ + public void addFlexOptions(UUID receiver, List flexOption) { + if (!flexOptions.containsKey(receiver)) { + List flexOptionValues = new ArrayList<>(flexOption); + flexOptions.put(receiver, flexOptionValues); + } else { + flexOptions.get(receiver).addAll(flexOption); + } + } + + /** + * Method for adding an em set point for a given asset. + * + * @param asset that will receive the set point + * @param power of the set point + */ + public void addSetPoint(UUID asset, PValue power) { + setPoints.put(asset, new EmSetPoint(asset, power)); + } + + /** + * Method for adding an em set point for a given asset. + * + * @param setPoint given set point + */ + public void addSetPoint(EmSetPoint setPoint) { + setPoints.put(setPoint.receiver, setPoint); + } + + /** + * Extracts the primary input data from this container. All other input data remains unchanged. + */ + public Map extractPrimaryData() { + return copyAndClear(primaryData); + } + + /** + * Extracts the flex option request input data from this container. All other input data remains + * the same. + */ + public Map extractFlexRequests() { + return copyAndClear(flexRequests); + } + + /** + * Extracts the flex option input data from this container. All other input data remains the same. + */ + public Map> extractFlexOptions() { + return copyAndClear(flexOptions); + } + + /** + * Extracts the set point input data from this container. All other input data remains the same. + */ + public Map extractSetPoints() { + return copyAndClear(setPoints); + } + + /** + * Returns a string representation of the primary input data without changing the data. To extract + * (remove) the primary input data, use {@link #extractPrimaryData()} instead. + */ + public String primaryDataString() { + return primaryData.toString(); + } + + /** + * Returns a string representation of the flex option request input data without changing the + * data. To extract (remove) the flex option request input data, use {@link + * #extractFlexRequests()} instead. + */ + public String flexRequestsString() { + return flexRequests.toString(); + } + + /** + * Returns a string representation of the flex option input data without changing the data. To + * extract (remove) the flex option input data, use {@link #extractFlexOptions()} instead. + */ + public String flexOptionsString() { + return flexOptions.toString(); + } + + /** + * Returns a string representation of the set point input data without changing the data. To + * extract (remove) the set point input data, use {@link #extractSetPoints()} instead. + */ + public String setPointsString() { + return setPoints.toString(); + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java deleted file mode 100644 index c5abd3d7..00000000 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtInputDataContainer.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * © 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.data.container; - -import edu.ie3.datamodel.models.value.PValue; -import edu.ie3.datamodel.models.value.Value; -import edu.ie3.simona.api.data.em.model.EmSetPoint; -import edu.ie3.simona.api.data.em.model.FlexOptionRequest; -import edu.ie3.simona.api.data.em.model.FlexOptions; -import java.util.*; - -/** Contains all inputs for SIMONA for a certain tick */ -public final class ExtInputDataContainer implements ExtDataContainer { - - /** The tick, the input data is meant for */ - private final long tick; - - /** The next tick, when data will be provided, if available */ - private final Optional maybeNextTick; - - // primary map - /** Map external id to primary input value for SIMONA */ - private final Map primaryData = new HashMap<>(); - - // em maps - private final Map flexRequests = new HashMap<>(); - private final Map> flexOptions = new HashMap<>(); - private final Map setPoints = new HashMap<>(); - - /** - * Container class for input data for SIMONA which can be read by SimonaAPI - * - * @param tick The tick, the input data is meant for - * @param nextTick tick, when the next data will be provided - */ - public ExtInputDataContainer(long tick, long nextTick) { - this.tick = tick; - this.maybeNextTick = Optional.of(nextTick); - } - - public ExtInputDataContainer(long tick) { - this.tick = tick; - this.maybeNextTick = Optional.empty(); - } - - @Override - public boolean isEmpty() { - return primaryData.isEmpty() - && flexRequests.isEmpty() - && flexOptions.isEmpty() - && setPoints.isEmpty(); - } - - public long getTick() { - return tick; - } - - public Optional getMaybeNextTick() { - return maybeNextTick; - } - - // add data - public void addPrimaryValue(UUID id, Value value) { - primaryData.put(id, value); - } - - public void addRequest(UUID receiver, FlexOptionRequest request) { - flexRequests.put(receiver, request); - } - - public void addFlexOptions(UUID id, List flexOption) { - if (!flexOptions.containsKey(id)) { - List flexOptionValues = new ArrayList<>(flexOption); - flexOptions.put(id, flexOptionValues); - } else { - flexOptions.get(id).addAll(flexOption); - } - } - - public void addSetPoint(UUID id, PValue setPoint) { - setPoints.put(id, new EmSetPoint(id, setPoint)); - } - - public void addSetPoint(EmSetPoint setPoint) { - setPoints.put(setPoint.receiver, setPoint); - } - - public Map extractPrimaryData() { - return copyAndClear(primaryData); - } - - // extract and delete data - public Map extractFlexRequests() { - return copyAndClear(flexRequests); - } - - public Map> extractFlexOptions() { - return copyAndClear(flexOptions); - } - - public Map extractSetPoints() { - return copyAndClear(setPoints); - } - - // data to string - public String primaryDataString() { - return primaryData.toString(); - } - - public String flexRequestsString() { - return flexRequests.toString(); - } - - public String flexOptionsString() { - return flexOptions.toString(); - } - - public String setPointsString() { - return setPoints.toString(); - } -} diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java index d22c1ab6..8ee67c80 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java @@ -7,28 +7,31 @@ package edu.ie3.simona.api.data.container; import edu.ie3.datamodel.models.result.ResultEntity; + import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.UUID; -/** Contains all results from SIMONA for a certain tick */ -public class ExtResultContainer implements ExtDataContainer { +/** Contains all SIMONA results for a certain tick. */ +public final class ExtResultContainer implements ExtDataContainer { - /** Tick the results are meant for */ + /** Tick for which the results are meant for. */ private final long tick; - /** Tick the external simulation can expect the next results */ + /** Tick when the external simulation can expect the next results from SIMONA. */ private final Optional maybeNextTick; /** - * Map external id to result from SIMONA ATTENTION: The time stamp of the result entities is not - * necessarily corresponding to the tick + * Map uuid to result from SIMONA. + * + *

ATTENTION: The time stamp of the result entities is not necessarily corresponding to the + * tick */ private final Map resultMap; /** - * Container class for result data from SIMONA + * Container class for result data from SIMONA. * * @param tick current tick * @param resultMap results from SIMONA with external id as key @@ -49,10 +52,19 @@ public boolean isEmpty() { return resultMap.isEmpty(); } + /** Returns a map: uuid to result. */ public Map getResults() { return resultMap; } + /** + * Method to extract results of a specific type. + * + * @param clazz of the results + * @return a map: uuid to requested result, or an empty map, if no results for the requested type + * are present + * @param result type + */ @SuppressWarnings("unchecked") public Map getResults(Class clazz) { Map result = new HashMap<>(); @@ -61,6 +73,7 @@ public Map getResults(Class clazz) { ResultEntity resultEntity = entry.getValue(); if (entry.getValue().getClass().equals(clazz)) { + // add the result, if the found result is of the requested type result.put(entry.getKey(), (R) resultEntity); } } @@ -68,11 +81,13 @@ public Map getResults(Class clazz) { return result; } - public Long getTick() { + /** Returns the tick the data is provided for. */ + public long getTick() { return tick; } - public Optional getNextTick() { + /** Returns an option for the next tick, when data will be provided. */ + public Optional getMaybeNextTick() { return maybeNextTick; } diff --git a/src/main/java/edu/ie3/simona/api/data/em/EmMode.java b/src/main/java/edu/ie3/simona/api/data/em/EmMode.java deleted file mode 100644 index 6d098eca..00000000 --- a/src/main/java/edu/ie3/simona/api/data/em/EmMode.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * © 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.em; - -public enum EmMode { - BASE("base"), - EM_COMMUNICATION("emCommunication"); - - public final String mode; - - EmMode(String mode) { - this.mode = mode; - } -} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java deleted file mode 100644 index 73474236..00000000 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptionRequest.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * © 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.em.model; - -import java.util.Optional; -import java.util.UUID; -import javax.measure.quantity.Time; -import tech.units.indriya.ComparableQuantity; - -public record FlexOptionRequest( - UUID receiver, Optional sender, Optional> delay) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java deleted file mode 100644 index 35ff3512..00000000 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexOptions.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * © 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.em.model; - -import java.util.Optional; -import java.util.UUID; -import javax.measure.quantity.Power; -import javax.measure.quantity.Time; -import tech.units.indriya.ComparableQuantity; - -public record FlexOptions( - UUID receiver, - UUID sender, - ComparableQuantity pMin, - ComparableQuantity pRef, - ComparableQuantity pMax, - Optional> delay) {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataMessageFromExt.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataMessageFromExt.java index 5125e292..a5ea688c 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataMessageFromExt.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataMessageFromExt.java @@ -8,5 +8,5 @@ import edu.ie3.simona.api.data.ontology.DataMessageFromExt; -/** Messages that are sent from an external data simulation which provides em data to SIMONA */ +/** Messages that are sent from an external data simulation which provides em data to SIMONA. */ public interface EmDataMessageFromExt extends DataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataResponseMessageToExt.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataResponseMessageToExt.java index 470a6483..8f373132 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataResponseMessageToExt.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmDataResponseMessageToExt.java @@ -8,4 +8,5 @@ import edu.ie3.simona.api.data.ontology.DataResponseMessageToExt; +/** Messages that are sent from SIMONA to the external simulation that needs em data. */ public interface EmDataResponseMessageToExt extends DataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java index 3e16ae2f..d11d1069 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/EmSetPointDataResponse.java @@ -6,7 +6,7 @@ package edu.ie3.simona.api.data.em.ontology; -import edu.ie3.simona.api.data.em.model.EmSetPointResult; +import edu.ie3.simona.api.data.model.em.EmSetPointResult; import java.util.Map; import java.util.UUID; diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java index 9c2e5c96..44f46a4e 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexOptionsResponse.java @@ -6,7 +6,7 @@ package edu.ie3.simona.api.data.em.ontology; -import edu.ie3.simona.api.data.em.model.ExtendedFlexOptionsResult; +import edu.ie3.simona.api.data.model.em.ExtendedFlexOptionsResult; import java.util.Map; import java.util.UUID; diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java index 0cb8ceec..816da929 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/FlexRequestResponse.java @@ -6,7 +6,7 @@ package edu.ie3.simona.api.data.em.ontology; -import edu.ie3.simona.api.data.em.model.FlexRequestResult; +import edu.ie3.simona.api.data.model.em.FlexRequestResult; import java.util.Map; import java.util.UUID; diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java index 856fbcd5..b94136ff 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmFlexOptionData.java @@ -6,7 +6,7 @@ package edu.ie3.simona.api.data.em.ontology; -import edu.ie3.simona.api.data.em.model.FlexOptions; +import edu.ie3.simona.api.data.model.em.FlexOptions; import java.util.List; import java.util.Map; import java.util.Optional; diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java index 074ecc3f..3f2bb40b 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideEmSetPointData.java @@ -6,7 +6,7 @@ package edu.ie3.simona.api.data.em.ontology; -import edu.ie3.simona.api.data.em.model.EmSetPoint; +import edu.ie3.simona.api.data.model.em.EmSetPoint; import java.util.Map; import java.util.Optional; import java.util.UUID; diff --git a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java index fb1cd2ee..f869a438 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java +++ b/src/main/java/edu/ie3/simona/api/data/em/ontology/ProvideFlexRequestData.java @@ -6,7 +6,7 @@ package edu.ie3.simona.api.data.em.ontology; -import edu.ie3.simona.api.data.em.model.FlexOptionRequest; +import edu.ie3.simona.api.data.model.em.FlexOptionRequest; import java.util.Map; import java.util.Optional; import java.util.UUID; diff --git a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java index 7cb84314..d294e6aa 100644 --- a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java @@ -9,6 +9,9 @@ import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; + +import edu.ie3.simona.api.mapping.DataType; +import edu.ie3.simona.api.simulation.mapping.ExtEntityEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java similarity index 85% rename from src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java rename to src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java index 2164401e..c4177a04 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPoint.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java @@ -4,16 +4,18 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.model; +package edu.ie3.simona.api.data.model.em; import edu.ie3.datamodel.models.value.PValue; +import tech.units.indriya.ComparableQuantity; + +import javax.measure.quantity.Power; +import javax.measure.quantity.Time; import java.util.Objects; import java.util.Optional; import java.util.UUID; -import javax.measure.quantity.Power; -import javax.measure.quantity.Time; -import tech.units.indriya.ComparableQuantity; +/** Energy management set point that will be sent to SIMONA. */ public final class EmSetPoint { public final UUID receiver; public final Optional power; @@ -48,18 +50,16 @@ public EmSetPoint( public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; EmSetPoint that = (EmSetPoint) o; - return Objects.equals(receiver, that.receiver) - && Objects.equals(power, that.power) - && Objects.equals(delay, that.delay); + return Objects.equals(receiver, that.receiver) && Objects.equals(power, that.power); } @Override public int hashCode() { - return Objects.hash(receiver, power, delay); + return Objects.hash(receiver, power); } @Override public String toString() { - return "EmSetPoint{" + "receiver=" + receiver + ", power=" + power + ", delay=" + delay + '}'; + return "EmSetPoint{" + "receiver=" + receiver + ", power=" + power + '}'; } } diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java similarity index 97% rename from src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java rename to src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java index 9a9a3876..92dbc537 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/EmSetPointResult.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.model; +package edu.ie3.simona.api.data.model.em; import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.PValue; diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java similarity index 98% rename from src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java rename to src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java index bff7980f..fa0f9675 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/ExtendedFlexOptionsResult.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.model; +package edu.ie3.simona.api.data.model.em; import edu.ie3.datamodel.models.result.system.FlexOptionsResult; import java.time.ZonedDateTime; diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java new file mode 100644 index 00000000..dc96c847 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java @@ -0,0 +1,54 @@ +/* + * © 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.model.em; + +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import javax.measure.quantity.Time; +import tech.units.indriya.ComparableQuantity; + +public final class FlexOptionRequest { + + public final UUID receiver; + public final Optional sender; + public final Optional> delay; + + public FlexOptionRequest(UUID receiver, Optional sender) { + this.receiver = receiver; + this.sender = sender; + this.delay = Optional.empty(); + } + + public FlexOptionRequest(UUID receiver, Optional sender, Optional> delay) { + this.receiver = receiver; + this.sender = sender; + this.delay = delay; + } + + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + FlexOptionRequest that = (FlexOptionRequest) o; + return Objects.equals(receiver, that.receiver) && Objects.equals(sender, that.sender) && Objects.equals(delay, that.delay); + } + + @Override + public int hashCode() { + return Objects.hash(receiver, sender, delay); + } + + @Override + public String toString() { + return "FlexOptionRequest{" + + "receiver=" + receiver + + ", sender=" + sender + + ", delay=" + delay + + '}'; + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java new file mode 100644 index 00000000..5847b641 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java @@ -0,0 +1,43 @@ +/* + * © 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.model.em; + +import java.util.Optional; +import java.util.UUID; +import javax.measure.quantity.Power; +import javax.measure.quantity.Time; +import tech.units.indriya.ComparableQuantity; + +/** + * Flex option that will be sent to SIMONA. + * + * @param receiver uuid of the flex options + * @param sender uuid of the flex options + * @param pRef current active power + * @param pMin minimal active power + * @param pMax maximal active power + * @param delay the delay of the message + */ +public record FlexOptions( + UUID receiver, + UUID sender, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax, + Optional> delay) { + + public static FlexOptions of( + UUID receiver, + UUID sender, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax + ) { + return new FlexOptions(receiver, sender, pRef, pMin, pMax, Optional.empty()); + } + +} diff --git a/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexRequestResult.java similarity index 95% rename from src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java rename to src/main/java/edu/ie3/simona/api/data/model/em/FlexRequestResult.java index dc83a39d..64d86511 100644 --- a/src/main/java/edu/ie3/simona/api/data/em/model/FlexRequestResult.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexRequestResult.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.model; +package edu.ie3.simona.api.data.model.em; import edu.ie3.datamodel.models.result.ResultEntity; import java.time.ZonedDateTime; diff --git a/src/main/java/edu/ie3/simona/api/exceptions/ExtDataConnectionException.java b/src/main/java/edu/ie3/simona/api/exceptions/ExtDataConnectionException.java index cfa54bc1..e409729c 100644 --- a/src/main/java/edu/ie3/simona/api/exceptions/ExtDataConnectionException.java +++ b/src/main/java/edu/ie3/simona/api/exceptions/ExtDataConnectionException.java @@ -6,7 +6,7 @@ package edu.ie3.simona.api.exceptions; -import edu.ie3.simona.api.data.ExtDataConnection; +import edu.ie3.simona.api.data.connection.ExtDataConnection; public class ExtDataConnectionException extends RuntimeException { diff --git a/src/main/java/edu/ie3/simona/api/exceptions/UnexpectedResponseMessageException.java b/src/main/java/edu/ie3/simona/api/exceptions/UnexpectedResponseMessageException.java new file mode 100644 index 00000000..499dceb1 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/exceptions/UnexpectedResponseMessageException.java @@ -0,0 +1,14 @@ +/* + * © 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.exceptions; + +/** This exception is thrown, if an unexpected response message type was received. */ +public class UnexpectedResponseMessageException extends RuntimeException { + public UnexpectedResponseMessageException(String message) { + super(message); + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/mapping/DataType.java b/src/main/java/edu/ie3/simona/api/mapping/DataType.java similarity index 96% rename from src/main/java/edu/ie3/simona/api/data/mapping/DataType.java rename to src/main/java/edu/ie3/simona/api/mapping/DataType.java index cddc1626..45f1cbbd 100644 --- a/src/main/java/edu/ie3/simona/api/data/mapping/DataType.java +++ b/src/main/java/edu/ie3/simona/api/mapping/DataType.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.mapping; +package edu.ie3.simona.api.mapping; import edu.ie3.datamodel.exceptions.ParsingException; 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 081448d7..6bd2fd6f 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -6,34 +6,33 @@ package edu.ie3.simona.api.simulation; -import static java.util.Collections.emptyList; - import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.ExtDataContainerQueue; -import edu.ie3.simona.api.data.container.ExtInputDataContainer; +import edu.ie3.simona.api.data.connection.ExtEmDataConnection; +import edu.ie3.simona.api.data.connection.ExtPrimaryDataConnection; +import edu.ie3.simona.api.data.connection.ExtResultDataConnection; +import edu.ie3.simona.api.data.container.ExtInputContainer; import edu.ie3.simona.api.data.container.ExtResultContainer; -import edu.ie3.simona.api.data.em.EmMode; -import edu.ie3.simona.api.data.em.ExtEmDataConnection; -import edu.ie3.simona.api.data.em.model.EmSetPoint; -import edu.ie3.simona.api.data.mapping.DataType; -import edu.ie3.simona.api.data.primarydata.ExtPrimaryDataConnection; -import edu.ie3.simona.api.data.results.ExtResultDataConnection; +import edu.ie3.simona.api.data.model.em.EmSetPoint; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; -import java.util.*; +import edu.ie3.simona.api.mapping.DataType; import org.slf4j.Logger; +import java.util.*; + +import static java.util.Collections.emptyList; + /** - * Abstract class for an external co-simulation with the structure: external api - ext-co-simulation - * - ext-simulation - simonaAPI - simona + * Abstract class for an external co-simulation with bidirectional communication with SIMONA. * - *

It contains all function to transfer primary data and em data to SIMONA and results to the - * external co-simulation. + *

It contains functions to simplify the transfer of primary data and em data to SIMONA and + * results to the external co-simulation. */ public abstract class ExtCoSimulation extends ExtSimulation { /** Queue for the data connection from the external co-simulation to SimonaAPI */ - protected final ExtDataContainerQueue queueToSimona; + protected final ExtDataContainerQueue queueToSimona; /** Queue for the data connection from SimonaAPI to the external co-simulation */ protected final ExtDataContainerQueue queueToExt; @@ -78,16 +77,18 @@ public static ExtPrimaryDataConnection buildPrimaryConnection( * @return an ext em data connection */ public static ExtEmDataConnection buildEmConnection( - List controlled, EmMode mode, Logger log) { + List controlled, ExtEmDataConnection.EmMode mode, Logger log) { if (controlled.isEmpty()) { log.warn("Em data connection with 0 controlled entities created. This might lead to errors!"); + throw new ExtDataConnectionException(ExtEmDataConnection.class); } else { - log.info("Em data connection with {} controlled entities created.", controlled.size()); - } - - log.info("Em mode: {}", mode); + log.info( + "Em data connection with mode '{}' and {} controlled entities created.", + mode, + controlled.size()); - return new ExtEmDataConnection(controlled, mode); + return new ExtEmDataConnection(controlled, mode); + } } /** @@ -118,7 +119,7 @@ public static ExtResultDataConnection buildResultConnection( } private void checkTick(long expectedTick) throws InterruptedException { - long dataTick = queueToSimona.takeData(ExtInputDataContainer::getTick); + long dataTick = queueToSimona.takeData(ExtInputContainer::getTick); if (dataTick != expectedTick) { throw new RuntimeException( @@ -140,18 +141,18 @@ private void checkTick(long expectedTick) throws InterruptedException { * @param log logger */ protected void sendPrimaryDataToSimona( - ExtPrimaryDataConnection extPrimaryDataConnection, - long tick, - Optional maybeNextTick, - Logger log) - throws InterruptedException { + ExtPrimaryDataConnection extPrimaryDataConnection, + long tick, + Optional maybeNextTick, + Logger log) + throws InterruptedException { checkTick(tick); - Map inputData = queueToSimona.takeData(ExtInputDataContainer::extractPrimaryData); + Map inputData = queueToSimona.takeData(ExtInputContainer::extractPrimaryData); sendPrimaryDataToSimona(extPrimaryDataConnection, tick, inputData, maybeNextTick, log); } /** - * Function to send primary data to SIMONA using the given {@link ExtPrimaryDataConnection}. + * Function to send primary data to SIMONA using ExtPrimaryData * * @param extPrimaryDataConnection the connection to SIMONA * @param tick for which data is sent @@ -202,24 +203,22 @@ protected void sendFlexOptionsToExt( * @throws InterruptedException if the fetching of data is interrupted */ protected void sendEmSetPointsToSimona( - ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) - throws InterruptedException { + ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) + throws InterruptedException { checkTick(tick); Map inputData = - queueToSimona.takeData(ExtInputDataContainer::extractSetPoints); + queueToSimona.takeData(ExtInputContainer::extractSetPoints); sendEmSetPointsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); } /** - * Function to send em set point 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. + * 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. * * @param extEmDataConnection the connection to SIMONA * @param tick for which data is sent - * @param setPoints map: id to value + * @param setPoints map: id to set point * @param maybeNextTick option for the next tick data is sent * @param log logger */ diff --git a/src/main/java/edu/ie3/simona/api/simulation/ExtSimulation.java b/src/main/java/edu/ie3/simona/api/simulation/ExtSimulation.java index 0e52a819..71c1b98b 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtSimulation.java @@ -6,7 +6,7 @@ package edu.ie3.simona.api.simulation; -import edu.ie3.simona.api.data.ExtDataConnection; +import edu.ie3.simona.api.data.connection.ExtDataConnection; import edu.ie3.simona.api.simulation.ontology.*; import java.util.Optional; import java.util.Set; diff --git a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityEntry.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java similarity index 86% rename from src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityEntry.java rename to src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java index b986dac4..52f5bff2 100644 --- a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityEntry.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java @@ -4,10 +4,11 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.mapping; +package edu.ie3.simona.api.simulation.mapping; import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; import edu.ie3.datamodel.models.input.InputEntity; +import edu.ie3.simona.api.mapping.DataType; import java.util.Optional; import java.util.UUID; @@ -16,7 +17,7 @@ * * @param uuid SIMONA uuid * @param id external id - * @param columnScheme option for data types the external asset expects + * @param columnScheme data types the external asset expects * @param dataType data types the external asset expects */ public record ExtEntityEntry( diff --git a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityFactory.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java similarity index 94% rename from src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityFactory.java rename to src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java index cdbc2eef..4b79cca4 100644 --- a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityFactory.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityFactory.java @@ -4,13 +4,14 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.mapping; +package edu.ie3.simona.api.simulation.mapping; import edu.ie3.datamodel.exceptions.FactoryException; import edu.ie3.datamodel.exceptions.ParsingException; import edu.ie3.datamodel.io.factory.EntityData; import edu.ie3.datamodel.io.factory.EntityFactory; import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; +import edu.ie3.simona.api.mapping.DataType; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; 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 new file mode 100644 index 00000000..6976be08 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java @@ -0,0 +1,47 @@ +/* + * © 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.simulation.mapping; + +import edu.ie3.simona.api.mapping.DataType; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; + +/** Contains the mapping between SIMONA uuid, the external id and the data type the assets hold */ +public class ExtEntityMapping { + + private final Map> extEntities; + + public ExtEntityMapping(List extEntityEntryList) { + this.extEntities = + extEntityEntryList.stream().collect(Collectors.groupingBy(ExtEntityEntry::dataType)); + } + + /** + * Mapping external id to SIMONA uuid + * + * @param dataType data type the external asset expects + * @return Mapping external id to SIMONA uuid + */ + public Map getExtId2UuidMapping(DataType dataType) { + return extEntities.getOrDefault(dataType, Collections.emptyList()).stream() + .collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); + } + + /** + * Mapping SIMONA uuid to external id + * + * @param dataType data type the external asset expects + * @return Mapping SIMONA uuid to external id + */ + public Map getExtUuid2IdMapping(DataType dataType) { + return extEntities.getOrDefault(dataType, Collections.emptyList()).stream() + .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMappingSource.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java similarity index 98% rename from src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMappingSource.java rename to src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java index 34c37d31..1d24d7ff 100644 --- a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMappingSource.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.mapping; +package edu.ie3.simona.api.simulation.mapping; import edu.ie3.datamodel.exceptions.SourceException; import edu.ie3.datamodel.io.factory.EntityData; diff --git a/src/test/groovy/edu/ie3/simona/api/data/ExtDataContainerQueueTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/ExtDataContainerQueueTest.groovy new file mode 100644 index 00000000..5375f0bb --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/ExtDataContainerQueueTest.groovy @@ -0,0 +1,117 @@ +package edu.ie3.simona.api.data + +import edu.ie3.datamodel.models.value.PValue +import edu.ie3.datamodel.models.value.Value +import edu.ie3.simona.api.data.container.ExtInputContainer +import edu.ie3.util.quantities.PowerSystemUnits +import spock.lang.Shared +import spock.lang.Specification +import tech.units.indriya.quantity.Quantities + +import java.util.concurrent.TimeUnit + +class ExtDataContainerQueueTest extends Specification { + + @Shared + private UUID uuid = UUID.fromString("07a724f6-c226-4826-87a6-e9ae42b734b0") + + @Shared + private Value value = new PValue(Quantities.getQuantity(10, PowerSystemUnits.KILOWATT)) + + def "An ExtDataContainerQueue should queue data as expected"() { + given: + def queue = new ExtDataContainerQueue() + def data = new ExtInputContainer(0L, 3600L) + + when: + queue.queueData(data) + + then: + queue.size() == 1 + } + + def "An ExtDataContainerQueue should take a container as expected"() { + given: + def queue = new ExtDataContainerQueue() + def data = new ExtInputContainer(0L, 3600L) + queue.queueData(data) + + when: + def container = queue.takeContainer() + + then: + container == data + queue.size() == 0 + } + + def "An ExtDataContainerQueue should poll no container, if queue remains empty"() { + given: + def queue = new ExtDataContainerQueue() + + when: + def container = queue.pollContainer(10, TimeUnit.MILLISECONDS) + + then: + container == Optional.empty() + queue.size() == 0 + } + + def "An ExtDataContainerQueue should poll a container, if queue contains data"() { + given: + def queue = new ExtDataContainerQueue() + def data = new ExtInputContainer(0L, 3600L) + queue.queueData(data) + + when: + def container = queue.pollContainer(10, TimeUnit.MILLISECONDS) + + then: + container == Optional.of(data) + queue.size() == 0 + } + + def "An ExtDataContainerQueue should take part of a container as expected"() { + given: + def queue = new ExtDataContainerQueue() + def data = new ExtInputContainer(0L, 3600L) + data.addPrimaryValue(uuid, value) + + queue.queueData(data) + + when: + def primaryData = queue.takeData(ExtInputContainer::extractPrimaryData) + + then: + primaryData == [(uuid): value] + queue.size() == 0 + } + + def "An ExtDataContainerQueue should poll no part of a container, if queue remains empty"() { + given: + def queue = new ExtDataContainerQueue() + + when: + def primaryData = queue.pollData(ExtInputContainer::extractPrimaryData, 10, TimeUnit.MILLISECONDS) + + then: + primaryData == Optional.empty() + queue.size() == 0 + } + + def "An ExtDataContainerQueue should poll part of a container, if queue contains data"() { + given: + def queue = new ExtDataContainerQueue() + def data = new ExtInputContainer(0L, 3600L) + data.addPrimaryValue(uuid, value) + + queue.queueData(data) + + when: + def primaryData = queue.pollData(ExtInputContainer::extractPrimaryData, 10, TimeUnit.MILLISECONDS) + + then: + primaryData == Optional.of([(uuid): value]) + queue.size() == 0 + } + +} diff --git a/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy new file mode 100644 index 00000000..b11d7b03 --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy @@ -0,0 +1,68 @@ +package edu.ie3.simona.api.data.connection + +import edu.ie3.simona.api.data.connection.ExtEmDataConnection.EmMode +import edu.ie3.simona.api.data.model.em.EmSetPoint +import edu.ie3.simona.api.data.ontology.DataMessageFromExt +import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage +import edu.ie3.simona.api.data.em.ontology.ProvideEmSetPointData +import edu.ie3.simona.api.test.common.DataServiceTestData +import org.apache.pekko.actor.testkit.typed.javadsl.ActorTestKit +import spock.lang.Shared +import spock.lang.Specification + +class ExtEmDataConnectionTest extends Specification implements DataServiceTestData { + + @Shared + ActorTestKit testKit + + @Shared + List controlled = [inputUuid] + + def setupSpec() { + testKit = ActorTestKit.create() + } + + def cleanupSpec() { + testKit.shutdownTestKit() + testKit = null + } + + def "ExtEmDataConnection should provide em data correctly"() { + given: + def dataService = testKit.createTestProbe(DataMessageFromExt) + def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) + def extEmDataConnection = new ExtEmDataConnection(controlled, EmMode.BASE) + extEmDataConnection.setActorRefs( + dataService.ref(), + extSimAdapter.ref() + ) + + def emData = Map.of(inputUuid, new EmSetPoint(inputUuid, pValue)) + + when: + extEmDataConnection.sendSetPoints(0L, emData, Optional.of(900L), log) + + then: + dataService.expectMessage(new ProvideEmSetPointData(0, emData, Optional.of(900L))) + extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) + } + + def "ExtEmDataConnection should send no message, if input data is empty"() { + given: + def dataService = testKit.createTestProbe(DataMessageFromExt) + def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) + def extEmDataConnection = new ExtEmDataConnection(controlled, EmMode.BASE) + extEmDataConnection.setActorRefs( + dataService.ref(), + extSimAdapter.ref() + ) + def inputDataMap = [:] as Map + + when: + extEmDataConnection.sendSetPoints(0L, inputDataMap, Optional.of(900L), log) + + then: + dataService.expectNoMessage() + } + +} diff --git a/src/test/groovy/edu/ie3/simona/api/data/ev/ExtEvDataConnectionTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEvDataConnectionTest.groovy similarity index 99% rename from src/test/groovy/edu/ie3/simona/api/data/ev/ExtEvDataConnectionTest.groovy rename to src/test/groovy/edu/ie3/simona/api/data/connection/ExtEvDataConnectionTest.groovy index ea925b95..581efacc 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/ev/ExtEvDataConnectionTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEvDataConnectionTest.groovy @@ -1,4 +1,4 @@ -package edu.ie3.simona.api.data.ev +package edu.ie3.simona.api.data.connection import edu.ie3.simona.api.data.ev.model.EvModel import edu.ie3.simona.api.data.ev.ontology.* diff --git a/src/test/groovy/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnectionTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtPrimaryDataConnectionTest.groovy similarity index 53% rename from src/test/groovy/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnectionTest.groovy rename to src/test/groovy/edu/ie3/simona/api/data/connection/ExtPrimaryDataConnectionTest.groovy index f337691f..0cbb19c2 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/primarydata/ExtPrimaryDataConnectionTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtPrimaryDataConnectionTest.groovy @@ -1,5 +1,6 @@ -package edu.ie3.simona.api.data.primarydata +package edu.ie3.simona.api.data.connection +import edu.ie3.datamodel.models.value.PValue import edu.ie3.datamodel.models.value.Value import edu.ie3.simona.api.data.ontology.DataMessageFromExt import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage @@ -15,10 +16,7 @@ class ExtPrimaryDataConnectionTest extends Specification implements DataServiceT ActorTestKit testKit @Shared - Map extPrimaryDataMapping = Map.of( - "Pv", - inputUuid - ) + Map> assetToValueClasses = [ (inputUuid): PValue] as Map def setupSpec() { testKit = ActorTestKit.create() @@ -33,58 +31,35 @@ class ExtPrimaryDataConnectionTest extends Specification implements DataServiceT given: def dataService = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extPrimaryDataConnection = new ExtPrimaryDataConnection(extPrimaryDataMapping) + def extPrimaryDataConnection = new ExtPrimaryDataConnection(assetToValueClasses) extPrimaryDataConnection.setActorRefs( dataService.ref(), extSimAdapter.ref() ) - def primaryData = [:] as HashMap - def uuid = UUID.randomUUID() - primaryData.put(uuid.toString(), pValue) - - def convertedPrimaryData = Map.of(uuid, pValue as Value) - - when: - extPrimaryDataConnection.provideData(0L, convertedPrimaryData, Optional.of(900L)) - - then: - dataService.expectMessage(new ProvidePrimaryData(0L, convertedPrimaryData, Optional.of(900L))) - extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) - } - - def "ExtPrimaryDataConnection should convert input data correctly"() { - given: - def dataService = testKit.createTestProbe(DataMessageFromExt) - def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extPrimaryDataConnection = new ExtPrimaryDataConnection(extPrimaryDataMapping) - extPrimaryDataConnection.setActorRefs( - dataService.ref(), - extSimAdapter.ref() - ) - def inputDataMap = Map.of("Pv", pValue) + def primaryData = Map.of(inputUuid, pValue as Value) when: - extPrimaryDataConnection.convertAndSend(0L, inputDataMap, Optional.of(900L), log) + extPrimaryDataConnection.sendPrimaryData(0L, primaryData, Optional.of(900L), log) then: - dataService.expectMessage(new ProvidePrimaryData(0L, Map.of(inputUuid, pValue), Optional.of(900L))) + dataService.expectMessage(new ProvidePrimaryData(0L, primaryData, Optional.of(900L))) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) } - def "ExtPrimaryDataConnection should send no message, if input data for a not requested asset was provided"() { + def "ExtPrimaryDataConnection should send no message, if input data is empty"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extPrimaryDataConnection = new ExtPrimaryDataConnection(extPrimaryDataMapping) + def extPrimaryDataConnection = new ExtPrimaryDataConnection(assetToValueClasses) extPrimaryDataConnection.setActorRefs( dataService.ref(), extSimAdapter.ref() ) - def inputDataMap = Map.of("Load", pValue) + def inputDataMap = [:] when: - extPrimaryDataConnection.convertAndSend(0L, inputDataMap, Optional.empty(), log) + extPrimaryDataConnection.sendPrimaryData(0L, inputDataMap, Optional.empty(), log) then: dataService.expectNoMessage() diff --git a/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultDataConnectionTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtResultDataConnectionTest.groovy similarity index 55% rename from src/test/groovy/edu/ie3/simona/api/data/results/ExtResultDataConnectionTest.groovy rename to src/test/groovy/edu/ie3/simona/api/data/connection/ExtResultDataConnectionTest.groovy index da4880a5..97cb81ba 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/results/ExtResultDataConnectionTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtResultDataConnectionTest.groovy @@ -1,26 +1,14 @@ -package edu.ie3.simona.api.data.results +package edu.ie3.simona.api.data.connection -import edu.ie3.datamodel.models.StandardUnits -import edu.ie3.datamodel.models.result.connector.LineResult import edu.ie3.simona.api.data.ontology.DataMessageFromExt import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage import edu.ie3.simona.api.data.results.ontology.ProvideResultEntities import edu.ie3.simona.api.data.results.ontology.RequestResultEntities import edu.ie3.simona.api.data.results.ontology.ResultDataResponseMessageToExt -import edu.ie3.simona.api.simulation.ExtSimulation import edu.ie3.simona.api.test.common.DataServiceTestData -import org.apache.pekko.actor.ActorSystem import org.apache.pekko.actor.testkit.typed.javadsl.ActorTestKit -import org.apache.pekko.testkit.TestProbe -import org.apache.pekko.testkit.javadsl.TestKit import spock.lang.Shared import spock.lang.Specification -import tech.units.indriya.quantity.Quantities - -import javax.measure.Quantity -import javax.measure.quantity.Angle -import javax.measure.quantity.ElectricCurrent -import java.time.ZonedDateTime class ExtResultDataConnectionTest extends Specification implements DataServiceTestData { @@ -28,13 +16,13 @@ class ExtResultDataConnectionTest extends Specification implements DataServiceTe ActorTestKit testKit @Shared - Map participantResultAssetMapping = Map.of(inputUuid, "Load") + List participantResultAssets = [inputUuid] @Shared - Map gridResultAssetMapping = [:] + List gridResultAssets = [] @Shared - Map flexResultAssetMapping = [:] + List flexResultAssets = [] class WrongResultDataResponseMessageToExt implements ResultDataResponseMessageToExt {} @@ -50,12 +38,10 @@ class ExtResultDataConnectionTest extends Specification implements DataServiceTe def "ExtResultsData should request and receive results correctly as ModelResultEntity"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) - def dataServiceActivation = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extResultDataConnection = new ExtResultDataConnection(participantResultAssetMapping, gridResultAssetMapping) + def extResultDataConnection = new ExtResultDataConnection(participantResultAssets, gridResultAssets, flexResultAssets) extResultDataConnection.setActorRefs( dataService.ref(), - dataServiceActivation.ref(), extSimAdapter.ref() ) @@ -67,20 +53,18 @@ class ExtResultDataConnectionTest extends Specification implements DataServiceTe def receivedResults = extResultDataConnection.requestResults(0L) then: - dataService.expectMessage(new RequestResultEntities(0L)) - extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataServiceActivation.ref())) - receivedResults.get("Load") == loadResult + dataService.expectMessage(new RequestResultEntities(0L, [inputUuid])) + extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) + receivedResults.get(inputUuid) == loadResult } def "ExtResultsData should fail if wrong response is sent"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) - def dataServiceActivation = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extResultDataConnection = new ExtResultDataConnection(participantResultAssetMapping, gridResultAssetMapping) + def extResultDataConnection = new ExtResultDataConnection(participantResultAssets, gridResultAssets, flexResultAssets) extResultDataConnection.setActorRefs( dataService.ref(), - dataServiceActivation.ref(), extSimAdapter.ref() ) @@ -92,38 +76,20 @@ class ExtResultDataConnectionTest extends Specification implements DataServiceTe extResultDataConnection.requestResults(0L) then: - dataService.expectMessage(new RequestResultEntities(0L)) - extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataServiceActivation.ref())) + dataService.expectMessage(new RequestResultEntities(0L, [inputUuid])) + extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.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, flexResultAssetMapping) + def extResultDataConnection = new ExtResultDataConnection(participantResultAssets, gridResultAssets, flexResultAssets) when: def mapOfResults = extResultDataConnection.createResultMap([loadResult]) then: mapOfResults.size() == 1 - mapOfResults.get("Load") == loadResult - } - - def "ExtResultData should throw an exception, if a result with a wrong data type was provided"() { - given: - 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) - Quantity iBAng = Quantities.getQuantity(30, StandardUnits.ELECTRIC_CURRENT_ANGLE) - def wrongResult = new LineResult( - ZonedDateTime.parse("2020-01-30T17:26:44Z"), inputUuid, iAMag, iAAng, iBMag, iBAng - ) - - when: - extResultDataConnection.createResultMap([wrongResult]) - - then: - thrown IllegalArgumentException + mapOfResults.get(inputUuid) == loadResult } } \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/simona/api/data/connection/ExtResultListenerTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtResultListenerTest.groovy new file mode 100644 index 00000000..e90beb01 --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtResultListenerTest.groovy @@ -0,0 +1,48 @@ +package edu.ie3.simona.api.data.connection + +import edu.ie3.datamodel.models.result.NodeResult +import edu.ie3.simona.api.data.results.ontology.ProvideResultEntities +import edu.ie3.simona.api.exceptions.UnexpectedResponseMessageException +import edu.ie3.simona.api.test.common.DataServiceTestData +import spock.lang.Specification + +class ExtResultListenerTest extends Specification implements DataServiceTestData { + + def "An ExtResultListener should receive any result correctly"() { + given: + ExtResultListener listener = new ExtResultListener() + + when: + listener.queueExtResponseMsg(new ProvideResultEntities([loadResult])) + + then: + ProvideResultEntities message = listener.receiveAny() + + message.results() == [loadResult] + } + + def "An ExtResultListener should receive a specific result correctly"() { + given: + ExtResultListener listener = new ExtResultListener() + + when: + listener.queueExtResponseMsg(new ProvideResultEntities([loadResult])) + + then: + def message = listener.receiveWithType(ProvideResultEntities) + + message.results() == [loadResult] + } + + def "An ExtResultListener should thrown an exception if the wrong type is received"() { + given: + ExtResultListener listener = new ExtResultListener() + + when: + listener.queueExtResponseMsg(new ProvideResultEntities([loadResult])) + listener.receiveWithType(NodeResult) + + then: + thrown(UnexpectedResponseMessageException) + } +} diff --git a/src/test/groovy/edu/ie3/simona/api/data/container/ExtInputContainerTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/container/ExtInputContainerTest.groovy new file mode 100644 index 00000000..c84a5ff3 --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/container/ExtInputContainerTest.groovy @@ -0,0 +1,197 @@ +package edu.ie3.simona.api.data.container + +import edu.ie3.datamodel.models.value.PValue +import edu.ie3.simona.api.data.model.em.EmSetPoint +import edu.ie3.simona.api.data.model.em.FlexOptionRequest +import edu.ie3.simona.api.data.model.em.FlexOptions +import spock.lang.Specification +import tech.units.indriya.quantity.Quantities + +import static edu.ie3.util.quantities.PowerSystemUnits.KILOWATT + +class ExtInputContainerTest extends Specification { + + def "An ExtInputContainer should add primary data correctly"() { + given: + UUID uuid = UUID.randomUUID() + def value = new PValue(Quantities.getQuantity(10d, KILOWATT)) + + def container = new ExtInputContainer(0L) + + when: + container.addPrimaryValue(uuid, value) + + then: + container.primaryData == [(uuid): value] + } + + def "An ExtInputContainer should add flex option request data correctly"() { + given: + UUID requester = UUID.randomUUID() + + def container = new ExtInputContainer(0L) + + when: + container.addRequest(requester, Optional.empty()) + + then: + container.flexRequests == [(requester): new FlexOptionRequest(requester, Optional.empty())] + } + + def "An ExtInputContainer should add flex option data correctly"() { + given: + UUID receiver = UUID.randomUUID() + UUID sender = UUID.randomUUID() + def flexOptions = new FlexOptions(receiver, sender, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) + + def container = new ExtInputContainer(0L) + + when: + container.addFlexOptions(receiver, [flexOptions]) + + then: + container.flexOptions == [(receiver): [flexOptions]] + } + + def "An ExtInputContainer should add set point data correctly"() { + given: + UUID uuid = UUID.randomUUID() + def power = new PValue(Quantities.getQuantity(5d, KILOWATT)) + + def container = new ExtInputContainer(0L) + + when: + container.addSetPoint(uuid, power) + + then: + container.setPoints == [(uuid): new EmSetPoint(uuid, power)] + } + + def "An ExtInputContainer should extract primary data correctly"() { + given: + def container = new ExtInputContainer(0L) + + UUID primaryUuid = UUID.randomUUID() + PValue primaryValue = new PValue(Quantities.getQuantity(10d, KILOWATT)) + container.addPrimaryValue(primaryUuid, primaryValue) + + UUID requestReceiver = UUID.randomUUID() + container.addRequest(requestReceiver, Optional.empty()) + + UUID receiver = UUID.randomUUID() + def flexOptions = new FlexOptions(receiver, UUID.randomUUID(), Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) + container.addFlexOptions(receiver, [flexOptions]) + + UUID emAsset = UUID.randomUUID() + def setPoint = new PValue(Quantities.getQuantity(5d, KILOWATT)) + container.addSetPoint(emAsset, setPoint) + + when: + def extracted = container.extractPrimaryData() + + then: + extracted.size() == 1 + extracted == [(primaryUuid): primaryValue] + + container.primaryData.size() == 0 + container.flexRequests.size() == 1 + container.flexOptions.size() == 1 + container.setPoints.size() == 1 + } + + def "An ExtInputContainer should extract flex option request data correctly"() { + given: + def container = new ExtInputContainer(0L) + + UUID primaryUuid = UUID.randomUUID() + PValue primaryValue = new PValue(Quantities.getQuantity(10d, KILOWATT)) + container.addPrimaryValue(primaryUuid, primaryValue) + + UUID requestReceiver = UUID.randomUUID() + container.addRequest(requestReceiver, Optional.empty()) + + UUID receiver = UUID.randomUUID() + def flexOptions = new FlexOptions(receiver, UUID.randomUUID(), Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) + container.addFlexOptions(receiver, [flexOptions]) + + UUID emAsset = UUID.randomUUID() + def setPoint = new PValue(Quantities.getQuantity(5d, KILOWATT)) + container.addSetPoint(emAsset, setPoint) + + when: + def extracted = container.extractFlexRequests() + + then: + extracted.size() == 1 + extracted == [(requestReceiver): new FlexOptionRequest(requestReceiver, Optional.empty())] + + container.primaryData.size() == 1 + container.flexRequests.size() == 0 + container.flexOptions.size() == 1 + container.setPoints.size() == 1 + } + + def "An ExtInputContainer should extract flex option data correctly"() { + given: + def container = new ExtInputContainer(0L) + + UUID primaryUuid = UUID.randomUUID() + PValue primaryValue = new PValue(Quantities.getQuantity(10d, KILOWATT)) + container.addPrimaryValue(primaryUuid, primaryValue) + + UUID requestReceiver = UUID.randomUUID() + container.addRequest(requestReceiver, Optional.empty()) + + UUID receiver = UUID.randomUUID() + def flexOptions = new FlexOptions(receiver, UUID.randomUUID(), Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) + container.addFlexOptions(receiver, [flexOptions]) + + UUID emAsset = UUID.randomUUID() + def setPoint = new PValue(Quantities.getQuantity(5d, KILOWATT)) + container.addSetPoint(emAsset, setPoint) + + when: + def extracted = container.extractFlexOptions() + + then: + extracted.size() == 1 + extracted == [(receiver): [flexOptions]] + + container.primaryData.size() == 1 + container.flexRequests.size() == 1 + container.flexOptions.size() == 0 + container.setPoints.size() == 1 + } + + def "An ExtInputContainer should extract set points data correctly"() { + given: + def container = new ExtInputContainer(0L) + + UUID primaryUuid = UUID.randomUUID() + PValue primaryValue = new PValue(Quantities.getQuantity(10d, KILOWATT)) + container.addPrimaryValue(primaryUuid, primaryValue) + + UUID requestReceiver = UUID.randomUUID() + container.addRequest(requestReceiver, Optional.empty()) + + UUID receiver = UUID.randomUUID() + def flexOptions = new FlexOptions(receiver, UUID.randomUUID(), Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) + container.addFlexOptions(receiver, [flexOptions]) + + UUID emAsset = UUID.randomUUID() + def power = new PValue(Quantities.getQuantity(5d, KILOWATT)) + container.addSetPoint(emAsset, power) + + when: + def extracted = container.extractSetPoints() + + then: + extracted.size() == 1 + extracted == [(emAsset): new EmSetPoint(emAsset, power)] + + container.primaryData.size() == 1 + container.flexRequests.size() == 1 + container.flexOptions.size() == 1 + container.setPoints.size() == 0 + } +} diff --git a/src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy new file mode 100644 index 00000000..5838da4d --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy @@ -0,0 +1,122 @@ +package edu.ie3.simona.api.data.container + +import edu.ie3.datamodel.models.StandardUnits +import edu.ie3.datamodel.models.result.NodeResult +import edu.ie3.datamodel.models.result.system.FlexOptionsResult +import edu.ie3.datamodel.models.result.system.LoadResult +import edu.ie3.simona.api.test.common.DataServiceTestData +import edu.ie3.util.quantities.PowerSystemUnits +import spock.lang.Shared +import spock.lang.Specification +import tech.units.indriya.quantity.Quantities + +import java.time.ZonedDateTime + +class ExtResultContainerTest extends Specification implements DataServiceTestData { + + @Shared + UUID nodeUuid = UUID.fromString("55b97041-64be-4e6b-983a-72dbde6eddf4") + + @Shared + NodeResult nodeResult = new NodeResult( + ZonedDateTime.parse("2020-01-30T17:26:44Z"), + nodeUuid, + Quantities.getQuantity(0.95, PowerSystemUnits.PU), + Quantities.getQuantity(45, StandardUnits.VOLTAGE_ANGLE) + ) + + def "ExtResultContainer should return all results correctly"() { + given: + def expected = [ + (nodeUuid): nodeResult, + (inputUuid): loadResult + ] + + def container = new ExtResultContainer(0L, expected) + + expect: + container.getResults() == expected + } + + def "ExtResultContainer should return specific results correctly"() { + given: + def expected = [ + (nodeUuid): nodeResult, + (inputUuid): loadResult + ] + + def container = new ExtResultContainer(0L, expected) + + when: + def nodeResults = container.getResults(NodeResult) + def loadResults = container.getResults(LoadResult) + def flexOptionsResults = container.getResults(FlexOptionsResult) + + then: + nodeResults == [(nodeUuid): nodeResult] + loadResults == [(inputUuid): loadResult] + flexOptionsResults == [:] + } + + def "ExtResultContainer should return voltage deviation correctly"() { + given: + def resultMap = Map.of(nodeUuid, nodeResult) + def extResultContainer = new ExtResultContainer(0L, resultMap) + + when: + def calculatedVoltageDeviation = extResultContainer.getVoltageDeviation(nodeUuid) + + then: + calculatedVoltageDeviation == -0.05d + } + + def "ExtResultContainer should throw an exception, if voltage deviation was requested for a not NodeResult"() { + given: + def resultMap = Map.of(inputUuid, loadResult) + def extResultContainer = new ExtResultContainer(0L, resultMap) + + when: + extResultContainer.getVoltageDeviation(inputUuid) + + then: + thrown IllegalArgumentException + } + + def "ExtResultContainer should return active power correctly"() { + given: + def resultMap = Map.of(inputUuid, loadResult) + def extResultContainer = new ExtResultContainer(0L, resultMap) + + when: + def returnedActivePower = extResultContainer.getActivePower(inputUuid) + + then: + returnedActivePower == 10d + } + + def "ExtResultContainer should return reactive power correctly"() { + given: + def resultMap = Map.of(inputUuid, loadResult) + def extResultContainer = new ExtResultContainer(0L, resultMap) + + when: + def returnedReactivePower = extResultContainer.getReactivePower(inputUuid) + + then: + returnedReactivePower == 5d + } + + def "ExtResultContainer should throw an exception, if active power was requested for a not SystemParticipantResult"() { + given: + def resultMap = Map.of( + nodeUuid, nodeResult + ) + def extResultContainer = new ExtResultContainer(0L, resultMap) + + when: + extResultContainer.getActivePower(nodeUuid) + + then: + thrown IllegalArgumentException + } +} \ No newline at end of file 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 deleted file mode 100644 index d3bed063..00000000 --- a/src/test/groovy/edu/ie3/simona/api/data/em/ExtEmDataConnectionTest.groovy +++ /dev/null @@ -1,94 +0,0 @@ -package edu.ie3.simona.api.data.em - -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.DataMessageFromExt -import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage -import edu.ie3.simona.api.test.common.DataServiceTestData -import org.apache.pekko.actor.testkit.typed.javadsl.ActorTestKit -import spock.lang.Shared -import spock.lang.Specification - -class ExtEmDataConnectionTest extends Specification implements DataServiceTestData { - - @Shared - ActorTestKit testKit - - @Shared - Map extEmDataMapping = Map.of( - "Em", - inputUuid - ) - - def setupSpec() { - testKit = ActorTestKit.create() - } - - def cleanupSpec() { - testKit.shutdownTestKit() - testKit = null - } - - def "ExtEmDataConnection should provide em data correctly"() { - given: - def dataService = testKit.createTestProbe(DataMessageFromExt) - def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extEmDataConnection = new ExtEmDataConnection(extEmDataMapping) - extEmDataConnection.setActorRefs( - dataService.ref(), - extSimAdapter.ref() - ) - - def emData = [:] as HashMap - def uuid = UUID.randomUUID() - emData.put(uuid.toString(), pValue) - - def convertedEmData = Map.of(uuid, pValue as PValue) - - when: - extEmDataConnection.provideData(0L, convertedEmData, Optional.of(900L)) - - then: - dataService.expectMessage(new ProvideEmSetPointData(0, convertedEmData, Optional.of(900L))) - extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) - } - - def "ExtEmDataConnection should convert input data correctly"() { - given: - def dataService = testKit.createTestProbe(DataMessageFromExt) - def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extEmDataConnection = new ExtEmDataConnection(extEmDataMapping) - extEmDataConnection.setActorRefs( - dataService.ref(), - extSimAdapter.ref() - ) - def inputDataMap = Map.of("Em", pValue) - - when: - extEmDataConnection.convertAndSend(0L, inputDataMap, Optional.of(900L), log) - - then: - dataService.expectMessage(new ProvideEmSetPointData(0L, Map.of(inputUuid, pValue), Optional.of(900L))) - extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) - } - - def "ExtEmDataConnection should send no message, if input data for a not requested asset was provided"() { - given: - def dataService = testKit.createTestProbe(DataMessageFromExt) - def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extEmDataConnection = new ExtEmDataConnection(extEmDataMapping) - extEmDataConnection.setActorRefs( - dataService.ref(), - extSimAdapter.ref() - ) - def inputDataMap = Map.of("Load", pValue) - - when: - extEmDataConnection.convertAndSend(0L, inputDataMap, Optional.of(900L), log) - - then: - dataService.expectNoMessage() - } - -} 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 07c25158..30a768f3 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy @@ -1,9 +1,11 @@ package edu.ie3.simona.api.simulation -import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme -import edu.ie3.simona.api.data.mapping.DataType -import edu.ie3.simona.api.data.mapping.ExtEntityEntry -import edu.ie3.simona.api.data.mapping.ExtEntityMapping +import edu.ie3.datamodel.models.value.PValue +import edu.ie3.datamodel.models.value.SValue +import edu.ie3.datamodel.models.value.Value +import edu.ie3.simona.api.data.connection.ExtEmDataConnection.EmMode +import edu.ie3.simona.api.exceptions.ExtDataConnectionException +import edu.ie3.simona.api.mapping.DataType import org.slf4j.Logger import org.slf4j.LoggerFactory import spock.lang.Shared @@ -18,42 +20,49 @@ class ExtCoSimulationTest extends Specification { given: UUID uuid1 = UUID.randomUUID() UUID uuid2 = UUID.randomUUID() - UUID uuid3 = UUID.randomUUID() - Optional columnScheme = Optional.of(ColumnScheme.ACTIVE_POWER) + Map> assetsToClasses = [ + (uuid1): PValue, + (uuid2): SValue + ] as Map + + when: + def actual = ExtCoSimulation.buildPrimaryConnection(assetsToClasses, log) - ExtEntityMapping mapping = new ExtEntityMapping([ - 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), - ]) + then: + actual.getPrimaryDataAssets() == [uuid1, uuid2] + } + def "An ExtCoSimulation throws an ExtDataConnectionException while trying to build an empty primary data connection"() { when: - def actual = ExtCoSimulation.buildPrimaryConnection(mapping, log) + ExtCoSimulation.buildPrimaryConnection([:], log) then: - actual.primaryDataAssets == [uuid3, uuid1] + ExtDataConnectionException ex = thrown(ExtDataConnectionException) + ex.message == "The external data connection 'ExtPrimaryDataConnection' could not be build!" } def "An ExtCoSimulation can build an em data connection correctly"() { given: UUID uuid1 = UUID.randomUUID() UUID uuid2 = UUID.randomUUID() - UUID uuid3 = UUID.randomUUID() - Optional columnScheme = Optional.of(ColumnScheme.ACTIVE_POWER) + def controlled = [uuid1, uuid2] + + when: + def actual = ExtCoSimulation.buildEmConnection(controlled, EmMode.BASE, log) - ExtEntityMapping mapping = new ExtEntityMapping([ - 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), - ]) + then: + actual.getControlledEms() == [uuid1, uuid2] + } + def "An ExtCoSimulation throws an ExtDataConnectionException while trying to build an empty em data connection"() { when: - def actual = ExtCoSimulation.buildEmConnection(mapping, log) + ExtCoSimulation.buildEmConnection([], EmMode.BASE, log) then: - actual.controlledEms == [uuid1, uuid2] + ExtDataConnectionException ex = thrown(ExtDataConnectionException) + ex.message == "The external data connection 'ExtEmDataConnection' could not be build!" } def "An ExtCoSimulation can build a result data connection correctly"() { @@ -62,20 +71,26 @@ 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, DataType.EXT_GRID_RESULT), - new ExtEntityEntry(uuid2, "participant_result", columnScheme, DataType.EXT_PARTICIPANT_RESULT), - new ExtEntityEntry(uuid3, "primary1", columnScheme, DataType.EXT_PRIMARY_INPUT), - ]) + def mapping = [ + (DataType.EXT_GRID_RESULT) : [uuid1], + (DataType.EXT_PARTICIPANT_RESULT): [uuid2], + (DataType.EXT_FLEX_OPTIONS_RESULT): [uuid3] + ] when: def actual = ExtCoSimulation.buildResultConnection(mapping, log) then: - actual.gridResultDataAssets == [uuid1] - actual.participantResultDataAssets == [uuid2] - actual.flexOptionAssets == [] + actual.getGridResultDataAssets() == [uuid1] + actual.getParticipantResultDataAssets() == [uuid2] + } + + def "An ExtCoSimulation throws an ExtDataConnectionException while trying to build an empty result data connection"() { + when: + ExtCoSimulation.buildResultConnection([:], log) + + then: + ExtDataConnectionException ex = thrown(ExtDataConnectionException) + ex.message == "The external data connection 'ExtResultDataConnection' could not be build!" } } diff --git a/src/test/groovy/edu/ie3/simona/api/simulation/ExtSimulationSpec.groovy b/src/test/groovy/edu/ie3/simona/api/simulation/ExtSimulationSpec.groovy index 7b24d955..56c2d129 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/ExtSimulationSpec.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/ExtSimulationSpec.groovy @@ -1,6 +1,6 @@ package edu.ie3.simona.api.simulation -import edu.ie3.simona.api.data.ExtDataConnection +import edu.ie3.simona.api.data.connection.ExtDataConnection import edu.ie3.simona.api.simulation.ontology.* import org.apache.pekko.actor.testkit.typed.javadsl.ActorTestKit import spock.lang.Shared diff --git a/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy b/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy index 85b5591d..ebebf43f 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy @@ -1,9 +1,7 @@ package edu.ie3.simona.api.simulation.mapping import edu.ie3.datamodel.models.input.NodeInput -import edu.ie3.simona.api.data.mapping.DataType -import edu.ie3.simona.api.data.mapping.ExtEntityEntry -import edu.ie3.simona.api.data.mapping.ExtEntityMappingSource +import edu.ie3.simona.api.mapping.DataType import spock.lang.Specification import java.nio.file.Path 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 73e87657..dea3928e 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 @@ -1,9 +1,7 @@ package edu.ie3.simona.api.simulation.mapping import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme -import edu.ie3.simona.api.data.mapping.DataType -import edu.ie3.simona.api.data.mapping.ExtEntityEntry -import edu.ie3.simona.api.data.mapping.ExtEntityMapping +import edu.ie3.simona.api.mapping.DataType import spock.lang.Shared import spock.lang.Specification diff --git a/src/test/groovy/edu/ie3/simona/api/test/common/DataServiceTestData.groovy b/src/test/groovy/edu/ie3/simona/api/test/common/DataServiceTestData.groovy index fa8e537d..88a7af56 100644 --- a/src/test/groovy/edu/ie3/simona/api/test/common/DataServiceTestData.groovy +++ b/src/test/groovy/edu/ie3/simona/api/test/common/DataServiceTestData.groovy @@ -18,7 +18,7 @@ trait DataServiceTestData { LoadResult loadResult = new LoadResult( ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), inputUuid, - Quantities.getQuantity(10, StandardUnits.ACTIVE_POWER_IN), - Quantities.getQuantity(5, StandardUnits.REACTIVE_POWER_IN) + Quantities.getQuantity(10, StandardUnits.ACTIVE_POWER_RESULT), + Quantities.getQuantity(5, StandardUnits.REACTIVE_POWER_RESULT) ) } \ No newline at end of file From 36153c0351fa5a6d4d9a335c5e9e8a902b35527b Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 24 Jun 2025 17:43:38 +0200 Subject: [PATCH 47/80] Saving changes. --- .../data/container/ExtResultContainer.java | 67 +------------------ 1 file changed, 1 insertion(+), 66 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java index 6f0077ee..8ee67c80 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java @@ -6,20 +6,12 @@ package edu.ie3.simona.api.data.container; -import static edu.ie3.util.quantities.PowerSystemUnits.PU; - -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.util.quantities.PowerSystemUnits; + import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.UUID; -import javax.measure.quantity.Dimensionless; -import tech.units.indriya.ComparableQuantity; -import tech.units.indriya.quantity.Quantities; /** Contains all SIMONA results for a certain tick. */ public final class ExtResultContainer implements ExtDataContainer { @@ -103,61 +95,4 @@ public Optional getMaybeNextTick() { public ResultEntity getResult(UUID assetId) { return resultMap.get(assetId); } - - /** - * Returns the voltage deviation in pu for a certain asset, if this asset provided a {@link - * NodeResult} - */ - public double getVoltageDeviation(UUID assetId) { - if (resultMap.get(assetId) instanceof NodeResult nodeResult) { - ComparableQuantity vMagDev = - Quantities.getQuantity(-1.0, PU).add(nodeResult.getvMag()); - return vMagDev.getValue().doubleValue(); - } else { - throw new IllegalArgumentException( - "Voltage deviation is only available for NodeResult's! AssetId: " + assetId); - } - } - - /** - * Returns the voltage deviation for certain asset, if this asset provided a {@link NodeResult} - */ - public double getVoltage(UUID assetId) { - if (resultMap.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 MW for certain asset, if this asset provided a {@link - * SystemParticipantResult} - */ - public double getActivePower(UUID assetId) { - if (resultMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { - return systemParticipantResult.getP().to(PowerSystemUnits.MEGAWATT).getValue().doubleValue(); - } else { - throw new IllegalArgumentException( - "Active power is only available for SystemParticipantResult's!"); - } - } - - /** - * Returns the reactive power in MVAr for certain asset, if this asset provided a {@link - * SystemParticipantResult} - */ - public double getReactivePower(UUID assetId) { - if (resultMap.get(assetId) instanceof SystemParticipantResult systemParticipantResult) { - return systemParticipantResult.getQ().to(PowerSystemUnits.MEGAVAR).getValue().doubleValue(); - } else { - throw new IllegalArgumentException( - "Reactive power is only available for SystemParticipantResult's!"); - } - } - - /** Returns the line loading for certain asset, if this asset provided a {@link LineResult} */ - public double getLineLoading(UUID assetId) { - throw new IllegalArgumentException("Line loading is not implemented yet!"); - } } From e1b2f7152aaaf69ea341e0d52c31f7306991ccd8 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 24 Jun 2025 17:43:51 +0200 Subject: [PATCH 48/80] Saving changes. --- .../api/data/connection/ExtEmDataConnection.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index 00672c68..1f93f710 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java @@ -6,13 +6,15 @@ package edu.ie3.simona.api.data.connection; -import edu.ie3.simona.api.data.em.ontology.EmDataMessageFromExt; -import edu.ie3.simona.api.data.em.ontology.EmDataResponseMessageToExt; -import edu.ie3.simona.api.data.em.ontology.ProvideEmSetPointData; +import edu.ie3.simona.api.data.em.ontology.*; import edu.ie3.simona.api.data.model.em.EmSetPoint; -import java.util.*; +import edu.ie3.simona.api.data.model.em.ExtendedFlexOptionsResult; +import edu.ie3.simona.api.data.model.em.FlexOptionRequest; +import edu.ie3.simona.api.data.model.em.FlexOptions; import org.slf4j.Logger; +import java.util.*; + /** Enables data connection of em data between SIMONA and SimonaAPI */ public final class ExtEmDataConnection extends BiDirectional { From 8ab0f8de27fa74fcc45da8b0303171153d15b5f2 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 25 Jun 2025 10:25:06 +0200 Subject: [PATCH 49/80] Adapting to changes in `dev`. --- .../data/connection/ExtEmDataConnection.java | 15 +-- .../data/container/ExtResultContainer.java | 1 - .../simona/api/data/model/em/EmSetPoint.java | 7 +- .../api/data/model/em/FlexOptionRequest.java | 79 ++++++------ .../simona/api/data/model/em/FlexOptions.java | 119 ++++++++++++++---- .../{data => }/mapping/ExtEntityMapping.java | 6 +- .../simona/api/ontology/em/EmCompletion.java | 2 +- .../ontology/em/EmSetPointDataResponse.java | 2 +- .../api/ontology/em/FlexOptionsResponse.java | 2 +- .../api/ontology/em/FlexRequestResponse.java | 2 +- .../ontology/em/ProvideEmFlexOptionData.java | 2 +- .../ontology/em/ProvideFlexRequestData.java | 2 +- .../api/ontology/em/RequestEmCompletion.java | 2 +- .../api/ontology/em/RequestEmFlexResults.java | 2 +- .../api/simulation/ExtCoSimulation.java | 24 ++-- .../container/ExtResultContainerTest.groovy | 62 --------- 16 files changed, 163 insertions(+), 166 deletions(-) rename src/main/java/edu/ie3/simona/api/{data => }/mapping/ExtEntityMapping.java (98%) diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index b01a69b4..7e227f5f 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java @@ -6,18 +6,13 @@ package edu.ie3.simona.api.data.connection; -import edu.ie3.simona.api.data.em.ontology.*; import edu.ie3.simona.api.data.model.em.EmSetPoint; -import edu.ie3.simona.api.ontology.em.EmDataMessageFromExt; -import edu.ie3.simona.api.ontology.em.EmDataResponseMessageToExt; -import edu.ie3.simona.api.ontology.em.ProvideEmSetPointData; -import java.util.*; import edu.ie3.simona.api.data.model.em.ExtendedFlexOptionsResult; import edu.ie3.simona.api.data.model.em.FlexOptionRequest; import edu.ie3.simona.api.data.model.em.FlexOptions; -import org.slf4j.Logger; - +import edu.ie3.simona.api.ontology.em.*; import java.util.*; +import org.slf4j.Logger; /** Enables data connection of em data between SIMONA and SimonaAPI */ public final class ExtEmDataConnection @@ -49,7 +44,7 @@ public List getControlledEms() { * @param log logger */ public void sendFlexRequests( - long tick, Map data, Optional maybeNextTick, Logger log) { + long tick, Map data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No em flex requests found! Sending no em data to SIMONA for tick {}.", tick); } else { @@ -67,7 +62,7 @@ public void sendFlexRequests( * @param log logger */ public void sendFlexOptions( - long tick, Map> data, Optional maybeNextTick, Logger log) { + long tick, Map> data, Optional maybeNextTick, Logger log) { if (data.isEmpty()) { log.warn("No em flex options found! Sending no em data to SIMONA for tick {}.", tick); } else { @@ -103,7 +98,7 @@ public void sendSetPoints( * @throws InterruptedException - on interruptions */ public Map requestEmFlexResults( - long tick, List emEntities, boolean disaggregated) throws InterruptedException { + long tick, List emEntities, boolean disaggregated) throws InterruptedException { sendExtMsg(new RequestEmFlexResults(tick, emEntities, disaggregated)); return receiveWithType(FlexOptionsResponse.class).receiverToFlexOptions(); } diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java index 8ee67c80..9ef5df37 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java @@ -7,7 +7,6 @@ package edu.ie3.simona.api.data.container; import edu.ie3.datamodel.models.result.ResultEntity; - import java.util.HashMap; import java.util.Map; import java.util.Optional; diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java index c4177a04..36416de4 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java @@ -7,13 +7,12 @@ package edu.ie3.simona.api.data.model.em; import edu.ie3.datamodel.models.value.PValue; -import tech.units.indriya.ComparableQuantity; - -import javax.measure.quantity.Power; -import javax.measure.quantity.Time; import java.util.Objects; import java.util.Optional; import java.util.UUID; +import javax.measure.quantity.Power; +import javax.measure.quantity.Time; +import tech.units.indriya.ComparableQuantity; /** Energy management set point that will be sent to SIMONA. */ public final class EmSetPoint { diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java index dc96c847..ae9a7f27 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java @@ -14,41 +14,46 @@ public final class FlexOptionRequest { - public final UUID receiver; - public final Optional sender; - public final Optional> delay; - - public FlexOptionRequest(UUID receiver, Optional sender) { - this.receiver = receiver; - this.sender = sender; - this.delay = Optional.empty(); - } - - public FlexOptionRequest(UUID receiver, Optional sender, Optional> delay) { - this.receiver = receiver; - this.sender = sender; - this.delay = delay; - } - - - @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; - FlexOptionRequest that = (FlexOptionRequest) o; - return Objects.equals(receiver, that.receiver) && Objects.equals(sender, that.sender) && Objects.equals(delay, that.delay); - } - - @Override - public int hashCode() { - return Objects.hash(receiver, sender, delay); - } - - @Override - public String toString() { - return "FlexOptionRequest{" + - "receiver=" + receiver + - ", sender=" + sender + - ", delay=" + delay + - '}'; - } + public final UUID receiver; + public final Optional sender; + public final Optional> delay; + + public FlexOptionRequest(UUID receiver, Optional sender) { + this.receiver = receiver; + this.sender = sender; + this.delay = Optional.empty(); + } + + public FlexOptionRequest( + UUID receiver, Optional sender, Optional> delay) { + this.receiver = receiver; + this.sender = sender; + this.delay = delay; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + FlexOptionRequest that = (FlexOptionRequest) o; + return Objects.equals(receiver, that.receiver) + && Objects.equals(sender, that.sender) + && Objects.equals(delay, that.delay); + } + + @Override + public int hashCode() { + return Objects.hash(receiver, sender, delay); + } + + @Override + public String toString() { + return "FlexOptionRequest{" + + "receiver=" + + receiver + + ", sender=" + + sender + + ", delay=" + + delay + + '}'; + } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java index 5847b641..6a77aa7f 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java @@ -6,38 +6,103 @@ package edu.ie3.simona.api.data.model.em; +import java.util.Objects; import java.util.Optional; import java.util.UUID; import javax.measure.quantity.Power; import javax.measure.quantity.Time; import tech.units.indriya.ComparableQuantity; -/** - * Flex option that will be sent to SIMONA. - * - * @param receiver uuid of the flex options - * @param sender uuid of the flex options - * @param pRef current active power - * @param pMin minimal active power - * @param pMax maximal active power - * @param delay the delay of the message - */ -public record FlexOptions( - UUID receiver, - UUID sender, - ComparableQuantity pRef, - ComparableQuantity pMin, - ComparableQuantity pMax, - Optional> delay) { - - public static FlexOptions of( - UUID receiver, - UUID sender, - ComparableQuantity pRef, - ComparableQuantity pMin, - ComparableQuantity pMax - ) { - return new FlexOptions(receiver, sender, pRef, pMin, pMax, Optional.empty()); - } +/** Flex option that will be sent to SIMONA. */ +public final class FlexOptions { + + public final UUID receiver; + public final UUID sender; + public final ComparableQuantity pRef; + public final ComparableQuantity pMin; + public final ComparableQuantity pMax; + public final Optional> delay; + + /** + * Flex option that will be sent to SIMONA. + * + * @param receiver uuid of the flex options + * @param sender uuid of the flex options + * @param pRef current active power + * @param pMin minimal active power + * @param pMax maximal active power + */ + public FlexOptions( + UUID receiver, + UUID sender, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax) { + this.receiver = receiver; + this.sender = sender; + this.pRef = pRef; + this.pMin = pMin; + this.pMax = pMax; + this.delay = Optional.empty(); + } + + /** + * Flex option that will be sent to SIMONA. + * + * @param receiver uuid of the flex options + * @param sender uuid of the flex options + * @param pRef current active power + * @param pMin minimal active power + * @param pMax maximal active power + * @param delay the delay of the message + */ + public FlexOptions( + UUID receiver, + UUID sender, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax, + Optional> delay) { + this.receiver = receiver; + this.sender = sender; + this.pRef = pRef; + this.pMin = pMin; + this.pMax = pMax; + this.delay = delay; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + FlexOptions that = (FlexOptions) o; + return Objects.equals(receiver, that.receiver) + && Objects.equals(sender, that.sender) + && Objects.equals(pRef, that.pRef) + && Objects.equals(pMin, that.pMin) + && Objects.equals(pMax, that.pMax) + && Objects.equals(delay, that.delay); + } + + @Override + public int hashCode() { + return Objects.hash(receiver, sender, pRef, pMin, pMax, delay); + } + @Override + public String toString() { + return "FlexOptions{" + + "receiver=" + + receiver + + ", sender=" + + sender + + ", pRef=" + + pRef + + ", pMin=" + + pMin + + ", pMax=" + + pMax + + ", delay=" + + delay + + '}'; + } } diff --git a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java similarity index 98% rename from src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java rename to src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java index d294e6aa..5e4e8b7f 100644 --- a/src/main/java/edu/ie3/simona/api/data/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java @@ -4,14 +4,12 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.mapping; +package edu.ie3.simona.api.mapping; +import edu.ie3.simona.api.simulation.mapping.ExtEntityEntry; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; - -import edu.ie3.simona.api.mapping.DataType; -import edu.ie3.simona.api.simulation.mapping.ExtEntityEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/EmCompletion.java b/src/main/java/edu/ie3/simona/api/ontology/em/EmCompletion.java index d35f89f9..4a0cd759 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/EmCompletion.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/EmCompletion.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.ontology; +package edu.ie3.simona.api.ontology.em; import java.util.Optional; diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java b/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java index d11d1069..c7a6c6e5 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.ontology; +package edu.ie3.simona.api.ontology.em; import edu.ie3.simona.api.data.model.em.EmSetPointResult; import java.util.Map; diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/FlexOptionsResponse.java b/src/main/java/edu/ie3/simona/api/ontology/em/FlexOptionsResponse.java index 44f46a4e..49852430 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/FlexOptionsResponse.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/FlexOptionsResponse.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.ontology; +package edu.ie3.simona.api.ontology.em; import edu.ie3.simona.api.data.model.em.ExtendedFlexOptionsResult; import java.util.Map; diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/FlexRequestResponse.java b/src/main/java/edu/ie3/simona/api/ontology/em/FlexRequestResponse.java index 816da929..69f8a1c4 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/FlexRequestResponse.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/FlexRequestResponse.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.ontology; +package edu.ie3.simona.api.ontology.em; import edu.ie3.simona.api.data.model.em.FlexRequestResult; import java.util.Map; diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java index b94136ff..3d8d0e53 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.ontology; +package edu.ie3.simona.api.ontology.em; import edu.ie3.simona.api.data.model.em.FlexOptions; import java.util.List; diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java index f869a438..4013e748 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.ontology; +package edu.ie3.simona.api.ontology.em; import edu.ie3.simona.api.data.model.em.FlexOptionRequest; import java.util.Map; diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java b/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java index 0a5d5322..209d8e20 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java @@ -4,6 +4,6 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.ontology; +package edu.ie3.simona.api.ontology.em; public record RequestEmCompletion(long tick) implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmFlexResults.java b/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmFlexResults.java index c7c4f4fe..47d41f92 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmFlexResults.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmFlexResults.java @@ -4,7 +4,7 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.data.em.ontology; +package edu.ie3.simona.api.ontology.em; import java.util.List; import java.util.UUID; 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 6bd2fd6f..870cfbf0 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -6,6 +6,8 @@ package edu.ie3.simona.api.simulation; +import static java.util.Collections.emptyList; + import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.ExtDataContainerQueue; @@ -17,11 +19,8 @@ import edu.ie3.simona.api.data.model.em.EmSetPoint; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; import edu.ie3.simona.api.mapping.DataType; -import org.slf4j.Logger; - import java.util.*; - -import static java.util.Collections.emptyList; +import org.slf4j.Logger; /** * Abstract class for an external co-simulation with bidirectional communication with SIMONA. @@ -141,11 +140,11 @@ private void checkTick(long expectedTick) throws InterruptedException { * @param log logger */ protected void sendPrimaryDataToSimona( - ExtPrimaryDataConnection extPrimaryDataConnection, - long tick, - Optional maybeNextTick, - Logger log) - throws InterruptedException { + ExtPrimaryDataConnection extPrimaryDataConnection, + long tick, + Optional maybeNextTick, + Logger log) + throws InterruptedException { checkTick(tick); Map inputData = queueToSimona.takeData(ExtInputContainer::extractPrimaryData); sendPrimaryDataToSimona(extPrimaryDataConnection, tick, inputData, maybeNextTick, log); @@ -203,11 +202,10 @@ protected void sendFlexOptionsToExt( * @throws InterruptedException if the fetching of data is interrupted */ protected void sendEmSetPointsToSimona( - ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) - throws InterruptedException { + ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) + throws InterruptedException { checkTick(tick); - Map inputData = - queueToSimona.takeData(ExtInputContainer::extractSetPoints); + Map inputData = queueToSimona.takeData(ExtInputContainer::extractSetPoints); sendEmSetPointsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); } diff --git a/src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy index 5838da4d..6dff294a 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy @@ -57,66 +57,4 @@ class ExtResultContainerTest extends Specification implements DataServiceTestDat loadResults == [(inputUuid): loadResult] flexOptionsResults == [:] } - - def "ExtResultContainer should return voltage deviation correctly"() { - given: - def resultMap = Map.of(nodeUuid, nodeResult) - def extResultContainer = new ExtResultContainer(0L, resultMap) - - when: - def calculatedVoltageDeviation = extResultContainer.getVoltageDeviation(nodeUuid) - - then: - calculatedVoltageDeviation == -0.05d - } - - def "ExtResultContainer should throw an exception, if voltage deviation was requested for a not NodeResult"() { - given: - def resultMap = Map.of(inputUuid, loadResult) - def extResultContainer = new ExtResultContainer(0L, resultMap) - - when: - extResultContainer.getVoltageDeviation(inputUuid) - - then: - thrown IllegalArgumentException - } - - def "ExtResultContainer should return active power correctly"() { - given: - def resultMap = Map.of(inputUuid, loadResult) - def extResultContainer = new ExtResultContainer(0L, resultMap) - - when: - def returnedActivePower = extResultContainer.getActivePower(inputUuid) - - then: - returnedActivePower == 10d - } - - def "ExtResultContainer should return reactive power correctly"() { - given: - def resultMap = Map.of(inputUuid, loadResult) - def extResultContainer = new ExtResultContainer(0L, resultMap) - - when: - def returnedReactivePower = extResultContainer.getReactivePower(inputUuid) - - then: - returnedReactivePower == 5d - } - - def "ExtResultContainer should throw an exception, if active power was requested for a not SystemParticipantResult"() { - given: - def resultMap = Map.of( - nodeUuid, nodeResult - ) - def extResultContainer = new ExtResultContainer(0L, resultMap) - - when: - extResultContainer.getActivePower(nodeUuid) - - then: - thrown IllegalArgumentException - } } \ No newline at end of file From 9650917d007908dd47e45289eeae0c5b62bd216e Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 25 Jun 2025 11:14:23 +0200 Subject: [PATCH 50/80] Saving changes. --- .../simulation/mapping/ExtEntityMapping.java | 47 ------------------- .../mapping/ExtEntityMappingSource.java | 2 + 2 files changed, 2 insertions(+), 47 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java 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 deleted file mode 100644 index 6976be08..00000000 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * © 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.simulation.mapping; - -import edu.ie3.simona.api.mapping.DataType; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.stream.Collectors; - -/** Contains the mapping between SIMONA uuid, the external id and the data type the assets hold */ -public class ExtEntityMapping { - - private final Map> extEntities; - - public ExtEntityMapping(List extEntityEntryList) { - this.extEntities = - extEntityEntryList.stream().collect(Collectors.groupingBy(ExtEntityEntry::dataType)); - } - - /** - * Mapping external id to SIMONA uuid - * - * @param dataType data type the external asset expects - * @return Mapping external id to SIMONA uuid - */ - public Map getExtId2UuidMapping(DataType dataType) { - return extEntities.getOrDefault(dataType, Collections.emptyList()).stream() - .collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); - } - - /** - * Mapping SIMONA uuid to external id - * - * @param dataType data type the external asset expects - * @return Mapping SIMONA uuid to external id - */ - public Map getExtUuid2IdMapping(DataType dataType) { - return extEntities.getOrDefault(dataType, Collections.emptyList()).stream() - .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); - } -} diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java index 1d24d7ff..c54dbd09 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java @@ -13,6 +13,8 @@ import edu.ie3.datamodel.io.source.DataSource; import edu.ie3.datamodel.io.source.csv.CsvDataSource; import edu.ie3.datamodel.models.Entity; +import edu.ie3.simona.api.mapping.ExtEntityMapping; + import java.nio.file.Path; import java.util.Map; import java.util.Optional; From 0470eb953225d99df466f5716b59f7fa3661e569 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 26 Jun 2025 11:41:19 +0200 Subject: [PATCH 51/80] Fixing some merging issues. --- .../simona/api/data/model/em/EmSetPoint.java | 11 ---- .../api/simulation/ExtCoSimulation.java | 56 +++++++++---------- 2 files changed, 28 insertions(+), 39 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java index 31292adf..7314e6f8 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java @@ -19,7 +19,6 @@ public final class EmSetPoint extends EmMessageBase { /** An option for the em set point. */ public final Optional power; - public final Optional> delay; /** * Constructor for {@link EmSetPoint}. @@ -31,7 +30,6 @@ public final class EmSetPoint extends EmMessageBase { public EmSetPoint(UUID receiver) { super(receiver); this.power = Optional.empty(); - this.delay = Optional.empty(); } /** @@ -43,7 +41,6 @@ public EmSetPoint(UUID receiver) { public EmSetPoint(UUID receiver, ComparableQuantity p) { super(receiver); this.power = Optional.of(new PValue(p)); - this.delay = Optional.empty(); } /** @@ -55,14 +52,6 @@ public EmSetPoint(UUID receiver, ComparableQuantity p) { public EmSetPoint(UUID receiver, PValue power) { super(receiver); this.power = Optional.of(power); - this.delay = Optional.empty(); - } - - public EmSetPoint( - UUID receiver, Optional power, Optional> delay) { - this.receiver = receiver; - this.power = power; - this.delay = delay; } /** 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 50571827..870cfbf0 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -117,38 +117,38 @@ public static ExtResultDataConnection buildResultConnection( } } - private void checkTick(long expectedTick) throws InterruptedException { - long dataTick = queueToSimona.takeData(ExtInputContainer::getTick); - - if (dataTick != expectedTick) { - throw new RuntimeException( - String.format( - "Provided input data for tick %d, but SIMONA expects input data for tick %d", - dataTick, expectedTick)); - } + private void checkTick(long expectedTick) throws InterruptedException { + long dataTick = queueToSimona.takeData(ExtInputContainer::getTick); + + if (dataTick != expectedTick) { + throw new RuntimeException( + String.format( + "Provided input data for tick %d, but SIMONA expects input data for tick %d", + dataTick, expectedTick)); } + } // primary data methods - /** - * Function to send primary data to SIMONA using the given {@link ExtPrimaryDataConnection}. This - * method will take a value from the {@link #queueToSimona}. - * - * @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 { - checkTick(tick); - Map inputData = queueToSimona.takeData(ExtInputContainer::extractPrimaryData); - sendPrimaryDataToSimona(extPrimaryDataConnection, tick, inputData, maybeNextTick, log); - } + /** + * Function to send primary data to SIMONA using the given {@link ExtPrimaryDataConnection}. This + * method will take a value from the {@link #queueToSimona}. + * + * @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 { + checkTick(tick); + Map inputData = queueToSimona.takeData(ExtInputContainer::extractPrimaryData); + sendPrimaryDataToSimona(extPrimaryDataConnection, tick, inputData, maybeNextTick, log); + } /** * Function to send primary data to SIMONA using ExtPrimaryData From 142175406ca4d908411aee8c9f61face28f24569 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 26 Jun 2025 12:32:28 +0200 Subject: [PATCH 52/80] Adapting to changes in `simonaAPI`. --- .../model/em/ExtendedFlexOptionsResult.java | 62 +++++++++++++++++++ .../api/data/model/em/FlexRequestResult.java | 40 ------------ 2 files changed, 62 insertions(+), 40 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/FlexRequestResult.java diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java index c03aaade..6f21cf68 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java @@ -10,6 +10,8 @@ import java.time.ZonedDateTime; import java.util.*; import javax.measure.quantity.Power; + +import org.slf4j.Logger; import tech.units.indriya.ComparableQuantity; /** @@ -69,6 +71,66 @@ public ExtendedFlexOptionsResult( this.disaggregated = disaggregated; } + public boolean validate(Logger log) { + List> refs = new ArrayList<>(); + List> mins = new ArrayList<>(); + List> maxs = new ArrayList<>(); + + disaggregated.forEach((uuid, flexOptionsResult) -> { + refs.add(flexOptionsResult.getpRef()); + mins.add(flexOptionsResult.getpMin()); + maxs.add(flexOptionsResult.getpMax()); + }); + + ComparableQuantity ref = getpRef(); + ComparableQuantity min = getpMin(); + ComparableQuantity max = getpMax(); + + Optional> refSum = refs.stream().reduce(ComparableQuantity::add); + Optional> minSum = mins.stream().reduce(ComparableQuantity::add); + Optional> maxSum = maxs.stream().reduce(ComparableQuantity::add); + + boolean isRefValid = false; + boolean isMinValid = false; + boolean isMaxValid = false; + + if (refSum.isPresent()) { + isRefValid = refSum.get() != ref; + + if (!isRefValid) { + log.warn("Disaggregated reference power does not match total reference power."); + } + } else { + log.warn("Cannot check disaggregated reference power."); + } + + if (minSum.isPresent()) { + isMinValid = minSum.get() != min; + + if (!isMinValid) { + log.warn("Disaggregated minimum power does not match total minimum power."); + } + } else { + log.warn("Cannot check disaggregated minimum power."); + } + + if (maxSum.isPresent()) { + isMaxValid = maxSum.get() != max; + + if (!isMaxValid) { + log.warn("Disaggregated maximum power does not match total maximum power."); + } + } else { + log.warn("Cannot check disaggregated maximum power."); + } + + return isRefValid && isMinValid && isMaxValid; + } + + public void addDisaggregated(UUID uuid, FlexOptionsResult flexOptionsResult) { + this.disaggregated.put(uuid, flexOptionsResult); + } + /** Returns the uuid of the sender ({@link #getInputModel()}) of the results. */ public UUID getSender() { return getInputModel(); diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexRequestResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexRequestResult.java deleted file mode 100644 index 64d86511..00000000 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexRequestResult.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * © 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.model.em; - -import edu.ie3.datamodel.models.result.ResultEntity; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.UUID; - -public class FlexRequestResult extends ResultEntity { - - private final List receivers; - - public FlexRequestResult(ZonedDateTime time, UUID inputModel, Collection receivers) { - super(time, inputModel); - this.receivers = new ArrayList<>(receivers); - } - - public List getReceivers() { - return receivers; - } - - @Override - public String toString() { - return "FlexRequestResult{" - + "time=" - + getTime() - + ", inputModel=" - + getInputModel() - + ", receivers=" - + receivers - + '}'; - } -} From 05c80d3b82274ce164e2e3771c65629ea4b4b6aa Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 30 Jun 2025 11:56:41 +0200 Subject: [PATCH 53/80] Adding max delay parameter. --- .../data/connection/ExtEmDataConnection.java | 22 +++++++++++++++++++ .../api/simulation/ExtCoSimulation.java | 12 ++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index 43fff5e9..b30456f5 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java @@ -13,6 +13,9 @@ import edu.ie3.simona.api.ontology.em.*; import java.util.*; import org.slf4j.Logger; +import tech.units.indriya.ComparableQuantity; + +import javax.measure.quantity.Time; /** Enables data connection of em data between SIMONA and SimonaAPI */ public final class ExtEmDataConnection @@ -23,11 +26,22 @@ public final class ExtEmDataConnection /** Assets that are controlled by external simulation */ private final List controlled; + private final Optional> maxDelay; + public ExtEmDataConnection(List controlled, EmMode mode) { super(); this.mode = mode; this.controlled = controlled; + this.maxDelay = Optional.empty(); + } + + public ExtEmDataConnection(List controlled, EmMode mode, Optional> maxDelay) { + super(); + + this.mode = mode; + this.controlled = controlled; + this.maxDelay = maxDelay; } /** Returns a list of the uuids of the em agents that expect external set points */ @@ -35,6 +49,14 @@ public List getControlledEms() { return new ArrayList<>(controlled); } + /** + * + * Returns the maximal delay, that is allowed for a message when using the em communication. + */ + public Optional> getMaxDelay() { + return maxDelay; + } + /** * Sends the em flex requests to SIMONA. * 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 870cfbf0..592618da 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -21,6 +21,9 @@ import edu.ie3.simona.api.mapping.DataType; import java.util.*; import org.slf4j.Logger; +import tech.units.indriya.ComparableQuantity; + +import javax.measure.quantity.Time; /** * Abstract class for an external co-simulation with bidirectional communication with SIMONA. @@ -72,11 +75,16 @@ public static ExtPrimaryDataConnection buildPrimaryConnection( * Builds an {@link ExtEmDataConnection}. * * @param controlled uuids for controlled em agents. + * @param maxDelay the maximal delay used in em communication mode * @param log logger * @return an ext em data connection */ public static ExtEmDataConnection buildEmConnection( - List controlled, ExtEmDataConnection.EmMode mode, Logger log) { + List controlled, ExtEmDataConnection.EmMode mode, Optional> maxDelay, Logger log) { + if (maxDelay.isEmpty() && mode == ExtEmDataConnection.EmMode.EM_COMMUNICATION) { + log.info("Using em communication without a maximum delay."); + } + if (controlled.isEmpty()) { log.warn("Em data connection with 0 controlled entities created. This might lead to errors!"); throw new ExtDataConnectionException(ExtEmDataConnection.class); @@ -86,7 +94,7 @@ public static ExtEmDataConnection buildEmConnection( mode, controlled.size()); - return new ExtEmDataConnection(controlled, mode); + return new ExtEmDataConnection(controlled, mode, maxDelay); } } From 8c47493461344d6acf83a963c0b0b555d37bc61d Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 21 Jul 2025 10:09:50 +0200 Subject: [PATCH 54/80] Refactoring em communication delay. --- .../data/connection/ExtEmDataConnection.java | 23 +--- .../api/data/container/ExtInputContainer.java | 2 +- .../api/data/model/em/EmMessageBase.java | 66 --------- .../simona/api/data/model/em/EmSetPoint.java | 55 ++------ .../api/data/model/em/FlexOptionRequest.java | 80 ++--------- .../simona/api/data/model/em/FlexOptions.java | 125 +++--------------- .../results/ProvideResultEntities.java | 4 + .../api/simulation/ExtCoSimulation.java | 19 +-- 8 files changed, 50 insertions(+), 324 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/EmMessageBase.java diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index b30456f5..ea2ce3a3 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java @@ -11,11 +11,9 @@ import edu.ie3.simona.api.data.model.em.FlexOptionRequest; import edu.ie3.simona.api.data.model.em.FlexOptions; import edu.ie3.simona.api.ontology.em.*; -import java.util.*; import org.slf4j.Logger; -import tech.units.indriya.ComparableQuantity; -import javax.measure.quantity.Time; +import java.util.*; /** Enables data connection of em data between SIMONA and SimonaAPI */ public final class ExtEmDataConnection @@ -26,22 +24,11 @@ public final class ExtEmDataConnection /** Assets that are controlled by external simulation */ private final List controlled; - private final Optional> maxDelay; - public ExtEmDataConnection(List controlled, EmMode mode) { super(); this.mode = mode; this.controlled = controlled; - this.maxDelay = Optional.empty(); - } - - public ExtEmDataConnection(List controlled, EmMode mode, Optional> maxDelay) { - super(); - - this.mode = mode; - this.controlled = controlled; - this.maxDelay = maxDelay; } /** Returns a list of the uuids of the em agents that expect external set points */ @@ -49,14 +36,6 @@ public List getControlledEms() { return new ArrayList<>(controlled); } - /** - * - * Returns the maximal delay, that is allowed for a message when using the em communication. - */ - public Optional> getMaxDelay() { - return maxDelay; - } - /** * Sends the em flex requests to SIMONA. * diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java index 1f8f8d26..42a7f1ce 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java @@ -127,7 +127,7 @@ public void addSetPoint(UUID asset, PValue power) { * @param setPoint given set point */ public void addSetPoint(EmSetPoint setPoint) { - setPoints.put(setPoint.receiver, setPoint); + setPoints.put(setPoint.receiver(), setPoint); } /** diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/EmMessageBase.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmMessageBase.java deleted file mode 100644 index d8156d7b..00000000 --- a/src/main/java/edu/ie3/simona/api/data/model/em/EmMessageBase.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * © 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.model.em; - -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; -import javax.measure.quantity.Time; -import tech.units.indriya.ComparableQuantity; - -/** Base class for messages used during communication. */ -public abstract sealed class EmMessageBase permits EmSetPoint, FlexOptionRequest, FlexOptions { - - /** The receiver of the message. */ - public final UUID receiver; - - /** An option for the delay of this message. */ - public final Optional> delay; - - /** - * Base constructor without {@link #delay}. - * - * @param receiver of the message - */ - protected EmMessageBase(UUID receiver) { - this.receiver = receiver; - this.delay = Optional.empty(); - } - - /** - * Base constructor with {@link #delay}. - * - * @param receiver of this message - * @param delay of this message - */ - protected EmMessageBase(UUID receiver, Optional> delay) { - this.receiver = receiver; - this.delay = delay; - } - - /** Returns {@code true}, if there is a delay. */ - public boolean hasDelay() { - return delay.isPresent(); - } - - @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; - EmMessageBase that = (EmMessageBase) o; - return Objects.equals(receiver, that.receiver) && Objects.equals(delay, that.delay); - } - - @Override - public int hashCode() { - return Objects.hash(receiver, delay); - } - - @Override - public String toString() { - return "EmMessageBase{" + "receiver=" + receiver + ", delay=" + delay + '}'; - } -} diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java index 7314e6f8..308a8730 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java @@ -7,19 +7,18 @@ package edu.ie3.simona.api.data.model.em; import edu.ie3.datamodel.models.value.PValue; -import java.util.Objects; import java.util.Optional; import java.util.UUID; import javax.measure.quantity.Power; -import javax.measure.quantity.Time; import tech.units.indriya.ComparableQuantity; -/** Energy management set point that will be sent to SIMONA. */ -public final class EmSetPoint extends EmMessageBase { - - /** An option for the em set point. */ - public final Optional power; - +/** + * Energy management set point that will be sent to SIMONA + * + * @param receiver The receiver of the message. + * @param power An option for the em set point. + */ +public record EmSetPoint(UUID receiver, Optional power) { /** * Constructor for {@link EmSetPoint}. * @@ -28,8 +27,7 @@ public final class EmSetPoint extends EmMessageBase { * @param receiver of the set point. */ public EmSetPoint(UUID receiver) { - super(receiver); - this.power = Optional.empty(); + this(receiver, Optional.empty()); } /** @@ -39,8 +37,7 @@ public EmSetPoint(UUID receiver) { * @param p power value of the set point */ public EmSetPoint(UUID receiver, ComparableQuantity p) { - super(receiver); - this.power = Optional.of(new PValue(p)); + this(receiver, Optional.of(new PValue(p))); } /** @@ -50,38 +47,6 @@ public EmSetPoint(UUID receiver, ComparableQuantity p) { * @param power value of the set point */ public EmSetPoint(UUID receiver, PValue power) { - super(receiver); - this.power = Optional.of(power); - } - - /** - * Constructor for {@link EmSetPoint}. - * - * @param receiver of the set point. - * @param power option for the set point - * @param delay option for the delay of this message - */ - public EmSetPoint( - UUID receiver, Optional power, Optional> delay) { - super(receiver, delay); - this.power = power; - } - - @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - EmSetPoint that = (EmSetPoint) o; - return Objects.equals(power, that.power); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), power); - } - - @Override - public String toString() { - return "EmSetPoint{" + "receiver=" + receiver + ", power=" + power + ", delay=" + delay + '}'; + this(receiver, Optional.ofNullable(power)); } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java index f1b1e307..5c91c29a 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java @@ -6,18 +6,16 @@ package edu.ie3.simona.api.data.model.em; -import java.util.Objects; import java.util.Optional; import java.util.UUID; -import javax.measure.quantity.Time; -import tech.units.indriya.ComparableQuantity; - -/** Energy management flex option request that will be sent to SIMONA. */ -public final class FlexOptionRequest extends EmMessageBase { - - /** The sender of the request. */ - public final Optional sender; +/** + * Energy management flex option request that will be sent to SIMONA + * + * @param receiver The receiver of the message. + * @param sender The sender of the request. + */ +public record FlexOptionRequest(UUID receiver, Optional sender) { /** * Constructor for {@link FlexOptionRequest}. Equals {@code new FlexOptionRequest(receiver, * Optional.empty())}. @@ -35,68 +33,6 @@ public FlexOptionRequest(UUID receiver) { * @param sender of the request */ public FlexOptionRequest(UUID receiver, UUID sender) { - super(receiver); - this.sender = Optional.ofNullable(sender); - } - - /** - * Constructor for {@link FlexOptionRequest}. - * - * @param receiver of the request - * @param sender of the request - */ - public FlexOptionRequest(UUID receiver, Optional sender) { - super(receiver); - this.sender = sender; - } - - /** - * Constructor for {@link FlexOptionRequest}. - * - * @param receiver of the request - * @param sender of the request - * @param delay option for the delay of this message - */ - public FlexOptionRequest(UUID receiver, UUID sender, Optional> delay) { - super(receiver, delay); - this.sender = Optional.ofNullable(sender); - } - - /** - * Constructor for {@link FlexOptionRequest}. - * - * @param receiver of the request - * @param sender option for the sender of the request - * @param delay option for the delay of this message - */ - public FlexOptionRequest( - UUID receiver, Optional sender, Optional> delay) { - super(receiver, delay); - this.sender = sender; - } - - @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - FlexOptionRequest that = (FlexOptionRequest) o; - return Objects.equals(sender, that.sender); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), delay); - } - - @Override - public String toString() { - return "FlexOptionRequest{" - + "receiver=" - + receiver - + ", sender=" - + sender - + ", delay=" - + delay - + '}'; + this(receiver, Optional.ofNullable(sender)); } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java index ce04bfa4..cc4bd68d 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java @@ -6,113 +6,26 @@ package edu.ie3.simona.api.data.model.em; -import java.util.Objects; -import java.util.Optional; import java.util.UUID; import javax.measure.quantity.Power; -import javax.measure.quantity.Time; import tech.units.indriya.ComparableQuantity; -/** Flex option that will be sent to SIMONA. */ -public final class FlexOptions extends EmMessageBase { - - /** The sender of the request. */ - public final UUID sender; - - /** Active power (might be negative, thus feed-in) that was suggested for regular usage. */ - public final ComparableQuantity pRef; - - /** - * Minimal active power to which the sender can be reduced (might be negative, thus feed-in), that - * was determined by the system. Therefore equates to lower bound of possible flexibility - * provision. - */ - public final ComparableQuantity pMin; - - /** - * Maximum active power to which the sender can be increased (might be negative, thus feed-in), - * that was determined by the system. Therefore equates to upper bound of possible flexibility - * provision. - */ - public final ComparableQuantity pMax; - - /** - * Flex option that will be sent to SIMONA. - * - * @param receiver uuid of the flex options - * @param sender uuid of the flex options - * @param pRef current active power - * @param pMin minimal active power - * @param pMax maximal active power - */ - public FlexOptions( - UUID receiver, - UUID sender, - ComparableQuantity pRef, - ComparableQuantity pMin, - ComparableQuantity pMax) { - super(receiver); - this.sender = sender; - this.pRef = pRef; - this.pMin = pMin; - this.pMax = pMax; - } - - /** - * Flex option that will be sent to SIMONA. - * - * @param receiver uuid of the flex options - * @param sender uuid of the flex options - * @param pRef current active power - * @param pMin minimal active power - * @param pMax maximal active power - * @param delay option for the delay of the message - */ - public FlexOptions( - UUID receiver, - UUID sender, - ComparableQuantity pRef, - ComparableQuantity pMin, - ComparableQuantity pMax, - Optional> delay) { - super(receiver, delay); - this.sender = sender; - this.pRef = pRef; - this.pMin = pMin; - this.pMax = pMax; - } - - @Override - public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - FlexOptions that = (FlexOptions) o; - return Objects.equals(sender, that.sender) - && Objects.equals(pRef, that.pRef) - && Objects.equals(pMin, that.pMin) - && Objects.equals(pMax, that.pMax); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), sender, pRef, pMin, pMax); - } - - @Override - public String toString() { - return "FlexOptions{" - + "receiver=" - + receiver - + ", sender=" - + sender - + ", pRef=" - + pRef - + ", pMin=" - + pMin - + ", pMax=" - + pMax - + ", delay=" - + delay - + '}'; - } -} +/** + * Flex option that will be sent to SIMONA. + * + * @param receiver The receiver of the message. + * @param sender The sender of the request. + * @param pRef Active power (might be negative, thus feed-in) that was suggested for regular usage. + * @param pMin Minimal active power to which the sender can be reduced (might be negative, thus + * feed-in), that was determined by the system. Therefore, equates to lower bound of possible + * flexibility provision. + * @param pMax Maximum active power to which the sender can be increased (might be negative, thus + * feed-in), that was determined by the system. Therefore, equates to upper bound of possible + * flexibility provision. + */ +public record FlexOptions( + UUID receiver, + UUID sender, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax) {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java index 722b4972..27f891fb 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java +++ b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java @@ -17,4 +17,8 @@ public record ProvideResultEntities(List results) public ProvideResultEntities(Map resultMap) { this(resultMap.values().stream().toList()); } + + public ProvideResultEntities(ResultEntity result) { + this(List.of(result)); + } } 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 592618da..8cdbdf1e 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -6,8 +6,6 @@ package edu.ie3.simona.api.simulation; -import static java.util.Collections.emptyList; - import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.ExtDataContainerQueue; @@ -19,11 +17,11 @@ import edu.ie3.simona.api.data.model.em.EmSetPoint; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; import edu.ie3.simona.api.mapping.DataType; -import java.util.*; import org.slf4j.Logger; -import tech.units.indriya.ComparableQuantity; -import javax.measure.quantity.Time; +import java.util.*; + +import static java.util.Collections.emptyList; /** * Abstract class for an external co-simulation with bidirectional communication with SIMONA. @@ -75,16 +73,13 @@ public static ExtPrimaryDataConnection buildPrimaryConnection( * Builds an {@link ExtEmDataConnection}. * * @param controlled uuids for controlled em agents. - * @param maxDelay the maximal delay used in em communication mode * @param log logger * @return an ext em data connection */ public static ExtEmDataConnection buildEmConnection( - List controlled, ExtEmDataConnection.EmMode mode, Optional> maxDelay, Logger log) { - if (maxDelay.isEmpty() && mode == ExtEmDataConnection.EmMode.EM_COMMUNICATION) { - log.info("Using em communication without a maximum delay."); - } - + List controlled, + ExtEmDataConnection.EmMode mode, + Logger log) { if (controlled.isEmpty()) { log.warn("Em data connection with 0 controlled entities created. This might lead to errors!"); throw new ExtDataConnectionException(ExtEmDataConnection.class); @@ -94,7 +89,7 @@ public static ExtEmDataConnection buildEmConnection( mode, controlled.size()); - return new ExtEmDataConnection(controlled, mode, maxDelay); + return new ExtEmDataConnection(controlled, mode); } } From 385cef10fb217697f926a19c46753c1eb1242d68 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 22 Jul 2025 12:38:28 +0200 Subject: [PATCH 55/80] Saving changes. --- .../edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java | 4 ++++ 1 file changed, 4 insertions(+) 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 52f5bff2..c4f78e76 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 @@ -23,7 +23,11 @@ public record ExtEntityEntry( UUID uuid, String id, Optional columnScheme, DataType dataType) implements InputEntity { + public ExtEntityEntry(UUID uuid, String id, DataType dataType) { + this(uuid, id, Optional.empty(), dataType); + } + @Override public String toString() { return "ExtEntityEntry={" + "UUID=" From e27cd1c2aad36cbc3f625e7359176d483a6fdf2c Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 22 Jul 2025 15:18:57 +0200 Subject: [PATCH 56/80] Updating to PSDM version 8.0 --- build.gradle | 2 +- .../simona/api/{simulation => }/mapping/ExtEntityEntry.java | 4 ++-- .../java/edu/ie3/simona/api/mapping/ExtEntityMapping.java | 1 - .../ie3/simona/api/simulation/mapping/ExtEntityFactory.java | 3 +++ .../simona/api/simulation/mapping/ExtEntityMappingSource.java | 2 ++ .../edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy | 1 - .../api/simulation/mapping/ExtEntityMappingSourceTest.groovy | 1 + 7 files changed, 9 insertions(+), 5 deletions(-) rename src/main/java/edu/ie3/simona/api/{simulation => }/mapping/ExtEntityEntry.java (92%) diff --git a/build.gradle b/build.gradle index a00cfc10..c4953f5a 100644 --- a/build.gradle +++ b/build.gradle @@ -62,7 +62,7 @@ dependencies{ } //PSDM - implementation('com.github.ie3-institute:PowerSystemDataModel:7.0.0') { + implementation('com.github.ie3-institute:PowerSystemDataModel:8.0.0') { exclude group: 'org.apache.logging.log4j' exclude group: 'org.slf4j' /* Exclude our own nested dependencies */ diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityEntry.java similarity index 92% rename from src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java rename to src/main/java/edu/ie3/simona/api/mapping/ExtEntityEntry.java index c4f78e76..c3f01e1d 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityEntry.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityEntry.java @@ -4,11 +4,11 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.api.simulation.mapping; +package edu.ie3.simona.api.mapping; import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; import edu.ie3.datamodel.models.input.InputEntity; -import edu.ie3.simona.api.mapping.DataType; + import java.util.Optional; import java.util.UUID; diff --git a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java index 301dd994..62703a3d 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java @@ -6,7 +6,6 @@ package edu.ie3.simona.api.mapping; -import edu.ie3.simona.api.simulation.mapping.ExtEntityEntry; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; 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 4b79cca4..d095a74c 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 @@ -12,11 +12,14 @@ import edu.ie3.datamodel.io.factory.EntityFactory; import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; import edu.ie3.simona.api.mapping.DataType; +import edu.ie3.simona.api.mapping.ExtEntityEntry; + import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; /** Class to build a mapping entry from the external simulation to SIMONA */ +@Deprecated public class ExtEntityFactory extends EntityFactory { public static final String SIMONA_UUID = "uuid"; diff --git a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java index db03893d..354dd706 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java +++ b/src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSource.java @@ -13,12 +13,14 @@ import edu.ie3.datamodel.io.source.DataSource; import edu.ie3.datamodel.io.source.csv.CsvDataSource; import edu.ie3.datamodel.models.Entity; +import edu.ie3.simona.api.mapping.ExtEntityEntry; import edu.ie3.simona.api.mapping.ExtEntityMapping; import java.nio.file.Path; import java.util.Map; import java.util.Optional; /** Source for external entity mapping. */ +@Deprecated public class ExtEntityMappingSource { protected final DataSource dataSource; diff --git a/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy b/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy index c4b4f3bc..e5d27000 100644 --- a/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy @@ -1,7 +1,6 @@ package edu.ie3.simona.api.mapping import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme -import edu.ie3.simona.api.simulation.mapping.ExtEntityEntry import spock.lang.Shared import spock.lang.Specification diff --git a/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy b/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy index ebebf43f..15f5bcbe 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingSourceTest.groovy @@ -2,6 +2,7 @@ package edu.ie3.simona.api.simulation.mapping import edu.ie3.datamodel.models.input.NodeInput import edu.ie3.simona.api.mapping.DataType +import edu.ie3.simona.api.mapping.ExtEntityEntry import spock.lang.Specification import java.nio.file.Path From d5460fbd2303fe68ab6ceff4400d95ca35171979 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 22 Jul 2025 16:33:36 +0200 Subject: [PATCH 57/80] Saving changes. --- .../connection/ExtOutputDataConnection.java | 2 +- .../ie3/simona/api/mapping/ExtEntityEntry.java | 17 ----------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java index 23dab268..441218e2 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java @@ -14,7 +14,7 @@ * * @param type of response messages to ext */ -public sealed interface ExtOutputDataConnection +public sealed interface ExtOutputDataConnection extends ExtDataConnection permits BiDirectional, ExtResultListener { /** Queues message from SIMONA that should be handled by the external simulation. */ diff --git a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityEntry.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityEntry.java index c3f01e1d..f35b0b87 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityEntry.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityEntry.java @@ -26,21 +26,4 @@ public record ExtEntityEntry( public ExtEntityEntry(UUID uuid, String id, DataType dataType) { this(uuid, id, Optional.empty(), dataType); } - - @Override - public String toString() { - return "ExtEntityEntry={" - + "UUID=" - + uuid - + ", " - + "extId=" - + id - + ", " - + "columnScheme=" - + columnScheme - + ", " - + "dataType=" - + dataType - + "}"; - } } From cea773c2c872b922375973e89104207810392513 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 8 Aug 2025 11:10:34 +0200 Subject: [PATCH 58/80] Saving changes. --- .../ie3/simona/api/ontology/results/ProvideResultEntities.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java index 27f891fb..4d7469d3 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java +++ b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java @@ -21,4 +21,6 @@ public ProvideResultEntities(Map resultMap) { public ProvideResultEntities(ResultEntity result) { this(List.of(result)); } + + public static ProvideResultEntities empty() { return new ProvideResultEntities(List.of()); } } From f738db703e9237a91baa28ac22f8b55975103310 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 13 Aug 2025 09:34:04 +0200 Subject: [PATCH 59/80] Update to java21. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 081cde7f..7cdbb012 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ plugins { } ext { - javaVersion = JavaVersion.VERSION_17 + javaVersion = JavaVersion.VERSION_21 scriptsLocation = 'gradle' + File.separator + 'scripts' + File.separator // location of script plugins // required for pekko @@ -84,7 +84,7 @@ dependencies{ testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0' } -task printVersion { +tasks.register('printVersion') { doLast { println project.version } From 766e02724398fba07a28af0feedd131be432455c Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 20 Aug 2025 16:45:18 +0200 Subject: [PATCH 60/80] Saving changes. --- .../connection/ExtResultDataConnection.java | 48 +++++++++---------- .../data/container/ExtResultContainer.java | 31 ++++++------ .../results/ProvideResultEntities.java | 12 ++--- .../api/simulation/ExtCoSimulation.java | 4 +- 4 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtResultDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtResultDataConnection.java index 76c77b45..47378e32 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtResultDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtResultDataConnection.java @@ -11,10 +11,10 @@ import edu.ie3.simona.api.ontology.results.RequestResultEntities; import edu.ie3.simona.api.ontology.results.ResultDataMessageFromExt; import edu.ie3.simona.api.ontology.results.ResultDataResponseMessageToExt; + import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.stream.Collectors; import java.util.stream.Stream; /** Enables data connection of results between SIMONA and SimonaAPI. */ @@ -51,48 +51,48 @@ public List getFlexOptionAssets() { /** Method for requesting SIMONA results as list from an external simulation. */ private List requestResultList(long tick) throws InterruptedException { - List allExtEntities = - Stream.concat( - Stream.concat(getFlexOptionAssets().stream(), getGridResultDataAssets().stream()), - getParticipantResultDataAssets().stream()) - .toList(); - sendExtMsg(new RequestResultEntities(tick, allExtEntities)); - return receiveWithType(ProvideResultEntities.class).results(); + return createResultList(requestResults(tick)); } private List requestFlexOptionResultsList(long tick) throws InterruptedException { - sendExtMsg(new RequestResultEntities(tick, getFlexOptionAssets())); - return receiveWithType(ProvideResultEntities.class).results(); + return createResultList(requestFlexOptionResults(tick)); } private List requestGridResultsList(long tick) throws InterruptedException { - sendExtMsg(new RequestResultEntities(tick, getGridResultDataAssets())); - return receiveWithType(ProvideResultEntities.class).results(); + return createResultList(requestGridResults(tick)); } private List requestParticipantResultsList(long tick) throws InterruptedException { - sendExtMsg(new RequestResultEntities(tick, getParticipantResultDataAssets())); - return receiveWithType(ProvideResultEntities.class).results(); + return createResultList(requestParticipantResults(tick)); } /** Method for requesting SIMONA results as a map uuid to object from an external simulation. */ - public Map requestResults(long tick) throws InterruptedException { - return createResultMap(requestResultList(tick)); + public Map> requestResults(long tick) throws InterruptedException { + List allExtEntities = + Stream.concat( + Stream.concat(getFlexOptionAssets().stream(), getGridResultDataAssets().stream()), + getParticipantResultDataAssets().stream()) + .toList(); + sendExtMsg(new RequestResultEntities(tick, allExtEntities)); + return receiveWithType(ProvideResultEntities.class).results(); } - public Map requestFlexOptionResults(long tick) throws InterruptedException { - return createResultMap(requestFlexOptionResultsList(tick)); + public Map> requestFlexOptionResults(long tick) throws InterruptedException { + sendExtMsg(new RequestResultEntities(tick, getFlexOptionAssets())); + return receiveWithType(ProvideResultEntities.class).results(); } - public Map requestGridResults(long tick) throws InterruptedException { - return createResultMap(requestGridResultsList(tick)); + public Map> requestGridResults(long tick) throws InterruptedException { + sendExtMsg(new RequestResultEntities(tick, getGridResultDataAssets())); + return receiveWithType(ProvideResultEntities.class).results(); } - public Map requestParticipantResults(long tick) throws InterruptedException { - return createResultMap(requestParticipantResultsList(tick)); + public Map> requestParticipantResults(long tick) throws InterruptedException { + sendExtMsg(new RequestResultEntities(tick, getParticipantResultDataAssets())); + return receiveWithType(ProvideResultEntities.class).results(); } - private Map createResultMap(List results) { - return results.stream().collect(Collectors.toMap(ResultEntity::getInputModel, i -> i)); + private List createResultList(Map> results) { + return results.values().stream().flatMap(List::stream).toList(); } } diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java index 9ef5df37..5bb6e5ba 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java @@ -7,10 +7,9 @@ package edu.ie3.simona.api.data.container; import edu.ie3.datamodel.models.result.ResultEntity; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; + +import java.util.*; +import java.util.stream.Collectors; /** Contains all SIMONA results for a certain tick. */ public final class ExtResultContainer implements ExtDataContainer { @@ -27,7 +26,7 @@ public final class ExtResultContainer implements ExtDataContainer { *

ATTENTION: The time stamp of the result entities is not necessarily corresponding to the * tick */ - private final Map resultMap; + private final Map> resultMap; /** * Container class for result data from SIMONA. @@ -36,14 +35,14 @@ public final class ExtResultContainer implements ExtDataContainer { * @param resultMap results from SIMONA with external id as key * @param nextTick tick the external simulation can expect the next results */ - public ExtResultContainer(long tick, Map resultMap, Optional nextTick) { + public ExtResultContainer(long tick, Map> resultMap, Optional nextTick) { this.tick = tick; this.resultMap = resultMap; this.maybeNextTick = nextTick; } public ExtResultContainer(long tick, Map resultMap) { - this(tick, resultMap, Optional.empty()); + this(tick, resultMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, i -> List.of(i.getValue()))), Optional.empty()); } @Override @@ -52,7 +51,7 @@ public boolean isEmpty() { } /** Returns a map: uuid to result. */ - public Map getResults() { + public Map> getResults() { return resultMap; } @@ -68,13 +67,17 @@ public Map getResults() { public Map getResults(Class clazz) { Map result = new HashMap<>(); - for (Map.Entry entry : resultMap.entrySet()) { - ResultEntity resultEntity = entry.getValue(); + for (Map.Entry> entry : resultMap.entrySet()) { + List resultEntities = entry.getValue(); + + for (ResultEntity resultEntity : resultEntities) { + if (resultEntity.getClass().equals(clazz)) { + // add the result, if the found result is of the requested type + result.put(entry.getKey(), (R) resultEntity); + } - if (entry.getValue().getClass().equals(clazz)) { - // add the result, if the found result is of the requested type - result.put(entry.getKey(), (R) resultEntity); } + } return result; @@ -91,7 +94,7 @@ public Optional getMaybeNextTick() { } /** Returns the result for a certain asset. */ - public ResultEntity getResult(UUID assetId) { + public List getResult(UUID assetId) { return resultMap.get(assetId); } } diff --git a/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java index 4d7469d3..23881fdb 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java +++ b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java @@ -10,17 +10,13 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; /** Provides a list of results from SIMONA to an external simulation. */ -public record ProvideResultEntities(List results) +public record ProvideResultEntities(Map> results) implements ResultDataResponseMessageToExt { - public ProvideResultEntities(Map resultMap) { - this(resultMap.values().stream().toList()); - } - public ProvideResultEntities(ResultEntity result) { - this(List.of(result)); + public ProvideResultEntities(List resultEntities) { + this(resultEntities.stream().collect(Collectors.groupingBy(ResultEntity::getInputModel))); } - - public static ProvideResultEntities empty() { return new ProvideResultEntities(List.of()); } } 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 8cdbdf1e..efe18a79 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -282,7 +282,7 @@ protected void sendResultToExt( ExtResultDataConnection connection, long tick, Optional maybeNextTick, Logger log) throws InterruptedException { log.debug("Request results from SIMONA!"); - Map resultsToBeSend = connection.requestResults(tick); + Map> resultsToBeSend = connection.requestResults(tick); log.debug("Received results from SIMONA!"); queueToExt.queueData(new ExtResultContainer(tick, resultsToBeSend, maybeNextTick)); log.debug("Sent results to {}", extSimulatorName); @@ -290,7 +290,7 @@ protected void sendResultToExt( private void sendSingleResultType( String type, - Map resultsToBeSend, + Map> resultsToBeSend, long tick, Optional nextTick, Logger log) From abddecf7d78c9249c5b66c5a77f6b9aec98b2d19 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 25 Aug 2025 09:22:49 +0200 Subject: [PATCH 61/80] Saving changes. --- .../edu/ie3/simona/api/data/container/ExtResultContainer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java index 5bb6e5ba..19695c0c 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java @@ -95,6 +95,6 @@ public Optional getMaybeNextTick() { /** Returns the result for a certain asset. */ public List getResult(UUID assetId) { - return resultMap.get(assetId); + return resultMap.getOrDefault(assetId, Collections.emptyList()); } } From 7e3c93a9edfb87afe863d73341ce63a027b1ccc3 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 26 Aug 2025 17:06:33 +0200 Subject: [PATCH 62/80] Saving changes. --- .../java/edu/ie3/simona/api/ontology/em/EmResults.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/EmResults.java diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/EmResults.java b/src/main/java/edu/ie3/simona/api/ontology/em/EmResults.java new file mode 100644 index 00000000..c45590bd --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/EmResults.java @@ -0,0 +1,9 @@ +package edu.ie3.simona.api.ontology.em; + +import edu.ie3.datamodel.models.result.ResultEntity; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public record EmResults(Map> emResults) implements EmDataResponseMessageToExt {} From 013ba3295d247d31f60a79654e32aad48799929f Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 1 Sep 2025 09:39:42 +0200 Subject: [PATCH 63/80] Saving changes. --- .../data/connection/ExtEmDataConnection.java | 4 ++-- .../simona/api/ontology/em/ProvideEmData.java | 19 +++++++++++++++++++ .../api/ontology/em/RequestEmCompletion.java | 5 ++++- 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmData.java diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index ea2ce3a3..a4e53fc4 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java @@ -110,8 +110,8 @@ public Map requestEmFlexResults( * @param tick for which the em service should stop * @return an option for the next tick in SIMONA */ - public Optional requestCompletion(long tick) throws InterruptedException { - sendExtMsg(new RequestEmCompletion(tick)); + public Optional requestCompletion(long tick, long nextTick) throws InterruptedException { + sendExtMsg(new RequestEmCompletion(tick, Optional.of(nextTick))); return receiveWithType(EmCompletion.class).maybeNextTick(); } diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmData.java b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmData.java new file mode 100644 index 00000000..0ab30908 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmData.java @@ -0,0 +1,19 @@ +package edu.ie3.simona.api.ontology.em; + +import edu.ie3.simona.api.data.model.em.EmSetPoint; +import edu.ie3.simona.api.data.model.em.FlexOptionRequest; +import edu.ie3.simona.api.data.model.em.FlexOptions; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +/** Message that provides em data from an external simulation. */ +public record ProvideEmData( + long tick, + Map flexRequests, + Map> flexOptions, + Map setPoints, + Optional maybeNextTick +) implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java b/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java index fc6f5b18..e024ed0a 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java @@ -6,9 +6,12 @@ package edu.ie3.simona.api.ontology.em; +import java.util.Optional; + /** * Request send to SIMONA to finish the em service. * * @param tick for which the em service should be finished + * @param maybeNextTick option for the next tick */ -public record RequestEmCompletion(long tick) implements EmDataMessageFromExt {} +public record RequestEmCompletion(long tick, Optional maybeNextTick) implements EmDataMessageFromExt {} From 17534c168d2617b22aef007f24b78f51bc24b365 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 1 Sep 2025 14:03:30 +0200 Subject: [PATCH 64/80] Saving changes. --- .../data/connection/ExtEmDataConnection.java | 56 ++++++++----------- .../api/data/model/em/FlexOptionRequest.java | 7 ++- .../model/em/FlexOptionRequestResult.java | 21 ++++++- .../simona/api/ontology/em/EmCompletion.java | 2 +- .../{EmResults.java => EmResultResponse.java} | 2 +- .../ontology/em/EmSetPointDataResponse.java | 15 ----- .../api/ontology/em/FlexRequestResponse.java | 15 ----- .../ontology/em/ProvideEmFlexOptionData.java | 18 ------ .../ontology/em/ProvideFlexRequestData.java | 17 ------ .../api/ontology/em/RequestEmCompletion.java | 2 +- .../connection/ExtEmDataConnectionTest.groovy | 14 ++--- 11 files changed, 54 insertions(+), 115 deletions(-) rename src/main/java/edu/ie3/simona/api/ontology/em/{EmResults.java => EmResultResponse.java} (59%) delete mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java delete mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/FlexRequestResponse.java delete mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java delete mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index a4e53fc4..2012b4a0 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java @@ -36,40 +36,28 @@ public List getControlledEms() { return new ArrayList<>(controlled); } - /** - * Sends the em flex requests to SIMONA. - * - * @param tick current tick - * @param data receiver to flex request, that should be sent to SIMONA - * @param maybeNextTick option for the next tick in the simulation - * @param log logger - */ - public void sendFlexRequests( - long tick, Map data, Optional maybeNextTick, Logger log) { - if (data.isEmpty()) { - log.debug("No em flex requests found! Sending no em data to SIMONA for tick {}.", tick); - } else { - log.debug("Provided SIMONA with em flex requests."); - sendExtMsg(new ProvideFlexRequestData(tick, data, maybeNextTick)); - } - } - - /** - * Sends the em flex options to SIMONA. - * - * @param tick current tick - * @param data receiver to flex options, that should be sent to SIMONA - * @param maybeNextTick option for the next tick in the simulation - * @param log logger - */ - public void sendFlexOptions( - long tick, Map> data, Optional maybeNextTick, Logger log) { - if (data.isEmpty()) { - log.debug("No em flex options found! Sending no em data to SIMONA for tick {}.", tick); - } else { - log.debug("Provided SIMONA with em flex options."); - sendExtMsg(new ProvideEmFlexOptionData(tick, data, maybeNextTick)); - } + /** + * Tries to send em data to SIMONA. A message is sent, if at least one map is not empty. + * @param tick current tick + * @param flexRequests receiver to flex option request + * @param flexOptions receiver to flex options + * @param setPoints receiver to set point + * @param maybeNextTick option for the next tick in the simulation + * @return true, if a message was sent + */ + public boolean sendEmData( + long tick, + Map flexRequests, + Map> flexOptions, + Map setPoints, + Optional maybeNextTick + ) { + // send message only if at least one value is present + if (!flexRequests.isEmpty() || !flexOptions.isEmpty() || !setPoints.isEmpty()) { + sendExtMsg(new ProvideEmData(tick, flexRequests, flexOptions, setPoints, maybeNextTick)); + return true; + } + return false; } /** diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java index 5c91c29a..d2b9c3ab 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java @@ -14,8 +14,9 @@ * * @param receiver The receiver of the message. * @param sender The sender of the request. + * @param disaggregated True, if disaggregated flex options should be returned. */ -public record FlexOptionRequest(UUID receiver, Optional sender) { +public record FlexOptionRequest(UUID receiver, Optional sender, boolean disaggregated) { /** * Constructor for {@link FlexOptionRequest}. Equals {@code new FlexOptionRequest(receiver, * Optional.empty())}. @@ -23,7 +24,7 @@ public record FlexOptionRequest(UUID receiver, Optional sender) { * @param receiver of the request */ public FlexOptionRequest(UUID receiver) { - this(receiver, Optional.empty()); + this(receiver, Optional.empty(), false); } /** @@ -33,6 +34,6 @@ public FlexOptionRequest(UUID receiver) { * @param sender of the request */ public FlexOptionRequest(UUID receiver, UUID sender) { - this(receiver, Optional.ofNullable(sender)); + this(receiver, Optional.ofNullable(sender), false); } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequestResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequestResult.java index d0a70687..de4209d8 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequestResult.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequestResult.java @@ -16,16 +16,23 @@ public final class FlexOptionRequestResult extends ResultEntity { /** The uuids of the receivers. */ private final List receivers; + /** + * True, if disaggregated flex option should be returned. + */ + private final boolean disaggregated; + /** * Constructor of a {@link FlexOptionRequest}. * * @param time date and time when the result is produced * @param sender uuid of the input model that produces the result * @param receivers a collection of receivers + * @param disaggregated if true, disaggregated flex option are requested */ - public FlexOptionRequestResult(ZonedDateTime time, UUID sender, Collection receivers) { + public FlexOptionRequestResult(ZonedDateTime time, UUID sender, Collection receivers, boolean disaggregated) { super(time, sender); this.receivers = new ArrayList<>(receivers); + this.disaggregated = disaggregated; } /** Returns the uuid of the sender. */ @@ -41,12 +48,20 @@ public List getReceivers() { return receivers; } + /** + * + * Returns true, if disaggregated flex options should be returned. + */ + public boolean isDisaggregated() { + return disaggregated; + } + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; FlexOptionRequestResult that = (FlexOptionRequestResult) o; - return Objects.equals(receivers, that.receivers); + return Objects.equals(receivers, that.receivers) && Objects.equals(disaggregated, that.disaggregated); } @Override @@ -63,6 +78,8 @@ public String toString() { + getInputModel() + ", receivers=" + receivers + + ", disaggregated=" + + disaggregated + '}'; } } diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/EmCompletion.java b/src/main/java/edu/ie3/simona/api/ontology/em/EmCompletion.java index 12bc1709..0c1ac6f5 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/EmCompletion.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/EmCompletion.java @@ -9,7 +9,7 @@ import java.util.Optional; /** - * Response send from SIMONA after the em service is finished. + * Response send from SIMONA after the em service is finished for the current tick. * * @param maybeNextTick option for the next tick in SIMONA */ diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/EmResults.java b/src/main/java/edu/ie3/simona/api/ontology/em/EmResultResponse.java similarity index 59% rename from src/main/java/edu/ie3/simona/api/ontology/em/EmResults.java rename to src/main/java/edu/ie3/simona/api/ontology/em/EmResultResponse.java index c45590bd..d236eb82 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/EmResults.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/EmResultResponse.java @@ -6,4 +6,4 @@ import java.util.Map; import java.util.UUID; -public record EmResults(Map> emResults) implements EmDataResponseMessageToExt {} +public record EmResultResponse(Map> emResults) implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java b/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java deleted file mode 100644 index c7a6c6e5..00000000 --- a/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * © 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.ontology.em; - -import edu.ie3.simona.api.data.model.em.EmSetPointResult; -import java.util.Map; -import java.util.UUID; - -/** Message that provides em data (set points) to an external simulation. */ -public record EmSetPointDataResponse(Map emData) - implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/FlexRequestResponse.java b/src/main/java/edu/ie3/simona/api/ontology/em/FlexRequestResponse.java deleted file mode 100644 index a2739e0e..00000000 --- a/src/main/java/edu/ie3/simona/api/ontology/em/FlexRequestResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -/* - * © 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.ontology.em; - -import edu.ie3.simona.api.data.model.em.FlexOptionRequestResult; -import java.util.Map; -import java.util.UUID; - -/** Message that provides em data (flexibility requests) to an external simulation. */ -public record FlexRequestResponse(Map flexRequests) - implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java deleted file mode 100644 index 3d8d0e53..00000000 --- a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * © 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.ontology.em; - -import edu.ie3.simona.api.data.model.em.FlexOptions; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; - -/** Message that provides em data (flexibility options) from an external simulation. */ -public record ProvideEmFlexOptionData( - long tick, Map> flexOptions, Optional maybeNextTick) - implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java deleted file mode 100644 index 4013e748..00000000 --- a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * © 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.ontology.em; - -import edu.ie3.simona.api.data.model.em.FlexOptionRequest; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; - -/** Message that provides em data (flex requests) from an external simulation. */ -public record ProvideFlexRequestData( - long tick, Map flexRequests, Optional maybeNextTick) - implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java b/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java index e024ed0a..b280208c 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java @@ -9,7 +9,7 @@ import java.util.Optional; /** - * Request send to SIMONA to finish the em service. + * Request send to SIMONA to finish the em service for the given tick. * * @param tick for which the em service should be finished * @param maybeNextTick option for the next tick diff --git a/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy index 4a26a52b..f877c051 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy @@ -44,10 +44,10 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa def emData = Map.of(inputUuid, new FlexOptionRequest(inputUuid)) when: - extEmDataConnection.sendFlexRequests(0L, emData, Optional.of(900L), log) + extEmDataConnection.sendEmData(0L, emData, [:], [:], Optional.of(900L), log) then: - dataService.expectMessage(new ProvideFlexRequestData(0, emData, Optional.of(900L))) + dataService.expectMessage(new ProvideEmData(0, emData, [:], [:], Optional.of(900L))) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) } @@ -60,10 +60,9 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa dataService.ref(), extSimAdapter.ref() ) - def inputDataMap = [:] as Map when: - extEmDataConnection.sendFlexRequests(0L, inputDataMap, Optional.of(900L), log) + extEmDataConnection.sendEmData(0L, [:], [:], [:], Optional.of(900L), log) then: dataService.expectNoMessage() @@ -82,10 +81,10 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa def emData = Map.of(inputUuid, [new FlexOptions(inputUuid, UUID.randomUUID(), power, power, power)]) when: - extEmDataConnection.sendFlexOptions(0L, emData, Optional.of(900L), log) + extEmDataConnection.sendEmData(0L, [:], emData, [:], Optional.of(900L), log) then: - dataService.expectMessage(new ProvideEmFlexOptionData(0, emData, Optional.of(900L))) + dataService.expectMessage(new ProvideEmData(0, [:], emData, [:], Optional.of(900L))) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) } @@ -98,10 +97,9 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa dataService.ref(), extSimAdapter.ref() ) - def inputDataMap = [:] as Map when: - extEmDataConnection.sendFlexRequests(0L, inputDataMap, Optional.of(900L), log) + extEmDataConnection.sendEmData(0L, [:], [:], [:], Optional.of(900L), log) then: dataService.expectNoMessage() From 8dc61aac736d7404f5f74365a55e3e9bfd69da57 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 1 Sep 2025 14:48:22 +0200 Subject: [PATCH 65/80] Saving changes. --- .../simona/api/data/model/em/FlexOptionRequest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java index d2b9c3ab..531e0f64 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java @@ -36,4 +36,14 @@ public FlexOptionRequest(UUID receiver) { public FlexOptionRequest(UUID receiver, UUID sender) { this(receiver, Optional.ofNullable(sender), false); } + + /** + * Constructor for {@link FlexOptionRequest}. + * + * @param receiver of the request + * @param sender option for the sender of the request + */ + public FlexOptionRequest(UUID receiver, Optional sender) { + this(receiver, sender, false); + } } From b57f1f216576fff41dcb929ff548a633c7b832b1 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 2 Sep 2025 17:36:42 +0200 Subject: [PATCH 66/80] Saving changes. --- .../ie3/simona/api/ontology/results/ProvideResultEntities.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java index 9be21e05..21c724a2 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java +++ b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java @@ -21,6 +21,6 @@ public ProvideResultEntities(List resultEntities) { } public ProvideResultEntities(ResultEntity result) { - this(List.of(result)); + this(Map.of(result.getInputModel(), List.of(result))); } } From e38bd47f88c7cc9d28c779ef6400b154239d6da2 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 3 Sep 2025 11:25:17 +0200 Subject: [PATCH 67/80] Saving changes. --- .../data/container/ExtOutputContainer.java | 2 +- .../simona/api/data/model/em/FlexOptions.java | 12 +++++ .../api/simulation/ExtCoSimulation.java | 52 ++----------------- 3 files changed, 16 insertions(+), 50 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java index f49a0920..c6ee88ca 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java @@ -133,6 +133,6 @@ public List getResult(UUID assetId) { /** Returns the em data for a certain asset. */ public List getEmData(UUID assetId) { - return emDataMap.get(assetId); + return emDataMap.getOrDefault(assetId, Collections.emptyList()); } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java index bb371945..0612a2e6 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java @@ -44,6 +44,18 @@ public FlexOptions( this(receiver, sender, pRef, pMin, pMax, Collections.emptyMap()); } + public ExtendedFlexOptionsResult asResult() { + return new ExtendedFlexOptionsResult( + null, + sender, + receiver, + pRef, + pMin, + pMax, + disaggregated + ); + } + @Override public UUID getReceiver() { return receiver; 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 a60df5fa..e3c8fe6b 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -176,13 +176,11 @@ protected void sendFlexOptionsToExt( throws InterruptedException { log.debug("Request results from SIMONA!"); - Map results = - new HashMap<>( - extEmDataConnection.requestEmFlexResults( - tick, extEmDataConnection.getControlledEms(), disaggregated)); + ExtOutputContainer container = new ExtOutputContainer(tick); + extEmDataConnection.requestEmFlexResults(tick, extEmDataConnection.getControlledEms(), disaggregated).forEach(container::addResult); log.debug("Received results from SIMONA!"); - queueToExt.queueData(new ExtResultContainer(tick, results)); + queueToExt.queueData(container); log.debug("Sent results to {}", extSimulatorName); } @@ -234,38 +232,6 @@ protected void sendEmSetPointsToSimona( // result data methods - /** - * Function to send only participant result data from SIMONA to the external simulation using the - * given {@link ExtResultDataConnection} - */ - protected void sendParticipantResultsToExt( - ExtResultDataConnection connection, long tick, Optional nextTick, Logger log) - throws InterruptedException { - sendSingleResultType( - "participant", connection.requestParticipantResults(tick), tick, nextTick, log); - } - - /** - * 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 { - sendSingleResultType("grid", connection.requestGridResults(tick), tick, nextTick, log); - } - - /** - * 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 { - sendSingleResultType( - "flex option", connection.requestFlexOptionResults(tick), tick, nextTick, log); - } - /** * Function to send all result data from SIMONA to the external simulation using the given {@link * ExtResultDataConnection} @@ -288,16 +254,4 @@ protected void sendResultToExt( log.debug("Sent results to {}", extSimulatorName); } - 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); - - queueToExt.queueData(new ExtResultContainer(tick, resultsToBeSend, nextTick)); - log.info("Sent {} results for tick {} to {}", type, tick, extSimulatorName); - } } From 9a487e1914c498c6f0fc6a5333bfd6fa8b46e50f Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 10 Sep 2025 16:31:48 +0200 Subject: [PATCH 68/80] Saving changes. --- .../simona/api/simulation/ExtSimAdapterData.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java b/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java index a1af39fa..32d93966 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java @@ -6,6 +6,7 @@ package edu.ie3.simona.api.simulation; +import edu.ie3.datamodel.models.input.container.JointGridContainer; import edu.ie3.simona.api.ontology.simulation.ControlMessageToExt; import edu.ie3.simona.api.ontology.simulation.ControlResponseMessageFromExt; import java.util.concurrent.LinkedBlockingQueue; @@ -23,12 +24,18 @@ public class ExtSimAdapterData { /** CLI arguments with which SIMONA is initiated */ private final String[] mainArgs; + /** + * The electrical grid. + */ + private final JointGridContainer grid; + // important trigger queue must be the same as held in actor // to make it safer one might consider asking the actor for a reference on its trigger queue?! public ExtSimAdapterData( - ActorRef extSimAdapter, String[] mainArgs) { + ActorRef extSimAdapter, String[] mainArgs, JointGridContainer grid) { this.extSimAdapter = extSimAdapter; this.mainArgs = mainArgs; + this.grid = grid; } public ActorRef getAdapter() { @@ -59,4 +66,8 @@ public void send(ControlResponseMessageFromExt msg) { public String[] getMainArgs() { return mainArgs; } + + public JointGridContainer getGrid() { + return grid; + } } From 20cb5f6a13d2f1350e0ff4c0f48ca89d7c6069d6 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 11 Sep 2025 11:31:38 +0200 Subject: [PATCH 69/80] Saving changes. --- .../api/simulation/ExtSimAdapterData.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java b/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java index 32d93966..b4b471ad 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java @@ -6,6 +6,7 @@ package edu.ie3.simona.api.simulation; +import com.typesafe.config.Config; import edu.ie3.datamodel.models.input.container.JointGridContainer; import edu.ie3.simona.api.ontology.simulation.ControlMessageToExt; import edu.ie3.simona.api.ontology.simulation.ControlResponseMessageFromExt; @@ -24,17 +25,19 @@ public class ExtSimAdapterData { /** CLI arguments with which SIMONA is initiated */ private final String[] mainArgs; - /** - * The electrical grid. - */ + /** The parsed simona config. */ + private final Config simonaConfig; + + /** The electrical grid. */ private final JointGridContainer grid; // important trigger queue must be the same as held in actor // to make it safer one might consider asking the actor for a reference on its trigger queue?! public ExtSimAdapterData( - ActorRef extSimAdapter, String[] mainArgs, JointGridContainer grid) { + ActorRef extSimAdapter, String[] mainArgs, Config simonaConfig, JointGridContainer grid) { this.extSimAdapter = extSimAdapter; this.mainArgs = mainArgs; + this.simonaConfig = simonaConfig; this.grid = grid; } @@ -67,7 +70,11 @@ public String[] getMainArgs() { return mainArgs; } + public Config getSimonaConfig() { + return simonaConfig; + } + public JointGridContainer getGrid() { - return grid; + return grid; } } From b90e40462bd9349706cfe1b148b703ead82fa9e8 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 15 Sep 2025 13:55:34 +0200 Subject: [PATCH 70/80] fmt --- CHANGELOG.md | 1 - .../data/connection/ExtOutputDataConnection.java | 4 ++-- .../ontology/results/ProvideResultEntities.java | 2 +- .../simona/api/simulation/ExtCoSimulation.java | 16 +++++++--------- .../simona/api/simulation/ExtSimAdapterData.java | 11 +++++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86c88ce1..af45e37f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Refactoring data containers [#268](https://github.com/ie3-institute/simonaAPI/issues/268) - Refactoring messages [#269](https://github.com/ie3-institute/simonaAPI/issues/269) - Refactoring models [#270](https://github.com/ie3-institute/simonaAPI/issues/270) -- Refactoring result handling [#325](https://github.com/ie3-institute/simonaAPI/issues/325) - Refactoring external entity mapping [#314](https://github.com/ie3-institute/simonaAPI/issues/314) - Refactoring and simplifying ext em communication [#323](https://github.com/ie3-institute/simonaAPI/issues/323) - Refactoring result handling [#325](https://github.com/ie3-institute/simonaAPI/issues/325) diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java index 441218e2..68552672 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java @@ -14,8 +14,8 @@ * * @param type of response messages to ext */ -public sealed interface ExtOutputDataConnection extends ExtDataConnection - permits BiDirectional, ExtResultListener { +public sealed interface ExtOutputDataConnection + extends ExtDataConnection permits BiDirectional, ExtResultListener { /** Queues message from SIMONA that should be handled by the external simulation. */ void queueExtResponseMsg(T msg) throws InterruptedException; diff --git a/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java index 21c724a2..d72ecfdd 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java +++ b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java @@ -21,6 +21,6 @@ public ProvideResultEntities(List resultEntities) { } public ProvideResultEntities(ResultEntity result) { - this(Map.of(result.getInputModel(), List.of(result))); + this(Map.of(result.getInputModel(), List.of(result))); } } 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 e3c8fe6b..db077dca 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -6,6 +6,8 @@ package edu.ie3.simona.api.simulation; +import static java.util.Collections.emptyList; + import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.ExtDataContainerQueue; @@ -17,11 +19,8 @@ import edu.ie3.simona.api.data.model.em.EmSetPoint; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; import edu.ie3.simona.api.mapping.DataType; -import org.slf4j.Logger; - import java.util.*; - -import static java.util.Collections.emptyList; +import org.slf4j.Logger; /** * Abstract class for an external co-simulation with bidirectional communication with SIMONA. @@ -77,9 +76,7 @@ public static ExtPrimaryDataConnection buildPrimaryConnection( * @return an ext em data connection */ public static ExtEmDataConnection buildEmConnection( - List controlled, - ExtEmDataConnection.EmMode mode, - Logger log) { + List controlled, ExtEmDataConnection.EmMode mode, Logger log) { if (controlled.isEmpty()) { log.warn("Em data connection with 0 controlled entities created. This might lead to errors!"); throw new ExtDataConnectionException(ExtEmDataConnection.class); @@ -177,7 +174,9 @@ protected void sendFlexOptionsToExt( log.debug("Request results from SIMONA!"); ExtOutputContainer container = new ExtOutputContainer(tick); - extEmDataConnection.requestEmFlexResults(tick, extEmDataConnection.getControlledEms(), disaggregated).forEach(container::addResult); + extEmDataConnection + .requestEmFlexResults(tick, extEmDataConnection.getControlledEms(), disaggregated) + .forEach(container::addResult); log.debug("Received results from SIMONA!"); queueToExt.queueData(container); @@ -253,5 +252,4 @@ protected void sendResultToExt( queueToExt.queueData(container); log.debug("Sent results to {}", extSimulatorName); } - } diff --git a/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java b/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java index b4b471ad..aeba6ad1 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtSimAdapterData.java @@ -34,7 +34,10 @@ public class ExtSimAdapterData { // important trigger queue must be the same as held in actor // to make it safer one might consider asking the actor for a reference on its trigger queue?! public ExtSimAdapterData( - ActorRef extSimAdapter, String[] mainArgs, Config simonaConfig, JointGridContainer grid) { + ActorRef extSimAdapter, + String[] mainArgs, + Config simonaConfig, + JointGridContainer grid) { this.extSimAdapter = extSimAdapter; this.mainArgs = mainArgs; this.simonaConfig = simonaConfig; @@ -71,10 +74,10 @@ public String[] getMainArgs() { } public Config getSimonaConfig() { - return simonaConfig; - } + return simonaConfig; + } public JointGridContainer getGrid() { - return grid; + return grid; } } From f8c955292b3d4aff45c543de8c5e0e5a9558ae35 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 14 Oct 2025 14:20:40 +0200 Subject: [PATCH 71/80] Saving changes. --- .../edu/ie3/simona/api/data/ExtDataContainerQueue.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java index cbc586c0..27168173 100644 --- a/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java +++ b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java @@ -21,6 +21,13 @@ public int size() { return receiverTriggerDeque.size(); } + /** + * Method for clearing this queue. + */ + public void clear() { + receiverTriggerDeque.clear(); + } + /** * Method for adding an {@link ExtDataContainer} to the queue. * From fb1b8b02de36e170f2b02e7a25b1f9a3f89791c7 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 15 Oct 2025 15:26:44 +0200 Subject: [PATCH 72/80] Saving changes. --- .../api/data/connection/BiDirectional.java | 9 ++ .../data/connection/ExtComDataConnection.java | 52 ++++++++++ .../data/model/com/CommunicationMessage.java | 5 + .../edu/ie3/simona/api/mapping/DataType.java | 12 ++- .../simona/api/mapping/ExtEntityMapping.java | 94 +++++++++++++++---- .../ontology/com/CommunicationMessages.java | 10 ++ 6 files changed, 162 insertions(+), 20 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/data/connection/ExtComDataConnection.java create mode 100644 src/main/java/edu/ie3/simona/api/data/model/com/CommunicationMessage.java create mode 100644 src/main/java/edu/ie3/simona/api/ontology/com/CommunicationMessages.java diff --git a/src/main/java/edu/ie3/simona/api/data/connection/BiDirectional.java b/src/main/java/edu/ie3/simona/api/data/connection/BiDirectional.java index 631a1c37..c2af3002 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/BiDirectional.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/BiDirectional.java @@ -9,6 +9,9 @@ import edu.ie3.simona.api.exceptions.UnexpectedResponseMessageException; import edu.ie3.simona.api.ontology.DataMessageFromExt; import edu.ie3.simona.api.ontology.DataResponseMessageToExt; + +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.LinkedBlockingQueue; /** @@ -38,6 +41,12 @@ public final R receiveAny() throws InterruptedException { return receiveTriggerQueue.take(); } + public final List receiveAll() { + List result = new ArrayList<>(); + receiveTriggerQueue.drainTo(result); + return result; + } + @Override @SuppressWarnings("unchecked") public final T receiveWithType(Class expectedMessageClass) diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtComDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtComDataConnection.java new file mode 100644 index 00000000..7d538ad8 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtComDataConnection.java @@ -0,0 +1,52 @@ +package edu.ie3.simona.api.data.connection; + +import edu.ie3.simona.api.data.model.com.CommunicationMessage; +import edu.ie3.simona.api.ontology.com.CommunicationMessages; + +import java.util.*; + +public class ExtComDataConnection extends BiDirectional { + private final Set awaitedMessages = new HashSet<>(); + + + public ExtComDataConnection() {} + + /** + * Method for sending communication messages to SIMONA. + * @param tick current tick + * @param messages to sent to SIMONA + * @param maybeNextTick option for the next tick in the simulation + * @return true, if data was sent + */ + public boolean sendMessages(long tick, Collection> messages, Optional maybeNextTick) { + if (!messages.isEmpty()) { + // saving the message ids of all + messages.forEach(message -> awaitedMessages.remove(message.msgId())); + sendExtMsg(new CommunicationMessages(tick, messages, maybeNextTick)); + return true; + } + return false; + } + + /** + * Method to retrieve messages that should be sent to the external simulation. + * @return a list of messages + * @throws InterruptedException - on interruptions + */ + public List> retrieveMessages() throws InterruptedException { + if (awaitedMessages.isEmpty()) { + return Collections.emptyList(); + } + + List> messages = new ArrayList<>(); + + for (CommunicationMessages receivedMessage : receiveAll()) { + messages.addAll(receivedMessage.messages()); + } + + // save all message ids + messages.forEach(message -> awaitedMessages.add(message.msgId())); + + return messages; + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/model/com/CommunicationMessage.java b/src/main/java/edu/ie3/simona/api/data/model/com/CommunicationMessage.java new file mode 100644 index 00000000..a4b4213c --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/model/com/CommunicationMessage.java @@ -0,0 +1,5 @@ +package edu.ie3.simona.api.data.model.com; + +import java.util.UUID; + +public record CommunicationMessage(UUID receiver, UUID sender, UUID msgId, D content, Class dataClass) {} diff --git a/src/main/java/edu/ie3/simona/api/mapping/DataType.java b/src/main/java/edu/ie3/simona/api/mapping/DataType.java index 8f11f447..b9728679 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/DataType.java +++ b/src/main/java/edu/ie3/simona/api/mapping/DataType.java @@ -6,8 +6,11 @@ package edu.ie3.simona.api.mapping; +import java.util.List; + /** Data types. */ public enum DataType { + GENERAL, PRIMARY, RESULT, PRIMARY_RESULT, @@ -15,11 +18,16 @@ public enum DataType { /** Returns all primary types. */ public static DataType[] primaryTypes() { - return new DataType[] {PRIMARY, PRIMARY_RESULT}; + return new DataType[] {PRIMARY, PRIMARY_RESULT, GENERAL}; } /** Returns all result types. */ public static DataType[] resultTypes() { - return new DataType[] {RESULT, PRIMARY_RESULT}; + return new DataType[] {RESULT, PRIMARY_RESULT, GENERAL}; + } + + public static List getExceptGeneral() { + return List.of(PRIMARY, PRIMARY_RESULT, RESULT, EM); } + } diff --git a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java index 62703a3d..2ae709c9 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java @@ -15,9 +15,51 @@ public class ExtEntityMapping { private final Map> extEntities; + private final Map> assets = new HashMap<>(); + private final Map uuidToId = new HashMap<>(); + private final Map idToUUID = new HashMap<>(); + public ExtEntityMapping(List extEntityEntryList) { - this.extEntities = - extEntityEntryList.stream().collect(Collectors.groupingBy(ExtEntityEntry::dataType)); + this.extEntities = extEntityEntryList.stream().collect(Collectors.groupingBy(ExtEntityEntry::dataType)); + + // handling of general mapping (from grid container) + List simonaUUIDs = new ArrayList<>(); + assets.put(DataType.GENERAL, simonaUUIDs); + + extEntities.getOrDefault(DataType.GENERAL, Collections.emptyList()).forEach(entry -> { + UUID uuid = entry.uuid(); + String id = entry.id(); + + idToUUID.put(id, uuid); + uuidToId.put(uuid, id); + simonaUUIDs.add(uuid); + }); + + // handling of mapping from external simulation + for (DataType dataType : DataType.getExceptGeneral()) { + if (extEntities.containsKey(dataType)) { + List entries = extEntities.get(dataType); + + List uuids = new ArrayList<>(); + + entries.forEach(entry -> { + UUID uuid = entry.uuid(); + String id = entry.id(); + + idToUUID.put(id, uuid); + uuidToId.put(uuid, id); + uuids.add(uuid); + }); + + assets.put(dataType, uuids); + } + } + } + + public ExtEntityMapping updateWith(List additional) { + List entries = allEntries(); + entries.addAll(additional); + return new ExtEntityMapping(entries); } /** Returns the data types of this mapping. */ @@ -35,14 +77,18 @@ public List getEntries(DataType dataType) { return extEntities.getOrDefault(dataType, Collections.emptyList()); } + public List allEntries() { + List entries = new ArrayList<>(); + extEntities.values().forEach(entries::addAll); + return entries; + } + /** * Returns the full mapping external id to SIMONA uuid. Equals {@code * getExtId2UuidMapping(DataType.values())}. */ public Map getExtId2UuidMapping() { - return extEntities.values().stream() - .flatMap(Collection::stream) - .collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); + return Collections.unmodifiableMap(idToUUID); } /** @@ -50,9 +96,7 @@ public Map getExtId2UuidMapping() { * getExtUuid2IdMapping(DataType.values())}. */ public Map getExtUuid2IdMapping() { - return extEntities.values().stream() - .flatMap(Collection::stream) - .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); + return Collections.unmodifiableMap(uuidToId); } /** @@ -62,8 +106,8 @@ public Map getExtUuid2IdMapping() { * @return mapping external id to SIMONA uuid */ public Map getExtId2UuidMapping(DataType dataType) { - return extEntities.getOrDefault(dataType, Collections.emptyList()).stream() - .collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); + List uuids = assets.getOrDefault(dataType, Collections.emptyList()); + return getExtId2UuidMapping(uuids); } /** @@ -73,9 +117,8 @@ public Map getExtId2UuidMapping(DataType dataType) { * @return mapping external id to SIMONA uuid */ public Map getExtId2UuidMapping(DataType... dataTypes) { - return Stream.of(dataTypes) - .flatMap(type -> extEntities.getOrDefault(type, Collections.emptyList()).stream()) - .collect(Collectors.toMap(ExtEntityEntry::id, ExtEntityEntry::uuid)); + List uuids = Stream.of(dataTypes).flatMap(type -> assets.getOrDefault(type, Collections.emptyList()).stream()).toList(); + return getExtId2UuidMapping(uuids); } /** @@ -85,8 +128,8 @@ public Map getExtId2UuidMapping(DataType... dataTypes) { * @return mapping SIMONA uuid to external id */ public Map getExtUuid2IdMapping(DataType dataType) { - return extEntities.getOrDefault(dataType, Collections.emptyList()).stream() - .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); + List uuids = assets.getOrDefault(dataType, Collections.emptyList()); + return getExtUuid2IdMapping(uuids); } /** @@ -96,8 +139,23 @@ public Map getExtUuid2IdMapping(DataType dataType) { * @return mapping SIMONA uuid to external id */ public Map getExtUuid2IdMapping(DataType... dataTypes) { - return Stream.of(dataTypes) - .flatMap(type -> extEntities.getOrDefault(type, Collections.emptyList()).stream()) - .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); + List uuids = Stream.of(dataTypes).flatMap(type -> assets.getOrDefault(type, Collections.emptyList()).stream()).toList(); + return getExtUuid2IdMapping(uuids); + } + + private Map getExtId2UuidMapping(List uuids) { + if (uuids.isEmpty()) { + return Collections.emptyMap(); + } else { + return idToUUID.entrySet().stream().filter(entry -> uuids.contains(entry.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } } + + private Map getExtUuid2IdMapping(List uuids) { + if (uuids.isEmpty()) { + return Collections.emptyMap(); + } else { + return uuidToId.entrySet().stream().filter(entry -> uuids.contains(entry.getKey())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + } } diff --git a/src/main/java/edu/ie3/simona/api/ontology/com/CommunicationMessages.java b/src/main/java/edu/ie3/simona/api/ontology/com/CommunicationMessages.java new file mode 100644 index 00000000..881b22d0 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/com/CommunicationMessages.java @@ -0,0 +1,10 @@ +package edu.ie3.simona.api.ontology.com; + +import edu.ie3.simona.api.data.model.com.CommunicationMessage; +import edu.ie3.simona.api.ontology.DataMessageFromExt; +import edu.ie3.simona.api.ontology.DataResponseMessageToExt; + +import java.util.Collection; +import java.util.Optional; + +public record CommunicationMessages(long tick, Collection> messages, Optional maybeNextTick) implements DataMessageFromExt, DataResponseMessageToExt {} From 6ddc50bdaded0ac4770885818ab37995ada3b071 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 15 Oct 2025 16:12:06 +0200 Subject: [PATCH 73/80] Saving changes. --- .../simona/api/mapping/ExtEntityMapping.java | 19 ++++++++++++--- .../api/simulation/ExtCoSimulation.java | 23 ++++++++----------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java index 2ae709c9..2b141b9e 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java @@ -56,6 +56,7 @@ public ExtEntityMapping(List extEntityEntryList) { } } + // can override previous mappings public ExtEntityMapping updateWith(List additional) { List entries = allEntries(); entries.addAll(additional); @@ -64,7 +65,19 @@ public ExtEntityMapping updateWith(List additional) { /** Returns the data types of this mapping. */ public Set getDataTypes() { - return extEntities.keySet(); + return assets.keySet(); + } + + public List getAssets() { + return assets.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); + } + + public List getAssets(DataType dataType) { + return assets.getOrDefault(dataType, Collections.emptyList()); + } + + public List getAssets(DataType... dataTypes) { + return Stream.of(dataTypes).flatMap(type -> assets.getOrDefault(type, Collections.emptyList()).stream()).toList(); } /** @@ -117,7 +130,7 @@ public Map getExtId2UuidMapping(DataType dataType) { * @return mapping external id to SIMONA uuid */ public Map getExtId2UuidMapping(DataType... dataTypes) { - List uuids = Stream.of(dataTypes).flatMap(type -> assets.getOrDefault(type, Collections.emptyList()).stream()).toList(); + List uuids = getAssets(dataTypes); return getExtId2UuidMapping(uuids); } @@ -139,7 +152,7 @@ public Map getExtUuid2IdMapping(DataType dataType) { * @return mapping SIMONA uuid to external id */ public Map getExtUuid2IdMapping(DataType... dataTypes) { - List uuids = Stream.of(dataTypes).flatMap(type -> assets.getOrDefault(type, Collections.emptyList()).stream()).toList(); + List uuids = getAssets(dataTypes); return getExtUuid2IdMapping(uuids); } 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 db077dca..6b20afa8 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -6,8 +6,6 @@ package edu.ie3.simona.api.simulation; -import static java.util.Collections.emptyList; - import edu.ie3.datamodel.models.result.ResultEntity; import edu.ie3.datamodel.models.value.Value; import edu.ie3.simona.api.data.ExtDataContainerQueue; @@ -18,10 +16,13 @@ import edu.ie3.simona.api.data.container.ExtOutputContainer; import edu.ie3.simona.api.data.model.em.EmSetPoint; import edu.ie3.simona.api.exceptions.ExtDataConnectionException; -import edu.ie3.simona.api.mapping.DataType; -import java.util.*; import org.slf4j.Logger; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + /** * Abstract class for an external co-simulation with bidirectional communication with SIMONA. * @@ -93,22 +94,18 @@ public static ExtEmDataConnection buildEmConnection( /** * Builds an {@link ExtResultDataConnection}. * - * @param mapping between the external simulation and SIMONA. + * @param uuids of assets that should send their results * @param log logger * @return an ext result data connection */ public static ExtResultDataConnection buildResultConnection( - Map> mapping, Logger log) { - List results = new ArrayList<>(); - Arrays.stream(DataType.resultTypes()) - .forEach(dataType -> results.addAll(mapping.getOrDefault(dataType, emptyList()))); - - if (results.isEmpty()) { + List uuids, Logger log) { + if (uuids.isEmpty()) { log.warn("No result connection was created."); throw new ExtDataConnectionException(ExtResultDataConnection.class); } else { - log.info("Result connection with {} result entities created.", results.size()); - return new ExtResultDataConnection(results); + log.info("Result connection with {} result entities created.", uuids.size()); + return new ExtResultDataConnection(uuids); } } From 2140e9c9c8f34ea7b5beb3477c14d6d41c96c7e6 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 17 Oct 2025 13:49:34 +0200 Subject: [PATCH 74/80] Refactoring em communication. --- .../data/connection/ExtComDataConnection.java | 52 ----- .../data/connection/ExtEmDataConnection.java | 23 +- .../api/data/container/ExtDataContainer.java | 15 ++ .../api/data/container/ExtInputContainer.java | 29 ++- .../data/model/com/CommunicationMessage.java | 5 - .../data/model/em/EmCommunicationMessage.java | 9 + .../ie3/simona/api/data/model/em/EmData.java | 11 +- .../simona/api/data/model/em/EmSetPoint.java | 28 +-- .../model/em/ExtendedFlexOptionsResult.java | 29 +-- .../api/data/model/em/FlexOptionRequest.java | 13 +- .../simona/api/data/model/em/FlexOptions.java | 12 +- .../simona/api/mapping/ExtEntityMapping.java | 196 ++++++++++++------ .../ontology/com/CommunicationMessages.java | 10 - .../ontology/em/EmCommunicationMessages.java | 9 + .../api/mapping/ExtEntityMappingTest.groovy | 27 --- 15 files changed, 219 insertions(+), 249 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/data/connection/ExtComDataConnection.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/model/com/CommunicationMessage.java create mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/EmCommunicationMessage.java delete mode 100644 src/main/java/edu/ie3/simona/api/ontology/com/CommunicationMessages.java create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/EmCommunicationMessages.java diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtComDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtComDataConnection.java deleted file mode 100644 index 7d538ad8..00000000 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtComDataConnection.java +++ /dev/null @@ -1,52 +0,0 @@ -package edu.ie3.simona.api.data.connection; - -import edu.ie3.simona.api.data.model.com.CommunicationMessage; -import edu.ie3.simona.api.ontology.com.CommunicationMessages; - -import java.util.*; - -public class ExtComDataConnection extends BiDirectional { - private final Set awaitedMessages = new HashSet<>(); - - - public ExtComDataConnection() {} - - /** - * Method for sending communication messages to SIMONA. - * @param tick current tick - * @param messages to sent to SIMONA - * @param maybeNextTick option for the next tick in the simulation - * @return true, if data was sent - */ - public boolean sendMessages(long tick, Collection> messages, Optional maybeNextTick) { - if (!messages.isEmpty()) { - // saving the message ids of all - messages.forEach(message -> awaitedMessages.remove(message.msgId())); - sendExtMsg(new CommunicationMessages(tick, messages, maybeNextTick)); - return true; - } - return false; - } - - /** - * Method to retrieve messages that should be sent to the external simulation. - * @return a list of messages - * @throws InterruptedException - on interruptions - */ - public List> retrieveMessages() throws InterruptedException { - if (awaitedMessages.isEmpty()) { - return Collections.emptyList(); - } - - List> messages = new ArrayList<>(); - - for (CommunicationMessages receivedMessage : receiveAll()) { - messages.addAll(receivedMessage.messages()); - } - - // save all message ids - messages.forEach(message -> awaitedMessages.add(message.msgId())); - - return messages; - } -} diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index 2cd59593..5726c8a4 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java @@ -6,10 +6,7 @@ package edu.ie3.simona.api.data.connection; -import edu.ie3.simona.api.data.model.em.EmSetPoint; -import edu.ie3.simona.api.data.model.em.ExtendedFlexOptionsResult; -import edu.ie3.simona.api.data.model.em.FlexOptionRequest; -import edu.ie3.simona.api.data.model.em.FlexOptions; +import edu.ie3.simona.api.data.model.em.*; import edu.ie3.simona.api.ontology.em.*; import java.util.*; @@ -58,6 +55,24 @@ public boolean sendEmData( return false; } + public boolean sendFlexRequest(long tick, Collection entities, boolean disaggregated) { + // send message only if at least one value is present + if (!entities.isEmpty() ) { + sendExtMsg(new RequestEmFlexResults(tick, new ArrayList<>(entities), disaggregated)); + return true; + } + return false; + } + + public boolean sendEmData(long tick, List> emData, Optional maybeNextTick) { + // send message only if at least one value is present + if (!emData.isEmpty() ) { + sendExtMsg(new EmCommunicationMessages(tick, emData, maybeNextTick)); + return true; + } + return false; + } + /** * Tries to send the em set points to SIMONA. * diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java index 615b3386..b6965391 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtDataContainer.java @@ -6,7 +6,9 @@ package edu.ie3.simona.api.data.container; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; /** Interface for data that are exchanged between an external simulation and SimonaAPI */ @@ -28,4 +30,17 @@ default Map copyAndClear(Map map) { map.clear(); return result; } + + /** + * Method to copy a given list and clear the original. + * + * @param list to be copied and cleared + * @return the copy + * @param type of value + */ + default List copyAndClear(List list) { + List result = new ArrayList<>(list); + list.clear(); + return result; + } } diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java index 56bb507d..f181982b 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java @@ -8,6 +8,7 @@ import edu.ie3.datamodel.models.value.PValue; import edu.ie3.datamodel.models.value.Value; +import edu.ie3.simona.api.data.model.em.EmCommunicationMessage; import edu.ie3.simona.api.data.model.em.EmSetPoint; import edu.ie3.simona.api.data.model.em.FlexOptionRequest; import edu.ie3.simona.api.data.model.em.FlexOptions; @@ -36,6 +37,9 @@ public final class ExtInputContainer implements ExtDataContainer { /** Map uuid to em set points. */ private final Map setPoints = new HashMap<>(); + /** List of em communication messages. */ + private final List> emMessages = new ArrayList<>(); + /** * Container class for input data for SIMONA which can be read by SimonaAPI * @@ -82,15 +86,18 @@ public void addPrimaryValue(UUID asset, Value value) { primaryData.put(asset, value); } + public void addFlexComMessage(EmCommunicationMessage message) { + emMessages.add(message); + } + /** * Method for adding flex option requests. No disaggregated flex option will be requested using * this method. * * @param receiver the uuid of the agent, that will receive the request - * @param sender option for the uuid of the sender */ - public void addRequest(UUID receiver, UUID sender) { - flexRequests.put(receiver, new FlexOptionRequest(receiver, sender, false)); + public void addRequest(UUID receiver) { + flexRequests.put(receiver, new FlexOptionRequest(receiver, false)); } public void addRequest(UUID receiver, FlexOptionRequest request) { @@ -104,12 +111,7 @@ public void addRequest(UUID receiver, FlexOptionRequest request) { * @param flexOption that will be added */ public void addFlexOptions(UUID receiver, List flexOption) { - if (!flexOptions.containsKey(receiver)) { - List flexOptionValues = new ArrayList<>(flexOption); - flexOptions.put(receiver, flexOptionValues); - } else { - flexOptions.get(receiver).addAll(flexOption); - } + flexOptions.computeIfAbsent(receiver, k -> new ArrayList<>()).addAll(flexOption); } /** @@ -119,7 +121,7 @@ public void addFlexOptions(UUID receiver, List flexOption) { * @param power of the set point */ public void addSetPoint(UUID asset, UUID sender, PValue power) { - setPoints.put(asset, new EmSetPoint(asset, sender, power)); + setPoints.put(asset, new EmSetPoint(asset, power)); } /** @@ -160,6 +162,13 @@ public Map extractSetPoints() { return copyAndClear(setPoints); } + /** + * Extracts the em message input data from this container. All other input data remains the same. + */ + public List> extractEmMessages() { + return copyAndClear(emMessages); + } + /** * Returns a string representation of the primary input data without changing the data. To extract * (remove) the primary input data, use {@link #extractPrimaryData()} instead. diff --git a/src/main/java/edu/ie3/simona/api/data/model/com/CommunicationMessage.java b/src/main/java/edu/ie3/simona/api/data/model/com/CommunicationMessage.java deleted file mode 100644 index a4b4213c..00000000 --- a/src/main/java/edu/ie3/simona/api/data/model/com/CommunicationMessage.java +++ /dev/null @@ -1,5 +0,0 @@ -package edu.ie3.simona.api.data.model.com; - -import java.util.UUID; - -public record CommunicationMessage(UUID receiver, UUID sender, UUID msgId, D content, Class dataClass) {} diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/EmCommunicationMessage.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmCommunicationMessage.java new file mode 100644 index 00000000..c8cd936d --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmCommunicationMessage.java @@ -0,0 +1,9 @@ +package edu.ie3.simona.api.data.model.em; + +import java.util.UUID; + +public record EmCommunicationMessage(UUID receiver, UUID sender, UUID msgId, D content) implements EmData { + public EmCommunicationMessage(UUID receiver, UUID sender, D content) { + this(receiver, sender, UUID.randomUUID(), content); + } +} diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/EmData.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmData.java index 54f02ff7..045b9e59 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/EmData.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmData.java @@ -6,14 +6,5 @@ package edu.ie3.simona.api.data.model.em; -import java.util.UUID; - /** Interface that is extended by all em data models. */ -public interface EmData { - - /** Returns the uuid of the receiver. */ - UUID getReceiver(); - - /** Returns the uuid of the sender. */ - UUID getSender(); -} +public interface EmData {} diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java index 329cae36..2935fbe6 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPoint.java @@ -16,51 +16,37 @@ * Energy management set point that will be sent to SIMONA. * * @param receiver The receiver of the set point. - * @param sender The sender of the set point. * @param power An option for the em set point. */ -public record EmSetPoint(UUID receiver, UUID sender, Optional power) implements EmData { +public record EmSetPoint(UUID receiver, Optional power) implements EmData { /** * Constructor for {@link EmSetPoint}. * *

Note: Using this constructor will signal SIMONA, that the current set point should be kept. * * @param receiver The receiver of the set point. - * @param sender The sender of the set point. */ - public EmSetPoint(UUID receiver, UUID sender) { - this(receiver, sender, Optional.empty()); + public EmSetPoint(UUID receiver) { + this(receiver, Optional.empty()); } /** * Constructor for {@link EmSetPoint}. * * @param receiver The receiver of the set point. - * @param sender The sender of the set point. * @param p Power value of the set point. */ - public EmSetPoint(UUID receiver, UUID sender, ComparableQuantity p) { - this(receiver, sender, Optional.of(new PValue(p))); + public EmSetPoint(UUID receiver, ComparableQuantity p) { + this(receiver, Optional.of(new PValue(p))); } /** * Constructor for {@link EmSetPoint}. * * @param receiver The receiver of the set point. - * @param sender The sender of the set point. * @param power value of the set point. */ - public EmSetPoint(UUID receiver, UUID sender, PValue power) { - this(receiver, sender, Optional.ofNullable(power)); - } - - @Override - public UUID getReceiver() { - return receiver; - } - - @Override - public UUID getSender() { - return sender; + public EmSetPoint(UUID receiver, PValue power) { + this(receiver, Optional.ofNullable(power)); } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java index e16eec9d..a0b9ebb7 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java @@ -7,21 +7,19 @@ package edu.ie3.simona.api.data.model.em; import edu.ie3.datamodel.models.result.system.FlexOptionsResult; -import java.time.ZonedDateTime; -import java.util.*; -import javax.measure.quantity.Power; import org.slf4j.Logger; import tech.units.indriya.ComparableQuantity; +import javax.measure.quantity.Power; +import java.time.ZonedDateTime; +import java.util.*; + /** * Extended {@link FlexOptionsResult}, that contains the receiver of the flex options. This models * may also contain a disaggregation of the total flex options. */ public final class ExtendedFlexOptionsResult extends FlexOptionsResult implements EmData { - /** The receiver of the message. */ - private final UUID receiver; - /** The disaggregated flex option results. */ private final Map disaggregated; @@ -30,7 +28,6 @@ public final class ExtendedFlexOptionsResult extends FlexOptionsResult implement * * @param time date and time when the result is produced * @param sender uuid of the input model that produces the result - * @param receiver uuid of the receiver that will receive this result * @param pRef active power that was suggested for regular usage by the system participant * @param pMin active minimal power that was determined by the system participant * @param pMax active maximum power that was determined by the system participant @@ -38,12 +35,10 @@ public final class ExtendedFlexOptionsResult extends FlexOptionsResult implement public ExtendedFlexOptionsResult( ZonedDateTime time, UUID sender, - UUID receiver, ComparableQuantity pRef, ComparableQuantity pMin, ComparableQuantity pMax) { super(time, sender, pRef, pMin, pMax); - this.receiver = receiver; this.disaggregated = new HashMap<>(); } @@ -52,7 +47,6 @@ public ExtendedFlexOptionsResult( * * @param time date and time when the result is produced * @param sender uuid of the input model that produces the result - * @param receiver uuid of the receiver that will receive this result * @param pRef active power that was suggested for regular usage by the system participant * @param pMin active minimal power that was determined by the system participant * @param pMax active maximum power that was determined by the system participant @@ -60,13 +54,11 @@ public ExtendedFlexOptionsResult( public ExtendedFlexOptionsResult( ZonedDateTime time, UUID sender, - UUID receiver, ComparableQuantity pRef, ComparableQuantity pMin, ComparableQuantity pMax, Map disaggregated) { super(time, sender, pRef, pMin, pMax); - this.receiver = receiver; this.disaggregated = disaggregated; } @@ -84,16 +76,10 @@ public void addDisaggregated(UUID uuid, FlexOptionsResult flexOptionsResult) { } /** Returns the uuid of the sender ({@link #getInputModel()}). */ - @Override public UUID getSender() { return getInputModel(); } - @Override - public UUID getReceiver() { - return receiver; - } - /** Returns {@code true}, if disaggregated flex option are available. */ public boolean hasDisaggregated() { return !disaggregated.isEmpty(); @@ -177,13 +163,12 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ExtendedFlexOptionsResult that = (ExtendedFlexOptionsResult) o; - return Objects.equals(receiver, that.receiver) - && Objects.equals(disaggregated, that.disaggregated); + return Objects.equals(disaggregated, that.disaggregated); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), receiver, disaggregated); + return Objects.hash(super.hashCode(), disaggregated); } @Override @@ -193,8 +178,6 @@ public String toString() { + getTime() + ", sender=" + getSender() - + ", receiver=" - + receiver + ", pRef=" + getpRef() + ", pMin=" diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java index d65e5cf9..6f3edd76 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java @@ -12,19 +12,8 @@ * Energy management flex option request that will be sent to SIMONA. * * @param receiver The receiver of the request. - * @param sender The sender of the request. * @param disaggregated True, if disaggregated flex option should be returned. */ -public record FlexOptionRequest(UUID receiver, UUID sender, boolean disaggregated) +public record FlexOptionRequest(UUID receiver, boolean disaggregated) implements EmData { - - @Override - public UUID getReceiver() { - return receiver; - } - - @Override - public UUID getSender() { - return sender; - } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java index c564f63f..c8f56330 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java @@ -46,16 +46,6 @@ public FlexOptions( /** Converts and returns this object as a {@link ExtendedFlexOptionsResult}. */ public ExtendedFlexOptionsResult asResult() { - return new ExtendedFlexOptionsResult(null, sender, receiver, pRef, pMin, pMax, disaggregated); - } - - @Override - public UUID getReceiver() { - return receiver; - } - - @Override - public UUID getSender() { - return sender; + return new ExtendedFlexOptionsResult(null, sender, pRef, pMin, pMax, disaggregated); } } diff --git a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java index 2b141b9e..19ab728e 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java @@ -6,94 +6,158 @@ package edu.ie3.simona.api.mapping; +import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; +import edu.ie3.datamodel.models.input.container.GridContainer; +import edu.ie3.datamodel.models.value.Value; + import java.util.*; import java.util.stream.Collectors; -import java.util.stream.Stream; /** Contains the mapping between SIMONA uuid, the external id and the data type the assets hold */ public class ExtEntityMapping { - private final Map> extEntities; + private final Map> extAssets = new HashMap<>(); + private final Map> primaryMapping = new HashMap<>(); - private final Map> assets = new HashMap<>(); - private final Map uuidToId = new HashMap<>(); - private final Map idToUUID = new HashMap<>(); + // asset lists + private final Set gridAssets = new HashSet<>(); + private final Set participants = new HashSet<>(); + private final Set ems = new HashSet<>(); - public ExtEntityMapping(List extEntityEntryList) { - this.extEntities = extEntityEntryList.stream().collect(Collectors.groupingBy(ExtEntityEntry::dataType)); + private final Map uuidToId = new HashMap<>(); + private final Map idToUuid = new HashMap<>(); + + public ExtEntityMapping(GridContainer grid) { + // handling of grid assets + grid.getRawGrid().allEntitiesAsList().forEach(asset -> { + UUID uuid = asset.getUuid(); + String id = asset.getId(); + + // add to mappings + uuidToId.put(uuid, id); + idToUuid.put(id, uuid); + + // add to asset list + gridAssets.add(asset.getUuid()); + }); + + // handling of participants and ems + grid.getSystemParticipants().allEntitiesAsList().forEach(participant -> { + UUID uuid = participant.getUuid(); + String id = participant.getId(); + + // add to mappings + uuidToId.put(uuid, id); + idToUuid.put(id, uuid); + + // add to asset list + participants.add(participant.getUuid()); + + // add ems + participant.getControllingEm().ifPresent(em -> { + UUID emUuid = em.getUuid(); + String emId = em.getId(); + + // add to mappings + uuidToId.put(emUuid, emId); + idToUuid.put(emId, emUuid); + + // add to asset list + ems.add(emUuid); + }); + }); + } - // handling of general mapping (from grid container) - List simonaUUIDs = new ArrayList<>(); - assets.put(DataType.GENERAL, simonaUUIDs); + private ExtEntityMapping( + Map> assets, + Map> primaryMapping, + Set gridAssets, + Set participants, + Set ems, + Map uuidToId, + Map idToUUID + ) { + this.extAssets.putAll(assets); + this.primaryMapping.putAll(primaryMapping); + this.gridAssets.addAll(gridAssets); + this.participants.addAll(participants); + this.ems.addAll(ems); + this.uuidToId.putAll(uuidToId); + this.idToUuid.putAll(idToUUID); + } - extEntities.getOrDefault(DataType.GENERAL, Collections.emptyList()).forEach(entry -> { - UUID uuid = entry.uuid(); - String id = entry.id(); + // can override previous mappings + public ExtEntityMapping include(List included) { + ExtEntityMapping copy = new ExtEntityMapping(extAssets, primaryMapping, gridAssets, participants, ems, uuidToId, idToUuid); + copy.includeEntries(included); + return copy; + } - idToUUID.put(id, uuid); - uuidToId.put(uuid, id); - simonaUUIDs.add(uuid); - }); + public ExtEntityMapping include(DataType dataType, List included, Optional schemeOption) { + ExtEntityMapping copy = new ExtEntityMapping(extAssets, primaryMapping, gridAssets, participants, ems, uuidToId, idToUuid); + includeIds(dataType, included.stream().map(this::from).toList(), schemeOption); + return copy; + } - // handling of mapping from external simulation - for (DataType dataType : DataType.getExceptGeneral()) { - if (extEntities.containsKey(dataType)) { - List entries = extEntities.get(dataType); + private void includeIds(DataType dataType, List included, Optional schemeOption) { + schemeOption.ifPresent(scheme -> included.forEach(uuid -> primaryMapping.put(uuid, scheme.getValueClass()))); + included.forEach(uuid -> extAssets.computeIfAbsent(dataType, d -> new ArrayList<>()).add(uuid)); + } - List uuids = new ArrayList<>(); + // overrides previous mappings + private void includeEntries(List included) { + included.forEach(entry -> { + DataType dataType = entry.dataType(); + UUID uuid = entry.uuid(); + String id = entry.id(); - entries.forEach(entry -> { - UUID uuid = entry.uuid(); - String id = entry.id(); + entry.columnScheme().ifPresent(scheme -> primaryMapping.put(uuid, scheme.getValueClass())); - idToUUID.put(id, uuid); - uuidToId.put(uuid, id); - uuids.add(uuid); - }); + // override mappings + uuidToId.put(uuid, id); + idToUuid.put(id, uuid); - assets.put(dataType, uuids); - } - } + extAssets.computeIfAbsent(dataType, d -> new ArrayList<>()).add(uuid); + }); } - // can override previous mappings - public ExtEntityMapping updateWith(List additional) { - List entries = allEntries(); - entries.addAll(additional); - return new ExtEntityMapping(entries); - } /** Returns the data types of this mapping. */ public Set getDataTypes() { - return assets.keySet(); + return extAssets.keySet(); } - public List getAssets() { - return assets.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); - } + public Map> getPrimaryMapping() { + return Collections.unmodifiableMap(primaryMapping); + } - public List getAssets(DataType dataType) { - return assets.getOrDefault(dataType, Collections.emptyList()); + public List getExtAssets() { + return extAssets.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); } - public List getAssets(DataType... dataTypes) { - return Stream.of(dataTypes).flatMap(type -> assets.getOrDefault(type, Collections.emptyList()).stream()).toList(); + public List getAssets(DataType dataType) { + List uuids = extAssets.getOrDefault(dataType, Collections.emptyList()); + + return switch (dataType) { + case PRIMARY, PRIMARY_RESULT -> new ArrayList<>(participants); + case RESULT -> { + List res = new ArrayList<>(); + res.addAll(gridAssets); + res.addAll(participants); + res.addAll(ems); + yield res; + } + case EM -> new ArrayList<>(ems); + default -> uuids; + }; } - /** - * 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 getEntries(DataType dataType) { - return extEntities.getOrDefault(dataType, Collections.emptyList()); + public UUID from(String id) { + return idToUuid.get(id); } - public List allEntries() { - List entries = new ArrayList<>(); - extEntities.values().forEach(entries::addAll); - return entries; + public String from(UUID uuid) { + return uuidToId.get(uuid); } /** @@ -101,7 +165,7 @@ public List allEntries() { * getExtId2UuidMapping(DataType.values())}. */ public Map getExtId2UuidMapping() { - return Collections.unmodifiableMap(idToUUID); + return Collections.unmodifiableMap(idToUuid); } /** @@ -118,8 +182,9 @@ public Map getExtUuid2IdMapping() { * @param dataType data type the external asset expects * @return mapping external id to SIMONA uuid */ + @Deprecated public Map getExtId2UuidMapping(DataType dataType) { - List uuids = assets.getOrDefault(dataType, Collections.emptyList()); + List uuids = extAssets.getOrDefault(dataType, Collections.emptyList()); return getExtId2UuidMapping(uuids); } @@ -129,8 +194,9 @@ public Map getExtId2UuidMapping(DataType dataType) { * @param dataTypes the external asset expects * @return mapping external id to SIMONA uuid */ + @Deprecated public Map getExtId2UuidMapping(DataType... dataTypes) { - List uuids = getAssets(dataTypes); + List uuids = getExtAssets(); return getExtId2UuidMapping(uuids); } @@ -140,8 +206,9 @@ public Map getExtId2UuidMapping(DataType... dataTypes) { * @param dataType data type the external asset expects * @return mapping SIMONA uuid to external id */ + @Deprecated public Map getExtUuid2IdMapping(DataType dataType) { - List uuids = assets.getOrDefault(dataType, Collections.emptyList()); + List uuids = extAssets.getOrDefault(dataType, Collections.emptyList()); return getExtUuid2IdMapping(uuids); } @@ -151,8 +218,9 @@ public Map getExtUuid2IdMapping(DataType dataType) { * @param dataTypes data types the external asset expects * @return mapping SIMONA uuid to external id */ + @Deprecated public Map getExtUuid2IdMapping(DataType... dataTypes) { - List uuids = getAssets(dataTypes); + List uuids = getExtAssets(); return getExtUuid2IdMapping(uuids); } @@ -160,7 +228,7 @@ private Map getExtId2UuidMapping(List uuids) { if (uuids.isEmpty()) { return Collections.emptyMap(); } else { - return idToUUID.entrySet().stream().filter(entry -> uuids.contains(entry.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + return idToUuid.entrySet().stream().filter(entry -> uuids.contains(entry.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } } diff --git a/src/main/java/edu/ie3/simona/api/ontology/com/CommunicationMessages.java b/src/main/java/edu/ie3/simona/api/ontology/com/CommunicationMessages.java deleted file mode 100644 index 881b22d0..00000000 --- a/src/main/java/edu/ie3/simona/api/ontology/com/CommunicationMessages.java +++ /dev/null @@ -1,10 +0,0 @@ -package edu.ie3.simona.api.ontology.com; - -import edu.ie3.simona.api.data.model.com.CommunicationMessage; -import edu.ie3.simona.api.ontology.DataMessageFromExt; -import edu.ie3.simona.api.ontology.DataResponseMessageToExt; - -import java.util.Collection; -import java.util.Optional; - -public record CommunicationMessages(long tick, Collection> messages, Optional maybeNextTick) implements DataMessageFromExt, DataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/EmCommunicationMessages.java b/src/main/java/edu/ie3/simona/api/ontology/em/EmCommunicationMessages.java new file mode 100644 index 00000000..ba6c0d2c --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/EmCommunicationMessages.java @@ -0,0 +1,9 @@ +package edu.ie3.simona.api.ontology.em; + +import edu.ie3.simona.api.data.model.em.EmCommunicationMessage; +import edu.ie3.simona.api.data.model.em.EmData; + +import java.util.Collection; +import java.util.Optional; + +public record EmCommunicationMessages(long tick, Collection> messages, Optional maybeNextTick) implements EmDataMessageFromExt, EmDataResponseMessageToExt {} diff --git a/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy b/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy index 251c7b94..14783394 100644 --- a/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy @@ -142,31 +142,4 @@ class ExtEntityMappingTest extends Specification { inputMap.get(prUuid) == "PR" inputMap.get(emUuid) == "Em" } - - def "ExtEntityMapping should return external id mapping correctly"() { - given: - def extAssetList = List.of(extResultEntry, extInputEntry, extPrimaryResultEntry, extEmInputEntry) - def extEntryMapping = new ExtEntityMapping(extAssetList) - - when: - def inputMap = extEntryMapping.getExtUuid2IdMapping(DataType.PRIMARY) - - then: - inputMap.size() == 1 - inputMap.get(pvUuid) == "PV" - } - - def "ExtEntityMapping should return multiple external id mapping correctly"() { - given: - def extAssetList = List.of(extResultEntry, extInputEntry, extPrimaryResultEntry, extEmInputEntry) - def extEntryMapping = new ExtEntityMapping(extAssetList) - - when: - def inputMap = extEntryMapping.getExtUuid2IdMapping(DataType.PRIMARY, DataType.EM) - - then: - inputMap.size() == 2 - inputMap.get(pvUuid) == "PV" - inputMap.get(emUuid) == "Em" - } } \ No newline at end of file From 25c43cb2fe20df312b05b877d8819f406edae062 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 20 Oct 2025 14:04:18 +0200 Subject: [PATCH 75/80] Saving changes. --- .../simona/api/mapping/ExtEntityMapping.java | 170 ++++++++---------- .../api/mapping/ExtEntityMappingTest.groovy | 36 +--- 2 files changed, 82 insertions(+), 124 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java index 19ab728e..2029bbcd 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java @@ -27,6 +27,22 @@ public class ExtEntityMapping { private final Map uuidToId = new HashMap<>(); private final Map idToUuid = new HashMap<>(); + public ExtEntityMapping(List entries) { + entries.forEach(entry -> { + DataType dataType = entry.dataType(); + UUID uuid = entry.uuid(); + String id = entry.id(); + + entry.columnScheme().ifPresent(scheme -> primaryMapping.put(uuid, scheme.getValueClass())); + + // override mappings + uuidToId.put(uuid, id); + idToUuid.put(id, uuid); + + extAssets.computeIfAbsent(dataType, k -> new ArrayList<>()).add(uuid); + }); + } + public ExtEntityMapping(GridContainer grid) { // handling of grid assets grid.getRawGrid().allEntitiesAsList().forEach(asset -> { @@ -68,40 +84,32 @@ public ExtEntityMapping(GridContainer grid) { }); } - private ExtEntityMapping( - Map> assets, - Map> primaryMapping, - Set gridAssets, - Set participants, - Set ems, - Map uuidToId, - Map idToUUID - ) { - this.extAssets.putAll(assets); - this.primaryMapping.putAll(primaryMapping); - this.gridAssets.addAll(gridAssets); - this.participants.addAll(participants); - this.ems.addAll(ems); - this.uuidToId.putAll(uuidToId); - this.idToUuid.putAll(idToUUID); + private ExtEntityMapping(ExtEntityMapping mapping) { + this.extAssets.putAll(mapping.extAssets); + this.primaryMapping.putAll(mapping.primaryMapping); + this.gridAssets.addAll(mapping.gridAssets); + this.participants.addAll(mapping.participants); + this.ems.addAll(mapping.ems); + this.uuidToId.putAll(mapping.uuidToId); + this.idToUuid.putAll(mapping.idToUuid); } // can override previous mappings public ExtEntityMapping include(List included) { - ExtEntityMapping copy = new ExtEntityMapping(extAssets, primaryMapping, gridAssets, participants, ems, uuidToId, idToUuid); + ExtEntityMapping copy = new ExtEntityMapping(this); copy.includeEntries(included); return copy; } public ExtEntityMapping include(DataType dataType, List included, Optional schemeOption) { - ExtEntityMapping copy = new ExtEntityMapping(extAssets, primaryMapping, gridAssets, participants, ems, uuidToId, idToUuid); - includeIds(dataType, included.stream().map(this::from).toList(), schemeOption); + ExtEntityMapping copy = new ExtEntityMapping(this); + includeIds(dataType, included.stream().map(this::get).filter(Optional::isPresent).map(Optional::get).toList(), schemeOption); return copy; } private void includeIds(DataType dataType, List included, Optional schemeOption) { schemeOption.ifPresent(scheme -> included.forEach(uuid -> primaryMapping.put(uuid, scheme.getValueClass()))); - included.forEach(uuid -> extAssets.computeIfAbsent(dataType, d -> new ArrayList<>()).add(uuid)); + addExtEntities(dataType, included); } // overrides previous mappings @@ -117,10 +125,18 @@ private void includeEntries(List included) { uuidToId.put(uuid, id); idToUuid.put(id, uuid); - extAssets.computeIfAbsent(dataType, d -> new ArrayList<>()).add(uuid); + addExtEntities(dataType, included.stream().map(ExtEntityEntry::uuid).toList()); }); } + private void addExtEntities(DataType dataType, List included) { + if (dataType == DataType.PRIMARY_RESULT) { + extAssets.computeIfAbsent(DataType.PRIMARY, d -> new ArrayList<>()).addAll(included); + extAssets.computeIfAbsent(DataType.RESULT, d -> new ArrayList<>()).addAll(included); + } else { + extAssets.computeIfAbsent(dataType, k -> new ArrayList<>()).addAll(included); + } + } /** Returns the data types of this mapping. */ public Set getDataTypes() { @@ -131,14 +147,12 @@ public Map> getPrimaryMapping() { return Collections.unmodifiableMap(primaryMapping); } - public List getExtAssets() { + public List getAllAssets() { return extAssets.values().stream().flatMap(Collection::stream).collect(Collectors.toList()); } public List getAssets(DataType dataType) { - List uuids = extAssets.getOrDefault(dataType, Collections.emptyList()); - - return switch (dataType) { + List uuids = switch (dataType) { case PRIMARY, PRIMARY_RESULT -> new ArrayList<>(participants); case RESULT -> { List res = new ArrayList<>(); @@ -148,8 +162,38 @@ public List getAssets(DataType dataType) { yield res; } case EM -> new ArrayList<>(ems); - default -> uuids; + default -> Collections.emptyList(); }; + + if (uuids.isEmpty()) { + if (dataType == DataType.PRIMARY_RESULT) { + List res = new ArrayList<>(); + res.addAll(extAssets.getOrDefault(DataType.PRIMARY, Collections.emptyList())); + res.addAll(extAssets.getOrDefault(DataType.RESULT, Collections.emptyList())); + + return res; + } else { + return extAssets.getOrDefault(dataType, Collections.emptyList()); + } + + } else { + List ext = new ArrayList<>(); + extAssets.values().forEach(ext::addAll); + + if (extAssets.isEmpty()) { + return uuids; + } else { + return uuids.stream().filter(ext::contains).toList(); + } + } + } + + public boolean contains(String id) { + return idToUuid.containsKey(id); + } + + public boolean contains(UUID uuid) { + return uuidToId.containsKey(uuid); } public UUID from(String id) { @@ -160,6 +204,14 @@ public String from(UUID uuid) { return uuidToId.get(uuid); } + public Optional get(String id) { + return Optional.ofNullable(idToUuid.get(id)); + } + + public Optional get(UUID uuid) { + return Optional.ofNullable(uuidToId.get(uuid)); + } + /** * Returns the full mapping external id to SIMONA uuid. Equals {@code * getExtId2UuidMapping(DataType.values())}. @@ -173,70 +225,6 @@ public Map getExtId2UuidMapping() { * getExtUuid2IdMapping(DataType.values())}. */ public Map getExtUuid2IdMapping() { - return Collections.unmodifiableMap(uuidToId); + return Collections.unmodifiableMap(uuidToId); } - - /** - * Mapping external id to SIMONA uuid. - * - * @param dataType data type the external asset expects - * @return mapping external id to SIMONA uuid - */ - @Deprecated - public Map getExtId2UuidMapping(DataType dataType) { - List uuids = extAssets.getOrDefault(dataType, Collections.emptyList()); - return getExtId2UuidMapping(uuids); - } - - /** - * Mapping external id to SIMONA uuid. - * - * @param dataTypes the external asset expects - * @return mapping external id to SIMONA uuid - */ - @Deprecated - public Map getExtId2UuidMapping(DataType... dataTypes) { - List uuids = getExtAssets(); - return getExtId2UuidMapping(uuids); - } - - /** - * Mapping SIMONA uuid to external id. - * - * @param dataType data type the external asset expects - * @return mapping SIMONA uuid to external id - */ - @Deprecated - public Map getExtUuid2IdMapping(DataType dataType) { - List uuids = extAssets.getOrDefault(dataType, Collections.emptyList()); - return getExtUuid2IdMapping(uuids); - } - - /** - * Mapping SIMONA uuid to external id. - * - * @param dataTypes data types the external asset expects - * @return mapping SIMONA uuid to external id - */ - @Deprecated - public Map getExtUuid2IdMapping(DataType... dataTypes) { - List uuids = getExtAssets(); - return getExtUuid2IdMapping(uuids); - } - - private Map getExtId2UuidMapping(List uuids) { - if (uuids.isEmpty()) { - return Collections.emptyMap(); - } else { - return idToUuid.entrySet().stream().filter(entry -> uuids.contains(entry.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - } - - private Map getExtUuid2IdMapping(List uuids) { - if (uuids.isEmpty()) { - return Collections.emptyMap(); - } else { - return uuidToId.entrySet().stream().filter(entry -> uuids.contains(entry.getKey())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - } } diff --git a/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy b/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy index 14783394..7ab60829 100644 --- a/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy @@ -68,22 +68,6 @@ class ExtEntityMappingTest extends Specification { [extResultEntry, extInputEntry, extPrimaryResultEntry, extEmInputEntry] | [DataType.RESULT, DataType.PRIMARY, DataType.PRIMARY_RESULT, DataType.EM] } - def "ExtEntityMapping should return the entries correctly"() { - when: - def extEntryMapping = new ExtEntityMapping(assets) - def types = extEntryMapping.getEntries(dataType) - - then: - types == expectedEntries - - where: - assets | dataType | expectedEntries - [extResultEntry, extInputEntry, extPrimaryResultEntry, extEmInputEntry] | DataType.RESULT | [extResultEntry] - [extResultEntry, extInputEntry, extPrimaryResultEntry, extEmInputEntry] | DataType.PRIMARY | [extInputEntry] - [extResultEntry, extInputEntry, extPrimaryResultEntry, extEmInputEntry] | DataType.PRIMARY_RESULT | [extPrimaryResultEntry] - [extResultEntry, extInputEntry, extPrimaryResultEntry, extEmInputEntry] | DataType.EM | [extEmInputEntry] - } - def "ExtEntityMapping should return all SIMONA uuid mapping correctly"() { given: def extAssetList = List.of(extResultEntry, extInputEntry, extPrimaryResultEntry, extEmInputEntry) @@ -106,25 +90,11 @@ class ExtEntityMappingTest extends Specification { def extEntryMapping = new ExtEntityMapping(extAssetList) when: - def inputMap = extEntryMapping.getExtId2UuidMapping(DataType.PRIMARY) - - then: - inputMap.size() == 1 - inputMap.get("PV") == pvUuid - } - - def "ExtEntityMapping should return multiple SIMONA uuid mapping correctly"() { - given: - def extAssetList = List.of(extResultEntry, extInputEntry, extPrimaryResultEntry, extEmInputEntry) - def extEntryMapping = new ExtEntityMapping(extAssetList) - - when: - def inputMap = extEntryMapping.getExtId2UuidMapping(DataType.PRIMARY, DataType.EM) + def actual = extEntryMapping.getAssets(DataType.PRIMARY) then: - inputMap.size() == 2 - inputMap.get("PV") == pvUuid - inputMap.get("Em") == emUuid + actual.size() == 1 + actual.getFirst() == pvUuid } def "ExtEntityMapping should return all external id mapping correctly"() { From a804633d47b02d2dc045f0f110b2051330cb717a Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 24 Oct 2025 12:27:14 +0200 Subject: [PATCH 76/80] Saving changes. --- .../java/edu/ie3/simona/api/mapping/DataType.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/mapping/DataType.java b/src/main/java/edu/ie3/simona/api/mapping/DataType.java index b9728679..8f11f447 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/DataType.java +++ b/src/main/java/edu/ie3/simona/api/mapping/DataType.java @@ -6,11 +6,8 @@ package edu.ie3.simona.api.mapping; -import java.util.List; - /** Data types. */ public enum DataType { - GENERAL, PRIMARY, RESULT, PRIMARY_RESULT, @@ -18,16 +15,11 @@ public enum DataType { /** Returns all primary types. */ public static DataType[] primaryTypes() { - return new DataType[] {PRIMARY, PRIMARY_RESULT, GENERAL}; + return new DataType[] {PRIMARY, PRIMARY_RESULT}; } /** Returns all result types. */ public static DataType[] resultTypes() { - return new DataType[] {RESULT, PRIMARY_RESULT, GENERAL}; - } - - public static List getExceptGeneral() { - return List.of(PRIMARY, PRIMARY_RESULT, RESULT, EM); + return new DataType[] {RESULT, PRIMARY_RESULT}; } - } From 1e9f889e38bfab365cedb2c3b6b948aee01f91f4 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 24 Oct 2025 15:55:29 +0200 Subject: [PATCH 77/80] Saving changes. --- .../data/connection/ExtEmDataConnection.java | 9 --- .../model/em/ExtendedFlexOptionsResult.java | 77 ++----------------- .../simona/api/mapping/ExtEntityMapping.java | 48 ++++++++++-- 3 files changed, 45 insertions(+), 89 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index 2b5b3ce1..edd0f8b5 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java @@ -55,15 +55,6 @@ public boolean sendEmData( return false; } - public boolean sendFlexRequest(long tick, Collection entities, boolean disaggregated) { - // send message only if at least one value is present - if (!entities.isEmpty() ) { - sendExtMsg(new RequestEmFlexResults(tick, new ArrayList<>(entities), disaggregated)); - return true; - } - return false; - } - public boolean sendEmData(long tick, List> emData, Optional maybeNextTick) { // send message only if at least one value is present if (!emData.isEmpty() ) { diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java index 05ed1d93..43f7ed0c 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java @@ -7,7 +7,6 @@ package edu.ie3.simona.api.data.model.em; import edu.ie3.datamodel.models.result.system.FlexOptionsResult; -import org.slf4j.Logger; import tech.units.indriya.ComparableQuantity; import javax.measure.quantity.Power; @@ -18,10 +17,10 @@ * Extended {@link FlexOptionsResult}, that contains the receiver of the flex options. This models * may also contain a disaggregation of the total flex options. */ -public final class ExtendedFlexOptionsResult extends FlexOptionsResult implements EmData { +public final class ExtendedFlexOptionsResult extends FlexOptionsResult implements FlexOptions { /** The disaggregated flex option results. */ - private final Map disaggregated; + private final Map disaggregated; /** * Standard constructor for {@link ExtendedFlexOptionsResult}. @@ -57,7 +56,7 @@ public ExtendedFlexOptionsResult( ComparableQuantity pRef, ComparableQuantity pMin, ComparableQuantity pMax, - Map disaggregated) { + Map disaggregated) { super(time, model, pRef, pMin, pMax); this.disaggregated = disaggregated; } @@ -65,13 +64,10 @@ public ExtendedFlexOptionsResult( /** * Method for adding disaggregated flex option results to this object. * - *

Note: This method does not check, if the disaggregated flex options match the total flex - * options. To do this, please use the method {@link #checkFlexOptions(Logger)}. - * * @param uuid of the inferior model * @param flexOptionsResult the flex options of the inferior model */ - public void addDisaggregated(UUID uuid, FlexOptionsResult flexOptionsResult) { + public void addDisaggregated(UUID uuid, FlexOptions flexOptionsResult) { this.disaggregated.put(uuid, flexOptionsResult); } @@ -86,73 +82,10 @@ public boolean hasDisaggregated() { *

Note: If no disaggregated flex options are present (see: {@link #hasDisaggregated()}), the * map will be empty. */ - public Map getDisaggregated() { + public Map getDisaggregated() { return Collections.unmodifiableMap(disaggregated); } - /** - * Method for checking if the disaggregated flex options match the total flex options. - * - * @param log used for logging - * @return {@code true} if the flex options match, else {@code false} - */ - public boolean checkFlexOptions(Logger log) { - List> refs = new ArrayList<>(); - List> mins = new ArrayList<>(); - List> maxs = new ArrayList<>(); - - disaggregated.forEach( - (uuid, flexOptionsResult) -> { - refs.add(flexOptionsResult.getpRef()); - mins.add(flexOptionsResult.getpMin()); - maxs.add(flexOptionsResult.getpMax()); - }); - - ComparableQuantity ref = getpRef(); - ComparableQuantity min = getpMin(); - ComparableQuantity max = getpMax(); - - Optional> refSum = refs.stream().reduce(ComparableQuantity::add); - Optional> minSum = mins.stream().reduce(ComparableQuantity::add); - Optional> maxSum = maxs.stream().reduce(ComparableQuantity::add); - - boolean isRefValid = false; - boolean isMinValid = false; - boolean isMaxValid = false; - - if (refSum.isPresent()) { - isRefValid = refSum.get().isEquivalentTo(ref); - - if (!isRefValid) { - log.warn("Disaggregated reference power does not match total reference power."); - } - } else { - log.warn("Cannot check disaggregated reference power."); - } - - if (minSum.isPresent()) { - isMinValid = minSum.get().isEquivalentTo(min); - - if (!isMinValid) { - log.warn("Disaggregated minimum power does not match total minimum power."); - } - } else { - log.warn("Cannot check disaggregated minimum power."); - } - - if (maxSum.isPresent()) { - isMaxValid = maxSum.get().isEquivalentTo(max); - - if (!isMaxValid) { - log.warn("Disaggregated maximum power does not match total maximum power."); - } - } else { - log.warn("Cannot check disaggregated maximum power."); - } - - return isRefValid && isMinValid && isMaxValid; - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java index a25b688b..7f56029b 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java @@ -7,14 +7,16 @@ package edu.ie3.simona.api.mapping; import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; +import edu.ie3.datamodel.models.input.EmInput; import edu.ie3.datamodel.models.input.container.GridContainer; import edu.ie3.datamodel.models.value.Value; + import java.util.*; /** Contains the mapping between SIMONA uuid, the external id and the data type the assets hold */ public class ExtEntityMapping { - private final EnumMap> extAssets = new EnumMap<>(DataType.class); + private final EnumMap> extAssets = new EnumMap<>(DataType.class); private final Map> primaryMapping = new HashMap<>(); // asset lists @@ -40,7 +42,7 @@ public ExtEntityMapping(List entries) { uuidToId.put(uuid, id); idToUuid.put(id, uuid); - extAssets.computeIfAbsent(dataType, k -> new ArrayList<>()).add(uuid); + extAssets.computeIfAbsent(dataType, k -> new HashSet<>()).add(uuid); }); } @@ -66,6 +68,8 @@ public ExtEntityMapping(GridContainer grid) { gridAssets.add(asset.getUuid()); }); + Set emInputs = new HashSet<>(); + // handling of participants and ems grid.getSystemParticipants() .allEntitiesAsList() @@ -95,8 +99,34 @@ public ExtEntityMapping(GridContainer grid) { // add to asset list ems.add(emUuid); + emInputs.add(em); }); }); + + + handleEMs(emInputs).forEach(em -> { + UUID uuid = em.getUuid(); + String id = em.getId(); + + uuidToId.put(uuid, id); + idToUuid.put(id, uuid); + + ems.add(uuid); + }); + } + + private Set handleEMs(Set givenSet) { + Set next = new HashSet<>(); + + givenSet.forEach(em -> em.getControllingEm().ifPresent(next::add)); + + Set result = new HashSet<>(givenSet); + + if (!next.isEmpty()) { + result.addAll(handleEMs(next)); + } + + return result; } /** @@ -189,10 +219,10 @@ private void includeEntries(List included) { */ private void addExtEntities(DataType dataType, List included) { if (dataType == DataType.PRIMARY_RESULT) { - extAssets.computeIfAbsent(DataType.PRIMARY, d -> new ArrayList<>()).addAll(included); - extAssets.computeIfAbsent(DataType.RESULT, d -> new ArrayList<>()).addAll(included); + extAssets.computeIfAbsent(DataType.PRIMARY, d -> new HashSet<>()).addAll(included); + extAssets.computeIfAbsent(DataType.RESULT, d -> new HashSet<>()).addAll(included); } else { - extAssets.computeIfAbsent(dataType, k -> new ArrayList<>()).addAll(included); + extAssets.computeIfAbsent(dataType, k -> new HashSet<>()).addAll(included); } } @@ -237,18 +267,20 @@ public List getAssets(DataType dataType) { if (uuids.isEmpty()) { if (dataType == DataType.PRIMARY_RESULT) { List res = new ArrayList<>(); - res.addAll(extAssets.getOrDefault(DataType.PRIMARY, Collections.emptyList())); - res.addAll(extAssets.getOrDefault(DataType.RESULT, Collections.emptyList())); + res.addAll(extAssets.getOrDefault(DataType.PRIMARY, Collections.emptySet())); + res.addAll(extAssets.getOrDefault(DataType.RESULT, Collections.emptySet())); return res; } else { - return extAssets.getOrDefault(dataType, Collections.emptyList()); + return new ArrayList<>(extAssets.getOrDefault(dataType, Collections.emptySet())); } } else { List ext = new ArrayList<>(); extAssets.values().forEach(ext::addAll); + System.out.println("Ems: "+ems); + if (extAssets.isEmpty()) { return uuids; } else { From 728d3aea20264a9eeaffd51a452eab39197c148b Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 27 Oct 2025 08:02:24 +0100 Subject: [PATCH 78/80] Saving changes. --- .../api/data/container/ExtInputContainer.java | 13 +++++++++++++ .../api/data/container/ExtOutputContainer.java | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java index 779cf2d1..0ef02209 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java @@ -201,4 +201,17 @@ public String flexOptionsString() { public String setPointsString() { return setPoints.toString(); } + + @Override + public String toString() { + return "ExtInputContainer{" + + "tick=" + tick + + ", maybeNextTick=" + maybeNextTick + + ", primaryData=" + primaryData + + ", flexRequests=" + flexRequests + + ", flexOptions=" + flexOptions + + ", setPoints=" + setPoints + + ", emMessages=" + emMessages + + '}'; + } } diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java index c6ee88ca..fd169ab1 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java @@ -135,4 +135,14 @@ public List getResult(UUID assetId) { public List getEmData(UUID assetId) { return emDataMap.getOrDefault(assetId, Collections.emptyList()); } + + @Override + public String toString() { + return "ExtOutputContainer{" + + "tick=" + tick + + ", maybeNextTick=" + maybeNextTick + + ", resultMap=" + resultMap + + ", emDataMap=" + emDataMap + + '}'; + } } From 9c2df60f1161dfa28a75bbccd782387f295e93e3 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 28 Oct 2025 09:33:29 +0100 Subject: [PATCH 79/80] Fixed issues related to em data --- CHANGELOG.md | 6 + .../data/connection/ExtEmDataConnection.java | 79 ++++++------- .../connection/ExtOutputDataConnection.java | 2 +- .../model/em/ExtendedFlexOptionsResult.java | 70 +---------- .../simona/api/data/model/em/FlexOptions.java | 16 ++- .../api/data/model/em/GeneralFlexOptions.java | 17 ++- .../data/model/em/PowerLimitFlexOptions.java | 16 ++- .../simona/api/mapping/ExtEntityMapping.java | 46 ++++++-- .../ontology/em/EmCommunicationMessages.java | 6 +- .../api/ontology/em/FlexOptionsResponse.java | 5 +- .../simona/api/ontology/em/ProvideEmData.java | 35 ++++-- .../ontology/em/ProvideEmSetPointData.java | 17 --- .../api/ontology/em/RequestEmFlexResults.java | 14 --- .../api/simulation/ExtCoSimulation.java | 26 ++++- .../connection/ExtEmDataConnectionTest.groovy | 109 +++++------------- .../container/ExtInputContainerTest.groovy | 21 ++-- .../container/ExtOutputContainerTest.groovy | 8 +- .../em/ExtendedFlexOptionsResultTest.groovy | 32 ----- .../api/data/model/em/FlexOptionsTest.groovy | 13 ++- .../api/simulation/ExtCoSimulationTest.groovy | 14 +-- 20 files changed, 245 insertions(+), 307 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmSetPointData.java delete mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/RequestEmFlexResults.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f2f8d9d..57eaf38a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased/Snapshot] +### Changed +- Changes to sent and received em data [#2366](https://github.com/ie3-institute/simonaAPI/issues/366) + +### Fixed +- Issues related to em data [#2366](https://github.com/ie3-institute/simonaAPI/issues/366) + ## [0.11.0] - 2025-10-23 ### Added diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index 024bee48..6b021ae0 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java @@ -9,6 +9,7 @@ import edu.ie3.simona.api.data.model.em.*; import edu.ie3.simona.api.ontology.em.*; import java.util.*; +import org.slf4j.Logger; /** Enables data connection of em data between SIMONA and SimonaAPI */ public final class ExtEmDataConnection @@ -32,80 +33,80 @@ public List getControlledEms() { } /** - * Tries to send em data to SIMONA. A message is sent, if at least one map is not empty. + * Tries to send flex option requests to SIMONA. A message is sent, if at least one entity is + * given. * * @param tick current tick - * @param flexRequests receiver to flex option request - * @param flexOptions receiver to flex options - * @param setPoints receiver to set point - * @param maybeNextTick option for the next tick in the simulation + * @param entities for which flex options should be requested + * @param disaggregated if disaggregated flex option should be returned * @return true, if data was sent */ - public boolean sendEmData( - long tick, - Map flexRequests, - Map> flexOptions, - Map setPoints, - Optional maybeNextTick) { + public boolean sendFlexRequest(long tick, Collection entities, boolean disaggregated) { + // create requests + Map requests = new HashMap<>(); + entities.forEach( + emEntity -> requests.put(emEntity, new FlexOptionRequest(emEntity, disaggregated))); + // send message only if at least one value is present - if (!flexRequests.isEmpty() || !flexOptions.isEmpty() || !setPoints.isEmpty()) { - sendExtMsg(new ProvideEmData(tick, flexRequests, flexOptions, setPoints, maybeNextTick)); + if (!entities.isEmpty()) { + sendExtMsg(new ProvideEmData(tick, requests, Collections.emptyMap(), Collections.emptyMap())); return true; } return false; } /** - * Tries to send flex option requests to SIMONA. A message is sent, if at least one entity is - * given. + * Tries to send em data to SIMONA. A message is sent, if the map is not empty. * * @param tick current tick - * @param entities for which flex options should be requested - * @param disaggregated if disaggregated flex option should be returned + * @param emData a map: receiver to em data + * @param log logger for logging warnings * @return true, if data was sent */ - public boolean sendFlexRequest(long tick, Collection entities, boolean disaggregated) { + public boolean sendEmData(long tick, Map emData, Logger log) { // send message only if at least one value is present - if (!entities.isEmpty()) { - sendExtMsg(new RequestEmFlexResults(tick, new ArrayList<>(entities), disaggregated)); + if (!emData.isEmpty()) { + sendExtMsg(ProvideEmData.create(tick, emData, log)); return true; } return false; } /** - * Tries to send communication messages to SIMONA. A message is sent, if at least one message is - * given. + * Tries to send em data to SIMONA. A message is sent, if at least one map is not empty. * * @param tick current tick - * @param emCommunicationMessages that should be sent - * @param maybeNextTick an option for the next tick + * @param flexRequests receiver to flex option request + * @param flexOptions receiver to flex options + * @param setPoints receiver to set point that should be sent to SIMONA * @return true, if data was sent */ - public boolean sendCommunicationMessage( + public boolean sendEmData( long tick, - List> emCommunicationMessages, - Optional maybeNextTick) { + Map flexRequests, + Map> flexOptions, + Map setPoints) { // send message only if at least one value is present - if (!emCommunicationMessages.isEmpty()) { - sendExtMsg(new EmCommunicationMessages(tick, emCommunicationMessages, maybeNextTick)); + if (!flexRequests.isEmpty() || !flexOptions.isEmpty() || !setPoints.isEmpty()) { + sendExtMsg(new ProvideEmData(tick, flexRequests, flexOptions, setPoints)); return true; } return false; } /** - * Tries to send the em set points to SIMONA. + * Tries to send communication messages to SIMONA. A message is sent, if at least one message is + * given. * * @param tick current tick - * @param setPoints receiver to set point, that should be sent to SIMONA - * @param maybeNextTick option for the next tick in the simulation + * @param emCommunicationMessages that should be sent * @return true, if data was sent */ - public boolean sendSetPoints( - long tick, Map setPoints, Optional maybeNextTick) { - if (!setPoints.isEmpty()) { - sendExtMsg(new ProvideEmSetPointData(tick, setPoints, maybeNextTick)); + public boolean sendCommunicationMessage( + long tick, List> emCommunicationMessages) { + // send message only if at least one value is present + if (!emCommunicationMessages.isEmpty()) { + sendExtMsg(new EmCommunicationMessages(tick, emCommunicationMessages)); return true; } return false; @@ -116,12 +117,12 @@ public boolean sendSetPoints( * * @param tick for which set points are requested * @param emEntities for which set points are requested - * @return an {@link FlexOptionsResponse} message + * @return a map: uuid to list of flex options * @throws InterruptedException - on interruptions */ - public Map requestEmFlexResults( + public Map> requestEmFlexResults( long tick, List emEntities, boolean disaggregated) throws InterruptedException { - sendExtMsg(new RequestEmFlexResults(tick, emEntities, disaggregated)); + sendFlexRequest(tick, emEntities, disaggregated); return receiveWithType(FlexOptionsResponse.class).receiverToFlexOptions(); } diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java index 23dab268..68552672 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtOutputDataConnection.java @@ -15,7 +15,7 @@ * @param type of response messages to ext */ public sealed interface ExtOutputDataConnection - permits BiDirectional, ExtResultListener { + extends ExtDataConnection permits BiDirectional, ExtResultListener { /** Queues message from SIMONA that should be handled by the external simulation. */ void queueExtResponseMsg(T msg) throws InterruptedException; diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java index e57b6ef8..243ac60e 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java @@ -10,14 +10,13 @@ import java.time.ZonedDateTime; import java.util.*; import javax.measure.quantity.Power; -import org.slf4j.Logger; import tech.units.indriya.ComparableQuantity; /** * Extended {@link FlexOptionsResult}, that contains the receiver of the flex options. This models * may also contain a disaggregation of the total flex options. */ -public final class ExtendedFlexOptionsResult extends FlexOptionsResult implements EmData { +public final class ExtendedFlexOptionsResult extends FlexOptionsResult { /** The disaggregated flex option results. */ private final Map disaggregated; @@ -49,6 +48,7 @@ public ExtendedFlexOptionsResult( * @param pRef active power that was suggested for regular usage by the system participant * @param pMin active minimal power that was determined by the system participant * @param pMax active maximum power that was determined by the system participant + * @param disaggregated a map: uuid to disaggregated flex options */ public ExtendedFlexOptionsResult( ZonedDateTime time, @@ -64,9 +64,6 @@ public ExtendedFlexOptionsResult( /** * Method for adding disaggregated flex option results to this object. * - *

Note: This method does not check, if the disaggregated flex options match the total flex - * options. To do this, please use the method {@link #checkFlexOptions(Logger)}. - * * @param uuid of the inferior model * @param flexOptionsResult the flex options of the inferior model */ @@ -89,69 +86,6 @@ public Map getDisaggregated() { return Collections.unmodifiableMap(disaggregated); } - /** - * Method for checking if the disaggregated flex options match the total flex options. - * - * @param log used for logging - * @return {@code true} if the flex options match, else {@code false} - */ - public boolean checkFlexOptions(Logger log) { - List> refs = new ArrayList<>(); - List> mins = new ArrayList<>(); - List> maxs = new ArrayList<>(); - - disaggregated.forEach( - (uuid, flexOptionsResult) -> { - refs.add(flexOptionsResult.getpRef()); - mins.add(flexOptionsResult.getpMin()); - maxs.add(flexOptionsResult.getpMax()); - }); - - ComparableQuantity ref = getpRef(); - ComparableQuantity min = getpMin(); - ComparableQuantity max = getpMax(); - - Optional> refSum = refs.stream().reduce(ComparableQuantity::add); - Optional> minSum = mins.stream().reduce(ComparableQuantity::add); - Optional> maxSum = maxs.stream().reduce(ComparableQuantity::add); - - boolean isRefValid = false; - boolean isMinValid = false; - boolean isMaxValid = false; - - if (refSum.isPresent()) { - isRefValid = refSum.get().isEquivalentTo(ref); - - if (!isRefValid) { - log.warn("Disaggregated reference power does not match total reference power."); - } - } else { - log.warn("Cannot check disaggregated reference power."); - } - - if (minSum.isPresent()) { - isMinValid = minSum.get().isEquivalentTo(min); - - if (!isMinValid) { - log.warn("Disaggregated minimum power does not match total minimum power."); - } - } else { - log.warn("Cannot check disaggregated minimum power."); - } - - if (maxSum.isPresent()) { - isMaxValid = maxSum.get().isEquivalentTo(max); - - if (!isMaxValid) { - log.warn("Disaggregated maximum power does not match total maximum power."); - } - } else { - log.warn("Cannot check disaggregated maximum power."); - } - - return isRefValid && isMinValid && isMaxValid; - } - @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java index d4f7b76a..42352229 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java @@ -6,5 +6,19 @@ package edu.ie3.simona.api.data.model.em; +import java.util.UUID; + /** Interface that defines flex options. */ -public interface FlexOptions extends EmData {} +public interface FlexOptions extends EmData { + + /** Returns the receiver of this flex options. */ + UUID receiver(); + + /** + * Enriches the flex option with disaggregated flex options. + * + * @param model of the flex options + * @param flexOptions to include + */ + void addDisaggregates(UUID model, FlexOptions flexOptions); +} diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/GeneralFlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/GeneralFlexOptions.java index 83bb2ece..c52349fb 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/GeneralFlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/GeneralFlexOptions.java @@ -25,9 +25,10 @@ * @param etaCharge The charging losses in percent. * @param etaDischarge The discharging losses in percent. * @param tickToEnergyLimits A map: tick to energy limits. - * @param disaggregatedFlexOptions A map: uuid to disaggregated flex options. + * @param disaggregated A map: uuid to disaggregated flex options. */ public record GeneralFlexOptions( + UUID receiver, UUID model, String flexType, ComparableQuantity pMin, @@ -35,10 +36,11 @@ public record GeneralFlexOptions( ComparableQuantity etaCharge, ComparableQuantity etaDischarge, Map>> tickToEnergyLimits, - Map disaggregatedFlexOptions) + Map disaggregated) implements FlexOptions { public GeneralFlexOptions( + UUID receiver, UUID model, String flexType, ComparableQuantity pMin, @@ -47,6 +49,7 @@ public GeneralFlexOptions( ComparableQuantity etaDischarge, Map>> tickToEnergyLimits) { this( + receiver, model, flexType, pMin, @@ -56,4 +59,14 @@ public GeneralFlexOptions( tickToEnergyLimits, Collections.emptyMap()); } + + @Override + public UUID receiver() { + return receiver; + } + + @Override + public void addDisaggregates(UUID model, FlexOptions flexOptions) { + disaggregated.put(model, flexOptions); + } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/PowerLimitFlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/PowerLimitFlexOptions.java index 4c72c35e..bde3a957 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/PowerLimitFlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/PowerLimitFlexOptions.java @@ -15,6 +15,7 @@ /** * Power limit flex option that will be sent to SIMONA. * + * @param receiver The uuid of the receiver. It can be the same as the model. * @param model That is providing this flex options. * @param pRef Active power (might be negative, thus feed-in) that was suggested for regular usage. * @param pMin Minimal active power to which the sender can be reduced (might be negative, thus @@ -23,8 +24,10 @@ * @param pMax Maximum active power to which the sender can be increased (might be negative, thus * feed-in), that was determined by the system. Therefore, equates to upper bound of possible * flexibility provision. + * @param disaggregated A map: uuid to disaggregated flex options. */ public record PowerLimitFlexOptions( + UUID receiver, UUID model, ComparableQuantity pRef, ComparableQuantity pMin, @@ -33,10 +36,21 @@ public record PowerLimitFlexOptions( implements FlexOptions { public PowerLimitFlexOptions( + UUID receiver, UUID model, ComparableQuantity pRef, ComparableQuantity pMin, ComparableQuantity pMax) { - this(model, pRef, pMin, pMax, Collections.emptyMap()); + this(receiver, model, pRef, pMin, pMax, Collections.emptyMap()); + } + + @Override + public UUID receiver() { + return receiver; + } + + @Override + public void addDisaggregates(UUID model, FlexOptions flexOptions) { + disaggregated.put(model, flexOptions); } } diff --git a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java index a25b688b..113308a1 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java @@ -7,6 +7,7 @@ package edu.ie3.simona.api.mapping; import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme; +import edu.ie3.datamodel.models.input.EmInput; import edu.ie3.datamodel.models.input.container.GridContainer; import edu.ie3.datamodel.models.value.Value; import java.util.*; @@ -14,7 +15,7 @@ /** Contains the mapping between SIMONA uuid, the external id and the data type the assets hold */ public class ExtEntityMapping { - private final EnumMap> extAssets = new EnumMap<>(DataType.class); + private final EnumMap> extAssets = new EnumMap<>(DataType.class); private final Map> primaryMapping = new HashMap<>(); // asset lists @@ -40,7 +41,7 @@ public ExtEntityMapping(List entries) { uuidToId.put(uuid, id); idToUuid.put(id, uuid); - extAssets.computeIfAbsent(dataType, k -> new ArrayList<>()).add(uuid); + extAssets.computeIfAbsent(dataType, k -> new HashSet<>()).add(uuid); }); } @@ -66,6 +67,8 @@ public ExtEntityMapping(GridContainer grid) { gridAssets.add(asset.getUuid()); }); + Set emInputs = new HashSet<>(); + // handling of participants and ems grid.getSystemParticipants() .allEntitiesAsList() @@ -95,8 +98,35 @@ public ExtEntityMapping(GridContainer grid) { // add to asset list ems.add(emUuid); + emInputs.add(em); }); }); + + handleEMs(emInputs) + .forEach( + em -> { + UUID uuid = em.getUuid(); + String id = em.getId(); + + uuidToId.put(uuid, id); + idToUuid.put(id, uuid); + + ems.add(uuid); + }); + } + + private Set handleEMs(Set givenSet) { + Set next = new HashSet<>(); + + givenSet.forEach(em -> em.getControllingEm().ifPresent(next::add)); + + Set result = new HashSet<>(givenSet); + + if (!next.isEmpty()) { + result.addAll(handleEMs(next)); + } + + return result; } /** @@ -189,10 +219,10 @@ private void includeEntries(List included) { */ private void addExtEntities(DataType dataType, List included) { if (dataType == DataType.PRIMARY_RESULT) { - extAssets.computeIfAbsent(DataType.PRIMARY, d -> new ArrayList<>()).addAll(included); - extAssets.computeIfAbsent(DataType.RESULT, d -> new ArrayList<>()).addAll(included); + extAssets.computeIfAbsent(DataType.PRIMARY, d -> new HashSet<>()).addAll(included); + extAssets.computeIfAbsent(DataType.RESULT, d -> new HashSet<>()).addAll(included); } else { - extAssets.computeIfAbsent(dataType, k -> new ArrayList<>()).addAll(included); + extAssets.computeIfAbsent(dataType, k -> new HashSet<>()).addAll(included); } } @@ -237,12 +267,12 @@ public List getAssets(DataType dataType) { if (uuids.isEmpty()) { if (dataType == DataType.PRIMARY_RESULT) { List res = new ArrayList<>(); - res.addAll(extAssets.getOrDefault(DataType.PRIMARY, Collections.emptyList())); - res.addAll(extAssets.getOrDefault(DataType.RESULT, Collections.emptyList())); + res.addAll(extAssets.getOrDefault(DataType.PRIMARY, Collections.emptySet())); + res.addAll(extAssets.getOrDefault(DataType.RESULT, Collections.emptySet())); return res; } else { - return extAssets.getOrDefault(dataType, Collections.emptyList()); + return new ArrayList<>(extAssets.getOrDefault(dataType, Collections.emptySet())); } } else { diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/EmCommunicationMessages.java b/src/main/java/edu/ie3/simona/api/ontology/em/EmCommunicationMessages.java index cb96f68f..91fa048a 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/EmCommunicationMessages.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/EmCommunicationMessages.java @@ -9,7 +9,6 @@ import edu.ie3.simona.api.data.model.em.EmCommunicationMessage; import edu.ie3.simona.api.data.model.em.EmData; import java.util.Collection; -import java.util.Optional; /** * This message contains {@link EmCommunicationMessage}s that can be sent either to SIMONA or to the @@ -17,10 +16,7 @@ * * @param tick of the message * @param messages the communication messages that should be sent - * @param maybeNextTick option for the next tick */ public record EmCommunicationMessages( - long tick, - Collection> messages, - Optional maybeNextTick) + long tick, Collection> messages) implements EmDataMessageFromExt, EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/FlexOptionsResponse.java b/src/main/java/edu/ie3/simona/api/ontology/em/FlexOptionsResponse.java index 49852430..6e636c79 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/FlexOptionsResponse.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/FlexOptionsResponse.java @@ -6,10 +6,11 @@ package edu.ie3.simona.api.ontology.em; -import edu.ie3.simona.api.data.model.em.ExtendedFlexOptionsResult; +import edu.ie3.simona.api.data.model.em.FlexOptions; +import java.util.List; import java.util.Map; import java.util.UUID; /** Message that provides em data (flexibility options) to an external simulation. */ -public record FlexOptionsResponse(Map receiverToFlexOptions) +public record FlexOptionsResponse(Map> receiverToFlexOptions) implements EmDataResponseMessageToExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmData.java b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmData.java index 5b3694f5..c25b25af 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmData.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmData.java @@ -6,19 +6,34 @@ package edu.ie3.simona.api.ontology.em; -import edu.ie3.simona.api.data.model.em.EmSetPoint; -import edu.ie3.simona.api.data.model.em.FlexOptionRequest; -import edu.ie3.simona.api.data.model.em.FlexOptions; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import edu.ie3.simona.api.data.model.em.*; +import java.util.*; +import org.slf4j.Logger; /** Message that provides em data from an external simulation. */ public record ProvideEmData( long tick, Map flexRequests, Map> flexOptions, - Map setPoints, - Optional maybeNextTick) - implements EmDataMessageFromExt {} + Map setPoints) + implements EmDataMessageFromExt { + + public static ProvideEmData create(long tick, Map emData, Logger log) { + Map flexRequests = new HashMap<>(); + Map> flexOptions = new HashMap<>(); + Map setPoints = new HashMap<>(); + + emData.forEach( + (uuid, emDataItem) -> { + switch (emDataItem) { + case FlexOptionRequest r -> flexRequests.put(uuid, r); + case FlexOptions r -> + flexOptions.computeIfAbsent(uuid, receiver -> new ArrayList<>()).add(r); + case EmSetPoint r -> setPoints.put(uuid, r); + default -> log.warn("Received unsupported em data: {}", emDataItem); + } + }); + + return new ProvideEmData(tick, flexRequests, flexOptions, setPoints); + } +} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmSetPointData.java b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmSetPointData.java deleted file mode 100644 index 330da4bf..00000000 --- a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmSetPointData.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * © 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.ontology.em; - -import edu.ie3.simona.api.data.model.em.EmSetPoint; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; - -/** Message that provides em data (set points) from an external simulation. */ -public record ProvideEmSetPointData( - long tick, Map emSetPoints, Optional maybeNextTick) - implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmFlexResults.java b/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmFlexResults.java deleted file mode 100644 index 47d41f92..00000000 --- a/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmFlexResults.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * © 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.ontology.em; - -import java.util.List; -import java.util.UUID; - -/** Request em set points from SIMONA in the given tick. */ -public record RequestEmFlexResults(long tick, List emEntities, boolean disaggregated) - implements EmDataMessageFromExt {} 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 0f34d11e..64342e61 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -133,6 +133,25 @@ protected void sendPrimaryDataToSimona( // energy management data methods + /** + * Function to send em set point data to SIMONA using the given {@link ExtEmDataConnection}. This + * method will take a value from the {@link #queueToSimona}. + * + *

{@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 log logger + * @throws InterruptedException if the fetching of data is interrupted + */ + protected void sendEmSetPointsToSimona( + ExtEmDataConnection extEmDataConnection, long tick, Logger log) throws InterruptedException { + Map inputData = queueToSimona.takeData(ExtInputContainer::extractSetPoints); + + sendEmSetPointsToSimona(extEmDataConnection, tick, inputData, log); + } + /** * 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. @@ -140,17 +159,15 @@ protected void sendPrimaryDataToSimona( * @param extEmDataConnection the connection to SIMONA * @param tick for which data is sent * @param setPoints map: id to set point - * @param maybeNextTick option for the next tick data is sent * @param log logger */ protected void sendEmSetPointsToSimona( ExtEmDataConnection extEmDataConnection, long tick, Map setPoints, - Optional maybeNextTick, Logger log) { log.debug("Received em set points from {}", extSimulatorName); - boolean wasSent = extEmDataConnection.sendSetPoints(tick, setPoints, maybeNextTick); + boolean wasSent = extEmDataConnection.sendEmData(tick, setPoints, log); if (!wasSent) { log.debug("No set point data was sent to SIMONA!"); } @@ -160,7 +177,8 @@ protected void sendEmSetPointsToSimona( // result data methods /** - * Function to get 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 diff --git a/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy index f29a4479..0e525431 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/connection/ExtEmDataConnectionTest.groovy @@ -2,7 +2,6 @@ package edu.ie3.simona.api.data.connection import edu.ie3.simona.api.data.connection.ExtEmDataConnection.EmMode import edu.ie3.simona.api.data.model.em.EmCommunicationMessage -import edu.ie3.simona.api.data.model.em.ExtendedFlexOptionsResult import edu.ie3.simona.api.data.model.em.FlexOptionRequest import edu.ie3.simona.api.data.model.em.PowerLimitFlexOptions import edu.ie3.simona.api.ontology.DataMessageFromExt @@ -13,8 +12,6 @@ import org.apache.pekko.actor.testkit.typed.javadsl.ActorTestKit import spock.lang.Shared import spock.lang.Specification -import java.time.ZonedDateTime - class ExtEmDataConnectionTest extends Specification implements DataServiceTestData { @Shared @@ -32,7 +29,7 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa testKit = null } - def "ExtEmDataConnection should provide em flex requests correctly"() { + def "ExtEmDataConnection should provide em data correctly"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) @@ -45,33 +42,16 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa def emData = Map.of(inputUuid, new FlexOptionRequest(inputUuid, false)) when: - def wasSent = extEmDataConnection.sendEmData(0L, emData, [:], [:], Optional.of(900L)) + def wasSent = extEmDataConnection.sendEmData(0L, emData, log) then: wasSent - dataService.expectMessage(new ProvideEmData(0, emData, [:], [:], Optional.of(900L))) + dataService.expectMessage(new ProvideEmData(0, emData, [:], [:])) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) - } - - def "ExtEmDataConnection should send no message, if no flex requests are given"() { - given: - def dataService = testKit.createTestProbe(DataMessageFromExt) - def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extEmDataConnection = new ExtEmDataConnection(controlled, EmMode.BASE) - extEmDataConnection.setActorRefs( - dataService.ref(), - extSimAdapter.ref() - ) - when: - def wasSent = extEmDataConnection.sendEmData(0L, [:], [:], [:], Optional.of(900L)) - - then: - !wasSent - dataService.expectNoMessage() } - def "ExtEmDataConnection should provide em flex options correctly"() { + def "ExtEmDataConnection should provide em flex requests correctly"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) @@ -81,18 +61,18 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa extSimAdapter.ref() ) - def emData = Map.of(inputUuid, [new PowerLimitFlexOptions(inputUuid, power, power, power)]) + def emData = Map.of(inputUuid, new FlexOptionRequest(inputUuid, false)) when: - def wasSent = extEmDataConnection.sendEmData(0L, [:], emData, [:], Optional.of(900L)) + def wasSent = extEmDataConnection.sendEmData(0L, emData, [:], [:]) then: wasSent - dataService.expectMessage(new ProvideEmData(0, [:], emData, [:], Optional.of(900L))) + dataService.expectMessage(new ProvideEmData(0, emData, [:], [:])) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) } - def "ExtEmDataConnection should send no message, if no flex options are given"() { + def "ExtEmDataConnection should send no message, if no flex requests are given"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) @@ -103,14 +83,14 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa ) when: - def wasSent = extEmDataConnection.sendEmData(0L, [:], [:], [:], Optional.of(900L)) + def wasSent = extEmDataConnection.sendEmData(0L, [:], [:], [:]) then: !wasSent dataService.expectNoMessage() } - def "ExtEmDataConnection should provide flex option requests correctly"() { + def "ExtEmDataConnection should provide em flex options correctly"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) @@ -120,16 +100,18 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa extSimAdapter.ref() ) + def emData = Map.of(inputUuid, [new PowerLimitFlexOptions(inputUuid, inputUuid, power, power, power)]) + when: - def wasSent = extEmDataConnection.sendFlexRequest(0L, [inputUuid], true) + def wasSent = extEmDataConnection.sendEmData(0L, [:], emData, [:]) then: wasSent - dataService.expectMessage(new RequestEmFlexResults(0, [inputUuid], true)) + dataService.expectMessage(new ProvideEmData(0, [:], emData, [:])) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) } - def "ExtEmDataConnection should send no message, if no flex requests are given"() { + def "ExtEmDataConnection should send no message, if no flex options are given"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) @@ -140,14 +122,14 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa ) when: - def wasSent = extEmDataConnection.sendFlexRequest(0L, [], true) + def wasSent = extEmDataConnection.sendEmData(0L, [:], [:], [:]) then: !wasSent dataService.expectNoMessage() } - def "ExtEmDataConnection should provide communication messages correctly"() { + def "ExtEmDataConnection should provide flex option requests correctly"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) @@ -157,36 +139,16 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa extSimAdapter.ref() ) - def message = new EmCommunicationMessage(UUID.randomUUID(), UUID.randomUUID(), null) - when: - def wasSent = extEmDataConnection.sendCommunicationMessage(0L, [message], Optional.of(900L)) + def wasSent = extEmDataConnection.sendFlexRequest(0L, [inputUuid], true) then: wasSent - dataService.expectMessage(new EmCommunicationMessages(0, [message], Optional.of(900L))) + dataService.expectMessage( new ProvideEmData(0, [(inputUuid): new FlexOptionRequest(inputUuid, true)], [:], [:])) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) } - def "ExtEmDataConnection should send no message, if no flex requests are given"() { - given: - def dataService = testKit.createTestProbe(DataMessageFromExt) - def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extEmDataConnection = new ExtEmDataConnection(controlled, EmMode.BASE) - extEmDataConnection.setActorRefs( - dataService.ref(), - extSimAdapter.ref() - ) - - when: - def wasSent = extEmDataConnection.sendCommunicationMessage(0L, [], Optional.of(900L)) - - then: - !wasSent - dataService.expectNoMessage() - } - - def "ExtEmDataConnection should send no message, if input data is empty"() { + def "ExtEmDataConnection should provide communication messages correctly"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) @@ -195,33 +157,16 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa dataService.ref(), extSimAdapter.ref() ) - def inputDataMap = [:] as Map - - when: - def wasSent = extEmDataConnection.sendSetPoints(0L, inputDataMap, Optional.of(900L)) - then: - !wasSent - dataService.expectNoMessage() - } - - def "ExtEmDataConnection should send no message, if no em set points are given"() { - given: - def dataService = testKit.createTestProbe(DataMessageFromExt) - def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) - def extEmDataConnection = new ExtEmDataConnection(controlled, EmMode.BASE) - extEmDataConnection.setActorRefs( - dataService.ref(), - extSimAdapter.ref() - ) - def inputDataMap = [:] as Map + def message = new EmCommunicationMessage(UUID.randomUUID(), UUID.randomUUID(), null) when: - def wasSent = extEmDataConnection.sendSetPoints(0L, inputDataMap, Optional.of(900L)) + def wasSent = extEmDataConnection.sendCommunicationMessage(0L, [message]) then: - !wasSent - dataService.expectNoMessage() + wasSent + dataService.expectMessage(new EmCommunicationMessages(0, [message])) + extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) } def "ExtEmDataConnection should request and receive flex options correctly"() { @@ -234,7 +179,7 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa extSimAdapter.ref() ) - def sendMsg = new FlexOptionsResponse([(inputUuid): new ExtendedFlexOptionsResult(ZonedDateTime.now(), inputUuid, power, power, power)]) + def sendMsg = new FlexOptionsResponse([(inputUuid): new PowerLimitFlexOptions(inputUuid, inputUuid, power, power, power)]) when: // we need to queue the msg beforehand because the receive method is blocking @@ -243,7 +188,7 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa def response = extEmDataConnection.requestEmFlexResults(0L, [inputUuid], false) then: - dataService.expectMessage(new RequestEmFlexResults(0L, [inputUuid], false)) + dataService.expectMessage(new ProvideEmData(0L, [(inputUuid): new FlexOptionRequest(inputUuid, false)], [:], [:])) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) response == sendMsg.receiverToFlexOptions() } diff --git a/src/test/groovy/edu/ie3/simona/api/data/container/ExtInputContainerTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/container/ExtInputContainerTest.groovy index 281e6bba..b813e876 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/container/ExtInputContainerTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/container/ExtInputContainerTest.groovy @@ -44,16 +44,17 @@ class ExtInputContainerTest extends Specification { def "An ExtInputContainer should add flex option data correctly"() { given: + UUID receiver = UUID.randomUUID() UUID sender = UUID.randomUUID() - def flexOptions = new PowerLimitFlexOptions(sender, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) + def flexOptions = new PowerLimitFlexOptions(receiver, sender, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) def container = new ExtInputContainer(0L) when: - container.addFlexOptions(sender, [flexOptions]) + container.addFlexOptions(receiver, [flexOptions]) then: - container.flexOptions == [(sender): [flexOptions]] + container.flexOptions == [(receiver): [flexOptions]] } def "An ExtInputContainer should add set point data correctly"() { @@ -81,9 +82,10 @@ class ExtInputContainerTest extends Specification { UUID requestReceiver = UUID.randomUUID() container.addRequest(requestReceiver) + UUID receiver = UUID.randomUUID() UUID sender = UUID.randomUUID() - def flexOptions = new PowerLimitFlexOptions(sender, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) - container.addFlexOptions(sender, [flexOptions]) + def flexOptions = new PowerLimitFlexOptions(receiver, sender, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) + container.addFlexOptions(receiver, [flexOptions]) UUID emAsset = UUID.randomUUID() def setPoint = new PValue(Quantities.getQuantity(5d, KILOWATT)) @@ -114,7 +116,8 @@ class ExtInputContainerTest extends Specification { container.addRequest(requestReceiver) UUID receiver = UUID.randomUUID() - def flexOptions = new PowerLimitFlexOptions(receiver, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) + UUID model = UUID.randomUUID() + def flexOptions = new PowerLimitFlexOptions(receiver, model, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) container.addFlexOptions(receiver, [flexOptions]) UUID emAsset = UUID.randomUUID() @@ -146,7 +149,8 @@ class ExtInputContainerTest extends Specification { container.addRequest(requestReceiver) UUID receiver = UUID.randomUUID() - def flexOptions = new PowerLimitFlexOptions(receiver, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) + UUID model = UUID.randomUUID() + def flexOptions = new PowerLimitFlexOptions(receiver, model, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) container.addFlexOptions(receiver, [flexOptions]) UUID emAsset = UUID.randomUUID() @@ -178,7 +182,8 @@ class ExtInputContainerTest extends Specification { container.addRequest(requestReceiver) UUID receiver = UUID.randomUUID() - def flexOptions = new PowerLimitFlexOptions(receiver, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) + UUID model = UUID.randomUUID() + def flexOptions = new PowerLimitFlexOptions(receiver, model, Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) container.addFlexOptions(receiver, [flexOptions]) UUID emAsset = UUID.randomUUID() diff --git a/src/test/groovy/edu/ie3/simona/api/data/container/ExtOutputContainerTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/container/ExtOutputContainerTest.groovy index 02309a07..a5c40d40 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/container/ExtOutputContainerTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/container/ExtOutputContainerTest.groovy @@ -35,8 +35,8 @@ class ExtOutputContainerTest extends Specification implements DataServiceTestDat def setPoint = new EmSetPoint(receiver1) UUID receiver2 = UUID.randomUUID() - def options = new PowerLimitFlexOptions(receiver2, null, null, null) - def options2 = new PowerLimitFlexOptions(receiver2, null, null, null) + def options = new PowerLimitFlexOptions(receiver2, UUID.randomUUID(), null, null, null) + def options2 = new PowerLimitFlexOptions(receiver2,UUID.randomUUID(), null, null, null) when: container.addEmData(receiver1, setPoint) @@ -95,8 +95,8 @@ class ExtOutputContainerTest extends Specification implements DataServiceTestDat def setPoint = new EmSetPoint(receiver1) UUID receiver2 = UUID.randomUUID() - def options = new PowerLimitFlexOptions(receiver2, null, null, null) - def options2 = new PowerLimitFlexOptions(receiver2, null, null, null) + def options = new PowerLimitFlexOptions(receiver2, UUID.randomUUID(), null, null, null) + def options2 = new PowerLimitFlexOptions(receiver2, UUID.randomUUID(), null, null, null) def allEmData = [ (receiver1): [setPoint], diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResultTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResultTest.groovy index 5cf6db81..e3cae0cc 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResultTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResultTest.groovy @@ -2,8 +2,6 @@ package edu.ie3.simona.api.data.model.em import edu.ie3.datamodel.models.result.system.FlexOptionsResult import edu.ie3.util.quantities.PowerSystemUnits -import org.slf4j.Logger -import org.slf4j.LoggerFactory import spock.lang.Shared import spock.lang.Specification import tech.units.indriya.ComparableQuantity @@ -14,9 +12,6 @@ import java.time.ZonedDateTime class ExtendedFlexOptionsResultTest extends Specification { - @Shared - Logger logger = LoggerFactory.getLogger(ExtendedFlexOptionsResultTest) - @Shared ZonedDateTime time = ZonedDateTime.now() @@ -103,31 +98,4 @@ class ExtendedFlexOptionsResultTest extends Specification { result.disaggregated.get(inferiorUuid1) == inferiorOptions1 result.disaggregated.get(inferiorUuid2) == inferiorOptions2 } - - def "The ExtendedFlexOptionsResult should check if disaggregated flex options match total flex options correctly"() { - given: - def result = new ExtendedFlexOptionsResult(time, senderUuid, pRef, pMin, pMax) - def inferiorUuid1 = UUID.fromString("a246eee3-405c-4af1-9ad2-69ecad2bfb65") - def inferiorUuid2 = UUID.fromString("78676121-f154-4f70-ad50-4384ddf8deed") - def inferiorUuid3 = UUID.randomUUID() - - def inferiorOptions1 = new FlexOptionsResult(time, inferiorUuid1, pRef, pMin, pMin) - def inferiorOptions2 = new FlexOptionsResult(time, inferiorUuid2, pMin, pMin, pMax) - def inferiorOptions3 = new FlexOptionsResult(time, inferiorUuid3, pRef, pRef, pMax) - - when: - result.addDisaggregated(inferiorUuid1, inferiorOptions1) - boolean withOnly1 = result.checkFlexOptions(logger) - - result.addDisaggregated(inferiorUuid2, inferiorOptions2) - boolean with1And2 = result.checkFlexOptions(logger) - - result.addDisaggregated(inferiorUuid3, inferiorOptions3) - boolean with1And2And3 = result.checkFlexOptions(logger) - - then: - !withOnly1 - with1And2 - !with1And2And3 - } } diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionsTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionsTest.groovy index 89a77f6b..bc93fe17 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionsTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionsTest.groovy @@ -26,10 +26,14 @@ class FlexOptionsTest extends Specification { ComparableQuantity pMax = Quantities.getQuantity(10, KILOWATT) def "PowerLimitFlexOptions can be constructed correctly"() { + given: + UUID receiver = UUID.randomUUID() + when: - def flexOptions = new PowerLimitFlexOptions(senderUuid, pRef, pMin, pMax) + def flexOptions = new PowerLimitFlexOptions(receiver, senderUuid, pRef, pMin, pMax) then: + flexOptions.receiver == receiver flexOptions.model == senderUuid flexOptions.pRef == pRef flexOptions.pMin == pMin @@ -38,8 +42,12 @@ class FlexOptionsTest extends Specification { } def "GeneralFlexOptions can be constructed correctly"() { + given: + UUID receiver = UUID.randomUUID() + when: def flexOptions = new GeneralFlexOptions( + receiver, senderUuid, "general flex type", Quantities.getQuantity(0, KILOWATT), @@ -50,6 +58,7 @@ class FlexOptionsTest extends Specification { ) then: + flexOptions.receiver == receiver flexOptions.model == senderUuid flexOptions.flexType == "general flex type" flexOptions.pMin == Quantities.getQuantity(0, KILOWATT) @@ -57,7 +66,7 @@ class FlexOptionsTest extends Specification { flexOptions.etaCharge == Quantities.getQuantity(95, PERCENT) flexOptions.etaDischarge == Quantities.getQuantity(95, PERCENT) flexOptions.tickToEnergyLimits == [:] - flexOptions.disaggregatedFlexOptions == [:] + flexOptions.disaggregated == [:] } } 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 24bac433..ab8cf41c 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy @@ -12,7 +12,7 @@ import edu.ie3.simona.api.mapping.DataType import edu.ie3.simona.api.mapping.ExtEntityMapping import edu.ie3.simona.api.ontology.DataMessageFromExt import edu.ie3.simona.api.ontology.ScheduleDataServiceMessage -import edu.ie3.simona.api.ontology.em.ProvideEmSetPointData +import edu.ie3.simona.api.ontology.em.ProvideEmData import org.apache.pekko.actor.testkit.typed.javadsl.ActorTestKit import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -106,9 +106,9 @@ class ExtCoSimulationTest extends Specification { def "An ExtCoSimulation can build a result data connection correctly"() { given: - UUID uuid1 = UUID.randomUUID() - UUID uuid2 = UUID.randomUUID() - UUID uuid3 = UUID.randomUUID() + UUID uuid1 = UUID.fromString("e7209ff5-788a-4b1d-bb26-89b3e326ce74") + UUID uuid2 = UUID.fromString("7ab84c3d-6c43-4c56-9257-21ef72e15b80") + UUID uuid3 = UUID.fromString("806b0cba-23a6-43d0-821e-e023b6a90cc4") def mapping = new ExtEntityMapping([]) mapping.includeIds(DataType.RESULT, [uuid1], Optional.empty()) @@ -147,10 +147,10 @@ class ExtCoSimulationTest extends Specification { def data = [(UUID.randomUUID()): new EmSetPoint(UUID.randomUUID())] when: - sim.sendEmSetPointsToSimona(extEmDataConnection, 0L, data, Optional.empty(), log) + sim.sendEmSetPointsToSimona(extEmDataConnection, 0L, data, log) then: - dataService.expectMessage(new ProvideEmSetPointData(0L, data, Optional.empty())) + dataService.expectMessage(new ProvideEmData(0L, [:], [:], data)) } def "An ExtCoSimulation should not sent empty em set point data"() { @@ -167,7 +167,7 @@ class ExtCoSimulationTest extends Specification { def data = [:] when: - sim.sendEmSetPointsToSimona(extEmDataConnection, 0L, data, Optional.empty(), log) + sim.sendEmSetPointsToSimona(extEmDataConnection, 0L, data, log) then: dataService.expectNoMessage() From f7e0013089374ce5d5fe421d0c5346d2579854fc Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 28 Oct 2025 11:15:42 +0100 Subject: [PATCH 80/80] Saving changes. --- .../model/em/ExtendedFlexOptionsResult.java | 2 +- .../simona/api/data/model/em/FlexOptions.java | 2 +- .../api/data/model/em/GeneralFlexOptions.java | 6 ++--- .../data/model/em/PowerLimitFlexOptions.java | 6 ++--- .../api/simulation/ExtCoSimulation.java | 24 +------------------ 5 files changed, 9 insertions(+), 31 deletions(-) diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java index 519c8957..243ac60e 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java @@ -56,7 +56,7 @@ public ExtendedFlexOptionsResult( ComparableQuantity pRef, ComparableQuantity pMin, ComparableQuantity pMax, - Map disaggregated) { + Map disaggregated) { super(time, model, pRef, pMin, pMax); this.disaggregated = disaggregated; } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java index 42352229..77a46758 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java @@ -20,5 +20,5 @@ public interface FlexOptions extends EmData { * @param model of the flex options * @param flexOptions to include */ - void addDisaggregates(UUID model, FlexOptions flexOptions); + void addDisaggregated(UUID model, FlexOptions flexOptions); } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/GeneralFlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/GeneralFlexOptions.java index c52349fb..b9f05e9b 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/GeneralFlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/GeneralFlexOptions.java @@ -7,7 +7,7 @@ package edu.ie3.simona.api.data.model.em; import edu.ie3.util.interval.ClosedInterval; -import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.measure.quantity.Dimensionless; @@ -57,7 +57,7 @@ public GeneralFlexOptions( etaCharge, etaDischarge, tickToEnergyLimits, - Collections.emptyMap()); + new HashMap<>()); } @Override @@ -66,7 +66,7 @@ public UUID receiver() { } @Override - public void addDisaggregates(UUID model, FlexOptions flexOptions) { + public void addDisaggregated(UUID model, FlexOptions flexOptions) { disaggregated.put(model, flexOptions); } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/PowerLimitFlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/PowerLimitFlexOptions.java index bde3a957..4afc7bb7 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/PowerLimitFlexOptions.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/PowerLimitFlexOptions.java @@ -6,7 +6,7 @@ package edu.ie3.simona.api.data.model.em; -import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.measure.quantity.Power; @@ -41,7 +41,7 @@ public PowerLimitFlexOptions( ComparableQuantity pRef, ComparableQuantity pMin, ComparableQuantity pMax) { - this(receiver, model, pRef, pMin, pMax, Collections.emptyMap()); + this(receiver, model, pRef, pMin, pMax, new HashMap<>()); } @Override @@ -50,7 +50,7 @@ public UUID receiver() { } @Override - public void addDisaggregates(UUID model, FlexOptions flexOptions) { + public void addDisaggregated(UUID model, FlexOptions flexOptions) { disaggregated.put(model, flexOptions); } } 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 4f383237..f957ed3f 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -172,35 +172,13 @@ protected void sendFlexOptionsToExt( ExtOutputContainer container = new ExtOutputContainer(tick); extEmDataConnection .requestEmFlexResults(tick, extEmDataConnection.getControlledEms(), disaggregated) - .forEach(container::addResult); + .forEach((r, d) -> d.forEach(option -> container.addEmData(r, option))); log.debug("Received results from SIMONA!"); queueToExt.queueData(container); log.debug("Sent results to {}", extSimulatorName); } - /** - * Function to send em set point data to SIMONA using the given {@link ExtEmDataConnection}. This - * method will take a value from the {@link #queueToSimona}. - * - *

{@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 - * @throws InterruptedException if the fetching of data is interrupted - */ - protected void sendEmSetPointsToSimona( - ExtEmDataConnection extEmDataConnection, long tick, Optional maybeNextTick, Logger log) - throws InterruptedException { - checkTick(tick); - Map inputData = queueToSimona.takeData(ExtInputContainer::extractSetPoints); - - sendEmSetPointsToSimona(extEmDataConnection, tick, inputData, maybeNextTick, log); - } - /** * Function to send em set point data to SIMONA using the given {@link ExtEmDataConnection}. This * method will take a value from the {@link #queueToSimona}.