|
1 /***************************************************************************** |
|
2 * Copyright (C) 2024 |
|
3 * |
|
4 * Michiel Broek <mbroek at mbse dot eu> |
|
5 * |
|
6 * This file is part of mbsePi-apps |
|
7 * |
|
8 * This is free software; you can redistribute it and/or modify it |
|
9 * under the terms of the GNU General Public License as published by the |
|
10 * Free Software Foundation; either version 2, or (at your option) any |
|
11 * later version. |
|
12 * |
|
13 * BrewCloud is distributed in the hope that it will be useful, but |
|
14 * WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
16 * General Public License for more details. |
|
17 * |
|
18 * You should have received a copy of the GNU General Public License |
|
19 * along with ThermFerm; see the file COPYING. If not, write to the Free |
|
20 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
|
21 *****************************************************************************/ |
|
22 |
|
23 |
|
24 function createDelElements() { |
|
25 $('#eventWindow').jqxWindow({ |
|
26 theme: theme, |
|
27 position: { x: 430, y: 210 }, |
|
28 width: 420, |
|
29 height: 175, |
|
30 resizable: false, |
|
31 isModal: true, |
|
32 modalOpacity: 0.4, |
|
33 okButton: $('#delOk'), |
|
34 cancelButton: $('#delCancel'), |
|
35 initContent: function() { |
|
36 $('#delOk').jqxButton({ template: 'danger', width: '65px', theme: theme }); |
|
37 $('#delCancel').jqxButton({ template: 'success', width: '65px', theme: theme }); |
|
38 $('#delCancel').focus(); |
|
39 } |
|
40 }); |
|
41 $('#eventWindow').jqxWindow('hide'); |
|
42 } |
|
43 |
|
44 |
|
45 function createAddElements() { |
|
46 $('#addWindow').jqxWindow({ |
|
47 theme: theme, |
|
48 position: { x: 400, y: 210 }, |
|
49 width: 480, |
|
50 height: 180, |
|
51 resizable: false, |
|
52 isModal: true, |
|
53 modalOpacity: 0.4, |
|
54 okButton: $('#addOk'), |
|
55 cancelButton: $('#addCancel'), |
|
56 initContent: function() { |
|
57 $('#addOk').jqxButton({ template: 'success', width: '65px', theme: theme }); |
|
58 $('#addCancel').jqxButton({ template: 'primary', width: '65px', theme: theme }); |
|
59 $('#addCancel').focus(); |
|
60 } |
|
61 }); |
|
62 $('#addWindow').jqxWindow('hide'); |
|
63 } |
|
64 |
|
65 |
|
66 |
|
67 $(document).ready(function() { |
|
68 var dataRecord = {}, |
|
69 url = 'dbfermenters.php', |
|
70 source = { |
|
71 datatype: 'json', |
|
72 cache: false, |
|
73 datafields: [ |
|
74 { name: 'uuid', type: 'string' }, |
|
75 { name: 'alias', type: 'string' }, |
|
76 { name: 'product_code', map: 'product>code' }, |
|
77 { name: 'product_name', map: 'product>name' }, |
|
78 { name: 'air_address', map: 'air>address' }, |
|
79 { name: 'air_idx', map: 'air>idx', type: 'int' }, |
|
80 { name: 'beer_address', map: 'beer>address' }, |
|
81 { name: 'beer_idx', map: 'beer>idx', type: 'int' }, |
|
82 { name: 'chiller_address', map: 'chiller>address' }, |
|
83 { name: 'chiller_idx', map: 'chiller>idx', type: 'int' }, |
|
84 { name: 'light_address', map: 'light>address' }, |
|
85 { name: 'light_state', map: 'light>state', type: 'int' }, |
|
86 { name: 'light_delay', map: 'light>delay', type: 'int' }, |
|
87 { name: 'light_idx', map: 'light>idx', type: 'int' }, |
|
88 { name: 'heater_address', map: 'heater>address' }, |
|
89 { name: 'heater_state', map: 'heater>state', type: 'int' }, |
|
90 { name: 'heater_delay', map: 'heater>delay', type: 'int' }, |
|
91 { name: 'heater_idx', map: 'heater>idx', type: 'int' }, |
|
92 { name: 'cooler_address', map: 'cooler>address' }, |
|
93 { name: 'cooler_state', map: 'cooler>state', type: 'int' }, |
|
94 { name: 'cooler_delay', map: 'cooler>delay', type: 'int' }, |
|
95 { name: 'cooler_idx', map: 'cooler>idx', type: 'int' }, |
|
96 { name: 'fan_address', map: 'fan>address' }, |
|
97 { name: 'fan_state', map: 'fan>state', type: 'int' }, |
|
98 { name: 'fan_delay', map: 'fan>delay', type: 'int' }, |
|
99 { name: 'fan_idx', map: 'fan>idx', type: 'int' }, |
|
100 { name: 'door_address', map: 'door>address' }, |
|
101 { name: 'door_idx', map: 'door>idx', type: 'int' }, |
|
102 { name: 'door_state', map: 'door>state', type: 'int' }, |
|
103 { name: 'psu_address', map: 'psu>address' }, |
|
104 { name: 'psu_idx', map: 'psu>idx', type: 'int' }, |
|
105 { name: 'psu_state', map: 'psu>state', type: 'int' }, |
|
106 { name: 'stage' }, |
|
107 { name: 'mode' }, |
|
108 { name: 'setpoint_low', map: 'setpoint>low', type: 'float' }, |
|
109 { name: 'setpoint_high', map: 'setpoint>high', type: 'float' }, |
|
110 { name: 'alarm', type: 'int' }, |
|
111 { name: 'pidc_p', map: 'pidc>P', type: 'float' }, |
|
112 { name: 'pidc_i', map: 'pidc>I', type: 'float' }, |
|
113 { name: 'pidc_d', map: 'pidc>D', type: 'float' }, |
|
114 { name: 'pidc_imax', map: 'pidc>imax', type: 'float' }, |
|
115 { name: 'pidc_idle', map: 'pidc>idle', type: 'float' }, |
|
116 { name: 'pidh_p', map: 'pidh>P', type: 'float' }, |
|
117 { name: 'pidh_i', map: 'pidh>I', type: 'float' }, |
|
118 { name: 'pidh_d', map: 'pidh>D', type: 'float' }, |
|
119 { name: 'pidh_imax', map: 'pidh>imax', type: 'float' }, |
|
120 { name: 'pidh_idle', map: 'pidh>idle', type: 'float' } |
|
121 ], |
|
122 id: 'uuid', |
|
123 url: url |
|
124 }, |
|
125 dataAdapter = new $.jqx.dataAdapter(source), |
|
126 editrow = -1; |
|
127 |
|
128 // initialize the input fields. |
|
129 $('#uuid').jqxInput({ theme: theme, width: 360, height: 23 }); |
|
130 $('#alias').jqxInput({ theme: theme, width: 120, height: 23 }); |
|
131 $('#product_code').jqxInput({ theme: theme, width: 120, height: 23 }); |
|
132 $('#product_name').jqxInput({ theme: theme, width: 360, height: 23 }); |
|
133 $('#mode').jqxInput({ theme: theme, width: 120, height: 23 }); |
|
134 $('#stage').jqxInput({ theme: theme, width: 120, height: 23 }); |
|
135 $('#air_address,#beer_address,#beer_address2,#chiller_address').jqxDropDownList({ |
|
136 theme: theme, |
|
137 source: tempsensorlist, |
|
138 valueMember: 'uuid', |
|
139 displayMember: 'name', |
|
140 width: 240, |
|
141 dropDownWidth: 480, |
|
142 autoDropDownHeight: true |
|
143 }); |
|
144 $('#air_idx,#beer_idx,#chiller_idx,#heater_idx,#cooler_idx,#fan_idx,#light_idx,#door_idx,#psu_idx').jqxNumberInput(Spin0dec); |
|
145 $('#heater_address,#cooler_address,#fan_address,#light_address').jqxDropDownList({ |
|
146 theme: theme, |
|
147 source: switcheslist, |
|
148 valueMember: 'uuid', |
|
149 displayMember: 'name', |
|
150 width: 240, |
|
151 dropDownWidth: 480, |
|
152 autoDropDownHeight: true |
|
153 }); |
|
154 $('#heater_state,#cooler_state,#fan_state,#light_state').jqxNumberInput(Perc0); |
|
155 $('#heater_delay,#cooler_delay,#fan_delay,#light_delay').jqxNumberInput(Spin0dec); |
|
156 $('#pidh_p,#pidh_i,#pidh_d,#pidc_p,#pidc_i,#pidc_d').jqxNumberInput(Spin3dec); |
|
157 $('#pidh_imax,#pidc_imax').jqxNumberInput(Perc1dec); |
|
158 $('#pidh_idle,#pidc_idle').jqxNumberInput(Spin2dec); |
|
159 $('#door_address,#psu_address').jqxDropDownList({ |
|
160 theme: theme, |
|
161 source: contactslist, |
|
162 valueMember: 'uuid', |
|
163 displayMember: 'name', |
|
164 width: 240, |
|
165 dropDownWidth: 480, |
|
166 autoDropDownHeight: true |
|
167 }); |
|
168 $('#door_state,#psu_state').jqxNumberInput(Show0dec); |
|
169 |
|
170 // initialize jqxGrid |
|
171 $('#jqxgrid').jqxGrid({ |
|
172 width: 1280, |
|
173 height: 630, |
|
174 source: dataAdapter, |
|
175 theme: theme, |
|
176 showstatusbar: true, |
|
177 renderstatusbar: function(statusbar) { |
|
178 var rowCount = $("#jqxgrid").jqxGrid('getrows').length; |
|
179 statusbar.append('<div style="float: left; margin: 8px; color: orange !important;">Total items: ' + rowCount + '</div>'); |
|
180 var container, addButton, impButton; |
|
181 container = $('<div style="overflow: hidden; position: relative; margin: 5px;"></div>'); |
|
182 addButton = $('<div style="float: right; margin-right: 15px;"><img style="position: relative; margin-top: 2px;" ' + |
|
183 'src="images/add.png"/><span style="margin-left: 4px; position: relative; top: -4px;">New</span></div>'); |
|
184 container.append(addButton); |
|
185 statusbar.append(container); |
|
186 addButton.jqxButton({ theme: theme, width: 90, height: 17 }); |
|
187 // add new row. |
|
188 addButton.click(function(event) { |
|
189 $('#addWindow').jqxWindow('open'); |
|
190 $('#addOk').click(function() { |
|
191 var data, |
|
192 data = 'add=true&name=dummy' |
|
193 console.log(data); |
|
194 $.ajax({ |
|
195 dataType: 'json', |
|
196 url: url, |
|
197 cache: false, |
|
198 data: data, |
|
199 type: 'POST', |
|
200 success: function(data) { |
|
201 if (data.error) { |
|
202 console.log('add: ' + data.msg); |
|
203 alert('Error: ' + data.msg); |
|
204 } else { |
|
205 console.log('add: success'); |
|
206 } |
|
207 }, |
|
208 error: function(jqXHR, textStatus, errorThrown) {} |
|
209 }); |
|
210 $('#jqxgrid').jqxGrid('updatebounddata'); |
|
211 }); |
|
212 }); |
|
213 }, |
|
214 columns: [ |
|
215 { text: 'Unit', datafield: 'alias', width: 200 }, |
|
216 { text: 'Mode', datafield: 'mode', width: 120 }, |
|
217 { text: 'Code', datafield: 'product_code', width: 150 }, |
|
218 { text: 'Beer', datafield: 'product_name' }, |
|
219 { text: '', datafield: 'Edit', width: 100, align: 'center', columntype: 'button', cellsrenderer: function() { |
|
220 return 'Edit'; |
|
221 }, buttonclick: function(row) { |
|
222 // open the popup window when the user clicks a button. |
|
223 editrow = row; |
|
224 $('#popupWindow').jqxWindow({ position: { x: 40, y: 15 } }); |
|
225 dataRecord = $('#jqxgrid').jqxGrid('getrowdata', editrow); |
|
226 $('#uuid').val(dataRecord.uuid); |
|
227 $('#alias').val(dataRecord.alias); |
|
228 $('#product_code').val(dataRecord.product_code); |
|
229 $('#product_name').val(dataRecord.product_name); |
|
230 $('#air_address').val(dataRecord.air_address); |
|
231 $('#air_idx').val(dataRecord.air_idx); |
|
232 $('#beer_address').val(dataRecord.beer_address); |
|
233 $('#beer_address2').val(dataRecord.beer_address2); |
|
234 $('#beer_idx').val(dataRecord.beer_idx); |
|
235 $('#chiller_address').val(dataRecord.chiller_address); |
|
236 $('#chiller_idx').val(dataRecord.chiller_idx); |
|
237 $('#heater_address').val(dataRecord.heater_address); |
|
238 $('#heater_idx').val(dataRecord.heater_idx); |
|
239 $('#heater_state').val(dataRecord.heater_state); |
|
240 $('#heater_delay').val(dataRecord.heater_delay); |
|
241 $('#cooler_address').val(dataRecord.cooler_address); |
|
242 $('#cooler_idx').val(dataRecord.cooler_idx); |
|
243 $('#cooler_state').val(dataRecord.cooler_state); |
|
244 $('#cooler_delay').val(dataRecord.cooler_delay); |
|
245 $('#fan_address').val(dataRecord.fan_address); |
|
246 $('#fan_idx').val(dataRecord.fan_idx); |
|
247 $('#fan_state').val(dataRecord.fan_state); |
|
248 $('#fan_delay').val(dataRecord.fan_delay); |
|
249 $('#light_address').val(dataRecord.light_address); |
|
250 $('#light_idx').val(dataRecord.light_idx); |
|
251 $('#light_state').val(dataRecord.light_state); |
|
252 $('#light_delay').val(dataRecord.light_delay); |
|
253 $('#door_address').val(dataRecord.door_address); |
|
254 $('#door_idx').val(dataRecord.door_idx); |
|
255 $('#door_state').val(dataRecord.door_state); |
|
256 $('#psu_address').val(dataRecord.psu_address); |
|
257 $('#psu_idx').val(dataRecord.psu_idx); |
|
258 $('#psu_state').val(dataRecord.psu_state); |
|
259 $('#mode').val(dataRecord.mode); |
|
260 $('#stage').val(dataRecord.stage); |
|
261 $('#pidc_p').val(dataRecord.pidc_p); |
|
262 $('#pidc_i').val(dataRecord.pidc_i); |
|
263 $('#pidc_d').val(dataRecord.pidc_d); |
|
264 $('#pidc_imax').val(dataRecord.pidc_imax); |
|
265 $('#pidc_idle').val(dataRecord.pidc_idle); |
|
266 $('#pidh_p').val(dataRecord.pidh_p); |
|
267 $('#pidh_i').val(dataRecord.pidh_i); |
|
268 $('#pidh_d').val(dataRecord.pidh_d); |
|
269 $('#pidh_imax').val(dataRecord.pidh_imax); |
|
270 $('#pidh_idle').val(dataRecord.pidh_idle); |
|
271 |
|
272 // show the popup window. |
|
273 $('#popupWindow').jqxWindow('open'); |
|
274 } |
|
275 } |
|
276 ], |
|
277 }); |
|
278 |
|
279 // initialize the popup window and buttons. |
|
280 $('#popupWindow').jqxWindow({ |
|
281 width: 1280, |
|
282 height: 625, |
|
283 resizable: false, |
|
284 theme: theme, |
|
285 isModal: true, |
|
286 autoOpen: false, |
|
287 cancelButton: $('#Cancel'), |
|
288 modalOpacity: 0.40 |
|
289 }); |
|
290 $('#popupWindow').on('open', function() { |
|
291 // $('#dev_description').jqxInput('selectAll'); |
|
292 }); |
|
293 $('#Delete').jqxButton({ template: 'danger', width: '90px', theme: theme }); |
|
294 $('#Delete').click(function() { |
|
295 // Open a popup to confirm this action. |
|
296 $('#eventWindow').jqxWindow('open'); |
|
297 $('#delOk').click(function() { |
|
298 var data, |
|
299 data = 'del=true&uuid=' + $('#uuid').val(); |
|
300 $.ajax({ |
|
301 dataType: 'json', |
|
302 url: url, |
|
303 cache: false, |
|
304 data: data, |
|
305 type: 'POST', |
|
306 success: function(data) { |
|
307 if (data.error) { |
|
308 console.log('del: ' + data.msg); |
|
309 alert('Error: ' + data.msg); |
|
310 } else { |
|
311 console.log('del: success'); |
|
312 } |
|
313 }, |
|
314 error: function(jqXHR, textStatus, errorThrown) {} |
|
315 }); |
|
316 $('#jqxgrid').jqxGrid('updatebounddata'); |
|
317 }); |
|
318 $('#popupWindow').jqxWindow('hide'); |
|
319 }); |
|
320 $('#Cancel').jqxButton({ template: 'primary', width: '90px', theme: theme }); |
|
321 $('#Save').jqxButton({ template: 'success', width: '90px', theme: theme }); |
|
322 $('#Save').click(function() { |
|
323 var data, |
|
324 row = { |
|
325 uuid: dataRecord.uuid, |
|
326 // type: $('#dev_type').val(), |
|
327 // direction: $('#dev_direction').val(), |
|
328 // value: parseInt($('#dev_value').jqxNumberInput('decimal')), |
|
329 // offset: parseInt($('#dev_offset').jqxNumberInput('decimal')), |
|
330 // present: $('#dev_present').val(), |
|
331 // address: $('#dev_address').val(), |
|
332 // subdevice: parseInt($('#dev_subdevice').jqxNumberInput('decimal')), |
|
333 // gpiopin: parseInt($('#dev_gpiopin').jqxNumberInput('val')), |
|
334 // description: $('#dev_description').val(), |
|
335 // comment: $('#dev_comment').val() |
|
336 }; |
|
337 data = 'update=true&' + $.param(row); |
|
338 console.log(data); |
|
339 $.ajax({ |
|
340 dataType: 'json', |
|
341 url: url, |
|
342 cache: false, |
|
343 data: data, |
|
344 type: 'POST', |
|
345 success: function(data) { |
|
346 if (data.error) { |
|
347 console.log('update: ' + data.msg); |
|
348 alert('Error: ' + data.msg); |
|
349 } else { |
|
350 console.log('update: success'); |
|
351 } |
|
352 }, |
|
353 error: function(jqXHR, textStatus, errorThrown) {} |
|
354 }); |
|
355 $('#popupWindow').jqxWindow('hide'); |
|
356 }); |
|
357 createDelElements(); |
|
358 createAddElements(); |
|
359 |
|
360 websocket.onmessage = function(evt) { |
|
361 var msg = evt.data; |
|
362 var obj = JSON.parse(msg); |
|
363 |
|
364 if (obj.ping) { |
|
365 websocket.send('{"pong":' + obj.ping + '}'); |
|
366 } |
|
367 |
|
368 if (obj.type == 'device') { |
|
369 // Use the message to trigger update. |
|
370 $('#jqxgrid').jqxGrid('updatebounddata'); |
|
371 } |
|
372 } |
|
373 }); |