Machine work

This example shows a production unit and how many items it has produced.
If you point with the mouse and drag to right, you can count number of units in an interval.

Data looks like

aa The Java script calls a program
get-device-counter.php
This file generates a datastream an encode it as JSON

2016-01-20 00:00:56 2096868
2016-01-20 00:01:56 2096868
2016-01-20 00:02:56 2096885
2016-01-20 00:03:56 2096934
2016-01-20 00:04:56 2096983
2016-01-20 00:05:56 2097002
2016-01-20 00:06:56 2097048
2016-01-20 00:07:56 2097096
2016-01-20 00:08:56 2097145
2016-01-20 00:09:56 2097170
2016-01-20 00:10:56 2097187
2016-01-20 00:11:57 2097224
2016-01-20 00:12:57 2097224
2016-01-20 00:13:57 2097224
2016-01-20 00:14:57 2097227
2016-01-20 00:15:57 2097243
2016-01-20 00:16:57 2097259
2016-01-20 00:17:57 2097273
2016-01-20 00:18:57 2097285
2016-01-20 00:19:57 2097314
...

Sourcecode

Source for the page

001: <?php
002: //----------------------------------------------------------------------
003: //
004: //  http://wesbos.com/html5-canvas-websockets-nodejs/
005: //  http://www.chartjs.org/
006: //  http://weblogs.asp.net/dwahlin/creating-a-line-chart-using-the-html-5-canvas
007: //  https://www.dashingd3js.com/using-data-bound-to-dom-elements
008: //
009: //----------------------------------------------------------------------
010: 
011: 
012: include_once('framework-config.php');   // configuration data
013: include_once('raditex-library.php');  // main library
014: include_once('framework-lists.php');    // lists - like menues an other
015: include_once('libs/rbis-library-widgets.php');
016: include_once('libs/rbis-library-database.php');
017: include_once('libs/rbis-library-html.php');
018: 
019: page_start();
020: 
021: page_header($header_image,"User: gorhas@demo.se");
022: page_drop_down_menu($site_menu);
023: 
024: page_menu($framework_menu);
025: 
026: page_row_start();
027: page_column_start_left();
028: 
029: 
030: html_title("Machine work", 1);
031: 
032: html_p("
033: This example shows a production unit and how
034: many items it has produced.
035: <br />
036: If you point with the mouse and drag to right, you can
037: count number of units in an interval.
038: ");
039: 
040: // A div where the graph will go
041: echo "<div id='chartContainer'></div>";
042: 
043: 
044: html_title("Data looks like");
045: 
046: html_paragraph("
047: The Java script calls a program
048: <br />
049: get-device-counter.php
050: <br />
051: This file generates a datastream an encode it as JSON
052: ");
053: 
054: ?>
055: <pre>
056: 2016-01-20 00:00:56 2096868
057: 2016-01-20 00:01:56 2096868
058: 2016-01-20 00:02:56 2096885
059: 2016-01-20 00:03:56 2096934
060: 2016-01-20 00:04:56 2096983
061: 2016-01-20 00:05:56 2097002
062: 2016-01-20 00:06:56 2097048
063: 2016-01-20 00:07:56 2097096
064: 2016-01-20 00:08:56 2097145
065: 2016-01-20 00:09:56 2097170
066: 2016-01-20 00:10:56 2097187
067: 2016-01-20 00:11:57 2097224
068: 2016-01-20 00:12:57 2097224
069: 2016-01-20 00:13:57 2097224
070: 2016-01-20 00:14:57 2097227
071: 2016-01-20 00:15:57 2097243
072: 2016-01-20 00:16:57 2097259
073: 2016-01-20 00:17:57 2097273
074: 2016-01-20 00:18:57 2097285
075: 2016-01-20 00:19:57 2097314
076: ...
077: </pre>
078: 
079: <?php
080: 
081: html_h("Sourcecode", 2);
082: 
083: html_p("Source for the page");
084: 
085: // html-version of this file
086: include_once("src/plott-advanced.php.html");
087: 
088: html_p("Source for the java-script");
089: 
090: include_once("src/production-library-prod-stat.js.html");
091: 
092: page_column_end();
093: page_row_end();
094: 
095: page_footer("http://www.raditex.nu","Raditex Konsult","http://www.rscada.se","rScada");
096: page_end();
097: 
098: print("<script src='libs/rbis-library-utils.js'></script>\n");
099: print("<script src='http://d3js.org/d3.v3.js'></script>\n");
100: print("<script src='./production-library-prod-stat.js'></script>\n");
101: 
102: //----------------------------------------------------------------------
103: // EOF
104: //---------------------------------------------------------------------
105: ?>
106: 

Source for the java-script

001: //----------------------------------------------------------------------
002: //
003: //  Ideas from
004: //  http://canvasjs.com/html5-javascript-line-chart
005: //  http://square.github.io/cubism/
006: //  http://www.d3noob.org/2013/01/adding-grid-lines-to-d3js-graph.html
007: //  http://jsfiddle.net/555Cv/2/
008: //  http://www.stator-afm.com/tutorial/d3-js-mouse-events/
009: //  http://christopheviau.com/d3list/ !!
010: //----------------------------------------------------------------------
011: 
012: 
013: var margin = {top: 20, right: 20, bottom: 50, left: 50},
014:     width = 1400 - margin.left - margin.right,
015:     height = 350 - margin.top - margin.bottom;
016: 
017: var parseDate0 = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
018: 
019: var x = d3.time.scale()
020:     .range([0, width]);
021: 
022: var y0 = d3.scale.linear()
023:      .range([height, 0]);
024: 
025: 
026: var xAxis = d3.svg.axis()
027:     .scale(x)
028:     .ticks(d3.time.hour, 1)
029:     .tickFormat(d3.time.format('%H:%M'))
030:     .orient("bottom");
031: 
032: var yAxisLeft = d3.svg.axis()
033:     .scale(y0)
034:     .tickSize(-width, 0, 0)
035:     .orient("left");
036: 
037: 
038: 
039: var line0 = d3.svg.line()
040:     .x(function(d) { return x(d.time); })
041:     .y(function(d) { return y(d.bags); });
042: 
043: 
044: var svg = d3.select("#chartContainer").append("svg")
045:     .attr("width", width + margin.left + margin.right)
046:     .attr("height", height + margin.top + margin.bottom)
047:     .attr("width", 1450)
048:     .attr("height", 350)
049:     .style("border", "1px solid blue")
050:     .on("mousedown", mouseDown)
051:     .on("mouseup", mouseUp)
052:     .on("click", mouseClick)
053:     .on("mousemove", mouseMove)
054:     .append("g")
055:     .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
056: 
057: var dup_data;
058: 
059: d3.json("./get-device-counter.php",function(error, json) {
060:     if(error) return console.warn(error);
061:     data = json;
062: 
063:     dup_data = data.slice();
064:     
065:     data.forEach(function(d) {
066:         d.time = parseDate0(d.log_time);
067:         d.bags = +d.bags_produced;
068:         // console.log("time  " + d.log_time );
069:     });
070:     
071: 
072:     var area = d3.svg.area()
073:         .interpolate("step-after")
074:         .x(function(d) { return x(d.time); })
075:         .y0(height)
076:         .y1(function(d) { return y0(d.bags); });
077:     
078:     
079:     x.domain(d3.extent(data, function(d) { return d.time; }));
080:     y0.domain([0, d3.max(data, function(d) { return d.bags; })+5]);
081: 
082:     
083:     svg.append("g")
084:         .attr("class", "x axis grid")
085:     //.attr("ckass", "grid")
086:         .attr("transform", "translate(0," + height + ")")
087:         .call(xAxis)
088:         .selectAll("text")
089:         .attr("y", 0)
090:         .attr("x", 9)
091:         .attr("dy", ".35em")
092:         .attr("transform", "rotate(50)")
093:         .style("text-anchor", "start");
094:     
095:     svg.append("g")
096:         .attr("class", "y axis grid")
097:     //.attr("class", "grid"
098:         .call(yAxisLeft)
099:         .append("text")
100:         .attr("transform", "rotate(-90)")
101:         .attr("y", 6)
102:         .attr("dy", "-3em")
103:         .style("text-anchor", "end")
104:         .text("items/min");
105:     
106:     svg.append("path")
107:         .datum(data)
108:         .attr("class", "area")
109:         .attr("d", area);
110: 
111: });
112: 
113: 
114: var x_start = 0;
115: var x_end = 0;
116: var sel_area;
117: var text_area;
118: 
119: var selection_in_progress = 0; 
120: 
121: function mouseDown() {
122: 
123:     //console.log("mouseDown");
124:     //alert("Down");
125: 
126:     selection_in_progress = 1;
127: 
128:     d3.select("#the_area").remove();
129: 
130:    // d3.select("#the_area").remove();
131: 
132:     x_start = d3.mouse(this)[0];
133: 
134:     d3.select("#the_area_text").remove();
135: 
136:     sel_area = svg.append("rect")
137:         .attr("height", height - 175)
138:         .attr("id", "the_area_text")
139:         .attr("width", 250)
140:         .attr("x", x_start - 52 )
141:         .attr("y", 0)
142:         .attr("opacity", 0.7)
143:         .style("stroke", "#FFFFFF")
144:         .style("fill", "#FFFFFF");
145:     
146: }
147:  
148: 
149: function mouseMove() {
150: 
151:     x_mouse = d3.mouse(this)[0];
152: 
153:     x_end = x_mouse;
154: 
155:     var no_bags = 0;
156: 
157:     //console.log("Xpos: " + x_mouse);
158:     //console.log("Selection in progress: " + selection_in_progress );
159: 
160:     // console.log( "xxx" +  x );
161: 
162:     if(selection_in_progress)
163:     {
164: 
165:        d3.select("#the_area").remove();
166:        d3.select("#the_text").remove();
167:        d3.select("#timespan_start").remove();
168:        d3.select("#timespan_end").remove();
169:        d3.select("#timespan").remove();
170:        d3.select("#bags_min").remove();
171: 
172: 
173:         var timespan;
174:         var i_min = 0;
175:         var i_max = 0;
176: 
177:         for( var i = 0; i < dup_data.length; i++)
178:         {
179:             //console.log("X value " +  x(parseDate0(dup_data[i].log_time)) );
180: 
181:             //console.log("X value " +  x(function(d) { return x(dup_data[i].log_time); });
182:             //console.log("Time : " +  parseDate0(dup_data[i].log_time));
183:             //console.log("Value : " + dup_data[i].bags_produced );
184: 
185:             if( (x_start -54) <= x(parseDate0(dup_data[i].log_time))  &&  x(parseDate0(dup_data[i].log_time)) <= (x_end -54) )
186:             {
187: 
188: 
189:                 // find out i_min, i_max
190:                 if(i_min == 0)
191:                 {
192:                   i_min = i;
193:                 }
194: 
195:                 i_max = i;
196: 
197:                 // sum bags in interval
198:                 no_bags = no_bags + +dup_data[i].bags_produced;
199:             }
200: 
201:             // calculate timespan
202: 
203:         }
204:         
205:         timespan = (((parseDate0(dup_data[i_max].log_time) - parseDate0(dup_data[i_min].log_time))/1000)/60); 
206: 
207:        sel_area = svg.append("rect")
208:        .attr("height", height - 100 )
209:        .attr("id", "the_area")
210:        .attr("width", x_end - x_start)
211:        .attr("x", x_start - 52 )
212:        .attr("y", 100)
213:        .attr("opacity", .35)
214:        .style("stroke", "#CCFFFF")
215:        .style("fill", "green");
216: 
217:         // Display timespan
218:         sel_area = svg.append("text")
219:             .attr("id", "timespan_start")
220:             .attr("x", x_start - 50 )
221:             .attr("y", 10)
222:             .attr("opacity", "1")
223:             .style("fill", "black")
224:             .attr("font-family", "sans-serif")  
225:             .text("Start: " + dup_data[i_min].log_time);
226: 
227:         sel_area = svg.append("text")
228:             .attr("id", "timespan_end")
229:             .attr("x", x_start - 50 )
230:             .attr("y", 30)
231:             .style("fill", "black")
232:             .attr("font-family", "sans-serif")  
233:             .attr("opacity", "1")
234:             .text("End: " + dup_data[i_max].log_time);
235: 
236: 
237:         sel_area = svg.append("text")
238:             .attr("id", "timespan")
239:             .attr("x", x_start - 50 )
240:             .attr("y", 50)
241:             .style("fill", "black")
242:             .attr("font-family", "sans-serif")  
243:             .attr("opacity", "1")
244:             .text("Minutes: " + timespan.toFixed(0));
245: 
246:         sel_area = svg.append("text")
247:             .attr("id", "the_text")
248:             .attr("x", x_start - 50  )
249:             .attr("y", + 70)
250:             .style("fill", "black")
251:             .attr("font-family", "sans-serif")  
252:             .attr("opacity", "1")
253:             .text("No units: " + no_bags);
254: 
255:         sel_area = svg.append("text")
256:             .attr("id", "bags_min")
257:             .attr("x", x_start - 50 )
258:             .attr("y", + 90)
259:             .style("fill", "black")
260:             .attr("font-family", "sans-serif")  
261:             .attr("opacity", "1")
262:             .text("Units/min: " + (no_bags/timespan).toFixed(1) );
263: 
264: 
265:     }
266: 
267: }
268: 
269: function mouseUp() {
270:     // console.log("mouseUp");
271: 
272:     selection_in_progress = 0;
273: 
274:     x_end = d3.mouse(this)[0];
275: 
276: 
277: }
278:  
279: function mouseClick() {
280:     //console.log("mouseClick");
281:     //alert("Click");
282: }
283: 
284: 
285: 
286: 
287: //----------------------------------------------------------------------
288: //
289: //----------------------------------------------------------------------
290: function draw_prod_stat() 
291: {
292: 
293: 
294:     //return;
295: 
296:     var prod_stat_canvas = document.getElementById("#chartContainer");
297:     var prod_stat_context = prod_stat_canvas.getContext("2d");
298:     
299:     var my_gradient = prod_stat_context.createLinearGradient(1500/2, 0, 1500/2, 350);
300: 
301:     my_gradient.addColorStop(0, '#FFFFFF' );
302:     my_gradient.addColorStop(1, '#99CCFF' );
303: 
304:     prod_stat_context.fillStyle = my_gradient;
305:     prod_stat_context.fillRect(0, 0, 1500, 350);
306: 
307:     //prod_stat_context.fillRect(0, 0, 1500, 200);
308: 
309: }
310: 
311: 
312: 
313: 
314: //----------------------------------------------------------------------
315: //  Draw nice data
316: //----------------------------------------------------------------------
317: function draw_nice()
318: {
319: 
320:     //return;
321: 
322:     var chart = new CanvasJS.Chart("chartContainer",
323:     {
324:         zoomEnabled: true,
325:         panEnabled: true, 
326:         title:
327:         {
328:             text: "Production statistics" 
329:         },
330:         legend: 
331:         {
332:             horizontalAlign: "left",
333:             verticalAlign: "center"        
334:         },
335:         axisY:
336:         {
337:             includeZero: false
338:         },
339:         data: data,  // random generator below
340:     });
341: 
342: 
343:     chart.render();
344: }
345: 
346: 
347: //----------------------------------------------------------------------
348: //
349: //----------------------------------------------------------------------
350: $().ready(function()
351: {
352: 
353: // ??
354: 
355: });
356: 

The script that generates data

01: <?php
02: //----------------------------------------------------------------------
03: //  get-device-counter.php
04: //
05: //  A server script that generates data for the graph
06: //----------------------------------------------------------------------
07: 
08: // $txt_file = file_get_contents("/home/gorhas/public_html/d3/stoved.log");
09: 
10: error_reporting(0);
11: 
12: // Here I have the data in a file. In real life it should be
13: // collected from a database
14: $file = fopen("/home/gorhas/public_html/framework/counter-device-1.log", "r");
15: 
16: $counter_data = array();
17: 
18: // We take the data in the file and create data for the diagram
19: // First read in first line
20: //
21: $first_line = fgets($file);
22: $row_data = explode(' ', $first_line);
23: $old_counter_data = $row_data[2];
24: 
25: while(!feof($file))
26: {
27:     
28:     $line = fgets($file);
29:     
30:     //get row data
31:     $row_data = explode(' ', $line);
32:     
33:     $new_counter_data = $row_data[2] - $old_counter_data;
34:     
35:  
36:     $values = array("log_time" => $row_data[0] . " " . $row_data[1],
37:                     "bags_produced"=> $new_counter_data);
38:     
39:     array_push($counter_data, $values); 
40:     
41:     $old_counter_data = $row_data[2];
42: 
43: }
44: 
45: // Now send the data to the webb-page
46: echo json_encode($counter_data);
47: //----------------------------------------------------------------------
48: // END
49: //----------------------------------------------------------------------
50: ?>
51: 
52: 

Temperature graph

A slight variant of this is a temperature graph.