From 83048780545909ca1672a3a0413a6f3f1c7c5933 Mon Sep 17 00:00:00 2001 From: Sebastian Peter <14994800+sebastian-peter@users.noreply.github.com> Date: Tue, 11 Jan 2022 13:23:36 +0100 Subject: [PATCH 01/11] Adapting to refactored api, replacing deprecated method call --- .../scala/edu/ie3/simona/api/ExtMessageUtils.scala | 4 ++-- .../edu/ie3/simona/sim/setup/ExtSimLoader.scala | 3 +-- .../scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala | 12 ++++++------ 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/api/ExtMessageUtils.scala b/src/main/scala/edu/ie3/simona/api/ExtMessageUtils.scala index d49182a183..97005139d6 100644 --- a/src/main/scala/edu/ie3/simona/api/ExtMessageUtils.scala +++ b/src/main/scala/edu/ie3/simona/api/ExtMessageUtils.scala @@ -25,8 +25,8 @@ object ExtMessageUtils { ) { def toSimona(triggerId: Long, triggerActor: ActorRef): CompletionMessage = { val newTriggers = - Option.when(!extCompl.getNewTriggers.isEmpty) { - extCompl.getNewTriggers.asScala.map { tick => + Option.when(!extCompl.newTriggers.isEmpty) { + extCompl.newTriggers.asScala.map { tick => ScheduleTriggerMessage(ActivityStartTrigger(tick), triggerActor) }.toSeq } diff --git a/src/main/scala/edu/ie3/simona/sim/setup/ExtSimLoader.scala b/src/main/scala/edu/ie3/simona/sim/setup/ExtSimLoader.scala index 353b38a4b9..8d3db4e970 100644 --- a/src/main/scala/edu/ie3/simona/sim/setup/ExtSimLoader.scala +++ b/src/main/scala/edu/ie3/simona/sim/setup/ExtSimLoader.scala @@ -50,7 +50,6 @@ object ExtSimLoader extends LazyLogging { name.substring(name.lastIndexOf('.') + 1).toLowerCase ) } - .toIterable } def loadExtLink(myJar: File): ExtLinkInterface = { @@ -59,7 +58,7 @@ object ExtSimLoader extends LazyLogging { this.getClass.getClassLoader ) val classToLoad = Class.forName(extLinkClassPath, true, classLoader) - classToLoad.newInstance match { + classToLoad.getDeclaredConstructor().newInstance() match { case extSim: ExtLinkInterface => extSim case other => diff --git a/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala b/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala index af7c74e8e7..7bc472c4f7 100644 --- a/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala +++ b/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala @@ -124,12 +124,12 @@ class ExtSimAdapterSpec ) awaitCond( - !extData.receiveTriggerQueue.isEmpty, + !extData.receiveMessageQueue.isEmpty, max = 3.seconds, message = "No message received" ) - extData.receiveTriggerQueue.size() shouldBe 1 - extData.receiveTriggerQueue.take() shouldBe new ExtActivityStartTrigger( + extData.receiveMessageQueue.size() shouldBe 1 + extData.receiveMessageQueue.take() shouldBe new ExtActivityStartTrigger( INIT_SIM_TICK ) scheduler.expectNoMessage() @@ -195,12 +195,12 @@ class ExtSimAdapterSpec ) awaitCond( - !extData.receiveTriggerQueue.isEmpty, + !extData.receiveMessageQueue.isEmpty, max = 3.seconds, message = "No message received" ) - extData.receiveTriggerQueue.size() shouldBe 1 - extData.receiveTriggerQueue.take() + extData.receiveMessageQueue.size() shouldBe 1 + extData.receiveMessageQueue.take() scheduler.expectNoMessage() extSimAdapter ! new ScheduleDataServiceMessage( From 6684db648b5ae6804bef69a86b8278eed95f79cc Mon Sep 17 00:00:00 2001 From: Sebastian Peter <14994800+sebastian-peter@users.noreply.github.com> Date: Tue, 11 Jan 2022 18:58:00 +0100 Subject: [PATCH 02/11] Send SimTerminated to ext simulation when main sim is finished --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 5 ++- .../ie3/simona/agent/state/AgentState.scala | 2 - .../edu/ie3/simona/api/ExtSimAdapter.scala | 9 +++- .../edu/ie3/simona/ontology/StopMessage.scala | 9 ++++ .../scala/edu/ie3/simona/sim/SimonaSim.scala | 15 +++++-- .../ie3/simona/api/ExtSimAdapterSpec.scala | 42 ++++++++++++++++++- 6 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 src/main/scala/edu/ie3/simona/ontology/StopMessage.scala diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 0ed6a265f0..bb04931dfe 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -13,12 +13,13 @@ import edu.ie3.simona.agent.grid.GridAgentData.{ GridAgentInitData, GridAgentUninitializedData } -import edu.ie3.simona.agent.state.AgentState.{Finish, Idle, Uninitialized} +import edu.ie3.simona.agent.state.AgentState.{Idle, Uninitialized} import edu.ie3.simona.agent.state.GridAgentState.SimulateGrid import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.grid.GridModel +import edu.ie3.simona.ontology.StopMessage import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage import edu.ie3.simona.ontology.messages.SchedulerMessage.{ CompletionMessage, @@ -243,7 +244,7 @@ class GridAgent( ) ) - case Event(Finish, data: GridAgentBaseData) => + case Event(StopMessage, data: GridAgentBaseData) => // shutdown children data.gridEnv.nodeToAssetAgents.foreach { case (_, actors) => actors.foreach(context.stop) diff --git a/src/main/scala/edu/ie3/simona/agent/state/AgentState.scala b/src/main/scala/edu/ie3/simona/agent/state/AgentState.scala index 4b25105c19..139d4ac81f 100644 --- a/src/main/scala/edu/ie3/simona/agent/state/AgentState.scala +++ b/src/main/scala/edu/ie3/simona/agent/state/AgentState.scala @@ -26,6 +26,4 @@ object AgentState { case object Idle extends AgentState - case object Finish extends AgentState - } diff --git a/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala b/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala index d2f24d926e..df6d4f3fce 100644 --- a/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala +++ b/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala @@ -6,7 +6,7 @@ package edu.ie3.simona.api -import akka.actor.{Actor, ActorRef, Props} +import akka.actor.{Actor, ActorRef, PoisonPill, Props} import edu.ie3.simona.api.ExtMessageUtils.{ RichExtCompletion, RichExtScheduleTrigger @@ -18,10 +18,12 @@ import edu.ie3.simona.api.ExtSimAdapter.{ import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage import edu.ie3.simona.api.simulation.ExtSimAdapterData import edu.ie3.simona.api.simulation.ontology.{ + SimTerminated, ActivityStartTrigger => ExtActivityStartTrigger, CompletionMessage => ExtCompletionMessage } import edu.ie3.simona.logging.SimonaActorLogging +import edu.ie3.simona.ontology.StopMessage import edu.ie3.simona.ontology.messages.SchedulerMessage.{ CompletionMessage, ScheduleTriggerMessage, @@ -124,6 +126,11 @@ final case class ExtSimAdapter(scheduler: ActorRef) ) scheduler ! scheduleDataService.toSimona(oldestTick) + case StopMessage => + // let external sim know that we have terminated + stateData.extSimData.queueExtMsg(new SimTerminated()) + + self ! PoisonPill } private def getOldestTickAndTriggerId(implicit diff --git a/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala b/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala new file mode 100644 index 0000000000..149208f2f6 --- /dev/null +++ b/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala @@ -0,0 +1,9 @@ +/* + * © 2022. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ + +package edu.ie3.simona.ontology + +case object StopMessage diff --git a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala index 6626241d66..aa98cbdd68 100644 --- a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala +++ b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala @@ -11,7 +11,6 @@ import akka.actor.{ Actor, ActorRef, AllForOneStrategy, - PoisonPill, Props, Stash, SupervisorStrategy, @@ -21,7 +20,7 @@ import akka.pattern.after import com.typesafe.scalalogging.LazyLogging import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData -import edu.ie3.simona.agent.state.AgentState.Finish +import edu.ie3.simona.ontology.StopMessage import edu.ie3.simona.ontology.messages.SchedulerMessage._ import edu.ie3.simona.ontology.trigger.Trigger.{ InitializeGridAgentTrigger, @@ -241,7 +240,7 @@ class SimonaSim(simonaSetup: SimonaSetup) gridAgents.foreach { case (gridAgentRef, _) => context.unwatch(gridAgentRef) } - gridAgents.foreach(_._1 ! Finish) + gridAgents.foreach(_._1 ! StopMessage) context.unwatch(scheduler) context.stop(scheduler) @@ -249,6 +248,16 @@ class SimonaSim(simonaSetup: SimonaSetup) context.unwatch(weatherService) context.stop(weatherService) + extSimulationData.allActorsAndInitTriggers.foreach { case (ref, _) => + context.unwatch(ref) + } + extSimulationData.extSimAdapters.foreach { case (ref, _) => + ref ! StopMessage + } + extSimulationData.extDataServices.foreach { case (ref, _) => + context.stop(ref) + } + /* Stop listeners with a delay */ logger.debug("Waiting for {} to stop the listeners.", listenerDelay) Await.ready( diff --git a/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala b/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala index 7bc472c4f7..08bc7ab4ef 100644 --- a/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala +++ b/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala @@ -6,16 +6,18 @@ package edu.ie3.simona.api -import akka.actor.ActorSystem +import akka.actor.{ActorSystem, Terminated} import akka.testkit.{TestActorRef, TestProbe} import com.typesafe.config.ConfigFactory import edu.ie3.simona.api.ExtSimAdapter.InitExtSimAdapter import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage import edu.ie3.simona.api.simulation.ExtSimAdapterData import edu.ie3.simona.api.simulation.ontology.{ + SimTerminated, ActivityStartTrigger => ExtActivityStartTrigger, CompletionMessage => ExtCompletionMessage } +import edu.ie3.simona.ontology.StopMessage import edu.ie3.simona.ontology.messages.SchedulerMessage.{ CompletionMessage, ScheduleTriggerMessage, @@ -215,6 +217,44 @@ class ExtSimAdapterSpec ) dataService.expectNoMessage() } + + "terminate the external simulation and itself when told to" in { + val extSimAdapter = TestActorRef( + new ExtSimAdapter(scheduler.ref) + ) + + val extData = new ExtSimAdapterData(extSimAdapter, mainArgs) + + scheduler.send( + extSimAdapter, + TriggerWithIdMessage( + InitializeExtSimAdapterTrigger( + InitExtSimAdapter( + extData + ) + ), + 1L, + extSimAdapter + ) + ) + + scheduler.expectMsgType[CompletionMessage] + + val stopWatcher = TestProbe() + stopWatcher.watch(extSimAdapter) + + extSimAdapter ! StopMessage + + awaitCond( + !extData.receiveMessageQueue.isEmpty, + max = 3.seconds, + message = "No message received" + ) + extData.receiveMessageQueue.size() shouldBe 1 + extData.receiveMessageQueue.take() shouldBe new SimTerminated() + stopWatcher.expectMsgType[Terminated].actor shouldBe extSimAdapter + scheduler.expectNoMessage() + } } } From 0306876c3fba5eb6792aa059c146d7b682427d78 Mon Sep 17 00:00:00 2001 From: Sebastian Peter <14994800+sebastian-peter@users.noreply.github.com> Date: Fri, 14 Jan 2022 22:19:32 +0100 Subject: [PATCH 03/11] Adapting to simulationSuccessful-indicator and TerminationCompleted-reply --- .../edu/ie3/simona/agent/grid/GridAgent.scala | 2 +- .../edu/ie3/simona/api/ExtSimAdapter.scala | 9 ++- .../edu/ie3/simona/ontology/StopMessage.scala | 2 +- .../scala/edu/ie3/simona/sim/SimonaSim.scala | 13 ++-- .../ie3/simona/api/ExtSimAdapterSpec.scala | 71 +++++++++++-------- 5 files changed, 58 insertions(+), 39 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index bb04931dfe..0532330184 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -244,7 +244,7 @@ class GridAgent( ) ) - case Event(StopMessage, data: GridAgentBaseData) => + case Event(StopMessage(_), data: GridAgentBaseData) => // shutdown children data.gridEnv.nodeToAssetAgents.foreach { case (_, actors) => actors.foreach(context.stop) diff --git a/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala b/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala index df6d4f3fce..208849ed26 100644 --- a/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala +++ b/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala @@ -18,7 +18,8 @@ import edu.ie3.simona.api.ExtSimAdapter.{ import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage import edu.ie3.simona.api.simulation.ExtSimAdapterData import edu.ie3.simona.api.simulation.ontology.{ - SimTerminated, + Terminate, + TerminationCompleted, ActivityStartTrigger => ExtActivityStartTrigger, CompletionMessage => ExtCompletionMessage } @@ -126,10 +127,12 @@ final case class ExtSimAdapter(scheduler: ActorRef) ) scheduler ! scheduleDataService.toSimona(oldestTick) - case StopMessage => + case StopMessage(simulationSuccessful) => // let external sim know that we have terminated - stateData.extSimData.queueExtMsg(new SimTerminated()) + stateData.extSimData.queueExtMsg(new Terminate(simulationSuccessful)) + case _: TerminationCompleted => + // external simulation has terminated as well, we can exit self ! PoisonPill } diff --git a/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala b/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala index 149208f2f6..e0ab763a52 100644 --- a/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala +++ b/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala @@ -6,4 +6,4 @@ package edu.ie3.simona.ontology -case object StopMessage +case class StopMessage(simulationSuccessful: Boolean) diff --git a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala index aa98cbdd68..65f34a076c 100644 --- a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala +++ b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala @@ -181,19 +181,21 @@ class SimonaSim(simonaSetup: SimonaSetup) scheduler ! StartScheduleMessage(pauseScheduleAtTick) case msg @ (SimulationSuccessfulMessage | SimulationFailureMessage) => - msg match { + val simulationSuccessful = msg match { case SimulationSuccessfulMessage => logger.info( "Simulation terminated successfully. Stopping children ..." ) + true case SimulationFailureMessage => logger.error( "An error occurred during the simulation. See stacktrace for details." ) + false } // stop all children - stopAllChildrenGracefully() + stopAllChildrenGracefully(simulationSuccessful) // inform initSimMessage Sender data.initSimSender ! msg @@ -213,7 +215,7 @@ class SimonaSim(simonaSetup: SimonaSetup) ) // stop all children - stopAllChildrenGracefully() + stopAllChildrenGracefully(simulationSuccessful = false) // inform initSimMessage Sender data.initSimSender ! SimulationFailureMessage @@ -235,12 +237,13 @@ class SimonaSim(simonaSetup: SimonaSetup) } def stopAllChildrenGracefully( + simulationSuccessful: Boolean, listenerDelay: FiniteDuration = 500.millis ): Unit = { gridAgents.foreach { case (gridAgentRef, _) => context.unwatch(gridAgentRef) } - gridAgents.foreach(_._1 ! StopMessage) + gridAgents.foreach(_._1 ! StopMessage(simulationSuccessful)) context.unwatch(scheduler) context.stop(scheduler) @@ -252,7 +255,7 @@ class SimonaSim(simonaSetup: SimonaSetup) context.unwatch(ref) } extSimulationData.extSimAdapters.foreach { case (ref, _) => - ref ! StopMessage + ref ! StopMessage(simulationSuccessful) } extSimulationData.extDataServices.foreach { case (ref, _) => context.stop(ref) diff --git a/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala b/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala index 08bc7ab4ef..09234e0b17 100644 --- a/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala +++ b/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala @@ -13,7 +13,8 @@ import edu.ie3.simona.api.ExtSimAdapter.InitExtSimAdapter import edu.ie3.simona.api.data.ontology.ScheduleDataServiceMessage import edu.ie3.simona.api.simulation.ExtSimAdapterData import edu.ie3.simona.api.simulation.ontology.{ - SimTerminated, + Terminate, + TerminationCompleted, ActivityStartTrigger => ExtActivityStartTrigger, CompletionMessage => ExtCompletionMessage } @@ -30,6 +31,7 @@ import edu.ie3.simona.ontology.trigger.Trigger.{ import edu.ie3.simona.test.common.TestKitWithShutdown import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import org.scalatest.wordspec.AnyWordSpecLike +import org.scalatest.prop.TableDrivenPropertyChecks._ import scala.concurrent.duration.DurationInt import scala.jdk.CollectionConverters.SeqHasAsJava @@ -219,41 +221,52 @@ class ExtSimAdapterSpec } "terminate the external simulation and itself when told to" in { - val extSimAdapter = TestActorRef( - new ExtSimAdapter(scheduler.ref) - ) + forAll(Table("simSuccessful", true, false)) { (simSuccessful: Boolean) => + val extSimAdapter = TestActorRef( + new ExtSimAdapter(scheduler.ref) + ) - val extData = new ExtSimAdapterData(extSimAdapter, mainArgs) + val extData = new ExtSimAdapterData(extSimAdapter, mainArgs) - scheduler.send( - extSimAdapter, - TriggerWithIdMessage( - InitializeExtSimAdapterTrigger( - InitExtSimAdapter( - extData - ) - ), - 1L, - extSimAdapter + scheduler.send( + extSimAdapter, + TriggerWithIdMessage( + InitializeExtSimAdapterTrigger( + InitExtSimAdapter( + extData + ) + ), + 1L, + extSimAdapter + ) ) - ) - scheduler.expectMsgType[CompletionMessage] + scheduler.expectMsgType[CompletionMessage] - val stopWatcher = TestProbe() - stopWatcher.watch(extSimAdapter) + val stopWatcher = TestProbe() + stopWatcher.watch(extSimAdapter) - extSimAdapter ! StopMessage + extSimAdapter ! StopMessage(simSuccessful) - awaitCond( - !extData.receiveMessageQueue.isEmpty, - max = 3.seconds, - message = "No message received" - ) - extData.receiveMessageQueue.size() shouldBe 1 - extData.receiveMessageQueue.take() shouldBe new SimTerminated() - stopWatcher.expectMsgType[Terminated].actor shouldBe extSimAdapter - scheduler.expectNoMessage() + awaitCond( + !extData.receiveMessageQueue.isEmpty, + max = 3.seconds, + message = "No message received" + ) + extData.receiveMessageQueue.size() shouldBe 1 + extData.receiveMessageQueue.take() shouldBe new Terminate(simSuccessful) + + // up until now, extSimAdapter should still be running + stopWatcher.expectNoMessage() + + extSimAdapter ! new TerminationCompleted() + + // extSimAdapter should have terminated now + stopWatcher.expectMsgType[Terminated].actor shouldBe extSimAdapter + + // scheduler is not involved in this + scheduler.expectNoMessage() + } } } From dfe8da1fd4d04cce20ee43d9c2065d0283f9862a Mon Sep 17 00:00:00 2001 From: Sebastian Peter <14994800+sebastian-peter@users.noreply.github.com> Date: Mon, 17 Jan 2022 16:01:47 +0100 Subject: [PATCH 04/11] Fixing code smell --- src/main/scala/edu/ie3/simona/ontology/StopMessage.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala b/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala index e0ab763a52..25e9a1bb37 100644 --- a/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala +++ b/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala @@ -6,4 +6,4 @@ package edu.ie3.simona.ontology -case class StopMessage(simulationSuccessful: Boolean) +final case class StopMessage(simulationSuccessful: Boolean) From 38fd4e0438d235034f2ff90d99d08d070a5525a2 Mon Sep 17 00:00:00 2001 From: Sebastian Peter <14994800+sebastian-peter@users.noreply.github.com> Date: Wed, 19 Jan 2022 15:15:52 +0100 Subject: [PATCH 05/11] Addressing reviewer's comments --- src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala | 2 +- src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala | 2 +- .../ie3/simona/ontology/{ => messages}/StopMessage.scala | 2 +- src/main/scala/edu/ie3/simona/sim/SimonaSim.scala | 9 ++++----- .../scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) rename src/main/scala/edu/ie3/simona/ontology/{ => messages}/StopMessage.scala (85%) diff --git a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala index 0532330184..4d13712b87 100644 --- a/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/grid/GridAgent.scala @@ -19,13 +19,13 @@ import edu.ie3.simona.agent.{EnvironmentRefs, SimonaAgent} import edu.ie3.simona.config.SimonaConfig import edu.ie3.simona.exceptions.agent.GridAgentInitializationException import edu.ie3.simona.model.grid.GridModel -import edu.ie3.simona.ontology.StopMessage import edu.ie3.simona.ontology.messages.PowerMessage.RequestGridPowerMessage import edu.ie3.simona.ontology.messages.SchedulerMessage.{ CompletionMessage, ScheduleTriggerMessage, TriggerWithIdMessage } +import edu.ie3.simona.ontology.messages.StopMessage import edu.ie3.simona.ontology.trigger.Trigger.{ ActivityStartTrigger, InitializeGridAgentTrigger, diff --git a/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala b/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala index 208849ed26..8db8eb4126 100644 --- a/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala +++ b/src/main/scala/edu/ie3/simona/api/ExtSimAdapter.scala @@ -24,12 +24,12 @@ import edu.ie3.simona.api.simulation.ontology.{ CompletionMessage => ExtCompletionMessage } import edu.ie3.simona.logging.SimonaActorLogging -import edu.ie3.simona.ontology.StopMessage import edu.ie3.simona.ontology.messages.SchedulerMessage.{ CompletionMessage, ScheduleTriggerMessage, TriggerWithIdMessage } +import edu.ie3.simona.ontology.messages.StopMessage import edu.ie3.simona.ontology.trigger.Trigger.{ ActivityStartTrigger, InitializeExtSimAdapterTrigger diff --git a/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala b/src/main/scala/edu/ie3/simona/ontology/messages/StopMessage.scala similarity index 85% rename from src/main/scala/edu/ie3/simona/ontology/StopMessage.scala rename to src/main/scala/edu/ie3/simona/ontology/messages/StopMessage.scala index 25e9a1bb37..33dab3aa58 100644 --- a/src/main/scala/edu/ie3/simona/ontology/StopMessage.scala +++ b/src/main/scala/edu/ie3/simona/ontology/messages/StopMessage.scala @@ -4,6 +4,6 @@ * Research group Distribution grid planning and operation */ -package edu.ie3.simona.ontology +package edu.ie3.simona.ontology.messages final case class StopMessage(simulationSuccessful: Boolean) diff --git a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala index 65f34a076c..e71227c906 100644 --- a/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala +++ b/src/main/scala/edu/ie3/simona/sim/SimonaSim.scala @@ -20,8 +20,8 @@ import akka.pattern.after import com.typesafe.scalalogging.LazyLogging import edu.ie3.simona.agent.EnvironmentRefs import edu.ie3.simona.agent.grid.GridAgentData.GridAgentInitData -import edu.ie3.simona.ontology.StopMessage import edu.ie3.simona.ontology.messages.SchedulerMessage._ +import edu.ie3.simona.ontology.messages.StopMessage import edu.ie3.simona.ontology.trigger.Trigger.{ InitializeGridAgentTrigger, InitializeServiceTrigger @@ -242,8 +242,8 @@ class SimonaSim(simonaSetup: SimonaSetup) ): Unit = { gridAgents.foreach { case (gridAgentRef, _) => context.unwatch(gridAgentRef) + gridAgentRef ! StopMessage(simulationSuccessful) } - gridAgents.foreach(_._1 ! StopMessage(simulationSuccessful)) context.unwatch(scheduler) context.stop(scheduler) @@ -251,13 +251,12 @@ class SimonaSim(simonaSetup: SimonaSetup) context.unwatch(weatherService) context.stop(weatherService) - extSimulationData.allActorsAndInitTriggers.foreach { case (ref, _) => - context.unwatch(ref) - } extSimulationData.extSimAdapters.foreach { case (ref, _) => + context.unwatch(ref) ref ! StopMessage(simulationSuccessful) } extSimulationData.extDataServices.foreach { case (ref, _) => + context.unwatch(ref) context.stop(ref) } diff --git a/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala b/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala index 09234e0b17..512d60038c 100644 --- a/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala +++ b/src/test/scala/edu/ie3/simona/api/ExtSimAdapterSpec.scala @@ -18,12 +18,12 @@ import edu.ie3.simona.api.simulation.ontology.{ ActivityStartTrigger => ExtActivityStartTrigger, CompletionMessage => ExtCompletionMessage } -import edu.ie3.simona.ontology.StopMessage import edu.ie3.simona.ontology.messages.SchedulerMessage.{ CompletionMessage, ScheduleTriggerMessage, TriggerWithIdMessage } +import edu.ie3.simona.ontology.messages.StopMessage import edu.ie3.simona.ontology.trigger.Trigger.{ ActivityStartTrigger, InitializeExtSimAdapterTrigger From 70f31ecb03ea53be06b597dbb28883429c957d7d Mon Sep 17 00:00:00 2001 From: Sebastian Peter <14994800+sebastian-peter@users.noreply.github.com> Date: Thu, 20 Jan 2022 16:32:16 +0100 Subject: [PATCH 06/11] changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c47d5ac600..37ae447fa4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Changed -- Improving code readability in EvcsAgent by moving FreeLotsRequest to separate methods +- Improving code readability in EvcsAgent by moving FreeLotsRequest to separate methods [#19](https://github.com/ie3-institute/simona/issues/19) +- Sending termination message to external simulation on expected and unexpected shutdowns of SIMONA [#35](https://github.com/ie3-institute/simona/issues/35) [Unreleased]: https://github.com/ie3-institute/simona From 890312b69d5505dfddf99a7884e08ca3fa60eb84 Mon Sep 17 00:00:00 2001 From: "Kittl, Chris" Date: Fri, 21 Jan 2022 11:39:32 +0100 Subject: [PATCH 07/11] Improve protocol documentation --- .../uml/protocol/ExtEvSimulationSequence.puml | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/uml/protocol/ExtEvSimulationSequence.puml b/docs/uml/protocol/ExtEvSimulationSequence.puml index 9fe4b331ad..7775168595 100644 --- a/docs/uml/protocol/ExtEvSimulationSequence.puml +++ b/docs/uml/protocol/ExtEvSimulationSequence.puml @@ -1,10 +1,46 @@ @startuml -SimScheduler -> ExtSimAdapter: ! ActivityStartTrigger + +!theme plain + +==Init== +SimScheduler -> ExtSimAdapter: ! ActivityStartTrigger(-1L) +activate ExtSimAdapter + +ExtSimAdapter -> ExtSimulation: queue(ActivityStartTrigger) +deactivate ExtSimAdapter +activate ExtSimulation +note right: Initialize external\nmobility simulation + +ExtSimulation -> ExtSimAdapter: ! CompletionMessage(newTriggers) +deactivate ExtSimulation +activate ExtSimAdapter + +ExtSimAdapter -> SimScheduler: ! CompletionMessage(newTriggers) +deactivate ExtSimAdapter + +==Sim== +SimScheduler -> ExtSimAdapter: ! ActivityStartTrigger(tick) activate ExtSimAdapter ExtSimAdapter -> ExtSimulation: queue(ActivityStartTrigger) deactivate ExtSimAdapter activate ExtSimulation + +ExtSimulation -> ExtEvDataService: ! RequestEvcsFreeLots +activate ExtEvDataService +ExtEvDataService -> EvcsAgent1: ! EvFreeLotsRequest(tick) +activate EvcsAgent1 +ExtEvDataService -> EvcsAgent2: ! EvFreeLotsRequest(tick) +activate EvcsAgent2 +EvcsAgent2 -> ExtEvDataService: ! FreeLotsResponse(_, _) +deactivate EvcsAgent2 +EvcsAgent1 -> ExtEvDataService: ! FreeLotsResponse(_, _) +deactivate EvcsAgent1 +ExtEvDataService -> ExtSimulation: ! ProvideEvcsFreeLots(_) +deactivate ExtEvDataService + +'TODO Refactor from here + ExtSimulation -> ExtEvDataService: ! EvMovementsMessage ExtSimulation -> ExtSimAdapter: ! ScheduleDataServiceMessage deactivate ExtSimulation From 9583616bdd97a103d16dd2a7d89b06a646a775e7 Mon Sep 17 00:00:00 2001 From: Sebastian Peter <14994800+sebastian-peter@users.noreply.github.com> Date: Fri, 21 Jan 2022 12:17:33 +0100 Subject: [PATCH 08/11] Adapting input directory to recent changes --- docs/readthedocs/usersguide.rst | 11 ++++++----- .../scala/edu/ie3/simona/sim/setup/ExtSimLoader.scala | 2 +- src/main/sh/deploy/init-run.sh | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/readthedocs/usersguide.rst b/docs/readthedocs/usersguide.rst index 4cf3a867f0..42d8a8034a 100644 --- a/docs/readthedocs/usersguide.rst +++ b/docs/readthedocs/usersguide.rst @@ -64,7 +64,8 @@ Default Config and Where to Find It ----------------------------------- Within the SIMONA repository, there are two default configurations and their corresponding grids with all necessary data to execute a simulation. -For each configuration, there is a separate directory in the project directory at ``./inputData``. +For each configuration, there is a separate directory in the project directory at ``./input``. +Sample configurations are provided within the subdirectory ``samples``. Each configuration is described by a ``.conf`` file that holds the simulation configuration parameters. @@ -79,7 +80,7 @@ When you want to start a simulation run from the command line interface you have .. code-block:: none - java -cp build/libs/simona-2.1-all.jar edu.ie3.simona.main.RunSimonaStandalone --config=inputData/vn_simona/vn_simona.conf + java -cp build/libs/simona-2.1-all.jar edu.ie3.simona.main.RunSimonaStandalone --config=input/samples/vn_simona/vn_simona.conf Using IntelliJ IDEA @@ -105,7 +106,7 @@ If you are using IntelliJ IDEA as your IDE, this is how setting the command line Enter ``--config={path from the content root of config file}`` .. note:: - For our example that would be ``--config=inputData/vn_simona/vn_simona.conf`` + For our example that would be ``--config=input/samples/vn_simona/vn_simona.conf`` .. figure:: ./images/usersguide/edit-conf2.png @@ -125,7 +126,7 @@ Model and Grid Data Besides a simulation configuration, the specifications of each grid component (e.g. lines, transformers, ...) and system participant (e.g. loads, pv plants, ... ) have to be fed into the simulation. Within SIMONA we use the PowerSystemDataModel (PSDM) for modeling the system components. Before the data can be utilized for a simulation run, make sure to convert them to the PSDM. -For more information on the PSDM visit the `docs `_ and for an example of how the converted data looks like you can take a look at an example grid at ``./inputData/vn_simona/fullGrid``. +For more information on the PSDM visit the `docs `_ and for an example of how the converted data looks like you can take a look at an example grid at ``./input/samples/vn_simona/fullGrid``. The example grids are provided as csv files. You can choose to use a different data source for your own grid. For more information on supported sources, check out the :doc:`/config/config` section. Include your grid and its specification by referencing the folder path, where all the converted grid data is located, within your custom configuration file. @@ -197,6 +198,6 @@ Preparation These steps have to be performed each time updates to the external simulation need to be deployed. - Execute ``gradle shadowJar`` inside the external simulation project. -- Copy the resulting *jar* (usually placed inside /build/libs) to SIMONA/inputData/ext_sim. +- Copy the resulting *jar* (usually placed inside /build/libs) to ``./input/ext_sim/``. Now, when a simulation with SIMONA is started (see `above <#running-a-standalone-simulation>`_), the external simulation is triggered at each tick that it requested. diff --git a/src/main/scala/edu/ie3/simona/sim/setup/ExtSimLoader.scala b/src/main/scala/edu/ie3/simona/sim/setup/ExtSimLoader.scala index 8d3db4e970..c711b88116 100644 --- a/src/main/scala/edu/ie3/simona/sim/setup/ExtSimLoader.scala +++ b/src/main/scala/edu/ie3/simona/sim/setup/ExtSimLoader.scala @@ -16,7 +16,7 @@ import java.net.URLClassLoader */ object ExtSimLoader extends LazyLogging { - private val extSimPath = "inputData" + java.io.File.separator + "ext_sim" + private val extSimPath = "input" + java.io.File.separator + "ext_sim" private val extLinkClassPath = "edu.ie3.simona.api.ExtLink" diff --git a/src/main/sh/deploy/init-run.sh b/src/main/sh/deploy/init-run.sh index bf2f04e52f..406b3a403f 100644 --- a/src/main/sh/deploy/init-run.sh +++ b/src/main/sh/deploy/init-run.sh @@ -28,7 +28,7 @@ margs=3 # Common functions - BEGIN function example() { - echo -e "example: $script -b jh/#123-test-run -c 92e8b8bea18e8f8a62f6397e05d369acaba0e3b7 -s inputData/vn_simona/vn_simona.conf" + echo -e "example: $script -b jh/#123-test-run -c 92e8b8bea18e8f8a62f6397e05d369acaba0e3b7 -s input/samples/vn_simona/vn_simona.conf" } function usage() { From abd057997cda346f1f2d773843123df294b9804b Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Sat, 12 Feb 2022 14:23:47 +0100 Subject: [PATCH 09/11] Small fix in ev sequence diagram --- docs/uml/protocol/ExtEvSimulationSequence.puml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/uml/protocol/ExtEvSimulationSequence.puml b/docs/uml/protocol/ExtEvSimulationSequence.puml index 7775168595..3debe4814e 100644 --- a/docs/uml/protocol/ExtEvSimulationSequence.puml +++ b/docs/uml/protocol/ExtEvSimulationSequence.puml @@ -36,7 +36,7 @@ EvcsAgent2 -> ExtEvDataService: ! FreeLotsResponse(_, _) deactivate EvcsAgent2 EvcsAgent1 -> ExtEvDataService: ! FreeLotsResponse(_, _) deactivate EvcsAgent1 -ExtEvDataService -> ExtSimulation: ! ProvideEvcsFreeLots(_) +ExtEvDataService -> ExtSimulation: queue(ProvideEvcsFreeLots(_)) deactivate ExtEvDataService 'TODO Refactor from here From 9cf3247f4225a91ca4f881b255ff012ffbb0936e Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Sun, 10 Apr 2022 20:06:17 +0200 Subject: [PATCH 10/11] Adapting ext ev simulation sequence diagram --- .../uml/protocol/ExtEvSimulationSequence.puml | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/docs/uml/protocol/ExtEvSimulationSequence.puml b/docs/uml/protocol/ExtEvSimulationSequence.puml index 3debe4814e..81f7d0626f 100644 --- a/docs/uml/protocol/ExtEvSimulationSequence.puml +++ b/docs/uml/protocol/ExtEvSimulationSequence.puml @@ -6,10 +6,10 @@ SimScheduler -> ExtSimAdapter: ! ActivityStartTrigger(-1L) activate ExtSimAdapter -ExtSimAdapter -> ExtSimulation: queue(ActivityStartTrigger) +ExtSimAdapter -> ExtSimulation: queue(ActivityStartTrigger(-1L)) deactivate ExtSimAdapter activate ExtSimulation -note right: Initialize external\nmobility simulation +... Initialize external mobility simulation ... ExtSimulation -> ExtSimAdapter: ! CompletionMessage(newTriggers) deactivate ExtSimulation @@ -22,16 +22,27 @@ deactivate ExtSimAdapter SimScheduler -> ExtSimAdapter: ! ActivityStartTrigger(tick) activate ExtSimAdapter -ExtSimAdapter -> ExtSimulation: queue(ActivityStartTrigger) +ExtSimAdapter -> ExtSimulation: queue(ActivityStartTrigger(tick)) deactivate ExtSimAdapter -activate ExtSimulation +activate ExtSimulation ExtSimulation -> ExtEvDataService: ! RequestEvcsFreeLots +ExtSimulation -> ExtSimAdapter: ! ScheduleDataServiceMessage(\n\tdataServiceRef\n) +deactivate ExtSimulation + +activate ExtSimAdapter +ExtSimAdapter -> SimScheduler: ! ScheduleTriggerMessage(\n\t_, dataServiceRef) +deactivate ExtSimAdapter + +SimScheduler -> ExtEvDataService: ! ActivityStartTrigger(tick) activate ExtEvDataService ExtEvDataService -> EvcsAgent1: ! EvFreeLotsRequest(tick) activate EvcsAgent1 ExtEvDataService -> EvcsAgent2: ! EvFreeLotsRequest(tick) activate EvcsAgent2 + +ExtEvDataService -> SimScheduler: ! CompletionMessage(None) + EvcsAgent2 -> ExtEvDataService: ! FreeLotsResponse(_, _) deactivate EvcsAgent2 EvcsAgent1 -> ExtEvDataService: ! FreeLotsResponse(_, _) @@ -39,49 +50,50 @@ deactivate EvcsAgent1 ExtEvDataService -> ExtSimulation: queue(ProvideEvcsFreeLots(_)) deactivate ExtEvDataService -'TODO Refactor from here - -ExtSimulation -> ExtEvDataService: ! EvMovementsMessage -ExtSimulation -> ExtSimAdapter: ! ScheduleDataServiceMessage +activate ExtSimulation +... Running external mobility simulation,\n determining EV positions ... +ExtSimulation -> ExtEvDataService: ! EvMovementsMessage(_) +ExtSimulation -> ExtSimAdapter: ! ScheduleDataServiceMessage(\n\tdataServiceRef\n) deactivate ExtSimulation -activate ExtSimAdapter -ExtSimAdapter -> SimScheduler: ! ScheduleTriggerMessage +activate ExtSimAdapter +ExtSimAdapter -> SimScheduler: ! ScheduleTriggerMessage(\n\t_, dataServiceRef) deactivate ExtSimAdapter -activate SimScheduler -SimScheduler -> ExtEvDataService: ! ActivityStartTrigger +activate SimScheduler +SimScheduler -> ExtEvDataService: ! ActivityStartTrigger(tick) deactivate SimScheduler -activate ExtEvDataService -ExtEvDataService -> EvcsAgent1: ! ProvideEvMovementsMessage -ExtEvDataService -> EvcsAgent2: ! ProvideEvMovementsMessage -ExtEvDataService -> SimScheduler: ! CompletionMessage(\n\tScheduleTriggerMessage[]\n) +activate ExtEvDataService +ExtEvDataService -> EvcsAgent1: ! ProvideEvDataMessage(\n\ttick, _) +ExtEvDataService -> EvcsAgent2: ! ProvideEvDataMessage(\n\ttick, _) +ExtEvDataService -> SimScheduler: ! CompletionMessage(evcsTriggers) deactivate ExtEvDataService -activate SimScheduler -SimScheduler -> EvcsAgent1: ! ActivityStartTrigger +activate SimScheduler +SimScheduler -> EvcsAgent1: ! ActivityStartTrigger(tick) activate EvcsAgent1 -SimScheduler -> EvcsAgent2: ! ActivityStartTrigger +SimScheduler -> EvcsAgent2: ! ActivityStartTrigger(tick) deactivate SimScheduler -activate EvcsAgent2 -EvcsAgent1 -> SimScheduler: ! CompletionMessage +activate EvcsAgent2 +EvcsAgent1 -> SimScheduler: ! CompletionMessage(None) deactivate EvcsAgent1 -EvcsAgent2 -> ExtEvDataService: ! DepartedEvsResponse +EvcsAgent2 -> ExtEvDataService: ! DepartedEvsResponse(_, _) activate ExtEvDataService -EvcsAgent2 -> SimScheduler: ! CompletionMessage +EvcsAgent2 -> SimScheduler: ! CompletionMessage(None) deactivate EvcsAgent2 -ExtEvDataService -> ExtSimulation: queue(AllDepartedEvsResponse) +ExtEvDataService -> ExtSimulation: queue(AllDepartedEvsResponse(_)) deactivate ExtEvDataService -activate ExtSimulation -ExtSimulation -> ExtSimAdapter: ! CompletionMessage +activate ExtSimulation +ExtSimulation -> ExtSimAdapter: ! CompletionMessage(None) deactivate ExtSimulation + activate ExtSimAdapter -ExtSimAdapter -> SimScheduler: ! CompletionMessage +ExtSimAdapter -> SimScheduler: ! CompletionMessage(None) deactivate ExtSimAdapter @enduml \ No newline at end of file From 3e3e5ee5844e381aea3c137bd88eb8a3ab6dfbb5 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Mon, 2 May 2022 15:33:15 +0200 Subject: [PATCH 11/11] Improving diagram once more --- docs/uml/protocol/ExtEvSimulationSequence.puml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/uml/protocol/ExtEvSimulationSequence.puml b/docs/uml/protocol/ExtEvSimulationSequence.puml index 81f7d0626f..470d49981e 100644 --- a/docs/uml/protocol/ExtEvSimulationSequence.puml +++ b/docs/uml/protocol/ExtEvSimulationSequence.puml @@ -28,13 +28,15 @@ deactivate ExtSimAdapter activate ExtSimulation ExtSimulation -> ExtEvDataService: ! RequestEvcsFreeLots ExtSimulation -> ExtSimAdapter: ! ScheduleDataServiceMessage(\n\tdataServiceRef\n) -deactivate ExtSimulation activate ExtSimAdapter ExtSimAdapter -> SimScheduler: ! ScheduleTriggerMessage(\n\t_, dataServiceRef) deactivate ExtSimAdapter +activate SimScheduler SimScheduler -> ExtEvDataService: ! ActivityStartTrigger(tick) +deactivate SimScheduler + activate ExtEvDataService ExtEvDataService -> EvcsAgent1: ! EvFreeLotsRequest(tick) activate EvcsAgent1 @@ -50,11 +52,9 @@ deactivate EvcsAgent1 ExtEvDataService -> ExtSimulation: queue(ProvideEvcsFreeLots(_)) deactivate ExtEvDataService -activate ExtSimulation ... Running external mobility simulation,\n determining EV positions ... ExtSimulation -> ExtEvDataService: ! EvMovementsMessage(_) ExtSimulation -> ExtSimAdapter: ! ScheduleDataServiceMessage(\n\tdataServiceRef\n) -deactivate ExtSimulation activate ExtSimAdapter ExtSimAdapter -> SimScheduler: ! ScheduleTriggerMessage(\n\t_, dataServiceRef) @@ -88,12 +88,11 @@ deactivate EvcsAgent2 ExtEvDataService -> ExtSimulation: queue(AllDepartedEvsResponse(_)) deactivate ExtEvDataService -activate ExtSimulation -ExtSimulation -> ExtSimAdapter: ! CompletionMessage(None) +ExtSimulation -> ExtSimAdapter: ! CompletionMessage(newTriggers) deactivate ExtSimulation activate ExtSimAdapter -ExtSimAdapter -> SimScheduler: ! CompletionMessage(None) +ExtSimAdapter -> SimScheduler: ! CompletionMessage(newTriggers) deactivate ExtSimAdapter @enduml \ No newline at end of file