Fix id bounds check for actuator + update graph code
[matches/MCTX3420.git] / testing / MCTXWeb / public_html / static / mctx.graph.js
1 /**
2  * Graph sensor and/or actuator values
3  */
4
5 //TODO: Clean this file up, I bow to Jeremy's superior JavaScript knowledge
6
7
8 mctx.graph = {};
9 mctx.graph.api = {};
10 mctx.graph.api.sensors = mctx.api + "sensors";
11 mctx.graph.api.actuators = mctx.api + "actuators";
12 mctx.sensors = {};
13 mctx.actuators = {};
14 mctx.graph.dependent = null;
15 mctx.graph.independent = null;
16 mctx.graph.timer = null;
17
18 /**
19  * Helper - Calculate pairs of (dependent, independent) values
20  * Given input as (time, value) pairs for dependent and independent
21  * Appends each value pair to the result
22  * @returns result
23  */
24 function dataMerge(dependent, independent, result) {
25         var j = 0;
26         for (var i = 0; i < dependent.length-1; ++i) {
27                 var start = dependent[i][0];
28                 var end = dependent[i+1][0];
29                 var average = 0, n = 0;
30                 for (; j < independent.length; ++j) {
31                         if (independent[j][0] < start)
32                                 continue;
33                         else if (independent[j][0] >= end)
34                                 break;
35                         average += independent[j][1];
36                         n += 1;
37                 }
38                 if (n > 0) {
39                         average /= n;
40                         result.push([dependent[i][1], average]);
41                 }
42         }
43         return result;
44 }
45
46 /**
47  * Helper function adds the sensors and actuators to a form
48  * @param input_type is it a radio? or is it a checkbox?
49  * @param check_first determines whether the first item is checked or not
50  * @param group which group this input belongs to (name field)
51  */
52 $.fn.deployDevices = function(input_type, check_first, group) {
53   var container = this;
54   var apply = function(dict, prefix) {
55     $.each(dict, function(key, val) {
56       var attributes = {
57           'type' : input_type, 'value' : key, 'alt' : val,
58           'class' : prefix, 'name' : group, 
59           'id' : prefix + '_' + val //Unique id (name mangling)
60       };
61       var entry = $("<input/>", attributes);
62       var label = $("<label/>", {'for' : prefix + '_' + val, 'text' : val}); 
63       entry.prop("checked", check_first);
64       check_first = false;
65       container.append(entry).append(label);
66     });
67   }
68   
69   apply(mctx.sensors, 'sensors');
70   apply(mctx.actuators, 'actuators');
71 };
72
73 /**
74  * Identify sensors/actuators
75  * @returns itself (Is this right?)
76  */
77 $.fn.setDevices = function() {
78   // Query for sensors and actuators
79   return $.ajax({
80     url : mctx.api + 'identify', 
81     data : {'sensors' : 1, 'actuators' : 1}
82   }).done(function (data) {
83     mctx.sensors = $.extend(mctx.sensors, data.sensors);
84     mctx.actuators = $.extend(mctx.actuators, data.actuators);
85     
86     $("#xaxis").deployDevices("radio", false, 'xaxis');
87     $("#yaxis").deployDevices("checkbox", true, 'yaxis');
88     $("#current_time").val(data.running_time);
89   });
90 };
91
92
93 /**
94  * Sets the graphs to graph stuff.
95  * @returns {$.fn}
96  */
97 $.fn.setGraph = function () {
98   clearTimeout(mctx.graph.timer);
99   var urls = {
100     'sensors' : mctx.graph.api.sensors,
101     'actuators' : mctx.graph.api.actuators
102   }
103
104   var updateData = function(json, data) {
105     for (var i = 0; i < json.data.length; ++i)
106       data.push(json.data[i]);
107     return data;
108   };
109   var graphdiv = this;
110
111   // Determine which actuator/sensors to plot
112  
113   var xaxis = $("#xaxis input:checked");
114   var yaxis = $("#yaxis input:checked");
115   var start_time = $("#start_time").val();
116   var end_time = $("#end_time").val();
117   if (!$.isNumeric(start_time)) {
118     start_time = null;
119   }
120   if (!$.isNumeric(end_time)) {
121     end_time = null;
122   }
123
124   var devices = {};
125   var populateDict = function () {
126     var dict = {};
127     dict['urltype'] = $(this).attr("class");
128     dict['id'] = $(this).attr("value");
129     dict['data'] = [];
130     dict['start_time'] = start_time;
131     dict['end_time'] = end_time;
132     devices[$(this).attr("alt")] = dict;
133   };
134   xaxis.each(populateDict);
135   yaxis.each(populateDict);
136   
137   /*
138   yaxis.each(function() {
139     
140     devices[$(this).attr("alt")] = {};
141     devices[$(this).attr("alt")]["url"] = mctx.api + $(this).attr("class");
142     devices[$(this).attr("alt")]["data"] = [];
143     devices[$(this).attr("alt")]["start_time"] = start_time;
144     devices[$(this).attr("alt")]["end_time"] = end_time;
145   });
146   */
147
148   var updater = function () {
149     var time_limit = 20;
150     var responses = [];
151     var ctime =  $("#current_time");
152     
153     $.each(devices, function(key, val) {
154       console.log(val);
155       if (val.urltype in urls) {
156         var parameters = {id : val.id};
157         if (start_time != null) {
158           parameters.start_time = start_time;
159         }
160         if (end_time != null) {
161           parameters.end_time = end_time;
162         }
163         responses.push($.ajax({url : urls[val.urltype], data : parameters})
164         .done(function(json) {
165           //alert("Hi from " + json.name);
166           var dev = val.data;
167           for (var i = 0; i < json.data.length; ++i) {
168             if (dev.length <= 0 || json.data[i][0] > dev[dev.length-1][0]) {
169               dev.push(json.data[i]);
170             }
171           }
172           ctime.val(json.running_time);
173           //alert(devices[json.name].data);
174         }));
175       }
176     });
177
178     //... When the response is received, then() will happen (I think?) yup
179     $.when.apply(this, responses).then(function () {
180       var plot_data = [];
181       yaxis.each(function() {
182         //alert("Add " + $(this).val() + " to plot");
183         if (xaxis.attr("alt") === "time") {
184           //alert("Against time");
185           plot_data.push(devices[$(this).attr("alt")].data);
186         }
187         else {
188           var result = []
189           dataMerge(devices[xaxis.attr("alt")].data, devices[$(this).attr("alt")].data, result);
190           /*
191           var astr = "[";
192           for (var i = 0; i < result.length; ++i)
193             astr += "[" + result[i][0] + "," + result[i][1] + "]" + ",";
194           astr += "]";
195           alert(astr);
196           */
197           plot_data.push(result);
198         }
199       });
200       
201       //alert(plot_data + "");
202       //alert("Plot happened");
203       $.plot("#graph", plot_data);
204       mctx.graph.timer = setTimeout(updater, 1000);
205     }, function () {alert("Graph crashed");});
206   };
207   
208   updater();
209   return this;
210 };
211
212 $.fn.runButton = function() {
213   //alert($(this).val());
214   if ($(this).val() === "Run") {
215     $("#graph").setGraph();
216     $(this).val("Pause");
217   }
218   else {
219     clearTimeout(mctx.graph.timer);
220     $(this).val("Run");
221   }
222 };

UCC git Repository :: git.ucc.asn.au