diff options
Diffstat (limited to 'flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala')
-rw-r--r-- | flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala b/flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala new file mode 100644 index 0000000..604dc74 --- /dev/null +++ b/flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala @@ -0,0 +1,99 @@ +package com.github.jodersky.flow + +import java.io.IOException + +import com.github.jodersky.flow.internal.InternalSerial + +import Serial.Close +import Serial.Closed +import Serial.Opened +import Serial.Received +import Serial.Write +import Serial.Wrote +import akka.actor.Actor +import akka.actor.ActorLogging +import akka.actor.ActorRef +import akka.actor.Terminated +import akka.actor.actorRef2Scala +import akka.util.ByteString + +class SerialOperator(handler: ActorRef, serial: InternalSerial) extends Actor with ActorLogging { + import context._ + + case class ReadException(ex: Exception) + + object Reader extends Thread { + + def enterReadLoop() = { + var continueReading = true + while (continueReading) { + try { + val data = ByteString(serial.read()) + handler ! Received(data) + } catch { + + //port is closing, stop thread gracefully + case ex: PortInterruptedException => { + continueReading = false + } + + //something else went wrong stop and tell actor + case ex: Exception => { + continueReading = false + self ! ReadException(ex) + } + } + } + } + + def name = this.getName() + + override def run() { + this.setName("flow-reader " + serial.port) + log.debug(name + ": started reader thread") + enterReadLoop() + log.debug(name + ": exiting") + } + + } + + override def preStart() = { + context watch handler + handler ! Opened(serial.port) + Reader.start() + } + + override def postStop = { + serial.close() + } + + def receive: Receive = { + + case Write(data, ack) => { + try { + val sent = serial.write(data.toArray) + if (ack) sender ! Wrote(ByteString(sent)) + } catch { + case ex: IOException => { + handler ! Closed(Some(ex)) + context stop self + } + } + } + + case Close => { + handler ! Closed(None) + context stop self + } + + case Terminated(`handler`) => context.stop(self) + + //go down with reader thread + case ReadException(ex) => { + handler ! Closed(Some(ex)) + context stop self + } + + } + +}
\ No newline at end of file |