git.haldean.org sousvide / 0e9076a
Pretty d3.js charts in the background! Will Haldean Brown 8 years ago
6 changed file(s) with 167 addition(s) and 43 deletion(s). Raw diff Collapse all Expand all
0 // used to implement a drop-n lowpass filter
1 var lowpass = 0
2 var drop = 1
3
4 // store an hour of data for graphing
5 var n = 30 * 60 / drop;
6 var data = new Array(n);
7 var target = new Array(n);
8
9 for (var i = 0; i < n; i++) {
10 data[i] = 0
11 target[i] = 50
12 }
13
14 var width, height, x, y
15
16 var line = d3.svg.line()
17 .interpolate("basis")
18 .x(function(d, i) { return x(i); })
19 .y(function(d, i) { return y(d); });
20
21 var svg, path, targetpath
22
23 function initChart() {
24 width = window.innerWidth;
25 height = window.innerHeight;
26
27 x = d3.scale.linear()
28 .domain([0, n - 1])
29 .range([0, width]);
30
31 y = d3.scale.linear()
32 .domain([0, 100])
33 .range([height, 0]);
34
35 svg = d3.select("body").append("svg")
36 .attr("width", width)
37 .attr("height", height)
38 .append("g");
39
40 targetpath = svg.append("g")
41 .append("path")
42 .datum(target)
43 .attr("class", "targetline")
44 .attr("d", line);
45
46 path = svg.append("g")
47 .append("path")
48 .datum(data)
49 .attr("class", "line")
50 .attr("d", line);
51 }
52
53 function addTemps(temps) {
54 for (var i = 0; i < temps.length; i += drop) {
55 data.push(temps[i])
56 if (data.length > n) {
57 data.shift();
58 }
59 }
60 }
61
62 function pushTemp(temp) {
63 if (lowpass++ % drop) return
64
65 data.push(temp);
66 path
67 .attr("d", line)
68 .attr("transform", null)
69 .transition()
70 .duration(1000)
71 .ease("linear")
72 .attr("transform", "translate(" + x(-1) + ",0)")
73 data.shift();
74 }
75
76 function setTarget(newT) {
77 for (var i = 0; i < n; i++) {
78 target[i] = newT
79 }
80 targetpath.attr("d", line)
81 }
66 <link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700|Source+Code+Pro' rel='stylesheet' type='text/css'>
77
88 <script src="http://cdn.enderjs.com/ender.min.js"></script>
9 <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
10 <script src="themes.js"></script>
911 <script src="sousvide.js"></script>
12 <script src="chart.js"></script>
1013 </head>
11 <body>
12 <h1><a href="http://263a.net">0x263A</a> &mdash; SV2.1.0</h1>
14 <body class="bg-primary">
15 <h1 class="fg-secondary">
16 <a href="http://263a.net" class="fg-secondary">0x263A</a> &mdash; SV2.1.0
17 </h1>
1318 <div id="floater">
1419 <div id="display">
1520 <div id="temp_container"><span id="temp"></span> &deg;C</div>
1621 <div id="target_container">
17 <span class="label">target</span>
22 <span class="fg-secondary">target</span>
1823 <span id="target"></span> &deg;C
1924 </div>
2025 <div id="error_container">
21 <span class="label">offset</span>
26 <span class="fg-secondary">offset</span>
2227 <span id="abs_err"></span> &deg;C
2328 </div>
2429 </div>
25 <div id="buttonbar">
30 <div id="buttonbar" class="bg-secondary">
2631 <a id="button_enable" href="#">Enabled</a>
2732 <a id="button_disable" href="#">Disabled</a>
2833 </div>
2934 </div>
30 <div id="loader">&deg;</div>
35 <div id="loader" class="fg-secondary">&deg;</div>
3136
3237 <section style="display:none;">
3338 <h2>timers</h2>
77 url('webfonts/norwester.svg#font') format('svg');
88 }
99
10 .bg-primary { background: #FE4F00; }
11 .bg-secondary { background: #FFB213; }
12 .fg-primary { color: #FE4F00; }
13 .fg-secondary { color: #FFB213; }
14 /*
15 .bg-primary { background: #78F418; }
16 .bg-secondary { background: #4D742E; }
17 .fg-primary { color: #78F418; }
18 .fg-secondary { color: #4D742E; }
19 */
20
1021 body {
1122 font-family: 'Source Sans Pro', sans-serif;
1223 font-size: 14pt;
13 background: #FE4F00;
1424 margin: 0;
25 overflow: hidden;
1526 }
1627
1728 #floater {
1829 position: fixed;
1930 right: 32pt;
20 top: 32pt;
31 top: 0;
2132 font-family: Norwester, monospace;
2233 width: 500pt;
2334 }
6172 #buttonbar {
6273 width: 500pt;
6374 float: left;
64 background: #FFB213;
65 color: #FE4F00;
6675 }
6776
6877 #buttonbar a {
7079 width: 216pt;
7180 padding: 8pt 16pt;
7281 text-transform: uppercase;
73 color: #FE4F00;
7482 text-decoration: none;
7583 }
7684
8391 text-align: right;
8492 }
8593
86 #buttonbar .selected {
94 #buttonbar .fg-secondary {
8795 background: #FFF;
88 color: #FFB213;
8996 }
9097
9198 #loader {
9299 font-family: Norwester, monospace;
93100 font-size: 128pt;
94 color: #FFB213;
95101 position: absolute;
96102 top: 32pt;
97103 left: 48pt;
135141 position: absolute;
136142 bottom: 16pt;
137143 right: 32pt;
138 color: #FFB213;
139144 }
140145
141146 h1 a {
142 color: #FFB213;
143147 text-decoration: none;
144148 }
149
150 .line {
151 fill: none;
152 stroke: #000;
153 stroke-width: 1.5px;
154 }
155
156 .targetline {
157 stroke: #FFB213;
158 stroke-width: 5px;
159 shape-rendering: crispEdges;
160 }
0 // store 3 hours of data for graphing
1 var MAX_TEMP_STORE = 60 * 60 * 3;
2 var temps = new Array();
3
40 var loader
51 var tempElem, absErrElem, targetElem, heatingElem, plotElem, accErrElem
62 var targetDisplayElem, targetChangeElem, targetInputElem
84 var enabledElem, maxErrElem
95 var timerElem, timerAudio
106
11 var enableButton, disableButton
7 var enableButton, disableButton, lastEnabled = undefined
128
139 var loadUntilTrue = undefined;
1410
1713 url: '/json',
1814 type: 'json',
1915 success: function(resp) {
16 var temps = Array();
2017 for (var i = 0; i < resp.length; i++) {
21 temps.push(resp[i].Temp);
22 if (temps.length > MAX_TEMP_STORE) {
23 temps.shift();
24 }
18 temps.push(resp[i].Temp)
2519 }
26 console.log("initialized temps to:");
27 console.log(temps);
28 getApiData();
20 console.log("initialized temps to:")
21 console.log(temps)
22 addTemps(temps)
23
24 initChart()
25 window.onresize = function() {
26 console.log("window onresize");
27 document.getElementsByTagName("svg")[0].remove();
28 initChart();
29 };
30 getApiData()
2931 }
3032 })
3133 }
5355 err = temp - target;
5456
5557 if (temp != undefined) {
56 temps.push(temp);
57 while (temps.length > MAX_TEMP_STORE) {
58 temps.shift();
59 }
58 pushTemp(temp);
6059 }
6160
6261 $(tempElem).text(temp.toFixed(1));
6362 $(targetElem).text(target.toFixed(2));
6463 $(absErrElem).text((err >= 0 ? '+' : '') + err.toFixed(2));
6564
66 if (data.Enabled) {
67 $(enableButton).addClass('selected')
68 $(disableButton).removeClass('selected')
69 } else {
70 $(enableButton).removeClass('selected')
71 $(disableButton).addClass('selected')
72 }
65 if (data.Enabled && (lastEnabled == false || lastEnabled == undefined)) {
66 console.log("dis -> en")
67 $(enableButton).addClass('fg-secondary')
68 $(enableButton).removeClass('fg-primary')
69 $(disableButton).addClass('fg-primary')
70 $(disableButton).removeClass('fg-secondary')
71 reapplyTheme()
72 } else if (!data.Enabled && (lastEnabled == true || lastEnabled == undefined)) {
73 console.log("en -> dis")
74 $(disableButton).addClass('fg-secondary')
75 $(disableButton).removeClass('fg-primary')
76 $(enableButton).addClass('fg-primary')
77 $(enableButton).removeClass('fg-secondary')
78 reapplyTheme()
79 }
80 lastEnabled = data.Enabled
7381
7482 $(accErrElem).text(data.AccError.toFixed(2))
7583 $(maxErrElem).text(data.MaxError.toFixed(2))
171179 }
172180
173181 $(document).ready(function() {
182 //setTheme("#FFF", "#000")
183
174184 tempElem = document.getElementById('temp')
175185 absErrElem = document.getElementById('abs_err')
176186 targetElem = document.getElementById('target')
0 var primary, secondary
1 function setTheme(p, s) {
2 primary = p
3 secondary = s
4 reapplyTheme();
5 }
6
7 function reapplyTheme() {
8 $('.bg-primary').css('background', primary)
9 $('.bg-secondary').css('background', secondary)
10 $('.fg-primary').css('color', primary)
11 $('.fg-secondary').css('color', secondary)
12 }
6363 func (s *SousVide) MeasureTemp() error {
6464 if *FakeTemp {
6565 if s.Heating {
66 s.Temp += Celsius(10 * rand.Float64())
66 s.Temp += Celsius(rand.Float64())
6767 } else {
68 if rand.Int() % 3 == 0 {
69 s.Temp -= Celsius(rand.Float64())
70 }
68 s.Temp -= Celsius(rand.Float64())
7169 }
7270 if s.Temp < 0 {
7371 s.Temp = 0