aboutsummaryrefslogtreecommitdiff
path: root/vfd-backend/app
diff options
context:
space:
mode:
Diffstat (limited to 'vfd-backend/app')
-rw-r--r--vfd-backend/app/controllers/Application.scala31
-rw-r--r--vfd-backend/app/plugins/UavPlugin.scala44
-rw-r--r--vfd-backend/app/views/index.scala.html47
-rw-r--r--vfd-backend/app/views/main.scala.html63
-rw-r--r--vfd-backend/app/views/panels/eicas.scala.html35
-rw-r--r--vfd-backend/app/views/panels/pfd.scala.html31
6 files changed, 251 insertions, 0 deletions
diff --git a/vfd-backend/app/controllers/Application.scala b/vfd-backend/app/controllers/Application.scala
new file mode 100644
index 0000000..5a473b4
--- /dev/null
+++ b/vfd-backend/app/controllers/Application.scala
@@ -0,0 +1,31 @@
+package controllers
+
+import play.api._
+import play.api.mvc._
+import play.api.Play.current
+import play.api.mvc.WebSocket.FrameFormatter
+
+import play.api.libs.functional.syntax._
+import play.api.libs.json._
+
+import vfd.uav.DataFrame
+import plugins.UavPlugin
+
+
+object Application extends Controller {
+
+ def use[A <: Plugin](implicit app: Application, m: Manifest[A]) = {
+ app.plugin[A].getOrElse(throw new RuntimeException(m.runtimeClass.toString + " plugin should be available at this point"))
+ }
+
+ def index() = Action {
+ Ok(views.html.index())
+ }
+
+ implicit val dataFrameFormat = Json.format[DataFrame]
+ implicit val dataFrameFormatter = FrameFormatter.jsonFrame[DataFrame]
+
+ def socket = WebSocket.acceptWithActor[String, DataFrame] { request =>
+ out => use[UavPlugin].register(out)
+ }
+} \ No newline at end of file
diff --git a/vfd-backend/app/plugins/UavPlugin.scala b/vfd-backend/app/plugins/UavPlugin.scala
new file mode 100644
index 0000000..a94ed9d
--- /dev/null
+++ b/vfd-backend/app/plugins/UavPlugin.scala
@@ -0,0 +1,44 @@
+package plugins
+
+import akka.actor._
+import play.api._
+import play.api.libs.concurrent.Akka
+import vfd.uav._
+
+class UavPlugin(app: Application) extends Plugin {
+
+ object conf {
+ private val config = app.configuration.getConfig("uav")
+ val connection = config.flatMap(_.getString("connection")).getOrElse("mock")
+ val port = config.flatMap(_.getString("port")).getOrElse("/dev/ttyACM0")
+ val baud = config.flatMap(_.getInt("baud")).getOrElse(9600)
+ }
+
+ lazy val connection: ActorRef = {
+ val props = conf.connection match {
+ case "mock" => Connection.dummy
+ case "fcu" => Connection.fcu(conf.port, conf.baud)
+ case _ => throw new RuntimeException("Unknown connection type.")
+ }
+ Akka.system(app).actorOf(props, name = "uav")
+ }
+
+ def register(out: ActorRef): Props = Repeater(out, connection)
+
+}
+
+class Repeater(out: ActorRef, connection: ActorRef) extends Actor {
+
+ override def preStart = {
+ connection ! Connection.Register
+ }
+
+ def receive = {
+ case Connection.NewDataFrame(df) => out ! df
+ }
+
+ }
+
+object Repeater {
+ def apply(out: ActorRef, connection: ActorRef) = Props(classOf[Repeater], out, connection)
+} \ No newline at end of file
diff --git a/vfd-backend/app/views/index.scala.html b/vfd-backend/app/views/index.scala.html
new file mode 100644
index 0000000..654c2a1
--- /dev/null
+++ b/vfd-backend/app/views/index.scala.html
@@ -0,0 +1,47 @@
+@main("Main"){
+
+ <div class="row">
+ <div class="col-lg-2">
+ <div style="width: 100%; height: 450px; background-color: #000000; display: table;">
+ <div style="display: table-cell; text-align: center; vertical-align: middle;">no feed</div>
+ </div>
+ </div>
+ <div class="col-lg-6">
+ @panels.pfd()
+ <!-- <div style="width: 100%; height: 450px; background-color: #000000; display: table;">
+ <div style="display: table-cell; text-align: center; vertical-align: middle;">no feed</div>
+ </div> -->
+ </div>
+ <div class="col-lg-4">
+ station
+ <ul>
+ <li>server link</li>
+ <li>uav link</li>
+ </ul>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-lg-4">
+ uav
+ </div>
+ <div class="col-lg-4">
+
+ </div>
+ <div class="col-lg-4">
+ @panels.eicas()
+ </div>
+ </div>
+
+
+
+
+
+ <script type="text/javascript">
+
+ window.onload = function () {
+ var frontend = new Frontend('#attitude', '#heading', '#altitude')
+ frontend.main()
+ }
+ </script>
+}
+
diff --git a/vfd-backend/app/views/main.scala.html b/vfd-backend/app/views/main.scala.html
new file mode 100644
index 0000000..db894d2
--- /dev/null
+++ b/vfd-backend/app/views/main.scala.html
@@ -0,0 +1,63 @@
+@(title: String)(content: Html)
+
+<!DOCTYPE html>
+
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>VFD - @title</title>
+
+ <link rel="shortcut icon" href="@routes.Assets.at("images/logo.svg")">
+ <link rel="stylesheet" media="screen" href="@routes.Assets.at("lib/bootstrap/css/bootstrap.css")">
+ <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
+</head>
+<body>
+ <header>
+ <nav class="navbar navbar-inverse navbar-static-top" role="navigation">
+ <div class="container-fluid">
+ <!-- Brand and toggle get grouped for better mobile display -->
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-main-collapse">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <a class="navbar-brand" href="@routes.Application.index">
+ <!-- <img style="max-height: 100%;" src="@routes.Assets.at("images/logo-invert.svg")" alt="logo"> -->
+ Virtual Flight Deck
+ </a>
+ </div>
+
+ <!-- Collect the nav links, forms, and other content for toggling -->
+ <div class="collapse navbar-collapse" id="navbar-main-collapse">
+ <ul class="nav navbar-nav">
+ </ul>
+ <ul class="nav navbar-nav navbar-right">
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">options<b class="caret"></b></a>
+ <ul class="dropdown-menu">
+ <li>
+ <form method="POST" action="">
+ <button type="submit" style="width: 100%;" class="btn btn-default">Sign Out</button>
+ </form>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div><!-- /.navbar-collapse -->
+ </div><!-- /.container-fluid -->
+ </nav>
+ </header>
+
+ <div class="container-fluid">
+ @content
+ </div>
+
+ <script type="text/javascript" src="@routes.Assets.at("lib/vfd-frontend-fastopt.js")"></script>
+ <script type="text/javascript" src="@routes.Assets.at("lib/jquery/jquery.js")"></script>
+ <script type="text/javascript" src="@routes.Assets.at("lib/bootstrap/js/bootstrap.min.js")"></script>
+</body>
+</html> \ No newline at end of file
diff --git a/vfd-backend/app/views/panels/eicas.scala.html b/vfd-backend/app/views/panels/eicas.scala.html
new file mode 100644
index 0000000..211adba
--- /dev/null
+++ b/vfd-backend/app/views/panels/eicas.scala.html
@@ -0,0 +1,35 @@
+@()
+
+@led(condition: String) = @{
+ "images/leds/" + (condition match {
+ case "error" => "red-on.svg"
+ case "warn" => "yellow-on.svg"
+ case "good" => "green-on.svg"
+ case "unknown" => "none.svg"
+ case _ => "a"
+ })
+}
+
+@instrument(name: String, condition: String, status: String) = {
+ <tr>
+ <td>@name</td>
+ <td>
+ <img src="@routes.Assets.at(led(condition))" alt="@condition" width="15px">
+ </td>
+ <td>
+ <span class="status @condition">
+ @status
+ </span>
+ </td>
+ </tr>
+}
+
+
+<!-- <table class="control-table">
+ @instrument("engine1", "unknown", "0 rpm")
+ @instrument("engine2", "unknown", "1000 rpm")
+ @instrument("engine3", "unknown", "2080 rpm")
+ @instrument("engine4", "unknown", "1000 rpm")
+ @instrument("battery", "unknown", "3000Wh")
+ @instrument("power", "unknown", "2000W")
+</table --> \ No newline at end of file
diff --git a/vfd-backend/app/views/panels/pfd.scala.html b/vfd-backend/app/views/panels/pfd.scala.html
new file mode 100644
index 0000000..9c89d6a
--- /dev/null
+++ b/vfd-backend/app/views/panels/pfd.scala.html
@@ -0,0 +1,31 @@
+@()
+
+@instrument(name: String) = {
+ @defining("images/instruments/" + name + ".svg") { location =>
+ <object id="@name" type="image/svg+xml" data="@routes.Assets.at(location)" width="100%">Error loading image.</object>
+ }
+}
+
+
+<div class="row">
+ <div class="col-lg-4">
+
+ </div>
+ <div class="col-lg-4">
+ @instrument("attitude")
+ </div>
+ <div class="col-lg-4">
+ @instrument("altitude")
+ </div>
+</div>
+<div class="row">
+ <div class="col-lg-4">
+
+ </div>
+ <div class="col-lg-4">
+ @instrument("heading")
+ </div>
+ <div class="col-lg-4">
+ @instrument("distance")
+ </div>
+</div> \ No newline at end of file