aboutsummaryrefslogtreecommitdiff
path: root/flow-main
diff options
context:
space:
mode:
authorJakob Odersky <jodersky@gmail.com>2013-08-04 22:01:24 +0200
committerJakob Odersky <jodersky@gmail.com>2013-08-04 22:01:24 +0200
commit10c5c4e68d027e6bbabaad17381c79df24401027 (patch)
tree00b980f9cbe4e66eee265de36d8abb57614af514 /flow-main
parent9efeb44063001d4df0fb7a665a52bfcc52d5a290 (diff)
downloadakka-serial-10c5c4e68d027e6bbabaad17381c79df24401027.tar.gz
akka-serial-10c5c4e68d027e6bbabaad17381c79df24401027.tar.bz2
akka-serial-10c5c4e68d027e6bbabaad17381c79df24401027.zip
group serial settings in class, cosmetic changes & documentation
Diffstat (limited to 'flow-main')
-rw-r--r--flow-main/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java2
-rw-r--r--flow-main/src/main/scala/com/github/jodersky/flow/Serial.scala92
-rw-r--r--flow-main/src/main/scala/com/github/jodersky/flow/SerialManager.scala9
-rw-r--r--flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala78
-rw-r--r--flow-main/src/main/scala/com/github/jodersky/flow/SerialSettings.scala11
5 files changed, 124 insertions, 68 deletions
diff --git a/flow-main/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java b/flow-main/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java
index e7322ed..524803e 100644
--- a/flow-main/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java
+++ b/flow-main/src/main/java/com/github/jodersky/flow/internal/NativeSerial.java
@@ -69,7 +69,7 @@ class NativeSerial {
* @return E_IO on error */
native static int close(long serial);
- /**Sets debugging option. If debugging is enabled, detailed error message are printed from method calls. */
+ /**Sets debugging option. If debugging is enabled, detailed error message are printed (to stderr) from method calls. */
native static void debug(boolean value);
}
diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/Serial.scala b/flow-main/src/main/scala/com/github/jodersky/flow/Serial.scala
index 54fea6b..abc8f39 100644
--- a/flow-main/src/main/scala/com/github/jodersky/flow/Serial.scala
+++ b/flow-main/src/main/scala/com/github/jodersky/flow/Serial.scala
@@ -7,62 +7,100 @@ import akka.util.ByteString
/** Defines messages used by flow's serial IO layer. */
object Serial extends ExtensionKey[SerialExt] {
- /** A message extending this trait is to be viewed as a command, that is an out-bound message. */
+ /** A message extending this trait is to be viewed as a command, an out-bound message issued by the client to flow's API. */
trait Command
- /** A message extending this trait is to be viewed as an event, that is an in-bound message. */
+ /** A message extending this trait is to be viewed as an event, an in-bound message issued by flow to the client. */
trait Event
-
+
+ /** A command has failed. */
case class CommandFailed(command: Command, reason: Throwable) extends Event
/**
- * Open a new serial port. Send this command to the serial manager to request the opening of a serial port. The manager will
+ * Open a new serial port.
+ *
+ * Send this command to the serial manager to request the opening of a serial port. The manager will
* attempt to open a serial port with the specified parameters and, if successful, create a `SerialOperator` actor associated to the port.
- * The operator actor acts as an intermediate to the underlying native serial port, dealing with threading issues and the such. It will send any events
- * to the sender of this message.
- * The manager will respond with an `OpenFailed` in case the port could not be opened, or the operator will respond with `Opened`.
- * @param port name of serial port
- * @param baud baud rate to use with serial port
- * @param characterSize size of a character of the data sent through the serial port
- * @param twoStopBits set to use two stop bits instead of one
- * @param parity type of parity to use with serial port
+ * The operator actor acts as an intermediate to the underlying native serial port, dealing with threading issues and dispatching messages.
+ *
+ * In case the port is successfully opened, the operator will respond with an `Opened` message.
+ * In case the port cannot be opened, the manager will respond with a `CommandFailed` message.
+ *
+ * @param settings settings of serial port to open
+ */
+ case class Open(settings: SerialSettings) extends Command
+
+ /**
+ * A port has been successfully opened.
+ *
+ * Event sent by a port operator, indicating that a serial port was successfully opened. The sender
+ * of this message is the operator associated to the given serial port. Furthermore, an additional reference
+ * to the operator is provided in this class' `operator` field.
+ *
+ * @param settings settings of port that was opened
+ * @param operator operator associated with the serial port
*/
- case class Open(port: String, baud: Int, characterSize: Int = 8, twoStopBits: Boolean = false, parity: Parity.Parity = Parity.None) extends Command
+ case class Opened(settings: SerialSettings, operator: ActorRef) extends Event
/**
- * Event sent from a port operator, indicating that a serial port was successfully opened. The sender of this message is the operator associated to the given serial port.
- * @param port name of serial port
- * @param baud baud rate to use with serial port
- * @param characterSize size of a character of the data sent through the serial port
- * @param twoStopBits set to use two stop bits instead of one
- * @param parity type of parity to use with serial port
+ * Register an actor to receive events.
+ *
+ * Send this command to a serial operator to register an actor for notification on the reception of data on the operator's associated port.
+ * Upon reception, data will be sent by the operator to registered actors in form of `Received` events.
+ *
+ * @param receiver actor to register
*/
- case class Opened(port: String, baud: Int, characterSize: Int, twoStopBits: Boolean, parity: Parity.Parity, operator: ActorRef) extends Event
-
-
case class Register(receiver: ActorRef) extends Command
+
+ /**
+ * Unregister an actor from receiving events.
+ *
+ * Send this command to a serial operator to unregister an actor for notification on the reception of data on the operator's associated port.
+ *
+ * @param receiver actor to unregister
+ */
case class Unregister(receiver: ActorRef) extends Command
/**
- * Event sent by operator, indicating that data was received from the operator's serial port.
- * @param data data received by port
+ * Data has been received.
+ *
+ * Event sent by an operator, indicating that data was received on the operator's serial port.
+ * Clients must register (see `Register`) with a serial operator to receive these events.
+ *
+ * @param data data received on the port
*/
case class Received(data: ByteString) extends Event
/**
- * Write data to serial port. Send this command to an operator to write the given data to its associated serial port.
+ * Write data to a serial port.
+ *
+ * Send this command to an operator to write the given data to its associated serial port.
+ * An acknowledgment may be set, in which case it is sent back to the sender on a successful write.
+ * Note that a successful write does not guarantee the actual transmission of data through the serial port,
+ * it merely guarantees that the data has been stored in the operating system's kernel buffer, ready to
+ * be written.
+ *
* @param data data to be written to port
* @param ack acknowledgment sent back to sender once data has been enqueued in kernel for sending
*/
case class Write(data: ByteString, ack: Event = NoAck) extends Command
- /** Special type of acknowledgment that is not sent back. */
+ /**
+ * Special type of acknowledgment that is not sent back.
+ */
case object NoAck extends Event
- /** Request closing of port. Send this command to an operator to close its associated port. */
+ /**
+ * Request closing of port.
+ *
+ * Send this command to an operator to close its associated port. The operator will respond
+ * with a `Closed` message upon closing the serial port.
+ */
case object Close extends Command
/**
+ * A port has been closed.
+ *
* Event sent from operator, indicating that its port has been closed.
*/
case object Closed extends Event
diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/SerialManager.scala b/flow-main/src/main/scala/com/github/jodersky/flow/SerialManager.scala
index 0d69213..b3128ac 100644
--- a/flow-main/src/main/scala/com/github/jodersky/flow/SerialManager.scala
+++ b/flow-main/src/main/scala/com/github/jodersky/flow/SerialManager.scala
@@ -20,6 +20,7 @@ import akka.actor.actorRef2Scala
/**
* Actor that manages serial port creation. Once opened, a serial port is handed over to
* a dedicated operator actor that acts as an intermediate between client code and the native system serial port.
+ * @see SerialOperator
*/
class SerialManager extends Actor with ActorLogging {
import SerialManager._
@@ -32,12 +33,12 @@ class SerialManager extends Actor with ActorLogging {
}
def receive = {
- case c @ Open(port, baud, cs, tsb, parity) => Try { InternalSerial.open(port, baud, cs, tsb, parity.id) } match {
+ case c @ Open(s) => Try { InternalSerial.open(s.port, s.baud, s.characterSize, s.twoStopBits, s.parity.id) } match {
case Failure(t) => sender ! CommandFailed(c, t)
case Success(serial) => {
- val operator = context.actorOf(Props(classOf[SerialOperator], serial), name = escapePortString(port))
- val opened = Opened(serial.port, serial.baud, serial.characterSize, serial.twoStopBits, Parity(serial.parity), operator)
- sender.tell(opened, operator)
+ val operator = context.actorOf(SerialOperator(serial), name = escapePortString(s.port))
+ val settings = SerialSettings(serial.port, serial.baud, serial.characterSize, serial.twoStopBits, Parity(serial.parity))
+ sender.tell(Opened(settings, operator), operator)
}
}
}
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
index 1c24729..3ac50c0 100644
--- a/flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala
+++ b/flow-main/src/main/scala/com/github/jodersky/flow/SerialOperator.scala
@@ -10,48 +10,19 @@ import akka.actor.Terminated
import akka.actor.actorRef2Scala
import akka.util.ByteString
import scala.collection.mutable.HashSet
+import akka.actor.Props
-/** Operator associated to an open serial port. All communication with a port is done via an operator. Operators are created though the serial manager. */
+/**
+ * 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(serial: InternalSerial) extends Actor with ActorLogging {
import SerialOperator._
import context._
- override def preStart() = {
- Reader.start()
- }
-
- override def postStop = {
- serial.close()
- }
-
- def receive: Receive = {
-
- case Register(actor) => receiversLock.synchronized{
- receivers += actor
- }
-
- case Unregister(actor) => receiversLock.synchronized{
- receivers -= actor
- }
-
- case Write(data, ack) => {
- val sent = serial.write(data.toArray)
- if (ack != NoAck) sender ! ack
- }
-
- case Close => {
- sendAllReceivers(Closed)
- context stop self
- }
-
- //go down with reader thread
- case ReadException(ex) => throw ex
-
- }
-
private val receivers = new HashSet[ActorRef]
private val receiversLock = new Object
- private def sendAllReceivers(msg: Any) = receiversLock.synchronized {
+ private def tellAllReceivers(msg: Any) = receiversLock.synchronized {
receivers.foreach { receiver =>
receiver ! msg
}
@@ -63,7 +34,7 @@ class SerialOperator(serial: InternalSerial) extends Actor with ActorLogging {
while (continueReading) {
try {
val data = ByteString(serial.read())
- sendAllReceivers(Received(data))
+ tellAllReceivers(Received(data))
} catch {
//port is closing, stop thread gracefully
@@ -88,8 +59,43 @@ class SerialOperator(serial: InternalSerial) extends Actor with ActorLogging {
}
}
+ override def preStart() = {
+ Reader.start()
+ }
+
+ override def postStop = {
+ serial.close()
+ }
+
+ def receive: Receive = {
+
+ case Register(actor) => receiversLock.synchronized {
+ receivers += actor
+ }
+
+ case Unregister(actor) => receiversLock.synchronized {
+ receivers -= actor
+ }
+
+ case Write(data, ack) => {
+ val sent = serial.write(data.toArray)
+ if (ack != NoAck) sender ! ack
+ }
+
+ case Close => {
+ tellAllReceivers(Closed)
+ context stop self
+ }
+
+ //go down with reader thread
+ case ReadException(ex) => throw ex
+
+ }
+
}
object SerialOperator {
private case class ReadException(ex: Exception)
+
+ def apply(serial: InternalSerial) = Props(classOf[SerialOperator], serial)
} \ No newline at end of file
diff --git a/flow-main/src/main/scala/com/github/jodersky/flow/SerialSettings.scala b/flow-main/src/main/scala/com/github/jodersky/flow/SerialSettings.scala
new file mode 100644
index 0000000..a3bc5e4
--- /dev/null
+++ b/flow-main/src/main/scala/com/github/jodersky/flow/SerialSettings.scala
@@ -0,0 +1,11 @@
+package com.github.jodersky.flow
+
+/**
+ * Groups settings used in communication over a serial port.
+ * @param port name of serial port
+ * @param baud baud rate to use with serial port
+ * @param characterSize size of a character of the data sent through the serial port
+ * @param twoStopBits set to use two stop bits instead of one
+ * @param parity type of parity to use with serial port
+ */
+case class SerialSettings(port: String, baud: Int, characterSize: Int = 8, twoStopBits: Boolean = false, parity: Parity.Parity = Parity.None) \ No newline at end of file