brewco/brewco.c

changeset 487
d5bc44183aa4
parent 486
5a237a99a793
child 488
bee1f70fb42b
--- a/brewco/brewco.c	Thu Feb 25 22:42:54 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1633 +0,0 @@
-/*****************************************************************************
- * Copyright (C) 2015
- *   
- * Michiel Broek <mbroek at mbse dot eu>
- *
- * This file is part of the mbsePi-apps
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * mbsePi-apps is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with ThermFerm; see the file COPYING.  If not, write to the Free
- * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *****************************************************************************/
-
-#include "brewco.h"
-#include "rdconfig.h"
-#include "rdsession.h"
-#include "rdrecipes.h"
-#include "util.h"
-#include "xutil.h"
-#include "lcd-pcf8574.h"
-#include "slcd.h"
-#include "lock.h"
-#include "devices.h"
-#include "keyboard.h"
-#include "simulator.h"
-#include "prompt.h"
-#include "setup.h"
-#include "logger.h"
-
-
-
-int			my_shutdown = FALSE;
-int			mlt_pump_state = 0;
-
-double			hltInput;			/* HLT PID variables		*/
-double			hltOutput;
-double			hltSetpoint;
-double			mltInput;			/* MLT PID variables		*/
-double			mltOutput;
-double			mltSetpoint;
-
-extern int              debug;
-extern sys_config       Config;
-extern a_recipe		*recipes;
-extern int              lcdHandle;
-extern int		slcdHandle;
-extern int		sock;
-
-#ifdef USE_SIMULATOR
-extern int		SIM_cooler;
-#endif
-char			*etcpath = NULL;
-char			*varpath = NULL;
-
-
-
-#ifndef HAVE_WIRINGPI_H
-pthread_t               threads[5];
-#endif
-
-
-#define	MANUAL_NONE	0
-#define	MANUAL_SELHLT	1
-#define	MANUAL_SELMLT	2
-#define	MANUAL_HLT	11
-#define	MANUAL_MLT	12
-
-#define	PERC_INIT	0
-#define	PERC_MLT	1
-#define	PERC_HLT	2
-#define	PERC_REST	3
-
-
-int manual		= MANUAL_NONE;
-
-
-
-/*
- * CGRAM characters
- */
-unsigned char	degC[8] 	= { 0b01000, 0b10100, 0b01000, 0b00111, 0b01000, 0b01000, 0b01000, 0b00111 };
-unsigned char	degF[8] 	= { 0b01000, 0b10100, 0b01000, 0b00111, 0b00100, 0b00110, 0b00100, 0b00100 };
-unsigned char	SP_Symbol[8]	= { 0b11100, 0b10000, 0b11100, 0b00111, 0b11101, 0b00111, 0b00100, 0b00100 };
-unsigned char	PumpONOFF[8]	= { 0b00000, 0b01110, 0b01010, 0b01110, 0b01000, 0b01000, 0b01000, 0b00000 };
-unsigned char	RevPumpONOFF[8]	= { 0b11111, 0b10001, 0b10101, 0b10001, 0b10111, 0b10111, 0b10111, 0b11111 };
-unsigned char	HeatONOFF[8]	= { 0b00000, 0b01010, 0b01010, 0b01110, 0b01110, 0b01010, 0b01010, 0b00000 };
-unsigned char	RevHeatONOFF[8]	= { 0b11111, 0b10101, 0b10101, 0b10001, 0b10001, 0b10101, 0b10101, 0b11111 };
-unsigned char	Language[8]	= { 0b11111, 0b00010, 0b01000, 0b11111, 0b00000, 0b10001, 0b10101, 0b11111 };
-
-
-void help(void);
-void die(int);
-
-
-
-void help(void)
-{
-    fprintf(stdout, "mbsePi-apps brewco v%s starting\n\n", VERSION);
-    fprintf(stdout, "Usage: brewco [-d] [-h]\n");
-    fprintf(stdout, "  -d --debug              Debug and run in foreground\n");
-    fprintf(stdout, "  -h --help               Display this help\n");
-}
-
-
-
-void die(int onsig)
-{
-    switch (onsig) {
-#ifdef USE_SIMULATOR
-	case SIGUSR1:	syslog(LOG_NOTICE, "Got SIGUSR1, start cooler");
-			SIM_cooler = TRUE;
-			return;
-	case SIGUSR2:	syslog(LOG_NOTICE, "Got SIGUSR2, stop cooler");
-			SIM_cooler = FALSE;
-			return;
-#endif
-	case SIGHUP:    syslog(LOG_NOTICE, "Got SIGHUP, shutting down");
-			break;
-	case SIGINT:    syslog(LOG_NOTICE, "Keyboard interrupt, shutting down");
-			break;
-	case SIGTERM:   syslog(LOG_NOTICE, "Got SIGTERM, shutting down");
-			break;
-	case SIGSEGV:   syslog(LOG_NOTICE, "Got SIGSEGV, shutting down");
-			my_shutdown = TRUE;
-			exit(SIGSEGV);
-			break;
-	default:        syslog(LOG_NOTICE, "die() on signal %d", onsig);
-    }
-
-    my_shutdown = TRUE;
-}
-
-
-
-void tempstatus(void)
-{
-    char	text[81];
-
-    snprintf(text, 8, "%6.2f\001", hltInput);
-#ifdef HAVE_WIRINGPI_H
-    piLock(LOCK_LCD);
-    lcdPosition(lcdHandle, 1, 1);
-    lcdPuts(lcdHandle, text);
-#endif
-    slcdPosition(slcdHandle, 1, 1);
-    slcdPuts(slcdHandle, text);
-
-    snprintf(text, 8, "%6.2f\001", mltInput);
-#ifdef HAVE_WIRINGPI_H
-    piLock(LOCK_LCD);
-    lcdPosition(lcdHandle, 10, 1);
-    lcdPuts(lcdHandle, text);
-#endif
-    slcdPosition(slcdHandle, 10, 1);
-    slcdPuts(slcdHandle, text);
-}
-
-
-
-/*
- * Third line, show setPoints or heater percentage.
- */
-void percstatus(int which)
-{
-    char	text[21];
-
-    if (which)
-	snprintf(text, 8, "%6.2f\002", hltSetpoint);
-    else
-    	snprintf(text, 8, "HLT%3d%%", (int)hltOutput);
-#ifdef HAVE_WIRINGPI_H
-    piLock(LOCK_LCD);
-    lcdPosition(lcdHandle, 1, 2);
-    lcdPuts(lcdHandle, text);
-#endif
-    slcdPosition(slcdHandle, 1, 2);
-    slcdPuts(slcdHandle, text);
-
-    if (which)
-	snprintf(text, 8, "%6.2f\002", mltSetpoint);
-    else
-    	snprintf(text, 8, "MLT%3d%%", (int)mltOutput);
-#ifdef HAVE_WIRINGPI_H
-    piLock(LOCK_LCD);
-    lcdPosition(lcdHandle, 10, 2);
-    lcdPuts(lcdHandle, text);
-#endif
-    slcdPosition(slcdHandle, 10, 2);
-    slcdPuts(slcdHandle, text);
-}
-
-
-
-/*
- * 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)
-{
-    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 (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 = STEP_NA, last_fase = -1, oldsec = 75, startdelay = 0;
-
-    if (brew->brewstep != last_step) {
-	snprintf(data, 40, brewstep_name(last_step));
-	syslog(LOG_NOTICE, "AUTO: brewstep %s to %s", data, brewstep_name(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_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(407, NULL);          /* "---  ---   No   Yes " */
-				    last_step = brew->brewstep;
-				}
-				slcdDummy(slcdHandle);
-				key = keycheck();
-				if (key == KEY_ENTER) {
-				    brew->brewstep = STEP_PUMPPRIME;
-				    syslog(LOG_NOTICE, "AUTO: confirmed water added");
-				}
-				if (key == KEY_RETURN) {
-				    syslog(LOG_NOTICE, "AUTO: aborted water added");
-				    brew->brewstep = STEP_CLEANUP;
-				}
-				break;
-
-	case STEP_PUMPPRIME:	if (brew->brewstep != last_step) {
-				    prompt(100, NULL);		/* "                    " */
-				    prompt(210, NULL);		/* "     Pump Prime     " */
-				    prompt(300, NULL);		/* "                    " */
-				    prompt(400, NULL);		/* "                    " */
-				    hlt_status(0);
-				    mlt_status(0);
-				    last_step = brew->brewstep;
-				}
-				for (i = 1; i < 6; i++) {
-				    if (set_MLT_pump(unit, 1))
-					syslog(LOG_NOTICE, "AUTO: pump prime %d turn %s MLT pump", i, mlt_pump_state ? "on":"off");
-				    usleep(750000 + (i * 250000));	/* 250 + i * 250 mSec */
-				    if (set_MLT_pump(unit, 0))
-					syslog(LOG_NOTICE, "AUTO: pump prime %d turn %s MLT pump", i, mlt_pump_state ? "on":"off");
-				    usleep(350000);			/* 350 mSec */
-				}
-				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, NULL);     	/* "AUTO --> Prepare    " */
-				    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 (oldsec != seconds) {
-				    tempstatus();
-				    percstatus((seconds / 2) % 4);
-				    oldsec = seconds;
-				}
-				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, 10.0))
-				    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");
-				if (hltInput >= 85.0) {
-				    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);
-
-				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;
-							    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(407, NULL);              	/* "---  ---   No   Yes " */
-							    last_fase = mash_fase;
-							}
-							if (set_MLT_pump(unit, 0))	/* Off during mash add */
-							    syslog(LOG_NOTICE, "AUTO: mash turn %s MLT pump", mlt_pump_state ? "on":"off");
-							slcdDummy(slcdHandle);
-							key = keycheck();
-							if (key == KEY_ENTER) {
-							    mash_fase = MASH_NA;
-							    brew->mashstep++;
-							    syslog(LOG_NOTICE, "AUTO: confirmed mash added");
-							}
-							if (key == KEY_RETURN) {
-							    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 (set_MLT_pump(unit, unit->pump_onmash))
-							    syslog(LOG_NOTICE, "AUTO: mash turn %s MLT pump", mlt_pump_state ? "on":"off");
-							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;
-							    syslog(LOG_NOTICE, "AUTO: mash step %d fase HEATING started", brew->mashstep);
-							}
-							if (set_MLT_pump(unit, unit->pump_onmash))
-							    syslog(LOG_NOTICE, "AUTO: mash turn %s MLT pump", mlt_pump_state ? "on":"off");
-							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(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();
-							    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 == 0) && ! unit->skip_add) {
-								    mash_fase = MASH_PROMPT;
-								} else 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(407, NULL);          /* "---  ---   No   Yes " */
-					last_step = brew->brewstep;
-				    }
-				    slcdDummy(slcdHandle);
-				    key = keycheck();
-				    if (key == KEY_ENTER) {
-					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.1))
-				    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.1))
-				    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_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;
-				}
-				syslog(LOG_NOTICE, "AUTO: brew done");
-				brew->brewstep = -1;
-				brew->endtime = time(NULL);
-				save = TRUE;
-				do {
-				    key = keywait();
-				} while (key != KEY_RETURN);
-				/*
-				 * Rewrite the display
-				 */
-				prompt(101, NULL);      	/* "    Brewco x.x.x    " */
-				tempstatus();
-				prompt(300, NULL);      	/* "                    " */
-				prompt(401, NULL);      	/* "---  MAN  AUTO SETUP" */
-				break;
-    }
-
-    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);
-    }
-}
-
-
-
-void manual_prompt(void)
-{
-    switch (manual) {
-	case MANUAL_SELHLT:	prompt(104, NULL);      /* "    MANUAL MODE     " */
-				prompt(303, NULL);      /* "     Manual HLT     " */
-				prompt(402, NULL);      /* "---  dwn  quit  ok  " */
-				break;
-	case MANUAL_SELMLT:	prompt(104, NULL);      /* "    MANUAL MODE     " */
-				prompt(304, NULL);      /* "     Manual MLT     " */
-				prompt(404, NULL);      /* " up  ---  quit  ok  " */
-				break;
-	case MANUAL_HLT:	prompt(104, NULL);      /* "    MANUAL MODE     " */
-				prompt(300, NULL);	/* "                    " */
-				prompt(413, NULL);      /* "UP* *DWN  heat  --- " */
-				break;
-	case MANUAL_MLT:	prompt(104, NULL);      /* "    MANUAL MODE     " */
-				prompt(300, NULL);	/* "                    " */
-				prompt(406, NULL);      /* "UP* *DWN  heat  pmp " */
-				break;
-    }
-}
-
-
-
-/*
- * Manual menu for testing your equipment.
- */
-int manual_menu(units_list *, int);
-int manual_menu(units_list *unit, int seconds)
-{
-    int		key;
-
-    switch (manual) {
-        case MANUAL_SELHLT:     slcdDummy(slcdHandle);
-				key = keycheck();
-                                if (key == KEY_DOWN) {
-                                    manual = MANUAL_SELMLT;
-				    manual_prompt();
-				}
-                                if (key == KEY_RETURN) {
-                                    manual = MANUAL_NONE;
-				    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, mlt_pump_state);
-				}
-                                if (key == KEY_ENTER) {
-                                                // TODO: prompt for water
-                                    manual = MANUAL_HLT;
-				    manual_prompt();
-                                }
-                                break;
-        case MANUAL_SELMLT:     slcdDummy(slcdHandle);
-				key = keycheck();
-                                if (key == KEY_UP) {
-                                    manual = MANUAL_SELHLT;
-				    manual_prompt();
-				}
-                                if (key == KEY_RETURN) {
-                                    manual = MANUAL_NONE;
-				    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, mlt_pump_state);
-				}
-                                if (key == KEY_ENTER) {
-                                                // TODO: prompt for water
-                                    manual = MANUAL_MLT;
-				    manual_prompt();
-                                }
-                                break;
-        case MANUAL_HLT:        tempstatus();
-				percstatus((seconds / 2) % 4);
-
-				slcdDummy(slcdHandle);
-                                key = keycheck();
-                                if (key == KEY_RETURN) {
-				    if (PID_getMode(unit->PID_hlt) == P_MANUAL) {
-					PID_setMode(unit->PID_hlt, P_AUTOMATIC);
-					hlt_status(1);
-				    } else {
-					PID_setMode(unit->PID_hlt, P_MANUAL);
-					hlt_status(0);
-				    }
-                                }
-				if ((key == KEY_DOWN) && (hltSetpoint > 10))
-				    hltSetpoint -= 1.0;
-				if ((key == KEY_UP) && (hltSetpoint < 100))
-				    hltSetpoint += 1.0;
-                                if (key == KEY_ESCAPE) {
-                                    manual = MANUAL_SELHLT;
-				    manual_prompt();
-                                }
-                                break;
-        case MANUAL_MLT:        tempstatus();
-				percstatus((seconds / 2) % 4);
-
-				slcdDummy(slcdHandle);
-				key = keycheck();
-                                if (key == KEY_RETURN) {
-				    if (PID_getMode(unit->PID_mlt) == P_MANUAL) {
-					PID_setMode(unit->PID_mlt, P_AUTOMATIC);
-					mlt_status(1);
-				    } else {
-					PID_setMode(unit->PID_mlt, P_MANUAL);
-					mlt_status(0);
-				    }
-                                }
-				if ((key == KEY_DOWN) && (mltSetpoint > 10))
-				    mltSetpoint -= 1.0;
-				if ((key == KEY_UP) && (mltSetpoint < 100))
-				    mltSetpoint += 1.0;
-                                if (key == KEY_ENTER) {
-                                    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, mlt_pump_state);
-                                break;
-    }
-
-    return 0;
-}
-
-
-
-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, 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);
-
-    /*
-     * Define special characters in the display CGRAM
-     */
-    if (Config.tempFormat == 'C')
-    	slcdCharDef(slcdHandle, 1, degC);
-    else
-	slcdCharDef(slcdHandle, 1, degF);
-    slcdCharDef(slcdHandle, 2, SP_Symbol);
-    slcdCharDef(slcdHandle, 3, PumpONOFF);
-    slcdCharDef(slcdHandle, 4, RevPumpONOFF);
-    slcdCharDef(slcdHandle, 5, HeatONOFF);
-    slcdCharDef(slcdHandle, 6, RevHeatONOFF);
-    slcdCharDef(slcdHandle, 7, Language);
-
-    if (lockprog((char *)"brewco")) {
-	syslog(LOG_NOTICE, "Can't lock");
-	return 1;
-    }
-
-    if (debug)
-	fprintf(stdout, "Begin server()\n");
-
-    if ((rc = devices_detect())) {
-	syslog(LOG_NOTICE, "Detected %d new devices", rc);
-	if (debug)
-	    fprintf(stdout, "Detected %d new devices\n", rc);
-	wrconfig();
-    }
-
-#ifdef HAVE_WIRINGPI_H
-    rc = piThreadCreate(my_devices_loop);
-#else
-    rc = pthread_create(&threads[t], NULL, my_devices_loop, (void *)t );
-#endif
-    if (rc) {
-	fprintf(stderr, "my_devices_loop thread didn't start rc=%d\n", rc);
-	syslog(LOG_NOTICE, "my_devices_loop thread didn't start rc=%d", rc);
-#ifndef HAVE_WIRINGPI_H
-    } else {
-	t++;
-#endif
-    }
-
-#ifdef HAVE_WIRINGPI_H
-    rc = piThreadCreate(my_keyboard_loop);
-#else
-    rc = pthread_create(&threads[t], NULL, my_keyboard_loop, (void *)t );
-#endif
-    if (rc) {
-	fprintf(stderr, "my_keyboard_loop thread didn't start rc=%d\n", rc);
-	syslog(LOG_NOTICE, "my_keyboard_loop thread didn't start rc=%d", rc);
-#ifndef HAVE_WIRINGPI_H
-    } else {
-	t++;
-#endif
-    }
-
-#ifdef USE_SIMULATOR
-#ifdef HAVE_WIRINGPI_H
-    rc = piThreadCreate(my_simulator_loop);
-#else
-    rc = pthread_create(&threads[t], NULL, my_simulator_loop, (void *)t );
-#endif
-    if (rc) {
-	fprintf(stderr, "my_simulator_loop thread didn't start rc=%d\n", rc);
-	syslog(LOG_NOTICE, "my_simulator_loop thread didn't start rc=%d", rc);
-#ifndef HAVE_WIRINGPI_H
-    } else {
-	t++;
-#endif
-    }
-#endif
-
-    if (! Config.units) {
-	/*
-	 * No brewsystems defined, add the first
-	 */
-	prompt(218, NULL);	/*   Add Brewsystem?   */
-	prompt(407, NULL);	/* ---  ---   Ok   --- */
-
-	do {
-	    key = keywait();
-	} while (key != KEY_RETURN);
-
-	if (key == KEY_RETURN) {
-	    addUnit(1);
-	}
-    }
-
-    /*
-     * Initialize units for processing
-     */
-    for (unit = Config.units; unit; unit = unit->next) {
-	if (unit->active)
-	    break;
-    }
-
-    if (! unit->active) {
-	fprintf(stdout, "No active units found\n");
-    }
-
-    /*
-     * Safety, turn everything off
-     */
-    if (unit->active) {
-	if (debug)
-	    fprintf(stdout, "Starting brewsystem %d `%s'\n", unit->number, unit->name);
-	syslog(LOG_NOTICE, "Starting brewsystem %d `%s'", unit->number, unit->name);
-    }
-
-    /*
-     * During automation there will be a state file:
-     * ~/.brewco/var/brewing.xml
-     * If this file is present, there has been a crash.
-     */
-    brew = (brew_session *)malloc(sizeof(brew_session));
-    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) {
-	    run = 0;
-	    unit->hlt_heater.value = 0;
-	    unit->mlt_heater.value = 0;
-	    unit->mlt_pump.value = 0;
-	    device_out(unit->hlt_heater.uuid, 0);
-	    device_out(unit->mlt_heater.uuid, 0);
-	    device_out(unit->mlt_pump.uuid, 0);
-	    hlt_status(0);
-	    mlt_status(0);
-	    break;
-	}
-
-	/*
-	 * Do we need to initialize this unit?
-	 */
-	if (do_init) {
-	    if (debug)
-		fprintf(stdout, "Initialize brewsystem %d `%s'\n", unit->number, unit->name);
-	    syslog(LOG_NOTICE, "Initialize brewsystem %d `%s'", unit->number, unit->name);
-
-	    prompt(0, NULL);
-	    prompt(101, NULL);		/* "    Brewco x.x.x    " */
-	    prompt(401, NULL);		/* "---  MAN  AUTO SETUP" */
-
-	    /*
-	     * Turn everything off
-	     */
-	    unit->hlt_heater.value = 0;
-	    unit->mlt_heater.value = 0;
-	    unit->mlt_pump.value = 0;
-	    device_out(unit->hlt_heater.uuid, 0);
-	    device_out(unit->mlt_heater.uuid, 0);
-	    device_out(unit->mlt_pump.uuid, 0);
-
-	    /*
-	     * Initialize PID's
-	     */
-	    hltInput = hltSetpoint = mltInput = mltSetpoint = 20.0;
-	    hltOutput = mltOutput = 0;
-	    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->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);
-	    mlt_status(0);
-
-	    manual = MANUAL_NONE;
-
-	    do_init = FALSE;
-	    nowmillis = perctimer = millis();
-	    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 */
-
-	/*
-	 * Update PID's, even if they are off. Both PID's will do
-	 * the scheduling by themselves.
-	 */
-	rc = PID_compute(unit->PID_hlt);
-	rc = PID_compute(unit->PID_mlt);
-
-	/*
-	 * This is the serial heaters schedule loop. The total
-	 * loop time is 5 seconds, heating is 0..100% so we
-	 * have 5 mSeconds timeslots. The MLT has priority over
-	 * the HLT heater, so the HLT heater can get too little
-	 * power. TODO: simultaneous use must be implemented.
-	 * In sequentiel mode, the total drawn power is the same
-	 * as the power used by the largest heater element.
-	 */
-	nowmillis = millis();
-	if (nowmillis > (perctimer + 50)) {
-	    percslot++;
-	    if (percfase == PERC_INIT) {
-		HLTp = (int)hltOutput;
-		MLTp = (int)mltOutput;
-		if ((MLTp + HLTp) > 100)
-		    HLTp = 100 - MLTp;		/* The HLT has lower priority	*/
-		if (MLTp) {
-		    percfase = PERC_MLT;
-		    device_out(unit->hlt_heater.uuid, 0);
-		    device_out(unit->mlt_heater.uuid, 1);
-		} else if (HLTp) {
-		    percfase = PERC_HLT;
-		    device_out(unit->hlt_heater.uuid, 1);
-		    device_out(unit->mlt_heater.uuid, 0);
-		} else { 
-		    percfase = PERC_REST;
-		    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);
-	    } else if (percfase == PERC_MLT) {
-		if (percslot > MLTp) {
-		    device_out(unit->mlt_heater.uuid, 0);
-		    if (HLTp) {
-			device_out(unit->hlt_heater.uuid, 1);
-			percfase = PERC_HLT;
-		    } else {
-			percfase = PERC_REST;
-		    }
-		}
-	    } else if (percfase == PERC_HLT) {
-		if (percslot > (MLTp + HLTp)) {
-		    device_out(unit->hlt_heater.uuid, 0);
-		    percfase = PERC_REST;
-		}
-	    }
-	    if (percslot == 100) {	/* End of the loop, start over */
-		percslot = 0;
-		percfase = PERC_INIT;
-	    }
-	    perctimer = nowmillis;
-	}
-
-	now = time(NULL);
-	if (now != last) {
-	    /*
-	     * Each second
-	     */
-	    last = now;
-	    seconds++;
-
-	    if (seconds > 59) {
-		seconds = 0;
-		minutes++;
-		dosave = 1;
-	    }
-
-	    rc = device_in(unit->hlt_sensor.uuid, &temp);
-	    if (rc == DEVPRESENT_YES) {
-		hltInput = temp / 1000.0;
-		unit->hlt_sensor.state = 0;
-	    } else if (rc == DEVPRESENT_ERROR) {
-		unit->hlt_sensor.state = 1;
-	    } else {
-		unit->hlt_sensor.state = 2;
-	    }
-	    rc = device_in(unit->mlt_sensor.uuid, &temp);
-	    if (rc == DEVPRESENT_YES) {
-		mltInput = temp / 1000.0;
-		unit->mlt_sensor.state = 0;
-	    } else if (rc == DEVPRESENT_ERROR) {
-		unit->mlt_sensor.state = 1;
-	    } else {
-		unit->mlt_sensor.state = 2;
-	    }
-
-	    if (debug && ((seconds % 10) == 1)) {
-		fprintf(stdout, "MLT: In=%.2lf Out=%.2lf Set=%.2lf Stat=%d  HLT: In=%.2lf Out=%.2lf Set=%.2lf Stat=%d\n",
-				mltInput, mltOutput, mltSetpoint, PID_getMode(unit->PID_mlt), 
-				hltInput, hltOutput, hltSetpoint, PID_getMode(unit->PID_hlt));
-	    }
-
-	}
-
-	if (brew) {
-	    /*
-	     * Automate mode
-	     */
-	    automatic_brew(unit, brew, recipe, dosave, seconds);
-	    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) {
-	    /*
-	     * Manual mode
-	     */
-	    manual_menu(unit, seconds);
-	    if (manual == MANUAL_NONE) {
-		/*
-		 * Rewrite the display
-		 */
-		prompt(101, NULL);	/* "    Brewco x.x.x    " */
-		prompt(300, NULL);	/* "                    " */
-		prompt(401, NULL);	/* "---  MAN  AUTO SETUP" */
-	    }
-	} else {
-	    /*
-	     * Not running.
-	     */
-	    tempstatus();
-	    key = keycheck();
-	    if (key == KEY_ENTER) {
-		setup();
-		prompt(101, NULL);	/* "    Brewco x.x.x    " */
-		prompt(200, NULL);
-		prompt(300, NULL);
-		hlt_status(0);
-		mlt_status(0);
-		pump_status(0);
-		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();
-	    }
-	}
-
-	usleep(5000);	/* 5 mSec */
-
-    } while (run);
-
-    syslog(LOG_NOTICE, "Out of loop");
-    if (debug)
-	fprintf(stdout, (char *)"Out of loop\n");
-
-    prompt(0, NULL);
-    prompt(101, NULL);		/* "    Brewco x.x.x    " */
-    prompt(302, NULL);		/* "   Shutting down    " */
-
-    /*
-     * Give threads time to cleanup
-     */
-    usleep(1500000);
-    prompt(0, NULL);
-    setBacklight(0);
-
-    if (sock != -1) {
-	if (shutdown(sock, SHUT_RDWR)) {
-	    syslog(LOG_NOTICE, "Can't shutdown socket: %s", strerror(errno));
-	}
-	sock = -1;
-    }
-
-    wrrecipes();
-    wrconfig();
-    ulockprog((char *)"brewco");
-    return 0;
-}
-
-
-
-int main(int argc, char *argv[])
-{
-    int		rc = 0, c, i;
-    char	*homepath = NULL;
-
-    while (1) {
-	int option_index = 0;
-	static struct option long_options[] = {
-	    {"debug", 0, 0, 'c'},
-	    {"help", 0, 0, 'h'},
-	    {0, 0, 0, 0}
-	};
-
-	c = getopt_long(argc, argv, "dh", long_options, &option_index);
-	if (c == -1)
-	    break;
-
-	switch (c) {
-	    case 'd':   debug = TRUE;
-			break;
-	    case 'h':   help();
-			return 1;
-	}
-    }
-
-    openlog("brewco", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_USER);
-    syslog(LOG_NOTICE, "mbsePi-apps brewco v%s starting", VERSION);
-    if (debug)
-	fprintf(stdout, "mbsePi-apps brewco v%s starting\n", VERSION);
-
-    /*
-     * Set home directory path
-     */
-    if (getenv((char *)"USER") == NULL) {
-	homepath = xstrcpy((char *)"/root");
-    } else {
-	homepath = xstrcpy(getenv((char *)"HOME"));
-    }
-    varpath = xstrcpy(homepath);
-    varpath = xstrcat(varpath, (char *)"/.brewco/var/");
-    etcpath = xstrcpy(homepath);
-    etcpath = xstrcat(etcpath, (char *)"/.brewco/etc/");
-    mkdirs(varpath, 0755);
-    mkdirs(etcpath, 0755);
-
-    if (rdconfig()) {
-	fprintf(stderr, "Error reading configuration\n");
-	syslog(LOG_NOTICE, "Error reading configuration: halted");
-	return 1;
-    }
-    if (debug)
-	fprintf(stdout, "configuration loaded\n");
-
-    if (rdrecipes()) {
-	fprintf(stderr, "Error reading recipes\n");
-    	syslog(LOG_NOTICE, "Error reading recipes: halted");
-	return 1;
-    }
-    if (debug)
-	fprintf(stdout, "recipes loaded\n");
-
-    /*
-     *  Catch all the signals we can, and ignore the rest. Note that SIGKILL can't be ignored
-     *  but that's live. This daemon should only be stopped by SIGTERM.
-     *  Don't catch SIGCHLD.
-     */
-    for (i = 0; i < NSIG; i++) {
-	if ((i != SIGCHLD) && (i != SIGKILL) && (i != SIGSTOP))
-	    signal(i, (void (*))die);
-    }
-
-#ifdef HAVE_WIRINGPI_H
-    if (wiringPiSetup () )
-	return 1;
-#endif
-
-    if ((rc = initLCD (Config.lcd_cols, Config.lcd_rows))) {
-	fprintf(stderr, "Cannot initialize LCD display, rc=%d\n", rc);
-	return 1;
-    }
-
-    rc = server();
-
-    syslog(LOG_NOTICE, "Finished, rc=%d", rc);
-    if (debug)
-	fprintf(stdout, "Finished, rc=%d\n", rc);
-    return rc;
-}
-
-

mercurial