From 73b9909e2a0dd5a0189ebf94fb93163b0f936bd0 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 25 Jun 2025 13:26:50 +0200 Subject: [PATCH 1/9] Added support for external em communication --- CHANGELOG.md | 3 + .../data/connection/ExtEmDataConnection.java | 70 ++++++++- .../connection/ExtPrimaryDataConnection.java | 6 +- .../api/data/container/ExtInputContainer.java | 4 + .../data/container/ExtResultContainer.java | 66 --------- .../api/data/model/em/EmMessageBase.java | 66 +++++++++ .../simona/api/data/model/em/EmSetPoint.java | 51 ++++++- .../api/data/model/em/EmSetPointResult.java | 67 +++++++++ .../model/em/ExtendedFlexOptionsResult.java | 129 ++++++++++++++++ .../api/data/model/em/FlexOptionRequest.java | 75 +++++++++- .../model/em/FlexOptionRequestResult.java | 53 +++++++ .../simona/api/data/model/em/FlexOptions.java | 121 +++++++++++++-- .../edu/ie3/simona/api/mapping/DataType.java | 2 + .../simona/api/mapping/ExtEntityMapping.java | 106 ++++++++++++++ .../simona/api/ontology/em/EmCompletion.java | 16 ++ .../ontology/em/EmSetPointDataResponse.java | 15 ++ .../api/ontology/em/FlexOptionsResponse.java | 15 ++ .../api/ontology/em/FlexRequestResponse.java | 15 ++ .../ontology/em/ProvideEmFlexOptionData.java | 18 +++ .../ontology/em/ProvideFlexRequestData.java | 17 +++ .../api/ontology/em/RequestEmCompletion.java | 14 ++ .../api/ontology/em/RequestEmFlexResults.java | 14 ++ .../api/simulation/ExtCoSimulation.java | 13 +- .../simulation/mapping/ExtEntityMapping.java | 47 ------ .../mapping/ExtEntityMappingSource.java | 1 + .../connection/ExtEmDataConnectionTest.groovy | 138 +++++++++++++++++- .../container/ExtResultContainerTest.groovy | 62 -------- .../mapping/ExtEntityMappingTest.groovy | 4 +- .../test/common/DataServiceTestData.groovy | 7 +- 29 files changed, 989 insertions(+), 226 deletions(-) create mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/EmMessageBase.java create mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java create mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java create mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequestResult.java create mode 100644 src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/EmCompletion.java create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/FlexOptionsResponse.java create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/FlexRequestResponse.java create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.java create mode 100644 src/main/java/edu/ie3/simona/api/ontology/em/RequestEmFlexResults.java delete mode 100644 src/main/java/edu/ie3/simona/api/simulation/mapping/ExtEntityMapping.java rename src/test/groovy/edu/ie3/simona/api/{simulation => }/mapping/ExtEntityMappingTest.groovy (93%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52e41c82..5ebe65ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased/Snapshot] +### Added +- Added support for external em communication [#304](https://github.com/ie3-institute/simonaAPI/issues/304) + ### 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) 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 ba5d3fe9..43fff5e9 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 @@ -7,9 +7,10 @@ package edu.ie3.simona.api.data.connection; 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 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.ontology.em.*; import java.util.*; import org.slf4j.Logger; @@ -34,11 +35,47 @@ 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)); + } + } + /** * Sends the em set points to SIMONA. * * @param tick current tick - * @param setPoints to be sent + * @param setPoints receiver to set point, that should be sent to SIMONA * @param maybeNextTick option for the next tick in the simulation * @param log logger */ @@ -52,6 +89,31 @@ public void sendSetPoints( } } + /** + * 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 FlexOptionsResponse} message + * @throws InterruptedException - on interruptions + */ + public Map requestEmFlexResults( + long tick, List emEntities, boolean disaggregated) throws InterruptedException { + sendExtMsg(new RequestEmFlexResults(tick, emEntities, disaggregated)); + return receiveWithType(FlexOptionsResponse.class).receiverToFlexOptions(); + } + + /** + * Method to request the completion of the em service in SIMONA for the given tick. + * + * @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)); + return receiveWithType(EmCompletion.class).maybeNextTick(); + } + /** Mode of the em connection */ public enum EmMode { BASE, diff --git a/src/main/java/edu/ie3/simona/api/data/connection/ExtPrimaryDataConnection.java b/src/main/java/edu/ie3/simona/api/data/connection/ExtPrimaryDataConnection.java index e75a978f..23f4425f 100644 --- a/src/main/java/edu/ie3/simona/api/data/connection/ExtPrimaryDataConnection.java +++ b/src/main/java/edu/ie3/simona/api/data/connection/ExtPrimaryDataConnection.java @@ -19,9 +19,9 @@ public final class ExtPrimaryDataConnection extends ExtInputDataConnection { - private final Map> valueClasses; + private final Map> valueClasses; - public ExtPrimaryDataConnection(Map> valueClasses) { + public ExtPrimaryDataConnection(Map> valueClasses) { this.valueClasses = valueClasses; } @@ -34,7 +34,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/data/container/ExtInputContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtInputContainer.java index c58f8221..1f8f8d26 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 @@ -92,6 +92,10 @@ 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. * 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..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 @@ -6,20 +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 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 +94,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!"); - } } 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 new file mode 100644 index 00000000..d8156d7b --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmMessageBase.java @@ -0,0 +1,66 @@ +/* + * © 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 1093dda1..0c631db0 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 @@ -11,42 +11,77 @@ 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 class EmSetPoint extends EmMessageBase { + + /** An option for the em set point. */ public final Optional power; + /** + * Constructor for {@link EmSetPoint}. + * + *

Note: Using this constructor will signal SIMONA, that the current set point should be kept. + * + * @param receiver of the set point. + */ public EmSetPoint(UUID receiver) { - this.receiver = receiver; + super(receiver); this.power = Optional.empty(); } + /** + * Constructor for {@link EmSetPoint}. + * + * @param receiver of the set point. + * @param p power value of the set point + */ public EmSetPoint(UUID receiver, ComparableQuantity p) { - this.receiver = receiver; + super(receiver); this.power = Optional.of(new PValue(p)); } + /** + * Constructor for {@link EmSetPoint}. + * + * @param receiver of the set point. + * @param power value of the set point + */ public EmSetPoint(UUID receiver, PValue power) { - this.receiver = receiver; + super(receiver); this.power = Optional.of(power); } + /** + * Constructor for {@link EmSetPoint}. + * + * @param receiver of the set point. + * @param power value of 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(receiver, that.receiver) && Objects.equals(power, that.power); + return Objects.equals(power, that.power); } @Override public int hashCode() { - return Objects.hash(receiver, power); + return Objects.hash(super.hashCode(), power); } @Override public String toString() { - return "EmSetPoint{" + "receiver=" + receiver + ", power=" + power + '}'; + return "EmSetPoint{" + "receiver=" + receiver + ", power=" + power + ", delay=" + delay + '}'; } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java new file mode 100644 index 00000000..2765f145 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java @@ -0,0 +1,67 @@ +/* + * © 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 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. */ +public final class EmSetPointResult extends ResultEntity { + + private final Map receiverToSetPoints; + + /** + * Basic constructor of an em set point result. + * + * @param time date and time when the result is produced + * @param sender uuid of the sending model + * @param receiverToSetPoints map: uuid to set point + */ + public EmSetPointResult(ZonedDateTime time, UUID sender, Map receiverToSetPoints) { + super(time, sender); + this.receiverToSetPoints = receiverToSetPoints; + } + + /** Returns the sender of the results. */ + public UUID getSender() { + return getInputModel(); + } + + /** Returns the mapped (receiver to set point) set point. */ + 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{" + + "time=" + + getTime() + + ", sender=" + + getInputModel() + + ", receiverToSetPoints=" + + receiverToSetPoints + + '}'; + } +} 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 new file mode 100644 index 00000000..cca28752 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResult.java @@ -0,0 +1,129 @@ +/* + * © 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.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; +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 { + + /** The receiver of the message. */ + private final UUID receiver; + + /** The disaggregated flex option results. */ + 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 = new HashMap<>(); + } + + /** + * 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; + } + + /** + * Method for adding partial flex options. + * + * @param uuid of the model, that provides the flex options + * @param flexOptionsResult the flex option of the model + */ + 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(); + } + + /** Returns the uuid of the receiver. */ + public UUID getReceiver() { + return receiver; + } + + /** Returns {@code true}, if disaggregated flex option are available. */ + public boolean hasDisaggregated() { + return !disaggregated.isEmpty(); + } + + /** + * Returns a map: uuid to disaggregated flex options. + * + *

Note: If no disaggregated flex options are present (see: {@link #hasDisaggregated()}), the + * map will be empty. + */ + 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/model/em/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java index 492838d6..09633fd0 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,13 +6,74 @@ 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; -/** - * Flex option request that will be sent to SIMONA. - * - * @param receiver uuid of the agent, that will receive the request - * @param sender option for the uuid of the agent, that sent the request - */ -public record FlexOptionRequest(UUID receiver, Optional sender) {} +/** 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; + + /** + * Constructor for {@link FlexOptionRequest}. Equals {@code new FlexOptionRequest(receiver, + * Optional.empty())}. + * + * @param receiver of the request + */ + public FlexOptionRequest(UUID receiver) { + this(receiver, Optional.empty()); + } + + /** + * 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, 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 + + '}'; + } +} 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 new file mode 100644 index 00000000..077163da --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequestResult.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.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; + +/** Em flex request result. */ +public final class FlexOptionRequestResult extends ResultEntity { + + /** The uuids of the receivers. */ + private final List receivers; + + /** + * Constructor of a {@link FlexOptionRequest}. + * + * @param time date and time when the result is produced + * @param inputModel uuid of the input model that produces the result + * @param receivers a collection of receivers + */ + public FlexOptionRequestResult(ZonedDateTime time, UUID inputModel, Collection receivers) { + super(time, inputModel); + this.receivers = new ArrayList<>(receivers); + } + + /** + * Returns the list of the uuids of all receivers, that should receive a request to provide flex + * options. + */ + 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/model/em/FlexOptions.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptions.java index c10b6481..b8e6d358 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,22 +6,113 @@ 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 pMin minimal active power - * @param pRef current active power - * @param pMax maximal active power - */ -public record FlexOptions( - UUID receiver, - UUID sender, - ComparableQuantity pMin, - ComparableQuantity pRef, - ComparableQuantity pMax) {} +/** 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 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 + + '}'; + } +} 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 ea6d2d4a..45f1cbbd 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/DataType.java +++ b/src/main/java/edu/ie3/simona/api/mapping/DataType.java @@ -11,6 +11,7 @@ public enum DataType { EXT_PRIMARY_INPUT("primary_input"), EXT_EM_INPUT("em_input"), + EXT_EM_COMMUNICATION("em_communication"), EXT_GRID_RESULT("grid_result"), EXT_PARTICIPANT_RESULT("participant_result"), EXT_FLEX_OPTIONS_RESULT("flex_options_result"); @@ -25,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; diff --git a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java new file mode 100644 index 00000000..29a5f727 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java @@ -0,0 +1,106 @@ +/* + * © 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.mapping; + +import edu.ie3.simona.api.simulation.mapping.ExtEntityEntry; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +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 final Map> extEntities; + + public ExtEntityMapping(List extEntityEntryList) { + this.extEntities = + 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 getEntries(DataType dataType) { + return extEntities.getOrDefault(dataType, Collections.emptyList()); + } + + /** + * 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)); + } + + /** + * Returns the full mapping SIMONA uuid to external id. Equals {@code + * getExtUuid2IdMapping(DataType.values())}. + */ + public Map getExtUuid2IdMapping() { + return extEntities.values().stream() + .flatMap(Collection::stream) + .collect(Collectors.toMap(ExtEntityEntry::uuid, ExtEntityEntry::id)); + } + + /** + * 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 external id to SIMONA uuid. + * + * @param dataTypes the external asset expects + * @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)); + } + + /** + * 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)); + } + + /** + * Mapping SIMONA uuid to external id. + * + * @param dataTypes data types the external asset expects + * @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)); + } +} 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 new file mode 100644 index 00000000..12bc1709 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/EmCompletion.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.ontology.em; + +import java.util.Optional; + +/** + * Response send from SIMONA after the em service is finished. + * + * @param maybeNextTick option for the next tick in SIMONA + */ +public record EmCompletion(Optional maybeNextTick) 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 new file mode 100644 index 00000000..c7a6c6e5 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/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.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/FlexOptionsResponse.java b/src/main/java/edu/ie3/simona/api/ontology/em/FlexOptionsResponse.java new file mode 100644 index 00000000..49852430 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/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.ontology.em; + +import edu.ie3.simona.api.data.model.em.ExtendedFlexOptionsResult; +import java.util.Map; +import java.util.UUID; + +/** Message that provides em data (flexibility options) to an external simulation. */ +public record FlexOptionsResponse(Map receiverToFlexOptions) + 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 new file mode 100644 index 00000000..a2739e0e --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/FlexRequestResponse.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.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 new file mode 100644 index 00000000..3d8d0e53 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java @@ -0,0 +1,18 @@ +/* + * © 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 new file mode 100644 index 00000000..4013e748 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.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.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 new file mode 100644 index 00000000..fc6f5b18 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/RequestEmCompletion.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.ontology.em; + +/** + * Request send to SIMONA to finish the em service. + * + * @param tick for which the em service should be finished + */ +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 new file mode 100644 index 00000000..47d41f92 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/ontology/em/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.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 445c0e9a..4291ec4d 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -19,10 +19,7 @@ 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.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import org.slf4j.Logger; /** @@ -59,7 +56,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."); @@ -120,6 +117,8 @@ public static ExtResultDataConnection buildResultConnection( } } + // primary data methods + /** * Function to send primary data to SIMONA using ExtPrimaryData * @@ -141,6 +140,8 @@ protected void sendPrimaryDataToSimona( log.debug("Provided Primary Data to SIMONA!"); } + // energy management data methods + /** * 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. @@ -162,6 +163,8 @@ protected void sendEmSetPointsToSimona( log.debug("Provided em set points to SIMONA!"); } + // result data methods + /** * Function to get result data from SIMONA using the available {@link ExtResultDataConnection} * 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..db03893d 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,7 @@ 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; 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 b9e9251a..4a26a52b 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 @@ -1,15 +1,19 @@ 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.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.ontology.DataMessageFromExt import edu.ie3.simona.api.ontology.ScheduleDataServiceMessage -import edu.ie3.simona.api.ontology.em.ProvideEmSetPointData +import edu.ie3.simona.api.ontology.em.* 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 +import java.time.ZonedDateTime + class ExtEmDataConnectionTest extends Specification implements DataServiceTestData { @Shared @@ -27,7 +31,45 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa testKit = null } - def "ExtEmDataConnection should provide em data correctly"() { + def "ExtEmDataConnection should provide em flex requests 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 FlexOptionRequest(inputUuid)) + + when: + extEmDataConnection.sendFlexRequests(0L, emData, Optional.of(900L), log) + + then: + dataService.expectMessage(new ProvideFlexRequestData(0, emData, Optional.of(900L))) + 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() + ) + def inputDataMap = [:] as Map + + when: + extEmDataConnection.sendFlexRequests(0L, inputDataMap, Optional.of(900L), log) + + then: + dataService.expectNoMessage() + } + + def "ExtEmDataConnection should provide em flex options correctly"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) def extSimAdapter = testKit.createTestProbe(ScheduleDataServiceMessage) @@ -37,16 +79,34 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa extSimAdapter.ref() ) - def emData = Map.of(inputUuid, new EmSetPoint(inputUuid, pValue)) + def emData = Map.of(inputUuid, [new FlexOptions(inputUuid, UUID.randomUUID(), power, power, power)]) when: - extEmDataConnection.sendSetPoints(0L, emData, Optional.of(900L), log) + extEmDataConnection.sendFlexOptions(0L, emData, Optional.of(900L), log) then: - dataService.expectMessage(new ProvideEmSetPointData(0, emData, Optional.of(900L))) + dataService.expectMessage(new ProvideEmFlexOptionData(0, emData, Optional.of(900L))) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) } + def "ExtEmDataConnection should send no message, if no flex options 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 + + when: + extEmDataConnection.sendFlexRequests(0L, inputDataMap, Optional.of(900L), log) + + then: + dataService.expectNoMessage() + } + def "ExtEmDataConnection should send no message, if input data is empty"() { given: def dataService = testKit.createTestProbe(DataMessageFromExt) @@ -65,4 +125,70 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa 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 + + when: + extEmDataConnection.sendSetPoints(0L, inputDataMap, Optional.of(900L), log) + + then: + dataService.expectNoMessage() + } + + def "ExtEmDataConnection should request and receive flex options 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 sendMsg = new FlexOptionsResponse([(inputUuid): new ExtendedFlexOptionsResult(ZonedDateTime.now(), inputUuid, UUID.randomUUID(), power, power, power)]) + + when: + // we need to queue the msg beforehand because the receive method is blocking + extEmDataConnection.queueExtResponseMsg(sendMsg) + + def response = extEmDataConnection.requestEmFlexResults(0L, [inputUuid], false) + + then: + dataService.expectMessage(new RequestEmFlexResults(0L, [inputUuid], false)) + extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) + response == sendMsg.receiverToFlexOptions() + } + + def "ExtEmDataConnection should request and receive flex completion 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 sendMsg = new EmCompletion(Optional.of(900L)) + + when: + // we need to queue the msg beforehand because the receive method is blocking + extEmDataConnection.queueExtResponseMsg(sendMsg) + + def response = extEmDataConnection.requestCompletion(0L) + + then: + dataService.expectMessage(new RequestEmCompletion(0L)) + extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) + response == sendMsg.maybeNextTick() + } + } 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 diff --git a/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingTest.groovy b/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy similarity index 93% rename from src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingTest.groovy rename to src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy index dea3928e..dcae9e3e 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/mapping/ExtEntityMappingTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy @@ -1,7 +1,7 @@ -package edu.ie3.simona.api.simulation.mapping +package edu.ie3.simona.api.mapping import edu.ie3.datamodel.io.naming.timeseries.ColumnScheme -import edu.ie3.simona.api.mapping.DataType +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/test/common/DataServiceTestData.groovy b/src/test/groovy/edu/ie3/simona/api/test/common/DataServiceTestData.groovy index 88a7af56..748b95ef 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 @@ -5,15 +5,20 @@ import edu.ie3.datamodel.models.result.system.LoadResult import edu.ie3.datamodel.models.value.PValue import org.slf4j.Logger import org.slf4j.LoggerFactory +import tech.units.indriya.ComparableQuantity import tech.units.indriya.quantity.Quantities +import javax.measure.quantity.Power import java.time.ZonedDateTime trait DataServiceTestData { Logger log = LoggerFactory.getLogger(DataServiceTestData) UUID inputUuid = UUID.fromString("22bea5fc-2cb2-4c61-beb9-b476e0107f52") - PValue pValue = new PValue(Quantities.getQuantity(500.0, StandardUnits.ACTIVE_POWER_IN)) + + ComparableQuantity power = Quantities.getQuantity(500.0, StandardUnits.ACTIVE_POWER_IN) + + PValue pValue = new PValue(power) LoadResult loadResult = new LoadResult( ZonedDateTime.parse("2020-01-30T17:26:44Z[UTC]"), From 1792fb32191e15280ced94d107fc517358c4c068 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Wed, 25 Jun 2025 13:29:19 +0200 Subject: [PATCH 2/9] fmt --- src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java | 2 -- 1 file changed, 2 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 29a5f727..301dd994 100644 --- a/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java +++ b/src/main/java/edu/ie3/simona/api/mapping/ExtEntityMapping.java @@ -10,8 +10,6 @@ import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; -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 { From 038faa1e0f68b8013c140aec58fc52551ddc569d Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 26 Jun 2025 11:20:15 +0200 Subject: [PATCH 3/9] Increasing test coverage. --- .../model/em/ExtendedFlexOptionsResult.java | 10 -- .../api/data/model/em/FlexOptionRequest.java | 11 ++ .../model/em/FlexOptionRequestResult.java | 11 +- .../data/model/em/EmSetPointResultTest.groovy | 52 ++++++++ .../api/data/model/em/EmSetPointTest.groovy | 67 ++++++++++ .../em/ExtendedFlexOptionsResultTest.groovy | 89 +++++++++++++ .../em/FlexOptionRequestResultTest.groovy | 30 +++++ .../model/em/FlexOptionRequestTest.groovy | 63 ++++++++++ .../api/data/model/em/FlexOptionsTest.groovy | 59 +++++++++ .../api/mapping/ExtEntityMappingTest.groovy | 119 ++++++++++++++++-- 10 files changed, 491 insertions(+), 20 deletions(-) create mode 100644 src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointResultTest.groovy create mode 100644 src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy create mode 100644 src/test/groovy/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResultTest.groovy create mode 100644 src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestResultTest.groovy create mode 100644 src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy create mode 100644 src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionsTest.groovy 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 cca28752..f2db2de8 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 @@ -72,16 +72,6 @@ public ExtendedFlexOptionsResult( this.disaggregated = disaggregated; } - /** - * Method for adding partial flex options. - * - * @param uuid of the model, that provides the flex options - * @param flexOptionsResult the flex option of the model - */ - 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/FlexOptionRequest.java b/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequest.java index 09633fd0..29bffb31 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 @@ -28,6 +28,17 @@ public FlexOptionRequest(UUID receiver) { this(receiver, Optional.empty()); } + /** + * Constructor for {@link FlexOptionRequest}. + * + * @param receiver of the request + * @param sender of the request + */ + public FlexOptionRequest(UUID receiver, UUID sender) { + super(receiver); + this.sender = Optional.ofNullable(sender); + } + /** * Constructor for {@link FlexOptionRequest}. * 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 077163da..3e49cf20 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 @@ -23,14 +23,19 @@ public final class FlexOptionRequestResult extends ResultEntity { * Constructor of a {@link FlexOptionRequest}. * * @param time date and time when the result is produced - * @param inputModel uuid of the input model that produces the result + * @param sender uuid of the input model that produces the result * @param receivers a collection of receivers */ - public FlexOptionRequestResult(ZonedDateTime time, UUID inputModel, Collection receivers) { - super(time, inputModel); + public FlexOptionRequestResult(ZonedDateTime time, UUID sender, Collection receivers) { + super(time, sender); this.receivers = new ArrayList<>(receivers); } + /** Returns the uuid of the sender. */ + public UUID getSender() { + return getInputModel(); + } + /** * Returns the list of the uuids of all receivers, that should receive a request to provide flex * options. diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointResultTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointResultTest.groovy new file mode 100644 index 00000000..c760ad04 --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointResultTest.groovy @@ -0,0 +1,52 @@ +package edu.ie3.simona.api.data.model.em + +import edu.ie3.datamodel.models.value.PValue +import edu.ie3.util.quantities.PowerSystemUnits +import spock.lang.Shared +import spock.lang.Specification +import tech.units.indriya.ComparableQuantity +import tech.units.indriya.quantity.Quantities + +import javax.measure.quantity.Power +import java.time.ZonedDateTime + +class EmSetPointResultTest extends Specification { + + @Shared + ZonedDateTime time = ZonedDateTime.now() + + @Shared + UUID senderUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + + @Shared + ComparableQuantity power = Quantities.getQuantity(10, PowerSystemUnits.KILOWATT) + + + def "An EmSetPoint can be constructed without set points correctly"() { + when: + def setPoint = new EmSetPointResult(time, senderUuid, [:]) + + then: + setPoint.time == time + setPoint.inputModel == senderUuid + setPoint.sender == senderUuid + setPoint.receiverToSetPoint == [:] + } + + def "An EmSetPoint can be constructed with set points correctly"() { + given: + def receiverUuid = UUID.fromString("81c7c8de-0f01-4559-97bb-844259e467b5") + + def setPoints = [(receiverUuid): new PValue(power)] + + when: + def setPoint = new EmSetPointResult(time, senderUuid, setPoints) + + then: + setPoint.time == time + setPoint.inputModel == senderUuid + setPoint.sender == senderUuid + setPoint.receiverToSetPoint == setPoints + } + +} diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy new file mode 100644 index 00000000..8192ccd3 --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy @@ -0,0 +1,67 @@ +package edu.ie3.simona.api.data.model.em + +import edu.ie3.datamodel.models.value.PValue +import edu.ie3.util.quantities.PowerSystemUnits +import spock.lang.Shared +import spock.lang.Specification +import tech.units.indriya.ComparableQuantity +import tech.units.indriya.quantity.Quantities + +import javax.measure.quantity.Power + +class EmSetPointTest extends Specification { + + @Shared + UUID receiverUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + + @Shared + ComparableQuantity power = Quantities.getQuantity(10, PowerSystemUnits.KILOWATT) + + + def "An empty EmSetPoint can be constructed correctly"() { + when: + def setPoint = new EmSetPoint(receiverUuid) + + then: + setPoint.receiver == receiverUuid + setPoint.power == Optional.empty() + setPoint.delay == Optional.empty() + !setPoint.hasDelay() + } + + def "An EmSetPoint can be constructed without delay correctly"() { + given: + def pValue = new PValue(power) + + when: + def setPoint1 = new EmSetPoint(receiverUuid, power) + def setPoint2 = new EmSetPoint(receiverUuid, pValue) + + then: + setPoint1.receiver == receiverUuid + setPoint1.power == Optional.of(pValue) + setPoint1.delay == Optional.empty() + !setPoint1.hasDelay() + + setPoint2.receiver == receiverUuid + setPoint2.power == Optional.of(pValue) + setPoint2.delay == Optional.empty() + !setPoint2.hasDelay() + } + + def "An EmSetPoint can be constructed with delay correctly"() { + given: + def pValue = new PValue(power) + def delay = Quantities.getQuantity(10, PowerSystemUnits.MILLISECOND) + + when: + def setPoint = new EmSetPoint(receiverUuid, Optional.of(pValue), Optional.of(delay)) + + then: + setPoint.receiver == receiverUuid + setPoint.power == Optional.of(pValue) + setPoint.delay == Optional.of(delay) + setPoint.hasDelay() + } + +} 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 new file mode 100644 index 00000000..7acaba94 --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/ExtendedFlexOptionsResultTest.groovy @@ -0,0 +1,89 @@ +package edu.ie3.simona.api.data.model.em + +import edu.ie3.datamodel.models.result.system.FlexOptionsResult +import edu.ie3.util.quantities.PowerSystemUnits +import spock.lang.Shared +import spock.lang.Specification +import tech.units.indriya.ComparableQuantity +import tech.units.indriya.quantity.Quantities + +import javax.measure.quantity.Power +import java.time.ZonedDateTime + +class ExtendedFlexOptionsResultTest extends Specification { + + @Shared + ZonedDateTime time = ZonedDateTime.now() + + @Shared + UUID receiverUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + + @Shared + UUID senderUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + + @Shared + ComparableQuantity pRef = Quantities.getQuantity(7, PowerSystemUnits.KILOWATT) + + @Shared + ComparableQuantity pMin = Quantities.getQuantity(0, PowerSystemUnits.KILOWATT) + + @Shared + ComparableQuantity pMax = Quantities.getQuantity(10, PowerSystemUnits.KILOWATT) + + + def "The ExtendedFlexOptionsResult can be constructed without disaggregated flex options"() { + when: + def result = new ExtendedFlexOptionsResult(time, senderUuid, receiverUuid, pRef, pMin, pMax, [:]) + + then: + result.time == time + result.inputModel == senderUuid + result.sender == senderUuid + result.receiver == receiverUuid + result.pRef == pRef + result.pMin == pMin + result.pMax == pMax + result.disaggregated == [:] + } + + def "The ExtendedFlexOptionsResult can be constructed with disaggregated flex options"() { + given: + def dis1 = UUID.fromString("a246eee3-405c-4af1-9ad2-69ecad2bfb65") + def dis2 = UUID.fromString("78676121-f154-4f70-ad50-4384ddf8deed") + + def disaggregated = [ + (dis1): new FlexOptionsResult(time, dis1, pRef, pMin, pMax), + (dis2): new FlexOptionsResult(time, dis2, pMin, pMin, pMin) + ] + + when: + def result = new ExtendedFlexOptionsResult(time, senderUuid, receiverUuid, pRef, pMin, pMax, disaggregated) + + then: + result.time == time + result.inputModel == senderUuid + result.sender == senderUuid + result.receiver == receiverUuid + result.pRef == pRef + result.pMin == pMin + result.pMax == pMax + result.disaggregated == disaggregated + } + + def "The ExtendedFlexOptionsResult should specify if there are disaggregated flex options correctly"() { + when: + def result = new ExtendedFlexOptionsResult(time, senderUuid, receiverUuid, pRef, pMin, pMax, diagregatedMap) + + then: + result.hasDisaggregated() == expectedResult + + where: + diagregatedMap | expectedResult + [:] as Map | false + [ + (UUID.fromString("a246eee3-405c-4af1-9ad2-69ecad2bfb65")): new FlexOptionsResult(time, UUID.fromString("a246eee3-405c-4af1-9ad2-69ecad2bfb65"), pRef, pMin, pMax), + (UUID.fromString("78676121-f154-4f70-ad50-4384ddf8deed")): new FlexOptionsResult(time, UUID.fromString("78676121-f154-4f70-ad50-4384ddf8deed"), pMin, pMin, pMin) + ] | true + } + +} diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestResultTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestResultTest.groovy new file mode 100644 index 00000000..a232cfe7 --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestResultTest.groovy @@ -0,0 +1,30 @@ +package edu.ie3.simona.api.data.model.em + +import spock.lang.Shared +import spock.lang.Specification + +import java.time.ZonedDateTime + +class FlexOptionRequestResultTest extends Specification { + + @Shared + ZonedDateTime time = ZonedDateTime.now() + + @Shared + UUID receiverUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + + @Shared + UUID senderUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + + def "An FlexOptionRequestResult can be constructed correctly"() { + when: + def result = new FlexOptionRequestResult(time, senderUuid, [receiverUuid]) + + then: + result.time == time + result.inputModel == senderUuid + result.sender == senderUuid + result.receivers == [receiverUuid] + } + +} diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy new file mode 100644 index 00000000..68689b8a --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy @@ -0,0 +1,63 @@ +package edu.ie3.simona.api.data.model.em + +import edu.ie3.util.quantities.PowerSystemUnits +import spock.lang.Shared +import spock.lang.Specification +import tech.units.indriya.quantity.Quantities + +class FlexOptionRequestTest extends Specification { + + @Shared + UUID receiverUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + + @Shared + UUID senderUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + + def "The FlexOptionRequest can be constructed without sender and delay correctly"() { + when: + def request = new FlexOptionRequest(receiverUuid) + + then: + request.receiver == receiverUuid + request.sender == Optional.empty() + request.delay == Optional.empty() + !request.hasDelay() + } + + def "The FlexOptionRequest can be constructed with sender and without delay correctly"() { + when: + def request = new FlexOptionRequest(receiverUuid, senderUuid) + + then: + request.receiver == receiverUuid + request.sender == Optional.of(senderUuid) + request.delay == Optional.empty() + !request.hasDelay() + } + + def "The FlexOptionRequest can be constructed with sender as optional and without delay correctly"() { + when: + def request = new FlexOptionRequest(receiverUuid, Optional.of(senderUuid)) + + then: + request.receiver == receiverUuid + request.sender == Optional.of(senderUuid) + request.delay == Optional.empty() + !request.hasDelay() + } + + def "The FlexOptionRequest can be constructed with sender and delay correctly"() { + given: + def delay = Quantities.getQuantity(10, PowerSystemUnits.MILLISECOND) + + when: + def request = new FlexOptionRequest(receiverUuid, Optional.of(senderUuid), Optional.of(delay)) + + then: + request.receiver == receiverUuid + request.sender == Optional.of(senderUuid) + request.delay == Optional.of(delay) + request.hasDelay() + } + +} 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 new file mode 100644 index 00000000..02ee987e --- /dev/null +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionsTest.groovy @@ -0,0 +1,59 @@ +package edu.ie3.simona.api.data.model.em + +import edu.ie3.util.quantities.PowerSystemUnits +import spock.lang.Shared +import spock.lang.Specification +import tech.units.indriya.ComparableQuantity +import tech.units.indriya.quantity.Quantities + +import javax.measure.quantity.Power + +class FlexOptionsTest extends Specification { + + @Shared + UUID receiverUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + + @Shared + UUID senderUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + + @Shared + ComparableQuantity pRef = Quantities.getQuantity(7, PowerSystemUnits.KILOWATT) + + @Shared + ComparableQuantity pMin = Quantities.getQuantity(0, PowerSystemUnits.KILOWATT) + + @Shared + ComparableQuantity pMax = Quantities.getQuantity(10, PowerSystemUnits.KILOWATT) + + def "FlexOptions can be constructed without delay correctly"() { + when: + def flexOptions = new FlexOptions(receiverUuid, senderUuid, pRef, pMin, pMax) + + then: + flexOptions.receiver == receiverUuid + flexOptions.sender == senderUuid + flexOptions.pRef == pRef + flexOptions.pMin == pMin + flexOptions.pMax == pMax + flexOptions.delay == Optional.empty() + !flexOptions.hasDelay() + } + + def "FlexOptions can be constructed with delay correctly"() { + given: + def delay = Quantities.getQuantity(10, PowerSystemUnits.MILLISECOND) + + when: + def flexOptions = new FlexOptions(receiverUuid, senderUuid, pRef, pMin, pMax, Optional.of(delay)) + + then: + flexOptions.receiver == receiverUuid + flexOptions.sender == senderUuid + flexOptions.pRef == pRef + flexOptions.pMin == pMin + flexOptions.pMax == pMax + flexOptions.delay == Optional.of(delay) + flexOptions.hasDelay() + } + +} 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 dcae9e3e..c4b4f3bc 100644 --- a/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/mapping/ExtEntityMappingTest.groovy @@ -9,25 +9,87 @@ class ExtEntityMappingTest extends Specification { @Shared UUID loadUuid = UUID.fromString("22bea5fc-2cb2-4c61-beb9-b476e0107f52") + @Shared + UUID pvUuid = UUID.fromString("12f5e864-2464-4e43-9a38-5753a439d45f") + + @Shared + UUID emUuid = UUID.fromString("60dbc7e4-9718-4bbd-913a-dd26925e68a3") + @Shared ExtEntityEntry extResultEntry = new ExtEntityEntry( loadUuid, "Load", - ColumnScheme.parse("p"), + Optional.empty(), DataType.EXT_PARTICIPANT_RESULT ) @Shared ExtEntityEntry extInputEntry = new ExtEntityEntry( - loadUuid, - "Load", + pvUuid, + "PV", ColumnScheme.parse("p"), DataType.EXT_PRIMARY_INPUT ) + @Shared + ExtEntityEntry extEmInputEntry = new ExtEntityEntry( + emUuid, + "Em", + Optional.empty(), + DataType.EXT_EM_INPUT + ) + + def "ExtEntityMapping should return the data types correctly"() { + when: + def extEntryMapping = new ExtEntityMapping(assets) + def types = extEntryMapping.dataTypes + + then: + types == expectedTypes as Set + + where: + assets | expectedTypes + [extResultEntry] | [DataType.EXT_PARTICIPANT_RESULT] + [extInputEntry] | [DataType.EXT_PRIMARY_INPUT] + [extEmInputEntry] | [DataType.EXT_EM_INPUT] + [extResultEntry, extInputEntry] | [DataType.EXT_PARTICIPANT_RESULT, DataType.EXT_PRIMARY_INPUT] + [extInputEntry, extEmInputEntry] | [DataType.EXT_PRIMARY_INPUT, DataType.EXT_EM_INPUT] + [extResultEntry, extInputEntry, extEmInputEntry] | [DataType.EXT_PARTICIPANT_RESULT, DataType.EXT_PRIMARY_INPUT, DataType.EXT_EM_INPUT] + } + + 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, extEmInputEntry] | DataType.EXT_PARTICIPANT_RESULT | [extResultEntry] + [extResultEntry, extInputEntry, extEmInputEntry] | DataType.EXT_PRIMARY_INPUT | [extInputEntry] + [extResultEntry, extInputEntry, extEmInputEntry] | DataType.EXT_EM_INPUT | [extEmInputEntry] + } + + def "ExtEntityMapping should return all SIMONA uuid mapping correctly"() { + given: + def extAssetList = List.of(extResultEntry, extInputEntry, extEmInputEntry) + def extEntryMapping = new ExtEntityMapping(extAssetList) + + when: + def inputMap = extEntryMapping.getExtId2UuidMapping() + + then: + inputMap.size() == 3 + inputMap.get("Load") == loadUuid + inputMap.get("PV") == pvUuid + inputMap.get("Em") == emUuid + } + def "ExtEntityMapping should return SIMONA uuid mapping correctly"() { given: - def extAssetList = List.of(extResultEntry, extInputEntry) + def extAssetList = List.of(extResultEntry, extInputEntry, extEmInputEntry) def extEntryMapping = new ExtEntityMapping(extAssetList) when: @@ -35,12 +97,41 @@ class ExtEntityMappingTest extends Specification { then: inputMap.size() == 1 - inputMap.get("Load") == loadUuid + inputMap.get("PV") == pvUuid + } + + def "ExtEntityMapping should return multiple SIMONA uuid mapping correctly"() { + given: + def extAssetList = List.of(extResultEntry, extInputEntry, extEmInputEntry) + def extEntryMapping = new ExtEntityMapping(extAssetList) + + when: + def inputMap = extEntryMapping.getExtId2UuidMapping(DataType.EXT_PRIMARY_INPUT, DataType.EXT_EM_INPUT) + + then: + inputMap.size() == 2 + inputMap.get("PV") == pvUuid + inputMap.get("Em") == emUuid + } + + def "ExtEntityMapping should return all external id mapping correctly"() { + given: + def extAssetList = List.of(extResultEntry, extInputEntry, extEmInputEntry) + def extEntryMapping = new ExtEntityMapping(extAssetList) + + when: + def inputMap = extEntryMapping.getExtUuid2IdMapping() + + then: + inputMap.size() == 3 + inputMap.get(loadUuid) == "Load" + inputMap.get(pvUuid) == "PV" + inputMap.get(emUuid) == "Em" } def "ExtEntityMapping should return external id mapping correctly"() { given: - def extAssetList = List.of(extResultEntry, extInputEntry) + def extAssetList = List.of(extResultEntry, extInputEntry, extEmInputEntry) def extEntryMapping = new ExtEntityMapping(extAssetList) when: @@ -48,6 +139,20 @@ class ExtEntityMappingTest extends Specification { then: inputMap.size() == 1 - inputMap.get(loadUuid) == "Load" + inputMap.get(pvUuid) == "PV" + } + + def "ExtEntityMapping should return multiple external id mapping correctly"() { + given: + def extAssetList = List.of(extResultEntry, extInputEntry, extEmInputEntry) + def extEntryMapping = new ExtEntityMapping(extAssetList) + + when: + def inputMap = extEntryMapping.getExtUuid2IdMapping(DataType.EXT_PRIMARY_INPUT, DataType.EXT_EM_INPUT) + + then: + inputMap.size() == 2 + inputMap.get(pvUuid) == "PV" + inputMap.get(emUuid) == "Em" } } \ No newline at end of file From 4ab44fd90a350f76d9ab1647aeae0229d4539a86 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 26 Jun 2025 11:34:45 +0200 Subject: [PATCH 4/9] Small improvements to em models. --- .../simona/api/data/model/em/EmSetPoint.java | 2 +- .../api/data/model/em/EmSetPointResult.java | 2 +- .../model/em/ExtendedFlexOptionsResult.java | 19 +++++++++++++++---- .../api/data/model/em/FlexOptionRequest.java | 12 ++++++++++++ .../model/em/FlexOptionRequestResult.java | 18 ++++++++++++++---- .../simona/api/data/model/em/FlexOptions.java | 2 +- 6 files changed, 44 insertions(+), 11 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 0c631db0..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 @@ -58,7 +58,7 @@ public EmSetPoint(UUID receiver, PValue power) { * Constructor for {@link EmSetPoint}. * * @param receiver of the set point. - * @param power value of the set point + * @param power option for the set point * @param delay option for the delay of this message */ public EmSetPoint( diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java index 2765f145..30611343 100644 --- a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java @@ -42,8 +42,8 @@ public Map getReceiverToSetPoint() { @Override public boolean equals(Object o) { + if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; EmSetPointResult that = (EmSetPointResult) o; return Objects.equals(receiverToSetPoints, that.receiverToSetPoints); } 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 f2db2de8..c03aaade 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 @@ -8,10 +8,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 java.util.*; import javax.measure.quantity.Power; import tech.units.indriya.ComparableQuantity; @@ -97,6 +94,20 @@ public Map getDisaggregated() { return Collections.unmodifiableMap(disaggregated); } + @Override + 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); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), receiver, disaggregated); + } + @Override public String toString() { return "ExtendedFlexOptionsResult{" 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 29bffb31..f1b1e307 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 @@ -57,6 +57,18 @@ public FlexOptionRequest(UUID receiver, Optional sender) { * @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); 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 3e49cf20..d0a70687 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 @@ -8,10 +8,7 @@ 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; +import java.util.*; /** Em flex request result. */ public final class FlexOptionRequestResult extends ResultEntity { @@ -44,6 +41,19 @@ public List getReceivers() { return receivers; } + @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); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), receivers); + } + @Override public String toString() { return "FlexRequestResult{" 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 b8e6d358..ce04bfa4 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 @@ -66,7 +66,7 @@ public FlexOptions( * @param pRef current active power * @param pMin minimal active power * @param pMax maximal active power - * @param delay the delay of the message + * @param delay option for the delay of the message */ public FlexOptions( UUID receiver, From 3a7b2133ecf56737e959889ec875888e595775d8 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Thu, 26 Jun 2025 12:52:45 +0200 Subject: [PATCH 5/9] Adding additional methods to `ExtendedFlexOptionsResult`. --- .../model/em/ExtendedFlexOptionsResult.java | 77 +++++++++++++++++++ .../em/ExtendedFlexOptionsResultTest.groovy | 51 ++++++++++++ 2 files changed, 128 insertions(+) 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..af9f4387 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,7 @@ import java.time.ZonedDateTime; import java.util.*; import javax.measure.quantity.Power; +import org.slf4j.Logger; import tech.units.indriya.ComparableQuantity; /** @@ -69,6 +70,19 @@ public ExtendedFlexOptionsResult( this.disaggregated = disaggregated; } + /** + * 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) { + this.disaggregated.put(uuid, flexOptionsResult); + } + /** Returns the uuid of the sender ({@link #getInputModel()}) of the results. */ public UUID getSender() { return getInputModel(); @@ -94,6 +108,69 @@ 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/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 7acaba94..3f359f71 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,6 +2,8 @@ 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 @@ -12,6 +14,9 @@ import java.time.ZonedDateTime class ExtendedFlexOptionsResultTest extends Specification { + @Shared + Logger logger = LoggerFactory.getLogger(ExtendedFlexOptionsResultTest) + @Shared ZonedDateTime time = ZonedDateTime.now() @@ -86,4 +91,50 @@ class ExtendedFlexOptionsResultTest extends Specification { ] | true } + def "The ExtendedFlexOptionsResult should add disaggregated flex options correctly"() { + given: + def result = new ExtendedFlexOptionsResult(time, senderUuid, receiverUuid, pRef, pMin, pMax) + def inferiorUuid1 = UUID.fromString("a246eee3-405c-4af1-9ad2-69ecad2bfb65") + def inferiorUuid2 = UUID.fromString("78676121-f154-4f70-ad50-4384ddf8deed") + + def inferiorOptions1 = new FlexOptionsResult(time, inferiorUuid1, pRef, pMin, pMax) + def inferiorOptions2 = new FlexOptionsResult(time, inferiorUuid2, pMin, pMin, pMin) + + when: + result.addDisaggregated(inferiorUuid1, inferiorOptions1) + result.addDisaggregated(inferiorUuid2, inferiorOptions2) + + then: + result.hasDisaggregated() + result.disaggregated.size() == 2 + 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, receiverUuid, 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 + } } From 10d7a4c40ec51670fbdfc980551ede834096a4d8 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 30 Jun 2025 12:35:33 +0200 Subject: [PATCH 6/9] Adding max delay parameter to em communication. --- .../data/connection/ExtEmDataConnection.java | 19 +++++++++++++++++++ .../api/simulation/ExtCoSimulation.java | 14 ++++++++++++-- .../api/simulation/ExtCoSimulationTest.groovy | 4 ++-- 3 files changed, 33 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 43fff5e9..1bf11433 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 @@ -12,7 +12,9 @@ import edu.ie3.simona.api.data.model.em.FlexOptions; import edu.ie3.simona.api.ontology.em.*; import java.util.*; +import javax.measure.quantity.Time; import org.slf4j.Logger; +import tech.units.indriya.ComparableQuantity; /** Enables data connection of em data between SIMONA and SimonaAPI */ public final class ExtEmDataConnection @@ -23,11 +25,23 @@ 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,11 @@ 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 4291ec4d..4932799b 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -20,7 +20,9 @@ import edu.ie3.simona.api.exceptions.ExtDataConnectionException; import edu.ie3.simona.api.mapping.DataType; import java.util.*; +import javax.measure.quantity.Time; import org.slf4j.Logger; +import tech.units.indriya.ComparableQuantity; /** * Abstract class for an external co-simulation with bidirectional communication with SIMONA. @@ -72,11 +74,19 @@ 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 +96,7 @@ public static ExtEmDataConnection buildEmConnection( mode, controlled.size()); - return new ExtEmDataConnection(controlled, mode); + return new ExtEmDataConnection(controlled, mode, maxDelay); } } 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 30a768f3..178ef609 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy @@ -50,7 +50,7 @@ class ExtCoSimulationTest extends Specification { def controlled = [uuid1, uuid2] when: - def actual = ExtCoSimulation.buildEmConnection(controlled, EmMode.BASE, log) + def actual = ExtCoSimulation.buildEmConnection(controlled, EmMode.BASE, Optional.empty(), log) then: actual.getControlledEms() == [uuid1, uuid2] @@ -58,7 +58,7 @@ class ExtCoSimulationTest extends Specification { def "An ExtCoSimulation throws an ExtDataConnectionException while trying to build an empty em data connection"() { when: - ExtCoSimulation.buildEmConnection([], EmMode.BASE, log) + ExtCoSimulation.buildEmConnection([], EmMode.BASE, Optional.empty(), log) then: ExtDataConnectionException ex = thrown(ExtDataConnectionException) From b9a90c1820c3d4c8a80acce040771e8741a94f70 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Mon, 21 Jul 2025 10:23:11 +0200 Subject: [PATCH 7/9] Removing delay parameter from em communication. --- build.gradle | 2 +- .../data/connection/ExtEmDataConnection.java | 19 --- .../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 | 14 +- .../api/data/model/em/EmSetPointTest.groovy | 23 +--- .../model/em/FlexOptionRequestTest.groovy | 26 +--- .../api/data/model/em/FlexOptionsTest.groovy | 19 --- .../api/simulation/ExtCoSimulationTest.groovy | 4 +- 13 files changed, 51 insertions(+), 388 deletions(-) delete mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/EmMessageBase.java diff --git a/build.gradle b/build.gradle index 47318f1c..a00cfc10 100644 --- a/build.gradle +++ b/build.gradle @@ -70,7 +70,7 @@ dependencies{ } // logging - implementation platform('org.apache.logging.log4j:log4j-bom:2.25.0') + implementation platform('org.apache.logging.log4j:log4j-bom:2.25.1') implementation 'org.apache.logging.log4j:log4j-api' // log4j implementation 'org.apache.logging.log4j:log4j-core' // log4j implementation 'org.apache.logging.log4j:log4j-slf4j-impl' // log4j -> slf4j 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 1bf11433..43fff5e9 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 @@ -12,9 +12,7 @@ import edu.ie3.simona.api.data.model.em.FlexOptions; import edu.ie3.simona.api.ontology.em.*; import java.util.*; -import javax.measure.quantity.Time; import org.slf4j.Logger; -import tech.units.indriya.ComparableQuantity; /** Enables data connection of em data between SIMONA and SimonaAPI */ public final class ExtEmDataConnection @@ -25,23 +23,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,11 +35,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 4932799b..4291ec4d 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -20,9 +20,7 @@ import edu.ie3.simona.api.exceptions.ExtDataConnectionException; import edu.ie3.simona.api.mapping.DataType; import java.util.*; -import javax.measure.quantity.Time; import org.slf4j.Logger; -import tech.units.indriya.ComparableQuantity; /** * Abstract class for an external co-simulation with bidirectional communication with SIMONA. @@ -74,19 +72,11 @@ 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); @@ -96,7 +86,7 @@ public static ExtEmDataConnection buildEmConnection( mode, controlled.size()); - return new ExtEmDataConnection(controlled, mode, maxDelay); + return new ExtEmDataConnection(controlled, mode); } } diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy index 8192ccd3..3a09e7d7 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy @@ -25,11 +25,9 @@ class EmSetPointTest extends Specification { then: setPoint.receiver == receiverUuid setPoint.power == Optional.empty() - setPoint.delay == Optional.empty() - !setPoint.hasDelay() } - def "An EmSetPoint can be constructed without delay correctly"() { + def "An EmSetPoint can be constructed correctly"() { given: def pValue = new PValue(power) @@ -40,28 +38,9 @@ class EmSetPointTest extends Specification { then: setPoint1.receiver == receiverUuid setPoint1.power == Optional.of(pValue) - setPoint1.delay == Optional.empty() - !setPoint1.hasDelay() setPoint2.receiver == receiverUuid setPoint2.power == Optional.of(pValue) - setPoint2.delay == Optional.empty() - !setPoint2.hasDelay() - } - - def "An EmSetPoint can be constructed with delay correctly"() { - given: - def pValue = new PValue(power) - def delay = Quantities.getQuantity(10, PowerSystemUnits.MILLISECOND) - - when: - def setPoint = new EmSetPoint(receiverUuid, Optional.of(pValue), Optional.of(delay)) - - then: - setPoint.receiver == receiverUuid - setPoint.power == Optional.of(pValue) - setPoint.delay == Optional.of(delay) - setPoint.hasDelay() } } diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy index 68689b8a..0252d46c 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy @@ -13,51 +13,31 @@ class FlexOptionRequestTest extends Specification { @Shared UUID senderUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") - def "The FlexOptionRequest can be constructed without sender and delay correctly"() { + def "The FlexOptionRequest can be constructed without sender correctly"() { when: def request = new FlexOptionRequest(receiverUuid) then: request.receiver == receiverUuid request.sender == Optional.empty() - request.delay == Optional.empty() - !request.hasDelay() } - def "The FlexOptionRequest can be constructed with sender and without delay correctly"() { + def "The FlexOptionRequest can be constructed with sender correctly"() { when: def request = new FlexOptionRequest(receiverUuid, senderUuid) then: request.receiver == receiverUuid request.sender == Optional.of(senderUuid) - request.delay == Optional.empty() - !request.hasDelay() } - def "The FlexOptionRequest can be constructed with sender as optional and without delay correctly"() { + def "The FlexOptionRequest can be constructed with sender as optional correctly"() { when: def request = new FlexOptionRequest(receiverUuid, Optional.of(senderUuid)) then: request.receiver == receiverUuid request.sender == Optional.of(senderUuid) - request.delay == Optional.empty() - !request.hasDelay() - } - - def "The FlexOptionRequest can be constructed with sender and delay correctly"() { - given: - def delay = Quantities.getQuantity(10, PowerSystemUnits.MILLISECOND) - - when: - def request = new FlexOptionRequest(receiverUuid, Optional.of(senderUuid), Optional.of(delay)) - - then: - request.receiver == receiverUuid - request.sender == Optional.of(senderUuid) - request.delay == Optional.of(delay) - request.hasDelay() } } 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 02ee987e..f88d9453 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 @@ -35,25 +35,6 @@ class FlexOptionsTest extends Specification { flexOptions.pRef == pRef flexOptions.pMin == pMin flexOptions.pMax == pMax - flexOptions.delay == Optional.empty() - !flexOptions.hasDelay() - } - - def "FlexOptions can be constructed with delay correctly"() { - given: - def delay = Quantities.getQuantity(10, PowerSystemUnits.MILLISECOND) - - when: - def flexOptions = new FlexOptions(receiverUuid, senderUuid, pRef, pMin, pMax, Optional.of(delay)) - - then: - flexOptions.receiver == receiverUuid - flexOptions.sender == senderUuid - flexOptions.pRef == pRef - flexOptions.pMin == pMin - flexOptions.pMax == pMax - flexOptions.delay == Optional.of(delay) - flexOptions.hasDelay() } } 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 178ef609..30a768f3 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/ExtCoSimulationTest.groovy @@ -50,7 +50,7 @@ class ExtCoSimulationTest extends Specification { def controlled = [uuid1, uuid2] when: - def actual = ExtCoSimulation.buildEmConnection(controlled, EmMode.BASE, Optional.empty(), log) + def actual = ExtCoSimulation.buildEmConnection(controlled, EmMode.BASE, log) then: actual.getControlledEms() == [uuid1, uuid2] @@ -58,7 +58,7 @@ class ExtCoSimulationTest extends Specification { def "An ExtCoSimulation throws an ExtDataConnectionException while trying to build an empty em data connection"() { when: - ExtCoSimulation.buildEmConnection([], EmMode.BASE, Optional.empty(), log) + ExtCoSimulation.buildEmConnection([], EmMode.BASE, log) then: ExtDataConnectionException ex = thrown(ExtDataConnectionException) From 6eb5c01bfa9abcb789cd9c11d4bd5a61532339e2 Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Tue, 29 Jul 2025 15:30:29 +0200 Subject: [PATCH 8/9] Refactoring em models. --- .../data/connection/ExtEmDataConnection.java | 6 +- .../api/data/container/ExtDataContainer.java | 2 +- .../api/data/container/ExtInputContainer.java | 8 +-- ...Container.java => ExtOutputContainer.java} | 40 ++++++++--- .../ie3/simona/api/data/model/em/EmData.java | 16 +++++ .../simona/api/data/model/em/EmSetPoint.java | 36 +++++++--- .../api/data/model/em/EmSetPointResult.java | 67 ------------------ .../api/data/model/em/FlexOptionRequest.java | 32 +++------ .../model/em/FlexOptionRequestResult.java | 68 ------------------- .../simona/api/data/model/em/FlexOptions.java | 37 +++++++++- ...aResponse.java => EmSetPointResponse.java} | 10 ++- .../api/ontology/em/FlexOptionsResponse.java | 6 +- .../api/ontology/em/FlexRequestResponse.java | 10 ++- ...tionData.java => ProvideEmFlexOption.java} | 2 +- ...tPointData.java => ProvideEmSetPoint.java} | 2 +- ...questData.java => ProvideFlexRequest.java} | 2 +- .../api/simulation/ExtCoSimulation.java | 8 ++- .../connection/ExtEmDataConnectionTest.groovy | 11 +-- .../container/ExtInputContainerTest.groovy | 32 +++++---- ...t.groovy => ExtOutputContainerTest.groovy} | 8 ++- .../data/model/em/EmSetPointResultTest.groovy | 52 -------------- .../api/data/model/em/EmSetPointTest.groovy | 16 +++-- .../em/FlexOptionRequestResultTest.groovy | 30 -------- .../model/em/FlexOptionRequestTest.groovy | 28 ++------ 24 files changed, 202 insertions(+), 327 deletions(-) rename src/main/java/edu/ie3/simona/api/data/container/{ExtResultContainer.java => ExtOutputContainer.java} (70%) create mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/EmData.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java delete mode 100644 src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequestResult.java rename src/main/java/edu/ie3/simona/api/ontology/em/{EmSetPointDataResponse.java => EmSetPointResponse.java} (55%) rename src/main/java/edu/ie3/simona/api/ontology/em/{ProvideEmFlexOptionData.java => ProvideEmFlexOption.java} (93%) rename src/main/java/edu/ie3/simona/api/ontology/em/{ProvideEmSetPointData.java => ProvideEmSetPoint.java} (93%) rename src/main/java/edu/ie3/simona/api/ontology/em/{ProvideFlexRequestData.java => ProvideFlexRequest.java} (93%) rename src/test/groovy/edu/ie3/simona/api/data/container/{ExtResultContainerTest.groovy => ExtOutputContainerTest.groovy} (87%) delete mode 100644 src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointResultTest.groovy delete mode 100644 src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestResultTest.groovy 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..f6c48b3b 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 @@ -49,7 +49,7 @@ public void sendFlexRequests( 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)); + sendExtMsg(new ProvideFlexRequest(tick, data, maybeNextTick)); } } @@ -67,7 +67,7 @@ public void sendFlexOptions( 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)); + sendExtMsg(new ProvideEmFlexOption(tick, data, maybeNextTick)); } } @@ -85,7 +85,7 @@ public void sendSetPoints( 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, setPoints, maybeNextTick)); + sendExtMsg(new ProvideEmSetPoint(tick, setPoints, maybeNextTick)); } } 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 96a18846..615b3386 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,7 +10,7 @@ import java.util.Map; /** Interface for data that are exchanged between an external simulation and SimonaAPI */ -public sealed interface ExtDataContainer permits ExtInputContainer, ExtResultContainer { +public sealed interface ExtDataContainer permits ExtInputContainer, ExtOutputContainer { /** Returns true, if the container is empty. */ boolean isEmpty(); 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 42a7f1ce..7fb2ac3c 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 @@ -86,9 +86,9 @@ public void addPrimaryValue(UUID asset, Value 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 + * @param sender uuid of the sender */ - public void addRequest(UUID receiver, Optional sender) { + public void addRequest(UUID receiver, UUID sender) { flexRequests.put(receiver, new FlexOptionRequest(receiver, sender)); } @@ -117,8 +117,8 @@ public void addFlexOptions(UUID receiver, List flexOption) { * @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)); + public void addSetPoint(UUID asset, UUID sender, PValue power) { + setPoints.put(asset, new EmSetPoint(asset, sender, power)); } /** diff --git a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java b/src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java similarity index 70% rename from src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java rename to src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java index 9ef5df37..8141a743 100644 --- a/src/main/java/edu/ie3/simona/api/data/container/ExtResultContainer.java +++ b/src/main/java/edu/ie3/simona/api/data/container/ExtOutputContainer.java @@ -7,13 +7,14 @@ package edu.ie3.simona.api.data.container; import edu.ie3.datamodel.models.result.ResultEntity; +import edu.ie3.simona.api.data.model.em.EmData; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.UUID; /** Contains all SIMONA results for a certain tick. */ -public final class ExtResultContainer implements ExtDataContainer { +public final class ExtOutputContainer implements ExtDataContainer { /** Tick for which the results are meant for. */ private final long tick; @@ -22,33 +23,52 @@ public final class ExtResultContainer implements ExtDataContainer { private final Optional maybeNextTick; /** - * Map uuid to result from SIMONA. + * Map receiver uuid to result from SIMONA. * *

ATTENTION: The time stamp of the result entities is not necessarily corresponding to the * tick */ private final Map resultMap; + /** Map receiver uuid to {@link EmData} from SIMONA. */ + private final Map emDataMap; + /** * Container class for result data from SIMONA. * * @param tick current tick - * @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 ExtOutputContainer(long tick, Optional nextTick) { this.tick = tick; - this.resultMap = resultMap; + this.resultMap = new HashMap<>(); + this.emDataMap = new HashMap<>(); this.maybeNextTick = nextTick; } - public ExtResultContainer(long tick, Map resultMap) { - this(tick, resultMap, Optional.empty()); + public ExtOutputContainer(long tick) { + this(tick, Optional.empty()); } @Override public boolean isEmpty() { - return resultMap.isEmpty(); + return resultMap.isEmpty() && emDataMap.isEmpty(); + } + + public void addResult(UUID receiver, ResultEntity result) { + resultMap.put(receiver, result); + } + + public void addResults(Map result) { + this.resultMap.putAll(result); + } + + public void addEmData(UUID receiver, EmData emData) { + emDataMap.put(receiver, emData); + } + + public void addEmData(Map emData) { + this.emDataMap.putAll(emData); } /** Returns a map: uuid to result. */ @@ -56,6 +76,10 @@ public Map getResults() { return resultMap; } + public Map getEmData() { + return emDataMap; + } + /** * Method to extract results of a specific type. * 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 new file mode 100644 index 00000000..35d50162 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/model/em/EmData.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.model.em; + +import java.util.UUID; + +public interface EmData { + + UUID getReceiver(); + + UUID getSender(); +} 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 308a8730..8f97d728 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 @@ -15,38 +15,52 @@ /** * 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. + * @param receiver of the message + * @param sender of the message + * @param power an option for the em set point */ -public record EmSetPoint(UUID receiver, Optional power) { +public record EmSetPoint(UUID receiver, UUID sender, 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 of the set point. + * @param sender of the set point. */ - public EmSetPoint(UUID receiver) { - this(receiver, Optional.empty()); + public EmSetPoint(UUID receiver, UUID sender) { + this(receiver, sender, Optional.empty()); } /** * Constructor for {@link EmSetPoint}. * - * @param receiver of the set point. + * @param receiver of the set point + * @param sender of the set point * @param p power value of the set point */ - public EmSetPoint(UUID receiver, ComparableQuantity p) { - this(receiver, Optional.of(new PValue(p))); + public EmSetPoint(UUID receiver, UUID sender, ComparableQuantity p) { + this(receiver, sender, Optional.of(new PValue(p))); } /** * Constructor for {@link EmSetPoint}. * - * @param receiver of the set point. + * @param receiver of the set point + * @param sender of the set point * @param power value of the set point */ - public EmSetPoint(UUID receiver, PValue power) { - this(receiver, Optional.ofNullable(power)); + 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; } } diff --git a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java b/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java deleted file mode 100644 index 30611343..00000000 --- a/src/main/java/edu/ie3/simona/api/data/model/em/EmSetPointResult.java +++ /dev/null @@ -1,67 +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 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. */ -public final class EmSetPointResult extends ResultEntity { - - private final Map receiverToSetPoints; - - /** - * Basic constructor of an em set point result. - * - * @param time date and time when the result is produced - * @param sender uuid of the sending model - * @param receiverToSetPoints map: uuid to set point - */ - public EmSetPointResult(ZonedDateTime time, UUID sender, Map receiverToSetPoints) { - super(time, sender); - this.receiverToSetPoints = receiverToSetPoints; - } - - /** Returns the sender of the results. */ - public UUID getSender() { - return getInputModel(); - } - - /** Returns the mapped (receiver to set point) set point. */ - public Map getReceiverToSetPoint() { - return receiverToSetPoints; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) 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{" - + "time=" - + getTime() - + ", sender=" - + getInputModel() - + ", receiverToSetPoints=" - + receiverToSetPoints - + '}'; - } -} 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..1478203a 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,33 +6,23 @@ package edu.ie3.simona.api.data.model.em; -import java.util.Optional; import java.util.UUID; /** - * Energy management flex option request that will be sent to SIMONA + * 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. + * @param receiver of the message + * @param sender of the request */ -public record FlexOptionRequest(UUID receiver, Optional sender) { - /** - * Constructor for {@link FlexOptionRequest}. Equals {@code new FlexOptionRequest(receiver, - * Optional.empty())}. - * - * @param receiver of the request - */ - public FlexOptionRequest(UUID receiver) { - this(receiver, Optional.empty()); +public record FlexOptionRequest(UUID receiver, UUID sender) implements EmData { + + @Override + public UUID getReceiver() { + return receiver; } - /** - * Constructor for {@link FlexOptionRequest}. - * - * @param receiver of the request - * @param sender of the request - */ - public FlexOptionRequest(UUID receiver, UUID sender) { - this(receiver, Optional.ofNullable(sender)); + @Override + public UUID getSender() { + return sender; } } 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 deleted file mode 100644 index d0a70687..00000000 --- a/src/main/java/edu/ie3/simona/api/data/model/em/FlexOptionRequestResult.java +++ /dev/null @@ -1,68 +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.*; - -/** Em flex request result. */ -public final class FlexOptionRequestResult extends ResultEntity { - - /** The uuids of the receivers. */ - private final List receivers; - - /** - * 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 - */ - public FlexOptionRequestResult(ZonedDateTime time, UUID sender, Collection receivers) { - super(time, sender); - this.receivers = new ArrayList<>(receivers); - } - - /** Returns the uuid of the sender. */ - public UUID getSender() { - return getInputModel(); - } - - /** - * Returns the list of the uuids of all receivers, that should receive a request to provide flex - * options. - */ - public List getReceivers() { - return receivers; - } - - @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); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), receivers); - } - - @Override - public String toString() { - return "FlexRequestResult{" - + "time=" - + getTime() - + ", inputModel=" - + getInputModel() - + ", receivers=" - + receivers - + '}'; - } -} 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 cc4bd68d..8463693a 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,6 +6,9 @@ package edu.ie3.simona.api.data.model.em; +import edu.ie3.datamodel.models.result.system.FlexOptionsResult; +import java.util.Collections; +import java.util.Map; import java.util.UUID; import javax.measure.quantity.Power; import tech.units.indriya.ComparableQuantity; @@ -28,4 +31,36 @@ public record FlexOptions( UUID sender, ComparableQuantity pRef, ComparableQuantity pMin, - ComparableQuantity pMax) {} + ComparableQuantity pMax, + Map disaggregated) + implements EmData { + + public FlexOptions( + UUID receiver, + UUID sender, + ComparableQuantity pRef, + ComparableQuantity pMin, + ComparableQuantity pMax) { + this(receiver, sender, pRef, pMin, pMax, Collections.emptyMap()); + } + + /** + * Method for adding disaggregated flex option results to this object. + * + * @param uuid of the inferior model + * @param flexOptionsResult the flex options of the inferior model + */ + public void addDisaggregated(UUID uuid, FlexOptionsResult flexOptionsResult) { + this.disaggregated.put(uuid, flexOptionsResult); + } + + @Override + public UUID getReceiver() { + return receiver; + } + + @Override + public UUID getSender() { + return sender; + } +} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java b/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointResponse.java similarity index 55% rename from src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java rename to src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointResponse.java index c7a6c6e5..7888da5f 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointDataResponse.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/EmSetPointResponse.java @@ -6,10 +6,14 @@ package edu.ie3.simona.api.ontology.em; -import edu.ie3.simona.api.data.model.em.EmSetPointResult; +import edu.ie3.simona.api.data.model.em.EmSetPoint; import java.util.Map; import java.util.UUID; -/** Message that provides em data (set points) to an external simulation. */ -public record EmSetPointDataResponse(Map emData) +/** + * Message that provides em data (set points) to an external simulation. + * + * @param emData map:receiver to em set point + */ +public record EmSetPointResponse(Map emData) implements 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..d196fa07 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 @@ -10,6 +10,10 @@ import java.util.Map; import java.util.UUID; -/** Message that provides em data (flexibility options) to an external simulation. */ +/** + * Message that provides em data (flexibility options) to an external simulation. + * + * @param receiverToFlexOptions map: receiver to {@link ExtendedFlexOptionsResult} + */ public record FlexOptionsResponse(Map receiverToFlexOptions) 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 index a2739e0e..dc3efb1d 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 @@ -6,10 +6,14 @@ package edu.ie3.simona.api.ontology.em; -import edu.ie3.simona.api.data.model.em.FlexOptionRequestResult; +import edu.ie3.simona.api.data.model.em.FlexOptionRequest; import java.util.Map; import java.util.UUID; -/** Message that provides em data (flexibility requests) to an external simulation. */ -public record FlexRequestResponse(Map flexRequests) +/** + * Message that provides em data (flexibility requests) to an external simulation. + * + * @param flexRequests map: receiver to {@link FlexOptionRequest} + */ +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/ProvideEmFlexOption.java similarity index 93% rename from src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java rename to src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOption.java index 3d8d0e53..79b048cc 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOptionData.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmFlexOption.java @@ -13,6 +13,6 @@ import java.util.UUID; /** Message that provides em data (flexibility options) from an external simulation. */ -public record ProvideEmFlexOptionData( +public record ProvideEmFlexOption( long tick, Map> flexOptions, Optional maybeNextTick) implements EmDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmSetPointData.java b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmSetPoint.java similarity index 93% rename from src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmSetPointData.java rename to src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmSetPoint.java index 330da4bf..1e8bf821 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmSetPointData.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideEmSetPoint.java @@ -12,6 +12,6 @@ import java.util.UUID; /** Message that provides em data (set points) from an external simulation. */ -public record ProvideEmSetPointData( +public record ProvideEmSetPoint( long tick, Map emSetPoints, 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/ProvideFlexRequest.java similarity index 93% rename from src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java rename to src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequest.java index 4013e748..b933114c 100644 --- a/src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequestData.java +++ b/src/main/java/edu/ie3/simona/api/ontology/em/ProvideFlexRequest.java @@ -12,6 +12,6 @@ import java.util.UUID; /** Message that provides em data (flex requests) from an external simulation. */ -public record ProvideFlexRequestData( +public record ProvideFlexRequest( 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 4291ec4d..bfbb6cfb 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtCoSimulation.java @@ -15,7 +15,7 @@ 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.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; @@ -34,7 +34,7 @@ public abstract class ExtCoSimulation extends ExtSimulation { protected final ExtDataContainerQueue queueToSimona; /** Queue for the data connection from SimonaAPI to the external co-simulation */ - protected final ExtDataContainerQueue queueToExt; + protected final ExtDataContainerQueue queueToExt; /** Name of the external co-simulation */ protected final String extSimulatorName; @@ -180,7 +180,9 @@ 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)); + ExtOutputContainer container = new ExtOutputContainer(tick, maybeNextTick); + container.addResults(resultsToBeSend); + queueToExt.queueData(container); log.debug("Sent results to {}", extSimulatorName); } } 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..e99ca73b 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 @@ -20,7 +20,10 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa ActorTestKit testKit @Shared - List controlled = [inputUuid] + private UUID sender = UUID.randomUUID() + + @Shared + private List controlled = [inputUuid] def setupSpec() { testKit = ActorTestKit.create() @@ -41,13 +44,13 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa extSimAdapter.ref() ) - def emData = Map.of(inputUuid, new FlexOptionRequest(inputUuid)) + def emData = Map.of(inputUuid, new FlexOptionRequest(inputUuid, sender)) when: extEmDataConnection.sendFlexRequests(0L, emData, Optional.of(900L), log) then: - dataService.expectMessage(new ProvideFlexRequestData(0, emData, Optional.of(900L))) + dataService.expectMessage(new ProvideFlexRequest(0, emData, Optional.of(900L))) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) } @@ -85,7 +88,7 @@ class ExtEmDataConnectionTest extends Specification implements DataServiceTestDa extEmDataConnection.sendFlexOptions(0L, emData, Optional.of(900L), log) then: - dataService.expectMessage(new ProvideEmFlexOptionData(0, emData, Optional.of(900L))) + dataService.expectMessage(new ProvideEmFlexOption(0, emData, Optional.of(900L))) extSimAdapter.expectMessage(new ScheduleDataServiceMessage(dataService.ref())) } 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 c84a5ff3..2b85d1ed 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 @@ -4,6 +4,7 @@ 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.Shared import spock.lang.Specification import tech.units.indriya.quantity.Quantities @@ -11,6 +12,9 @@ import static edu.ie3.util.quantities.PowerSystemUnits.KILOWATT class ExtInputContainerTest extends Specification { + @Shared + private UUID sender = UUID.randomUUID() + def "An ExtInputContainer should add primary data correctly"() { given: UUID uuid = UUID.randomUUID() @@ -32,10 +36,10 @@ class ExtInputContainerTest extends Specification { def container = new ExtInputContainer(0L) when: - container.addRequest(requester, Optional.empty()) + container.addRequest(requester, sender) then: - container.flexRequests == [(requester): new FlexOptionRequest(requester, Optional.empty())] + container.flexRequests == [(requester): new FlexOptionRequest(requester, sender)] } def "An ExtInputContainer should add flex option data correctly"() { @@ -61,10 +65,10 @@ class ExtInputContainerTest extends Specification { def container = new ExtInputContainer(0L) when: - container.addSetPoint(uuid, power) + container.addSetPoint(uuid, sender, power) then: - container.setPoints == [(uuid): new EmSetPoint(uuid, power)] + container.setPoints == [(uuid): new EmSetPoint(uuid, sender, power)] } def "An ExtInputContainer should extract primary data correctly"() { @@ -76,7 +80,7 @@ class ExtInputContainerTest extends Specification { container.addPrimaryValue(primaryUuid, primaryValue) UUID requestReceiver = UUID.randomUUID() - container.addRequest(requestReceiver, Optional.empty()) + container.addRequest(requestReceiver, sender) UUID receiver = UUID.randomUUID() def flexOptions = new FlexOptions(receiver, UUID.randomUUID(), Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) @@ -84,7 +88,7 @@ class ExtInputContainerTest extends Specification { UUID emAsset = UUID.randomUUID() def setPoint = new PValue(Quantities.getQuantity(5d, KILOWATT)) - container.addSetPoint(emAsset, setPoint) + container.addSetPoint(emAsset, sender, setPoint) when: def extracted = container.extractPrimaryData() @@ -108,7 +112,7 @@ class ExtInputContainerTest extends Specification { container.addPrimaryValue(primaryUuid, primaryValue) UUID requestReceiver = UUID.randomUUID() - container.addRequest(requestReceiver, Optional.empty()) + container.addRequest(requestReceiver, sender) UUID receiver = UUID.randomUUID() def flexOptions = new FlexOptions(receiver, UUID.randomUUID(), Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) @@ -116,14 +120,14 @@ class ExtInputContainerTest extends Specification { UUID emAsset = UUID.randomUUID() def setPoint = new PValue(Quantities.getQuantity(5d, KILOWATT)) - container.addSetPoint(emAsset, setPoint) + container.addSetPoint(emAsset, sender, setPoint) when: def extracted = container.extractFlexRequests() then: extracted.size() == 1 - extracted == [(requestReceiver): new FlexOptionRequest(requestReceiver, Optional.empty())] + extracted == [(requestReceiver): new FlexOptionRequest(requestReceiver, sender)] container.primaryData.size() == 1 container.flexRequests.size() == 0 @@ -140,7 +144,7 @@ class ExtInputContainerTest extends Specification { container.addPrimaryValue(primaryUuid, primaryValue) UUID requestReceiver = UUID.randomUUID() - container.addRequest(requestReceiver, Optional.empty()) + container.addRequest(requestReceiver, sender) UUID receiver = UUID.randomUUID() def flexOptions = new FlexOptions(receiver, UUID.randomUUID(), Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) @@ -148,7 +152,7 @@ class ExtInputContainerTest extends Specification { UUID emAsset = UUID.randomUUID() def setPoint = new PValue(Quantities.getQuantity(5d, KILOWATT)) - container.addSetPoint(emAsset, setPoint) + container.addSetPoint(emAsset, sender, setPoint) when: def extracted = container.extractFlexOptions() @@ -172,7 +176,7 @@ class ExtInputContainerTest extends Specification { container.addPrimaryValue(primaryUuid, primaryValue) UUID requestReceiver = UUID.randomUUID() - container.addRequest(requestReceiver, Optional.empty()) + container.addRequest(requestReceiver, sender) UUID receiver = UUID.randomUUID() def flexOptions = new FlexOptions(receiver, UUID.randomUUID(), Quantities.getQuantity(0d, KILOWATT), Quantities.getQuantity(2d, KILOWATT), Quantities.getQuantity(5d, KILOWATT)) @@ -180,14 +184,14 @@ class ExtInputContainerTest extends Specification { UUID emAsset = UUID.randomUUID() def power = new PValue(Quantities.getQuantity(5d, KILOWATT)) - container.addSetPoint(emAsset, power) + container.addSetPoint(emAsset, sender, power) when: def extracted = container.extractSetPoints() then: extracted.size() == 1 - extracted == [(emAsset): new EmSetPoint(emAsset, power)] + extracted == [(emAsset): new EmSetPoint(emAsset, sender, power)] container.primaryData.size() == 1 container.flexRequests.size() == 1 diff --git a/src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/container/ExtOutputContainerTest.groovy similarity index 87% rename from src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy rename to src/test/groovy/edu/ie3/simona/api/data/container/ExtOutputContainerTest.groovy index 6dff294a..6519093a 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/container/ExtResultContainerTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/container/ExtOutputContainerTest.groovy @@ -12,7 +12,7 @@ import tech.units.indriya.quantity.Quantities import java.time.ZonedDateTime -class ExtResultContainerTest extends Specification implements DataServiceTestData { +class ExtOutputContainerTest extends Specification implements DataServiceTestData { @Shared UUID nodeUuid = UUID.fromString("55b97041-64be-4e6b-983a-72dbde6eddf4") @@ -32,7 +32,8 @@ class ExtResultContainerTest extends Specification implements DataServiceTestDat (inputUuid): loadResult ] - def container = new ExtResultContainer(0L, expected) + def container = new ExtOutputContainer(0L) + container.addResults(expected) expect: container.getResults() == expected @@ -45,7 +46,8 @@ class ExtResultContainerTest extends Specification implements DataServiceTestDat (inputUuid): loadResult ] - def container = new ExtResultContainer(0L, expected) + def container = new ExtOutputContainer(0L) + container.addResults(expected) when: def nodeResults = container.getResults(NodeResult) diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointResultTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointResultTest.groovy deleted file mode 100644 index c760ad04..00000000 --- a/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointResultTest.groovy +++ /dev/null @@ -1,52 +0,0 @@ -package edu.ie3.simona.api.data.model.em - -import edu.ie3.datamodel.models.value.PValue -import edu.ie3.util.quantities.PowerSystemUnits -import spock.lang.Shared -import spock.lang.Specification -import tech.units.indriya.ComparableQuantity -import tech.units.indriya.quantity.Quantities - -import javax.measure.quantity.Power -import java.time.ZonedDateTime - -class EmSetPointResultTest extends Specification { - - @Shared - ZonedDateTime time = ZonedDateTime.now() - - @Shared - UUID senderUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") - - @Shared - ComparableQuantity power = Quantities.getQuantity(10, PowerSystemUnits.KILOWATT) - - - def "An EmSetPoint can be constructed without set points correctly"() { - when: - def setPoint = new EmSetPointResult(time, senderUuid, [:]) - - then: - setPoint.time == time - setPoint.inputModel == senderUuid - setPoint.sender == senderUuid - setPoint.receiverToSetPoint == [:] - } - - def "An EmSetPoint can be constructed with set points correctly"() { - given: - def receiverUuid = UUID.fromString("81c7c8de-0f01-4559-97bb-844259e467b5") - - def setPoints = [(receiverUuid): new PValue(power)] - - when: - def setPoint = new EmSetPointResult(time, senderUuid, setPoints) - - then: - setPoint.time == time - setPoint.inputModel == senderUuid - setPoint.sender == senderUuid - setPoint.receiverToSetPoint == setPoints - } - -} diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy index 3a09e7d7..3c68a76d 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/EmSetPointTest.groovy @@ -12,18 +12,22 @@ import javax.measure.quantity.Power class EmSetPointTest extends Specification { @Shared - UUID receiverUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + private UUID receiverUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") @Shared - ComparableQuantity power = Quantities.getQuantity(10, PowerSystemUnits.KILOWATT) + private UUID sender = UUID.randomUUID() + + @Shared + private ComparableQuantity power = Quantities.getQuantity(10, PowerSystemUnits.KILOWATT) def "An empty EmSetPoint can be constructed correctly"() { when: - def setPoint = new EmSetPoint(receiverUuid) + def setPoint = new EmSetPoint(receiverUuid, sender) then: setPoint.receiver == receiverUuid + setPoint.sender == sender setPoint.power == Optional.empty() } @@ -32,14 +36,16 @@ class EmSetPointTest extends Specification { def pValue = new PValue(power) when: - def setPoint1 = new EmSetPoint(receiverUuid, power) - def setPoint2 = new EmSetPoint(receiverUuid, pValue) + def setPoint1 = new EmSetPoint(receiverUuid, sender, power) + def setPoint2 = new EmSetPoint(receiverUuid, sender, pValue) then: setPoint1.receiver == receiverUuid + setPoint1.sender == sender setPoint1.power == Optional.of(pValue) setPoint2.receiver == receiverUuid + setPoint2.sender == sender setPoint2.power == Optional.of(pValue) } diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestResultTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestResultTest.groovy deleted file mode 100644 index a232cfe7..00000000 --- a/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestResultTest.groovy +++ /dev/null @@ -1,30 +0,0 @@ -package edu.ie3.simona.api.data.model.em - -import spock.lang.Shared -import spock.lang.Specification - -import java.time.ZonedDateTime - -class FlexOptionRequestResultTest extends Specification { - - @Shared - ZonedDateTime time = ZonedDateTime.now() - - @Shared - UUID receiverUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") - - @Shared - UUID senderUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") - - def "An FlexOptionRequestResult can be constructed correctly"() { - when: - def result = new FlexOptionRequestResult(time, senderUuid, [receiverUuid]) - - then: - result.time == time - result.inputModel == senderUuid - result.sender == senderUuid - result.receivers == [receiverUuid] - } - -} diff --git a/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy index 0252d46c..de607e36 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/model/em/FlexOptionRequestTest.groovy @@ -1,26 +1,19 @@ package edu.ie3.simona.api.data.model.em -import edu.ie3.util.quantities.PowerSystemUnits + import spock.lang.Shared import spock.lang.Specification -import tech.units.indriya.quantity.Quantities class FlexOptionRequestTest extends Specification { @Shared - UUID receiverUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") + private UUID receiverUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") @Shared - UUID senderUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") - - def "The FlexOptionRequest can be constructed without sender correctly"() { - when: - def request = new FlexOptionRequest(receiverUuid) + private UUID sender = UUID.randomUUID() - then: - request.receiver == receiverUuid - request.sender == Optional.empty() - } + @Shared + private UUID senderUuid = UUID.fromString("978554e5-32cc-4221-bd39-84beac60f327") def "The FlexOptionRequest can be constructed with sender correctly"() { when: @@ -28,16 +21,7 @@ class FlexOptionRequestTest extends Specification { then: request.receiver == receiverUuid - request.sender == Optional.of(senderUuid) - } - - def "The FlexOptionRequest can be constructed with sender as optional correctly"() { - when: - def request = new FlexOptionRequest(receiverUuid, Optional.of(senderUuid)) - - then: - request.receiver == receiverUuid - request.sender == Optional.of(senderUuid) + request.sender == senderUuid } } From 20d3162937da22757c21dd716f42ffff45c4dd0f Mon Sep 17 00:00:00 2001 From: staudtMarius Date: Fri, 8 Aug 2025 13:01:34 +0200 Subject: [PATCH 9/9] Improving javadoc. --- .../api/data/container/ExtInputContainer.java | 2 +- .../data/container/ExtOutputContainer.java | 4 ++-- .../simona/api/data/model/em/EmSetPoint.java | 24 +++++++++---------- .../api/data/model/em/FlexOptionRequest.java | 4 ++-- .../simona/api/data/model/em/FlexOptions.java | 4 ++-- 5 files changed, 19 insertions(+), 19 deletions(-) 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 7fb2ac3c..ca983b91 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 @@ -86,7 +86,7 @@ public void addPrimaryValue(UUID asset, Value value) { * Method for adding flex option requests. * * @param receiver the uuid of the agent, that will receive the request - * @param sender uuid of the sender + * @param sender option for the uuid of the sender */ public void addRequest(UUID receiver, UUID sender) { flexRequests.put(receiver, new FlexOptionRequest(receiver, sender)); 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 8141a743..572b6408 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 @@ -23,14 +23,14 @@ public final class ExtOutputContainer implements ExtDataContainer { private final Optional maybeNextTick; /** - * Map receiver uuid to result from SIMONA. + * Map: receiver uuid to result from SIMONA. * *

ATTENTION: The time stamp of the result entities is not necessarily corresponding to the * tick */ private final Map resultMap; - /** Map receiver uuid to {@link EmData} from SIMONA. */ + /** Map: receiver uuid to {@link EmData} from SIMONA. */ private final Map emDataMap; /** 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 8f97d728..329cae36 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 @@ -13,11 +13,11 @@ import tech.units.indriya.ComparableQuantity; /** - * Energy management set point that will be sent to SIMONA + * Energy management set point that will be sent to SIMONA. * - * @param receiver of the message - * @param sender of the message - * @param power an option for the em set point + * @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 { /** @@ -25,8 +25,8 @@ public record EmSetPoint(UUID receiver, UUID sender, Optional power) imp * *

Note: Using this constructor will signal SIMONA, that the current set point should be kept. * - * @param receiver of the set point. - * @param sender of the set point. + * @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()); @@ -35,9 +35,9 @@ public EmSetPoint(UUID receiver, UUID sender) { /** * Constructor for {@link EmSetPoint}. * - * @param receiver of the set point - * @param sender of the set point - * @param p power value of the set point + * @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))); @@ -46,9 +46,9 @@ public EmSetPoint(UUID receiver, UUID sender, ComparableQuantity p) { /** * Constructor for {@link EmSetPoint}. * - * @param receiver of the set point - * @param sender of the set point - * @param power value of the set point + * @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)); 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 1478203a..14691ae1 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 @@ -11,8 +11,8 @@ /** * Energy management flex option request that will be sent to SIMONA. * - * @param receiver of the message - * @param sender of the request + * @param receiver The receiver of the request. + * @param sender The sender of the request. */ public record FlexOptionRequest(UUID receiver, UUID sender) implements EmData { 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 8463693a..fe50763d 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 @@ -16,8 +16,8 @@ /** * Flex option that will be sent to SIMONA. * - * @param receiver The receiver of the message. - * @param sender The sender of the request. + * @param receiver The receiver of the flex options. + * @param sender The sender of the 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 * feed-in), that was determined by the system. Therefore, equates to lower bound of possible