aboutsummaryrefslogtreecommitdiff
path: root/mavigator-uav/src/main/scala/mavigator/uav/SerialConnection.scala
diff options
context:
space:
mode:
Diffstat (limited to 'mavigator-uav/src/main/scala/mavigator/uav/SerialConnection.scala')
-rw-r--r--mavigator-uav/src/main/scala/mavigator/uav/SerialConnection.scala136
1 files changed, 136 insertions, 0 deletions
diff --git a/mavigator-uav/src/main/scala/mavigator/uav/SerialConnection.scala b/mavigator-uav/src/main/scala/mavigator/uav/SerialConnection.scala
new file mode 100644
index 0000000..24c70a1
--- /dev/null
+++ b/mavigator-uav/src/main/scala/mavigator/uav/SerialConnection.scala
@@ -0,0 +1,136 @@
+package mavigator.uav
+
+import java.util.concurrent.TimeUnit.MILLISECONDS
+
+import scala.concurrent.duration.FiniteDuration
+
+import org.mavlink.enums.MavAutopilot
+import org.mavlink.enums.MavModeFlag
+import org.mavlink.enums.MavState
+import org.mavlink.enums.MavType
+import org.mavlink.messages.Heartbeat
+
+import com.github.jodersky.flow.Parity
+import com.github.jodersky.flow.Serial
+import com.github.jodersky.flow.SerialSettings
+
+import akka.actor.Actor
+import akka.actor.ActorLogging
+import akka.actor.ActorRef
+import akka.actor.Props
+import akka.actor.Terminated
+import akka.actor.actorRef2Scala
+import akka.io.IO
+
+class SerialConnection(
+ val systemId: Byte,
+ val componentId: Byte,
+ heartbeatInterval: Option[FiniteDuration],
+ port: String,
+ settings: SerialSettings) extends Actor with ActorLogging with Connection with MavlinkUtil {
+
+ import context._
+
+ override def preStart() = heartbeatInterval foreach { interval =>
+ context.system.scheduler.schedule(interval, interval) {
+ self ! Connection.Send(
+ assemble(
+ Heartbeat(
+ MavType.MavTypeGeneric.toByte,
+ MavAutopilot.MavAutopilotGeneric.toByte,
+ 0, //no base mode
+ 0, //no custom mode
+ MavState.MavStateActive.toByte,
+ 0 //TODO properly implement read-only fields
+ )
+ )
+ )
+ }
+ }
+
+ def _closed: Receive = {
+
+ case Connection.Register =>
+ register(sender)
+ IO(Serial) ! Serial.Open(port, settings)
+ context become opening
+
+ case Connection.Send(_) =>
+ IO(Serial) ! Serial.Open(port, settings)
+ context become opening
+
+ }
+
+ def _opening: Receive = {
+
+ case Serial.CommandFailed(cmd: Serial.Open, reason) =>
+ sendAll(Connection.Closed(reason.toString))
+ context become closed
+
+ case Serial.Opened(_) =>
+ context watch (sender)
+ context become opened(sender)
+
+ case Connection.Send(_) => () // ignore
+ /*
+ * During opening, any outgoing messages are discarded.
+ * By using some kind of message stashing, maybe messages could be treated
+ * once the port has been opened. However, in such a case failure also needs
+ * to be considered, thus complicating the protocol. Since opening is typically
+ * quite fast and since mavlink uses heartbeats and acknowledgements (in certain
+ * circumstances) anyway, keeping messages is not really required.
+ */
+
+ }
+
+ def _opened(operator: ActorRef): Receive = {
+
+ case Terminated(`operator`) =>
+ sendAll(Connection.Closed("Serial connection crashed."))
+ context become closed
+
+ case Serial.Closed =>
+ sendAll(Connection.Closed("Serial connection was closed."))
+ context become closed
+
+ case Serial.Received(bstr) =>
+ sendAll(Connection.Received(bstr))
+ incoming.push(bstr)
+
+ case Connection.Send(bstr) =>
+ outgoing.push(bstr)
+ //no sending is currently enabled
+
+ }
+
+ def closed = _closed orElse handleRegistration
+ def opening = _opening orElse handleRegistration
+ def opened(op: ActorRef) = _opened(op) orElse handleRegistration
+ override def receive = closed
+
+}
+
+object SerialConnection {
+ def apply(
+ systemId: Byte,
+ componentId: Byte,
+ heartbeatInterval: Int,
+ port: String,
+ baud: Int,
+ tsb: Boolean,
+ parity: Int): Props = {
+
+ val settings = SerialSettings(
+ baud,
+ 8,
+ tsb,
+ parity match {
+ case 0 => Parity.None
+ case 1 => Parity.Odd
+ case 2 => Parity.Even
+ })
+ val hb = if (heartbeatInterval == 0) None else Some(FiniteDuration(heartbeatInterval, MILLISECONDS))
+
+ Props(classOf[SerialConnection], systemId, componentId, hb, port, settings)
+ }
+}