Skip to content

Commit 4eaa3a2

Browse files
committed
WIP default message handlers
1 parent ad9b141 commit 4eaa3a2

File tree

10 files changed

+254
-185
lines changed

10 files changed

+254
-185
lines changed

cmd/src/main/scala/chargepoint/docile/test/InteractiveOcppTest.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package chargepoint.docile
22
package test
33

44
import chargepoint.docile.dsl._
5-
import com.thenewmotion.ocpp.VersionFamily
5+
import com.thenewmotion.ocpp.{Version, Version1X, VersionFamily}
66
import com.thenewmotion.ocpp.messages.v1x.{CentralSystemReq, CentralSystemReqRes, CentralSystemRes, ChargePointReq, ChargePointReqRes, ChargePointRes}
77
import com.thenewmotion.ocpp.messages.v20._
88
import com.thenewmotion.ocpp.messages.{ReqRes, Request, Response}
@@ -61,6 +61,7 @@ object InteractiveOcpp1XTest {
6161

6262
trait V1XPromptCommands extends InteractiveOcppTest.PromptCommands[
6363
VersionFamily.V1X.type,
64+
Version1X,
6465
CentralSystemReq,
6566
CentralSystemRes,
6667
CentralSystemReqRes,
@@ -98,6 +99,7 @@ object InteractiveOcpp20Test {
9899

99100
trait V20PromptCommands extends InteractiveOcppTest.PromptCommands[
100101
VersionFamily.V20.type,
102+
Version.V20.type,
101103
CsmsRequest,
102104
CsmsResponse,
103105
CsmsReqRes,
@@ -114,7 +116,7 @@ object InteractiveOcppTest {
114116

115117
new InteractiveOcpp1XTest {
116118

117-
private def connDat = connectionData
119+
private def connDat = connection
118120

119121
implicit val csmsMessageTypes = VersionFamily.V1XCentralSystemMessages
120122
implicit val csMessageTypes = VersionFamily.V1XChargePointMessages
@@ -139,7 +141,7 @@ object InteractiveOcppTest {
139141

140142
new InteractiveOcpp20Test {
141143

142-
private def connDat = connectionData
144+
private def connDat = connection
143145

144146
implicit val csmsMessageTypes = VersionFamily.V20CsmsMessages
145147
implicit val csMessageTypes = VersionFamily.V20CsMessages
@@ -162,6 +164,7 @@ object InteractiveOcppTest {
162164

163165
trait PromptCommands[
164166
VFam <: VersionFamily,
167+
VersionBound <: Version,
165168
OutReq <: Request,
166169
InRes <: Response,
167170
OutReqRes[_ <: OutReq, _ <: InRes] <: ReqRes[_, _],
@@ -170,7 +173,7 @@ object InteractiveOcppTest {
170173
InReqRes[_ <: InReq, _ <: OutRes] <: ReqRes[_, _]
171174
] {
172175

173-
protected def connectionData: OcppConnectionData[VFam, OutReq, InRes, OutReqRes, InReq, OutRes, InReqRes]
176+
protected def connectionData: DocileConnection[VFam, VersionBound, OutReq, InRes, OutReqRes, InReq, OutRes, InReqRes]
174177

175178
def q: Unit =
176179
connectionData.receivedMsgManager.currentQueueContents foreach println

core/src/main/scala/chargepoint/docile/dsl/CoreOps.scala

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import scala.util.{Failure, Success, Try}
1313
import com.thenewmotion.ocpp.json.api.{OcppError, OcppException}
1414
import com.thenewmotion.ocpp.messages.{ReqRes, Request, Response}
1515
import com.typesafe.scalalogging.Logger
16-
import expectations.{IncomingMessage => GenericIncomingMessage}
1716
import org.slf4j.LoggerFactory
1817

1918
trait CoreOps[
@@ -26,13 +25,16 @@ trait CoreOps[
2625
InReqRes[_ <: InReq, _ <: OutRes] <: ReqRes[_, _]
2726
] extends OpsLogging with MessageLogging {
2827

28+
type IncomingMessage =
29+
GenericIncomingMessage[OutReq, InRes, OutReqRes, InReq, OutRes, InReqRes]
30+
type IncomingMessageProcessor[+T] =
31+
GenericIncomingMessageProcessor[OutReq, InRes, OutReqRes, InReq, OutRes, InReqRes, T]
2932

3033
implicit val csmsMessageTypes: CsmsMessageTypesForVersionFamily[VFam, OutReq, InRes, OutReqRes]
3134
implicit val csMessageTypes: CsMessageTypesForVersionFamily[VFam, InReq, OutRes, InReqRes]
3235

3336
implicit def executionContext: ExecutionContext
3437

35-
type IncomingMessage = GenericIncomingMessage[OutReq, InRes, OutReqRes, InReq, OutRes, InReqRes]
3638
object IncomingMessage {
3739
def apply(res: InRes): IncomingMessage = GenericIncomingMessage[OutReq, InRes, OutReqRes, InReq, OutRes, InReqRes](res)
3840
def apply(req: InReq, respond: OutRes => Unit): IncomingMessage = GenericIncomingMessage[OutReq, InRes, OutReqRes, InReq, OutRes, InReqRes](req, respond)
@@ -42,7 +44,7 @@ trait CoreOps[
4244
val logger = Logger(LoggerFactory.getLogger("script"))
4345
def say(m: String): Unit = logger.info(m)
4446

45-
protected def connectionData: OcppConnectionData[VFam, OutReq, InRes, OutReqRes, InReq, OutRes, InReqRes]
47+
protected def connectionData: DocileConnection[VFam, _, OutReq, InRes, OutReqRes, InReq, OutRes, InReqRes]
4648

4749
/**
4850
* Send an OCPP request to the Central System under test.
@@ -79,6 +81,15 @@ trait CoreOps[
7981
}
8082
}
8183

84+
// WIP an operation to add a default handler for a certain subset of incoming messages
85+
def handlingIncomingMessages[T](proc: IncomingMessageProcessor[_])(f: => T): T = {
86+
connectionData.pushIncomingMessageHandler(proc)
87+
val result = f
88+
connectionData.popIncomingMessageHandler()
89+
90+
result
91+
}
92+
8293
def awaitIncoming(num: Int)(implicit awaitTimeout: AwaitTimeout): Seq[IncomingMessage] = {
8394

8495
val timeout = awaitTimeout.toDuration

core/src/main/scala/chargepoint/docile/dsl/expectations/IncomingMessage.scala renamed to core/src/main/scala/chargepoint/docile/dsl/GenericIncomingMessage.scala

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
package chargepoint.docile
2-
package dsl
3-
package expectations
1+
package chargepoint.docile.dsl
42

5-
import scala.language.higherKinds
6-
import com.thenewmotion.ocpp.messages.{ReqRes, Request, Response}
73
import com.thenewmotion.ocpp.json.api.OcppError
4+
import com.thenewmotion.ocpp.messages.{ReqRes, Request, Response}
5+
6+
import scala.language.higherKinds
87

9-
sealed trait IncomingMessage[
8+
sealed trait GenericIncomingMessage[
109
OutgoingReqBound <: Request,
1110
IncomingResBound <: Response,
1211
OutgoingReqRes[_ <: OutgoingReqBound, _ <: IncomingResBound] <: ReqRes[_, _],
@@ -15,7 +14,7 @@ sealed trait IncomingMessage[
1514
IncomingReqRes[_ <: IncomingReqBound, _ <: OutgoingResBound] <: ReqRes[_, _]
1615
]
1716

18-
object IncomingMessage {
17+
object GenericIncomingMessage {
1918
def apply[
2019
OutReq <: Request,
2120
InRes <: Response,
@@ -90,7 +89,7 @@ case class IncomingResponse[
9089
InReqRes[_ <: InReq, _ <: OutRes] <: ReqRes[_, _]
9190
](
9291
res: InRes
93-
) extends IncomingMessage[
92+
) extends GenericIncomingMessage[
9493
OutReq,
9594
InRes,
9695
OutReqRes,
@@ -109,7 +108,7 @@ case class IncomingRequest[
109108
](
110109
req: InReq,
111110
respond: OutRes => Unit
112-
) extends IncomingMessage[
111+
) extends GenericIncomingMessage[
113112
OutReq,
114113
InRes,
115114
OutReqRes,
@@ -125,7 +124,7 @@ case class IncomingError[
125124
InReq <: Request,
126125
OutRes <: Response,
127126
InReqRes[_ <: InReq, _ <: OutRes] <: ReqRes[_, _]
128-
](error: OcppError) extends IncomingMessage[
127+
](error: OcppError) extends GenericIncomingMessage[
129128
OutReq,
130129
InRes,
131130
OutReqRes,
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package chargepoint.docile.dsl
2+
3+
import com.thenewmotion.ocpp.messages.{ReqRes, Request, Response}
4+
5+
import scala.language.higherKinds
6+
7+
/**
8+
* A partial function with side effects working on incoming OCPP messages
9+
*/
10+
trait GenericIncomingMessageProcessor[
11+
OutgoingReqBound <: Request,
12+
IncomingResBound <: Response,
13+
OutgoingReqRes[_ <: OutgoingReqBound, _ <: IncomingResBound] <: ReqRes[_, _],
14+
IncomingReqBound <: Request,
15+
OutgoingResBound <: Response,
16+
IncomingReqRes[_ <: IncomingReqBound, _ <: OutgoingResBound] <: ReqRes[_, _],
17+
+T
18+
] {
19+
type IncomingMessage = GenericIncomingMessage[
20+
OutgoingReqBound,
21+
IncomingResBound,
22+
OutgoingReqRes,
23+
IncomingReqBound,
24+
OutgoingResBound,
25+
IncomingReqRes
26+
]
27+
28+
/** Whether this processor can do something with a certain incoming message */
29+
def accepts(msg: IncomingMessage): Boolean
30+
31+
/**
32+
* The outcome of applying this processor to the given incoming message.
33+
*
34+
* Applying the processor do a message outside of its domain should throw
35+
* a MatchError.
36+
*/
37+
def result(msg: IncomingMessage): T
38+
39+
/**
40+
* Execute the side effects of this processor.
41+
*
42+
* In an OCPP test, this is supposed to happen when an assertion expecting a
43+
* certain incoming message has received an inomcing message that matches
44+
* the expectation.
45+
*/
46+
def fireSideEffects(msg: IncomingMessage): Unit
47+
48+
def lift(msg: IncomingMessage): Option[T] =
49+
if (accepts(msg))
50+
Some(result(msg))
51+
else
52+
None
53+
}
54+

0 commit comments

Comments
 (0)