Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Convert WeatherService to typed #1218

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Typo and format of `ThermalGrid` and `ThermalHouse` ScalaDocs [#1196](https://github.com/ie3-institute/simona/issues/1196)
- Refactor `EmRuntimeConfig` [#1181](https://github.com/ie3-institute/simona/issues/1181)
- Based `PvModel` calculations on irradiance (power per area) instead of irradiation (energy per area) [#1212](https://github.com/ie3-institute/simona/issues/1212)
- Converting `ExtEvDataService` to pekko typed [#1214](https://github.com/ie3-institute/simona/issues/1214)
- Converting `WeatherService` to pekko typed [#1216](https://github.com/ie3-institute/simona/issues/1216)

### Fixed
- Fix rendering of references in documentation [#505](https://github.com/ie3-institute/simona/issues/505)
Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/edu/ie3/simona/agent/EnvironmentRefs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package edu.ie3.simona.agent

import edu.ie3.simona.event.RuntimeEvent
import edu.ie3.simona.ontology.messages.SchedulerMessage
import edu.ie3.simona.ontology.messages.services.{EvMessage, WeatherMessage}
import org.apache.pekko.actor.typed.ActorRef
import org.apache.pekko.actor.{ActorRef => ClassicRef}

Expand All @@ -29,6 +30,6 @@ final case class EnvironmentRefs(
scheduler: ActorRef[SchedulerMessage],
runtimeEventListener: ActorRef[RuntimeEvent],
primaryServiceProxy: ClassicRef,
weather: ClassicRef,
evDataService: Option[ClassicRef],
weather: ActorRef[WeatherMessage],
evDataService: Option[ActorRef[EvMessage]],
)
15 changes: 10 additions & 5 deletions src/main/scala/edu/ie3/simona/agent/grid/GridAgentController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ import edu.ie3.simona.exceptions.agent.GridAgentInitializationException
import edu.ie3.simona.ontology.messages.SchedulerMessage
import edu.ie3.simona.ontology.messages.SchedulerMessage.ScheduleActivation
import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage.FlexResponse
import edu.ie3.simona.ontology.messages.services.{
EvMessage,
ServiceMessage,
WeatherMessage,
}
import edu.ie3.simona.service.ServiceType
import edu.ie3.simona.util.ConfigUtil
import edu.ie3.simona.util.ConfigUtil._
Expand Down Expand Up @@ -334,7 +339,7 @@ class GridAgentController(
maybeControllingEm: Option[ActorRef[FlexResponse]],
): ActorRef[ParticipantAgent.Request] = {

val serviceMap: Map[ServiceType, ClassicRef] =
val serviceMap: Map[ServiceType, ActorRef[_ >: ServiceMessage]] =
Seq(
Some(ServiceType.WeatherService -> environmentRefs.weather),
environmentRefs.evDataService.map(ref =>
Expand Down Expand Up @@ -527,7 +532,7 @@ class GridAgentController(
evcsInput: EvcsInput,
modelConfiguration: EvcsRuntimeConfig,
primaryServiceProxy: ClassicRef,
evMovementsService: ClassicRef,
evMovementsService: ActorRef[EvMessage],
simulationStartDate: ZonedDateTime,
simulationEndDate: ZonedDateTime,
resolution: Long,
Expand All @@ -545,7 +550,7 @@ class GridAgentController(
primaryServiceProxy,
Iterable(
ActorExtEvDataService(
evMovementsService
evMovementsService.toClassic
)
),
simulationStartDate,
Expand Down Expand Up @@ -591,7 +596,7 @@ class GridAgentController(
thermalGrid: ThermalGrid,
modelConfiguration: HpRuntimeConfig,
primaryServiceProxy: ClassicRef,
weatherService: ClassicRef,
weatherService: ActorRef[WeatherMessage],
requestVoltageDeviationThreshold: Double,
outputConfig: NotifierConfig,
maybeControllingEm: Option[ActorRef[FlexResponse]],
Expand All @@ -605,7 +610,7 @@ class GridAgentController(
thermalGrid,
modelConfiguration,
primaryServiceProxy,
Iterable(ActorWeatherService(weatherService)),
Iterable(ActorWeatherService(weatherService.toClassic)),
simulationStartDate,
simulationEndDate,
resolution,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import edu.ie3.simona.model.participant.{
}
import edu.ie3.simona.ontology.messages.services.EvMessage.RegisterForEvDataMessage
import edu.ie3.simona.ontology.messages.services.WeatherMessage.RegisterForWeatherMessage
import org.apache.pekko.actor.typed.scaladsl.adapter.ClassicActorRefOps

trait ServiceRegistration[
PD <: PrimaryDataWithComplexPower[PD],
Expand Down Expand Up @@ -122,7 +123,7 @@ trait ServiceRegistration[
s"is invalid."
)
}
serviceRef ! RegisterForWeatherMessage(participantRef, lat, lon)
serviceRef ! RegisterForWeatherMessage(participantRef.toTyped, lat, lon)
}

/** Register for the EV movement service
Expand All @@ -139,7 +140,7 @@ trait ServiceRegistration[
): Unit = {
inputModel match {
case evcsInput: EvcsInput =>
serviceRef ! RegisterForEvDataMessage(evcsInput.getUuid)
serviceRef ! RegisterForEvDataMessage(self.toTyped, evcsInput.getUuid)
case _ =>
throw new ServiceRegistrationException(
s"Cannot register for EV movements information at node ${inputModel.getNode.getId} " +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ import edu.ie3.simona.ontology.messages.SchedulerMessage.{
}
import edu.ie3.simona.ontology.messages.flex.FlexibilityMessage._
import edu.ie3.simona.ontology.messages.services.EvMessage.RegisterForEvDataMessage
import edu.ie3.simona.ontology.messages.services.ServiceMessage
import edu.ie3.simona.ontology.messages.services.ServiceMessage.PrimaryServiceRegistrationMessage
import edu.ie3.simona.ontology.messages.services.WeatherMessage.RegisterForWeatherMessage
import edu.ie3.simona.ontology.messages.{Activation, SchedulerMessage}
import edu.ie3.simona.service.ServiceType
import edu.ie3.simona.util.SimonaConstants.INIT_SIM_TICK
import org.apache.pekko.actor.typed.scaladsl.Behaviors
import org.apache.pekko.actor.typed.scaladsl.{ActorContext, Behaviors}
import org.apache.pekko.actor.typed.scaladsl.adapter.TypedActorRefOps
import org.apache.pekko.actor.typed.{ActorRef, Behavior}
import org.apache.pekko.actor.{ActorRef => ClassicRef}
Expand Down Expand Up @@ -55,7 +56,7 @@ object ParticipantAgentInit {
final case class ParticipantRefs(
gridAgent: ActorRef[GridAgent.Request],
primaryServiceProxy: ClassicRef,
services: Map[ServiceType, ClassicRef],
services: Map[ServiceType, ActorRef[_ >: ServiceMessage]],
resultListener: Iterable[ActorRef[ResultEvent]],
)

Expand Down Expand Up @@ -241,12 +242,14 @@ object ParticipantAgentInit {
// requiring at least one secondary service, thus send out registrations and wait for replies
val requiredServices = requiredServiceTypes
.map(serviceType =>
serviceType -> participantRefs.services.getOrElse(
serviceType,
throw new CriticalFailureException(
s"${modelShell.identifier}: Service of type $serviceType is not available."
),
)
serviceType -> participantRefs.services
.getOrElse(
serviceType,
throw new CriticalFailureException(
s"${modelShell.identifier}: Service of type $serviceType is not available."
),
)
.toClassic
)
.toMap

Expand All @@ -257,7 +260,7 @@ object ParticipantAgentInit {
modelShell,
serviceType,
serviceRef,
)
)(ctx)
}

waitingForServices(
Expand All @@ -277,18 +280,14 @@ object ParticipantAgentInit {
modelShell: ParticipantModelShell[_, _],
serviceType: ServiceType,
serviceRef: ClassicRef,
): Unit =
)(implicit ctx: ActorContext[ParticipantAgent.Request]): Unit =
serviceType match {
case ServiceType.WeatherService =>
val geoPosition = participantInput.getNode.getGeoPosition

Option(geoPosition.getY).zip(Option(geoPosition.getX)) match {
case Some((lat, lon)) =>
serviceRef ! RegisterForWeatherMessage(
participantRef.toClassic,
lat,
lon,
)
serviceRef ! RegisterForWeatherMessage(ctx.self, lat, lon)
case _ =>
throw new CriticalFailureException(
s"${modelShell.identifier} cannot register for weather information at " +
Expand All @@ -304,7 +303,7 @@ object ParticipantAgentInit {
)

case ServiceType.EvMovementService =>
serviceRef ! RegisterForEvDataMessage(modelShell.uuid)
serviceRef ! RegisterForEvDataMessage(ctx.self, modelShell.uuid)
}

/** Waiting for replies from secondary services. If all replies have been
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,31 @@
package edu.ie3.simona.ontology.messages.services

import edu.ie3.simona.agent.participant.data.Data.SecondaryData
import edu.ie3.simona.agent.participant2.ParticipantAgent
import edu.ie3.simona.agent.participant2.ParticipantAgent.ParticipantRequest
import edu.ie3.simona.model.participant.evcs.EvModelWrapper
import edu.ie3.simona.ontology.messages.services.ServiceMessage.ServiceRegistrationMessage
import org.apache.pekko.actor.typed.ActorRef

import java.util.UUID

sealed trait EvMessage

object EvMessage {

private[services] trait EvInternal extends EvMessage

/** Indicate the [[edu.ie3.simona.service.ev.ExtEvDataService]] that the
* requesting agent wants to receive EV movements
*
* @param actorRef
* actor ref for the agent to be registered
* @param evcs
* the charging station
*/
final case class RegisterForEvDataMessage(
evcs: UUID
actorRef: ActorRef[ParticipantAgent.Request],
evcs: UUID,
) extends EvMessage
with ServiceRegistrationMessage

Expand All @@ -35,6 +43,8 @@ object EvMessage {
* The latest tick that the data is requested for
*/
final case class EvFreeLotsRequest(tick: Long)
extends EvMessage
with ParticipantRequest

/** Requests EV models of departing EVs with given UUIDs
*
Expand All @@ -44,6 +54,8 @@ object EvMessage {
* The UUIDs of EVs that are requested
*/
final case class DepartingEvsRequest(tick: Long, departingEvs: Seq[UUID])
extends EvMessage
with ParticipantRequest

/** Holds arrivals for one charging station
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,45 @@

package edu.ie3.simona.ontology.messages.services

import org.apache.pekko.actor.ActorRef
import org.apache.pekko.actor.{ActorRef => ClassicRef}

import java.util.UUID
import edu.ie3.simona.agent.participant.data.Data
import edu.ie3.simona.api.data.ontology.DataMessageFromExt
import edu.ie3.simona.ontology.messages.Activation
import edu.ie3.simona.ontology.messages.services.EvMessage.EvInternal
import edu.ie3.simona.ontology.messages.services.WeatherMessage.WeatherInternal
import edu.ie3.simona.scheduler.ScheduleLock.ScheduleKey
import edu.ie3.simona.service.ServiceStateData.InitializeServiceStateData

/** Collections of all messages, that are send to and from the different
* services
*/
sealed trait ServiceMessage
sealed trait ServiceMessage extends EvInternal with WeatherInternal

object ServiceMessage {

final case class WrappedActivation(activation: Activation)
extends ServiceMessage

final case class WrappedExternalMessage(
extMsg: DataMessageFromExt
) extends ServiceMessage

/** Service initialization data can sometimes only be constructed once the
* service actor is created (e.g.
* [[edu.ie3.simona.service.ev.ExtEvDataService]]). Thus, we need an extra
* initialization message.
*/
final case class Create[+I <: InitializeServiceStateData](
initializeStateData: I,
unlockKey: ScheduleKey,
) extends ServiceMessage

final case class ScheduleServiceActivation(
tick: Long,
unlockKey: ScheduleKey,
) extends ServiceMessage

/** Message used to register for a service
*/
trait ServiceRegistrationMessage extends ServiceMessage
Expand All @@ -31,7 +57,7 @@ object ServiceMessage {
* Identifier of the input model
*/
final case class PrimaryServiceRegistrationMessage(
requestingActor: ActorRef,
requestingActor: ClassicRef,
inputModelUuid: UUID,
) extends ServiceRegistrationMessage

Expand All @@ -42,12 +68,6 @@ object ServiceMessage {
* @param requestingActor
* Reference to the requesting actor
*/
final case class WorkerRegistrationMessage(requestingActor: ActorRef)
final case class WorkerRegistrationMessage(requestingActor: ClassicRef)
extends ServiceRegistrationMessage

final case class ScheduleServiceActivation(
tick: Long,
unlockKey: ScheduleKey,
)

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
package edu.ie3.simona.ontology.messages.services

import edu.ie3.simona.agent.participant.data.Data.SecondaryData
import edu.ie3.simona.agent.participant2.ParticipantAgent
import edu.ie3.simona.ontology.messages.services.ServiceMessage.ServiceRegistrationMessage
import edu.ie3.util.scala.quantities.Irradiance
import org.apache.pekko.actor.ActorRef
import org.apache.pekko.actor.typed.ActorRef
import squants.{Temperature, Velocity}

sealed trait WeatherMessage
Expand All @@ -22,6 +23,8 @@ sealed trait WeatherMessage
*/
object WeatherMessage {

private[services] trait WeatherInternal extends WeatherMessage

/** Indicate the [[edu.ie3.simona.service.weather.WeatherService]] that the
* requesting agent wants to receive weather for the provided coordinates
*
Expand All @@ -33,7 +36,7 @@ object WeatherMessage {
* Longitude of the requested location
*/
final case class RegisterForWeatherMessage(
requestingActor: ActorRef,
requestingActor: ActorRef[ParticipantAgent.Request],
latitude: Double,
longitude: Double,
) extends WeatherMessage
Expand Down
35 changes: 27 additions & 8 deletions src/main/scala/edu/ie3/simona/service/ExtDataSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,41 @@ package edu.ie3.simona.service

import edu.ie3.simona.api.data.ontology.DataMessageFromExt
import edu.ie3.simona.ontology.messages.services.EvMessage.EvResponseMessage
import edu.ie3.simona.service.ServiceStateData.ServiceBaseStateData
import edu.ie3.simona.ontology.messages.services.ServiceMessage
import edu.ie3.simona.ontology.messages.services.ServiceMessage.WrappedExternalMessage
import edu.ie3.simona.service.ServiceStateData.ServiceConstantStateData
import org.apache.pekko.actor.typed.Behavior
import org.apache.pekko.actor.typed.scaladsl.{Behaviors, StashBuffer}

/** Trait that enables handling of external data.
* @tparam T
* the type of messages this service accepts
*/
trait ExtDataSupport[
S <: ServiceBaseStateData
T >: ServiceMessage
] {
this: SimonaService[S] =>
this: TypedSimonaService[T] =>

override def idleExternal(implicit stateData: S): Receive = {
case extMsg: DataMessageFromExt =>
override private[service] def idleExternal(implicit
stateData: S,
constantData: ServiceConstantStateData,
buffer: StashBuffer[T],
): Behavior[T] = Behaviors.receive {
case (_, WrappedExternalMessage(extMsg)) =>
val updatedStateData = handleDataMessage(extMsg)(stateData)
context become idle(updatedStateData)

case extResponseMsg: EvResponseMessage =>
buffer.unstashAll(idle(updatedStateData, constantData, buffer))

case (_, extResponseMsg: EvResponseMessage) =>
val updatedStateData =
handleDataResponseMessage(extResponseMsg)(stateData)
context become idle(updatedStateData)

buffer.unstashAll(idle(updatedStateData, constantData, buffer))

case (ctx, unsupported) =>
ctx.log.warn(s"Received unsupported message: $unsupported!")
buffer.stash(unsupported)
buffer.unstashAll(idleInternal)
}

/** Handle a message from outside the simulation
Expand Down
Loading
Loading