aboutsummaryrefslogtreecommitdiff
path: root/flow/src/main/scala/com/github/jodersky/flow/SerialOperator.scala
blob: 5524125d424796118b91f881916d6701202266e5 (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
package com.github.jodersky.flow

import java.nio.ByteBuffer

import com.github.jodersky.flow.internal.Reader
import com.github.jodersky.flow.internal.ReaderDied
import com.github.jodersky.flow.internal.SerialConnection

import Serial.Close
import Serial.Closed
import Serial.NoAck
import Serial.Opened
import Serial.Write
import akka.actor.Actor
import akka.actor.ActorLogging
import akka.actor.ActorRef
import akka.actor.Props
import akka.actor.Terminated
import akka.actor.actorRef2Scala

/**
 * Operator associated to an open serial port. All communication with a port is done via an operator. Operators are created though the serial manager.
 * @see SerialManager
 */
class SerialOperator(connection: SerialConnection, bufferSize: Int, client: ActorRef) extends Actor with ActorLogging {
  import SerialOperator._
  import context._

  val readBuffer = ByteBuffer.allocateDirect(bufferSize)
  val reader = new Reader(connection, readBuffer, self, client)
  val writeBuffer = ByteBuffer.allocateDirect(bufferSize)

  context.watch(client)
  client ! Opened(connection.port)
  reader.start()

  override def postStop = {
    connection.close()
  }

  def receive: Receive = {

    case Write(data, ack) => {
      writeBuffer.clear()
      data.copyToBuffer(writeBuffer)
      val sent = connection.write(writeBuffer)
      if (ack != NoAck) sender ! ack(sent)
    }

    case Close => {
      client ! Closed
      context stop self
    }
    
    case Terminated(`client`) => {
      context stop self
    }

    //go down with reader thread
    case ReaderDied(ex) => throw ex

  }

}

object SerialOperator {
  def apply(connection: SerialConnection, bufferSize: Int, client: ActorRef) = Props(classOf[SerialOperator], connection, bufferSize, client)
}