git.haldean.org sousvide / 671fd6a
More modularization, error mask Now there's a modal interstitial that pops up when api_data takes a long time at first, and it animates around really nicely because yay! Will Haldean Brown 8 years ago
6 changed file(s) with 200 addition(s) and 129 deletion(s). Raw diff Collapse all Expand all
99 <script src="themes.js"></script>
1010 <script src="chart.js"></script>
1111 <script src="timers.js"></script>
12 <script src="temp.js"></script>
1213 <script src="sousvide.js"></script>
1314 </head>
1415 <body class="bg-primary">
16 <div id="mask">
17 <div id="wait">
18 <h2>Sorry about this</h2>
19 Your sous vide is taking a second to give us the deets. Hold
20 tight.
21 </div>
22 </div>
1523 <h1 class="fg-secondary">SV2.1.0</h1>
1624 <div id="floater">
1725 <div id="display">
1919 overflow: hidden;
2020 }
2121
22 #mask {
23 position: fixed;
24 left: 0;
25 top: 0;
26 width: 100%;
27 height: 100%;
28 z-index: 10;
29 display: none;
30 background: #000;
31 }
32
33 #wait {
34 position: absolute;
35 top: 30%;
36 left: 50%;
37 width: 500pt;
38 background: #FFF;
39 padding: 32pt;
40 margin-left: -282pt;
41 text-align: center;
42 }
43
44 #wait h2 {
45 font-family: Norwester, monospace;
46 text-transform: uppercase;
47 font-weight: normal;
48 font-size: 64pt;
49 margin: 0;
50 }
51
2252 #floater {
2353 position: fixed;
2454 left: 32pt;
2555 top: 32pt;
2656 font-family: Norwester, monospace;
2757 width: 500pt;
58 z-index: 0;
2859 }
2960
3061 #display {
0 var loader
1 var tempElem, absErrElem, targetElem, heatingElem, plotElem, accErrElem
2 var targetDisplayElem, targetChangeElem, targetInputElem
3 var pInputElem, iInputElem, dInputElem
4 var enabledElem, maxErrElem
0 var MASK_TIMEOUT_MS = 500
51
6 var enableButton, disableButton, lastEnabled = undefined
7
2 var loader;
83 var loadUntilTrue = undefined;
94
10 function primeTempCache() {
11 $.ajax({
12 url: '/json',
13 type: 'json',
14 success: function(resp) {
15 var temps = Array();
16 for (var i = 0; i < resp.length; i++) {
17 temps.push(resp[i].Temp)
18 }
19 console.log("initialized temps to:")
20 console.log(temps)
21 addTemps(temps)
5 var mask;
6 var maskHidden = true;
227
23 initChart()
24 window.onresize = function() {
25 console.log("window onresize");
26 document.getElementsByTagName("svg")[0].remove();
27 initChart();
28 };
29 getApiData()
30 }
31 })
8 function hideMask() {
9 if (maskHidden) return;
10 maskHidden = true;
11 d3.select('#mask')
12 .transition()
13 .style('opacity', '0')
14 .remove()
3215 }
3316
34 function getApiData() {
35 $.ajax({
36 url: '/api_data',
37 type: 'json',
38 success: function(resp) {
39 displayData(resp)
17 function startMaskTimeout() {
18 maskHidden = false;
19 setTimeout(function() {
20 if (!maskHidden) {
21 d3.select('#mask')
22 .style('display', 'block')
23 .style('opacity', '0')
24 .transition()
25 .style('opacity', '1')
4026 }
41 })
42 plotElem.setAttribute('src', '/plot?' + (new Date()).getTime())
43 setTimeout(getApiData, 1000)
27 }, MASK_TIMEOUT_MS);
4428 }
4529
46 function displayData(data) {
30 function loaded(data) {
31 console.log(data);
4732 if (loadUntilTrue && loadUntilTrue(data)) {
48 $(loader).css('display', 'none')
49 loadUntilTrue = undefined
33 $(loader).css('display', 'none');
34 loadUntiltrue = undefined;
5035 }
51
52 var temp = data.Temp,
53 target = data.Target,
54 err = temp - target;
55
56 if (temp != undefined) {
57 pushTemp(temp);
58 }
59
60 $(tempElem).text(temp.toFixed(1));
61 $(targetElem).text(target.toFixed(2));
62 $(absErrElem).text((err >= 0 ? '+' : '') + err.toFixed(2));
63
64 if (data.Enabled && (lastEnabled == false || lastEnabled == undefined)) {
65 console.log("dis -> en");
66 $(enableButton).removeClass('fg-primary');
67 $(disableButton).removeClass('fg-secondary');
68 $(enableButton).addClass('fg-secondary');
69 $(disableButton).addClass('fg-primary');
70 setOrange();
71 } else if (!data.Enabled && (lastEnabled == true || lastEnabled == undefined)) {
72 console.log("en -> dis");
73 $(enableButton).removeClass('fg-secondary');
74 $(disableButton).removeClass('fg-primary');
75 $(enableButton).addClass('fg-primary');
76 $(disableButton).addClass('fg-secondary');
77 setBlue();
78 }
79 lastEnabled = data.Enabled
80
81 $(accErrElem).text(data.AccError.toFixed(2))
82 $(maxErrElem).text(data.MaxError.toFixed(2))
83
84 pInputElem.setAttribute('value', data.Pid.P)
85 iInputElem.setAttribute('value', data.Pid.I)
86 dInputElem.setAttribute('value', data.Pid.D)
36 hideMask();
8737 }
8838
8939 function attachRequest(elem, path, blinkUntil) {
10959 }
11060
11161 $(document).ready(function() {
112 tempElem = document.getElementById('temp')
113 absErrElem = document.getElementById('abs_err')
114 targetElem = document.getElementById('target')
62 loader = document.getElementById('loader');
63 mask = document.getElementById('mask');
11564
116 enableButton = document.getElementById('button_enable')
117 attachRequest(enableButton, "/enable", function(data) {
118 return data.Enabled
119 })
120 disableButton = document.getElementById('button_disable')
121 attachRequest(disableButton, "/disable", function(data) {
122 return !data.Enabled
123 })
65 startMaskTimeout();
12466
125 loader = document.getElementById('loader')
67 initTempElems();
68 primeTempCache();
12669
127 heatingElem = document.getElementById('heating')
128 plotElem = document.getElementById('plot')
129 accErrElem = document.getElementById('acc_err')
130 maxErrElem = document.getElementById('max_err')
131 enabledElem = document.getElementById('enabled')
132
133 targetChangeElem = document.getElementById('target_change')
134 targetDisplayElem = document.getElementById('target_display')
135 targetInputElem = document.getElementById('target_input')
136
137 pInputElem = document.getElementById('pid_p')
138 iInputElem = document.getElementById('pid_i')
139 dInputElem = document.getElementById('pid_d')
140
141 targetElem.onclick = function() {
142 $(targetDisplayElem).css('display', 'none')
143 $(targetChangeElem).css('display', 'inline')
144 targetInputElem.setAttribute('value', $(targetElem).text())
145 }
146
147 primeTempCache()
148
149 timerElem = document.getElementById('timers')
150 timerAudio = document.getElementById('timernoise')
151 audioEnable = document.getElementById('enable_audio')
152 audioEnable.onclick = function() {
153 $(audioEnable).css('display', 'none')
154 timerAudio.play()
155 }
156 getTimerData()
70 initTimerElems();
71 getTimerData();
15772 })
0 var tempElem, absErrElem, targetElem, heatingElem, accErrElem
1 var targetDisplayElem, targetChangeElem, targetInputElem
2 var enableButton, disableButton, lastEnabled = undefined
3 var pInputElem, iInputElem, dInputElem
4
5 function initTempElems() {
6 tempElem = document.getElementById('temp')
7 absErrElem = document.getElementById('abs_err')
8 targetElem = document.getElementById('target')
9
10 enableButton = document.getElementById('button_enable')
11 attachRequest(enableButton, "/enable", function(data) {
12 return data.Enabled
13 })
14 disableButton = document.getElementById('button_disable')
15 attachRequest(disableButton, "/disable", function(data) {
16 return !data.Enabled
17 })
18
19 heatingElem = document.getElementById('heating')
20 accErrElem = document.getElementById('acc_err')
21
22 targetChangeElem = document.getElementById('target_change')
23 targetDisplayElem = document.getElementById('target_display')
24 targetInputElem = document.getElementById('target_input')
25
26 pInputElem = document.getElementById('pid_p')
27 iInputElem = document.getElementById('pid_i')
28 dInputElem = document.getElementById('pid_d')
29
30 targetElem.onclick = function() {
31 $(targetDisplayElem).css('display', 'none')
32 $(targetChangeElem).css('display', 'inline')
33 targetInputElem.setAttribute('value', $(targetElem).text())
34 }
35 }
36
37 function primeTempCache() {
38 $.ajax({
39 url: '/json',
40 type: 'json',
41 success: function(resp) {
42 var temps = Array();
43 for (var i = 0; i < resp.length; i++) {
44 temps.push(resp[i].Temp)
45 }
46 addTemps(temps)
47
48 initChart()
49 window.onresize = function() {
50 console.log("window onresize");
51 document.getElementsByTagName("svg")[0].remove();
52 initChart();
53 reapplyTheme();
54 };
55 getApiData()
56 }
57 })
58 }
59
60 function getApiData() {
61 $.ajax({
62 url: '/api_data',
63 type: 'json',
64 success: function(resp) {
65 displayData(resp)
66 }
67 })
68 setTimeout(getApiData, 1000)
69 }
70
71 function displayData(data) {
72 console.log("got data!");
73 loaded(data);
74
75 var temp = data.Temp,
76 target = data.Target,
77 err = temp - target;
78
79 if (temp != undefined) {
80 pushTemp(temp);
81 }
82
83 $(tempElem).text(temp.toFixed(1));
84 $(targetElem).text(target.toFixed(2));
85 $(absErrElem).text((err >= 0 ? '+' : '') + err.toFixed(2));
86
87 if (data.Enabled && (lastEnabled == false || lastEnabled == undefined)) {
88 console.log("dis -> en");
89 $(enableButton).removeClass('fg-primary');
90 $(disableButton).removeClass('fg-secondary');
91 $(enableButton).addClass('fg-secondary');
92 $(disableButton).addClass('fg-primary');
93 setOrange();
94 } else if (!data.Enabled && (lastEnabled == true || lastEnabled == undefined)) {
95 console.log("en -> dis");
96 $(enableButton).removeClass('fg-secondary');
97 $(disableButton).removeClass('fg-primary');
98 $(enableButton).addClass('fg-primary');
99 $(disableButton).addClass('fg-secondary');
100 setBlue();
101 }
102 lastEnabled = data.Enabled
103
104 $(accErrElem).text(data.AccError.toFixed(2))
105
106 pInputElem.setAttribute('value', data.Pid.P)
107 iInputElem.setAttribute('value', data.Pid.I)
108 dInputElem.setAttribute('value', data.Pid.D)
109 }
0 var primary, secondary
0 var primary, secondary, graph
11
2 function setTheme(p, s) {
2 function setTheme(p, s, g) {
33 primary = p
44 secondary = s
5 graph = g
56 reapplyTheme();
67 }
78
8 function setBlue() {
9 setTheme("#5116FE", "#45317E");
10 }
11
12 function setOrange() {
13 setTheme("#FE4F00", "#FFB213");
14 }
9 function setBlue() { setTheme("#5116FE", "#45317E", "#000"); }
10 function setOrange() { setTheme("#FE4F00", "#FFB213", "#000"); }
1511
1612 function reapplyTheme() {
1713 d3.selectAll('.bg-primary').transition().style('background-color', primary)
1814 d3.selectAll('.bg-secondary').transition().style('background-color', secondary)
1915 d3.selectAll('.fg-primary').transition().style('color', primary)
2016 d3.selectAll('.fg-secondary').transition().style('color', secondary)
21 d3.select('.targetline').transition().style('stroke', secondary)
17 d3.selectAll('.targetline').transition().style('stroke', secondary)
18 d3.selectAll('.line').transition().style('stroke', graph)
2219 }
2320
0 var timerElem, timerAudio
0 var timerElem, timerAudio, audioEnable
1
2 function initTimerElems() {
3 timerElem = document.getElementById('timers')
4 timerAudio = document.getElementById('timernoise')
5 audioEnable = document.getElementById('enable_audio')
6 audioEnable.onclick = function() {
7 $(audioEnable).css('display', 'none')
8 timerAudio.play()
9 }
10 }
111
212 function getTimerData() {
313 $.ajax({