In bmsd added missing json percent. The Makefile didn't install the fpdf library. Added profile commands. Small changes to the monitor fermenters screen. The monitor fermenters scheduler is now more responsive. Profiles selection and commands in the remote thermferm.

Sat, 19 Jan 2019 12:05:37 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 19 Jan 2019 12:05:37 +0100
changeset 189
6470e5c6a001
parent 188
0ef62ec2d5b0
child 190
77bbfdaa22e9

In bmsd added missing json percent. The Makefile didn't install the fpdf library. Added profile commands. Small changes to the monitor fermenters screen. The monitor fermenters scheduler is now more responsive. Profiles selection and commands in the remote thermferm.

.hgignore file | annotate | diff | comparison | revisions
bmsd/fermenters.c file | annotate | diff | comparison | revisions
www/Makefile file | annotate | diff | comparison | revisions
www/cmd_fermenter.php file | annotate | diff | comparison | revisions
www/css/style.css file | annotate | diff | comparison | revisions
www/includes/db_profile_fermentation.php file | annotate | diff | comparison | revisions
www/js/mon_fermenter.js file | annotate | diff | comparison | revisions
www/js/profile_fermentation.js file | annotate | diff | comparison | revisions
www/mon_fermenter.php file | annotate | diff | comparison | revisions
--- a/.hgignore	Sat Jan 12 20:18:54 2019 +0100
+++ b/.hgignore	Sat Jan 19 12:05:37 2019 +0100
@@ -9,6 +9,7 @@
 doc/bms.pdf
 www/version.php
 www/config.php
+www/thermferm
 www/run/sequence
 
 syntax: glob
--- a/bmsd/fermenters.c	Sat Jan 12 20:18:54 2019 +0100
+++ b/bmsd/fermenters.c	Sat Jan 19 12:05:37 2019 +0100
@@ -3,7 +3,7 @@
  * @brief Handle fermenters status
  * @author Michiel Broek <mbroek at mbse dot eu>
  *
- * Copyright (C) 2018
+ * Copyright (C) 2018-2019
  *
  * This file is part of the bms (Brewery Management System)
  *
@@ -271,6 +271,9 @@
 		    free(fermenter->profile_state);
 		fermenter->profile_state = xstrcpy((char *)json_object_get_string(val));
 	    }
+	    if (json_object_object_get_ex(sensor, "percent", &val)) {
+		fermenter->profile_percent = json_object_get_int(val);
+	    }
 	    if (json_object_object_get_ex(sensor, "inittemp", &temp)) {
 		if (json_object_object_get_ex(temp, "low", &val)) {
 		    fermenter->profile_inittemp_low = json_object_get_double(val);
--- a/www/Makefile	Sat Jan 12 20:18:54 2019 +0100
+++ b/www/Makefile	Sat Jan 19 12:05:37 2019 +0100
@@ -30,7 +30,8 @@
 		rm -f version.php
 
 install:
-		${INSTALL} -d -g 314 -o 314 ${PREFIX} ${WWWDIR} ${WWWDIR}/css \
+		${INSTALL} -d -g 314 -o 314 ${PREFIX} ${WWWDIR} ${WWWDIR}/css ${WWWDIR}/fpdf \
+			${WWWDIR}/fpdf/font \
 			${WWWDIR}/jqwidgets ${WWWDIR}/js ${WWWDIR}/images/ ${WWWDIR}/includes/
 		${INSTALL} -d -g 314 -o 314 -m 0777 ${WWWDIR}/run
 		${INSTALL} -g 314 -o 314 ${SRC} ${WWWDIR}/
@@ -40,6 +41,8 @@
 		${INSTALL} -g 314 -o 314 includes/* ${WWWDIR}/includes/
 		cp -r jqwidgets/* ${WWWDIR}/jqwidgets/
 		chown -R 314:314 ${WWWDIR}/jqwidgets
+		cp -r fpdf/* ${WWWDIR}/fpdf/
+		chown -R 314:314 ${WWWDIR}/fpdf
 		${INSTALL} -g 314 -o 314 js/* ${WWWDIR}/js/
 
 filelist:	Makefile
--- a/www/cmd_fermenter.php	Sat Jan 12 20:18:54 2019 +0100
+++ b/www/cmd_fermenter.php	Sat Jan 19 12:05:37 2019 +0100
@@ -44,6 +44,7 @@
  *           {"profile":{"uuid":"...","name":"profielnaam","inittemp":{"low":18.2,"high":20.5},"fridgemode":0,
  *              "steps":[{"resttime":12,"steptime":36,"target":{"low":20.8,"high":23.1},"fridgemode":0},
  *              	 {"resttime":48,"steptime":48,"target":{"low":27.5,"high":28.0},"fridgemode":0}]}}
+ *           {"profile":{"command":"start/stop/pause/abort"}
  */
 $topic = "mbv1.0/fermenters/DCMD/" . $node . "/" . $alias;
 $payload = '\'{"timestamp":' . time() . ',"seq":' . $nr . ',"metric":' . $payload . '}\'';
--- a/www/css/style.css	Sat Jan 12 20:18:54 2019 +0100
+++ b/www/css/style.css	Sat Jan 19 12:05:37 2019 +0100
@@ -53,7 +53,7 @@
 
 #fermenter_table {
     width: 960px;
-    height: 200px;
+    height: 210px;
     background: #252526;
     margin: 5px;
     border: 2px solid;
@@ -96,6 +96,7 @@
     float: left;
     background-color: #252526;
     margin: 5px;
+    margin-top: 3px;
     border: 2px solid;
     border-color: #59b4d4;
     border-radius: 5px 5px 5px 5px;
@@ -125,7 +126,7 @@
  */
 #fermenter_panel_top {
   width: 290px;
-  height: 200px;
+  height: 100px;
   float: right;
   margin: 5px;
   background-color: #252526;
@@ -142,25 +143,25 @@
   height: 30px;
   float: left;
   text-align: center;
-  margin-top: 10px;
+  margin-top: 15px;
   margin-left: 20px;
 }
 
 
 #fermenter_panel_display {
   width: 290px;
-  height: 70px;
+  height:  98px;
   float: right;
   margin: 5px;
+  margin-top: 3px;
   background-color: #252526;
   border: 2px solid;
   border-color: #59b4d4;
   border-radius: 5px 5px 5px 5px;
-  margin-bottom: 3px;
 }
 #fermenter_display {
   width: 145px;
-  height: 70px;
+  height: 98px;
   float: left;
   text-align: center;
 }
@@ -168,14 +169,14 @@
 
 #fermenter_panel_control {
   width: 290px;
-  height: 140px;
+  height: 150px;
   float: right;
   margin: 5px;
+  margin-top: 3px;
   background-color: #252526;
   border: 2px solid;
   border-color: #59b4d4;
   border-radius: 5px 5px 5px 5px;
-  margin-bottom: 3px;
 }
 
 #fermenter_led1,
@@ -185,7 +186,7 @@
   height: 30px;
   float: left;
   text-align: center;
-  margin-top: 8px;
+  margin-top: 13px;
 }
 
 #fermenter_toggle1 {
@@ -204,9 +205,10 @@
 
 #fermenter_panel_buttons {
   width: 290px;
-  height: 155px;
+  height: 227px;
   float: right;
   margin: 5px;
+  margin-top: 3px;
   background-color: #252526;
   border: 2px solid;
   border-color: #59b4d4;
--- a/www/includes/db_profile_fermentation.php	Sat Jan 12 20:18:54 2019 +0100
+++ b/www/includes/db_profile_fermentation.php	Sat Jan 19 12:05:37 2019 +0100
@@ -26,11 +26,9 @@
 
 	if (isset($_GET['uuid']) && (strlen($_GET['uuid']) == 36)) {
 		$sql .= "uuid='" . $_GET['uuid'];
-//		syslog(LOG_NOTICE, 'Keep uuid ');
 	} else {
 		$uuid = str_replace("\n", "", file_get_contents('/proc/sys/kernel/random/uuid'));
 		$sql .= "uuid='" . $uuid;
-//		syslog(LOG_NOTICE, 'New uuid ');
 	}
 
 	$sql .= "', name='" . mysqli_real_escape_string($connect, $_GET['name']);
@@ -107,7 +105,7 @@
 		$profiles .= '}';
 	}
 	$profiles .= ']';
-//	syslog(LOG_NOTICE, $profiles);
+	syslog(LOG_NOTICE, $profiles);
 	header("Content-type: application/json");
 	echo $profiles;
 }
--- a/www/js/mon_fermenter.js	Sat Jan 12 20:18:54 2019 +0100
+++ b/www/js/mon_fermenter.js	Sat Jan 19 12:05:37 2019 +0100
@@ -25,10 +25,12 @@
 
 	var	record = {};
 	var	blank = {};
+	var	ppayload = '';
 	var	newBase = false;
 	var	newProduct = false;
 	var	newSwitch = false;
 	var	newProfile = false;
+	var	schedule = 0;
 	var	yl = 12;	// Normal yeast temp range
 	var	yh = 24;
 
@@ -53,8 +55,7 @@
 			data.push(blank);
 			for (var i = 0; i < records.length; i++) {
 				var row = records[i];
-				if (row.inventory || ! fermentableinstock)
-					data.push(row);
+				data.push(row);
 			}
 			return data;
 		},
@@ -68,7 +69,7 @@
 		source: productlist,
 		displayMember: "code",
 		width: 150,
-		height: 23,
+		height: 24,
 		dropDownWidth: 500,
 		autoDropDownHeight: true,
 		renderer: function (index, label, value) {
@@ -77,6 +78,59 @@
 		}
 	});
 
+	var profileSource = {
+		datatype: "json",
+		cache: false,
+		datafields: [
+			{ name: 'record', type: 'int' },
+			{ name: 'uuid', type: 'string' },
+			{ name: 'name', type: 'string' },
+			{ name: 'inittemp_lo', type: 'float' },
+			{ name: 'inittemp_hi', type: 'float' },
+			{ name: 'fridgemode', type: 'int' },
+			{ name: 'totalsteps', type: 'int' },
+			{ name: 'duration', type: 'int' },
+			{ name: 'steps', type: 'array' }
+		],
+		id: 'record',
+		url: "includes/db_profile_fermentation.php"
+	};
+	var profilelist = new $.jqx.dataAdapter(profileSource, {
+		beforeLoadComplete: function (records) {
+			var data = new Array();
+			var empty = {};
+			// Create a dummy beer on top to store in idle fermenters.
+			empty['record'] = -1;
+			empty['uuid'] = '';
+			empty['name'] = 'Wis profiel';
+			empty['inittemp_lo'] = 20;
+			empty['inittemp_hi'] = 20;
+			empty['fridgemode'] = 0;
+			empty['totalsteps'] = 0;
+			empty['duration'] = 0;
+			empty['steps'] = '[]';
+			data.push(empty);
+			for (var i = 0; i < records.length; i++) {
+				var row = records[i];
+				data.push(row);
+			}
+			return data;
+		},
+		loadError: function(jqXHR, status, error) {
+			$('#err').text(status + ' ' + error);
+		},
+	});
+	$("#select_profile").jqxDropDownList({
+		placeHolder: "Kies profiel:",
+		theme: theme,
+		source: profilelist,
+		displayMember: "name",
+		width: 150,
+		height: 24,
+		dropDownWidth: 500,
+		autoDropDownHeight: true,
+	});
+
 	var gaugeoptions = {
 		min: 0, max: 40, width: 375, height: 375,
 		ranges: [{ startValue:  0, endValue: yl, style: { fill: '#3399FF', stroke: '#3399FF' }, endWidth: 10, startWidth: 10 },
@@ -123,15 +177,14 @@
 
 	srcMode = [ "OFF", "NONE", "FRIDGE", "BEER", "PROFILE" ];
 	srcStage = [ "PRIMARY", "SECONDARY", "TERTIARY", "CARBONATION" ];
-	$("#info_mode").jqxDropDownList({ theme: theme, source: srcMode, width: 100, height: 23, dropDownHeight: 156 });
-	$("#info_stage").jqxDropDownList({ theme: theme, source: srcStage, width: 150, height: 23, dropDownHeight: 125 });
+	$("#info_mode").jqxDropDownList({  theme: theme, source: srcMode, width: 100, height: 24, dropDownHeight: 156 });
+	$("#info_stage").jqxDropDownList({ theme: theme, source: srcStage, width: 150, height: 24, dropDownHeight: 125 });
 
 	var targetoptions = {
 		inputMode: 'simple',
 		spinMode: 'simple',
 		theme: theme,
 		width: 70,
-		height: 23,
 		min:0, max: 40,
 		decimalDigits: 1,
 		spinButtons: true,
@@ -140,6 +193,11 @@
 	$("#target_lo").jqxNumberInput( targetoptions );
 	$("#target_hi").jqxNumberInput( targetoptions );
 
+	$("#Profile1").jqxButton({ template: "info", width: '150px', height: 24, theme: theme });
+	$("#Profile2").jqxButton({ template: "info", width: '150px', height: 24, theme: theme });
+	$("#Profile1").hide();	// Hide these until they are needed.
+	$("#Profile2").hide();
+
 	function sendBase(stage, mode, tlo, thi) {
 
 		console.log("sendBase("+stage+", "+mode+", "+tlo+", "+thi+")");
@@ -194,6 +252,23 @@
 		});
 	}
 
+	function sendProfile(payload) {
+
+		console.log("sendProfile("+payload+")");
+		var data  = 'node='+record.node+'&alias='+record.alias+'&payload='+payload;
+		$.ajax({
+			url: "cmd_fermenter.php",
+			data: data,
+			type: "POST",
+			success: function(data) {
+				//do something after something is received from php
+			},
+			error: function(jqXHR, textStatus, errorThrown) {
+				console.log("sendBase() error");
+			}
+		});
+	}
+
     	var url = "getfermenter.php?uuid='" + my_uuid + "'";
     	var source = {
 		datatype: "json",
@@ -217,9 +292,12 @@
 			{ name: 'cooler_usage', type: 'int' },
 			{ name: 'fan_state', type: 'int' },
 			{ name: 'fan_usage', type: 'int' },
+			{ name: 'light_address', type: 'string' },
 			{ name: 'light_state', type: 'int' },
 			{ name: 'light_usage', type: 'int' },
+			{ name: 'door_address', type: 'string' },
 			{ name: 'door_state', type: 'int' },
+			{ name: 'psu_address', type: 'string' },
 			{ name: 'psu_state', type: 'int' },
 			{ name: 'mode', type: 'string' },
 			{ name: 'alarm', type: 'int' },
@@ -228,7 +306,7 @@
 			{ name: 'profile_uuid', type: 'string' },
 			{ name: 'profile_name', type: 'string' },
 			{ name: 'profile_state', type: 'string' },
-			{ name: 'profile_precent', type: 'int' },
+			{ name: 'profile_percent', type: 'int' },
 			{ name: 'profile_inittemp_high', type: 'float' },
 			{ name: 'profile_inittemp_low', type: 'float' },
 			{ name: 'profile_steps', type: 'string' },
@@ -243,7 +321,8 @@
 			record = dataAdapter.records[0];
 			var oline = (record.online) ? "On-line" : "Off-line";
 			$("#info_uuid").html(record.uuid);
-			$("#info_system").html(record.node +  "/" + record.alias + " " + oline);
+			$("#info_system").html(record.node +  "/" + record.alias);
+			$("#info_online").html(oline);
 			$("#info_beer").html(record.beercode + " - " + record.beername);
 			$("#info_mode").jqxDropDownList('selectItem', record.mode);
 			$("#info_stage").jqxDropDownList('selectItem', record.stage);
@@ -264,12 +343,12 @@
 				$("#target_hi").jqxNumberInput({ readOnly: true, Width: 50, spinButtons: false });
 			}
 
-			if (record.online && (record.door_state != "0")) {
+			if (record.online && record.door_address && (record.door_state == "0")) {
 				$("#fermenter_doorled").html('<div class="LEDyellow_on"></div>Door');
 			} else {
 				$("#fermenter_doorled").html('<div class="LEDyellow_off"></div>Door');
 			}
-			if (record.online && (record.light_state != "0")) {
+			if (record.online && record.light_address && (record.light_state != "0")) {
 				$("#fermenter_lightled").html('<div class="LEDyellow_on"></div>Light');
 			} else {
 				$("#fermenter_lightled").html('<div class="LEDyellow_off"></div>Light');
@@ -279,8 +358,10 @@
 				$("#fermenter_powerled").html('<div class="LEDblue_on"></div>Power');
 				$("#select_beer").jqxDropDownList({ disabled: true });
 				$("#select_beer").jqxDropDownList('clearSelection');
+				$("#select_beer").hide();
 			} else {
 				$("#fermenter_powerled").html('<div class="LEDblue_off"></div>Power');
+				$("#select_beer").show();
 				$("#select_beer").jqxDropDownList({ disabled: false });
 			}
 			if (record.online && (record.alarm != "0")) {
@@ -317,6 +398,51 @@
 				$("#fermenter_toggle3").val( (record.fan_state != "0") );
 			}
 
+			if (record.online && (record.mode == "PROFILE")) {
+				if (record.profile_state == "OFF") {
+					$("#select_profile").show();
+					$("#select_profile").jqxDropDownList({ disabled: false });
+					$("#info_mode").jqxDropDownList({ disabled: false });
+					$('#Profile1').jqxButton({ template: "success", value: "Starten" });
+					$("#Profile1").show();
+					$("#Profile2").hide();
+					$("#status_profile").html('');
+				} else if (record.profile_state == "RUN") {
+					$("#select_profile").jqxDropDownList({ disabled: true });
+					$("#select_profile").hide();
+					$("#info_mode").jqxDropDownList({ disabled: true });
+					$('#Profile1').jqxButton({ template: "danger", value: "Afbreken" });
+					$('#Profile2').jqxButton({ template: "primary", value: "Pauze" });
+					$("#Profile1").show();
+					$("#Profile2").show();
+					$("#status_profile").html('Profiel actief, '+record.profile_percent+'% gereed');
+				} else if (record.profile_state == "PAUSE") {
+					$("#select_profile").jqxDropDownList({ disabled: true });
+					$("#select_profile").hide();
+					$("#info_mode").jqxDropDownList({ disabled: true });
+					$('#Profile1').jqxButton({ template: "danger", value: "Afbreken" });
+					$('#Profile2').jqxButton({ template: "success", value: "Doorgaan" });
+					$("#Profile1").show();
+					$("#Profile2").show();
+					$("#status_profile").html('Profiel pauze, '+record.profile_percent+'% gereed');
+				} else if (record.profile_state == "DONE") {
+					$("#select_profile").jqxDropDownList({ disabled: true });
+					$("#select_profile").hide();
+					$("#info_mode").jqxDropDownList({ disabled: true });
+					$('#Profile1').jqxButton({ template: "primary", value: "Profiel Ok" });
+					$("#Profile1").show();
+					$("#Profile2").hide();
+					$("#status_profile").html('Profiel is gereed');
+				}
+			} else {
+				$("#select_profile").show();
+				$("#select_profile").jqxDropDownList({ disabled: false });
+				$("#info_mode").jqxDropDownList({ disabled: false });
+				$("#Profile1").hide();
+				$("#Profile2").hide();
+				$("#status_profile").html('');
+			}
+
 			$("#gaugeContainer_air").jqxGauge( { caption: { value: 'Air: '+record.air_temperature.toFixed(3) }});
 			$('#gaugeContainer_air').jqxGauge({ value: record.air_temperature });
 			if (record.online && (record.air_state == "OK")) {
@@ -359,12 +485,23 @@
 			newProduct = false;
 			skip = true;
 		}
+		if (newProfile) {
+			sendProfile(ppayload);
+			newProfile = false;
+			skip = true;
+		}
+		if (skip) {
+			schedule = 4;	// 2 seconds wait to get the results
+		} else {
+			if (schedule > 0)
+				schedule--;
+		}
 
-		if (! skip) {
-			// Only if we didn't send a command so that a command can be processed.
+		if (schedule <= 0) {
 			dataAdapter.dataBind();
+			schedule = 20;
 		}
-	}, 10000);
+	}, 500);
 
 	$('#info_mode').on('change', function (event) {
 		record.mode = args.item.value;
@@ -386,6 +523,29 @@
 			newProduct = true;
 		}
 	});
+	$("#select_profile").on('select', function (event) {
+		if (event.args) {
+			var index = event.args.index;
+			var datarecord = profilelist.records[index];
+			if (datarecord.record == -1) {
+				ppayload  = '{"profile":null}';
+			} else {
+				ppayload  = '{"profile":{"uuid":"'+datarecord.uuid+'","name":"'+datarecord.name+'",';
+				ppayload += '"inittemp":{"low":'+datarecord.inittemp_lo+',"high":'+datarecord.inittemp_hi+'},';
+				ppayload += '"fridgemode":'+datarecord.fridgemode+',"steps":[';
+				for (var i = 0; i < datarecord.steps.length; i++) {
+					var row = datarecord.steps[i];
+					if (i > 0)
+						ppayload += ',';
+					ppayload += '{"steptime":'+row['steptime']+',"resttime":'+row['resttime'];
+					ppayload += ',"target_lo":'+row['target_lo']+',"target_hi":'+row['target_hi'];
+					ppayload += ',"fridgemode":'+row['fridgemode']+',"name":"'+row['name']+'"}';
+				}
+				ppayload += ']}}';
+			}
+			newProfile = true;
+		}
+	});
 
 	$('#target_lo').on('change', function (event) {
 		record.setpoint_low = parseFloat(event.args.value);
@@ -446,10 +606,31 @@
 			newSwitch = true;
 		}
 	});
-
+	$("#Profile1").click(function () {
+		if (record.mode == "PROFILE") {
+			if (record.profile_state == "OFF") {
+				ppayload  = '{"profile":{"command":"start"}}';
+				newProfile = true;
+			} else if ((record.profile_state == "RUN") || (record.profile_state == "PAUSE")) {
+				ppayload  = '{"profile":{"command":"abort"}}';
+				newProfile = true;
+			} else if (record.profile_state == "DONE") {
+				ppayload  = '{"profile":{"command":"done"}}';
+				newProfile = true;
+			}
+		}
+	});
+	$("#Profile2").click(function () {
+		if (record.mode == "PROFILE") {
+			if ((record.profile_state == "RUN") || (record.profile_state == "PAUSE")) {
+				ppayload  = '{"profile":{"command":"pause"}}';
+				newProfile = true;
+			}
+		}
+	});
 
 	// The chart button.
-   	$("#FLog").jqxButton({ template: "info", width: '150px', theme: theme });
+   	$("#FLog").jqxButton({ template: "primary", width: '150px', theme: theme });
 	$("#FLog").click(function () {
 		var url="log_fermentation.php?code=" + record.beercode + "&name=" + record.beername;
 		window.open(url);
--- a/www/js/profile_fermentation.js	Sat Jan 12 20:18:54 2019 +0100
+++ b/www/js/profile_fermentation.js	Sat Jan 19 12:05:37 2019 +0100
@@ -62,7 +62,7 @@
 			{ name: 'name', type: 'string' },
 			{ name: 'inittemp_lo', type: 'float' },
 			{ name: 'inittemp_hi', type: 'float' },
-			{ name: 'fridgemode', type: 'bool' },
+			{ name: 'fridgemode', type: 'int' },
 			{ name: 'totalsteps', type: 'int' },
 			{ name: 'duration', type: 'int' },
 			{ name: 'steps', type: 'array' }
--- a/www/mon_fermenter.php	Sat Jan 12 20:18:54 2019 +0100
+++ b/www/mon_fermenter.php	Sat Jan 19 12:05:37 2019 +0100
@@ -9,13 +9,38 @@
      <div id="fermenter_table">
       <div id="fermenter_info">
        <table style='width: 100%; padding: 10px;'>
+	<col width="20%">
+	<col width="40%">
+        <col width="40%">
         <tr><th colspan=3>Klimaatkast overzicht</th></tr>
-        <tr><td>Uuid</td><td colspan="2"><div id="info_uuid"></div></td></tr>
-        <tr><td>Systeem</td><td colspan="2"><div id="info_system"></div></td></tr>
-        <tr><td>Code en bier</td><td><div id="info_beer"></div></td><td><div id="select_beer"></div></td></tr>
-        <tr><td>Werking</td><td colspan="2"><div id="info_mode"></div></td></tr>
-	<tr><td>Vergisting fase</td><td colspan="2"><div id="info_stage"></div></td></tr>
-        <tr><td>Vergisting profiel</td><td><div id="info_profile"></div></td><td><div id="select_profile"></div></td></tr>
+	<tr style="height: 25px;">
+         <td>Uuid</td>
+         <td colspan="2"><div id="info_uuid"></div></td>
+        </tr>
+	<tr style="height: 25px;">
+         <td>Systeem</td>
+	 <td><div id="info_system"></div></td>
+         <td><div id="info_online"></div></td>
+        </tr>
+	<tr style="height: 25px;">
+         <td>Code en bier</td>
+         <td><div id="info_beer"></div></td>
+         <td><div id="select_beer"></div></td>
+        </tr>
+	<tr style="height: 25px;">
+         <td>Werking</td>
+         <td><div id="info_mode"></div></td>
+         <td><input type="button" id="Profile1" value="Profile 1" /><input style="margin-left: 10px;" type="button" id="Profile2" value="Profile 2" /></td>
+        </tr>
+	<tr style="height: 25px;">
+         <td>Vergisting fase</td>
+         <td colspan="2"><div id="info_stage"></div></td>
+        </tr>
+	<tr style="height: 25px;">
+         <td>Vergisting profiel</td>
+         <td><div id="info_profile"></div></td>
+         <td><div id="select_profile"></div><div id="status_profile"></div></td>
+        </tr>
        </table>
       </div>
      </div>

mercurial