Tue, 30 Apr 2024 17:26:41 +0200
Version 0.9.19b2. Simulator redesign and it is now possible to run more then one simulator. All simulated devices have address names that include the simulator number. Added the setup screen for the most part. Not compatible with previous versions if a simulator was used, delete all simulators and simulated devices during stop and start.
/***************************************************************************** * Copyright (C) 2024 * * Michiel Broek <mbroek at mbse dot eu> * * This file is part of mbsePi-apps * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * BrewCloud is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ThermFerm; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *****************************************************************************/ function createDelElements() { $('#eventWindow').jqxWindow({ theme: theme, position: { x: 430, y: 210 }, width: 420, height: 175, resizable: false, isModal: true, modalOpacity: 0.4, okButton: $('#delOk'), cancelButton: $('#delCancel'), initContent: function() { $('#delOk').jqxButton({ template: 'danger', width: '65px', theme: theme }); $('#delCancel').jqxButton({ template: 'success', width: '65px', theme: theme }); $('#delCancel').focus(); } }); $('#eventWindow').jqxWindow('hide'); } function createAddElements() { $('#addWindow').jqxWindow({ theme: theme, position: { x: 400, y: 210 }, width: 480, height: 180, resizable: false, isModal: true, modalOpacity: 0.4, okButton: $('#addOk'), cancelButton: $('#addCancel'), initContent: function() { $('#addOk').jqxButton({ template: 'success', width: '65px', theme: theme }); $('#addCancel').jqxButton({ template: 'primary', width: '65px', theme: theme }); $('#addCancel').focus(); } }); $('#addWindow').jqxWindow('hide'); } $(document).ready(function() { var dataRecord = {}, url = 'dbfermenters.php', source = { datatype: 'json', cache: false, datafields: [ { name: 'uuid', type: 'string' }, { name: 'alias', type: 'string' }, { name: 'product_code', map: 'product>code' }, { name: 'product_name', map: 'product>name' }, { name: 'air_address', map: 'air>address' }, { name: 'air_idx', map: 'air>idx', type: 'int' }, { name: 'beer_address', map: 'beer>address' }, { name: 'beer_address2', map: 'beer>address2' }, { name: 'beer_idx', map: 'beer>idx', type: 'int' }, { name: 'chiller_address', map: 'chiller>address' }, { name: 'chiller_idx', map: 'chiller>idx', type: 'int' }, { name: 'light_address', map: 'light>address' }, { name: 'light_state', map: 'light>state', type: 'int' }, { name: 'light_delay', map: 'light>delay', type: 'int' }, { name: 'light_idx', map: 'light>idx', type: 'int' }, { name: 'heater_address', map: 'heater>address' }, { name: 'heater_state', map: 'heater>state', type: 'int' }, { name: 'heater_delay', map: 'heater>delay', type: 'int' }, { name: 'heater_idx', map: 'heater>idx', type: 'int' }, { name: 'cooler_address', map: 'cooler>address' }, { name: 'cooler_state', map: 'cooler>state', type: 'int' }, { name: 'cooler_delay', map: 'cooler>delay', type: 'int' }, { name: 'cooler_idx', map: 'cooler>idx', type: 'int' }, { name: 'fan_address', map: 'fan>address' }, { name: 'fan_state', map: 'fan>state', type: 'int' }, { name: 'fan_delay', map: 'fan>delay', type: 'int' }, { name: 'fan_idx', map: 'fan>idx', type: 'int' }, { name: 'door_address', map: 'door>address' }, { name: 'door_idx', map: 'door>idx', type: 'int' }, { name: 'door_state', map: 'door>state', type: 'int' }, { name: 'psu_address', map: 'psu>address' }, { name: 'psu_idx', map: 'psu>idx', type: 'int' }, { name: 'psu_state', map: 'psu>state', type: 'int' }, { name: 'stage' }, { name: 'mode' }, { name: 'setpoint_low', map: 'setpoint>low', type: 'float' }, { name: 'setpoint_high', map: 'setpoint>high', type: 'float' }, { name: 'alarm', type: 'int' }, { name: 'pidc_p', map: 'pidc>P', type: 'float' }, { name: 'pidc_i', map: 'pidc>I', type: 'float' }, { name: 'pidc_d', map: 'pidc>D', type: 'float' }, { name: 'pidc_imax', map: 'pidc>imax', type: 'float' }, { name: 'pidc_idle', map: 'pidc>idle', type: 'float' }, { name: 'pidh_p', map: 'pidh>P', type: 'float' }, { name: 'pidh_i', map: 'pidh>I', type: 'float' }, { name: 'pidh_d', map: 'pidh>D', type: 'float' }, { name: 'pidh_imax', map: 'pidh>imax', type: 'float' }, { name: 'pidh_idle', map: 'pidh>idle', type: 'float' } ], id: 'uuid', url: url }, dataAdapter = new $.jqx.dataAdapter(source), editrow = -1; // initialize the input fields. $('#uuid').jqxInput({ theme: theme, width: 360, height: 23 }); $('#alias').jqxInput({ theme: theme, width: 120, height: 23 }); $('#product_code').jqxInput({ theme: theme, width: 120, height: 23 }); $('#product_name').jqxInput({ theme: theme, width: 360, height: 23 }); $('#mode').jqxInput({ theme: theme, width: 120, height: 23 }); $('#stage').jqxInput({ theme: theme, width: 120, height: 23 }); $('#air_address,#beer_address,#beer_address2,#chiller_address').jqxDropDownList({ theme: theme, source: tempsensorlist, valueMember: 'uuid', displayMember: 'name', width: 240, dropDownWidth: 480, autoDropDownHeight: true }); $('#air_address').on('select', function (event) { var args = event.args; if (args) { if ((args.index > 0) && (args.type != 'none')) { dataRecord.air_idx = 0; $('#air_idx').val(0); } } }); $('#beer_address').on('select', function (event) { var args = event.args; if (args) { if ((args.index > 0) && (args.type != 'none')) { dataRecord.beer_idx = 0; $('#beer_idx').val(0); } } }); $('#chiller_address').on('select', function (event) { var args = event.args; if (args) { if ((args.index > 0) && (args.type != 'none')) { dataRecord.chiller_idx = 0; $('#chiller_idx').val(0); } } }); $('#air_idx,#beer_idx,#chiller_idx,#heater_idx,#cooler_idx,#fan_idx,#light_idx,#door_idx,#psu_idx').jqxNumberInput(Spin0dec); $('#heater_address,#cooler_address,#fan_address,#light_address').jqxDropDownList({ theme: theme, source: switcheslist, valueMember: 'uuid', displayMember: 'name', width: 240, dropDownWidth: 480, autoDropDownHeight: true }); $('#heater_address').on('select', function (event) { var args = event.args; if (args) { if ((args.index > 0) && (args.type != 'none')) { dataRecord.heater_idx = dataRecord.heater_state = dataRecord.heater_delay = 0; $('#heater_idx').val(0); $('#heater_state').val(0); $('#heater_delay').val(0); } } }); $('#cooler_address').on('select', function (event) { var args = event.args; if (args) { if ((args.index > 0) && (args.type != 'none')) { dataRecord.cooler_idx = dataRecord.cooler_state = dataRecord.cooler_delay = 0; $('#cooler_idx').val(0); $('#cooler_state').val(0); $('#cooler_delay').val(0); } } }); $('#fan_address').on('select', function (event) { var args = event.args; if (args) { if ((args.index > 0) && (args.type != 'none')) { dataRecord.fan_idx = dataRecord.fan_state = dataRecord.fan_delay = 0; $('#fan_idx').val(0); $('#fan_state').val(0); $('#fan_delay').val(0); } } }); $('#light_address').on('select', function (event) { var args = event.args; if (args) { if ((args.index > 0) && (args.type != 'none')) { dataRecord.light_idx = dataRecord.light_state = dataRecord.light_delay = 0; $('#light_idx').val(0); $('#light_state').val(0); $('#light_delay').val(0); } } }); $('#heater_state,#cooler_state,#fan_state,#light_state').jqxNumberInput(Perc0); $('#heater_delay,#cooler_delay,#fan_delay,#light_delay').jqxNumberInput(Spin0dec); $('#pidh_p,#pidh_i,#pidh_d,#pidc_p,#pidc_i,#pidc_d').jqxNumberInput(Spin3dec); $('#pidh_imax,#pidc_imax').jqxNumberInput(Perc1dec); $('#pidh_idle,#pidc_idle').jqxNumberInput(Spin2dec); $('#door_address,#psu_address').jqxDropDownList({ theme: theme, source: contactslist, valueMember: 'uuid', displayMember: 'name', width: 240, dropDownWidth: 480, autoDropDownHeight: true }); $('#door_address').on('select', function (event) { var args = event.args; if (args) { if ((args.index > 0) && (args.type != 'none')) { dataRecord.door_idx = 0; $('#door_idx').val(0); } } }); $('#psu_address').on('select', function (event) { var args = event.args; if (args) { if ((args.index > 0) && (args.type != 'none')) { dataRecord.psu_idx = 0; $('#psu_idx').val(0); } } }); $('#door_state,#psu_state').jqxNumberInput(Show0dec); // initialize jqxGrid $('#jqxgrid').jqxGrid({ width: 1280, height: 630, source: dataAdapter, theme: theme, showstatusbar: true, renderstatusbar: function(statusbar) { var rowCount = $("#jqxgrid").jqxGrid('getrows').length; statusbar.append('<div style="float: left; margin: 8px; color: orange !important;">Total items: ' + rowCount + '</div>'); var container, addButton, impButton; container = $('<div style="overflow: hidden; position: relative; margin: 5px;"></div>'); addButton = $('<div style="float: right; margin-right: 15px;"><img style="position: relative; margin-top: 2px;" ' + 'src="images/add.png"/><span style="margin-left: 4px; position: relative; top: -4px;">New</span></div>'); container.append(addButton); statusbar.append(container); addButton.jqxButton({ theme: theme, width: 90, height: 17 }); // add new row. addButton.click(function(event) { $('#addWindow').jqxWindow('open'); $('#addOk').click(function() { var data, data = 'add=true&name=dummy' console.log(data); $.ajax({ dataType: 'json', url: url, cache: false, data: data, type: 'POST', success: function(data) { if (data.error) { console.log('add: ' + data.msg); alert('Error: ' + data.msg); } else { console.log('add: success'); } }, error: function(jqXHR, textStatus, errorThrown) {} }); $('#jqxgrid').jqxGrid('updatebounddata'); }); }); }, columns: [ { text: 'Unit', datafield: 'alias', width: 200 }, { text: 'Mode', datafield: 'mode', width: 120 }, { text: 'Code', datafield: 'product_code', width: 150 }, { text: 'Beer', datafield: 'product_name' }, { text: '', datafield: 'Edit', width: 100, align: 'center', columntype: 'button', cellsrenderer: function() { return 'Edit'; }, buttonclick: function(row) { // open the popup window when the user clicks a button. editrow = row; $('#popupWindow').jqxWindow({ position: { x: 40, y: 15 } }); dataRecord = $('#jqxgrid').jqxGrid('getrowdata', editrow); $('#uuid').val(dataRecord.uuid); $('#alias').val(dataRecord.alias); $('#product_code').val(dataRecord.product_code); $('#product_name').val(dataRecord.product_name); $('#air_address').val(dataRecord.air_address); $('#air_idx').val(dataRecord.air_idx); $('#beer_address').val(dataRecord.beer_address); $('#beer_address2').val(dataRecord.beer_address2); $('#beer_idx').val(dataRecord.beer_idx); $('#chiller_address').val(dataRecord.chiller_address); $('#chiller_idx').val(dataRecord.chiller_idx); $('#heater_address').val(dataRecord.heater_address); $('#heater_idx').val(dataRecord.heater_idx); $('#heater_state').val(dataRecord.heater_state); $('#heater_delay').val(dataRecord.heater_delay); $('#cooler_address').val(dataRecord.cooler_address); $('#cooler_idx').val(dataRecord.cooler_idx); $('#cooler_state').val(dataRecord.cooler_state); $('#cooler_delay').val(dataRecord.cooler_delay); $('#fan_address').val(dataRecord.fan_address); $('#fan_idx').val(dataRecord.fan_idx); $('#fan_state').val(dataRecord.fan_state); $('#fan_delay').val(dataRecord.fan_delay); $('#light_address').val(dataRecord.light_address); $('#light_idx').val(dataRecord.light_idx); $('#light_state').val(dataRecord.light_state); $('#light_delay').val(dataRecord.light_delay); $('#door_address').val(dataRecord.door_address); $('#door_idx').val(dataRecord.door_idx); $('#door_state').val(dataRecord.door_state); $('#psu_address').val(dataRecord.psu_address); $('#psu_idx').val(dataRecord.psu_idx); $('#psu_state').val(dataRecord.psu_state); $('#mode').val(dataRecord.mode); $('#stage').val(dataRecord.stage); $('#pidc_p').val(dataRecord.pidc_p); $('#pidc_i').val(dataRecord.pidc_i); $('#pidc_d').val(dataRecord.pidc_d); $('#pidc_imax').val(dataRecord.pidc_imax); $('#pidc_idle').val(dataRecord.pidc_idle); $('#pidh_p').val(dataRecord.pidh_p); $('#pidh_i').val(dataRecord.pidh_i); $('#pidh_d').val(dataRecord.pidh_d); $('#pidh_imax').val(dataRecord.pidh_imax); $('#pidh_idle').val(dataRecord.pidh_idle); // show the popup window. $('#popupWindow').jqxWindow('open'); } } ], }); // initialize the popup window and buttons. $('#popupWindow').jqxWindow({ width: 1280, height: 625, resizable: false, theme: theme, isModal: true, autoOpen: false, cancelButton: $('#Cancel'), modalOpacity: 0.40 }); $('#popupWindow').on('open', function() { // $('#dev_description').jqxInput('selectAll'); }); $('#Delete').jqxButton({ template: 'danger', width: '90px', theme: theme }); $('#Delete').click(function() { // Open a popup to confirm this action. $('#eventWindow').jqxWindow('open'); $('#delOk').click(function() { var data, data = 'del=true&uuid=' + $('#uuid').val(); $.ajax({ dataType: 'json', url: url, cache: false, data: data, type: 'POST', success: function(data) { if (data.error) { console.log('del: ' + data.msg); alert('Error: ' + data.msg); } else { console.log('del: success'); } }, error: function(jqXHR, textStatus, errorThrown) {} }); $('#jqxgrid').jqxGrid('updatebounddata'); }); $('#popupWindow').jqxWindow('hide'); }); $('#Cancel').jqxButton({ template: 'primary', width: '90px', theme: theme }); $('#Save').jqxButton({ template: 'success', width: '90px', theme: theme }); $('#Save').click(function() { var data, row = { uuid: dataRecord.uuid, alias: dataRecord.alias, mode: dataRecord.mode, stage: dataRecord.stage, pidh_p: parseFloat($('#pidh_p').jqxNumberInput('decimal')), pidh_i: parseFloat($('#pidh_i').jqxNumberInput('decimal')), pidh_d: parseFloat($('#pidh_d').jqxNumberInput('decimal')), pidh_imax: parseFloat($('#pidh_imax').jqxNumberInput('decimal')), pidh_idle: parseFloat($('#pidh_idle').jqxNumberInput('decimal')), pidc_p: parseFloat($('#pidc_p').jqxNumberInput('decimal')), pidc_i: parseFloat($('#pidc_i').jqxNumberInput('decimal')), pidc_d: parseFloat($('#pidc_d').jqxNumberInput('decimal')), pidc_imax: parseFloat($('#pidc_imax').jqxNumberInput('decimal')), pidc_idle: parseFloat($('#pidc_idle').jqxNumberInput('decimal')) }; data = 'update=true&' + $.param(row); if ($('#air_address').val() != '') { var row = { air_address: $('#air_address').val(), air_idx: parseInt($('#air_idx').jqxNumberInput('decimal')) }; data += '&' + $.param(row); } else { data += '&air_address='; } if ($('#beer_address').val() != '') { var row = { beer_address: $('#beer_address').val(), beer_address2: $('#beer_address2').val(), beer_idx: parseInt($('#beer_idx').jqxNumberInput('decimal')) }; data += '&' + $.param(row); } else { data += '&beer_address=&beer_address2='; } if ($('#chiller_address').val() != '') { var row = { chiller_address: $('#chiller_address').val(), chiller_idx: parseInt($('#chiller_idx').jqxNumberInput('decimal')) }; data += '&' + $.param(row); } else { data += '&chiller_address='; } if ($('#heater_address').val() != '') { var row = { heater_address: $('#heater_address').val(), heater_idx: parseInt($('#heater_idx').jqxNumberInput('decimal')), heater_state: parseInt($('#heater_state').jqxNumberInput('decimal')), heater_delay: parseInt($('#heater_delay').jqxNumberInput('decimal')) }; data += '&' + $.param(row); } else { data += '&heater_address='; } if ($('#cooler_address').val() != '') { var row = { cooler_address: $('#cooler_address').val(), cooler_idx: parseInt($('#cooler_idx').jqxNumberInput('decimal')), cooler_state: parseInt($('#cooler_state').jqxNumberInput('decimal')), cooler_delay: parseInt($('#cooler_delay').jqxNumberInput('decimal')) }; data += '&' + $.param(row); } else { data += '&cooler_address='; } if ($('#fan_address').val() != '') { var row = { fan_address: $('#fan_address').val(), fan_idx: parseInt($('#fan_idx').jqxNumberInput('decimal')), fan_state: parseInt($('#fan_state').jqxNumberInput('decimal')), fan_delay: parseInt($('#fan_delay').jqxNumberInput('decimal')) }; data += '&' + $.param(row); } else { data += '&fan_address='; } if ($('#light_address').val() != '') { var row = { light_address: $('#light_address').val(), light_idx: parseInt($('#light_idx').jqxNumberInput('decimal')), light_state: parseInt($('#light_state').jqxNumberInput('decimal')), light_delay: parseInt($('#light_delay').jqxNumberInput('decimal')) }; data += '&' + $.param(row); } else { data += '&light_address='; } if ($('#door_address').val() != '') { var row = { door_address: $('#door_address').val(), door_idx: parseInt($('#door_idx').jqxNumberInput('decimal')) }; data += '&' + $.param(row); } else { data += '&door_address='; } if ($('#psu_address').val() != '') { var row = { psu_address: $('#psu_address').val(), psu_idx: parseInt($('#psu_idx').jqxNumberInput('decimal')) }; data += '&' + $.param(row); } else { data += '&psu_address='; } console.log(data); $.ajax({ dataType: 'json', url: url, cache: false, data: data, type: 'POST', success: function(data) { if (data.error) { console.log('update: ' + data.msg); alert('Error: ' + data.msg); } else { console.log('update: success'); } }, error: function(jqXHR, textStatus, errorThrown) {} }); $('#popupWindow').jqxWindow('hide'); }); createDelElements(); createAddElements(); websocket.onmessage = function(evt) { var msg = evt.data; var obj = JSON.parse(msg); if (obj.ping) { websocket.send('{"pong":' + obj.ping + '}'); } if (obj.type == 'device') { // Use the message to trigger update. $('#jqxgrid').jqxGrid('updatebounddata'); } } });