Skip to content

Added support for external em communication #305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
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 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
Expand All @@ -22,23 +25,76 @@ public final class ExtEmDataConnection
/** Assets that are controlled by external simulation */
private final List<UUID> controlled;

private final Optional<ComparableQuantity<Time>> maxDelay;

public ExtEmDataConnection(List<UUID> controlled, EmMode mode) {
super();

this.mode = mode;
this.controlled = controlled;
this.maxDelay = Optional.empty();
}

public ExtEmDataConnection(
List<UUID> controlled, EmMode mode, Optional<ComparableQuantity<Time>> 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 */
public List<UUID> getControlledEms() {
return new ArrayList<>(controlled);
}

/** Returns the maximal delay, that is allowed for a message when using the em communication. */
public Optional<ComparableQuantity<Time>> getMaxDelay() {
return maxDelay;
}

/**
* 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<UUID, FlexOptionRequest> data, Optional<Long> 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<UUID, List<FlexOptions>> data, Optional<Long> 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
*/
Expand All @@ -52,6 +108,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<UUID, ExtendedFlexOptionsResult> requestEmFlexResults(
long tick, List<UUID> 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<Long> requestCompletion(long tick) throws InterruptedException {
sendExtMsg(new RequestEmCompletion(tick));
return receiveWithType(EmCompletion.class).maybeNextTick();
}

/** Mode of the em connection */
public enum EmMode {
BASE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
public final class ExtPrimaryDataConnection
extends ExtInputDataConnection<PrimaryDataMessageFromExt> {

private final Map<UUID, Class<Value>> valueClasses;
private final Map<UUID, Class<? extends Value>> valueClasses;

public ExtPrimaryDataConnection(Map<UUID, Class<Value>> valueClasses) {
public ExtPrimaryDataConnection(Map<UUID, Class<? extends Value>> valueClasses) {
this.valueClasses = valueClasses;
}

Expand All @@ -34,7 +34,7 @@ public List<UUID> getPrimaryDataAssets() {
* @param uuid of the model
* @return an option for the value class associated with the model.
*/
public Optional<Class<Value>> getValueClass(UUID uuid) {
public Optional<Class<? extends Value>> getValueClass(UUID uuid) {
return Optional.ofNullable(valueClasses.get(uuid));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ public void addRequest(UUID receiver, Optional<UUID> 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.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -103,61 +94,4 @@ public Optional<Long> 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<Dimensionless> 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!");
}
}
66 changes: 66 additions & 0 deletions src/main/java/edu/ie3/simona/api/data/model/em/EmMessageBase.java
Original file line number Diff line number Diff line change
@@ -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<ComparableQuantity<Time>> 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<ComparableQuantity<Time>> 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 + '}';
}
}
Loading
Loading