Last active
January 5, 2017 15:16
-
-
Save joesan/9c883161b610652cfb74385e8fba09e3 to your computer and use it in GitHub Desktop.
Akka Flow Serial Actor Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import akka.actor.{Actor, ActorRef, Props, Terminated} | |
import akka.util.ByteString | |
import ch.jodersky.flow.Serial | |
import com.typesafe.scalalogging.LazyLogging | |
import my.samples.deviceManager.DeviceWatcherActor.InitializeSerialPort | |
class DeviceExplorerActor(serialActorRef: ActorRef) | |
extends Actor with LazyLogging { | |
def receive: Receive = { | |
case InitializeSerialPort(serialPort, serialSettings) => | |
serialActorRef ! Serial.Open(serialPort, serialSettings) | |
case Serial.CommandFailed(cmd, reason) => | |
logger.error(s"Connection failed, stopping terminal. Reason: $reason") | |
//context stop self | |
case Serial.Opened(port) => | |
logger.info(s"Port $port is now open.") | |
context become opened(sender) | |
//context watch sender // get notified in the event the operator crashes | |
} | |
def opened(operator: ActorRef): Receive = { | |
case Serial.Received(data) => | |
logger.info(s"Received data: " + data) | |
case Serial.Closed => | |
logger.info("Operator closed normally, exiting terminal.") | |
context stop self | |
case Terminated(`operator`) => | |
logger.error("Operator crashed unexpectedly, exiting terminal.") | |
context stop self | |
case ":q" => | |
operator ! Serial.Close | |
case str: String => | |
operator ! Serial.Write(ByteString(str)) | |
} | |
} | |
object DeviceExplorerActor { | |
def props(serialActorRef: ActorRef) = | |
Props(new DeviceExplorerActor(serialActorRef)) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import akka.actor.{Actor, ActorRef, Kill, Props} | |
import ch.jodersky.flow.{Serial, SerialSettings} | |
import com.typesafe.scalalogging.LazyLogging | |
import my.samples.deviceManager.DeviceWatcherActor.{InitializeSerialPort, Terminate} | |
class DeviceWatcherActor(portSettings: Map[String, SerialSettings], serialActorRef: ActorRef) | |
extends Actor with LazyLogging { | |
val ports = portSettings.keys.toSeq | |
val portActorRef = | |
ports.map(port => port -> context.actorOf(DeviceExplorerActor.props(serialActorRef))).toMap | |
override def preStart() = { | |
val cmd = Serial.Watch() | |
serialActorRef ! Serial.Watch() | |
logger.info(s"Watching ${cmd.directory} for new devices.") | |
} | |
override def receive: Receive = { | |
case Terminate => | |
portActorRef.values.toSeq.foreach(actorRef => actorRef ! ":q") | |
context stop self | |
case Serial.CommandFailed(w: Serial.Watch, err) => | |
logger.error(s"Could not get a watch on ${w.directory}.", err) | |
self ! Kill // TODO: catch the ActorKilledException in the parent | |
case Serial.Connected(path) => | |
logger.info(s"New device: $path") | |
val found: Option[(String, SerialSettings)] = portSettings.find(_._1.matches(path)) | |
found match { | |
case Some((port, serialSettings)) => | |
logger.info(s"Device is a serial device.") | |
portActorRef(port) ! InitializeSerialPort(port, serialSettings) | |
case None => | |
logger.warn(s"Device is NOT serial device.") | |
} | |
} | |
} | |
object DeviceWatcherActor { | |
def props(portSettings: Map[String, SerialSettings], serialActorRef: ActorRef) = | |
Props(new DeviceWatcherActor(portSettings, serialActorRef)) | |
case object Terminate | |
case class InitializeSerialPort(port: String, serialSettings: SerialSettings) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I don't think that the
serialActorRef
parameter is required here (from a quick, superficial overview). You can simply useIO(Serial)
instead. This uses the Akka extension mechanism to provide you with the same single actor instance, regardless of the number of invocations.