move files around, add local js/css, start profiles

master
James Gao 2014-10-23 01:20:53 -07:00
rodzic 3ac85ba18b
commit 5034ed1ce1
14 zmienionych plików z 155 dodań i 49 usunięć

0
kiln/Adafruit_I2C.py 100755 → 100644
Wyświetl plik

Wyświetl plik

@ -1,5 +1,6 @@
import time
import os
import re
import time
import json
import traceback
import inspect
@ -8,15 +9,7 @@ import tornado.ioloop
import tornado.web
from tornado import websocket
cwd = os.path.split(os.path.abspath(__file__))[0]
class ManagerHandler(tornado.web.RequestHandler):
def initialize(self, manager):
self.manager = manager
class MainHandler(ManagerHandler):
def get(self):
return self.render("template.html", state=self.manager.state.__class__.__name__)
import paths
class ClientSocket(websocket.WebSocketHandler):
def initialize(self, parent):
@ -28,12 +21,46 @@ class ClientSocket(websocket.WebSocketHandler):
def on_close(self):
self.parent.clients.remove(self)
class ManagerHandler(tornado.web.RequestHandler):
def initialize(self, manager):
self.manager = manager
class MainHandler(ManagerHandler):
def get(self):
files = os.listdir(paths.profile_path)
fixname = lambda x: os.path.splitext(x)[0].replace("_", " ")
profiles = dict((fname, fixname(fname)) for fname in files)
return self.render(os.path.join(paths.html_templates, "main.html"),
state=self.manager.state.__class__.__name__,
profiles=profiles,
)
class DataRequest(ManagerHandler):
def get(self):
data = list(self.manager.history)
output = [dict(time=ts.time, temp=ts.temp) for ts in data]
self.write(json.dumps(output))
class ProfileHandler(tornado.web.RequestHandler):
def get(self, name):
try:
with open(os.path.join(paths.profile_path, name)) as fp:
self.write(fp.read())
except IOError:
self.write_error(404)
def post(self, name):
try:
schedule = self.get_argument("schedule")
fname = os.path.join(paths.profile_path, name)
with open(fname, 'w') as fp:
json.dump(schedule, fp)
self.write(dict(type="success"))
except IOError:
self.write_error(404)
except Exception as e:
self.write(dict(type="error", error=repr(e), msg=traceback.format_exc()))
class DoAction(ManagerHandler):
def _run(self, name, argfunc):
func = getattr(self.manager.state, name)
@ -68,16 +95,17 @@ class DoAction(ManagerHandler):
self._run(action, self.get_argument)
self.write(json.dumps(dict(type="success")))
except Exception as e:
self.write(json.dumps(dict(type="error", error=repr(e), msg=traceback.format_exc())))
self.write(json.dumps(dict(type="error", error=repr(e), msg=traceback.format_exc())))
class WebApp(object):
def __init__(self, manager, port=8888):
self.handlers = [
(r'/', MainHandler, dict(manager=manager)),
(r"/ws/", ClientSocket, dict(parent=self)),
(r"/temperature.json", DataRequest, dict(manager=manager)),
(r"/do/(.*)", DoAction, dict(manager=manager)),
(r"/(.*)", tornado.web.StaticFileHandler, dict(path=cwd)),
(r"^/$", MainHandler, dict(manager=manager)),
(r"^/ws/?$", ClientSocket, dict(parent=self)),
(r"^/temperature.json$", DataRequest, dict(manager=manager)),
(r"^/do/(.*)/?$", DoAction, dict(manager=manager)),
(r"^/profile/?(.*)$", ProfileHandler),
(r"^/(.*)$", tornado.web.StaticFileHandler, dict(path=paths.html_static)),
]
self.clients = []
self.port = port

Wyświetl plik

@ -84,10 +84,11 @@ class Cooling(State):
return Running, kwargs
class Running(State):
def __init__(self, parent, history, **kwargs):
def __init__(self, parent, history, start_time=None, **kwargs):
super(Running, self).__init__(parent)
self.start_time = start_time
self.profile = manager.Profile(therm=self.parent.therm, regulator=self.parent.regulator,
callback=self._notify, **kwargs)
callback=self._notify, start_time=start_time **kwargs)
self.history = history
def _notify(self, therm, setpoint, out):

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

File diff suppressed because one or more lines are too long

5
kiln/static/js/d3.v3.min.js vendored 100644

File diff suppressed because one or more lines are too long

4
kiln/static/js/jquery.min.js vendored 100644

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -1,31 +1,34 @@
var tempgraph = (function(module) {
module.Monitor = function(initial) {
this.temperature = initial;
this.profile = null;
//default to F
this.scalefunc = module.temp_to_F;
this.temp_suffix = "°F"
this.temp_prefix = ""
this.graph = new tempgraph.Graph();
this.graph = new module.Graph();
this._mapped = this.temperature.map(this._map_temp.bind(this));
this.graph.plot(this._mapped, "temperature", false);
this.update_temp(this.last());
this.updateTemp(this.last());
this._bindUI();
}
module.Monitor.prototype.update_temp = function(data) {
module.Monitor.prototype.updateTemp = function(data) {
var now = new Date(data.time*1000.);
var temp = this.scalefunc(data.temp);
var hourstr = now.getHours() % 12;
hourstr = hourstr == 0 ? 12 : hourstr;
var minstr = now.getMinutes();
minstr = minstr.length < 2 ? "0"+minstr : minstr;
var nowstr = hourstr + ":" + minstr + (now.getHours() >= 12 ? " pm" : " am");
var nowstr = module.format_time(now);
var tempstr = Math.round(temp*100) / 100;
$("#current_time").text(nowstr);
$("#current_temp").text(this.temp_prefix+tempstr+this.temp_suffix);
if (this.profile) {
var finish = module.format_time(this.profile.time_finish(now));
$("#profile_time_finish").text(finish);
}
//Adjust x and ylims
if (now > this.last().time) {
this.temperature.push(data);
@ -60,10 +63,14 @@ var tempgraph = (function(module) {
}
}
}
module.Monitor.prototype.update_UI = function(packet) {
}
module.Monitor.prototype.setProfile = function(profile) {
module.Monitor.prototype.setProfile = function(schedule, start_time) {
this.profile = new module.Profile(schedule, start_time);
var start = this.profile.time_start === undefined ?
"Not started" : module.format_time(start_time);
$("#profile_time_total").text(this.profile.time_total);
$("#profile_time_start").text(start);
//$("#profile_time_finish") = this.profile.time_finish();
$("#profile_info, #profile_actions").hide().removeClass("hidden").slideDown();
}
module.Monitor.prototype.last = function() {
return this.temperature[this.temperature.length-1];
@ -103,17 +110,19 @@ var tempgraph = (function(module) {
return {x:new Date(d.time*1000), y:this.scalefunc(d.temp)};
}
module.Monitor.prototype.set_state = function(name) {
module.Monitor.prototype.setState = function(name) {
if (name == "Lit") {
$("#ignite_button").addClass("disabled");
$("#current_output").removeAttr("disabled");
$("#stop_button").removeClass("disabled");
$("#stop_button_navbar").removeClass("hidden disabled");
$("#profile_select").removeClass("disabled");
} else if (name == "Idle" || name == "Cooling") {
$("#ignite_button").removeClass("disabled");
$("#current_output").attr("disabled", "disabled");
$("#stop_button").addClass("disabled");
$("#stop_button_navbar").addClass("hidden disabled");
$("#profile_select").removeClass("disabled");
}
}
module.Monitor.prototype._bindUI = function() {
@ -121,6 +130,8 @@ var tempgraph = (function(module) {
$("#temp_scale_F").click(function() { this.setScale("F");}.bind(this));
//$("#temp_scale_C").click(function() { this.setScale("C");}.bind(this));
$("#profile_name").val("");
$("#ignite_button").click(function() {
this._disable_all();
$.getJSON("/do/ignite", function(data) {
@ -149,9 +160,13 @@ var tempgraph = (function(module) {
})
});
$("#profile_list a").click(function(e) {
$("#profile_name").val($(e.target).text());
var fname = $(e.target).attr("data-fname");
$.getJSON("/profile/"+fname, function(data) {
this.setProfile(data);
}.bind(this));
}.bind(this));
try {
var sock = new WebSocket("ws://"+window.location.hostname+":"+window.location.port+"/ws/", "protocolOne");
@ -159,9 +174,9 @@ var tempgraph = (function(module) {
sock.onmessage = function(event) {
var data = JSON.parse(event.data);
if (data.type == "temperature")
this.update_temp(data);
this.updateTemp(data);
else if (data.type == "state") {
this.set_state(data.state);
this.setState(data.state);
}
}.bind(this);
} catch (e) {}
@ -180,5 +195,15 @@ var tempgraph = (function(module) {
return "Not implemented"
}
module.format_time = function(now) {
if (!(now instanceof Date))
now = new Date(now);
var hourstr = now.getHours() % 12;
hourstr = hourstr == 0 ? 12 : hourstr;
var minstr = now.getMinutes();
minstr = minstr < 10 ? "0"+minstr : minstr;
return hourstr + ":" + minstr + (now.getHours() >= 12 ? " pm" : " am");
}
return module;
}(tempgraph || {}));

Wyświetl plik

@ -0,0 +1,22 @@
var tempgraph = (function(module) {
module.Profile = function(schedule, start_time) {
var end = schedule[schedule.length-1][0];
var days = Math.floor(end / 60 / 60 / 24);
var hours = Math.floor((end - days*60*60*24) / 60 / 60);
var minutes = Math.ceil((end - days*60*60*24 - hours*60*60) / 60);
var daystr = days > 0 ? days + " days, " : "";
var hourstr = hours > 0 ? hours + " hours": "";
var minstr = minutes > 0 ? ", "+minutes + " minutes.":".";
this.length = end;
this.time_total = daystr+hourstr+minstr;
this.time_start = start_time;
}
module.Profile.prototype.time_finish = function(now) {
if (this.time_start instanceof Date) {
return new Date(this.time_start.getTime() + this.length*1000);
}
return new Date(now.getTime() + this.length*1000);
}
return module;
}(tempgraph || {}));

Wyświetl plik

@ -8,10 +8,10 @@
<!-- Bootstrap -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="css/bootstrap-theme.min.css">
<style type="text/css">
body {
@ -118,11 +118,13 @@
</div>
<div class="col-sm-4 col-md-4">
<div class="input-group input-group-lg row-space">
<input type="text" disabled="disabled" class="form-control" placeholder="Load profile">
<input id="profile_name" type="text" disabled="disabled" class="form-control" placeholder="Load profile">
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
<li><a href="#">...</a></li>
<ul id="profile_list" class="dropdown-menu dropdown-menu-right" role="menu">
{% for fname, name in profiles.items() %}
<li><a href="#" data-fname="{{fname}}">{{ name }}</a></li>
{% end %}
</ul>
</div><!-- /btn-group -->
</div><!-- /input-group -->
@ -130,9 +132,11 @@
<div class='panel-body'>
<dl class='dl-horizontal'>
<dt>Total time</dt>
<dd></dd>
<dd id="profile_time_total"></dd>
<dt>Start time</dt>
<dd id="profile_time_start"></dd>
<dt>Finish at</dt>
<dd></dd>
<dd id="profile_time_finish"></dd>
</dl>
</div>
</div>
@ -148,16 +152,17 @@
</div> <!-- /container -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script type="text/javascript" src="temp_graph.js"></script>
<script type="text/javascript" src="temp_monitor.js"></script>
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/d3.v3.min.js" charset="utf-8"></script>
<script type="text/javascript" src="js/temp_graph.js"></script>
<script type="text/javascript" src="js/temp_profile.js"></script>
<script type="text/javascript" src="js/temp_monitor.js"></script>
<script type="text/javascript">
var monitor;
d3.json("temperature.json", function(error, data) {
monitor = new tempgraph.Monitor(data);
monitor.set_state("{{ state }}");
monitor.setState("{{ state }}");
});
</script>
</body>