diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f2f8d9..57eaf38 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/ExtDataContainerQueue.java b/src/main/java/edu/ie3/simona/api/data/ExtDataContainerQueue.java index cbc586c..2716817 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. * 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 631a1c3..c2af300 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/ExtEmDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtEmDataConnection.java index 024bee4..6b021ae 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 23dab26..6855267 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/container/ExtInputContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java index 779cf2d..0ef0220 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 c6ee88c..fd169ab 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 + + '}'; + } } 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 e57b6ef..243ac60 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 d4f7b76..77a4675 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 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 83bb2ec..b9f05e9 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; @@ -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, @@ -54,6 +57,16 @@ public GeneralFlexOptions( etaCharge, etaDischarge, tickToEnergyLimits, - Collections.emptyMap()); + new HashMap<>()); + } + + @Override + public UUID receiver() { + return receiver; + } + + @Override + 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 4c72c35..4afc7bb 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; @@ -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, new HashMap<>()); + } + + @Override + public UUID receiver() { + return receiver; + } + + @Override + public void addDisaggregated(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 a25b688..634e961 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,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 +220,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 +268,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 { 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 cb96f68..62184e8 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 @@ -8,8 +8,8 @@ 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 +17,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 4985243..6e636c7 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 5b3694f..c25b25a 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 330da4b..0000000 --- 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 47d41f9..0000000 --- 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/ontology/results/ProvideResultEntities.java b/src/main/java/edu/ie3/simona/api/ontology/results/ProvideResultEntities.java index 23881fd..d72ecfd 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 @@ -19,4 +19,8 @@ public record ProvideResultEntities(Map> results) public ProvideResultEntities(List resultEntities) { this(resultEntities.stream().collect(Collectors.groupingBy(ResultEntity::getInputModel))); } + + public ProvideResultEntities(ResultEntity 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 0f34d11..f957ed3 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -108,8 +108,39 @@ 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)); + } + } + // 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 ExtPrimaryData * @@ -133,6 +164,40 @@ 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!"); + + ExtOutputContainer container = new ExtOutputContainer(tick); + extEmDataConnection + .requestEmFlexResults(tick, extEmDataConnection.getControlledEms(), disaggregated) + .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 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 +205,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 +223,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 f29a447..0e52543 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 281e6bb..b813e87 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 02309a0..a5c40d4 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 5cf6db8..e3cae0c 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 89a77f6..bc93fe1 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 24bac43..ab8cf41 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()