kopia lustrzana https://github.com/jamesgao/kiln_controller
Node dragging works, no saving yet
rodzic
c678d10e56
commit
fae13053ee
|
@ -52,5 +52,12 @@ body {
|
||||||
stroke-width:1px;
|
stroke-width:1px;
|
||||||
}
|
}
|
||||||
.profile-line.dot:hover {
|
.profile-line.dot:hover {
|
||||||
stroke-width:5px;
|
stroke-width:3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile-node-info {
|
||||||
|
float:left;
|
||||||
|
position:absolute;
|
||||||
|
display:none;
|
||||||
|
width:200px;
|
||||||
}
|
}
|
|
@ -34,8 +34,8 @@ var tempgraph = (function(module) {
|
||||||
this.x = d3.time.scale().range([0, this.width]);
|
this.x = d3.time.scale().range([0, this.width]);
|
||||||
this.y = d3.scale.linear().range([this.height, 0]);
|
this.y = d3.scale.linear().range([this.height, 0]);
|
||||||
|
|
||||||
this.zoom = d3.behavior.zoom().on("zoom", this.draw.bind(this))
|
this.zoom = d3.behavior.zoom(this.obj).on("zoom", this.draw.bind(this))
|
||||||
.on("zoomend", this.recenter.bind(this));
|
.on("zoomend", this.recenter.bind(this, .2));
|
||||||
|
|
||||||
if (options.show_axes === undefined || options.show_axes) {
|
if (options.show_axes === undefined || options.show_axes) {
|
||||||
this.x_axis = d3.svg.axis().scale(this.x).orient("bottom")
|
this.x_axis = d3.svg.axis().scale(this.x).orient("bottom")
|
||||||
|
@ -71,7 +71,6 @@ var tempgraph = (function(module) {
|
||||||
};
|
};
|
||||||
module.Graph.prototype.plot = function(data, className, marker) {
|
module.Graph.prototype.plot = function(data, className, marker) {
|
||||||
this.x.domain(d3.extent(data, function(d) { return d.x; }));
|
this.x.domain(d3.extent(data, function(d) { return d.x; }));
|
||||||
this.y.domain(d3.extent(data, function(d) { return d.y; }));
|
|
||||||
this.zoom.x(this.x);
|
this.zoom.x(this.x);
|
||||||
|
|
||||||
var line = d3.svg.line()
|
var line = d3.svg.line()
|
||||||
|
@ -97,7 +96,8 @@ var tempgraph = (function(module) {
|
||||||
this.lines[className] = {line:line, data:data, marker:marker};
|
this.lines[className] = {line:line, data:data, marker:marker};
|
||||||
this.svg.call(this.zoom);
|
this.svg.call(this.zoom);
|
||||||
this.draw();
|
this.draw();
|
||||||
return line;
|
this.recenter(.2);
|
||||||
|
return this.lines[className];
|
||||||
}
|
}
|
||||||
module.Graph.prototype.draw = function() {
|
module.Graph.prototype.draw = function() {
|
||||||
this.svg.select("g.x.axis").call(this.x_axis);
|
this.svg.select("g.x.axis").call(this.x_axis);
|
||||||
|
@ -130,15 +130,24 @@ var tempgraph = (function(module) {
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.draw();
|
this.draw();
|
||||||
}
|
}
|
||||||
module.Graph.prototype.recenter = function() {
|
module.Graph.prototype.recenter = function(margin) {
|
||||||
|
//Argument margin gives the fraction of (max - min) to add to the margin
|
||||||
|
//Defaults to 0
|
||||||
var extent = [], data, valid,
|
var extent = [], data, valid,
|
||||||
low = this.x.domain()[0], high=this.x.domain()[1];
|
low = this.x.domain()[0], high=this.x.domain()[1];
|
||||||
|
|
||||||
for (var name in this.lines) {
|
for (var name in this.lines) {
|
||||||
data = this.lines[name].data;
|
data = this.lines[name].data;
|
||||||
valid = data.filter(function(d) { return low <= d.x && d.x <= high; })
|
valid = data.filter(function(d) { return low <= d.x && d.x <= high; })
|
||||||
extent = extent.concat(valid);
|
extent = extent.concat(valid);
|
||||||
}
|
}
|
||||||
this.y.domain(d3.extent(extent, function(d) {return d.y;}));
|
extent = d3.extent(extent, function(d){return d.y});
|
||||||
|
if (margin > 0) {
|
||||||
|
var range = extent[1]-extent[0];
|
||||||
|
extent[0] -= margin*range;
|
||||||
|
extent[1] += margin*range;
|
||||||
|
}
|
||||||
|
this.y.domain(extent);
|
||||||
this.draw();
|
this.draw();
|
||||||
}
|
}
|
||||||
module.Graph.prototype.update = function(className, data) {
|
module.Graph.prototype.update = function(className, data) {
|
||||||
|
|
|
@ -3,9 +3,7 @@ var tempgraph = (function(module) {
|
||||||
this.temperature = initial;
|
this.temperature = initial;
|
||||||
this.profile = null;
|
this.profile = null;
|
||||||
//default to F
|
//default to F
|
||||||
this.scalefunc = module.temp_to_F;
|
this.scalefunc = new module.TempScale("F");
|
||||||
this.temp_suffix = "°F"
|
|
||||||
this.temp_prefix = ""
|
|
||||||
|
|
||||||
this.graph = new module.Graph();
|
this.graph = new module.Graph();
|
||||||
this._mapped = this.temperature.map(this._map_temp.bind(this));
|
this._mapped = this.temperature.map(this._map_temp.bind(this));
|
||||||
|
@ -16,13 +14,11 @@ var tempgraph = (function(module) {
|
||||||
}
|
}
|
||||||
module.Monitor.prototype.updateTemp = function(data) {
|
module.Monitor.prototype.updateTemp = function(data) {
|
||||||
var now = new Date(data.time*1000.);
|
var now = new Date(data.time*1000.);
|
||||||
var temp = this.scalefunc(data.temp);
|
var temp = this.scalefunc.scale(data.temp);
|
||||||
|
|
||||||
var nowstr = module.format_time(now);
|
var nowstr = module.format_time(now);
|
||||||
|
|
||||||
var tempstr = Math.round(temp*100) / 100;
|
|
||||||
$("#current_time").text(nowstr);
|
$("#current_time").text(nowstr);
|
||||||
$("#current_temp").text(this.temp_prefix+tempstr+this.temp_suffix);
|
$("#current_temp").text(this.scalefunc.print(Math.round(temp*100) / 100));
|
||||||
|
|
||||||
if (this.profile) {
|
if (this.profile) {
|
||||||
var finish = module.format_time(this.profile.time_finish(now));
|
var finish = module.format_time(this.profile.time_finish(now));
|
||||||
|
@ -42,11 +38,9 @@ var tempgraph = (function(module) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//If incoming sample is higher or lower than the ylims, expand that as well
|
//If incoming sample is higher or lower than the ylims, expand that as well
|
||||||
var ylims = this.graph.y.domain(), range = 2*(ylims[1] - ylims[0]);
|
var ylims = this.graph.y.domain();
|
||||||
if (temp >= ylims[1]) {
|
if (temp >= ylims[1] || temp <= ylims[0]) {
|
||||||
this.graph.y.domain([ylims[0], ylims[0]+range]);
|
this.graph.recenter(.2);
|
||||||
} else if (temp <= ylims[0]) {
|
|
||||||
this.graph.y.domain([ylims[1]-range, ylims[1]]);
|
|
||||||
}
|
}
|
||||||
this.graph.update("temperature", this._mapped);
|
this.graph.update("temperature", this._mapped);
|
||||||
}
|
}
|
||||||
|
@ -86,22 +80,16 @@ var tempgraph = (function(module) {
|
||||||
$("a#temp_scale_cone").parent().removeClass("active");
|
$("a#temp_scale_cone").parent().removeClass("active");
|
||||||
if (scale == "C") {
|
if (scale == "C") {
|
||||||
$("li a#temp_scale_C").parent().addClass("active");
|
$("li a#temp_scale_C").parent().addClass("active");
|
||||||
this.scalefunc = module.temp_to_C;
|
this.scalefunc = new module.TempScale("C");
|
||||||
this.graph.ylabel("Temperature (°C)")
|
this.graph.ylabel("Temperature (°C)")
|
||||||
this.temp_suffix = "°C";
|
|
||||||
this.temp_prefix = "";
|
|
||||||
} else if (scale == "F") {
|
} else if (scale == "F") {
|
||||||
$("li a#temp_scale_F").parent().addClass("active");
|
$("li a#temp_scale_F").parent().addClass("active");
|
||||||
this.scalefunc = module.temp_to_F;
|
this.scalefunc = new module.TempScale("F");
|
||||||
this.graph.ylabel("Temperature (°F)")
|
this.graph.ylabel("Temperature (°F)")
|
||||||
this.temp_suffix = "°F";
|
|
||||||
this.temp_prefix = "";
|
|
||||||
} else if (scale == "cone") {
|
} else if (scale == "cone") {
|
||||||
$("li a#temp_scale_cone").parent().addClass("active");
|
$("li a#temp_scale_cone").parent().addClass("active");
|
||||||
this.scalefunc = module.temp_to_cone;
|
this.scalefunc = new module.TempScale("cone");
|
||||||
this.graph.ylabel("Temperature (Δ)");
|
this.graph.ylabel("Temperature (Δ)");
|
||||||
this.temp_prefix = "Δ";
|
|
||||||
this.temp_suffix = "";
|
|
||||||
}
|
}
|
||||||
this._mapped = this.temperature.map(this._map_temp.bind(this));
|
this._mapped = this.temperature.map(this._map_temp.bind(this));
|
||||||
this.graph.y.domain(d3.extent(this._mapped, function(d) { return d.y; }));
|
this.graph.y.domain(d3.extent(this._mapped, function(d) { return d.y; }));
|
||||||
|
@ -113,7 +101,7 @@ var tempgraph = (function(module) {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.Monitor.prototype._map_temp = function(d) {
|
module.Monitor.prototype._map_temp = function(d) {
|
||||||
return {x:new Date(d.time*1000), y:this.scalefunc(d.temp)};
|
return {x:new Date(d.time*1000), y:this.scalefunc.scale(d.temp)};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.Monitor.prototype.setState = function(name) {
|
module.Monitor.prototype.setState = function(name) {
|
||||||
|
@ -193,11 +181,19 @@ var tempgraph = (function(module) {
|
||||||
$("input").attr("disabled", "disabled");
|
$("input").attr("disabled", "disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
module.temp_to_C = function(temp) { return temp; }
|
|
||||||
module.temp_to_F = function(temp) {
|
module.TempScale = function(name) {
|
||||||
return temp * 9 / 5 + 32;
|
if (name == "C") {
|
||||||
|
this.scale = function(t) { return t;};
|
||||||
|
this.inverse = function(t) { return t;};
|
||||||
|
this.print = function(t) { return t+"°C"}
|
||||||
|
} else if (name == "F") {
|
||||||
|
this.scale = function(temp) { return temp * 9 / 5 + 32; }
|
||||||
|
this.inverse = function(temp) { return (temp - 32) * 5 / 9;}
|
||||||
|
this.print = function(t) { return t+"°F"}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
module.temp_to_cone = function(temp) {
|
module.TempScale.C_to_cone = function(temp) {
|
||||||
var cones = [600,614,635,683,717,747,792,804,838,852,884,894,900,923,955,984,999,1046,1060,1101,1120,1137,1154,1162,1168,1186,1196,1222,1240,1263,1280,1305,1315,1326,1346]
|
var cones = [600,614,635,683,717,747,792,804,838,852,884,894,900,923,955,984,999,1046,1060,1101,1120,1137,1154,1162,1168,1186,1196,1222,1240,1263,1280,1305,1315,1326,1346]
|
||||||
var names = [];
|
var names = [];
|
||||||
for (var i = -22; i < 0; i++) {
|
for (var i = -22; i < 0; i++) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ var tempgraph = (function(module) {
|
||||||
|
|
||||||
module.Profile.prototype.setScale = function(scale) {
|
module.Profile.prototype.setScale = function(scale) {
|
||||||
this.scalefunc = scale;
|
this.scalefunc = scale;
|
||||||
|
this.update();
|
||||||
}
|
}
|
||||||
module.Profile.prototype.setupGraph = function() {
|
module.Profile.prototype.setupGraph = function() {
|
||||||
//immediately view range from 10 min before to end time of profile
|
//immediately view range from 10 min before to end time of profile
|
||||||
|
@ -37,16 +38,35 @@ var tempgraph = (function(module) {
|
||||||
.attr("class", "profile-pane")
|
.attr("class", "profile-pane")
|
||||||
.attr("height", this.graph.height)
|
.attr("height", this.graph.height)
|
||||||
|
|
||||||
this.graph.zoom.on("zoom.profile", this.update.bind(this));
|
|
||||||
this.line = this.graph.plot(this._schedule(), "profile-line", true);
|
this.line = this.graph.plot(this._schedule(), "profile-line", true);
|
||||||
this.update();
|
this.update();
|
||||||
|
|
||||||
|
//events
|
||||||
|
this.drag = d3.behavior.drag().origin(function(d) {
|
||||||
|
return {x:this.graph.x(d.x), y:this.graph.y(d.y)};
|
||||||
|
}.bind(this)).on("dragstart", function(d) {
|
||||||
|
d3.event.sourceEvent.stopPropagation();
|
||||||
|
this._node = this._findNode(d);
|
||||||
|
}.bind(this)).on("drag", this.dragNode.bind(this));
|
||||||
|
this.line.marker.call(this.drag);
|
||||||
|
|
||||||
|
var hide_info = function() {
|
||||||
|
this.hide_timeout = setTimeout(function() { $("#profile-node-info").hide(); }, 250);
|
||||||
|
};
|
||||||
|
this.graph.zoom.on("zoom.profile", this.update.bind(this));
|
||||||
|
this.line.marker.on("mouseover", this.hoverNode.bind(this));
|
||||||
|
this.line.marker.on("mouseout", hide_info.bind(this));
|
||||||
|
$("#profile-node-info").on("mouseout.profile", hide_info.bind(this));
|
||||||
|
$("#profile-node-info").on("mouseover.profile", function() {
|
||||||
|
clearTimeout(this.hide_timeout);
|
||||||
|
}.bind(this));
|
||||||
}
|
}
|
||||||
module.Profile.prototype._schedule = function() {
|
module.Profile.prototype._schedule = function() {
|
||||||
var start_time = this.time_start instanceof Date ? this.time_start : new Date();
|
var start_time = this.time_start instanceof Date ? this.time_start : new Date();
|
||||||
var schedule = [];
|
var schedule = [];
|
||||||
for (var i = 0; i < this.schedule.length; i++) {
|
for (var i = 0; i < this.schedule.length; i++) {
|
||||||
var time = new Date(start_time.getTime() + this.schedule[i][0]*1000);
|
var time = new Date(start_time.getTime() + this.schedule[i][0]*1000);
|
||||||
var temp = this.scalefunc(this.schedule[i][1]);
|
var temp = this.scalefunc.scale(this.schedule[i][1]);
|
||||||
schedule.push({x:time, y:temp});
|
schedule.push({x:time, y:temp});
|
||||||
}
|
}
|
||||||
return schedule;
|
return schedule;
|
||||||
|
@ -64,15 +84,42 @@ var tempgraph = (function(module) {
|
||||||
this.scalefunc = scale;
|
this.scalefunc = scale;
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
module.Profile.prototype._findNode = function(d) {
|
||||||
|
var time, temp,
|
||||||
|
start_time = this.time_start instanceof Date ? this.time_start : new Date();
|
||||||
|
for (var i = 0; i < this.schedule.length; i++) {
|
||||||
|
time = new Date((start_time.getTime() + this.schedule[i][0]*1000));
|
||||||
|
temp = this.schedule[i][1];
|
||||||
|
//if time is within 10 seconds and temperature matches exactly
|
||||||
|
if ((time - d.x) < 10000 && d.y == this.scalefunc.scale(temp))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
module.Profile.prototype.addNode = function() {
|
module.Profile.prototype.addNode = function() {
|
||||||
|
|
||||||
}
|
}
|
||||||
module.Profile.prototype.delNode = function() {
|
module.Profile.prototype.delNode = function() {
|
||||||
|
|
||||||
}
|
}
|
||||||
module.Profile.prototype.dragNode = function() {
|
module.Profile.prototype.dragNode = function(d) {
|
||||||
|
var time = this.graph.x.invert(d3.event.x);
|
||||||
|
var temp = this.graph.y.invert(d3.event.y);
|
||||||
|
var start_time = this.time_start instanceof Date ? this.time_start : new Date();
|
||||||
|
this.schedule[this._node][0] = (time - start_time) / 1000;
|
||||||
|
this.schedule[this._node][1] = this.scalefunc.inverse(temp);
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
module.Profile.prototype.hoverNode = function(d) {
|
||||||
|
clearTimeout(this.hide_timeout);
|
||||||
|
var node = this._findNode(d);
|
||||||
|
$("#profile-node-info")
|
||||||
|
.css('left', this.graph.x(d.x)+80)
|
||||||
|
.css('top', this.graph.y(d.y)+50)
|
||||||
|
.show();
|
||||||
|
|
||||||
|
$("#profile-node-info div.name").text("Set point "+(node+1));
|
||||||
|
$("#profile-node-info input.temp").val(this.scalefunc.scale(this.schedule[node][1]));
|
||||||
|
$("#profile-node-info input.time");
|
||||||
}
|
}
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
|
@ -61,8 +60,9 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-8 col-md-8 row-space">
|
<div class="col-sm-8 col-md-8 row-space">
|
||||||
<svg id="graph" class="row-space"></svg>
|
|
||||||
|
|
||||||
|
<svg id="graph" class="row-space"></svg>
|
||||||
|
|
||||||
<div class="btn-group btn-group-justified row-space">
|
<div class="btn-group btn-group-justified row-space">
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<button id="stop_button" type="button" class="btn btn-primary disabled"><span class="glyphicon glyphicon-stop"></span> Off</button>
|
<button id="stop_button" type="button" class="btn btn-primary disabled"><span class="glyphicon glyphicon-stop"></span> Off</button>
|
||||||
|
@ -109,6 +109,22 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id='profile-node-info' class='panel panel-info'>
|
||||||
|
<div class='panel-heading name'>
|
||||||
|
Set point
|
||||||
|
</div>
|
||||||
|
<div class='panel-body'>
|
||||||
|
<div class="input-group input-group-sm row-space">
|
||||||
|
<span class="input-group-addon">Time</span>
|
||||||
|
<input type="text" class="form-control time">
|
||||||
|
</div>
|
||||||
|
<div class="input-group input-group-sm">
|
||||||
|
<span class="input-group-addon">Temp</span>
|
||||||
|
<input type="text" class="form-control temp">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div> <!-- /container -->
|
</div> <!-- /container -->
|
||||||
|
|
||||||
<script src="js/jquery.min.js"></script>
|
<script src="js/jquery.min.js"></script>
|
||||||
|
|
Ładowanie…
Reference in New Issue