Sun, 31 May 2020 12:23:01 +0200
Version 0.3.34 Changed log messages in the daemon. Added yeast_pitchrate field to the product database. Added yeast pitchrate edit field to the yeast tab. Initial value is guessed. There is also a popup window for predefined values. An finally the value can be edited by the user. All popup windows are initialized together.
bmsd/websocket.c | file | annotate | diff | comparison | revisions | |
config.status | file | annotate | diff | comparison | revisions | |
configure | file | annotate | diff | comparison | revisions | |
configure.ac | file | annotate | diff | comparison | revisions | |
www/includes/db_product.php | file | annotate | diff | comparison | revisions | |
www/js/global.js | file | annotate | diff | comparison | revisions | |
www/js/prod_edit.js | file | annotate | diff | comparison | revisions | |
www/prod_edit.php | file | annotate | diff | comparison | revisions |
--- a/bmsd/websocket.c Fri May 29 09:17:52 2020 +0200 +++ b/bmsd/websocket.c Sun May 31 12:23:01 2020 +0200 @@ -77,14 +77,13 @@ case LWS_CALLBACK_ESTABLISHED: { ws_clients++; - syslog(LOG_NOTICE, "ws: new connection, total %d", ws_clients); pss->ringbuffer_tail = ringbuffer_head; pss->wsi = wsi; break; } case LWS_CALLBACK_PROTOCOL_DESTROY: - syslog(LOG_NOTICE, "ws: protocol cleaning up"); + syslog(LOG_NOTICE, "Websocket: protocol cleaning up"); for (n = 0; n < sizeof ringbuffer / sizeof ringbuffer[0]; n++) if (ringbuffer[n].payload) free(ringbuffer[n].payload); @@ -133,7 +132,6 @@ case LWS_CALLBACK_CLOSED: ws_clients--; - syslog(LOG_NOTICE, "ws: connection closed, left %d", ws_clients); break; default: @@ -222,8 +220,9 @@ if (context == NULL) { syslog(LOG_NOTICE, "libwebsocket_create_context() failed"); + return (void *)1; } - syslog(LOG_NOTICE, "Websocket server port %d started", info.port); + syslog(LOG_NOTICE, "Websocket: server started port %d", info.port); /* * Loop forever until external shutdown variable is set. @@ -234,8 +233,8 @@ } lws_context_destroy(context); - syslog(LOG_NOTICE, "Thread ws_loop stopped"); - return 0; + syslog(LOG_NOTICE, "Websocket: server stopped"); + return (void *)0; }
--- a/config.status Fri May 29 09:17:52 2020 +0200 +++ b/config.status Sun May 31 12:23:01 2020 +0200 @@ -621,7 +621,7 @@ S["CC"]="gcc" S["CYEARS"]="2016-2020" S["COPYRIGHT"]="Copyright (C) 2016-2020 Michiel Broek, All Rights Reserved" -S["VERSION"]="0.3.33" +S["VERSION"]="0.3.34" S["PACKAGE"]="bms" S["SUBDIRS"]="bmsd doc script tools www" S["target_alias"]="" @@ -710,7 +710,7 @@ D["PACKAGE_STRING"]=" \"\"" D["PACKAGE_BUGREPORT"]=" \"\"" D["PACKAGE_URL"]=" \"\"" -D["VERSION"]=" \"0.3.33\"" +D["VERSION"]=" \"0.3.34\"" D["COPYRIGHT"]=" \"Copyright (C) 2016-2020 Michiel Broek, All Rights Reserved\"" D["STDC_HEADERS"]=" 1" D["HAVE_SYS_TYPES_H"]=" 1"
--- a/configure Fri May 29 09:17:52 2020 +0200 +++ b/configure Sun May 31 12:23:01 2020 +0200 @@ -2043,7 +2043,7 @@ PACKAGE="bms" -VERSION="0.3.33" +VERSION="0.3.34" COPYRIGHT="Copyright (C) 2016-2020 Michiel Broek, All Rights Reserved" CYEARS="2016-2020"
--- a/configure.ac Fri May 29 09:17:52 2020 +0200 +++ b/configure.ac Sun May 31 12:23:01 2020 +0200 @@ -8,7 +8,7 @@ dnl General settings dnl After changeing the version number, run autoconf! PACKAGE="bms" -VERSION="0.3.33" +VERSION="0.3.34" COPYRIGHT="Copyright (C) 2016-2020 Michiel Broek, All Rights Reserved" CYEARS="2016-2020" AC_SUBST(PACKAGE)
--- a/www/includes/db_product.php Fri May 29 09:17:52 2020 +0200 +++ b/www/includes/db_product.php Sun May 31 12:23:01 2020 +0200 @@ -269,7 +269,8 @@ $sql .= "', yeast_prod_date=NULL"; else $sql .= "', yeast_prod_date='" . $_POST['yeast_prod_date'] . "'"; - $sql .= ", divide_type='" . $_POST['divide_type']; + $sql .= ", yeast_pitchrate='" . floatval($_POST['yeast_pitchrate']); + $sql .= "', divide_type='" . $_POST['divide_type']; $sql .= "', divide_size='" . floatval($_POST['divide_size']); $sql .= "', divide_factor='" . floatval($_POST['divide_factor']); $sql .= "', divide_parts='" . $_POST['divide_parts']; @@ -881,7 +882,8 @@ $brew .= ',"starter_sg":' . $row['starter_sg']; $brew .= ',"starter_viability":' . $row['starter_viability']; $brew .= ',"yeast_prod_date":"' . $row['yeast_prod_date']; - $brew .= '","prop1_type":' . $row['prop1_type']; + $brew .= '","yeast_pitchrate":' . $row['yeast_pitchrate']; + $brew .= ',"prop1_type":' . $row['prop1_type']; $brew .= ',"prop1_volume":' . $row['prop1_volume']; $brew .= ',"prop2_type":' . $row['prop2_type']; $brew .= ',"prop2_volume":' . $row['prop2_volume'];
--- a/www/js/global.js Fri May 29 09:17:52 2020 +0200 +++ b/www/js/global.js Sun May 31 12:23:01 2020 +0200 @@ -247,6 +247,22 @@ }, StarterTypeAdapter = new $.jqx.dataAdapter(StarterTypeSource), +PitchrateData = [ + { rate: 0, nl: ' - Kies factor - ' }, + { rate: 0.75, nl: 'Ale, 0.75' }, + { rate: 1.0, nl: 'Ale, 1.00 zwaar > 1.060' }, + { rate: 1.25, nl: 'Ale, 1.25 zwaar > 1.076' }, + { rate: 1.5, nl: 'Lager 1.50' }, + { rate: 2.0, nl: 'Lager, 2.00 zwaar > 1.060' }, + { rate: 0.075, nl: 'Kveik, 0.075 origineel' } +], +PitchrateSource = { + localdata: PitchrateData, + datatype: 'array', + datafields: [{ name: 'rate' }, { name: 'nl' }] +}, +PitchrateAdapter = new $.jqx.dataAdapter(PitchrateSource), + MiscTypeData = [ { id: 0, en: 'Spice', nl: 'Specerij' }, { id: 1, en: 'Herb', nl: 'Kruid' },
--- a/www/js/prod_edit.js Fri May 29 09:17:52 2020 +0200 +++ b/www/js/prod_edit.js Sun May 31 12:23:01 2020 +0200 @@ -21,7 +21,7 @@ *****************************************************************************/ -function createDelElements() { +function createPopupElements() { $('#eventWindow').jqxWindow({ theme: theme, @@ -40,7 +40,6 @@ $('#delCancel').focus(); } }); - $('#eventWindow').jqxWindow('hide'); $('#volumeWindow').jqxWindow({ theme: theme, @@ -53,7 +52,78 @@ autoOpen: false, cancelButton: $('#volumeReady') }); - $('#volumeWindow').jqxWindow('hide'); + + $('#pitchrateWindow').jqxWindow({ + theme: theme, + position: { x: 330, y: 210 }, + width: 600, + height: 200, + resizable: false, + isModal: true, + modalOpacity: 0.4, + autoOpen: false, + cancelButton: $('#pitchrateReady') + }); + + $('#popupFermentable').jqxWindow({ + width: 800, + height: 300, + position: { x: 230, y: 100 }, + resizable: false, + theme: theme, + isModal: true, + autoOpen: false, + cancelButton: $('#FermentableReady'), + modalOpacity: 0.40 + }); + + $('#popupHop').jqxWindow({ + width: 800, + height: 300, + position: { x: 230, y: 100 }, + resizable: false, + theme: theme, + isModal: true, + autoOpen: false, + cancelButton: $('#HopReady'), + modalOpacity: 0.40 + }); + + $('#popupMisc').jqxWindow({ + width: 800, + height: 275, + position: { x: 230, y: 100 }, + resizable: false, + theme: theme, + isModal: true, + autoOpen: false, + cancelButton: $('#MiscReady'), + modalOpacity: 0.40 + }); + + $('#popupYeast').jqxWindow({ + width: 800, + height: 300, + position: { x: 230, y: 100 }, + resizable: false, + theme: theme, + isModal: true, + autoOpen: false, + cancelButton: $('#YeastReady'), + modalOpacity: 0.40 + }); + + $('#popupMash').jqxWindow({ + width: 800, + height: 375, + position: { x: 230, y: 100 }, + resizable: false, + theme: theme, + isModal: true, + autoOpen: false, + cancelButton: $('#MashReady'), + modalOpacity: 0.40 + }); } @@ -69,7 +139,6 @@ pcara = 0, // Percentage cara/crystal malts svg = 77, // Default attenuation mashkg = 0, // Malt in mash weight - pitchrate = 0.75, // Yeast pitch rate default initcells = 0, // Initial yeast cell count ok_fermentables = 1, // Fermentables are in stock @@ -325,6 +394,7 @@ { name: 'starter_sg', type: 'float' }, { name: 'starter_viability', type: 'int' }, { name: 'yeast_prod_date', type: 'string' }, + { name: 'yeast_pitchrate', type: 'float' }, { name: 'prop1_type', type: 'int' }, { name: 'prop1_volume', type: 'float' }, { name: 'prop2_type', type: 'int' }, @@ -555,6 +625,7 @@ $('#starter_sg').val(dataRecord.starter_sg); $('#starter_viability').val(dataRecord.starter_viability); $('#yeast_prod_date').val(dataRecord.yeast_prod_date); + $('#yeast_pitchrate').val(dataRecord.yeast_pitchrate); $('#prop1_type').val(dataRecord.prop1_type); $('#prop1_volume').val(dataRecord.prop1_volume); $('#prop2_type').val(dataRecord.prop2_type); @@ -2195,7 +2266,7 @@ if (volume <= 0) volume = dataRecord.batch_size - dataRecord.eq_trub_chiller_loss; - return pitchrate * volume * plato; + return dataRecord.yeast_pitchrate * volume * plato; } function hopFlavourContribution(bt, vol, use, amount) { @@ -2568,6 +2639,7 @@ return; // no yeast in recipe var maybe_starter = 0; + var pitchrate = 0.75; // Yeast pitch rate default for (i = 0; i < rowscount; i++) { row = $('#yeastGrid').jqxGrid('getrowdata', i); if (row.y_use == 0) { // primary @@ -2584,6 +2656,10 @@ if (dataRecord.est_og > 1.060) pitchrate = 1.0; } + if (dataRecord.yeast_pitchrate < 0.01) { + dataRecord.yeast_pitchrate = pitchrate; + $('#yeast_pitchrate').val(pitchrate); + } if (row.y_form != 1) { // Not dry yeast maybe_starter = 1; @@ -2591,12 +2667,12 @@ } } - needed = Round(pitchrate * volume * plato, 1); + needed = Round(dataRecord.yeast_pitchrate * volume * plato, 1); $('#need_cells').val(needed); use_cells = initcells; if (needed <= initcells) maybe_starter = 0; - console.log('calcYeast() pitchrate:' + pitchrate + ' start:' + initcells + ' needed:' + needed + ' volume:' + volume + ' maybe_starter:' + maybe_starter); + console.log('calcYeast() pitchrate:' + dataRecord.yeast_pitchrate + ' start:' + initcells + ' needed:' + needed + ' volume:' + volume + ' maybe_starter:' + maybe_starter); if (maybe_starter != dataRecord.starter_enable) { dataRecord.starter_enable = maybe_starter; @@ -3731,6 +3807,8 @@ $('#starter_try').jqxButton({ disabled: true }); $('#starter_sg').jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 }); $('#yeast_prod_date').jqxDateTimeInput({ disabled: true }); + $('#yeast_pitchrate').jqxNumberInput({ spinButtons: false, readOnly: true, width: 90 }); + $('#but_pickpitchrate').jqxButton({ disabled: true }); } if (dataRecord.stage > 3) { // Primary fermentation done $('#brew_date_start').jqxDateTimeInput({ disabled: true }); @@ -4620,6 +4698,7 @@ starter_sg: parseFloat($('#starter_sg').jqxNumberInput('decimal')), starter_viability: parseFloat($('#starter_viability').jqxNumberInput('decimal')), yeast_prod_date: $('#yeast_prod_date').val(), + yeast_pitchrate: parseFloat($('#yeast_pitchrate').jqxNumberInput('decimal')), prop1_type: $('#prop1_type').val(), prop1_volume: parseFloat($('#prop1_volume').jqxNumberInput('decimal')), prop2_type: $('#prop2_type').val(), @@ -4818,17 +4897,6 @@ colorRanges: [{ stop: 30, color: '#FF0000' },{ stop: 40, color: '#EB7331' },{ stop: 200, color: '#008C00' }], renderText: function(text) { return (parseInt(text) * 2) + ' lintner'; } }); - $('#popupFermentable').jqxWindow({ - width: 800, - height: 300, - position: { x: 230, y: 100 }, - resizable: false, - theme: theme, - isModal: true, - autoOpen: false, - cancelButton: $('#FermentableReady'), - modalOpacity: 0.40 - }); $('#FermentableReady').jqxButton({ template: 'success', width: '90px', theme: theme }); $('#FermentableReady').click(function() { var row, rowID = $('#fermentableGrid').jqxGrid('getrowid', fermentableRow); @@ -5084,17 +5152,6 @@ return 'Zeer veel'; } }); - $('#popupHop').jqxWindow({ - width: 800, - height: 300, - position: { x: 230, y: 100 }, - resizable: false, - theme: theme, - isModal: true, - autoOpen: false, - cancelButton: $('#HopReady'), - modalOpacity: 0.40 - }); $('#HopReady').jqxButton({ template: 'success', width: '90px', theme: theme }); $('#HopReady').click(function() { var row, rowID = $('#hopGrid').jqxGrid('getrowid', hopRow); @@ -5233,17 +5290,6 @@ }); // Tab 5, Miscs - $('#popupMisc').jqxWindow({ - width: 800, - height: 275, - position: { x: 230, y: 100 }, - resizable: false, - theme: theme, - isModal: true, - autoOpen: false, - cancelButton: $('#MiscReady'), - modalOpacity: 0.40 - }); $('#MiscReady').jqxButton({ template: 'success', width: '90px', theme: theme }); $('#MiscReady').click(function() { var row, rowID = $('#miscGrid').jqxGrid('getrowid', miscRow); @@ -5345,9 +5391,12 @@ $('#need_cells').jqxTooltip({ content: 'Het aantal miljard nodige cellen is afhankelijk van het begin SG, biertype en volume.' }); $('#plato_cells').jqxTooltip({ content: 'De berekende pitchrate in miljard cellen per ml per graad Plato.' }); $('#yeast_prod_date').jqxTooltip({ content: 'Bij korrelgisten is meestal "best voor" datum op het zakje gedrukt.<br>Gebruik die datum maar dan twee jaar eerder als productie datum.<br>Bij White Labs is de productie datum vier maanden voor de "Best by" datum die geprint op het buisje.<br>Bij Wyeast is dit de "manufacture date" die op het pak geprint is.<br>Voor schuine buis, slurry, opkweek en gedroogd is dit de datum dat je de gist geoogst hebt.' }); + $('#yeast_pitchrate').jqxTooltip({ content: 'De gewenste pitchrate in miljard cellen per ml per graad Plato voor de vergisting van dit bier.' }); $('#est_fg2,#plato_cells').jqxNumberInput(Show3dec); + $('#est_fg2').jqxNumberInput({ width: 70 }); $('#est_abv2').jqxNumberInput(Show2dec); + $('#est_abv2').jqxNumberInput({ width: 70, symbol: '%', symbolPosition: 'right' }); $('#yeast_cells,#need_cells').jqxNumberInput(Show1dec); $('#yeast_prod_date').jqxDateTimeInput(Dateopts); $('#yeast_prod_date').on('close', function(event) { @@ -5355,16 +5404,37 @@ calcFermentables(); calcYeast(); }); - $('#popupYeast').jqxWindow({ - width: 800, - height: 300, - position: { x: 230, y: 100 }, - resizable: false, + $('#yeast_pitchrate').jqxNumberInput(Spin3dec); + $('#yeast_pitchrate').on('change', function(event) { + dataRecord.yeast_pitchrate = parseFloat(event.args.value); + calcViability(); + calcFermentables(); + calcYeast(); + }); + $('#but_pickpitchrate').jqxButton({ template: 'success', width: '23px', height: 23, theme: theme }); + $('#but_pickpitchrate').bind('click', function() { + $('#pick_pitchrate').val(0); // Set default pick incase no perfect match. + $('#pick_pitchrate').val(dataRecord.yeast_pitchrate); + $('#pitchrateWindow').jqxWindow('open'); + }); + $('#pick_pitchrate').jqxDropDownList({ theme: theme, - isModal: true, - autoOpen: false, - cancelButton: $('#YeastReady'), - modalOpacity: 0.40 + source: PitchrateAdapter, + valueMember: 'rate', + displayMember: 'nl', + width: 275, + height: 23, + autoDropDownHeight: true, + dropDownVerticalAlignment: 'top' + }); + $('#pitchrateReady').jqxButton({ template: 'success', width: '90px', theme: theme }); + $('#pitchrateReady').click(function() { + console.log('pitchrateReady ' + $('#pick_pitchrate').val() ); + dataRecord.yeast_pitchrate = parseFloat($('#pick_pitchrate').val()); + $('#yeast_pitchrate').val(dataRecord.yeast_pitchrate); + calcViability(); + calcFermentables(); + calcYeast(); }); $('#YeastReady').jqxButton({ template: 'success', width: '90px', theme: theme }); $('#YeastReady').click(function() { @@ -5587,17 +5657,6 @@ $('#est_mashvol').jqxNumberInput(Show1dec); $('#est_mashtime').jqxTooltip({ content: 'De totale tijdsduur van het maischen.' }); $('#est_mashtime').jqxInput({ theme: theme, width: 70, height: 23 }); - $('#popupMash').jqxWindow({ - width: 800, - height: 375, - position: { x: 230, y: 100 }, - resizable: false, - theme: theme, - isModal: true, - autoOpen: false, - cancelButton: $('#MashReady'), - modalOpacity: 0.40 - }); $('#MashReady').jqxButton({ template: 'success', width: '90px', theme: theme }); $('#MashReady').click(function() { calcFermentables(); @@ -6289,6 +6348,6 @@ $('#Save').bind('click', function() { saveRecord(1); }); - createDelElements(); + createPopupElements(); });
--- a/www/prod_edit.php Fri May 29 09:17:52 2020 +0200 +++ b/www/prod_edit.php Sun May 31 12:23:01 2020 +0200 @@ -259,8 +259,8 @@ <div style="overflow: hidden;"> <table style="width: 100%;"> <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Verwacht eind SG:</td> - <td style="padding: 3px;"><div id="est_fg2"></div></td> + <td style="vertical-align: top; float: right; padding: 3px;">Verwacht FG en ABV:</td> + <td style="padding: 3px;"><div style="float: left;" id="est_fg2"></div><div style="float: left; margin-left: 10px;" id="est_abv2"></div></td> <td align="center" colspan="5" rowspan="5"> <div id="propagator"> <table style="width: 100%;"> @@ -315,10 +315,6 @@ </td> </tr> <tr> - <td style="vertical-align: top; float: right; padding: 3px;">Verwacht ABV %:</td> - <td style="padding: 3px;"><div id="est_abv2"></div></td> - </tr> - <tr> <td style="vertical-align: top; float: right; padding: 3px;">Gist productie datum:</td> <td style="padding: 3px;"><div id="yeast_prod_date"></div></td> </tr> @@ -331,6 +327,10 @@ <td style="padding: 3px;"><div id="yeast_cells"></div></td> </tr> <tr> + <td style="vertical-align: top; float: right; padding: 3px;">Pitch rate:</td> + <td style="padding: 3px;"><div style="float: left;" id="yeast_pitchrate"></div><input type="button" id="but_pickpitchrate" value="?" style="margin-left: 10px" /></td> + </tr> + <tr> <td style="vertical-align: top; float: right; padding: 3px;">Cellen nodig miljard:</td> <td style="padding: 3px;"><div id="need_cells"></div></td> </tr> @@ -1127,6 +1127,25 @@ </div> </div> + <div id="pitchrateWindow"> + <div>Kies een voorgedefinieerde pitchrate.</div> + <div style="overflow: hidden;"> + <table style="width: 100%; padding-top: 20px;"> + <col width="50%"> + <col width="50%"> + <tr> + <td align="right" style="vertical-align: top;">Pitchrate in miljard cellen/ml/°P:</td> + <td style="padding: 3px;"><div id="pick_pitchrate" /></div></td> + </tr> + <tr> + <td style="padding-top: 50px;" colspan="2" align="center"> + <input id="pitchrateReady" type="button" value="Ok" /> + </td> + </tr> + </table> + </div> + </div> + <?php confirm_delete(); page_footer();