2 * Graph sensor and/or actuator values
5 //TODO: Clean this file up, I bow to Jeremy's superior JavaScript knowledge
10 mctx.graph.api.sensors = mctx.api + "sensors";
11 mctx.graph.api.actuators = mctx.api + "actuators";
14 mctx.graph.dependent = null;
15 mctx.graph.independent = null;
16 mctx.graph.timer = null;
17 mctx.graph.running = false;
20 * Helper - Calculate pairs of (dependent, independent) values
21 * Given input as (time, value) pairs for dependent and independent
22 * Appends each value pair to the result
25 function dataMerge(dependent, independent, result) {
27 for (var i = 0; i < dependent.length-1; ++i) {
28 var start = dependent[i][0];
29 var end = dependent[i+1][0];
30 var average = 0, n = 0;
31 for (; j < independent.length; ++j) {
32 if (independent[j][0] < start)
34 else if (independent[j][0] >= end)
36 average += independent[j][1];
41 result.push([dependent[i][1], average]);
48 * Helper function adds the sensors and actuators to a form
49 * @param input_type is it a radio? or is it a checkbox?
50 * @param check_first determines whether the first item is checked or not
51 * @param group which group this input belongs to (name field)
53 $.fn.deployDevices = function(input_type, check_first, group) {
55 var apply = function(dict, prefix) {
56 $.each(dict, function(key, val) {
58 'type' : input_type, 'value' : key, 'alt' : val,
59 'class' : prefix, 'name' : group,
60 'id' : prefix + '_' + val //Unique id (name mangling)
62 var entry = $("<input/>", attributes);
63 var label = $("<label/>", {'for' : prefix + '_' + val, 'text' : val});
64 entry.prop("checked", check_first);
66 container.append(entry).append(label);
70 apply(mctx.sensors, 'sensors');
71 apply(mctx.actuators, 'actuators');
75 * Identify sensors/actuators
76 * @returns itself (Is this right?)
78 $.fn.setDevices = function() {
79 // Query for sensors and actuators
81 url : mctx.api + 'identify',
82 data : {'sensors' : 1, 'actuators' : 1}
83 }).done(function (data) {
84 mctx.sensors = $.extend(mctx.sensors, data.sensors);
85 mctx.actuators = $.extend(mctx.actuators, data.actuators);
87 //Always set the 'time' option to be checked
88 $("#xaxis input").prop('checked', true);
89 $("#xaxis").deployDevices("radio", false, 'xaxis');
90 $("#yaxis").deployDevices("checkbox", true, 'yaxis');
91 $("#current_time").val(data.running_time);
92 //Add event listeners for when the inputs are changed
93 $(".change input").change(function () {
94 $("#graph").setGraph();
99 function graphUpdater() {
101 'sensors' : mctx.graph.api.sensors,
102 'actuators' : mctx.graph.api.actuators
105 var updater = function () {
108 var ctime = $("#current_time");
110 var xaxis = mctx.graph.xaxis;
111 var yaxis = mctx.graph.yaxis;
112 var start_time = mctx.graph.start_time;
113 var end_time = mctx.graph.end_time;
114 var devices = mctx.graph.devices;
116 if (xaxis.size() < 1 || yaxis.size() < 1) {
117 mctx.graph.running = false;
121 $.each(devices, function(key, val) {
122 if (val.urltype in urls) {
123 var parameters = {id : val.id};
124 if (start_time != null) {
125 parameters.start_time = start_time;
127 if (end_time != null) {
128 parameters.end_time = end_time;
130 responses.push($.ajax({url : urls[val.urltype], data : parameters})
131 .done(function(json) {
132 //alert("Hi from " + json.name);
134 for (var i = 0; i < json.data.length; ++i) {
135 if (dev.length <= 0 || json.data[i][0] > dev[dev.length-1][0]) {
136 dev.push(json.data[i]);
139 ctime.val(json.running_time);
140 //alert(devices[json.name].data);
145 //... When the response is received, then() will happen (I think?)
146 $.when.apply(this, responses).then(function () {
148 yaxis.each(function() {
149 //alert("Add " + $(this).val() + " to plot");
150 if (xaxis.attr("alt") === "time") {
151 //alert("Against time");
152 plot_data.push(devices[$(this).attr("alt")].data);
155 dataMerge(devices[xaxis.attr("alt")].data, devices[$(this).attr("alt")].data, result);
158 for (var i = 0; i < result.length; ++i)
159 astr += "[" + result[i][0] + "," + result[i][1] + "]" + ",";
163 plot_data.push(result);
167 $.plot("#graph", plot_data);
168 if (mctx.graph.running) {
169 mctx.graph.timer = setTimeout(updater, 1000);
171 }, function () {mctx.graph.running=false; alert("Graph crashed");});
174 mctx.graph.running = true;
180 * Sets the graphs to graph stuff.
183 $.fn.setGraph = function () {
184 // Determine which actuator/sensors to plot
185 var xaxis = $("#xaxis input[name=xaxis]:checked");
186 var yaxis = $("#yaxis input[name=yaxis]:checked");
187 if (xaxis.size() < 1 || yaxis.size() < 1) {
192 var start_time = $("#start_time").val();
193 var end_time = $("#end_time").val();
194 if (!$.isNumeric(start_time)) {
197 if (!$.isNumeric(end_time)) {
202 var populateDict = function () {
204 dict['urltype'] = $(this).attr("class");
205 dict['id'] = $(this).attr("value");
207 dict['start_time'] = start_time;
208 dict['end_time'] = end_time;
209 devices[$(this).attr("alt")] = dict;
211 xaxis.each(populateDict);
212 yaxis.each(populateDict);
214 mctx.graph.xaxis = xaxis;
215 mctx.graph.yaxis = yaxis;
216 mctx.graph.start_time = start_time;
217 mctx.graph.end_time = end_time;
218 mctx.graph.devices = devices;
220 if (!mctx.graph.running) {
221 $("#graph-run").val("Pause");
228 $.fn.runButton = function() {
229 //alert($(this).val());
230 if ($(this).val() === "Run") {
231 $("#graph").setGraph();
232 $(this).val("Pause");
235 mctx.graph.running = false;
236 clearTimeout(mctx.graph.timer);