aboutsummaryrefslogtreecommitdiff
path: root/vfd-uav/src/main/scala
diff options
context:
space:
mode:
authorJakob Odersky <jodersky@gmail.com>2014-10-03 23:22:10 +0200
committerJakob Odersky <jodersky@gmail.com>2014-10-03 23:22:10 +0200
commitab19a9d1a3124f310bbb48de0779b5b96801940e (patch)
tree9392461ee5605dc10deae89d96ded417c26dc9a2 /vfd-uav/src/main/scala
parente269a40911f901cac415269916d34032e167a618 (diff)
downloadmavigator-ab19a9d1a3124f310bbb48de0779b5b96801940e.tar.gz
mavigator-ab19a9d1a3124f310bbb48de0779b5b96801940e.tar.bz2
mavigator-ab19a9d1a3124f310bbb48de0779b5b96801940e.zip
modularize project
Diffstat (limited to 'vfd-uav/src/main/scala')
-rw-r--r--vfd-uav/src/main/scala/vfd/uav/Connection.scala27
-rw-r--r--vfd-uav/src/main/scala/vfd/uav/DummyConnection.scala43
-rw-r--r--vfd-uav/src/main/scala/vfd/uav/FcuConnection.scala53
-rw-r--r--vfd-uav/src/main/scala/vfd/uav/Framer.scala70
4 files changed, 193 insertions, 0 deletions
diff --git a/vfd-uav/src/main/scala/vfd/uav/Connection.scala b/vfd-uav/src/main/scala/vfd/uav/Connection.scala
new file mode 100644
index 0000000..b4e6493
--- /dev/null
+++ b/vfd-uav/src/main/scala/vfd/uav/Connection.scala
@@ -0,0 +1,27 @@
+package vfd.uav
+
+import akka.actor.Actor
+import akka.actor.ActorRef
+import akka.actor.Props
+import scala.collection.mutable.ArrayBuffer
+
+object Connection {
+ def dummy = Props(classOf[DummyConnection])
+ def fcu(port: String, baud: Int) = Props(classOf[FcuConnection], port, baud)
+
+ trait Event
+ trait Command
+ case object Register extends Command
+ case class NewDataFrame(df: DataFrame) extends Event
+
+}
+
+trait Connection {that: Actor =>
+ private val _clients = new ArrayBuffer[ActorRef]
+ def clients = _clients.toSeq
+ def register(client: ActorRef) = {
+ _clients += client;
+ that.context.watch(client)
+ }
+ def unregister(client: ActorRef) = _clients -= client
+}
diff --git a/vfd-uav/src/main/scala/vfd/uav/DummyConnection.scala b/vfd-uav/src/main/scala/vfd/uav/DummyConnection.scala
new file mode 100644
index 0000000..bf8714f
--- /dev/null
+++ b/vfd-uav/src/main/scala/vfd/uav/DummyConnection.scala
@@ -0,0 +1,43 @@
+package vfd.uav
+
+import akka.actor.Actor
+import akka.actor.Terminated
+import scala.concurrent.duration.FiniteDuration
+import java.util.concurrent.TimeUnit._
+
+class DummyConnection extends Actor with Connection {
+ import context._
+
+ var time = 0.0
+ val messageInterval = FiniteDuration(20, MILLISECONDS)
+
+ def flightData(time: Double) = {
+ val speed = 5.0 / 1000
+ val roll = 5.0/180*math.Pi
+ val pitch = 10.0/180*math.Pi
+ Connection.NewDataFrame(DataFrame(
+ roll,
+ pitch,
+ (roll * time * speed) % math.Pi,
+ (pitch * time * speed),
+ 22
+ ))
+ }
+
+
+ override def preStart() = {
+ context.system.scheduler.schedule(messageInterval, messageInterval){
+ time += messageInterval.toMillis
+ clients foreach (_ ! flightData(time))
+ }
+ }
+
+ def receive = {
+ case Connection.Register => register(sender)
+ case Terminated(client) => unregister(client)
+ }
+
+}
+
+
+
diff --git a/vfd-uav/src/main/scala/vfd/uav/FcuConnection.scala b/vfd-uav/src/main/scala/vfd/uav/FcuConnection.scala
new file mode 100644
index 0000000..f9f267d
--- /dev/null
+++ b/vfd-uav/src/main/scala/vfd/uav/FcuConnection.scala
@@ -0,0 +1,53 @@
+package vfd.uav
+
+import akka.actor.Actor
+import akka.actor.Props
+import akka.actor.Terminated
+import akka.io.IO
+import com.github.jodersky.flow._
+import com.github.jodersky.flow.Serial
+
+
+class FcuConnection(port: String, baud: Int) extends Actor with Connection {
+ import context._
+
+ val settings = SerialSettings(
+ baud = this.baud,
+ characterSize = 8,
+ twoStopBits = false,
+ parity = Parity.None
+ )
+
+ override def preStart() = {
+ IO(Serial) ! Serial.Open(port, settings)
+ }
+
+ def receive = {
+ case Connection.Register => register(sender)
+ case Terminated(client) => unregister(client)
+ case Serial.CommandFailed(cmd: Serial.Open, reason: AccessDeniedException) => println("you're not allowed to open that port!")
+ case Serial.CommandFailed(cmd: Serial.Open, reason) => println("could not open port for some other reason: " + reason)
+ case Serial.Opened(settings) => {
+ val operator = sender
+
+ }
+ case Serial.Received(bstr) =>
+ val str = (new String(bstr.toArray, "UTF-8")).trim
+
+
+ val LinePattern = ".*[(](.+)[)].*".r
+ val Number = "([-]?\\d+[.]\\d+?)".r
+ val Components = "(.+),(.+),(.+),(.+),(.+)".r
+
+ str match {
+ case LinePattern(Components(Number(r),Number(p),Number(h),Number(a),Number(t))) =>
+ val data = Connection.NewDataFrame(DataFrame(r.toDouble, p.toDouble, h.toDouble, a.toDouble, t.toDouble))
+ println(data)
+ for (client <- clients) {
+ client ! data
+ }
+ case _ => println("unknown message: " + str)
+ }
+ }
+
+}
diff --git a/vfd-uav/src/main/scala/vfd/uav/Framer.scala b/vfd-uav/src/main/scala/vfd/uav/Framer.scala
new file mode 100644
index 0000000..f587c9e
--- /dev/null
+++ b/vfd-uav/src/main/scala/vfd/uav/Framer.scala
@@ -0,0 +1,70 @@
+package vfd.uav
+
+import scala.collection.mutable.ArrayBuffer
+
+class Framer {
+ final val MTU: Int = 1024
+
+ final val START: Byte = 0xfd.toByte
+ final val STOP: Byte = 0xfe.toByte
+ final val ESCAPE: Byte = 0xff.toByte
+
+ final val WAITING = 0
+ final val RECEIVING = 1
+ final val ESCAPING = 2
+
+ private val data = new Array[Byte](MTU)
+ private var index = 0
+ private var state = WAITING
+
+ private def add(byte: Byte): Unit = {
+ data(index) = byte
+ index += 1
+ if (index >= MTU) index = 0
+ }
+
+ private def clear(): Unit = index = 0
+
+
+ def push(byte: Byte): Option[Array[Byte]] = state match {
+ case WAITING =>
+ if (byte == START) {
+ clear()
+ state = RECEIVING
+ }
+ None
+
+ case RECEIVING => byte match {
+ case START =>
+ clear()
+ state = RECEIVING
+ None
+ case ESCAPE =>
+ state = ESCAPING
+ None
+ case STOP =>
+ state = WAITING
+ Some(java.util.Arrays.copyOfRange(data, 0, index))
+
+ case _ =>
+ add(byte)
+ None
+ }
+ case ESCAPING =>
+ add(byte)
+ state = RECEIVING
+ None
+ }
+
+ def push(bytes: Array[Byte]): Seq[Array[Byte]] = {
+ val messages = new ArrayBuffer[Array[Byte]]
+
+ for (byte <- bytes) push(byte) match {
+ case None => ()
+ case Some(message) => messages += message
+ }
+
+ messages
+ }
+
+} \ No newline at end of file