brewco/brewco.c

changeset 473
fdd30e935079
parent 472
55bcbf92ecab
child 474
fe1c3e3e90dc
--- a/brewco/brewco.c	Tue Dec 22 21:07:14 2015 +0100
+++ b/brewco/brewco.c	Sat Dec 26 21:45:44 2015 +0100
@@ -34,11 +34,12 @@
 #include "simulator.h"
 #include "prompt.h"
 #include "setup.h"
+#include "logger.h"
 
 
 
 int			my_shutdown = FALSE;
-int			man_mlt_pump = 0;
+int			mlt_pump_state = 0;
 
 double			hltInput;			/* HLT PID variables		*/
 double			hltOutput;
@@ -139,7 +140,7 @@
 
 
 
-void tempstatus(double hlttemp, double mlttemp)
+void tempstatus(void)
 {
     char	text[81];
 
@@ -198,107 +199,608 @@
 
 
 
-void automatic_brew(units_list *, brew_session *, a_recipe *, int);
-void automatic_brew(units_list *unit, brew_session *brew, a_recipe *recipe, int dosave)
+/*
+ * Third line during boil, only MLT status
+ */
+void mltstatus(void)
+{
+    char        text[21];
+
+    snprintf(text, 20, "MLT %3d%%  %6.2f\002      ", (int)mltOutput, mltSetpoint);
+#ifdef HAVE_WIRINGPI_H
+    piLock(LOCK_LCD);
+    lcdPosition(lcdHandle, 0, 2);
+    lcdPuts(lcdHandle, text);
+#endif
+    slcdPosition(slcdHandle, 0, 2);
+    slcdPuts(slcdHandle, text);
+}
+
+
+
+void timestatus(int row, int timeval)
+{
+    char	text[21];
+    int		hours, mins, val = timeval;
+
+    hours = val / 3600;
+    val -= (hours * 3600);
+    mins = val / 60;
+    val -= (mins * 60);
+ 
+    snprintf(text, 20, "      %02d:%02d:%02d      ", hours, mins, val);
+#ifdef HAVE_WIRINGPI_H
+    piLock(LOCK_LCD);
+    lcdPosition(lcdHandle, 0, row);
+    lcdPuts(lcdHandle, text);
+#endif
+    slcdPosition(slcdHandle, 0, row);
+    slcdPuts(slcdHandle, text);
+}
+
+
+
+int set_HLT_heater(units_list *unit, int state, double val)
 {
-    int		key, save = dosave;
+    if (strcmp(unit->hlt_heater.uuid, (char *)"00000000-0000-0000-0000-000000000000") == 0)
+	return 0;
+
+    hltSetpoint = val;
+
+    if (state && (PID_getMode(unit->PID_hlt) == P_MANUAL)) {
+	hlt_status(1);
+	PID_setMode(unit->PID_hlt, P_AUTOMATIC);
+	return 1;
+    }
+    if (! state && (PID_getMode(unit->PID_hlt) == P_AUTOMATIC)) {
+	hlt_status(0);
+	PID_setMode(unit->PID_hlt, P_MANUAL);
+	return 1;
+    }
+
+    return 0;
+}
+
+
+
+int set_MLT_heater(units_list *unit, int state, double val)
+{
+    if (strcmp(unit->mlt_heater.uuid, (char *)"00000000-0000-0000-0000-000000000000") == 0)
+	return 0;
+
+    mltSetpoint = val;
 
-//    if (debug)
-//	fprintf(stdout, "auto: step %d\n", brew->brewstep);
+    if (state && (PID_getMode(unit->PID_mlt) == P_MANUAL)) {
+	mlt_status(1);
+	PID_setMode(unit->PID_mlt, P_AUTOMATIC);
+	return 1;
+    }
+    if (! state && (PID_getMode(unit->PID_mlt) == P_AUTOMATIC)) {
+	mlt_status(0);
+	PID_setMode(unit->PID_mlt, P_MANUAL);
+	return 1;
+    }
+
+    return 0;
+}
+
+
+
+int set_MLT_pump(units_list *unit, int state)
+{
+    if (strcmp(unit->mlt_pump.uuid, (char *)"00000000-0000-0000-0000-000000000000") == 0)
+	return 0;
+
+    if (state && ! mlt_pump_state) {
+	device_out(unit->mlt_pump.uuid, 1);
+	mlt_pump_state = 1;
+	return 1;
+    }
+    if (! state && mlt_pump_state) {
+	device_out(unit->mlt_pump.uuid, 0);
+	mlt_pump_state = 0;
+	return 1;
+    }
+
+    return 0;
+}
+
+
+
+void automatic_brew(units_list *, brew_session *, a_recipe *, int, int);
+void automatic_brew(units_list *unit, brew_session *brew, a_recipe *recipe, int dosave, int seconds)
+{
+    int		key, save = dosave, i;
+    char	data[128];
+    static int	mash_fase = MASH_NA, hopstand = 0, last_step = -1, last_fase = -1, oldsec = 75, startdelay = 0;
 
     switch (brew->brewstep) {
 	case STEP_NA:		if (debug)
 				    fprintf(stdout, "auto: init recipe: %s-%s  unit: %s\n", recipe->code, recipe->name, unit->name);
 				syslog(LOG_NOTICE, "AUTO: starting new brew, recipe: %s-%s  unit: %s", recipe->code, recipe->name, unit->name);
+				brew->brewstep = STEP_BREWINIT;
+				break;
+
+	case STEP_BREWINIT:	prompt(103, NULL);		/* "   AUTOMATIC MODE   " */
+				prompt(207, NULL);		/* "    Delay start?    " */
+				prompt(300, NULL);		/* "                    " */
+				prompt(407, NULL);		/* "---  ---   No   Yes " */
+				if (debug)
+					fprintf(stdout, "step brewinit\n");
+				key = keywait();
+				if (key == KEY_RETURN) {
+				    brew->brewstep = STEP_WATERCHECK;
+				    startdelay = 0;
+				    syslog(LOG_NOTICE, "AUTO: brew initialize, direct start selected");
+				    break;
+				}
+				if (key == KEY_ENTER) {
+				    startdelay = 30;
+				    editInteger(&startdelay, 10, 960, 10, (char *)"Start delay", (char *)"mins");
+				}
+				syslog(LOG_NOTICE, "AUTO: brew initialize");
+				brew->brewstep = STEP_WATERCHECK;
+				break;
+
+	case STEP_WATERCHECK:	if (brew->brewstep != last_step) {
+				    prompt(111, NULL);		/* "AUTO --> Mash In    " */
+				    prompt(209, NULL);		/* "    Water Added?    " */
+				    prompt(300, NULL);
+				    prompt(410, NULL);          /* " Continue: Yes  No  " */
+				    last_step = brew->brewstep;
+				}
+				slcdDummy(slcdHandle);
+				key = keycheck();
+				if (key == KEY_RETURN) {
+				    brew->brewstep = STEP_PUMPPRIME;
+				    syslog(LOG_NOTICE, "AUTO: confirmed water added");
+				}
+				if (key == KEY_ENTER) {
+				    syslog(LOG_NOTICE, "AUTO: aborted water added");
+				    brew->brewstep = STEP_CLEANUP;
+				}
+				break;
+
+	case STEP_PUMPPRIME:	if (brew->brewstep != last_step) {
+				    prompt(111, NULL);		/* "AUTO --> Mash In    " */
+				    prompt(210, NULL);		/* "     Pump Prime     " */
+				    prompt(300, NULL);		/* "                    " */
+				    prompt(400, NULL);		/* "                    " */
+				    last_step = brew->brewstep;
+				}
+				brew->brewstep = STEP_WAITSTART;
+				break;
+
+	case STEP_WAITSTART:	if (startdelay == 0) {
+				    brew->brewstep = STEP_PREMASH;
+				    break;
+				}
+				if (brew->brewstep != last_step) {
+				    brew->timeout = startdelay * 60;
+				    prompt(111, NULL);          /* "AUTO --> Mash In    " */
+				    prompt(212, NULL);          /* "  To be started in  " */
+				    prompt(410, NULL);          /* " Continue: Yes  No  " */
+				    last_step = brew->brewstep;
+				}
+				if (oldsec != seconds) {
+				    timestatus(2, brew->timeout);
+				    brew->timeout--;
+				    if (brew->timeout <= 0) {
+					syslog(LOG_NOTICE, "AUTO: delayed start time reached");
+					brew->brewstep = STEP_PREMASH;
+				    }
+				    oldsec = seconds;
+				}
+				slcdDummy(slcdHandle);
+				key = keycheck();
+				if (key == KEY_RETURN) {
+				    syslog(LOG_NOTICE, "AUTO: delayed start skipped by user");
+				    brew->brewstep = STEP_PREMASH;
+				}
+				break;
+
+	case STEP_PREMASH:	if (brew->brewstep != last_step) {
+				    prompt(111 + brew->mashstep, NULL);     /* "AUTO --> [mashname] " */
+				    prompt(300, NULL);                      /* "                    " */
+				    prompt(418, NULL);                      /* "---  ---  Pause --- " */
+				    tempstatus();
+				    hlt_status(1);
+				    mlt_status(1);
+				    pump_status(unit->pump_premash);
+				    last_step = brew->brewstep;
+				}
+				initlog(brew->name);
+				if (set_HLT_heater(unit, 1, 85.0))
+				    syslog(LOG_NOTICE, "AUTO: premash turn on HLT at %6.2f", hltSetpoint);
+				if (set_MLT_heater(unit, 1, recipe->mash[0].setpoint))
+				    syslog(LOG_NOTICE, "AUTO: premash turn on MLT at %6.2f", mltSetpoint);
+				if (set_MLT_pump(unit, unit->pump_premash))
+				    syslog(LOG_NOTICE, "AUTO: premash turn %s MLT pump", mlt_pump_state ? "on":"off");
+				brew->brewstep = STEP_MASHING;
+				brew->mashstep = 0;
+				mash_fase = MASH_NA;
+				save = TRUE;
+				break;
+
+	case STEP_MASHING:	if (brew->brewstep != last_step) {
+				    prompt(111 + brew->mashstep, NULL);     /* "AUTO --> [mashname] " */
+				    prompt(300, NULL);                      /* "                    " */
+				    prompt(418, NULL);                      /* "---  ---  Pause --- " */
+				    tempstatus();
+				    hlt_status(1);
+				    mlt_status(1);
+				    pump_status(unit->pump_onmash);
+				    last_step = brew->brewstep;
+				}
+				if (set_HLT_heater(unit, 1, 85.0))
+				    syslog(LOG_NOTICE, "AUTO: mash turn on HLT at %6.2f", hltSetpoint);
+				if (set_MLT_heater(unit, 1, recipe->mash[brew->mashstep].setpoint))
+				    syslog(LOG_NOTICE, "AUTO: mash turn on MLT at %6.2f", mltSetpoint);
+				if ((mash_fase != MASH_REST) && set_MLT_pump(unit, unit->pump_onmash))
+				    syslog(LOG_NOTICE, "AUTO: mash turn %s MLT pump", mlt_pump_state ? "on":"off");
+
+				switch (mash_fase) {
+				    case MASH_NA:	if (recipe->mash[brew->mashstep].skip) {
+							    syslog(LOG_NOTICE, "AUTO: skipping mash step %d", brew->mashstep);
+							    brew->mashstep++;
+							} else {
+					    		    mltSetpoint = recipe->mash[brew->mashstep].setpoint;
+							    brew->timeout = recipe->mash[brew->mashstep].duration * 60;
+					    		    if ((brew->mashstep == 0) && ! unit->skip_add) {
+							    	mash_fase = MASH_PROMPT;
+							    } else
+							    	mash_fase = MASH_HEATING;
+							    syslog(LOG_NOTICE, "AUTO: mash step %d fase NA, setpoint %6.2f, duration %d", 
+									brew->mashstep, mltSetpoint, brew->timeout);
+							}
+							if (brew->mashstep == 0) {
+							    brew->starttime = time(NULL);
+							    save = TRUE;
+							}
+					    		break;
+
+				    case MASH_PROMPT:	if (last_fase != mash_fase) {
+							    prompt(111 + brew->mashstep, NULL);	/* "AUTO --> [mashname] " */
+							    prompt(219, NULL);              	/* "    Mash added?     " */
+							    prompt(300, NULL);
+							    prompt(410, NULL);              	/* " Continue: Yes  No  " */
+							    last_fase = mash_fase;
+							}
+							slcdDummy(slcdHandle);
+							key = keycheck();
+							if (key == KEY_RETURN) {
+							    mash_fase = MASH_HEATING;
+							    syslog(LOG_NOTICE, "AUTO: confirmed mash added");
+							}
+							if (key == KEY_ENTER) {
+							    syslog(LOG_NOTICE, "AUTO: aborted mash added");
+							    brew->brewstep = STEP_CLEANUP;
+							    brew->mashstep = 0;
+							}
+							break;
+
+				    case MASH_IODINE:	if (last_fase != mash_fase) {
+							    prompt(118, NULL);          /* "AUTO --> Mash Out   " */
+							    prompt(213, NULL);          /* "    Iodine test     " */
+							    timestatus(2, brew->timeout);
+							    prompt(410, NULL);          /* " Continue: Yes  No  " */
+							    last_fase = mash_fase;
+							}
+							if (oldsec != seconds) {
+							    brew->timeout--;
+							    timestatus(2, brew->timeout);
+							    if (brew->timeout <= 0) {
+								syslog(LOG_NOTICE, "AUTO: mash IODINE test timeout");
+								mash_fase = MASH_NA;
+								brew->mashstep++;
+							    }
+							    oldsec = seconds;
+							}
+							slcdDummy(slcdHandle);
+							key = keycheck();
+							if (key == KEY_RETURN) {
+							    syslog(LOG_NOTICE, "AUTO: mash IODINE test confirmed");
+							    mash_fase = MASH_NA;
+							    brew->mashstep++;
+							}
+							if (key == KEY_ENTER) {
+							    syslog(LOG_NOTICE, "AUTO: mash IODINE test declined");
+							    mash_fase = MASH_REST;
+							    brew->timeout = 600;	/* Add 10 more minutes */
+							}
+							break;
+
+				    case MASH_HEATING:	if (last_fase != mash_fase) {
+							    prompt(111 + brew->mashstep, NULL);     /* "AUTO --> [mashname] " */
+							    prompt(200, NULL);
+							    prompt(300, NULL);
+							    prompt(418, NULL);                      /* "---  ---  Pause --- " */
+							    hlt_status(1);
+							    mlt_status(1);
+							    pump_status(unit->pump_onmash);
+							    last_fase = mash_fase;
+							}
+							if (oldsec != seconds) {
+							    tempstatus();
+							    percstatus((seconds / 2) % 4);
+							    oldsec = seconds;
+							}
+							if (mltInput > mltSetpoint) {
+							    syslog(LOG_NOTICE, "AUTO: mash step %d fase HEATING reached %6.2f", brew->mashstep, mltSetpoint);
+							    mash_fase = MASH_REST;
+							}
+							break;
+
+				    case MASH_REST:	if (last_fase != mash_fase) {
+							    prompt(111 + brew->mashstep, NULL);     /* "AUTO --> [mashname] " */
+							    prompt(300, NULL);
+							    prompt(418, NULL);                      /* "---  ---  Pause --- " */
+							    hlt_status(1);
+							    mlt_status(1);
+							    pump_status(unit->pump_onmash);
+							    last_fase = mash_fase;
+							}
+							if (oldsec != seconds) {
+							    tempstatus();
+							    timestatus(2, brew->timeout);
+							    if (brew->mashstep == 7) {
+								/*
+								 * During mash-out rest, allow the grain to sink
+								 */
+								if (set_MLT_pump(unit, unit->pump_mashout))
+								    syslog(LOG_NOTICE, "AUTO: mash-out turn %s MLT pump", mlt_pump_state ? "on":"off");
+							    } else {
+								if (set_MLT_pump(unit, unit->pump_onmash))
+								    syslog(LOG_NOTICE, "AUTO: mash turn %s MLT pump", mlt_pump_state ? "on":"off");
+							    }
+							    brew->timeout--;
+							    if (brew->timeout <= 0) {
+								syslog(LOG_NOTICE, "AUTO: mash step %d fase REST done", brew->mashstep);
+								if ((brew->mashstep == 6) && ! unit->skip_iodine) {
+								    mash_fase = MASH_IODINE;
+								    brew->timeout = unit->iodine_time * 60;
+								} else if (brew->mashstep == 7) {
+								    mash_fase = MASH_DONE;
+								} else {
+								    mash_fase = MASH_NA;
+								    brew->mashstep++;
+								}
+							    }
+							    oldsec = seconds;
+							}
+							break;
+
+				    case MASH_DONE:	syslog(LOG_NOTICE, "AUTO: mash step %d fase DONE", brew->mashstep);
+							if (set_MLT_heater(unit, 1, recipe->mash[7].setpoint))
+							    syslog(LOG_NOTICE, "AUTO: mash done turn MLT off");
+							if (set_MLT_pump(unit, 0))
+							    syslog(LOG_NOTICE, "AUTO: mash done turn %s MLT pump", mlt_pump_state ? "on":"off");
+							brew->mashstep = 0;
+							brew->brewstep = STEP_MASHREMOVE;
+							break;
+				}
+				break;
+
+	case STEP_MASHREMOVE:	if (unit->skip_remove) {
+				    syslog(LOG_NOTICE, "AUTO: skipping Mash remove");
+				    brew->brewstep = STEP_PREBOIL;
+				} else {
+				    if (brew->brewstep != last_step) {
+					prompt(118, NULL);          /* "AUTO --> Mash Out   " */
+					prompt(220, NULL);          /* "   Mash Removed?    " */
+					prompt(300, NULL);
+					prompt(410, NULL);          /* " Continue: Yes  No  " */
+					last_step = brew->brewstep;
+				    }
+				    slcdDummy(slcdHandle);
+				    key = keycheck();
+				    if (key == KEY_RETURN) {
+					syslog(LOG_NOTICE, "AUTO: Confirmed Mash removed");
+					brew->brewstep = STEP_PREBOIL;
+				    }
+				}
+				break;
+
+	case STEP_PREBOIL:	if (brew->brewstep != last_step) {
+				    prompt(119, NULL);          /* "AUTO --> Boil       " */
+				    prompt(200, NULL);
+				    prompt(300, NULL);
+				    tempstatus();
+				    mltstatus();
+				    prompt(418, NULL);          /* "---  ---  Pause --- " */
+				    hlt_status(0);
+				    mlt_status(1);
+				    pump_status(unit->pump_onboil && (mltInput < unit->pump_stop));
+				    last_step = brew->brewstep;
+				}
+				if (oldsec != seconds) {
+				    tempstatus();
+				    mltstatus();
+				    oldsec = seconds;
+				}
+				if (set_HLT_heater(unit, 0, 10.0))
+				    syslog(LOG_NOTICE, "AUTO: preboil turn off HLT");
+				if (set_MLT_heater(unit, 1, 100.0))
+				    syslog(LOG_NOTICE, "AUTO: preboil turn on MLT to boil");
+				if (set_MLT_pump(unit, unit->pump_onboil && (mltInput < unit->pump_stop)))
+				    syslog(LOG_NOTICE, "AUTO: preboil turn %s MLT pump", mlt_pump_state ? "on":"off");
+				if (mltInput > 99.2) {
+				    syslog(LOG_NOTICE, "AUTO: reached boil temperature %.2f, start %d minutes boil", mltInput, recipe->boiltime);
+				    brew->brewstep = STEP_BOILING;
+				    brew->boiltimer = recipe->boiltime * 60;
+				}
+				break;
+
+	case STEP_BOILING:	if (set_HLT_heater(unit, 0, 10.0))
+				    syslog(LOG_NOTICE, "AUTO: boil turn off HLT");
+				if (set_MLT_heater(unit, 1, 100.0))
+				    syslog(LOG_NOTICE, "AUTO: boil turn on MLT to boil");
+				if (set_MLT_pump(unit, unit->pump_onboil && (mltInput < unit->pump_stop)))
+				    syslog(LOG_NOTICE, "AUTO: boil turn %s MLT pump", mlt_pump_state ? "on":"off");
+				if (brew->brewstep != last_step) {
+				    prompt(119, NULL);          /* "AUTO --> Boil       " */
+				    prompt(200, NULL);
+				    prompt(300, NULL);
+				    tempstatus();
+				    mltstatus();
+				    prompt(418, NULL);          /* "---  ---  Pause --- " */
+				    hlt_status(0);
+				    mlt_status(1);
+				    pump_status(unit->pump_onboil && (mltInput < unit->pump_stop));
+				    last_step = brew->brewstep;
+				}
+				if (oldsec != seconds) {
+				    tempstatus();
+				    if ((seconds / 2) % 4) {
+				        timestatus(2, brew->boiltimer);
+				    } else {
+					mltstatus();
+				    }
+				    if (brew->boiltimer >= 0) {
+				    	brew->boiltimer--;
+				    } else {
+					brew->brewstep = STEP_BOILDONE;
+				        syslog(LOG_NOTICE, "AUTO: boil is done");
+				    }
+				    oldsec = seconds;
+				}
+				break;
+
+	case STEP_BOILDONE:	if (set_MLT_heater(unit, 0, 10.0))
+				    syslog(LOG_NOTICE, "AUTO: after boil turn off MLT heater");
+				if (set_MLT_pump(unit, 0))
+				    syslog(LOG_NOTICE, "AUTO: after boil turn %s MLT pump", mlt_pump_state ? "on":"off");
+				if (brew->brewstep != last_step) {
+				    prompt(120, NULL);          /* "AUTO --> Cooling    " */
+				    prompt(214, NULL);          /* "   START COOLING    " */
+				    prompt(300, NULL);
+				    prompt(410, NULL);		/* " Continue: Yes  No  " */
+				    last_step = brew->brewstep;
+				}
+				slcdDummy(slcdHandle);
+				key = keycheck();
+				if (key == KEY_ENTER) {
+				    brew->brewstep = STEP_CLEANUP;
+				    syslog(LOG_NOTICE, "AUTO: user skipped cooling");
+				}
+				if (key == KEY_RETURN) {
+				    brew->brewstep = STEP_COOLING;
+				    syslog(LOG_NOTICE, "AUTO: user started cooling");
+				}
+				break;
+
+	case STEP_COOLING:	for (i = 0; i < 3; i++) {
+				    if ((recipe->hopstand[i].skip == 0) && (mltInput <= recipe->hopstand[i].max) && (mltInput >= recipe->hopstand[i].min)) {
+				        brew->brewstep = STEP_HOPSTAND;
+					hopstand = i;
+					syslog(LOG_NOTICE, "AUTO: starting hopstand %d", i+1);
+				    }
+				}
+				if (brew->brewstep == STEP_HOPSTAND)
+				    break;
+				// hot whirlpool start at 85 degrees
+				// cold whirlpool start at 30 degrees
+
+				if (brew->brewstep != last_step) {
+				    prompt(120, NULL);          /* "AUTO --> Cooling    " */
+				    prompt(200, NULL);
+				    tempstatus();
+				    prompt(300, NULL);
+				    prompt(418, NULL);          /* "---  ---  Pause --- " */
+				    hlt_status(0);
+				    mlt_status(0);
+				    pump_status(0);
+				    last_step = brew->brewstep;
+				}
+				if (oldsec != seconds) {
+				    tempstatus();
+				    oldsec = seconds;
+				}
+				if (mltInput <= recipe->coolto) {
+				    syslog(LOG_NOTICE, "AUTO: cool temperture %.2f reached", recipe->coolto);
+				    brew->brewstep = STEP_CLEANUP;
+				}
+				break;
+
+	case STEP_HOPSTAND:	if (brew->brewstep != last_step) {
+				    prompt(122 + hopstand, NULL);	/* "AUTO --> Hopstand n " */
+				    tempstatus();
+				    timestatus(2, brew->timeout);
+				    prompt(418, NULL);			/* "---  ---  Pause --- " */
+				    brew->boiltimer = recipe->hopstand[hopstand].duration * 60;
+				    last_step = brew->brewstep;
+				}
+
+				if (recipe->hopstand[hopstand].hold) {
+				    if (set_MLT_heater(unit, 1, recipe->hopstand[hopstand].setpoint))
+					syslog(LOG_NOTICE, "AUTO: hopstand 1 turn on MLT at %6.2f", mltSetpoint);
+				}
+				if (set_MLT_pump(unit, 1))
+				    syslog(LOG_NOTICE, "AUTO: hopstand 1 turn %s MLT pump", mlt_pump_state ? "on":"off");
+				if (oldsec != seconds) {
+				    tempstatus();
+				    timestatus(2, brew->timeout);
+				    brew->boiltimer--;
+				    if (brew->boiltimer <= 0) {
+					syslog(LOG_NOTICE, "AUTO: hopstand %d done", hopstand+1);
+					if (set_MLT_heater(unit, 0, 10.0))
+					    syslog(LOG_NOTICE, "AUTO: hopstand 1 turn off MLT at %6.2f", mltSetpoint);
+					brew->brewstep = STEP_COOLING;
+				    }
+				    oldsec = seconds;
+				}
+				break;
+
+	case STEP_WHIRLPOOL:	prompt(121, NULL);		/* "AUTO --> Whirlpool  " */
+				break;
+
+	case STEP_CLEANUP:	if (brew->brewstep != last_step) {
+				    prompt(101, NULL);              /* "    Brewco x.x.x    " */
+				    prompt(200, NULL);              /* "                    " */
+				    prompt(300, NULL);              /* "                    " */
+				    prompt(400, NULL);              /* "                    " */
+				    last_step = brew->brewstep;
+				}
+				syslog(LOG_NOTICE, "AUTO: cleanup");
+				if (set_HLT_heater(unit, 0, 10.0))
+				    syslog(LOG_NOTICE, "AUTO: cleanup turn on HLT at %6.2f", hltSetpoint);
+				if (set_MLT_heater(unit, 0, 10.0))
+				    syslog(LOG_NOTICE, "AUTO: cleanup turn on MLT at %6.2f", mltSetpoint);
+				if (set_MLT_pump(unit, 0))
+				    syslog(LOG_NOTICE, "AUTO: cleanup turn %s MLT pump", mlt_pump_state ? "on":"off");
 				brew->brewstep = STEP_BREWDONE;
 				break;
 
-	case STEP_BREWINIT:
-				break;
-	case STEP_WATERCHECK:	prompt(111, NULL);		/* "AUTO --> Mash In    " */
-				prompt(209, NULL);		/* "    Water Added?    " */
-				break;
-	case STEP_PUMPPRIME:	prompt(111, NULL);		/* "AUTO --> Mash In    " */
-				prompt(210, NULL);		/* "     Pump Prime     " */
-				break;
-	case STEP_WAITSTART:	prompt(111, NULL);		/* "AUTO --> Mash In    " */
-				prompt(212, NULL);		/* "  To be started in  " */
-				break;
-	case STEP_PREMASH:	prompt(111, NULL);		/* "AUTO --> Mash In    " */
-				/* Heatup until strike temp reached */
-				break;
-	case STEP_MASHING:	switch (brew->mashstep) {
-				    case 0:	prompt(111, NULL);
-					    	break;
-				    case 1:	prompt(112, NULL);
-						break;
-				    case 2:	prompt(113, NULL);
-						break;
-				    case 3:	prompt(114, NULL);
-						break;
-				    case 4:	prompt(115, NULL);
-						break;
-				    case 5:	prompt(116, NULL);
-						break;
-				    case 6:	prompt(117, NULL);
-						break;
-				    case 7:	prompt(118, NULL);
-						break;
+	case STEP_BREWDONE:	if (brew->brewstep != last_step) {
+				    prompt(101, NULL);              /* "    Brewco x.x.x    " */
+				    prompt(200, NULL);              /* "                    " */
+				    prompt(301, NULL);              /* "      Finished      " */
+				    prompt(408, NULL);              /* "---  ---   Ok   --- " */
+				    last_step = brew->brewstep;
 				}
-				break;
-	case STEP_IODINE:	prompt(118, NULL);		/* "AUTO --> Mash Out   " */
-				prompt(213, NULL);		/* "    Iodine test     " */
-				break;
-	case STEP_MASHREMOVE:	prompt(118, NULL);		/* "AUTO --> Mash Out   " */
-				break;
-	case STEP_PREBOIL:
-				break;
-	case STEP_BOILING:	prompt(119, NULL);		/* "AUTO --> Boil       " */
-				break;
-	case STEP_BOILDONE:
-				break;
-	case STEP_HOPSTAND1:
-				break;
-	case STEP_COOLING1:	prompt(120, NULL);		/* "AUTO --> Cooling    " */
-				prompt(214, NULL);		/* "   START COOLING    " */
-				break;
-	case STEP_WHIRLPOOL1:	prompt(121, NULL);		/* "AUTO --> Whirlpool  " */
-				break;
-	case STEP_COOLING2:	prompt(120, NULL);		/* "AUTO --> Cooling    " */
-				break;
-	case STEP_HOPSTAND2:
-				break;
-	case STEP_COOLING3:	prompt(120, NULL);		/* "AUTO --> Cooling    " */
-				break;
-	case STEP_HOPSTAND3:
-				break;
-	case STEP_COOLING:	prompt(120, NULL);		/* "AUTO --> Cooling    " */
-				break;
-	case STEP_WHIRLPOOL:	prompt(121, NULL);		/* "AUTO --> Whirlpool  " */
-				break;
-	case STEP_CLEANUP:
-				break;
-	case STEP_BREWDONE:	syslog(LOG_NOTICE, "AUTO: brew done");
+				syslog(LOG_NOTICE, "AUTO: brew done");
 				brew->brewstep = -1;
 				brew->endtime = time(NULL);
-				prompt(101, NULL);      	/* "    Brewco x.x.x    " */
-				prompt(200, NULL);		/* "                    " */
-				prompt(301, NULL);		/* "      Finished      " */
-				prompt(408, NULL);		/* "---  ---   Ok   --- " */
+				save = TRUE;
 				do {
 				    key = keywait();
 				} while (key != KEY_RETURN);
 				/*
 				 * Rewrite the display
 				 */
-				prompt(101, NULL);      /* "    Brewco x.x.x    " */
-				prompt(300, NULL);      /* "                    " */
-				prompt(401, NULL);      /* "---  MAN  AUTO SETUP" */
+				prompt(101, NULL);      	/* "    Brewco x.x.x    " */
+				tempstatus();
+				prompt(300, NULL);      	/* "                    " */
+				prompt(401, NULL);      	/* "---  MAN  AUTO SETUP" */
 				break;
     }
 
-    if (save)
+    if (save) {
+	snprintf(data, 127, "%d,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f", brew->brewstep,
+			hltInput, hltOutput, hltSetpoint, mltInput, mltOutput, mltSetpoint);
+	logger(brew->name, data);
 	wrsession(brew);
+    }
 }
 
 
@@ -344,12 +846,12 @@
 				}
                                 if (key == KEY_RETURN) {
                                     manual = MANUAL_NONE;
-				    man_mlt_pump = 0;
+				    mlt_pump_state = 0;
 				    PID_setMode(unit->PID_mlt, P_MANUAL);
 				    PID_setMode(unit->PID_hlt, P_MANUAL);
 				    hlt_status(0);
 				    mlt_status(0);
-				    device_out(unit->mlt_pump.uuid, man_mlt_pump);
+				    device_out(unit->mlt_pump.uuid, mlt_pump_state);
 				}
                                 if (key == KEY_ENTER) {
                                                 // TODO: prompt for water
@@ -365,12 +867,12 @@
 				}
                                 if (key == KEY_RETURN) {
                                     manual = MANUAL_NONE;
-				    man_mlt_pump = 0;
+				    mlt_pump_state = 0;
 				    PID_setMode(unit->PID_mlt, P_MANUAL);
 				    PID_setMode(unit->PID_hlt, P_MANUAL);
 				    hlt_status(0);
 				    mlt_status(0);
-				    device_out(unit->mlt_pump.uuid, man_mlt_pump);
+				    device_out(unit->mlt_pump.uuid, mlt_pump_state);
 				}
                                 if (key == KEY_ENTER) {
                                                 // TODO: prompt for water
@@ -378,7 +880,7 @@
 				    manual_prompt();
                                 }
                                 break;
-        case MANUAL_HLT:        tempstatus(*unit->PID_hlt->myInput, *unit->PID_mlt->myInput);
+        case MANUAL_HLT:        tempstatus();
 				percstatus((seconds / 2) % 4);
 
 				slcdDummy(slcdHandle);
@@ -401,7 +903,7 @@
 				    manual_prompt();
                                 }
                                 break;
-        case MANUAL_MLT:        tempstatus(*unit->PID_hlt->myInput, *unit->PID_mlt->myInput);
+        case MANUAL_MLT:        tempstatus();
 				percstatus((seconds / 2) % 4);
 
 				slcdDummy(slcdHandle);
@@ -420,16 +922,16 @@
 				if ((key == KEY_UP) && (mltSetpoint < 100))
 				    mltSetpoint += 1.0;
                                 if (key == KEY_ENTER) {
-                                    if (man_mlt_pump)
-                                        man_mlt_pump = 0;
-                                    else
-                                        man_mlt_pump = 1;
+                                    if (mlt_pump_state)
+					set_MLT_pump(unit, 0);
+				    else
+					set_MLT_pump(unit, 1);
                                 }
                                 if (key == KEY_ESCAPE) {
                                     manual = MANUAL_SELMLT;
 				    manual_prompt();
                                 }
-                                device_out(unit->mlt_pump.uuid, man_mlt_pump);
+                                device_out(unit->mlt_pump.uuid, mlt_pump_state);
                                 break;
     }
 
@@ -627,14 +1129,30 @@
      * If this file is present, there has been a crash.
      */
     brew = (brew_session *)malloc(sizeof(brew_session));
-    if (rdsession(brew) == 0) {
-    } else {
-	/*
-	 * No active brew session, make that permanent.
-	 */
+    rc = rdsession(brew);
+    syslog(LOG_NOTICE, "rdsession: rc=%d", rc);
+    if (debug)
+	fprintf(stdout, "rdsession: rc=%d\n", rc);
+
+    char *mypath = xstrcpy(etcpath);
+    mypath = xstrcat(mypath, (char *)"brewing.xml");
+    if (rc == 0) {
+	if (debug)
+	    fprintf(stdout, "Active brew session found\n");
+    } else if (rc == -1) {
 	free(brew);
 	brew = NULL;
+	if (debug)
+	    fprintf(stdout, "No active brew session found\n");
+    } else {
+	unlink(mypath);
+	free(brew);
+	brew = NULL;
+	if (debug)
+	    fprintf(stdout, "Error brew session found\n");
     }
+    free(mypath);
+    mypath = NULL;
 
     do {
 	if (my_shutdown) {
@@ -677,10 +1195,10 @@
 	     */
 	    hltInput = hltSetpoint = mltInput = mltSetpoint = 20.0;
 	    hltOutput = mltOutput = 0;
-	    PID_init(unit->PID_hlt, &hltInput, &hltOutput, &hltSetpoint, unit->PID_hlt->dispKd, unit->PID_hlt->dispKi, unit->PID_hlt->dispKd, unit->PID_hlt->Direction);
+	    PID_init(unit->PID_hlt, &hltInput, &hltOutput, &hltSetpoint, unit->PID_hlt->dispKp, unit->PID_hlt->dispKi, unit->PID_hlt->dispKd, unit->PID_hlt->Direction);
 	    PID_setOutputLimits(unit->PID_hlt, 0, 100);
 	    PID_setSampleTime(unit->PID_hlt, unit->PID_hlt->SampleTime);
-	    PID_init(unit->PID_mlt, &mltInput, &mltOutput, &mltSetpoint, unit->PID_mlt->dispKd, unit->PID_mlt->dispKi, unit->PID_mlt->dispKd, unit->PID_mlt->Direction);
+	    PID_init(unit->PID_mlt, &mltInput, &mltOutput, &mltSetpoint, unit->PID_mlt->dispKp, unit->PID_mlt->dispKi, unit->PID_mlt->dispKd, unit->PID_mlt->Direction);
 	    PID_setOutputLimits(unit->PID_mlt, 0, 100);
 	    PID_setSampleTime(unit->PID_mlt, unit->PID_mlt->SampleTime);
 	    hlt_status(0);
@@ -693,6 +1211,21 @@
 	    percslot = 0;
 	    percfase = PERC_INIT;
 	    dosave = 0;
+
+	    if (brew) {
+		/*
+		 * Restore session
+		 */
+		if (debug)
+		    fprintf(stdout, "loop_init: restoring brew session\n");
+	    	for (recipe = recipes; recipe; recipe = recipe->next) {
+		    if (strcmp(recipe->uuid, brew->uuid_recipe) == 0) {
+			break;
+		    }
+		}
+		if (debug)
+		    fprintf(stdout, "loop_init: brewstep=%d mashstep=%d recipe=%s\n", brew->brewstep, brew->mashstep, recipe->code);
+	    }
 	}
 
 	/* run_pause code here */
@@ -734,8 +1267,8 @@
 		    device_out(unit->hlt_heater.uuid, 0);
 		    device_out(unit->mlt_heater.uuid, 0);
 		}
-		if (debug)
-		    fprintf(stdout, "  perslot=%d MLT=%d%% HLT=%d%% fase=%d\n", percslot, MLTp, HLTp, percfase);
+//		if (debug)
+//		    fprintf(stdout, "  perslot=%d MLT=%d%% HLT=%d%% fase=%d\n", percslot, MLTp, HLTp, percfase);
 	    } else if (percfase == PERC_MLT) {
 		if (percslot > MLTp) {
 		    device_out(unit->mlt_heater.uuid, 0);
@@ -773,8 +1306,6 @@
 		dosave = 1;
 	    }
 
-//fprintf(stdout, "%d seconds %d minutes %ld millis\n", seconds, minutes, millis());
-
 	    rc = device_in(unit->hlt_sensor.uuid, &temp);
 	    if (rc == DEVPRESENT_YES) {
 		hltInput = temp / 1000.0;
@@ -806,7 +1337,7 @@
 	    /*
 	     * Automate mode
 	     */
-	    automatic_brew(unit, brew, recipe, dosave);
+	    automatic_brew(unit, brew, recipe, dosave, seconds);
 	    dosave = 0;
 	    if (brew->brewstep == -1) {
 		/*
@@ -857,7 +1388,7 @@
 	    /*
 	     * Not running.
 	     */
-	    tempstatus(hltInput, mltInput);
+	    tempstatus();
 	    key = keycheck();
 	    if (key == KEY_ENTER) {
 		setup();

mercurial