From bd624d7604de62f3fe18c4fabd081a14ac22d5f0 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Mon, 2 Sep 2024 16:26:28 +0200 Subject: [PATCH 01/14] Enabling EmAgents to handle initialization Signed-off-by: Sebastian Peter --- CHANGELOG.md | 1 + docs/uml/protocol/em/ControlledEm.puml | 5 + docs/uml/protocol/em/UncontrolledEm.puml | 2 + .../edu/ie3/simona/agent/em/EmAgent.scala | 54 +++-- .../edu/ie3/simona/agent/em/EmDataCore.scala | 83 +++++-- .../ParticipantAgentFundamentals.scala | 6 +- .../messages/flex/FlexibilityMessage.scala | 23 +- .../edu/ie3/simona/agent/em/EmAgentSpec.scala | 215 ++++++++++++----- .../EvcsAgentModelCalculationSpec.scala | 221 ++++++++---------- .../StorageAgentModelCalculationSpec.scala | 133 +++++------ 10 files changed, 447 insertions(+), 296 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 781aba25a6..ab479e850e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update RTD references and bibliography [#868](https://github.com/ie3-institute/simona/issues/868) - Add gradle application plugin for command line execution with gradle run [#890](https://github.com/ie3-institute/simona/issues/890) - Additional tests to check flexibility options of thermal house and storage [#729](https://github.com/ie3-institute/simona/issues/729) +- EmAgents should be able to handle initialization [#945](https://github.com/ie3-institute/simona/issues/945) ### Changed - Adapted to changed data source in PSDM [#435](https://github.com/ie3-institute/simona/issues/435) diff --git a/docs/uml/protocol/em/ControlledEm.puml b/docs/uml/protocol/em/ControlledEm.puml index 385170e355..185bee971a 100644 --- a/docs/uml/protocol/em/ControlledEm.puml +++ b/docs/uml/protocol/em/ControlledEm.puml @@ -81,12 +81,15 @@ activate PvAgent EmAgent2 -> StorageAgent: IssuePowerControl(tick=0) activate StorageAgent +PvAgent -> EmAgent2: FlexResult PvAgent -> EmAgent2: FlexCompletion(nextTick=3600) deactivate PvAgent +StorageAgent -> EmAgent2: FlexResult StorageAgent -> EmAgent2: FlexCompletion(nextTick=1805) deactivate StorageAgent +EmAgent2 -> EmAgent1: FlexResult EmAgent2 -> EmAgent1: FlexCompletion(nextTick=1805) deactivate EmAgent2 @@ -116,9 +119,11 @@ activate EmAgent2 EmAgent2 -> StorageAgent: IssuePowerControl(tick=1805) activate StorageAgent +StorageAgent -> EmAgent2: FlexResult StorageAgent -> EmAgent2: FlexCompletion(nextTick=10800) deactivate StorageAgent +EmAgent2 -> EmAgent1: FlexResult EmAgent2 -> EmAgent1: FlexCompletion(nextTick=3600) deactivate EmAgent2 diff --git a/docs/uml/protocol/em/UncontrolledEm.puml b/docs/uml/protocol/em/UncontrolledEm.puml index 16bdc19619..53f27b0e6d 100644 --- a/docs/uml/protocol/em/UncontrolledEm.puml +++ b/docs/uml/protocol/em/UncontrolledEm.puml @@ -68,9 +68,11 @@ activate PvAgent EmAgent -> StorageAgent: IssuePowerControl(tick=0) activate StorageAgent +PvAgent -> EmAgent: FlexResult PvAgent -> EmAgent: FlexCompletion(nextTick=3600) deactivate PvAgent +StorageAgent -> EmAgent: FlexResult StorageAgent -> EmAgent: FlexCompletion(nextTick=8400) deactivate StorageAgent diff --git a/src/main/scala/edu/ie3/simona/agent/em/EmAgent.scala b/src/main/scala/edu/ie3/simona/agent/em/EmAgent.scala index 06a7bf598a..f280b676f6 100644 --- a/src/main/scala/edu/ie3/simona/agent/em/EmAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/em/EmAgent.scala @@ -197,7 +197,10 @@ object EmAgent { _ ! RequestFlexOptions(msg.tick) } - awaitingFlexOptions(emData, modelShell, newCore) + newCore.fold( + awaitingFlexOptions(emData, modelShell, _), + awaitingCompletions(emData, modelShell, _), + ) case Flex(_: IssueFlexControl) => // We got sent a flex control message instead of a flex request, @@ -359,7 +362,15 @@ object EmAgent { modelShell: EmModelShell, core: EmDataCore.AwaitingCompletions, ): Behavior[Request] = Behaviors.receiveMessagePartial { - // Completions and results + case result: FlexResult => + val updatedCore = core.handleResult(result) + + awaitingCompletions( + emData, + modelShell, + updatedCore, + ) + case completion: FlexCtrlCompletion => val updatedCore = core.handleCompletion(completion) @@ -385,34 +396,38 @@ object EmAgent { } + /** Completions have all been received, possibly send results and report to + * parent + */ private def sendCompletionCommunication( emData: EmData, modelShell: EmModelShell, inactiveCore: EmDataCore.Inactive, lastActiveTick: Long, ): Unit = { - // calc result - val result = inactiveCore.getResults + // Sum up resulting power, if applicable. + // After initialization, there are no results yet. + val maybeResult = inactiveCore.getResults .reduceOption { (power1, power2) => ApparentPower(power1.p + power2.p, power1.q + power2.q) } - .getOrElse( - ApparentPower( - zeroMW, - zeroMVAr, - ) - ) - emData.listener.foreach { - _ ! ParticipantResultEvent( - new EmResult( - lastActiveTick - .toDateTime(emData.simulationStartDate), - modelShell.uuid, - result.p.toMegawatts.asMegaWatt, - result.q.toMegavars.asMegaVar, + maybeResult.foreach { result => + emData.listener.foreach { + _ ! ParticipantResultEvent( + new EmResult( + lastActiveTick + .toDateTime(emData.simulationStartDate), + modelShell.uuid, + result.p.toMegawatts.asMegaWatt, + result.q.toMegavars.asMegaVar, + ) ) - ) + } + + emData.parentData.foreach { + _.emAgent ! FlexResult(modelShell.uuid, result) + } } emData.parentData.fold( @@ -423,7 +438,6 @@ object EmAgent { ), _.emAgent ! FlexCtrlCompletion( modelShell.uuid, - result, inactiveCore.hasFlexWithNext, inactiveCore.nextActiveTick, ), diff --git a/src/main/scala/edu/ie3/simona/agent/em/EmDataCore.scala b/src/main/scala/edu/ie3/simona/agent/em/EmDataCore.scala index 3b46b176ee..8c1470cc5d 100644 --- a/src/main/scala/edu/ie3/simona/agent/em/EmDataCore.scala +++ b/src/main/scala/edu/ie3/simona/agent/em/EmDataCore.scala @@ -6,11 +6,12 @@ package edu.ie3.simona.agent.em -import edu.ie3.simona.exceptions.CriticalFailureException +import edu.ie3.simona.agent.em.EmAgent.Actor +import edu.ie3.simona.agent.em.FlexCorrespondenceStore.WithTime import edu.ie3.simona.agent.participant.data.Data.PrimaryData.ApparentPower -import EmAgent.Actor -import FlexCorrespondenceStore.WithTime +import edu.ie3.simona.exceptions.CriticalFailureException import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage._ +import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.util.scala.collection.mutable.PriorityMultiBiSet import squants.Power @@ -178,8 +179,9 @@ object EmDataCore { * @param correspondences * The data structure storing received and sent flex messages with the * corresponding tick - * @param awaitedFlexOptions - * The set of model uuids, from which flex options are still expected + * @param awaitedConnectedAgents + * The set of model uuids, from which flex options or completions are still + * expected * @param activeTick * The currently active tick */ @@ -187,24 +189,28 @@ object EmDataCore { private val modelToActor: Map[UUID, Actor], private val activationQueue: PriorityMultiBiSet[Long, UUID], private val correspondences: FlexCorrespondenceStore, - private val awaitedFlexOptions: Set[UUID] = Set.empty, + private val awaitedConnectedAgents: Set[UUID] = Set.empty, activeTick: Long, ) { /** Removes and returns flex requests scheduled for the current tick, which - * can be sent out at the current moment. + * can be sent out at the current moment. Depending on the current tick, + * the next state of the [[EmAgent]] is chosen. During initialization, flex + * request, flex control and results are not expected, thus we change to + * [[AwaitingCompletions]] right away. * * @return * A tuple of a collection of agents scheduled for the current tick, and - * the updated [[AwaitingFlexOptions]] core + * either an updated [[AwaitingFlexOptions]] core or an + * [[AwaitingCompletions]] core if we're in initialization * @throws CriticalFailureException * on critical error */ - def takeNewFlexRequests(): (Iterable[Actor], AwaitingFlexOptions) = { + def takeNewFlexRequests(): ( + Iterable[Actor], + Either[AwaitingFlexOptions, AwaitingCompletions], + ) = { val toActivate = activationQueue.getAndRemoveSet(activeTick) - val newFlexOptionsCore = - copy(awaitedFlexOptions = awaitedFlexOptions.concat(toActivate)) - val actors = toActivate.map { modelUuid => modelToActor .getOrElse( @@ -215,7 +221,25 @@ object EmDataCore { ) } - (actors, newFlexOptionsCore) + val newCore = if (activeTick == INIT_SIM_TICK) { + Right( + AwaitingCompletions( + modelToActor, + activationQueue = activationQueue, + correspondences = correspondences, + awaitedCompletions = awaitedConnectedAgents.concat(toActivate), + activeTick = activeTick, + ) + ) + } else { + Left( + copy(awaitedConnectedAgents = + awaitedConnectedAgents.concat(toActivate) + ) + ) + } + + (actors, newCore) } /** Handles the retrieval of flex options sent by some connected agent for @@ -232,7 +256,8 @@ object EmDataCore { copy( correspondences = correspondences.updateFlexOptions(flexOptions, activeTick), - awaitedFlexOptions = awaitedFlexOptions.excl(flexOptions.modelUuid), + awaitedConnectedAgents = + awaitedConnectedAgents.excl(flexOptions.modelUuid), ) /** Checks whether all awaited flex options have been received and we can @@ -241,7 +266,7 @@ object EmDataCore { * @return * true if all awaited flex options have been received */ - def isComplete: Boolean = awaitedFlexOptions.isEmpty + def isComplete: Boolean = awaitedConnectedAgents.isEmpty /** Returns all flex options that are currently relevant, which can include * flex options received at an earlier tick @@ -389,6 +414,26 @@ object EmDataCore { activeTick: Long, ) { + /** Handles a result by some connected agent for the currently active tick. + * + * @param flexResult + * The received result + * @return + * The updated [[AwaitingCompletions]] core + */ + def handleResult(flexResult: FlexResult): AwaitingCompletions = { + val updatedCorrespondence = + correspondences.updateResult( + flexResult.modelUuid, + flexResult.result, + activeTick, + ) + + copy( + correspondences = updatedCorrespondence + ) + } + /** Tries to handle the completion of some connected agent for the currently * active tick. If completion is not valid, a [[CriticalFailureException]] * is thrown. @@ -412,20 +457,12 @@ object EmDataCore { completion.requestAtTick .foreach { activationQueue.set(_, completion.modelUuid) } - val updatedCorrespondence = - correspondences.updateResult( - completion.modelUuid, - completion.result, - activeTick, - ) - val updatedFlexWithNext = if (completion.requestAtNextActivation) flexWithNext.incl(completion.modelUuid) else flexWithNext copy( - correspondences = updatedCorrespondence, flexWithNext = updatedFlexWithNext, awaitedCompletions = awaitedCompletions.excl(completion.modelUuid), ) diff --git a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala index e9fef1ad20..f9e7944aaf 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala @@ -797,9 +797,13 @@ protected trait ParticipantAgentFundamentals[ ) .getOrElse((flexChangeIndicator.changesAtTick, stateDataWithResults)) - flexStateData.emAgent ! FlexCtrlCompletion( + flexStateData.emAgent ! FlexResult( baseStateData.modelUuid, result.primaryData.toApparentPower, + ) + + flexStateData.emAgent ! FlexCtrlCompletion( + baseStateData.modelUuid, flexChangeIndicator.changesAtNextActivation, nextActivation, ) diff --git a/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala b/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala index 812eafbfff..b66983f098 100644 --- a/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala +++ b/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala @@ -115,9 +115,9 @@ object FlexibilityMessage { final case class IssueNoControl(override val tick: Long) extends IssueFlexControl - /** Message sent by flex options providers indicating that the - * [[IssueFlexControl]] message has been handled and the flex communication - * for the current tick is completed. + /** Message sent by flex options providers that transports the result after + * flex control has been handled. Has to be sent before + * [[FlexCtrlCompletion]], but is not required during initialization. * * @param modelUuid * The UUID of the flex options provider asset model @@ -125,9 +125,21 @@ object FlexibilityMessage { * The apparent power that is produced/consumed by the flex options * provider, which can deviate from the set point communicated by a * [[IssueFlexControl]] message if it is not feasible. + */ + final case class FlexResult( + override val modelUuid: UUID, + result: ApparentPower, + ) extends FlexResponse + + /** Message sent by flex options providers indicating that the + * [[IssueFlexControl]] message has been handled and the flex communication + * for the current tick is completed. + * + * @param modelUuid + * The UUID of the flex options provider asset model * @param requestAtNextActivation - * Whether or not to request flex options at the very next activation of - * the receiving EM agent. This is the case if flex options change the very + * Whether to request flex options at the very next activation of the + * receiving EM agent. This is the case if flex options change the very * next second after the current tick. * @param requestAtTick * Optionally the tick at which flex options are foreseen to have changed, @@ -136,7 +148,6 @@ object FlexibilityMessage { */ final case class FlexCtrlCompletion( override val modelUuid: UUID, - result: ApparentPower, requestAtNextActivation: Boolean = false, requestAtTick: Option[Long] = None, ) extends FlexResponse diff --git a/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala b/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala index fb06c37e8d..7e901b48c6 100644 --- a/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala @@ -15,15 +15,16 @@ import edu.ie3.simona.event.ResultEvent.{ ParticipantResultEvent, } import edu.ie3.simona.event.notifier.NotifierConfig -import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage._ -import edu.ie3.simona.ontology.messages.flex.MinMaxFlexibilityMessage.ProvideMinMaxFlexOptions import edu.ie3.simona.ontology.messages.SchedulerMessage.{ Completion, ScheduleActivation, } +import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage._ +import edu.ie3.simona.ontology.messages.flex.MinMaxFlexibilityMessage.ProvideMinMaxFlexOptions import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage} import edu.ie3.simona.test.common.input.EmInputTestData import edu.ie3.simona.test.matchers.SquantsMatchers +import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK import edu.ie3.simona.util.TickUtil.TickLong import edu.ie3.util.TimeUtil import edu.ie3.util.quantities.QuantityMatchers.equalWithTolerance @@ -88,20 +89,47 @@ class EmAgentSpec val pvAgent = TestProbe[FlexRequest]("PvAgent") emAgent ! RegisterParticipant(pvInput.getUuid, pvAgent.ref, pvInput) - emAgent ! ScheduleFlexRequest(pvInput.getUuid, 0) + emAgent ! ScheduleFlexRequest(pvInput.getUuid, INIT_SIM_TICK) val sa1 = scheduler.expectMessageType[ScheduleActivation] - sa1.tick shouldBe 0 + sa1.tick shouldBe INIT_SIM_TICK sa1.unlockKey shouldBe None val emAgentActivation = sa1.actor val evcsAgent = TestProbe[FlexRequest]("EvcsAgent") emAgent ! RegisterParticipant(evcsInput.getUuid, evcsAgent.ref, evcsInput) - emAgent ! ScheduleFlexRequest(evcsInput.getUuid, 0) + emAgent ! ScheduleFlexRequest(evcsInput.getUuid, INIT_SIM_TICK) + + // no additional scheduling message, since tick -1 has already been scheduled + scheduler.expectNoMessage() + + /* TICK -1 */ + emAgentActivation ! Activation(INIT_SIM_TICK) + + // expect flex requests + pvAgent.expectMessage(RequestFlexOptions(INIT_SIM_TICK)) + evcsAgent.expectMessage(RequestFlexOptions(INIT_SIM_TICK)) + + // receive flex completions + emAgent ! FlexCtrlCompletion( + modelUuid = pvInput.getUuid, + requestAtTick = Some(0), + ) - // no additional scheduling message, since tick 0 has already been scheduled scheduler.expectNoMessage() + emAgent ! FlexCtrlCompletion( + modelUuid = evcsInput.getUuid, + requestAtTick = Some(0), + ) + + // expect no results for init + resultListener.expectNoMessage() + // expect completion from EmAgent + scheduler.expectMessage( + Completion(emAgentActivation, Some(0)) + ) + /* TICK 0 */ emAgentActivation ! Activation(0) @@ -129,9 +157,12 @@ class EmAgentSpec // receive flex control messages pvAgent.expectMessage(IssueNoControl(0)) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexResult( modelUuid = pvInput.getUuid, result = ApparentPower(Kilowatts(-5d), Kilovars(-0.5d)), + ) + emAgent ! FlexCtrlCompletion( + modelUuid = pvInput.getUuid, requestAtTick = Some(600), ) @@ -141,9 +172,12 @@ class EmAgentSpec case IssuePowerControl(0, setPower) => setPower should approximate(Kilowatts(5.0)) } - emAgent ! FlexCtrlCompletion( + emAgent ! FlexResult( modelUuid = evcsInput.getUuid, result = ApparentPower(Kilowatts(5d), Kilovars(0.1d)), + ) + emAgent ! FlexCtrlCompletion( + modelUuid = evcsInput.getUuid, requestAtTick = Some(300), ) @@ -184,11 +218,11 @@ class EmAgentSpec pvAgent.expectNoMessage() - emAgent ! - FlexCtrlCompletion( - evcsInput.getUuid, - ApparentPower(Kilowatts(0d), Kilovars(0d)), - ) + emAgent ! FlexResult( + modelUuid = evcsInput.getUuid, + result = ApparentPower(Kilowatts(0d), Kilovars(0d)), + ) + emAgent ! FlexCtrlCompletion(modelUuid = evcsInput.getUuid) // expect correct results resultListener.expectMessageType[ParticipantResultEvent] match { @@ -236,6 +270,8 @@ class EmAgentSpec // no additional scheduling message, since tick 0 has already been scheduled scheduler.expectNoMessage() + // We skip initialization here for simplicity + /* TICK 0 */ emAgentActivation ! Activation(0) @@ -269,17 +305,24 @@ class EmAgentSpec } // send completions - emAgent ! FlexCtrlCompletion( + emAgent ! FlexResult( modelUuid = pvInput.getUuid, result = ApparentPower(Kilowatts(-5d), Kilovars(-0.5d)), + ) + emAgent ! FlexCtrlCompletion( + modelUuid = pvInput.getUuid, requestAtTick = Some(300), ) + emAgent ! FlexResult( + modelUuid = evcsInput.getUuid, + result = ApparentPower(Kilowatts(5d), Kilovars(0.1d)), + ) + scheduler.expectNoMessage() emAgent ! FlexCtrlCompletion( modelUuid = evcsInput.getUuid, - result = ApparentPower(Kilowatts(5d), Kilovars(0.1d)), requestAtTick = Some(600), ) @@ -316,9 +359,13 @@ class EmAgentSpec // receive flex control messages pvAgent.expectMessage(IssueNoControl(300)) + emAgent ! FlexResult( + modelUuid = pvInput.getUuid, + result = ApparentPower(Kilowatts(-3d), Kilovars(-0.06d)), + ) + emAgent ! FlexCtrlCompletion( - pvInput.getUuid, - ApparentPower(Kilowatts(-3d), Kilovars(-0.06d)), + modelUuid = pvInput.getUuid ) // evcs is now sent control too @@ -329,9 +376,12 @@ class EmAgentSpec scheduler.expectNoMessage() + emAgent ! FlexResult( + modelUuid = evcsInput.getUuid, + result = ApparentPower(Kilowatts(3d), Kilovars(0.06d)), + ) emAgent ! FlexCtrlCompletion( - evcsInput.getUuid, - ApparentPower(Kilowatts(3d), Kilovars(0.06d)), + modelUuid = evcsInput.getUuid, requestAtTick = Some(800), // should overwrite tick 600 ) @@ -382,6 +432,8 @@ class EmAgentSpec // no additional scheduling message, since tick 0 has already been scheduled scheduler.expectNoMessage() + // We skip initialization here for simplicity + /* TICK 0 */ emAgentActivation ! Activation(0) @@ -416,17 +468,24 @@ class EmAgentSpec } // send completions + emAgent ! FlexResult( + modelUuid = pvInput.getUuid, + result = ApparentPower(Kilowatts(-5d), Kilovars(-0.5d)), + ) emAgent ! FlexCtrlCompletion( - pvInput.getUuid, - ApparentPower(Kilowatts(-5d), Kilovars(-0.5d)), + modelUuid = pvInput.getUuid, requestAtTick = Some(300), ) + emAgent ! FlexResult( + modelUuid = evcsInput.getUuid, + result = ApparentPower(Kilowatts(5d), Kilovars(0.1d)), + ) + scheduler.expectNoMessage() emAgent ! FlexCtrlCompletion( - evcsInput.getUuid, - ApparentPower(Kilowatts(5d), Kilovars(0.1d)), + modelUuid = evcsInput.getUuid, requestAtNextActivation = true, // sending ChangingFlexOptions indicator requestAtTick = Some(600), ) @@ -473,9 +532,12 @@ class EmAgentSpec // FLEX CONTROL pvAgent.expectMessage(IssueNoControl(300)) + emAgent ! FlexResult( + modelUuid = pvInput.getUuid, + result = ApparentPower(Kilowatts(-3d), Kilovars(-0.06d)), + ) emAgent ! FlexCtrlCompletion( - pvInput.getUuid, - ApparentPower(Kilowatts(-3d), Kilovars(-0.06d)), + modelUuid = pvInput.getUuid ) evcsAgent.expectMessageType[IssuePowerControl] match { @@ -485,9 +547,12 @@ class EmAgentSpec scheduler.expectNoMessage() + emAgent ! FlexResult( + modelUuid = evcsInput.getUuid, + result = ApparentPower(Kilowatts(3d), Kilovars(0.06d)), + ) emAgent ! FlexCtrlCompletion( - evcsInput.getUuid, // revoking tick 600 - ApparentPower(Kilowatts(3d), Kilovars(0.06d)), + modelUuid = evcsInput.getUuid // revoking tick 600 ) // expect correct results @@ -525,7 +590,7 @@ class EmAgentSpec val pvAgent = TestProbe[FlexRequest]("PvAgent") emAgent ! RegisterParticipant(pvInput.getUuid, pvAgent.ref, pvInput) - emAgent ! ScheduleFlexRequest(pvInput.getUuid, 0) + emAgent ! ScheduleFlexRequest(pvInput.getUuid, INIT_SIM_TICK) val emAgentFlex = parentEmAgent.expectMessageType[RegisterParticipant] match { @@ -534,15 +599,47 @@ class EmAgentSpec inputModel shouldBe emInput participant } - parentEmAgent.expectMessage(ScheduleFlexRequest(emInput.getUuid, 0)) + parentEmAgent.expectMessage( + ScheduleFlexRequest(emInput.getUuid, INIT_SIM_TICK) + ) val evcsAgent = TestProbe[FlexRequest]("EvcsAgent") emAgent ! RegisterParticipant(evcsInput.getUuid, evcsAgent.ref, evcsInput) - emAgent ! ScheduleFlexRequest(evcsInput.getUuid, 0) + emAgent ! ScheduleFlexRequest(evcsInput.getUuid, INIT_SIM_TICK) + + // no additional scheduling message, since tick -1 has already been scheduled + parentEmAgent.expectNoMessage() + + /* TICK -1 */ + emAgentFlex ! RequestFlexOptions(INIT_SIM_TICK) + + // expect flex requests + pvAgent.expectMessage(RequestFlexOptions(INIT_SIM_TICK)) + evcsAgent.expectMessage(RequestFlexOptions(INIT_SIM_TICK)) + + // receive flex completions + emAgent ! FlexCtrlCompletion( + modelUuid = pvInput.getUuid, + requestAtTick = Some(0), + ) - // no additional scheduling message, since tick 0 has already been scheduled parentEmAgent.expectNoMessage() + emAgent ! FlexCtrlCompletion( + modelUuid = evcsInput.getUuid, + requestAtTick = Some(0), + ) + + // expect no results for init + resultListener.expectNoMessage() + // expect completion from EmAgent + parentEmAgent.expectMessage( + FlexCtrlCompletion( + modelUuid = emInput.getUuid, + requestAtTick = Some(0), + ) + ) + /* TICK 0 */ emAgentFlex ! RequestFlexOptions(0) @@ -597,9 +694,12 @@ class EmAgentSpec // expect issue power control pvAgent.expectMessage(IssueNoControl(0)) + emAgent ! FlexResult( + modelUuid = pvInput.getUuid, + result = ApparentPower(Kilowatts(-5), Kilovars(-0.5)), + ) emAgent ! FlexCtrlCompletion( - pvInput.getUuid, - ApparentPower(Kilowatts(-5), Kilovars(-0.5)), + modelUuid = pvInput.getUuid, requestAtTick = Some(600), ) @@ -610,9 +710,12 @@ class EmAgentSpec parentEmAgent.expectNoMessage() + emAgent ! FlexResult( + modelUuid = evcsInput.getUuid, + result = ApparentPower(Kilowatts(11), Kilovars(1.1)), + ) emAgent ! FlexCtrlCompletion( - evcsInput.getUuid, - ApparentPower(Kilowatts(11), Kilovars(1.1)), + modelUuid = evcsInput.getUuid, requestAtTick = Some(300), ) @@ -625,20 +728,20 @@ class EmAgentSpec emResult.getQ should equalWithTolerance(0.0006d.asMegaVar) } - parentEmAgent.expectMessageType[FlexCtrlCompletion] match { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => + parentEmAgent.expectMessageType[FlexResult] match { + case FlexResult(modelUuid, result) => modelUuid shouldBe emInput.getUuid result.p should approximate(Kilowatts(6)) result.q should approximate(Kilovars(0.6)) - requestAtNextActivation shouldBe false - requestAtTick shouldBe Some(300) } + parentEmAgent.expectMessage( + FlexCtrlCompletion( + modelUuid = emInput.getUuid, + requestAtTick = Some(300), + ) + ) + /* TICK 150 */ // The mock parent EM now acts as if the situation changed before tick 300, // so that the flex control changes before new flex option calculations are due @@ -657,9 +760,12 @@ class EmAgentSpec parentEmAgent.expectNoMessage() + emAgent ! FlexResult( + modelUuid = evcsInput.getUuid, + result = ApparentPower(Kilowatts(5.0), Kilovars(0.5)), + ) emAgent ! FlexCtrlCompletion( - evcsInput.getUuid, - ApparentPower(Kilowatts(5.0), Kilovars(0.5)), + modelUuid = evcsInput.getUuid, requestAtTick = Some(700), ) @@ -672,19 +778,18 @@ class EmAgentSpec emResult.getQ should equalWithTolerance(0d.asMegaVar) } - parentEmAgent.expectMessageType[FlexCtrlCompletion] match { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => + parentEmAgent.expectMessageType[FlexResult] match { + case FlexResult(modelUuid, result) => modelUuid shouldBe emInput.getUuid result.p should approximate(Kilowatts(0)) result.q should approximate(Kilovars(0)) - requestAtNextActivation shouldBe false - requestAtTick shouldBe Some(600) } + parentEmAgent.expectMessage( + FlexCtrlCompletion( + modelUuid = emInput.getUuid, + requestAtTick = Some(600), + ) + ) } } diff --git a/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala index 3e3a9c7a2c..286e7806cb 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala @@ -1308,19 +1308,17 @@ class EvcsAgentModelCalculationSpec // next potential activation at fully charged battery: // net power = 12.961kW * 0.92 = 11.92412kW // time to charge fully ~= 16.7727262054h = 60382 ticks (rounded) - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe evcsInputModelQv.getUuid - result.p should approximate(Kilowatts(0)) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe false - requestAtTick shouldBe Some(900) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe evcsInputModelQv.getUuid + result.p should approximate(Kilowatts(0)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModelQv.getUuid, + requestAtTick = Some(900), + ) + ) // results arrive after next activation resultListener.expectNoMessage() @@ -1368,28 +1366,27 @@ class EvcsAgentModelCalculationSpec emAgent.send(evcsAgent, IssueNoControl(900)) // at 4500 ev is departing - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe evcsInputModelQv.getUuid - result.p should approximate( - Kilowatts( - ev900 - .unwrap() - .getSRatedAC - .to(PowerSystemUnits.KILOWATT) - .getValue - .doubleValue - ) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe evcsInputModelQv.getUuid + result.p should approximate( + Kilowatts( + ev900 + .unwrap() + .getSRatedAC + .to(PowerSystemUnits.KILOWATT) + .getValue + .doubleValue ) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe true - requestAtTick shouldBe Some(4500) + ) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModelQv.getUuid, + requestAtNextActivation = true, + requestAtTick = Some(4500), + ) + ) // result of tick 0 resultListener.expectMsgPF() { @@ -1488,19 +1485,18 @@ class EvcsAgentModelCalculationSpec // we currently have an empty battery in ev4500 // time to charge to minimal soc ~= 1.45454545455h = 5236 ticks (rounded) from now // current tick is 4500, thus: 4500 + 5236 = 9736 - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe evcsInputModelQv.getUuid - result.p should approximate(Kilowatts(11)) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe true - requestAtTick shouldBe Some(9736) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe evcsInputModelQv.getUuid + result.p should approximate(Kilowatts(11)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModelQv.getUuid, + requestAtNextActivation = true, + requestAtTick = Some(9736), + ) + ) // already sent out after EV departed resultListener.expectNoMessage() @@ -1541,20 +1537,18 @@ class EvcsAgentModelCalculationSpec // ev4500 is now at 16 kWh // time to charge fully = 6.4 h = 23040 ticks from now // current tick is 9736, thus: 9736 + 23040 = 32776 - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe evcsInputModelQv.getUuid - result.p should approximate(Kilowatts(10)) - result.q should approximate(Megavars(0)) - // since battery is still below lowest soc, it's still considered empty - requestAtNextActivation shouldBe true - requestAtTick shouldBe Some(11700) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe evcsInputModelQv.getUuid + result.p should approximate(Kilowatts(10)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModelQv.getUuid, + requestAtNextActivation = true, + requestAtTick = Some(11700), + ) + ) resultListener.expectMsgPF() { case ParticipantResultEvent(result: EvResult) => @@ -1633,20 +1627,18 @@ class EvcsAgentModelCalculationSpec // ev4500: time to charge fully ~= 7.3180556 h = 26345 ticks from now // ev11700: time to charge fully = 5.8 h = 20880 ticks from now // current tick is 11700, thus: 11700 + 20880 = 32580 - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe evcsInputModelQv.getUuid - result.p should approximate(Kilowatts(16)) - result.q should approximate(Megavars(0)) - // since battery is still below lowest soc, it's still considered empty - requestAtNextActivation shouldBe true - requestAtTick shouldBe Some(32580) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe evcsInputModelQv.getUuid + result.p should approximate(Kilowatts(16)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModelQv.getUuid, + requestAtNextActivation = true, + requestAtTick = Some(32580), + ) + ) resultListener.expectMsgPF() { case ParticipantResultEvent(result: EvResult) => @@ -1707,19 +1699,17 @@ class EvcsAgentModelCalculationSpec // ev4500: time to discharge to lowest soc ~= 1.9455556 h = 7004 ticks from now // ev11700: time to discharge to lowest soc ~= 1.4 h = 5040 ticks from now // current tick is 18000, thus: 18000 + 5040 = 23040 - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe evcsInputModelQv.getUuid - result.p should approximate(Kilowatts(-20)) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe false - requestAtTick shouldBe Some(23040) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe evcsInputModelQv.getUuid + result.p should approximate(Kilowatts(-20)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModelQv.getUuid, + requestAtTick = Some(23040), + ) + ) Range(0, 2) .map { _ => @@ -1791,19 +1781,17 @@ class EvcsAgentModelCalculationSpec // ev4500 is now at 21.455556 kWh, ev11700 at 11.6 kWh (lowest soc) // ev4500: time to discharge to lowest soc = 0.5455556 h = 1964 ticks from now // current tick is 18864, thus: 23040 + 1964 = 25004 - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe evcsInputModelQv.getUuid - result.p should approximate(Kilowatts(-10)) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe false - requestAtTick shouldBe Some(25004) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe evcsInputModelQv.getUuid + result.p should approximate(Kilowatts(-10)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModelQv.getUuid, + requestAtTick = Some(25004), + ) + ) Range(0, 2) .map { _ => @@ -1866,19 +1854,16 @@ class EvcsAgentModelCalculationSpec evService.expectNoMessage() // no new activation - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe evcsInputModelQv.getUuid - result.p should approximate(Kilowatts(0)) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe false - requestAtTick shouldBe None + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe evcsInputModelQv.getUuid + result.p should approximate(Kilowatts(0)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModelQv.getUuid + ) + ) Range(0, 2) .map { _ => @@ -1984,20 +1969,18 @@ class EvcsAgentModelCalculationSpec // ev11700: time to charge fully = 16 h = 57600 ticks from now // current tick is 36000, thus: 36000 + 57600 = 93600 // BUT: departing tick 72000 is earlier - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe evcsInputModelQv.getUuid - result.p should approximate(Kilowatts(4)) - result.q should approximate(Megavars(0)) - // since we're starting from lowest again - requestAtNextActivation shouldBe true - requestAtTick shouldBe Some(72000) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe evcsInputModelQv.getUuid + result.p should approximate(Kilowatts(4)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = evcsInputModelQv.getUuid, + requestAtNextActivation = true, + requestAtTick = Some(72000), + ) + ) // expect no more messages after completion of initialization scheduler.expectNoMessage() diff --git a/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala index d7c8378ce5..d9eeece2a4 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala @@ -362,19 +362,18 @@ class StorageAgentModelCalculationSpec // next potential activation at fully charged battery: // net power = 12.961kW * 0.92 = 11.92412kW // time to charge fully ~= 16.7727262054h = 60382 ticks (rounded) - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe storageInputQv.getUuid - result.p should approximate(pMax) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe true - requestAtTick shouldBe Some(60382) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe storageInputQv.getUuid + result.p should approximate(pMax) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = storageInputQv.getUuid, + requestAtNextActivation = true, + requestAtTick = Some(60382), + ) + ) resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => @@ -422,19 +421,17 @@ class StorageAgentModelCalculationSpec // net power = 9kW * 0.92 = 8.28kW // time to charge fully ~= 12.6337004831h = 45481 ticks (rounded) from now // current tick is 28800, thus: 28800 + 45481 = 74281 - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe storageInputQv.getUuid - result.p should approximate(Kilowatts(9)) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe false - requestAtTick shouldBe Some(74281) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe storageInputQv.getUuid + result.p should approximate(Kilowatts(9)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = storageInputQv.getUuid, + requestAtTick = Some(74281), + ) + ) resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => @@ -464,19 +461,17 @@ class StorageAgentModelCalculationSpec // net power = -12.961kW / 0.92 = -14.08804348kW // time to discharge until lowest energy (0 kWh) ~= 7.946664856h = 28608 ticks (rounded) from now // current tick is 36000, thus: 36000 + 28608 = 64608 - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe storageInputQv.getUuid - result.p should approximate(pMax * -1) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe false - requestAtTick shouldBe Some(64608) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe storageInputQv.getUuid + result.p should approximate(pMax * -1) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = storageInputQv.getUuid, + requestAtTick = Some(64608), + ) + ) resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => @@ -500,19 +495,17 @@ class StorageAgentModelCalculationSpec // net power = 12 * 0.92 = 11.04 kW // time to charge until full ~= 10.52745715h = 37899 ticks (rounded) from now // current tick is 43200, thus: 43200 + 37899 = 81099 - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe storageInputQv.getUuid - result.p should approximate(Kilowatts(12)) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe false - requestAtTick shouldBe Some(81099) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe storageInputQv.getUuid + result.p should approximate(Kilowatts(12)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = storageInputQv.getUuid, + requestAtTick = Some(81099), + ) + ) resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => @@ -560,19 +553,18 @@ class StorageAgentModelCalculationSpec // net power = -12 / 0.92 = -13.04347826 kW // time to discharge until empty ~= 15.33333333h = 55200 ticks from now // current tick is 79688, thus: 81099 + 55200 = 136299 - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe storageInputQv.getUuid - result.p should approximate(Kilowatts(-12)) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe true - requestAtTick shouldBe Some(136299) + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe storageInputQv.getUuid + result.p should approximate(Kilowatts(-12)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = storageInputQv.getUuid, + requestAtNextActivation = true, + requestAtTick = Some(136299), + ) + ) resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => @@ -615,19 +607,16 @@ class StorageAgentModelCalculationSpec emAgent.send(storageAgent, IssuePowerControl(136299, Kilowatts(0d))) // we're not charging or discharging, no new expected tick - emAgent.expectMsgPF() { - case FlexCtrlCompletion( - modelUuid, - result, - requestAtNextActivation, - requestAtTick, - ) => - modelUuid shouldBe storageInputQv.getUuid - result.p should approximate(Kilowatts(0)) - result.q should approximate(Megavars(0)) - requestAtNextActivation shouldBe false - requestAtTick shouldBe None + emAgent.expectMsgPF() { case FlexResult(modelUuid, result) => + modelUuid shouldBe storageInputQv.getUuid + result.p should approximate(Kilowatts(0)) + result.q should approximate(Megavars(0)) } + emAgent.expectMsg( + FlexCtrlCompletion( + modelUuid = storageInputQv.getUuid + ) + ) resultListener.expectMsgPF() { case ParticipantResultEvent(result: StorageResult) => From 999273cf5181a751d6c22900c8f566fd80c43cd6 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Tue, 3 Sep 2024 09:53:30 +0200 Subject: [PATCH 02/14] Adapting message documentation Signed-off-by: Sebastian Peter --- .../simona/ontology/messages/flex/FlexibilityMessage.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala b/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala index b66983f098..1ddc561443 100644 --- a/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala +++ b/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala @@ -70,8 +70,9 @@ object FlexibilityMessage { scheduleKey: Option[ScheduleKey] = None, ) extends FlexResponse - /** Message that requests flex options from a flex options provider for given - * tick + /** Message that activates a connected agent, usually in order to requests + * flex options for given tick. During initialization, no flex option + * provision is expected. * * @param tick * The tick to request flex options for From fdb836bf4667219e3ca2cb787396122a2d3f8101 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Tue, 3 Sep 2024 12:49:38 +0200 Subject: [PATCH 03/14] Changelog format Signed-off-by: Sebastian Peter --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab479e850e..50f02e4302 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update RTD references and bibliography [#868](https://github.com/ie3-institute/simona/issues/868) - Add gradle application plugin for command line execution with gradle run [#890](https://github.com/ie3-institute/simona/issues/890) - Additional tests to check flexibility options of thermal house and storage [#729](https://github.com/ie3-institute/simona/issues/729) -- EmAgents should be able to handle initialization [#945](https://github.com/ie3-institute/simona/issues/945) +- EmAgents should be able to handle initialization [#945](https://github.com/ie3-institute/simona/issues/945) ### Changed - Adapted to changed data source in PSDM [#435](https://github.com/ie3-institute/simona/issues/435) From 9f8a46abe11d70b0bf2f51be45f3afa58e8a5005 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Tue, 3 Sep 2024 12:48:58 +0200 Subject: [PATCH 04/14] Refactoring EM messages Signed-off-by: Sebastian Peter --- CHANGELOG.md | 1 + docs/readthedocs/models/em.md | 6 +- docs/uml/protocol/em/ControlledEm.puml | 10 +-- docs/uml/protocol/em/UncontrolledEm.puml | 4 +- .../edu/ie3/simona/agent/em/EmAgent.scala | 8 +- .../edu/ie3/simona/agent/em/EmDataCore.scala | 2 +- .../agent/participant/ParticipantAgent.scala | 6 +- .../ParticipantAgentFundamentals.scala | 2 +- .../messages/flex/FlexibilityMessage.scala | 11 ++- .../edu/ie3/simona/agent/em/EmAgentSpec.scala | 78 +++++++++---------- .../EvcsAgentModelCalculationSpec.scala | 36 ++++----- .../StorageAgentModelCalculationSpec.scala | 20 ++--- 12 files changed, 92 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50f02e4302..052527a251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,6 +79,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Updated `Gradle` to version V8.10 [#829](https://github.com/ie3-institute/simona/issues/829) - Updated AUTHORS.md [#905](https://github.com/ie3-institute/simona/issues/905) - Rewrote BMModelTest from groovy to scala [#646](https://github.com/ie3-institute/simona/issues/646) +- Refactoring EM messages [#947](https://github.com/ie3-institute/simona/issues/947) ### Fixed - Removed a repeated line in the documentation of vn_simona config [#658](https://github.com/ie3-institute/simona/issues/658) diff --git a/docs/readthedocs/models/em.md b/docs/readthedocs/models/em.md index f59f96a036..3b91f52657 100644 --- a/docs/readthedocs/models/em.md +++ b/docs/readthedocs/models/em.md @@ -6,11 +6,11 @@ Energy Management Agents (EmAgents) control power feed-in and load of system par ## Protocol -During simulation, EmAgents send `RequestFlexOptions` and `IssueFlexControl` messages and receive `ProvideFlexOptions` and `FlexCompletion` messages. -After having been requested to calculate flex options via `RequestFlexOptions`, controllable assets send back their flex options to the controlling unit using `ProvideFlexOptions`. +During simulation, EmAgents send `FlexActivation` and `IssueFlexControl` messages and receive `ProvideFlexOptions` and `FlexCompletion` messages. +After having been requested to calculate flex options via `FlexActivation`, controllable assets send back their flex options to the controlling unit using `ProvideFlexOptions`. Eventually the controlling EmAgent responds with some type of `IssueFlexControl` messages, setting a power set point for operation. The asset then tries to realize the set power as best as it can and replies with a `FlexCompletion` messages. -If an EmAgent is itself controlled by another EmAgent, it also behaves like a system participant (sends `RequestFlexOptions` and `IssueFlexControl` messages etc.). +If an EmAgent is itself controlled by another EmAgent, it also behaves like a system participant (sends `FlexActivation` and `IssueFlexControl` messages etc.). Every EmAgent aggregates flex options and power of its connected assets and disaggregates flex control among the connected assets. diff --git a/docs/uml/protocol/em/ControlledEm.puml b/docs/uml/protocol/em/ControlledEm.puml index 185bee971a..7310a5b7c5 100644 --- a/docs/uml/protocol/em/ControlledEm.puml +++ b/docs/uml/protocol/em/ControlledEm.puml @@ -54,13 +54,13 @@ deactivate WeatherService Scheduler -> EmAgent1: Activation(tick=0) activate EmAgent1 -EmAgent1 -> EmAgent2: RequestFlexOptions(tick=0) +EmAgent1 -> EmAgent2: FlexActivation(tick=0) activate EmAgent2 -EmAgent2 -> StorageAgent: RequestFlexOptions(tick=0) +EmAgent2 -> StorageAgent: FlexActivation(tick=0) activate StorageAgent -EmAgent2 -> PvAgent: RequestFlexOptions(tick=0) +EmAgent2 -> PvAgent: FlexActivation(tick=0) activate PvAgent PvAgent -> EmAgent2: ProvideFlexOptions @@ -101,10 +101,10 @@ deactivate EmAgent1 Scheduler -> EmAgent1: Activation(tick=1805) activate EmAgent1 -EmAgent1 -> EmAgent2: RequestFlexOptions(tick=1805) +EmAgent1 -> EmAgent2: FlexActivation(tick=1805) activate EmAgent2 -EmAgent2 -> StorageAgent: RequestFlexOptions(tick=1805) +EmAgent2 -> StorageAgent: FlexActivation(tick=1805) activate StorageAgent StorageAgent -> EmAgent2: ProvideFlexOptions diff --git a/docs/uml/protocol/em/UncontrolledEm.puml b/docs/uml/protocol/em/UncontrolledEm.puml index 53f27b0e6d..fc3e2dd3ef 100644 --- a/docs/uml/protocol/em/UncontrolledEm.puml +++ b/docs/uml/protocol/em/UncontrolledEm.puml @@ -50,10 +50,10 @@ deactivate WeatherService Scheduler -> EmAgent: Activation(tick=0) activate EmAgent -EmAgent -> StorageAgent: RequestFlexOptions(tick=0) +EmAgent -> StorageAgent: FlexActivation(tick=0) activate StorageAgent -EmAgent -> PvAgent: RequestFlexOptions(tick=0) +EmAgent -> PvAgent: FlexActivation(tick=0) activate PvAgent PvAgent -> EmAgent: ProvideFlexOptions diff --git a/src/main/scala/edu/ie3/simona/agent/em/EmAgent.scala b/src/main/scala/edu/ie3/simona/agent/em/EmAgent.scala index f280b676f6..fc95473bf8 100644 --- a/src/main/scala/edu/ie3/simona/agent/em/EmAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/em/EmAgent.scala @@ -191,10 +191,10 @@ object EmAgent { val flexOptionsCore = core.activate(msg.tick) msg match { - case Flex(_: RequestFlexOptions) | EmActivation(_) => + case Flex(_: FlexActivation) | EmActivation(_) => val (toActivate, newCore) = flexOptionsCore.takeNewFlexRequests() toActivate.foreach { - _ ! RequestFlexOptions(msg.tick) + _ ! FlexActivation(msg.tick) } newCore.fold( @@ -371,7 +371,7 @@ object EmAgent { updatedCore, ) - case completion: FlexCtrlCompletion => + case completion: FlexCompletion => val updatedCore = core.handleCompletion(completion) updatedCore @@ -436,7 +436,7 @@ object EmAgent { schedulerData.activationAdapter, inactiveCore.nextActiveTick, ), - _.emAgent ! FlexCtrlCompletion( + _.emAgent ! FlexCompletion( modelShell.uuid, inactiveCore.hasFlexWithNext, inactiveCore.nextActiveTick, diff --git a/src/main/scala/edu/ie3/simona/agent/em/EmDataCore.scala b/src/main/scala/edu/ie3/simona/agent/em/EmDataCore.scala index 8c1470cc5d..9cd9070de8 100644 --- a/src/main/scala/edu/ie3/simona/agent/em/EmDataCore.scala +++ b/src/main/scala/edu/ie3/simona/agent/em/EmDataCore.scala @@ -446,7 +446,7 @@ object EmDataCore { * on critical error */ def handleCompletion( - completion: FlexCtrlCompletion + completion: FlexCompletion ): AwaitingCompletions = { if (!awaitedCompletions.contains(completion.modelUuid)) throw new CriticalFailureException( diff --git a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala index 8bfac96858..70ce7c2d09 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala @@ -49,7 +49,7 @@ import edu.ie3.simona.ontology.messages.Activation import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage.{ FlexResponse, IssueFlexControl, - RequestFlexOptions, + FlexActivation, } import edu.ie3.simona.ontology.messages.services.ServiceMessage.RegistrationResponseMessage.RegistrationSuccessfulMessage import edu.ie3.simona.ontology.messages.services.ServiceMessage.{ @@ -221,7 +221,7 @@ abstract class ParticipantAgent[ finalizeTickAfterPF(baseStateData, tick) case Event( - RequestFlexOptions(tick), + FlexActivation(tick), baseStateData: ParticipantModelBaseStateData[PD, CD, MS, M], ) => val expectedSenders = baseStateData.foreseenDataTicks @@ -336,7 +336,7 @@ abstract class ParticipantAgent[ )(stateData.baseStateData.outputConfig) case Event( - RequestFlexOptions(tick), + FlexActivation(tick), stateData: DataCollectionStateData[PD], ) => checkForExpectedDataAndChangeState( diff --git a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala index f9e7944aaf..ee2d4941ff 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgentFundamentals.scala @@ -802,7 +802,7 @@ protected trait ParticipantAgentFundamentals[ result.primaryData.toApparentPower, ) - flexStateData.emAgent ! FlexCtrlCompletion( + flexStateData.emAgent ! FlexCompletion( baseStateData.modelUuid, flexChangeIndicator.changesAtNextActivation, nextActivation, diff --git a/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala b/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala index 1ddc561443..9a946de85e 100644 --- a/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala +++ b/src/main/scala/edu/ie3/simona/ontology/messages/flex/FlexibilityMessage.scala @@ -77,12 +77,11 @@ object FlexibilityMessage { * @param tick * The tick to request flex options for */ - final case class RequestFlexOptions(override val tick: Long) - extends FlexRequest + final case class FlexActivation(override val tick: Long) extends FlexRequest /** Message that provides flex options to an * [[edu.ie3.simona.agent.em.EmAgent]] after they have been requested via - * [[RequestFlexOptions]] + * [[FlexActivation]] */ trait ProvideFlexOptions extends FlexResponse @@ -117,8 +116,8 @@ object FlexibilityMessage { extends IssueFlexControl /** Message sent by flex options providers that transports the result after - * flex control has been handled. Has to be sent before - * [[FlexCtrlCompletion]], but is not required during initialization. + * flex control has been handled. Has to be sent before [[FlexCompletion]], + * but is not required during initialization. * * @param modelUuid * The UUID of the flex options provider asset model @@ -147,7 +146,7 @@ object FlexibilityMessage { * i.e. the tick at which the flex options provider would like to be * activated at the latest. */ - final case class FlexCtrlCompletion( + final case class FlexCompletion( override val modelUuid: UUID, requestAtNextActivation: Boolean = false, requestAtTick: Option[Long] = None, diff --git a/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala b/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala index 7e901b48c6..b6157eac06 100644 --- a/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala @@ -107,18 +107,18 @@ class EmAgentSpec emAgentActivation ! Activation(INIT_SIM_TICK) // expect flex requests - pvAgent.expectMessage(RequestFlexOptions(INIT_SIM_TICK)) - evcsAgent.expectMessage(RequestFlexOptions(INIT_SIM_TICK)) + pvAgent.expectMessage(FlexActivation(INIT_SIM_TICK)) + evcsAgent.expectMessage(FlexActivation(INIT_SIM_TICK)) // receive flex completions - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = pvInput.getUuid, requestAtTick = Some(0), ) scheduler.expectNoMessage() - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = evcsInput.getUuid, requestAtTick = Some(0), ) @@ -134,8 +134,8 @@ class EmAgentSpec emAgentActivation ! Activation(0) // expect flex requests - pvAgent.expectMessage(RequestFlexOptions(0)) - evcsAgent.expectMessage(RequestFlexOptions(0)) + pvAgent.expectMessage(FlexActivation(0)) + evcsAgent.expectMessage(FlexActivation(0)) // send flex options emAgent ! ProvideMinMaxFlexOptions( @@ -161,7 +161,7 @@ class EmAgentSpec modelUuid = pvInput.getUuid, result = ApparentPower(Kilowatts(-5d), Kilovars(-0.5d)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = pvInput.getUuid, requestAtTick = Some(600), ) @@ -176,7 +176,7 @@ class EmAgentSpec modelUuid = evcsInput.getUuid, result = ApparentPower(Kilowatts(5d), Kilovars(0.1d)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = evcsInput.getUuid, requestAtTick = Some(300), ) @@ -203,7 +203,7 @@ class EmAgentSpec // thus 1 does not get activated pvAgent.expectNoMessage() - evcsAgent.expectMessage(RequestFlexOptions(300)) + evcsAgent.expectMessage(FlexActivation(300)) // send flex options again, ev is fully charged emAgent ! ProvideMinMaxFlexOptions( @@ -222,7 +222,7 @@ class EmAgentSpec modelUuid = evcsInput.getUuid, result = ApparentPower(Kilowatts(0d), Kilovars(0d)), ) - emAgent ! FlexCtrlCompletion(modelUuid = evcsInput.getUuid) + emAgent ! FlexCompletion(modelUuid = evcsInput.getUuid) // expect correct results resultListener.expectMessageType[ParticipantResultEvent] match { @@ -276,8 +276,8 @@ class EmAgentSpec emAgentActivation ! Activation(0) // expect flex requests - pvAgent.expectMessage(RequestFlexOptions(0)) - evcsAgent.expectMessage(RequestFlexOptions(0)) + pvAgent.expectMessage(FlexActivation(0)) + evcsAgent.expectMessage(FlexActivation(0)) // send flex options emAgent ! ProvideMinMaxFlexOptions( @@ -309,7 +309,7 @@ class EmAgentSpec modelUuid = pvInput.getUuid, result = ApparentPower(Kilowatts(-5d), Kilovars(-0.5d)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = pvInput.getUuid, requestAtTick = Some(300), ) @@ -321,7 +321,7 @@ class EmAgentSpec scheduler.expectNoMessage() - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = evcsInput.getUuid, requestAtTick = Some(600), ) @@ -346,7 +346,7 @@ class EmAgentSpec // thus evcs does not get activated evcsAgent.expectNoMessage() - pvAgent.expectMessage(RequestFlexOptions(300)) + pvAgent.expectMessage(FlexActivation(300)) // send flex options again, now there's a cloud and thus less feed-in emAgent ! ProvideMinMaxFlexOptions( @@ -364,7 +364,7 @@ class EmAgentSpec result = ApparentPower(Kilowatts(-3d), Kilovars(-0.06d)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = pvInput.getUuid ) @@ -380,7 +380,7 @@ class EmAgentSpec modelUuid = evcsInput.getUuid, result = ApparentPower(Kilowatts(3d), Kilovars(0.06d)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = evcsInput.getUuid, requestAtTick = Some(800), // should overwrite tick 600 ) @@ -438,8 +438,8 @@ class EmAgentSpec emAgentActivation ! Activation(0) // expect flex requests - pvAgent.expectMessage(RequestFlexOptions(0)) - evcsAgent.expectMessage(RequestFlexOptions(0)) + pvAgent.expectMessage(FlexActivation(0)) + evcsAgent.expectMessage(FlexActivation(0)) // send flex options emAgent ! ProvideMinMaxFlexOptions( @@ -472,7 +472,7 @@ class EmAgentSpec modelUuid = pvInput.getUuid, result = ApparentPower(Kilowatts(-5d), Kilovars(-0.5d)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = pvInput.getUuid, requestAtTick = Some(300), ) @@ -484,7 +484,7 @@ class EmAgentSpec scheduler.expectNoMessage() - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = evcsInput.getUuid, requestAtNextActivation = true, // sending ChangingFlexOptions indicator requestAtTick = Some(600), @@ -509,7 +509,7 @@ class EmAgentSpec // expect activations and flex requests. // pv is scheduled regularly and evcs at any next tick // thus, we expect activations for both - pvAgent.expectMessage(RequestFlexOptions(300)) + pvAgent.expectMessage(FlexActivation(300)) // send flex options again, now there's a cloud and thus less feed-in emAgent ! ProvideMinMaxFlexOptions( @@ -520,7 +520,7 @@ class EmAgentSpec ) // expecting flex options request, since we asked for it last time - evcsAgent.expectMessage(RequestFlexOptions(300)) + evcsAgent.expectMessage(FlexActivation(300)) emAgent ! ProvideMinMaxFlexOptions( evcsInput.getUuid, @@ -536,7 +536,7 @@ class EmAgentSpec modelUuid = pvInput.getUuid, result = ApparentPower(Kilowatts(-3d), Kilovars(-0.06d)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = pvInput.getUuid ) @@ -551,7 +551,7 @@ class EmAgentSpec modelUuid = evcsInput.getUuid, result = ApparentPower(Kilowatts(3d), Kilovars(0.06d)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = evcsInput.getUuid // revoking tick 600 ) @@ -611,21 +611,21 @@ class EmAgentSpec parentEmAgent.expectNoMessage() /* TICK -1 */ - emAgentFlex ! RequestFlexOptions(INIT_SIM_TICK) + emAgentFlex ! FlexActivation(INIT_SIM_TICK) // expect flex requests - pvAgent.expectMessage(RequestFlexOptions(INIT_SIM_TICK)) - evcsAgent.expectMessage(RequestFlexOptions(INIT_SIM_TICK)) + pvAgent.expectMessage(FlexActivation(INIT_SIM_TICK)) + evcsAgent.expectMessage(FlexActivation(INIT_SIM_TICK)) // receive flex completions - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = pvInput.getUuid, requestAtTick = Some(0), ) parentEmAgent.expectNoMessage() - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = evcsInput.getUuid, requestAtTick = Some(0), ) @@ -634,18 +634,18 @@ class EmAgentSpec resultListener.expectNoMessage() // expect completion from EmAgent parentEmAgent.expectMessage( - FlexCtrlCompletion( + FlexCompletion( modelUuid = emInput.getUuid, requestAtTick = Some(0), ) ) /* TICK 0 */ - emAgentFlex ! RequestFlexOptions(0) + emAgentFlex ! FlexActivation(0) // expect activations and flex requests - pvAgent.expectMessage(RequestFlexOptions(0)) - evcsAgent.expectMessage(RequestFlexOptions(0)) + pvAgent.expectMessage(FlexActivation(0)) + evcsAgent.expectMessage(FlexActivation(0)) // send flex options emAgent ! ProvideMinMaxFlexOptions( @@ -698,7 +698,7 @@ class EmAgentSpec modelUuid = pvInput.getUuid, result = ApparentPower(Kilowatts(-5), Kilovars(-0.5)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = pvInput.getUuid, requestAtTick = Some(600), ) @@ -714,7 +714,7 @@ class EmAgentSpec modelUuid = evcsInput.getUuid, result = ApparentPower(Kilowatts(11), Kilovars(1.1)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = evcsInput.getUuid, requestAtTick = Some(300), ) @@ -736,7 +736,7 @@ class EmAgentSpec } parentEmAgent.expectMessage( - FlexCtrlCompletion( + FlexCompletion( modelUuid = emInput.getUuid, requestAtTick = Some(300), ) @@ -764,7 +764,7 @@ class EmAgentSpec modelUuid = evcsInput.getUuid, result = ApparentPower(Kilowatts(5.0), Kilovars(0.5)), ) - emAgent ! FlexCtrlCompletion( + emAgent ! FlexCompletion( modelUuid = evcsInput.getUuid, requestAtTick = Some(700), ) @@ -785,7 +785,7 @@ class EmAgentSpec result.q should approximate(Kilovars(0)) } parentEmAgent.expectMessage( - FlexCtrlCompletion( + FlexCompletion( modelUuid = emInput.getUuid, requestAtTick = Some(600), ) diff --git a/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala index 286e7806cb..06c3e797c0 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/EvcsAgentModelCalculationSpec.scala @@ -1277,7 +1277,7 @@ class EvcsAgentModelCalculationSpec - currently no cars */ - emAgent.send(evcsAgent, RequestFlexOptions(0)) + emAgent.send(evcsAgent, FlexActivation(0)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -1314,7 +1314,7 @@ class EvcsAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = evcsInputModelQv.getUuid, requestAtTick = Some(900), ) @@ -1340,7 +1340,7 @@ class EvcsAgentModelCalculationSpec ), ) - emAgent.send(evcsAgent, RequestFlexOptions(900)) + emAgent.send(evcsAgent, FlexActivation(900)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -1381,7 +1381,7 @@ class EvcsAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = evcsInputModelQv.getUuid, requestAtNextActivation = true, requestAtTick = Some(4500), @@ -1457,7 +1457,7 @@ class EvcsAgentModelCalculationSpec ), ) - emAgent.send(evcsAgent, RequestFlexOptions(4500)) + emAgent.send(evcsAgent, FlexActivation(4500)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -1491,7 +1491,7 @@ class EvcsAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = evcsInputModelQv.getUuid, requestAtNextActivation = true, requestAtTick = Some(9736), @@ -1507,7 +1507,7 @@ class EvcsAgentModelCalculationSpec */ // sending flex request at very next activated tick - emAgent.send(evcsAgent, RequestFlexOptions(9736)) + emAgent.send(evcsAgent, FlexActivation(9736)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -1543,7 +1543,7 @@ class EvcsAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = evcsInputModelQv.getUuid, requestAtNextActivation = true, requestAtTick = Some(11700), @@ -1587,7 +1587,7 @@ class EvcsAgentModelCalculationSpec ), ) - emAgent.send(evcsAgent, RequestFlexOptions(11700)) + emAgent.send(evcsAgent, FlexActivation(11700)) val combinedChargingPower = ev11700.unwrap().getSRatedAC.add(ev4500.unwrap().getSRatedAC) @@ -1633,7 +1633,7 @@ class EvcsAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = evcsInputModelQv.getUuid, requestAtNextActivation = true, requestAtTick = Some(32580), @@ -1663,7 +1663,7 @@ class EvcsAgentModelCalculationSpec */ // sending flex request at very next activated tick - emAgent.send(evcsAgent, RequestFlexOptions(18000)) + emAgent.send(evcsAgent, FlexActivation(18000)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -1705,7 +1705,7 @@ class EvcsAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = evcsInputModelQv.getUuid, requestAtTick = Some(23040), ) @@ -1743,7 +1743,7 @@ class EvcsAgentModelCalculationSpec - discharging with 10 kW */ - emAgent.send(evcsAgent, RequestFlexOptions(23040)) + emAgent.send(evcsAgent, FlexActivation(23040)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -1787,7 +1787,7 @@ class EvcsAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = evcsInputModelQv.getUuid, requestAtTick = Some(25004), ) @@ -1825,7 +1825,7 @@ class EvcsAgentModelCalculationSpec - no power */ - emAgent.send(evcsAgent, RequestFlexOptions(25004)) + emAgent.send(evcsAgent, FlexActivation(25004)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -1860,7 +1860,7 @@ class EvcsAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = evcsInputModelQv.getUuid ) ) @@ -1940,7 +1940,7 @@ class EvcsAgentModelCalculationSpec } // sending flex request at very next activated tick - emAgent.send(evcsAgent, RequestFlexOptions(36000)) + emAgent.send(evcsAgent, FlexActivation(36000)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -1975,7 +1975,7 @@ class EvcsAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = evcsInputModelQv.getUuid, requestAtNextActivation = true, requestAtTick = Some(72000), diff --git a/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala b/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala index d9eeece2a4..06035ed30d 100644 --- a/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/participant/StorageAgentModelCalculationSpec.scala @@ -328,7 +328,7 @@ class StorageAgentModelCalculationSpec - expecting changing flex options indicator (charging from empty) */ - emAgent.send(storageAgent, RequestFlexOptions(0)) + emAgent.send(storageAgent, FlexActivation(0)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -368,7 +368,7 @@ class StorageAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = storageInputQv.getUuid, requestAtNextActivation = true, requestAtTick = Some(60382), @@ -390,7 +390,7 @@ class StorageAgentModelCalculationSpec */ // Re-request flex options, since we've been asked to - emAgent.send(storageAgent, RequestFlexOptions(28800)) + emAgent.send(storageAgent, FlexActivation(28800)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -427,7 +427,7 @@ class StorageAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = storageInputQv.getUuid, requestAtTick = Some(74281), ) @@ -467,7 +467,7 @@ class StorageAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = storageInputQv.getUuid, requestAtTick = Some(64608), ) @@ -501,7 +501,7 @@ class StorageAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = storageInputQv.getUuid, requestAtTick = Some(81099), ) @@ -522,7 +522,7 @@ class StorageAgentModelCalculationSpec */ // Request flex options - emAgent.send(storageAgent, RequestFlexOptions(81099)) + emAgent.send(storageAgent, FlexActivation(81099)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -559,7 +559,7 @@ class StorageAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = storageInputQv.getUuid, requestAtNextActivation = true, requestAtTick = Some(136299), @@ -581,7 +581,7 @@ class StorageAgentModelCalculationSpec */ // Request flex options - emAgent.send(storageAgent, RequestFlexOptions(136299)) + emAgent.send(storageAgent, FlexActivation(136299)) emAgent.expectMsgType[ProvideFlexOptions] match { case ProvideMinMaxFlexOptions( @@ -613,7 +613,7 @@ class StorageAgentModelCalculationSpec result.q should approximate(Megavars(0)) } emAgent.expectMsg( - FlexCtrlCompletion( + FlexCompletion( modelUuid = storageInputQv.getUuid ) ) From 1aa81bfb778a9a16d700f6e81101db07aba03433 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 16:19:08 +0000 Subject: [PATCH 05/14] Bump jtsVersion from 1.19.0 to 1.20.0 (#942) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b17292a4cb..e670ce7ef7 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ ext { scalaVersion = '2.13' scalaBinaryVersion = '2.13.14' pekkoVersion = '1.0.3' - jtsVersion = '1.19.0' + jtsVersion = '1.20.0' confluentKafkaVersion = '7.4.0' tscfgVersion = '1.1.3' scapegoatVersion = '3.0.0' From 073bf612731456d473ebdb5c61e5d46f1b20719a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:07:16 +0000 Subject: [PATCH 06/14] Bump ch.qos.logback:logback-classic from 1.5.7 to 1.5.8 (#950) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e670ce7ef7..58bd6dc1d2 100644 --- a/build.gradle +++ b/build.gradle @@ -98,7 +98,7 @@ dependencies { /* logging */ implementation "com.typesafe.scala-logging:scala-logging_${scalaVersion}:3.9.5" // pekko scala logging - implementation "ch.qos.logback:logback-classic:1.5.7" + implementation "ch.qos.logback:logback-classic:1.5.8" /* testing */ testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0' From 8e43473e32c816b933aafd5c29f894c2c21e6ddc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:19:22 +0000 Subject: [PATCH 07/14] Bump sphinx-hoverxref from 1.4.0 to 1.4.1 in /docs/readthedocs (#953) --- docs/readthedocs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/readthedocs/requirements.txt b/docs/readthedocs/requirements.txt index 34b2f0762a..044c4a3020 100644 --- a/docs/readthedocs/requirements.txt +++ b/docs/readthedocs/requirements.txt @@ -3,5 +3,5 @@ sphinx-rtd-theme==2.0.0 sphinxcontrib-plantuml==0.30 myst-parser==4.0.0 markdown-it-py==3.0.0 -sphinx-hoverxref==1.4.0 +sphinx-hoverxref==1.4.1 sphinxcontrib-bibtex==2.6.2 From c75a4a77b27570fd0ff11147a6b815c3e3ddd37f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 09:40:10 +0000 Subject: [PATCH 08/14] Bump pekkoVersion from 1.0.3 to 1.1.0 (#949) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 58bd6dc1d2..e1120357b7 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ ext { scalaVersion = '2.13' scalaBinaryVersion = '2.13.14' - pekkoVersion = '1.0.3' + pekkoVersion = '1.1.0' jtsVersion = '1.20.0' confluentKafkaVersion = '7.4.0' tscfgVersion = '1.1.3' From 3bec459766c937bc5333eaaf0dcdd3756337bce0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 10:08:59 +0000 Subject: [PATCH 09/14] Bump sphinx from 7.3.7 to 7.4.7 in /docs/readthedocs (#855) --- docs/readthedocs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/readthedocs/requirements.txt b/docs/readthedocs/requirements.txt index 044c4a3020..97c05b1356 100644 --- a/docs/readthedocs/requirements.txt +++ b/docs/readthedocs/requirements.txt @@ -1,4 +1,4 @@ -Sphinx==7.3.7 +Sphinx==7.4.7 sphinx-rtd-theme==2.0.0 sphinxcontrib-plantuml==0.30 myst-parser==4.0.0 From 8eab695b3d22afb67671213e0754db5dc70a54f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Sep 2024 08:01:23 +0000 Subject: [PATCH 10/14] Bump sphinxcontrib-bibtex from 2.6.2 to 2.6.3 in /docs/readthedocs (#954) --- docs/readthedocs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/readthedocs/requirements.txt b/docs/readthedocs/requirements.txt index 97c05b1356..6c1bfcb1a8 100644 --- a/docs/readthedocs/requirements.txt +++ b/docs/readthedocs/requirements.txt @@ -4,4 +4,4 @@ sphinxcontrib-plantuml==0.30 myst-parser==4.0.0 markdown-it-py==3.0.0 sphinx-hoverxref==1.4.1 -sphinxcontrib-bibtex==2.6.2 +sphinxcontrib-bibtex==2.6.3 From a17eef637cdbd2547b4816dd47beed51ba2911a8 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Fri, 13 Sep 2024 12:56:01 +0200 Subject: [PATCH 11/14] Update docs/readthedocs/models/em.md wording Co-authored-by: Daniel Feismann <98817556+danielfeismann@users.noreply.github.com> --- docs/readthedocs/models/em.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/readthedocs/models/em.md b/docs/readthedocs/models/em.md index 3b91f52657..ae10cb3ac2 100644 --- a/docs/readthedocs/models/em.md +++ b/docs/readthedocs/models/em.md @@ -7,7 +7,7 @@ Energy Management Agents (EmAgents) control power feed-in and load of system par ## Protocol During simulation, EmAgents send `FlexActivation` and `IssueFlexControl` messages and receive `ProvideFlexOptions` and `FlexCompletion` messages. -After having been requested to calculate flex options via `FlexActivation`, controllable assets send back their flex options to the controlling unit using `ProvideFlexOptions`. +After being requested to calculate flex options via `FlexActivation`, controllable assets send back their flex options to the controlling unit using `ProvideFlexOptions`. Eventually the controlling EmAgent responds with some type of `IssueFlexControl` messages, setting a power set point for operation. The asset then tries to realize the set power as best as it can and replies with a `FlexCompletion` messages. If an EmAgent is itself controlled by another EmAgent, it also behaves like a system participant (sends `FlexActivation` and `IssueFlexControl` messages etc.). From 89015d698e2f0200925cca81defca2d426142903 Mon Sep 17 00:00:00 2001 From: Sebastian Peter Date: Fri, 13 Sep 2024 13:02:59 +0200 Subject: [PATCH 12/14] Adapting test commentary Signed-off-by: Sebastian Peter --- .../edu/ie3/simona/agent/em/EmAgentSpec.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala b/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala index b6157eac06..fb550a9a77 100644 --- a/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala +++ b/src/test/scala/edu/ie3/simona/agent/em/EmAgentSpec.scala @@ -106,7 +106,7 @@ class EmAgentSpec /* TICK -1 */ emAgentActivation ! Activation(INIT_SIM_TICK) - // expect flex requests + // expect flex activations pvAgent.expectMessage(FlexActivation(INIT_SIM_TICK)) evcsAgent.expectMessage(FlexActivation(INIT_SIM_TICK)) @@ -133,7 +133,7 @@ class EmAgentSpec /* TICK 0 */ emAgentActivation ! Activation(0) - // expect flex requests + // expect flex activations pvAgent.expectMessage(FlexActivation(0)) evcsAgent.expectMessage(FlexActivation(0)) @@ -275,7 +275,7 @@ class EmAgentSpec /* TICK 0 */ emAgentActivation ! Activation(0) - // expect flex requests + // expect flex activations pvAgent.expectMessage(FlexActivation(0)) evcsAgent.expectMessage(FlexActivation(0)) @@ -341,7 +341,7 @@ class EmAgentSpec /* TICK 300 */ emAgentActivation ! Activation(300) - // expect activations and flex requests. + // expect activations and flex activations. // only pv agent has been scheduled for this tick, // thus evcs does not get activated evcsAgent.expectNoMessage() @@ -437,7 +437,7 @@ class EmAgentSpec /* TICK 0 */ emAgentActivation ! Activation(0) - // expect flex requests + // expect flex activations pvAgent.expectMessage(FlexActivation(0)) evcsAgent.expectMessage(FlexActivation(0)) @@ -506,7 +506,7 @@ class EmAgentSpec // FLEX OPTIONS - // expect activations and flex requests. + // expect activations and flex activations. // pv is scheduled regularly and evcs at any next tick // thus, we expect activations for both pvAgent.expectMessage(FlexActivation(300)) @@ -613,7 +613,7 @@ class EmAgentSpec /* TICK -1 */ emAgentFlex ! FlexActivation(INIT_SIM_TICK) - // expect flex requests + // expect flex activations pvAgent.expectMessage(FlexActivation(INIT_SIM_TICK)) evcsAgent.expectMessage(FlexActivation(INIT_SIM_TICK)) From e41cdb3d3227040ebddbbe7a169cc8b263e8adc8 Mon Sep 17 00:00:00 2001 From: danielfeismann Date: Fri, 13 Sep 2024 16:24:12 +0200 Subject: [PATCH 13/14] Fix expected secondaryData in baseStateData --- CHANGELOG.md | 1 + .../agent/participant/ParticipantAgent.scala | 18 +++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 052527a251..c4030aa839 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,6 +106,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Handle MobSim requests for current prices [#892](https://github.com/ie3-institute/simona/issues/892) - Fix determineState of ThermalHouse [#926](https://github.com/ie3-institute/simona/issues/926) - Fix activation of Hp when not under control of an EM [#922](https://github.com/ie3-institute/simona/issues/922) +- Fix expected secondaryData in baseStateData [#955](https://github.com/ie3-institute/simona/issues/955) ## [3.0.0] - 2023-08-07 diff --git a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala index 70ce7c2d09..52e3a53a59 100644 --- a/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala +++ b/src/main/scala/edu/ie3/simona/agent/participant/ParticipantAgent.scala @@ -436,13 +436,17 @@ abstract class ParticipantAgent[ _, ), ) => - val updatedReceivedSecondaryData = ValueStore.updateValueStore( - participantStateData.receivedSecondaryDataStore, - currentTick, - data.map { case (actorRef, Some(data: SecondaryData)) => - actorRef -> data - }, - ) + val updatedReceivedSecondaryData = data match { + case nonEmptyData if nonEmptyData.nonEmpty => + ValueStore.updateValueStore( + participantStateData.receivedSecondaryDataStore, + currentTick, + nonEmptyData.collect { case (actorRef, Some(data: SecondaryData)) => + actorRef -> data + }, + ) + case _ => participantStateData.receivedSecondaryDataStore + } /* At least parts of the needed data has been received or it is an additional activation, that has been triggered. * Anyways, the calculation routine has also to take care of filling up missing data. */ From 6bc4ea82c40f277b3829ba39dbc7d1e80da29cdd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 08:19:50 +0000 Subject: [PATCH 14/14] Bump pekkoVersion from 1.1.0 to 1.1.1 (#957) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e1120357b7..b47bc21820 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ ext { scalaVersion = '2.13' scalaBinaryVersion = '2.13.14' - pekkoVersion = '1.1.0' + pekkoVersion = '1.1.1' jtsVersion = '1.20.0' confluentKafkaVersion = '7.4.0' tscfgVersion = '1.1.3'