diff --git a/CHANGELOG.md b/CHANGELOG.md index 98b6335f..ce263d91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Implemented `ExtPrimaryData` and `ExtResultsData` [#145](https://github.com/ie3-institute/simonaAPI/issues/145) +- Have EV simulation communicate the next tick [#170](https://github.com/ie3-institute/simonaAPI/issues/170) ## [0.4.0] - 2023-11-22 diff --git a/src/main/java/edu/ie3/simona/api/data/ev/ExtEvData.java b/src/main/java/edu/ie3/simona/api/data/ev/ExtEvData.java index 904abf7f..81a3526c 100644 --- a/src/main/java/edu/ie3/simona/api/data/ev/ExtEvData.java +++ b/src/main/java/edu/ie3/simona/api/data/ev/ExtEvData.java @@ -7,6 +7,7 @@ package edu.ie3.simona.api.data.ev; import edu.ie3.simona.api.data.ExtData; +import edu.ie3.simona.api.data.ev.model.ArrivingEvsData; import edu.ie3.simona.api.data.ev.model.EvModel; import edu.ie3.simona.api.data.ev.ontology.*; import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage; @@ -81,9 +82,9 @@ public List requestDepartingEvs(Map> departures) * Provide all EVs that are arriving at some charging station to SIMONA. Method returns right away * without expecting an answer from SIMONA. * - * @param arrivals the arriving EV models per charging station UUID + * @param arrivals the arriving EVs data per charging station UUID */ - public void provideArrivingEvs(Map> arrivals) { + public void provideArrivingEvs(Map arrivals) { sendExtMsg(new ProvideArrivingEvs(arrivals)); } diff --git a/src/main/java/edu/ie3/simona/api/data/ev/model/ArrivingEvsData.java b/src/main/java/edu/ie3/simona/api/data/ev/model/ArrivingEvsData.java new file mode 100644 index 00000000..735436e6 --- /dev/null +++ b/src/main/java/edu/ie3/simona/api/data/ev/model/ArrivingEvsData.java @@ -0,0 +1,21 @@ +/* + * © 2024. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.api.data.ev.model; + +import java.util.List; +import java.util.Optional; + +/** + * Data including arriving EVs and next arrival tick for a single charging station. Arriving EVs + * cannot be provided without being scheduled first. + * + * @param arrivals The arriving EVs for the current station. Can be empty if only the next tick + * needs to be communicated. + * @param maybeNextTick The optional next tick at which the next arrivals are expected. Empty if no + * next arrivals for the EVCS are known at this moment. + */ +public record ArrivingEvsData(List arrivals, Optional maybeNextTick) {} diff --git a/src/main/java/edu/ie3/simona/api/data/ev/ontology/ProvideArrivingEvs.java b/src/main/java/edu/ie3/simona/api/data/ev/ontology/ProvideArrivingEvs.java index a3e74d05..9847e719 100644 --- a/src/main/java/edu/ie3/simona/api/data/ev/ontology/ProvideArrivingEvs.java +++ b/src/main/java/edu/ie3/simona/api/data/ev/ontology/ProvideArrivingEvs.java @@ -6,15 +6,14 @@ package edu.ie3.simona.api.data.ev.ontology; -import edu.ie3.simona.api.data.ev.model.EvModel; -import java.util.List; +import edu.ie3.simona.api.data.ev.model.ArrivingEvsData; import java.util.Map; import java.util.UUID; /** - * Provide arriving EVs to SIMONA and its charging stations + * Provide arriving EVs data to SIMONA and its charging stations * - * @param arrivals the arriving EVs per charging station UUID + * @param arrivingEvsData the arriving EVs data per charging station UUID */ -public record ProvideArrivingEvs(Map> arrivals) +public record ProvideArrivingEvs(Map arrivingEvsData) implements EvDataMessageFromExt {} diff --git a/src/main/java/edu/ie3/simona/api/simulation/ExtSimulation.java b/src/main/java/edu/ie3/simona/api/simulation/ExtSimulation.java index aa8d5b75..ae900cdb 100644 --- a/src/main/java/edu/ie3/simona/api/simulation/ExtSimulation.java +++ b/src/main/java/edu/ie3/simona/api/simulation/ExtSimulation.java @@ -54,12 +54,11 @@ private boolean takeAndHandleMessage() throws InterruptedException { Optional newTrigger; if (activationMessage.tick() == -1L) { - newTrigger = initialize(); // this is blocking until initialization has finished + // this is blocking until initialization has finished + newTrigger = Optional.of(initialize()); } else { - newTrigger = - doActivity( - activationMessage - .tick()); // this is blocking until processing of this tick has finished + // this is blocking until processing of this tick has finished + newTrigger = doActivity(activationMessage.tick()); } data.send(new CompletionMessage(newTrigger)); @@ -81,7 +80,7 @@ private boolean takeAndHandleMessage() throws InterruptedException { * @return The first regular tick at which this external simulation wants to be triggered, if * applicable. */ - protected abstract Optional initialize(); + protected abstract Long initialize(); /** * This method is called for every tick of the external simulation that is triggered. diff --git a/src/test/groovy/edu/ie3/simona/api/data/ev/ExtEvDataTest.groovy b/src/test/groovy/edu/ie3/simona/api/data/ev/ExtEvDataTest.groovy index 676af7cd..80b8c0fd 100644 --- a/src/test/groovy/edu/ie3/simona/api/data/ev/ExtEvDataTest.groovy +++ b/src/test/groovy/edu/ie3/simona/api/data/ev/ExtEvDataTest.groovy @@ -1,5 +1,6 @@ package edu.ie3.simona.api.data.ev +import edu.ie3.simona.api.data.ev.model.ArrivingEvsData import org.apache.pekko.actor.ActorSystem import org.apache.pekko.testkit.TestProbe import org.apache.pekko.testkit.javadsl.TestKit @@ -94,14 +95,14 @@ class ExtEvDataTest extends Specification { def extSimAdapter = new TestProbe(actorSystem) def extEvData = new ExtEvData(dataService.ref(), extSimAdapter.ref()) - def arrivingEvs = new HashMap>() - arrivingEvs.put(UUID.randomUUID(), new ArrayList()) + def arrivingEvsData = new HashMap() + arrivingEvsData.put(UUID.randomUUID(), new ArrivingEvsData(new ArrayList(), Optional.of(60L))) when: - extEvData.provideArrivingEvs(arrivingEvs) + extEvData.provideArrivingEvs(arrivingEvsData) then: - dataService.expectMsg(new ProvideArrivingEvs(arrivingEvs)) + dataService.expectMsg(new ProvideArrivingEvs(arrivingEvsData)) extSimAdapter.expectMsg(new ScheduleDataServiceMessage(dataService.ref())) } diff --git a/src/test/groovy/edu/ie3/simona/api/simulation/ExtSimulationSpec.groovy b/src/test/groovy/edu/ie3/simona/api/simulation/ExtSimulationSpec.groovy index 51c86108..c1fd13be 100644 --- a/src/test/groovy/edu/ie3/simona/api/simulation/ExtSimulationSpec.groovy +++ b/src/test/groovy/edu/ie3/simona/api/simulation/ExtSimulationSpec.groovy @@ -28,17 +28,17 @@ class ExtSimulationSpec extends Specification { */ private class TestSimulation extends ExtSimulation { - private Optional initReturnTicks + private Long initReturnTick private Optional activationReturnTick - TestSimulation(Optional initReturnTick, Optional activationReturnTick) { - this.initReturnTicks = initReturnTick + TestSimulation(Long initReturnTick, Optional activationReturnTick) { + this.initReturnTick = initReturnTick this.activationReturnTick = activationReturnTick } @Override - protected Optional initialize() { - return this.initReturnTicks + protected Long initialize() { + return this.initReturnTick } @Override @@ -63,7 +63,7 @@ class ExtSimulationSpec extends Specification { def "An ExtSimulation should handle initialization"() { given: def tick = -1L - def newTick = Optional.of(0L) + def newTick = 0L def testProbe = new TestProbe(actorSystem) def extSimData = new ExtSimAdapterData(testProbe.ref(), new String[0]) def extSim = new TestSimulation(newTick, Optional.of(-2L)) @@ -75,7 +75,7 @@ class ExtSimulationSpec extends Specification { then: finishedActual == false - testProbe.expectMsg(new CompletionMessage(newTick)) + testProbe.expectMsg(new CompletionMessage(Optional.of(newTick))) } def "An ExtSimulation should handle activation and return given new triggers"() { @@ -84,7 +84,7 @@ class ExtSimulationSpec extends Specification { def extSimData = new ExtSimAdapterData(testProbe.ref(), new String[0]) def newTickOpt = newTick.isEmpty() ? Optional.empty() : Optional.of(newTick.first()) - def extSim = new TestSimulation(Optional.of(-2L), newTickOpt) + def extSim = new TestSimulation(-2L, newTickOpt) extSim.setup(extSimData, new ArrayList()) when: @@ -107,7 +107,7 @@ class ExtSimulationSpec extends Specification { given: def testProbe = new TestProbe(actorSystem) def extSimData = new ExtSimAdapterData(testProbe.ref(), new String[0]) - def extSim = new TestSimulation(Optional.empty(), Optional.empty()) + def extSim = new TestSimulation(-1L, Optional.empty()) extSim.setup(extSimData, new ArrayList()) when: @@ -130,7 +130,7 @@ class ExtSimulationSpec extends Specification { given: def testProbe = new TestProbe(actorSystem) def extSimData = new ExtSimAdapterData(testProbe.ref(), new String[0]) - def extSim = new TestSimulation(Optional.empty(), Optional.empty()) + def extSim = new TestSimulation(-1L, Optional.empty()) extSim.setup(extSimData, new ArrayList()) when: