aboutsummaryrefslogtreecommitdiff
path: root/mavigator-uav/src/main/scala/mavigator/uav/Connection.scala
blob: 7399657f23ae36102bc39f8f7ff3b3c67e0779c2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package mavigator.uav

import akka.actor.ActorLogging
import scala.collection.mutable.ArrayBuffer

import akka.actor.Actor
import akka.actor.ActorRef
import akka.actor.Terminated
import akka.actor.actorRef2Scala
import akka.util.ByteString

/** Protocol definition. */
object Connection {

  /** Any messages received and transmitted by actors implementing this protocol. */
  sealed trait Message

  /** Messages emitted by actors implementing this protocol. */
  trait Event extends Message

  /** Received data from the uav (or any other systems on the link) */
  case class Received(bstr: ByteString) extends Event

  /** The connection closed or could not be opened */
  case class Closed(message: String) extends Event

  /** Messages that can be received by actors implementing this protocol. */
  trait Command extends Message

  /** Register the sender to be notified on events */
  case object Register extends Command

  case class Unregister(client: ActorRef) extends Command

  /** Send given bytes out to the uav (or any other systems on the link) */
  case class Send(bstr: ByteString) extends Command

}

/** Common behavior of connection actors. */
trait Connection { myself: Actor with ActorLogging =>

  private val _clients = new ArrayBuffer[ActorRef]

  /** Current clients that should be notified on incoming messages. */
  def clients = _clients.toSeq

  /** Adds a client to the client list and acquires a deathwatch. */
  protected def register(client: ActorRef): Unit = {
    _clients += client
    myself.context.watch(client)
    myself.log.info("Client registered {}", client)
  }

  /** Remove client and release deathwatch. */
  protected def unregister(client: ActorRef): Unit = if (clients contains client) {
    _clients -= client
    myself.context.unwatch(client)
    myself.log.info("Client unregistered {}", client)
  }

  /** Sends a message to all registered clients. */
  protected def sendAll(msg: Any): Unit = clients foreach (_ ! msg)

  /** Common registration behavior. Manages the messages `Register` and `Terminated` by
    * registering and unregistering clients. */
  protected def handleRegistration: Receive = {
    case Connection.Register => register(sender)
    case Terminated(client) => unregister(client)
    case other => myself.log.warning("Unknown message: {}", other)
  }

}