# HG changeset patch # User Michiel Broek # Date 1590920581 -7200 # Node ID 367ae7ff52f0e1a6a1266fcb59a0a8455c02ab9d # Parent f4de55f587c1f316fa5ce8d6027237f1d76829d1 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. diff -r f4de55f587c1 -r 367ae7ff52f0 bmsd/websocket.c --- 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; } diff -r f4de55f587c1 -r 367ae7ff52f0 config.status --- 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" diff -r f4de55f587c1 -r 367ae7ff52f0 configure --- 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" diff -r f4de55f587c1 -r 367ae7ff52f0 configure.ac --- 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) diff -r f4de55f587c1 -r 367ae7ff52f0 www/includes/db_product.php --- 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']; diff -r f4de55f587c1 -r 367ae7ff52f0 www/js/global.js --- 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' }, diff -r f4de55f587c1 -r 367ae7ff52f0 www/js/prod_edit.js --- 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.
Gebruik die datum maar dan twee jaar eerder als productie datum.
Bij White Labs is de productie datum vier maanden voor de "Best by" datum die geprint op het buisje.
Bij Wyeast is dit de "manufacture date" die op het pak geprint is.
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(); }); diff -r f4de55f587c1 -r 367ae7ff52f0 www/prod_edit.php --- 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 @@
- - + +
Verwacht eind SG:
Verwacht FG en ABV:
@@ -315,10 +315,6 @@ - - - - @@ -331,6 +327,10 @@ + + + + @@ -1127,6 +1127,25 @@ +
+
Kies een voorgedefinieerde pitchrate.
+
+
Verwacht ABV %:
Gist productie datum:
Pitch rate:
Cellen nodig miljard:
+ + + + + + + + + +
Pitchrate in miljard cellen/ml/°P:
+ +
+
+ +