Added automate state file.

Sat, 28 Nov 2015 20:15:38 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 28 Nov 2015 20:15:38 +0100
changeset 441
bde74a8f2ad7
parent 440
8df3252b688f
child 442
1193bd7d460f

Added automate state file.

brewco/Makefile file | annotate | diff | comparison | revisions
brewco/brewco.c file | annotate | diff | comparison | revisions
brewco/brewco.h file | annotate | diff | comparison | revisions
brewco/futil.c file | annotate | diff | comparison | revisions
brewco/futil.h file | annotate | diff | comparison | revisions
brewco/keyboard.c file | annotate | diff | comparison | revisions
brewco/keyboard.h file | annotate | diff | comparison | revisions
brewco/rdconfig.c file | annotate | diff | comparison | revisions
brewco/rdsession.c file | annotate | diff | comparison | revisions
brewco/rdsession.h file | annotate | diff | comparison | revisions
--- a/brewco/Makefile	Sat Nov 28 13:47:00 2015 +0100
+++ b/brewco/Makefile	Sat Nov 28 20:15:38 2015 +0100
@@ -57,9 +57,10 @@
 slcd.o: brewco.h slcd.h futil.h xutil.h
 devices.o: brewco.h devices.h xutil.h keyboard.h
 futil.o: brewco.h futil.h
-brewco.o: rdconfig.h brewco.h futil.h xutil.h lcd-pcf8574.h slcd.h lock.h devices.h keyboard.h simulator.h
+brewco.o: brewco.h rdconfig.h rdsession.h futil.h xutil.h lcd-pcf8574.h slcd.h lock.h devices.h keyboard.h simulator.h
 lock.o: lock.h brewco.h
 lcd-pcf8574.o: brewco.h lcd-pcf8574.h slcd.h
+rdsession.o: brewco.h rdsession.h futil.h xutil.h
 pid.o: brewco.h pid.h
 xutil.o: brewco.h xutil.h
 keyboard.o: brewco.h lcd-pcf8574.h slcd.h keyboard.h
--- a/brewco/brewco.c	Sat Nov 28 13:47:00 2015 +0100
+++ b/brewco/brewco.c	Sat Nov 28 20:15:38 2015 +0100
@@ -20,8 +20,9 @@
  * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  *****************************************************************************/
 
+#include "brewco.h"
 #include "rdconfig.h"
-#include "brewco.h"
+#include "rdsession.h"
 #include "futil.h"
 #include "xutil.h"
 #include "lcd-pcf8574.h"
@@ -211,13 +212,85 @@
 }
 
 
+
+void editUnit(units_list *unit)
+{
+    if (debug)
+    	fprintf(stdout, "Start edit brewsystem %d %s\n", unit->number, unit->uuid);
+
+    if (debug)
+	fprintf(stdout, "End edit brewsystem %d %s\n", unit->number, unit->uuid);
+}
+
+
+
+void addUnit(int number)
+{
+    units_list	*tmpu, *unit = (units_list *)malloc(sizeof(units_list));
+    char	name[81];
+    uuid_t	uu;
+
+    if (debug)
+	fprintf(stdout, "Adding new brewsystem %d\n", number);
+    unit->next = NULL;
+    unit->version = 1;
+    unit->uuid = malloc(37);
+    uuid_generate(uu);
+    uuid_unparse(uu, unit->uuid);
+    snprintf(name, 20, "System %d", number);
+    unit->name = xstrcpy(name);
+    unit->number = number;
+    if (number == 1)
+	unit->active = 1;
+    else
+	unit->active = 0;
+    unit->hlt_sensor = unit->mlt_sensor = NULL;
+    unit->hlt_heater = unit->mlt_heater = unit->mlt_pump = NULL;
+    unit->hlt_heater_mltfirst = 1;
+    unit->pump_cycle = 7;
+    unit->pump_rest = 2;
+    unit->pump_premash = 1;
+    unit->pump_onmash = 1;
+    unit->pump_mashout = 0;
+    unit->pump_onboil = 0;
+    unit->pump_stop = 90;
+    unit->skip_add = 0;
+    unit->skip_remove = 0;
+    unit->skip_iodine = 0;
+    unit->iodine_time = 90;
+    unit->whirlpool = 1;
+    unit->PID_hlt = (pid_var *)malloc(sizeof(pid_var));
+    unit->PID_mlt = (pid_var *)malloc(sizeof(pid_var));
+    InitPID(unit->PID_hlt);
+    InitPID(unit->PID_mlt);
+
+    editUnit(unit);
+
+    if (Config.units == NULL) {
+	Config.units = unit;
+    } else {
+	for (tmpu = Config.units; tmpu; tmpu = tmpu->next) {
+	    if (tmpu->next == NULL) {
+		tmpu->next = unit;
+		break;
+	    }
+	}
+    }
+    syslog(LOG_NOTICE, "Brewsystem %d added to the configuration", number);
+    if (debug)
+	fprintf(stdout, "Brewsystem %d added to the configuration\n", number);
+}
+
+
+
 int server(void);
 int server(void)
 {
-    int 	rc = 0, run = 1, key;
-    units_list	*unit;
+    int 		rc = 0, run = 1, key;
+    units_list		*unit;
+    brew_session	*brew = NULL;
 #ifndef HAVE_WIRINGPI_H
-    long	t = 0;
+    long		t = 0;
 #endif
 
 //    if (lockprog((char *)"brewco")) {
@@ -225,8 +298,13 @@
 //	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();
     }
 
@@ -245,13 +323,13 @@
     }
 
 #ifdef HAVE_WIRINGPI_H
-    rc = piThreadCreate(my_panel_loop);
+    rc = piThreadCreate(my_keyboard_loop);
 #else
-    rc = pthread_create(&threads[t], NULL, my_panel_loop, (void *)t );
+    rc = pthread_create(&threads[t], NULL, my_keyboard_loop, (void *)t );
 #endif
     if (rc) {
-	fprintf(stderr, "my_panel_loop thread didn't start rc=%d\n", rc);
-	syslog(LOG_NOTICE, "my_panel_loop thread didn't start rc=%d", 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++;
@@ -277,13 +355,19 @@
     /*
      * Initialize units for processing
      */
-//    for (unit = Config.units; unit; unit = unit->next) {
+    for (unit = Config.units; unit; unit = unit->next) {
 	/*
 	 * Safety, turn everything off
 	 */
-//	unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->light_state = 0;
-//	unit->heater_wait = unit->cooler_wait = unit->fan_wait = unit->light_wait = 0;
-//    }
+	if (unit->active) {
+	    if (unit->hlt_heater)
+	    	unit->hlt_heater->value = 0;
+	    if (unit->mlt_heater)
+	    	unit->mlt_heater->value = 0;
+	    if (unit->mlt_pump)
+		unit->mlt_pump->value = 0;
+	}
+    }
 
     prompt(101);
     if (! Config.units) {
@@ -294,39 +378,49 @@
 	prompt(407);    /* ---  ---   Ok   --- */
 
 	do {
-	    usleep(10000);
-	    slcdDummy(slcdHandle);
-	    key = keycheck();
+	    key = keywait();
 	} while (key != KEY_RETURN);
+
+	if (key == KEY_RETURN) {
+	    addUnit(1);
+	}
     }
 
-    /* Check for a crash and recover */
-
-    prompt(0);
-    prompt(401);
+    /*
+     * 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));
+    if (rdsession(brew) == 0) {
+    } else {
+	/*
+	 * No active brew session, make that permanent.
+	 */
+	free(brew);
+	brew = NULL;
+    }
 
     do {
-	if (my_shutdown)
+	if (my_shutdown) {
 	    run = 0;
-
-	/*
-	 * If there is no unit, setup a unit
-	 */
-	if (! Config.units) {
+	    break;
 	}
 
-	/*
-	 * Select the active unit
-	 */
+	if (brew) {
+	    /*
+	     * Automate mode
+	     */
 
-	/*
-	 * If running, do the things
-	 */
-
-	/*
-	 * Not running, do manual, setup etc
-	 */
-
+	} else {
+	    /*
+	     * Not running.
+	     */
+	    prompt(0);
+	    prompt(101);
+	    prompt(401);
+	    key = keywait();
+	}
 
 	usleep(100000);
 
@@ -401,6 +495,8 @@
 	syslog(LOG_NOTICE, "Error reading configuration: halted");
 	return 1;
     }
+    if (debug)
+	fprintf(stdout, "configuration loaded\n");
 
     /*
      *  Catch all the signals we can, and ignore the rest. Note that SIGKILL can't be ignored
--- a/brewco/brewco.h	Sat Nov 28 13:47:00 2015 +0100
+++ b/brewco/brewco.h	Sat Nov 28 20:15:38 2015 +0100
@@ -115,6 +115,8 @@
     int                 version;                /* Record version               */
     char		*uuid;			/* uuid code			*/
     char                *name;                  /* Unit name                    */
+    int			number;			/* Unit number			*/
+    int			active;			/* 0/1 active unit		*/
     sensor_var		*hlt_sensor;		/* HLT sensor			*/
     switch_var		*hlt_heater;		/* HLT heater			*/
     int			hlt_heater_mltfirst;	/* HLT heater MLT high priority	*/
@@ -272,4 +274,36 @@
 
 
 
+/*
+ * Brewing state file ~/.brewco/var/brewing.xml
+ * If present a brew session is running
+ */
+
+#define	MAISH_NA	0			/* Not in any state yet		*/
+#define	MASIH_PROMPT	1			/* Prompt the user		*/
+#define	MAISH_HEATING	2			/* Heating phase		*/
+#define	MAISH_REST	3			/* Rest phase			*/
+#define	MAISH_DONE	4			/* This step is done		*/
+
+
+typedef struct _brew_session {
+    char		*uuid_recipe;		/* Brewing this recipe		*/
+    char		*uuid_unit;		/* Brewing unit			*/
+    int			premash;		/* In premash state		*/
+    int			mashstep;		/* In or into maishstep or -1	*/
+    int			mashstate;		/* State this step is in	*/
+    int			resttime;		/* Rest time downcouner		*/
+    int			iodine;			/* Mash iodine test		*/
+    int			mashremove;		/* Mash remove step		*/
+    int			boilheating;		/* Heat for boiling		*/
+    int			boiling;		/* Boiling started		*/
+    int			boiltimer;		/* Boiling downcount		*/
+    int			cooling;		/* Cooling phase		*/
+    int			whirlpool;		/* Whirlpool phase		*/
+    int			cleanup;		/* Cleanup phase		*/
+    time_t		starttime;		/* Start of brew		*/
+    time_t		endtime;		/* End of brew			*/
+} brew_session;
+
+
 #endif
--- a/brewco/futil.c	Sat Nov 28 13:47:00 2015 +0100
+++ b/brewco/futil.c	Sat Nov 28 20:15:38 2015 +0100
@@ -58,3 +58,20 @@
 }
 
 
+
+/*
+ * Test if the given file exists. The second option is:
+ * R_OK - test for Read rights 
+ * W_OK - test for Write rights
+ * X_OK - test for eXecute rights
+ * F_OK - test file presence only
+ */ 
+int file_exist(char *path, int mode)
+{
+    if (access(path, mode) != 0)
+	return errno;
+
+    return 0;
+}
+
+
--- a/brewco/futil.h	Sat Nov 28 13:47:00 2015 +0100
+++ b/brewco/futil.h	Sat Nov 28 20:15:38 2015 +0100
@@ -3,5 +3,6 @@
 
 
 int  mkdirs(char *, mode_t);
+int  file_exist(char *, int);
 
 #endif
--- a/brewco/keyboard.c	Sat Nov 28 13:47:00 2015 +0100
+++ b/brewco/keyboard.c	Sat Nov 28 20:15:38 2015 +0100
@@ -64,6 +64,28 @@
 int keypressed(void);
 
 
+
+/*
+ * Wait for a key. Return the pressed key.
+ */
+int keywait(void)
+{
+    int	key;
+
+    do {
+	usleep(50000);
+	slcdDummy(slcdHandle);
+	key = keycheck();
+	if (my_shutdown)
+	    return KEY_NONE;
+    } while (key == KEY_NONE);
+
+    fprintf(stdout, "keywait %d\n", key);
+    return key;
+}
+
+
+
 /*
  * Check for a key. Return last pressed key or none.
  */
@@ -99,9 +121,9 @@
 
 
 #ifdef HAVE_WIRINGPI_H
-PI_THREAD (my_panel_loop)
+PI_THREAD (my_keyboard_loop)
 #else
-void *my_panel_loop(void *threadid)
+void *my_keyboard_loop(void *threadid)
 #endif
 {
     int		Return = 0, Enter = 0, Up = 0, Down = 0, Backlight = LCD_SLEEP, AnyKey = FALSE;
@@ -114,9 +136,9 @@
     pinMode(PANEL_DOWN, INPUT);
 #endif
 
-    syslog(LOG_NOTICE, "Thread my_panel_loop started");
+    syslog(LOG_NOTICE, "Thread my_keyboard_loop started");
     if (debug)
-	fprintf(stdout, "Thread my_panel_loop started\n");
+	fprintf(stdout, "Thread my_keyboard_loop started\n");
 
     /*
      * Loop forever until the external shutdown variable is set.
@@ -215,20 +237,6 @@
 		if (Backlight > 0) {
 		    Backlight--;
 		}
-
-#ifdef HAVE_WIRINGPI_H
-//		piLock(LOCK_MENU);
-#endif
-//	    	if (setupmenu != MENU_NONE) {
-//		    if (menutimer < MENU_TIMEOUT)
-//			menutimer++;
-//		    else {
-//			setupmenu = MENU_NONE;
-//		    }
-//		}
-#ifdef HAVE_WIRINGPI_H
-//		piUnlock(LOCK_MENU);
-#endif
 	    }
 	}
 
@@ -238,9 +246,9 @@
 	usleep(10000);
     }
 
-    syslog(LOG_NOTICE, "Thread my_panel_loop stopped");
+    syslog(LOG_NOTICE, "Thread my_keyboard_loop stopped");
     if (debug)
-	fprintf(stdout, "Thread my_panel_loop stopped\n");
+	fprintf(stdout, "Thread my_keyboard_loop stopped\n");
     return 0;
 }
 
--- a/brewco/keyboard.h	Sat Nov 28 13:47:00 2015 +0100
+++ b/brewco/keyboard.h	Sat Nov 28 20:15:38 2015 +0100
@@ -23,12 +23,13 @@
 #define	KEY_ALL		99
 
 
+int keywait(void);
 int keycheck(void);
 
 #ifdef HAVE_WIRINGPI_H
-PI_THREAD (my_panel_loop);
+PI_THREAD (my_keyboard_loop);
 #else
-void *my_panel_loop(void *);
+void *my_keyboard_loop(void *);
 #endif
 
 #endif
--- a/brewco/rdconfig.c	Sat Nov 28 13:47:00 2015 +0100
+++ b/brewco/rdconfig.c	Sat Nov 28 20:15:38 2015 +0100
@@ -263,6 +263,14 @@
                 syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                 return 1;
             }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NUMBER", "%d", unit->number)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ACTIVE", "%d", unit->active)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
 
             if (unit->hlt_sensor) {
                 if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_SENSOR_UUID", "%s", unit->hlt_sensor->uuid)) < 0)) {
@@ -773,6 +781,8 @@
     unit->next = NULL;
     unit->version = 1;
     unit->uuid = unit->name = NULL;
+    unit->number = 0;
+    unit->active = 0;
     unit->hlt_sensor = unit->mlt_sensor = NULL;
     unit->hlt_heater = unit->mlt_heater = unit->mlt_pump = NULL;
     unit->hlt_heater_mltfirst = 0;
@@ -787,7 +797,7 @@
     unit->skip_remove = 0;
     unit->skip_iodine = 0;
     unit->iodine_time = 90;
-    unit->whirlpool = 0;
+    unit->whirlpool = 1;
     unit->PID_hlt = (pid_var *)malloc(sizeof(pid_var));
     unit->PID_mlt = (pid_var *)malloc(sizeof(pid_var));
     InitPID(unit->PID_hlt);
@@ -810,6 +820,18 @@
         if ((!xmlStrcmp(cur->name, (const xmlChar *)"NAME"))) {
             unit->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
         }
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"NUMBER"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->number = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"ACTIVE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->active = ival;
+	    xmlFree(key);
+	}
 
         if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_SENSOR_UUID"))) {
 	    if (unit->hlt_sensor == NULL) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brewco/rdsession.c	Sat Nov 28 20:15:38 2015 +0100
@@ -0,0 +1,371 @@
+/*****************************************************************************
+ * 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 "rdsession.h"
+#include "futil.h"
+#include "xutil.h"
+
+extern int	debug;
+
+
+
+#define MY_ENCODING "utf-8"
+
+
+int do_wrsession(brew_session *brew);
+int do_wrsession(brew_session *brew)
+{
+    int			rc = 0;
+    FILE		*fp;
+    char		*mypath = NULL;
+    xmlTextWriterPtr	writer;
+    xmlBufferPtr	buf;
+
+    /* 
+     * Create a new XML buffer, to which the XML document will be written
+     */
+    if ((buf = xmlBufferCreate()) == NULL) {
+	syslog(LOG_NOTICE, "wrsession: error creating the xml buffer");
+	return 1;
+    }
+
+    /* 
+     * Create a new XmlWriter for memory, with no compression.
+     */
+    if ((writer = xmlNewTextWriterMemory(buf, 0)) == NULL) {
+	syslog(LOG_NOTICE, "wrsession: error creating the xml writer");
+	return 1;
+    }
+
+    /*
+     * Use indentation instead of one long line
+     */
+    if ((rc = xmlTextWriterSetIndent(writer, 2)) < 0) {
+	syslog(LOG_NOTICE, "wrsession: error setting Indent");
+	return 1;
+    }
+
+    /* 
+     * Start the document with the xml default for the version,
+     * encoding ISO 8859-1 and the default for the standalone
+     * declaration. 
+     */
+    if ((rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL)) < 0) {
+	syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterStartDocument");
+	return 1;
+    }
+
+    /* 
+     * Start an element named "BREWCO". Since thist is the first
+     * element, this will be the root element of the document.
+     */
+    if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "BREWCO_BREW")) < 0) {
+	syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterStartElement");
+	return 1;
+    }
+
+    /* 
+     * Add an attribute with name "VERSION" and value "1" to BRWCO.
+     */
+    if ((rc = xmlTextWriterWriteElement(writer, BAD_CAST "VERSION", BAD_CAST "1")) < 0) {
+	syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+	return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "UUID_RECIPE", "%s", brew->uuid_recipe)) < 0) {
+	syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteFormatElement");
+	return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "UUID_UNIT", "%s", brew->uuid_unit)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteFormatElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PREMASH", "%d", brew->premash)) < 0) {
+	syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+	return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MASHSTEP", "%d", brew->mashstep)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MASHSTATE", "%d", brew->mashstate)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "RESTTIME", "%d", brew->resttime)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IODINE", "%d", brew->iodine)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MASHREMOVE", "%d", brew->mashremove)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BOILHEATING", "%d", brew->boilheating)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BOILING", "%d", brew->boiling)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BOILTIMER", "%d", brew->boiltimer)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "COOLING", "%d", brew->cooling)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "WHIRLPOOL", "%d", brew->whirlpool)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "CLEANUP", "%d", brew->cleanup)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "STARTTIME", "%d", (int)brew->starttime)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ENDTIME", "%d", (int)brew->endtime)) < 0) {
+        syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterWriteElement");
+        return 1;
+    }
+
+    /*
+     * All done, close any open elements
+     */
+    if ((rc = xmlTextWriterEndDocument(writer)) < 0) {
+	syslog(LOG_NOTICE, "wrsession: error at xmlTextWriterEndDocument");
+	return 1;
+    }
+    xmlFreeTextWriter(writer);
+
+    /*
+     * Now write the XML configuration
+     */
+    if (getenv((char *)"USER") == NULL) {
+	mypath = xstrcpy((char *)"/root");
+    } else {
+	mypath = xstrcpy(getenv((char *)"HOME"));
+    }
+    mypath = xstrcat(mypath, (char *)"/.brewco/var/");
+    mkdirs(mypath, 0755);
+    mypath = xstrcat(mypath, (char *)"brewing.xml");
+
+    if (debug)
+	fprintf(stdout, "Writing %s\n", mypath);
+
+    if ((fp = fopen(mypath, "w")) == NULL) {
+	syslog(LOG_NOTICE, "could not rewrite %s", mypath);
+	free(mypath);
+	return 1;
+    }
+    free(mypath);
+
+    fprintf(fp, "%s", (const char *) buf->content);
+    fclose(fp);
+    xmlBufferFree(buf);
+
+    return 0;
+}
+
+
+
+int wrsession(brew_session *brew)
+{
+    int		rc;
+
+    rc = do_wrsession(brew);
+    syslog(LOG_NOTICE, "Rewritten brewsession, rc=%d", rc);
+    return rc;
+}
+
+
+
+/*
+ * Returns:
+ *  0 - All is well, session loaded.
+ *  1 - Something went wrong
+ * -1 - No brew session available
+ */
+int rdsession(brew_session *brew) 
+{
+    int		ival;
+    char	*mypath;
+    xmlDocPtr	doc;
+    xmlNodePtr	cur;
+    xmlChar	*key;
+
+    syslog(LOG_NOTICE, "HOME='%s' USER='%s' LOGNAME='%s'", MBSE_SS(getenv((char *)"HOME")), MBSE_SS(getenv((char *)"USER")), MBSE_SS(getenv((char *)"LOGNAME")));
+
+    /*
+     * Search config file
+     */
+    if (getenv((char *)"USER") == NULL) {
+	mypath = xstrcpy((char *)"/root");
+    } else {
+    	mypath = xstrcpy(getenv((char *)"HOME"));
+    }
+    mypath = xstrcat(mypath, (char *)"/.brewco/var/");
+    mkdirs(mypath, 0755);
+    mypath = xstrcat(mypath, (char *)"brewing.xml");
+
+    /*
+     * See if we have a brewing state file.
+     */
+    if (file_exist(mypath, W_OK)) {
+	syslog(LOG_NOTICE, "rdsession: %s not found, good.", mypath);
+	free(mypath);
+	return -1;
+    }
+
+    if ((doc = xmlParseFile(mypath)) == NULL) {
+	syslog(LOG_NOTICE, "rdsession: %s not found, should not happen.", mypath);
+	free(mypath);
+	return -1;
+    }
+    syslog(LOG_NOTICE, "rdsession: using %s", mypath);
+
+    if ((cur = xmlDocGetRootElement(doc)) == NULL) {
+	syslog(LOG_NOTICE, "XML file %s empty.", mypath);
+	xmlFreeDoc(doc);
+	return 1;
+    }
+    if (xmlStrcmp(cur->name, (const xmlChar*)"BREWCO")) {
+	syslog(LOG_NOTICE, "XML file %s is not a valid configuration file.", mypath);
+	xmlFreeDoc(doc);
+	return 1;
+    }
+
+    /*
+     * Parse session
+     */
+    cur = cur->xmlChildrenNode;
+    while (cur != NULL) {
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"UUID_RECIPE"))) {
+	    brew->uuid_recipe = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"UUID_UNIT"))) {
+	    brew->uuid_unit = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PREMASH"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->premash = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"MASHSTEP"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->mashstep = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"MASHSTATE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->mashstate = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"RESTTIME"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->resttime = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"IODINE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->iodine = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"MASHREMOVE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->mashremove = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"BOILHEATING"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->boilheating = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"BOILING"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->boiling = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"BOILTIMER"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->boiltimer = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"COOLING"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->cooling = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"WHIRLPOOL"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->whirlpool = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"CLEANUP"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->cleanup = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"STARTTIME"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->starttime = (time_t)ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"ENDTIME"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		brew->endtime = (time_t)ival;
+	    xmlFree(key);
+	}
+	cur = cur->next;
+    }
+    xmlFreeDoc(doc);
+
+    free(mypath);
+    mypath = NULL;
+
+    return 0;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brewco/rdsession.h	Sat Nov 28 20:15:38 2015 +0100
@@ -0,0 +1,9 @@
+#ifndef	_RDSESSION_H
+#define	_RDSESSION_H
+
+
+int  rdsession(brew_session *brew);
+int  wrsession(brew_session *brew);
+
+
+#endif

mercurial