Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/jb/#671-externaldataservice' int…
Browse files Browse the repository at this point in the history
…o jb/#671-externaldataservice
  • Loading branch information
jo-bao committed Feb 21, 2024
2 parents ffaa520 + 778b4e6 commit 3effeab
Show file tree
Hide file tree
Showing 15 changed files with 370 additions and 76 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {
id 'signing'
id 'maven-publish' // publish to a maven repo (local or mvn central, has to be defined)
id 'pmd' // code check, working on source code
id 'com.diffplug.spotless' version '6.23.3'// code format
id 'com.diffplug.spotless' version '6.24.0'// code format
id "com.github.ben-manes.versions" version '0.50.0'
id "de.undercouch.download" version "5.5.0" // downloads plugin
id "kr.motd.sphinx" version "2.10.1" // documentation generation
Expand Down Expand Up @@ -107,7 +107,7 @@ dependencies {
/* testing */
testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0'
testImplementation 'org.scalatestplus:mockito-3-4_2.13:3.2.10.0'
testImplementation 'org.mockito:mockito-core:5.8.0' // mocking framework
testImplementation 'org.mockito:mockito-core:5.9.0' // mocking framework
testImplementation "org.scalatest:scalatest_${scalaVersion}:3.2.17"
testRuntimeOnly 'com.vladsch.flexmark:flexmark-all:0.64.8' //scalatest html output
testImplementation group: 'org.pegdown', name: 'pegdown', version: '1.6.0'
Expand Down
102 changes: 102 additions & 0 deletions docs/uml/protocol/ExtDataService.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
@startuml

!theme plain

==Init==




SimScheduler -> ExtSimAdapter: <font color=red>!</font> <font color=green>ActivityStartTrigger(-1L)</font>
activate ExtSimAdapter

ExtSimAdapter -> ExtSimulation: queue(ActivityStartTrigger(-1L))
deactivate ExtSimAdapter
activate ExtSimulation
... Initialize external mobility simulation ...

ExtSimulation -> ExtSimAdapter: <font color=red>!</font> CompletionMessage(newTriggers)
deactivate ExtSimulation
activate ExtSimAdapter

ExtSimAdapter -> SimScheduler: <font color=red>!</font> <font color=green>CompletionMessage(newTriggers)</font>
deactivate ExtSimAdapter

==Sim==
SimScheduler -> ExtSimAdapter: <font color=red>!</font> <font color=green>ActivityStartTrigger(tick)</font>
activate ExtSimAdapter

ExtSimAdapter -> ExtSimulation: queue(ActivityStartTrigger(tick))
deactivate ExtSimAdapter

activate ExtSimulation
ExtSimulation -> ExtEvDataService: <font color=red>!</font> RequestEvcsFreeLots
ExtSimulation -> ExtSimAdapter: <font color=red>!</font> ScheduleDataServiceMessage(\n\tdataServiceRef\n)

activate ExtSimAdapter
ExtSimAdapter -> SimScheduler: <font color=red>!</font> ScheduleTriggerMessage(\n\t_, dataServiceRef)
deactivate ExtSimAdapter

activate SimScheduler
SimScheduler -> ExtEvDataService: <font color=red>!</font> ActivityStartTrigger(tick)
deactivate SimScheduler

activate ExtEvDataService
ExtEvDataService -> EvcsAgent1: <font color=red>!</font> EvFreeLotsRequest(tick)
activate EvcsAgent1
ExtEvDataService -> EvcsAgent2: <font color=red>!</font> EvFreeLotsRequest(tick)
activate EvcsAgent2

ExtEvDataService -> SimScheduler: <font color=red>!</font> CompletionMessage(None)

EvcsAgent2 -> ExtEvDataService: <font color=red>!</font> FreeLotsResponse(_, _)
deactivate EvcsAgent2
EvcsAgent1 -> ExtEvDataService: <font color=red>!</font> FreeLotsResponse(_, _)
deactivate EvcsAgent1
ExtEvDataService -> ExtSimulation: queue(ProvideEvcsFreeLots(_))
deactivate ExtEvDataService

... Running external mobility simulation,\n determining EV positions ...
ExtSimulation -> ExtEvDataService: <font color=red>!</font> EvMovementsMessage(_)
ExtSimulation -> ExtSimAdapter: <font color=red>!</font> ScheduleDataServiceMessage(\n\tdataServiceRef\n)

activate ExtSimAdapter
ExtSimAdapter -> SimScheduler: <font color=red>!</font> ScheduleTriggerMessage(\n\t_, dataServiceRef)
deactivate ExtSimAdapter

activate SimScheduler
SimScheduler -> ExtEvDataService: <font color=red>!</font> ActivityStartTrigger(tick)
deactivate SimScheduler

activate ExtEvDataService
ExtEvDataService -> EvcsAgent1: <font color=red>!</font> ProvideEvDataMessage(\n\ttick, _)
ExtEvDataService -> EvcsAgent2: <font color=red>!</font> ProvideEvDataMessage(\n\ttick, _)
ExtEvDataService -> SimScheduler: <font color=red>!</font> CompletionMessage(evcsTriggers)
deactivate ExtEvDataService

activate SimScheduler
SimScheduler -> EvcsAgent1: <font color=red>!</font> ActivityStartTrigger(tick)
activate EvcsAgent1
SimScheduler -> EvcsAgent2: <font color=red>!</font> ActivityStartTrigger(tick)
deactivate SimScheduler

activate EvcsAgent2
EvcsAgent1 -> SimScheduler: <font color=red>!</font> CompletionMessage(None)
deactivate EvcsAgent1

EvcsAgent2 -> ExtEvDataService: <font color=red>!</font> DepartedEvsResponse(_, _)
activate ExtEvDataService
EvcsAgent2 -> SimScheduler: <font color=red>!</font> CompletionMessage(None)
deactivate EvcsAgent2

ExtEvDataService -> ExtSimulation: queue(AllDepartedEvsResponse(_))
deactivate ExtEvDataService

ExtSimulation -> ExtSimAdapter: <font color=red>!</font> CompletionMessage(newTriggers)
deactivate ExtSimulation

activate ExtSimAdapter
ExtSimAdapter -> SimScheduler: <font color=red>!</font> <font color=green>CompletionMessage(newTriggers)</font>
deactivate ExtSimAdapter

@enduml
29 changes: 8 additions & 21 deletions src/main/scala/edu/ie3/simona/event/ResultEvent.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ import edu.ie3.simona.agent.grid.GridResultsSupport.PartialTransformer3wResult
import edu.ie3.simona.event.listener.ResultEventListener.ResultMessage


sealed trait ResultEvent extends ResultMessage {
def getResults(): Iterable[ResultEntity]
}
sealed trait ResultEvent extends ResultMessage

/** Calculation result events
*/
object ResultEvent {

final case class ExternalResultEvent(
resultEntity: ResultEntity
) extends ResultEvent

/** Event that holds a calculation result of a
* [[edu.ie3.simona.model.participant.SystemParticipant]]
*
Expand All @@ -30,19 +32,15 @@ object ResultEvent {
*/
final case class ParticipantResultEvent(
systemParticipantResult: SystemParticipantResult
) extends ResultEvent {
override def getResults(): Iterable[ResultEntity] = Iterable(systemParticipantResult)
}
) extends ResultEvent

/** Event, that is triggered every time a thermal model has a new result
* @param thermalResult
* Result of the thermal calculation
*/
final case class ThermalResultEvent(
thermalResult: ThermalUnitResult
) extends ResultEvent {
override def getResults(): Iterable[ResultEntity] = Iterable(thermalResult)
}
) extends ResultEvent

/** Event that holds all grid calculation results of a power flow calculation.
* The usage of a type is necessary here, to avoid passing in other instances
Expand All @@ -66,16 +64,5 @@ object ResultEvent {
lineResults: Iterable[LineResult],
transformer2wResults: Iterable[Transformer2WResult],
transformer3wResults: Iterable[PartialTransformer3wResult]
) extends ResultEvent {
override def getResults(): Iterable[ResultEntity] = {
var results: Iterable[ResultEntity] = Iterable.empty[ResultEntity]
results = results ++ nodeResults
results = results ++ switchResults
results = results ++ lineResults
results = results ++ transformer2wResults
// results = results ++ transformer3wResults
results
}
}

) extends ResultEvent
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,14 @@ import edu.ie3.datamodel.io.processor.result.ResultEntityProcessor
import edu.ie3.datamodel.models.result.{NodeResult, ResultEntity}
import edu.ie3.simona.agent.grid.GridResultsSupport.PartialTransformer3wResult
import edu.ie3.simona.event.Event
import edu.ie3.simona.event.ResultEvent.{
ParticipantResultEvent,
PowerFlowResultEvent,
ThermalResultEvent
}
import edu.ie3.simona.exceptions.{
FileHierarchyException,
ProcessResultEventException
}
import edu.ie3.simona.event.ResultEvent.{ExternalResultEvent, ParticipantResultEvent, PowerFlowResultEvent, ThermalResultEvent}
import edu.ie3.simona.exceptions.{FileHierarchyException, ProcessResultEventException}
import edu.ie3.simona.io.result._
import edu.ie3.simona.ontology.messages.StopMessage
import edu.ie3.simona.ontology.messages.services.ResultMessage.ResultResponseMessage
import edu.ie3.simona.sim.SimonaSim.ResultMessage
import edu.ie3.simona.util.ResultFileHierarchy
import org.apache.pekko.actor.ActorRef
import org.slf4j.Logger

import scala.concurrent.ExecutionContext.Implicits.global
Expand All @@ -43,15 +39,19 @@ object ResultEventListener extends Transformer3wResultSupport {

private final case object StopTimeout extends ResultMessage


/** [[ResultEventListener]] base data containing all information the listener
* needs
*
* @param classToSink
* a map containing the sink for each class that should be processed by the
* listener
* @param extResultDataService
* actor for the external data service
*/
private final case class BaseData(
classToSink: Map[Class[_], ResultEntitySink],
extResultDataService: Option[ActorRef],
threeWindingResults: Map[
Transformer3wKey,
AggregatedTransformer3wResult
Expand Down Expand Up @@ -157,6 +157,9 @@ object ResultEventListener extends Transformer3wResultSupport {
log: Logger
): BaseData = {
handOverToSink(resultEntity, baseData.classToSink, log)
if (baseData.extResultDataService.isDefined) {
handOverToExternalService(resultEntity, baseData.extResultDataService, log)
}
baseData
}

Expand Down Expand Up @@ -231,8 +234,18 @@ object ResultEventListener extends Transformer3wResultSupport {
log.error("Error while writing result event: ", exception)
}

private def handOverToExternalService(
resultEntity: ResultEntity,
extResultDataService: Option[ActorRef],
log: Logger
): Unit = Try {
val extResultDataServiceRef = extResultDataService.getOrElse(throw new Exception("No external data service registered!"))
extResultDataServiceRef ! ResultResponseMessage(resultEntity)
}

def apply(
resultFileHierarchy: ResultFileHierarchy
resultFileHierarchy: ResultFileHierarchy,
extResultDataService: Option[ActorRef] = Option.empty[ActorRef]
): Behavior[ResultMessage] = Behaviors.setup[ResultMessage] { ctx =>
ctx.log.debug("Starting initialization!")
resultFileHierarchy.resultSinkType match {
Expand All @@ -256,15 +269,15 @@ object ResultEventListener extends Transformer3wResultSupport {
case Success(result) => SinkResponse(result.toMap)
}

init()
init(extResultDataService)
}

private def init(): Behavior[ResultMessage] = Behaviors.withStash(200) {
private def init(extResultDataService: Option[ActorRef]): Behavior[ResultMessage] = Behaviors.withStash(200) {
buffer =>
Behaviors.receive[ResultMessage] {
case (ctx, SinkResponse(response)) =>
ctx.log.debug("Initialization complete!")
buffer.unstashAll(idle(BaseData(response)))
buffer.unstashAll(idle(BaseData(response, extResultDataService)))

case (ctx, Failed(ex)) =>
ctx.log.error("Unable to setup ResultEventListener.", ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ sealed trait ResultMessage extends DataMessage
object ResultMessage {
final case class ResultRequest(tick: Long)

final case class ResultResponseMessage(results: Iterable[ResultEntity]) extends ResultMessage
final case class ResultResponseMessage(result: ResultEntity) extends ResultMessage
}
14 changes: 6 additions & 8 deletions src/main/scala/edu/ie3/simona/service/SimonaService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,17 @@

package edu.ie3.simona.service

import edu.ie3.simona.event
import edu.ie3.simona.event.Event
import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps
import org.apache.pekko.actor.{Actor, ActorContext, ActorRef, Stash}
import edu.ie3.simona.logging.SimonaActorLogging
import edu.ie3.simona.ontology.messages.Activation
import edu.ie3.simona.ontology.messages.SchedulerMessage.{
Completion,
ScheduleActivation
}
import edu.ie3.simona.ontology.messages.SchedulerMessage.{Completion, ScheduleActivation}
import edu.ie3.simona.ontology.messages.services.ServiceMessage.RegistrationResponseMessage.ScheduleServiceActivation
import edu.ie3.simona.ontology.messages.services.ServiceMessage.ServiceRegistrationMessage
import edu.ie3.simona.scheduler.ScheduleLock.ScheduleKey
import edu.ie3.simona.service.ServiceStateData.{
InitializeServiceStateData,
ServiceBaseStateData
}
import edu.ie3.simona.service.ServiceStateData.{InitializeServiceStateData, ServiceBaseStateData}
import edu.ie3.simona.service.SimonaService.Create
import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK

Expand Down Expand Up @@ -132,6 +128,7 @@ abstract class SimonaService[

private def idleInternal(implicit stateData: S): Receive = {
// agent registration process

case registrationMsg: ServiceRegistrationMessage =>
/* Someone asks to register for information from the service */
handleRegistrationRequest(registrationMsg) match {
Expand Down Expand Up @@ -168,6 +165,7 @@ abstract class SimonaService[
unhandled(x)
}


/** Internal api method that allows handling incoming messages from external
* simulations
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object ExtPrimaryDataService {
extPrimaryDataMessage: Option[PrimaryDataMessageFromExt] = None
) extends ServiceBaseStateData

final case class InitExtPrimaryData(
case class InitExtPrimaryData(
extPrimaryData: ExtPrimaryData
) extends InitializeServiceStateData

Expand Down Expand Up @@ -71,18 +71,23 @@ final case class ExtPrimaryDataService(
override protected def handleRegistrationRequest(
registrationMessage: ServiceMessage.ServiceRegistrationMessage
)(implicit serviceStateData: ExtPrimaryDataStateData):
Try[ExtPrimaryDataStateData] = registrationMessage match {
Try[ExtPrimaryDataStateData] = {
println("Habe erhalten 0")
registrationMessage match {
case ExtPrimaryDataServiceRegistrationMessage(modelUuid, requestingActor) =>
println("Habe erhalten")
Success(handleRegistrationRequest(requestingActor, modelUuid))
case invalidMessage =>
Failure(
InvalidRegistrationRequestException(
s"A primary service provider is not able to handle registration request '$invalidMessage'."
)
)
}
}



private def handleRegistrationRequest(
agentToBeRegistered: ActorRef,
agentUUID: UUID
Expand Down

0 comments on commit 3effeab

Please sign in to comment.