Created
January 10, 2017 05:11
-
-
Save joesan/9e7bbc991d5999ad409e28046276fa65 to your computer and use it in GitHub Desktop.
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
package my.samples.deviceManager | |
import akka.actor.{Actor, ActorLogging, ActorRef, Kill, Props, Terminated} | |
import akka.io.IO | |
import akka.util.ByteString | |
import ch.jodersky.flow.Serial.Command | |
import ch.jodersky.flow.{Parity, Serial, SerialSettings} | |
import my.samples.deviceManager.DeviceExplorerActor.DeviceSerialNumber | |
import my.samples.deviceManager.DeviceWatcherActor.InitializeSerialPort | |
class Device1Actor(parent: ActorRef) extends Actor with ActorLogging { | |
val serialSettings = SerialSettings(38400, 8, twoStopBits = true, Parity(0)) | |
val writeMessage = "{<}D000 ~C5" + "\r\n" | |
val ioSerial = IO(Serial) | |
override def receive: Receive = { | |
case InitializeSerialPort(serialPort) => | |
ioSerial ! Serial.Open(serialPort, serialSettings) | |
case Serial.CommandFailed(cmd, reason) => | |
log.error(s"Connection failed, stopping terminal. Reason: $reason") | |
parent ! Kill | |
case Serial.Opened(port) => | |
log.info(s"Port $port is now open.") | |
self ! writeMessage | |
context become checkSerial(sender, "", "") | |
} | |
def parseSerialNumber(message: String): Option[String] = { | |
val regex = """D003 S/N\|([^~]+)~""".r.unanchored | |
message match { | |
case regex(c) => Some(c) | |
case _ => None | |
} | |
} | |
def parseEndOfSerial(message: String): Option[String] = { | |
val regex = """D006 ([^~]+)~""".r.unanchored | |
message match { | |
case regex(c) => Some(c) | |
case _ => None | |
} | |
} | |
def checkSerial(operator: ActorRef, appendedMsg: String, serial: String): Receive = { | |
case Serial.Received(data) => | |
val newMsg = data.decodeString("windows-1250") | |
val latestMessages = s"$appendedMsg$newMsg" | |
if (serial.isEmpty) { | |
parseSerialNumber(latestMessages) match { | |
case Some(serialNumber) => | |
// TODO inject serialNumber into ThingWorx | |
log.info(s"serial number parsed is $serialNumber") | |
context become checkSerial(operator, latestMessages, serialNumber) | |
case None => | |
context become checkSerial(operator, latestMessages, "") | |
} | |
} else { | |
parseEndOfSerial(latestMessages) match { | |
case Some(_) => | |
context become opened(operator, "", serial) | |
case None => | |
context become checkSerial(operator, latestMessages, serial) | |
} | |
} | |
case str: String => | |
operator ! Serial.Write(ByteString(str)) | |
} | |
def opened(operator: ActorRef, appendedMsg: String, serial: String): Receive = { | |
case Serial.Received(data) => | |
val newMsg = data.decodeString("windows-1250") | |
val latestMessages = s"$appendedMsg$newMsg" | |
log.info(s"Received data: $latestMessages with serial $serial ${context.parent.path}") | |
context become opened(operator, latestMessages, serial) | |
case Serial.Closed => | |
log.info("Operator closed normally, exiting terminal.") | |
context stop self | |
case Terminated(`operator`) => | |
log.error("Operator crashed unexpectedly, exiting terminal.") | |
context stop self | |
case ":q" => | |
log.info("q from opened ") | |
operator ! Serial.Close | |
case DeviceSerialNumber => | |
log.info("device serial request") | |
parent ! serial | |
} | |
} | |
object Device1Actor { | |
def props(parent: ActorRef) = Props(new Device1Actor(parent)) | |
} |
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
package my.samples.deviceManager | |
import akka.actor.{Actor, ActorLogging, ActorRef, Props} | |
import akka.util.Timeout | |
import my.samples.deviceManager.DeviceExplorerActor.DeviceSerialNumber | |
import my.samples.deviceManager.DeviceWatcherActor.InitializeSerialPort | |
import akka.pattern.ask | |
import scala.concurrent.Await | |
import scala.concurrent.duration._ | |
class DeviceExplorerActor extends Actor with ActorLogging { | |
implicit val timeout = Timeout(4.seconds) | |
def tryDevices(port: String, actorRef: ActorRef): String = { | |
actorRef ! InitializeSerialPort(port) | |
Await.result((actorRef ? DeviceSerialNumber).mapTo[String], 4.seconds) | |
} | |
def receive: Receive = { | |
case InitializeSerialPort(serialPort) => | |
val device1Actor = s"device1$serialPort" | |
val device2Actor = s"device2$serialPort" | |
if(tryDevices(serialPort, context.actorOf(Device1Actor.props(self), device1Actor)) == "") { // try Device1 | |
log.info(s"found Device1 serial device at port $serialPort") | |
} else if (tryDevices(serialPort, context.actorOf(Device2Actor.props(self), device2Actor)) == "") { // try Device2 | |
log.info(s"found Device2 serial device at port $serialPort") | |
} else { // nothing worked out, log and send a message to SupervisorActor | |
log.info(s"unknown serial device on port $serialPort") | |
} | |
} | |
} | |
object DeviceExplorerActor { | |
case object DeviceSerialNumber | |
def props = Props(new DeviceExplorerActor) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment