Added initial part of the brew automation.

Tue, 22 Dec 2015 21:07:14 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Tue, 22 Dec 2015 21:07:14 +0100
changeset 472
55bcbf92ecab
parent 471
1564b60558b1
child 473
fdd30e935079

Added initial part of the brew automation.

brewco/brewco.c file | annotate | diff | comparison | revisions
brewco/brewco.h file | annotate | diff | comparison | revisions
brewco/rdsession.c file | annotate | diff | comparison | revisions
--- a/brewco/brewco.c	Tue Dec 22 15:59:26 2015 +0100
+++ b/brewco/brewco.c	Tue Dec 22 21:07:14 2015 +0100
@@ -49,6 +49,7 @@
 
 extern int              debug;
 extern sys_config       Config;
+extern a_recipe		*recipes;
 extern int              lcdHandle;
 extern int		slcdHandle;
 extern int		sock;
@@ -197,9 +198,107 @@
 
 
 
-void automatic_brew(units_list *, brew_session *);
-void automatic_brew(units_list *unit, brew_session *brew)
+void automatic_brew(units_list *, brew_session *, a_recipe *, int);
+void automatic_brew(units_list *unit, brew_session *brew, a_recipe *recipe, int dosave)
 {
+    int		key, save = dosave;
+
+//    if (debug)
+//	fprintf(stdout, "auto: step %d\n", brew->brewstep);
+
+    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_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;
+				}
+				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");
+				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   --- " */
+				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" */
+				break;
+    }
+
+    if (save)
+	wrsession(brew);
 }
 
 
@@ -339,18 +438,76 @@
 
 
 
+char *choose_recipe(void);
+char *choose_recipe(void)
+{
+    int			total, i, key, choice = 1;
+    static char		uuid[37];
+    a_recipe		*recipe;
+    char		pmpt[81];
+
+    strcpy(uuid, (char *)"00000000-0000-0000-0000-000000000000");
+    for (;;) {
+	total = 0;
+	for (recipe = recipes; recipe; recipe = recipe->next)
+	    total++;
+
+	if (total == 0)
+	    return uuid;
+
+	i = 0;
+	for (recipe = recipes; recipe; recipe = recipe->next) {
+	    i++;
+	    if (i == choice)
+		break;
+	}
+
+	prompt(102, NULL);          /* "     SETUP MENU     " */
+	prompt(221, NULL);          /* "   Select Recipe    " */
+	if (total) {
+	    snprintf(pmpt, Config.lcd_cols + 1, "%s %s                   ", recipe->code, recipe->name);
+	    prompt(300, pmpt);
+	}
+	if (total == 1)
+	    prompt(405, NULL);      /* "---  ---  quit  ok  " */
+	else if (choice == 1)
+	    prompt(402, NULL);      /* "---  dwn  quit  ok  " */
+	else if (choice == total)
+	    prompt(404, NULL);      /* " up  ---  quit  ok  " */
+	else
+	    prompt(403, NULL);      /* " up  dwn  quit  ok  " */
+
+	key = keywait();
+	if ((key == KEY_RETURN) || my_shutdown)
+	    return uuid;
+	if (key == KEY_ENTER) {
+	    strcpy(uuid, recipe->uuid);
+	    return uuid;
+	}
+	if ((key == KEY_UP) && (total > 1) && (choice > 1)) {
+	    choice--;
+	}
+	if ((key == KEY_DOWN) && (total > 1) && (choice < total))
+	    choice++;
+    }
+}
+
+
+
 int server(void);
 int server(void)
 {
-    int 		rc = 0, run = 1, key, temp, MLTp, HLTp, percslot, percfase = PERC_INIT;
+    int 		rc = 0, run = 1, dosave, key, temp, MLTp, HLTp, percslot, percfase = PERC_INIT;
     int			do_init = TRUE, seconds = 0, minutes = 0;
     units_list		*unit;
+    a_recipe		*recipe = NULL;
     brew_session	*brew = NULL;
 #ifndef HAVE_WIRINGPI_H
     long		t = 0;
 #endif
     time_t		now, last = (time_t)0;
     long		nowmillis, perctimer;
+    struct tm		*tm;
 
     prompt(101, NULL);
 
@@ -535,6 +692,7 @@
 	    nowmillis = perctimer = millis();
 	    percslot = 0;
 	    percfase = PERC_INIT;
+	    dosave = 0;
 	}
 
 	/* run_pause code here */
@@ -544,11 +702,7 @@
 	 * the scheduling by themselves.
 	 */
 	rc = PID_compute(unit->PID_hlt);
-//	if (seconds < 3)
-//	fprintf(stdout, "hlt rc=%d");
 	rc = PID_compute(unit->PID_mlt);
-//	if (seconds < 3)
-//		        fprintf(stdout, "   mlt rc=%d\n");
 
 	/*
 	 * This is the serial heaters schedule loop. The total
@@ -612,9 +766,11 @@
 	     */
 	    last = now;
 	    seconds++;
+
 	    if (seconds > 59) {
 		seconds = 0;
 		minutes++;
+		dosave = 1;
 	    }
 
 //fprintf(stdout, "%d seconds %d minutes %ld millis\n", seconds, minutes, millis());
@@ -650,7 +806,39 @@
 	    /*
 	     * Automate mode
 	     */
-	    automatic_brew(unit, brew);
+	    automatic_brew(unit, brew, recipe, dosave);
+	    dosave = 0;
+	    if (brew->brewstep == -1) {
+		/*
+		 * Save session and move it
+		 */
+		wrsession(brew);
+		char	*fpath, *tpath;
+		fpath = xstrcpy(etcpath);
+		fpath = xstrcat(fpath, (char *)"brewing.xml");
+		tpath = xstrcpy(varpath);
+		tpath = xstrcat(tpath, (char *)"old/brewing.xml.");
+		mkdirs(tpath, 0755);
+		tpath = xstrcat(tpath, brew->name);
+		if (debug)
+		    fprintf(stdout, "auto: saving as %s\n", tpath);
+		file_cp(fpath, tpath);
+		unlink(fpath);
+		free(fpath);
+		free(tpath);
+
+		/*
+		 * Free memory, session is over.
+		 */
+		if (brew->name)
+		    free(brew->name);
+		if (brew->uuid_recipe)
+		    free(brew->uuid_recipe);
+		if (brew->uuid_unit)
+		    free(brew->uuid_unit);
+		free(brew);
+		brew = NULL;
+	    }
 
 	} else if (manual != MANUAL_NONE) {
 	    /*
@@ -675,6 +863,79 @@
 		setup();
 		prompt(101, NULL);	/* "    Brewco x.x.x    " */
 		prompt(401, NULL);	/* "---  MAN  AUTO SETUP" */
+	    } else if (key == KEY_RETURN && ! brew) {
+		int     i, isOk = TRUE;
+		char    message[41];
+
+		tm = localtime(&now);
+		snprintf(message, 40, "%04d%02d%02d-%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
+		brew = (brew_session *)malloc(sizeof(brew_session));
+		brew->uuid_recipe = xstrcpy(choose_recipe());
+		brew->uuid_unit = xstrcpy(unit->uuid);
+		brew->name = xstrcpy(message);
+		brew->brewstep = STEP_NA;
+		brew->mashstep = MASH_NA;
+		brew->timeout = brew->boiltimer = 0;
+		brew->starttime = brew->endtime = (time_t)0;
+		/*
+		 * Now check if everything is sane
+		 */
+		if (strcmp(brew->uuid_recipe, (char *)"00000000-0000-0000-0000-000000000000") == 0) {
+		    isOk = FALSE;
+		    snprintf(message, Config.lcd_cols + 1, " No recipe selected ");
+		    if (debug)
+			fprintf(stdout, "brew init: No recipe selected\n");
+		}
+		if (isOk) {
+		    isOk = FALSE;
+		    for (recipe = recipes; recipe; recipe = recipe->next) {
+			if (strcmp(recipe->uuid, brew->uuid_recipe) == 0) {
+			    isOk = TRUE;
+			    if (! recipe->boiltime)
+				isOk = FALSE;
+			    for (i = 0; i < 8; i++) {
+				if (! recipe->mash[i].skip && ! recipe->mash[i].setpoint)
+				    isOk = FALSE;
+			    }
+			    for (i = 0; i < 3; i++) {
+				if (! recipe->hopstand[i].skip && recipe->hopstand[i].hold && (recipe->hopstand[i].setpoint == 0))
+				    isOk = FALSE;
+			    }
+			    break;
+			}
+		    }
+		    if (isOk == FALSE) {
+			snprintf(message, Config.lcd_cols + 1, "    Recipe error    ");
+			if (debug)
+			    fprintf(stdout, "brew init: recipe error\n");
+		    }
+		}
+
+		if (debug)
+		    fprintf(stdout, "init brew: %s\n", isOk ? (char *)"Ok":(char *)"Error");
+
+		if (isOk) {
+		    wrsession(brew);
+		} else {
+		    prompt(300, message);
+		    prompt(408, NULL);		/* "---  ---   Ok   --- " */
+		    key = keywait();
+		    if (brew->name)
+			free(brew->name);
+		    if (brew->uuid_recipe)
+			free(brew->uuid_recipe);
+		    if (brew->uuid_unit)
+			free(brew->uuid_unit);
+		    free(brew);
+		    brew = NULL;
+		    /*
+		     * Rewrite the display
+		     */
+		    prompt(101, NULL);      /* "    Brewco x.x.x    " */
+		    prompt(300, NULL);      /* "                    " */
+		    prompt(401, NULL);      /* "---  MAN  AUTO SETUP" */
+		}
+
 	    } else if (key == KEY_DOWN) {
 		manual = MANUAL_SELHLT;
 		manual_prompt();
--- a/brewco/brewco.h	Tue Dec 22 15:59:26 2015 +0100
+++ b/brewco/brewco.h	Tue Dec 22 21:07:14 2015 +0100
@@ -316,6 +316,7 @@
 typedef struct _brew_session {
     char		*uuid_recipe;		/* Brewing this recipe		*/
     char		*uuid_unit;		/* Brewing unit			*/
+    char		*name;			/* Session name			*/
     int			brewstep;		/* Main steps			*/
     int			mashstep;		/* Mash step			*/
     int			timeout;		/* Generic time downcouner	*/
--- a/brewco/rdsession.c	Tue Dec 22 15:59:26 2015 +0100
+++ b/brewco/rdsession.c	Tue Dec 22 21:07:14 2015 +0100
@@ -106,6 +106,10 @@
         syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteFormatElement");
         return 1;
     }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", brew->name)) < 0) {
+	syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteFormatElement");
+	return 1;
+    }
     if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BREWSTEP", "%s", BREWSTEP[brew->brewstep])) < 0) {
 	syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
 	return 1;
@@ -234,6 +238,9 @@
 	if ((!xmlStrcmp(cur->name, (const xmlChar *)"UUID_UNIT"))) {
 	    brew->uuid_unit = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
 	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"NAME"))) {
+	    brew->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	}
 	if ((!xmlStrcmp(cur->name, (const xmlChar *)"BREWSTEP"))) {
 	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
 	    for (i = 0; i < 23; i++) {

mercurial