More configuration items added.

Thu, 26 Nov 2015 22:47:42 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Thu, 26 Nov 2015 22:47:42 +0100
changeset 435
4b1ed6897d80
parent 434
eb724767860d
child 436
4df9ae3095f8

More configuration items added.

brewco/Makefile file | annotate | diff | comparison | revisions
brewco/brewco.h file | annotate | diff | comparison | revisions
brewco/devices.c file | annotate | diff | comparison | revisions
brewco/keyboard.c file | annotate | diff | comparison | revisions
brewco/keyboard.h file | annotate | diff | comparison | revisions
brewco/pid.c file | annotate | diff | comparison | revisions
brewco/pid.h file | annotate | diff | comparison | revisions
brewco/rdconfig.c file | annotate | diff | comparison | revisions
--- a/brewco/Makefile	Wed Nov 25 22:49:35 2015 +0100
+++ b/brewco/Makefile	Thu Nov 26 22:47:42 2015 +0100
@@ -62,5 +62,6 @@
 lcd-pcf8574.o: brewco.h lcd-pcf8574.h slcd.h
 pid.o: brewco.h pid.h
 xutil.o: brewco.h xutil.h
+keyboard.o: brewco.h lcd-pcf8574.h slcd.h keyboard.h
 rdconfig.o: rdconfig.h brewco.h futil.h xutil.h
 # End of generated dependencies
--- a/brewco/brewco.h	Wed Nov 25 22:49:35 2015 +0100
+++ b/brewco/brewco.h	Thu Nov 26 22:47:42 2015 +0100
@@ -83,6 +83,27 @@
 #define MBSE_SS(x) (x)?(x):"(null)"
 
 
+/*
+ * Sensor strcuture
+ */
+typedef struct _sensor_var {
+    char		uuid[37];		/* sensor uuid			*/
+    int			state;			/* sensor state			*/
+    int			value;			/* sensor value			*/
+} sensor_var;
+
+
+
+/*
+ * Switch structure
+ */
+typedef struct _switch_var {
+    char		uuid[37];		/* switch uuid			*/
+    int			value;			/* switch value (0..100)	*/
+    int			delay;			/* switch delay			*/
+} switch_var;
+
+
 
 /*
  * Brewing units. The sensors of the units are connected via the 1-wire bus.
@@ -94,22 +115,24 @@
     int                 version;                /* Record version               */
     char		*uuid;			/* uuid code			*/
     char                *name;                  /* Unit name                    */
-    char                *hlt_sensor_address;    /* HLT sensor address           */
-    int                 hlt_sensor_state;       /* HLT sensor state             */
-    int                 hlt_sensor_value;       /* HLT sensor value             */
-    char		*hlt_heater_address;	/* HLT heater address		*/
-    int			hlt_heater_state;	/* HLT heater state 0..100	*/
-    int			hlt_heater_delay;	/* HLT heater delay / 15 sec	*/
+    sensor_var		*hlt_sensor;		/* HLT sensor			*/
+    switch_var		*hlt_heater;		/* HLT heater			*/
     int			hlt_heater_mltfirst;	/* HLT heater MLT high priority	*/
-    char                *mlt_sensor_address;    /* MLT sensor address           */
-    int                 mlt_sensor_state;       /* MLT sensor state             */
-    int                 mlt_sensor_value;       /* MLT sensor value             */
-    char		*mlt_heater_address;	/* MLT heater address		*/
-    int			mlt_heater_state;	/* MLT heater state 0..100	*/
-    int			mlt_heater_delay;	/* MLT heater delay / 15 sec	*/
-    char		*mlt_pump_address;	/* MLT pump address		*/
-    int			mlt_pump_state;		/* MLT pump state 0..100	*/
-    int			mlt_pump_delay;		/* MLT_pump_delay		*/
+    sensor_var		*mlt_sensor;		/* MLT sensor			*/
+    switch_var		*mlt_heater;		/* MLT heater			*/
+    switch_var		*mlt_pump;		/* MLT pump			*/
+    int			pump_cycle;		/* 5..15 minutes 		*/
+    int			pump_rest;		/* 1..5 minutes			*/
+    int			pump_premash;		/* 0/1				*/
+    int			pump_onmash;		/* 0/1				*/
+    int			pump_mashout;		/* 0/1				*/
+    int			pump_onboil;		/* 0/1 pump during boiling	*/
+    int			pump_stop;		/* 80..105 C			*/
+    int			skip_add;		/* 0/1 skip Add phase		*/
+    int			skip_remove;		/* 0/1 skip Remove phase	*/
+    int			skip_iodine;		/* 0/1 skip Iodine test		*/
+    int			iodine_time;		/* 0..90 minutes		*/
+    int			whirlpool;		/* off/cold/hot			*/
     pid_var		*PID_hlt;		/* HLT PID			*/
     pid_var		*PID_mlt;		/* MLT PID			*/
 } units_list;
@@ -161,6 +184,48 @@
 #define DEVDIR_INTERN           6               /* Internal function            */
 
 
+
+/*
+ * Recipes.
+ */
+typedef struct _mash_step {
+    char		name[21];		/* Step name			*/
+    int			min;			/* Minimum temperature		*/
+    int			max;			/* Maximum temperature		*/
+    int			canskip;		/* 0/1 can we skip this step	*/
+    int			setpoint;		/* Temperature setpoint		*/
+    int			skip;			/* Skip this step		*/
+    int			duration;		/* Step duration		*/
+} mash_step;
+
+// mash-in	20	80	noskip
+// fitasi	25	55	canskip
+// glucanasi	35	50	canskip
+// proteasi	45	60	canskip
+// B-amilasi	50	70	canskip
+// A-amilasi 1	60	76	canskip
+// A-amilasi 2	60	76	noskip
+// mash-out	75	80	noskip
+
+typedef struct _hop_addition {
+    char		name[21];		/* Hop name			*/
+    int			boil_duration;		/* -1=fwh, 0..boiltime		*/
+} hop_addition;
+
+typedef struct _a_recipe {
+    char		uuid[37];		/* Recipe uuid			*/
+    char		code[21];		/* Recipe code			*/
+    char		name[21];		/* Recipe name			*/
+    mash_step		mash[8];		/* 8 mash steps			*/
+    hop_addition	hops[10];		/* 10 hop additions		*/
+    int			boiltime;		/* 1..240 minutes		*/
+    time_t		started;		/* Start time			*/
+    time_t		endtime;		/* Ending time			*/
+} a_recipe;
+
+
+
+
 #ifdef USE_SIMULATOR
 
 /*
@@ -198,12 +263,7 @@
     char		*name;			/* Configuration name		*/
     int			my_port;		/* my client/server port	*/
     unsigned char	tempFormat;		/* Temperature format, C or F	*/
-    char                *temp_address;          /* Environment temperature      */
-    int                 temp_state;             /* 0=ok, 1=missing, 2=error     */
-    int                 temp_value;             /* Air temperature in C * 1000  */
-    char                *hum_address;           /* Environment huminity         */
-    int                 hum_state;              /* 0=ok, 1=missing, 2=error     */
-    int                 hum_value;              /* Huminity in % * 1000         */
+    sensor_var		*roomtemp;		/* Environment temperature      */
     int			lcd_cols;		/* LCD display columns		*/
     int			lcd_rows;		/* LCD display rows		*/
     int			lcd_address;		/* LCD display i2c address	*/
--- a/brewco/devices.c	Wed Nov 25 22:49:35 2015 +0100
+++ b/brewco/devices.c	Thu Nov 26 22:47:42 2015 +0100
@@ -438,31 +438,57 @@
 	    	ndev->subdevice = i;
 	    	ndev->gpiopin = pin;
 	    	ndev->timestamp = time(NULL);
-		if (i == PANEL_RETURN) {
-		    ndev->direction = DEVDIR_IN_BIN;
-		    ndev->inuse = 1;
-		    ndev->comment = xstrcpy((char *)"Frontpanel Return");
-		} else if (i == PANEL_ENTER) {
-		    ndev->direction = DEVDIR_IN_BIN;
-		    ndev->inuse = 1;
-		    ndev->comment = xstrcpy((char *)"Frontpanel Enter key");
-		} else if (i == PANEL_DOWN) {
-		    ndev->direction = DEVDIR_IN_BIN;
-		    ndev->inuse = 1;
-		    ndev->comment = xstrcpy((char *)"Frontpanel Down key");
-		} else if (i == PANEL_UP) {
-		    ndev->direction = DEVDIR_IN_BIN;
-		    ndev->inuse = 1;
-		    ndev->comment = xstrcpy((char *)"Frontpanel Up key");
-		} else if (i == 7) {
-		    ndev->direction = DEVDIR_INTERN;
-		    ndev->inuse = 1;
-		    ndev->comment = xstrcpy((char *)"1-Wire bus");
-	    	} else {
-		    ndev->direction = DEVDIR_IN_BIN;
-		    ndev->inuse = 0;
-		    ndev->comment = xstrcpy((char *)"Raspberry GPIO");
-	    	}
+		switch (i) {
+		    case 0:
+			    	ndev->direction = DEVDIR_OUT_ANALOG;
+				ndev->inuse = 1;
+				ndev->comment = xstrcpy((char *)"MLT heater SSR");
+				break;
+		    case 1:
+			    	ndev->direction = DEVDIR_OUT_ANALOG;
+				ndev->inuse = 1;
+				ndev->comment = xstrcpy((char *)"MLT heater PWM");
+				break;
+		    case 2:
+				ndev->direction = DEVDIR_OUT_ANALOG;
+				ndev->inuse = 1;
+				ndev->comment = xstrcpy((char *)"MLT pump relay");
+				break;
+		    case PANEL_RETURN:
+		    		ndev->direction = DEVDIR_IN_BIN;
+		    		ndev->inuse = 1;
+		    		ndev->comment = xstrcpy((char *)"Frontpanel Return");
+				break;
+		    case PANEL_ENTER:
+		    		ndev->direction = DEVDIR_IN_BIN;
+		    		ndev->inuse = 1;
+		    		ndev->comment = xstrcpy((char *)"Frontpanel Enter key");
+				break;
+		    case PANEL_DOWN:
+		    		ndev->direction = DEVDIR_IN_BIN;
+		    		ndev->inuse = 1;
+		    		ndev->comment = xstrcpy((char *)"Frontpanel Down key");
+				break;
+		    case PANEL_UP:
+		    		ndev->direction = DEVDIR_IN_BIN;
+		    		ndev->inuse = 1;
+		    		ndev->comment = xstrcpy((char *)"Frontpanel Up key");
+				break;
+		    case 7:
+		    		ndev->direction = DEVDIR_INTERN;
+		    		ndev->inuse = 1;
+		    		ndev->comment = xstrcpy((char *)"1-Wire bus");
+				break;
+		    case 8:
+				ndev->direction = DEVDIR_OUT_BIN;
+				ndev->inuse = 1;
+				ndev->comment = xstrcpy((char *)"Buzzer");
+				break;
+	    	    default:
+		    		ndev->direction = DEVDIR_IN_BIN;
+		    		ndev->inuse = 0;
+		    		ndev->comment = xstrcpy((char *)"Raspberry GPIO");
+		}
 	    	pin++;
 
 	    	if (Config.devices == NULL) {
@@ -491,7 +517,7 @@
     }
 
     if (found == FALSE) {
-	subdevices = 5;
+	subdevices = 6;
 	for (i = 0; i < subdevices; i++) {
 	    ndev = (devices_list *)malloc(sizeof(devices_list));
 	    ndev->next = NULL;
@@ -528,6 +554,10 @@
 			ndev->address = xstrcpy((char *)"SimMLTheater");
 			ndev->description = xstrcpy((char *)"Simulated MLT heater");
 			break;
+		case 5:	ndev->direction = DEVDIR_OUT_ANALOG;
+			ndev->address = xstrcpy((char *)"SimMLTpump");
+			ndev->description = xstrcpy((char *)"Simulated MLT pump");
+			break;
 	    }
 
 	    if (Config.devices == NULL) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brewco/keyboard.c	Thu Nov 26 22:47:42 2015 +0100
@@ -0,0 +1,243 @@
+/*****************************************************************************
+ * 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 "lcd-pcf8574.h"
+#include "slcd.h"
+#include "keyboard.h"
+
+
+
+/*
+ * 10 Milliseconds counts for a key to be short or long pressed.
+ */
+#define PRESS_NORMAL    5
+#define PRESS_LONG      200
+
+/*
+ * LCD timeout in seconds
+ */
+#define LCD_SLEEP       120
+
+/*
+ * Menu timeout in seconds
+ */
+#define MENU_TIMEOUT    60
+
+
+
+extern int		my_shutdown;
+extern int		debug;
+extern int		setupmenu;
+extern uint16_t		keys;
+extern uint16_t		leds;
+extern int		slcdHandle;
+
+int			Key_Enter = FALSE;
+int			Key_Return = FALSE;
+int			Key_Up = FALSE;
+int			Key_Down = FALSE;
+
+int			previous_key = KEY_NONE;
+int			menutimer = 0;
+
+
+int keypressed(void);
+
+
+/*
+ * Check for a key. Return last pressed key or none.
+ */
+int keycheck(void)
+{
+    int		key, retkey = KEY_NONE;
+
+    key = keypressed();
+    if ((key == KEY_NONE) && (previous_key != KEY_NONE)) {
+	retkey = previous_key;
+    }
+
+    previous_key = key;
+    return retkey;
+}
+
+
+
+int keypressed(void)
+{
+    if (Key_Enter && Key_Up && Key_Down && Key_Return)
+	return KEY_ALL;
+    if (Key_Up)
+	return KEY_UP;
+    if (Key_Down)
+	return KEY_DOWN;
+    if (Key_Enter)
+	return KEY_ENTER;
+    if (Key_Return)
+	return KEY_RETURN;
+    return KEY_NONE;
+}
+
+
+#ifdef HAVE_WIRINGPI_H
+PI_THREAD (my_panel_loop)
+#else
+void *my_panel_loop(void *threadid)
+#endif
+{
+    int		Return = 0, Enter = 0, Up = 0, Down = 0, Backlight = LCD_SLEEP, AnyKey = FALSE;
+    time_t	Last = (time_t)0, Now;
+
+#ifdef HAVE_WIRINGPI_H
+    pinMode(PANEL_RETURN, INPUT);
+    pinMode(PANEL_ENTER, INPUT);
+    pinMode(PANEL_UP, INPUT);
+    pinMode(PANEL_DOWN, INPUT);
+#endif
+
+    syslog(LOG_NOTICE, "Thread my_panel_loop started");
+
+    /*
+     * Loop forever until the external shutdown variable is set.
+     */
+    for (;;) {
+	if (my_shutdown)
+	    break;
+
+#ifdef HAVE_WIRINGPI_H
+	if (digitalRead(PANEL_ENTER) && ((keys & 0x0001) == 0)) {
+#else
+	if ((keys & 0x0001) == 0) {
+#endif
+	    Enter = 0;
+	    Key_Enter = FALSE;
+	} else {
+	    Enter++;
+	    if (Enter > PRESS_NORMAL)
+		Key_Enter = TRUE;
+	}
+
+#ifdef HAVE_WIRINGPI_H
+	if (digitalRead(PANEL_RETURN) && ((keys & 0x0002) == 0)) {
+#else
+	if ((keys & 0x0002) == 0) {
+#endif
+	    Return = 0;
+	    Key_Return = FALSE;
+	} else {
+	    Return++;
+	    if (Return > PRESS_NORMAL)
+	    	Key_Return = TRUE;
+	}
+
+#ifdef HAVE_WIRINGPI_H
+	if (digitalRead(PANEL_UP) && ((keys & 0x0008) == 0)) {
+#else
+	if ((keys & 0x0008) == 0) {
+#endif
+	    Up = 0;
+	    Key_Up = FALSE;
+	} else {
+	    Up++;
+	    if (Up > PRESS_NORMAL)
+		Key_Up = TRUE;
+	}
+
+#ifdef HAVE_WIRINGPI_H
+	if (digitalRead(PANEL_DOWN) && ((keys & 0x0004) == 0)) {
+#else
+	if ((keys & 0x0004) == 0) {
+#endif
+	    Down = 0;
+	    Key_Down = FALSE;
+	} else {
+	    Down++;
+	    if (Down > PRESS_NORMAL)
+		Key_Down = TRUE;
+	}
+
+	if (Key_Enter || Key_Return || Key_Up || Key_Down) {
+	    AnyKey = TRUE;
+	    /*
+	     * Any key is pressed.
+	     */
+#ifdef HAVE_WIRINGPI_H
+	    piLock(LOCK_LCD);
+#endif
+	    setBacklight(1);
+#ifdef HAVE_WIRINGPI_H
+	    piUnlock(LOCK_LCD);
+#endif
+	    Backlight = LCD_SLEEP;
+	    menutimer = 0;
+	} else {
+	    /*
+	     * No key pressed.
+	     */
+	    AnyKey = FALSE;
+	}
+
+	Now = time(NULL);
+	if (Now != Last) {
+	    Last = Now;
+
+	    if (AnyKey == FALSE) {
+		if (Backlight == 1) {
+#ifdef HAVE_WIRINGPI_H
+		    piLock(LOCK_LCD);
+#endif
+		    setBacklight(0);
+#ifdef HAVE_WIRINGPI_H
+		    piUnlock(LOCK_LCD);
+#endif
+		}
+		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
+	    }
+	}
+
+	/*
+	 * Loop 10 milliseconds
+	 */
+	usleep(10000);
+    }
+
+    syslog(LOG_NOTICE, "Thread my_panel_loop stopped");
+    return 0;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brewco/keyboard.h	Thu Nov 26 22:47:42 2015 +0100
@@ -0,0 +1,34 @@
+#ifndef	_KEYBOARD_H
+#define	_KEYBOARD_H
+
+
+
+/*
+ * GPIO pins for the push buttons.
+ */
+#define	PANEL_RETURN	3
+#define	PANEL_ENTER	4
+#define	PANEL_DOWN	5
+#define	PANEL_UP	6
+
+
+/*
+ * Key names
+ */
+#define	KEY_NONE	0
+#define	KEY_UP		1
+#define	KEY_DOWN	2
+#define	KEY_RETURN	3
+#define	KEY_ENTER	4
+#define	KEY_ALL		99
+
+
+int keycheck(void);
+
+#ifdef HAVE_WIRINGPI_H
+PI_THREAD (my_panel_loop);
+#else
+void *my_panel_loop(void *);
+#endif
+
+#endif
--- a/brewco/pid.c	Wed Nov 25 22:49:35 2015 +0100
+++ b/brewco/pid.c	Thu Nov 26 22:47:42 2015 +0100
@@ -31,6 +31,7 @@
     pid->pGain = pid->iGain = pid->dGain = 0.0;
     pid->Mode = PID_MODE_NONE;
     pid->iMax = 100.0;
+    pid->Times = PID_TIMES;
 }
 
 
--- a/brewco/pid.h	Wed Nov 25 22:49:35 2015 +0100
+++ b/brewco/pid.h	Thu Nov 26 22:47:42 2015 +0100
@@ -22,6 +22,7 @@
 	double		SetP;		/* Set point					*/
 	double		OutP;		/* Output of PID algorithm			*/
 	int		Mode;		/* Value is 'PID_AUTO' if loop is automatic	*/
+	int		Times;		/* Calculations per minute			*/
 } pid_var;
 
 
--- a/brewco/rdconfig.c	Wed Nov 25 22:49:35 2015 +0100
+++ b/brewco/rdconfig.c	Thu Nov 26 22:47:42 2015 +0100
@@ -31,10 +31,11 @@
 #define MY_ENCODING "utf-8"
 
 const char	TEMPSTATE[3][8] = { "OK", "MISSING", "ERROR" };
-const char	DEVTYPE[8][6] = { "NA", "W1", "GPIO", "RC433", "DHT", "I2C", "SPI", "SIM" };
+const char	DEVTYPE[6][5] = { "NA", "W1", "GPIO", "I2C", "SPI", "SIM" };
 const char	DEVPRESENT[4][6] = { "UNDEF", "NO", "YES", "ERROR" };
 const char	DEVDIR[7][11] = { "UNDEF", "IN_BIN", "OUT_BIN", "IN_ANALOG", "OUT_ANALOG", "OUT_PWM", "INTERN" };
 const char	PIDMODE[3][5] = { "NONE", "AUTO", "BOO" };
+const char	WHIRLPOOL_TYPE[3][5] = { "OFF", "COLD", "HOT" };
 
 
 void killconfig(void)
@@ -51,14 +52,9 @@
 
     Config.my_port = 6554;
     Config.tempFormat = 'C';
-    if (Config.temp_address)
-        free(Config.temp_address);
-    if (Config.hum_address)
-        free(Config.hum_address);
-    Config.temp_address = Config.hum_address = NULL;
-    Config.temp_value = 20000;
-    Config.temp_state = Config.hum_state = 1;   // missing
-    Config.hum_value = 50000;
+    if (Config.roomtemp)
+        free(Config.roomtemp);
+    Config.roomtemp = NULL;
     Config.lcd_cols = 20;
     Config.lcd_rows = 4;
 
@@ -67,16 +63,20 @@
             free(unit->uuid);
         if (unit->name)
             free(unit->name);
-        if (unit->hlt_sensor_address)
-            free(unit->hlt_sensor_address);
-        if (unit->mlt_sensor_address)
-            free(unit->mlt_sensor_address);
-        if (unit->hlt_heater_address)
-            free(unit->hlt_heater_address);
-        if (unit->mlt_heater_address)
-            free(unit->mlt_heater_address);
-        if (unit->mlt_pump_address)
-            free(unit->mlt_pump_address);
+        if (unit->hlt_sensor)
+            free(unit->hlt_sensor);
+        if (unit->mlt_sensor)
+            free(unit->mlt_sensor);
+        if (unit->hlt_heater)
+            free(unit->hlt_heater);
+        if (unit->mlt_heater)
+            free(unit->mlt_heater);
+        if (unit->mlt_pump)
+            free(unit->mlt_pump);
+	if (unit->PID_hlt)
+	    free(unit->PID_hlt);
+	if (unit->PID_mlt)
+	    free(unit->PID_mlt);
         free(unit);
     }
     Config.units = NULL;
@@ -184,29 +184,19 @@
 	syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
 	return 1;
     }
-    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "TEMP_ADDRESS", "%s", Config.temp_address)) < 0) {
-        syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-        return 1;
-    }
-    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "TEMP_STATE", "%d", Config.temp_state)) < 0) {
-        syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-        return 1;                           
-    }
-    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "TEMP_VALUE", "%d", Config.temp_value)) < 0) {
-        syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-        return 1;
-    }
-    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HUM_ADDRESS", "%s", Config.hum_address)) < 0) {
-        syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-        return 1;
-    }   
-    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HUM_STATE", "%d", Config.hum_state)) < 0) {
-        syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-        return 1;    
-    }   
-    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HUM_VALUE", "%d", Config.hum_value)) < 0) {
-        syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-        return 1;
+    if (Config.roomtemp) {
+    	if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ROOMTEMP_UUID", "%s", Config.roomtemp->uuid)) < 0) {
+            syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+            return 1;
+    	}
+    	if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ROOMTEMP_STATE", "%d", Config.roomtemp->state)) < 0) {
+            syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+            return 1;                           
+    	}
+    	if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ROOMTEMP_VALUE", "%d", Config.roomtemp->value)) < 0) {
+            syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+            return 1;
+    	}
     }
 
     /* 
@@ -285,80 +275,134 @@
                 return 1;
             }
 
-            if (unit->hlt_sensor_address) {
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_SENSOR_ADDRESS", "%s", unit->hlt_sensor_address)) < 0)) {
+            if (unit->hlt_sensor) {
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_SENSOR_UUID", "%s", unit->hlt_sensor->uuid)) < 0)) {
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_SENSOR_STATE", "%d", unit->hlt_sensor_state)) < 0)) {
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_SENSOR_STATE", "%d", unit->hlt_sensor->state)) < 0)) {
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_SENSOR_VALUE", "%d", unit->hlt_sensor_value)) < 0)) {
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_SENSOR_VALUE", "%d", unit->hlt_sensor->value)) < 0)) {
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
             }
 
-            if (unit->hlt_heater_address) {
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_HEATER_ADDRESS", "%s", unit->hlt_heater_address)) < 0)) {
+            if (unit->hlt_heater) {
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_HEATER_UUID", "%s", unit->hlt_heater->uuid)) < 0)) {
+                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+                    return 1;
+                }
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_HEATER_VALUE", "%d", unit->hlt_heater->value)) < 0)) {
+                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+                    return 1;
+                }
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_HEATER_DELAY", "%d", unit->hlt_heater->delay)) < 0)) {
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_HEATER_STATE", "%d", unit->hlt_heater_state)) < 0)) {
+            }
+
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_HEATER_MLTFIRST", "%d", unit->hlt_heater_mltfirst)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+
+            if (unit->mlt_sensor) {
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_SENSOR_UUID", "%s", unit->mlt_sensor->uuid)) < 0)) {
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HLT_HEATER_DELAY", "%d", unit->hlt_heater_delay)) < 0)) {
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_SENSOR_STATE", "%d", unit->mlt_sensor->state)) < 0)) {
+                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+                    return 1;
+                }
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_SENSOR_VALUE", "%d", unit->mlt_sensor->value)) < 0)) {
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
             }
 
-            if (unit->mlt_sensor_address) {
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_SENSOR_ADDRESS", "%s", unit->mlt_sensor_address)) < 0)) {
+            if (unit->mlt_heater) {
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_HEATER_UUID", "%s", unit->mlt_heater->uuid)) < 0)) {
+                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+                    return 1;
+                }
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_HEATER_VALUE", "%d", unit->mlt_heater->value)) < 0)) {
+                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+                    return 1;
+                }
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_HEATER_DELAY", "%d", unit->mlt_heater->delay)) < 0)) {
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_SENSOR_STATE", "%d", unit->mlt_sensor_state)) < 0)) {
+            }
+
+            if (unit->mlt_pump) {
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_PUMP_UUID", "%s", unit->mlt_pump->uuid)) < 0)) {
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_SENSOR_VALUE", "%d", unit->mlt_sensor_value)) < 0)) {
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_PUMP_VALUE", "%d", unit->mlt_pump->value)) < 0)) {
+                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+                    return 1;
+                }
+                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_PUMP_DELAY", "%d", unit->mlt_pump->delay)) < 0)) {
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
             }
 
-            if (unit->mlt_heater_address) {
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_HEATER_ADDRESS", "%s", unit->mlt_heater_address)) < 0)) {
-                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-                    return 1;
-                }
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_HEATER_STATE", "%d", unit->mlt_heater_state)) < 0)) {
-                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-                    return 1;
-                }
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_HEATER_DELAY", "%d", unit->mlt_heater_delay)) < 0)) {
-                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-                    return 1;
-                }
-            }
-
-            if (unit->mlt_pump_address) {
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_PUMP_ADDRESS", "%s", unit->mlt_pump_address)) < 0)) {
-                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-                    return 1;
-                }
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_PUMP_STATE", "%d", unit->mlt_pump_state)) < 0)) {
-                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-                    return 1;
-                }
-                if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MLT_PUMP_DELAY", "%d", unit->mlt_pump_delay)) < 0)) {
-                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-                    return 1;
-                }
-            }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PUMP_CYCLE", "%d", unit->pump_cycle)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PUMP_REST", "%d", unit->pump_rest)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PUMP_PREMASH", "%d", unit->pump_premash)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PUMP_ONMASH", "%d", unit->pump_onmash)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PUMP_MASHOUT", "%d", unit->pump_mashout)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PUMP_ONBOIL", "%d", unit->pump_onboil)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PUMP_STOP", "%d", unit->pump_stop)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "SKIP_ADD", "%d", unit->skip_add)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "SKIP_REMOVE", "%d", unit->skip_remove)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "SKIP_IODINE", "%d", unit->skip_iodine)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IODINE_TIME", "%d", unit->iodine_time)) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
+	    if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "WHIRLPOOL", "%s", WHIRLPOOL_TYPE[unit->whirlpool])) < 0)) {
+		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		return 1;
+	    }
 
             if (unit->PID_hlt) {
                 if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PID_HLT_IMAX", "%.2f", unit->PID_hlt->iMax)) < 0) {
@@ -405,10 +449,10 @@
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
-                if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PID_HLT_TYPE", "HEAT")) < 0) {
-                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-                    return 1;
-                }
+		if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PID_HLT_TIMES", "%d", unit->PID_hlt->Times)) < 0)) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;
+		}
             }
 
             if (unit->PID_mlt) {
@@ -456,10 +500,10 @@
                     syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
                     return 1;
                 }
-                if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PID_MLT_TYPE", "HEAT")) < 0) {
-                    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-                    return 1;
-                }
+		if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "PID_MLT_TIMES", "%d", unit->PID_mlt->Times)) < 0)) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;
+		}
             }
 
             if ((rc = xmlTextWriterEndElement(writer)) < 0) {
@@ -707,11 +751,22 @@
     unit = (units_list *)malloc(sizeof(units_list));
     unit->next = NULL;
     unit->version = 1;
-    unit->uuid = unit->name = unit->hlt_sensor_address = unit->hlt_heater_address = unit->mlt_sensor_address = \
-                 unit->mlt_heater_address = unit->mlt_pump_address = NULL;
-    unit->hlt_sensor_state = unit->mlt_sensor_state = 1; // missing
-    unit->hlt_heater_state = unit->mlt_heater_state = unit->mlt_pump_state = 0;
-    unit->hlt_heater_delay = unit->mlt_heater_delay = unit->mlt_pump_delay = 20;     /* 5 minutes delay */
+    unit->uuid = unit->name = NULL;
+    unit->hlt_sensor = unit->mlt_sensor = NULL;
+    unit->hlt_heater = unit->mlt_heater = unit->mlt_pump = NULL;
+    unit->hlt_heater_mltfirst = 0;
+    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 = 0;
     unit->PID_hlt = (pid_var *)malloc(sizeof(pid_var));
     unit->PID_mlt = (pid_var *)malloc(sizeof(pid_var));
     InitPID(unit->PID_hlt);
@@ -735,65 +790,200 @@
             unit->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
         }
 
-        if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_SENSOR_ADDRESS"))) {
-            unit->hlt_sensor_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+        if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_SENSOR_UUID"))) {
+	    if (unit->hlt_sensor == NULL) {
+		unit->hlt_sensor = (sensor_var *)malloc(sizeof(sensor_var));
+    		unit->hlt_sensor->uuid[0] = '\0';
+        	unit->hlt_sensor->state = 1;        // missing
+	    	unit->hlt_sensor->value = 0;
+	    }
+            snprintf(unit->hlt_sensor->uuid, 36, "%s", xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
         }
         if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_SENSOR_STATE"))) {
             key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
             if (sscanf((const char *)key, "%d", &ival) == 1)
-                unit->hlt_sensor_state = ival;
+                unit->hlt_sensor->state = ival;
             xmlFree(key);
         }
         if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_SENSOR_VALUE"))) {
             key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
             if (sscanf((const char *)key, "%d", &ival) == 1)
-                unit->hlt_sensor_value = ival;
+                unit->hlt_sensor->value = ival;
             xmlFree(key);                           
         }
-        if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_HEATER_ADDRESS"))) {
-            unit->hlt_heater_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+
+        if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_HEATER_UUID"))) {
+	    if (unit->hlt_heater == NULL) {
+		unit->hlt_heater = (switch_var *)malloc(sizeof(switch_var));
+		unit->hlt_heater->uuid[0] = '\0';
+		unit->hlt_heater->value = 0;
+		unit->hlt_heater->delay = 1;	// 15 seconds
+	    }
+            snprintf(unit->hlt_heater->uuid, 36, "%s", xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
         }
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_HEATER_VALUE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->hlt_heater->value = ival;
+	    xmlFree(key);
+	}
         if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_HEATER_DELAY"))) {
             key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
             if (sscanf((const char *)key, "%d", &ival) == 1)
-                unit->hlt_heater_delay = ival;
+                unit->hlt_heater->delay = ival;
             xmlFree(key);
         }
 
-        if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_SENSOR_ADDRESS"))) {
-            unit->mlt_sensor_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"HLT_HEATER_MLTFIRST"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->hlt_heater_mltfirst = ival;
+	    xmlFree(key);
+	}
+
+        if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_SENSOR_UUID"))) {
+	    if (unit->mlt_sensor == NULL) {
+		unit->mlt_sensor = (sensor_var *)malloc(sizeof(sensor_var));
+		unit->mlt_sensor->uuid[0] = '\0';
+		unit->mlt_sensor->state = 1;        // missing
+		unit->mlt_sensor->value = 0;
+	    }
+            snprintf(unit->mlt_sensor->uuid, 36, "%s", xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
         }
         if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_SENSOR_STATE"))) {
             key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
             if (sscanf((const char *)key, "%d", &ival) == 1)
-                unit->mlt_sensor_state = ival;
+                unit->mlt_sensor->state = ival;
             xmlFree(key);
         }
         if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_SENSOR_VALUE"))) {
             key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
             if (sscanf((const char *)key, "%d", &ival) == 1)
-                unit->mlt_sensor_value = ival;
+                unit->mlt_sensor->value = ival;
             xmlFree(key);
         }
-        if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_HEATER_ADDRESS"))) {
-            unit->mlt_heater_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+
+        if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_HEATER_UUID"))) {
+	    if (unit->mlt_heater == NULL) {
+		unit->mlt_heater = (switch_var *)malloc(sizeof(switch_var));
+		unit->mlt_heater->uuid[0] = '\0';
+		unit->mlt_heater->value = 0;
+		unit->mlt_heater->delay = 1;    // 15 seconds
+	    }
+	    snprintf(unit->mlt_heater->uuid, 36, "%s", xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
         }
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_HEATER_VALUE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->mlt_heater->value = ival;
+	    xmlFree(key);
+	}
         if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_HEATER_DELAY"))) {
             key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
             if (sscanf((const char *)key, "%d", &ival) == 1)
-                unit->mlt_heater_delay = ival;
+                unit->mlt_heater->delay = ival;
             xmlFree(key);
         }
-        if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_PUMP_ADDRESS"))) {
-            unit->mlt_pump_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+
+        if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_PUMP_UUID"))) {
+	    if (unit->mlt_pump == NULL) {
+		unit->mlt_pump = (switch_var *)malloc(sizeof(switch_var));
+		unit->mlt_pump->uuid[0] = '\0';
+		unit->mlt_pump->value = 0;
+		unit->mlt_pump->delay = 1;    // 15 seconds
+	    }
+	    snprintf(unit->mlt_pump->uuid, 36, "%s", xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
         }
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_PUMP_VALUE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->mlt_pump->value = ival;
+	    xmlFree(key);
+	}
         if ((!xmlStrcmp(cur->name, (const xmlChar *)"MLT_PUMP_DELAY"))) {
             key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
             if (sscanf((const char *)key, "%d", &ival) == 1)
-                unit->mlt_pump_delay = ival;
+                unit->mlt_pump->delay = ival;
             xmlFree(key);
         }
 
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PUMP_CYCLE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->pump_cycle = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PUMP_REST"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->pump_rest = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PUMP_PREMASH"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->pump_premash = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PUMP_ONMASH"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->pump_onmash = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PUMP_MASHOUT "))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->pump_mashout = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PUMP_ONBOIL"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->pump_onboil = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PUMP_STOP"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->pump_stop = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"SKIP_ADD"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+	    	unit->skip_add = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"SKIP_REMOVE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->skip_remove = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"SKIP_IODINE"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->skip_iodine = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"IODINE_TIME"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    if (sscanf((const char *)key, "%d", &ival) == 1)
+		unit->iodine_time = ival;
+	    xmlFree(key);
+	}
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"WHIRLPOOL"))) {
+	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	    for (i = 0; i < 2; i++) {
+		if (! xmlStrcmp(key, (const xmlChar *)WHIRLPOOL_TYPE[i])) {
+		    unit->whirlpool = i;
+		    break;
+		}
+	    }
+	    xmlFree(key);
+	}
+
         if ((!xmlStrcmp(cur->name, (const xmlChar *)"PID_HLT_IMAX"))) {
             key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
             if (sscanf((const char *)key, "%f", &val) == 1)
@@ -1327,11 +1517,14 @@
 	    Config.tempFormat = key[0];
 	    xmlFree(key);
 	}
-	if ((!xmlStrcmp(cur->name, (const xmlChar *)"TEMP_ADDRESS"))) {
-	    Config.temp_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
-	}
-	if ((!xmlStrcmp(cur->name, (const xmlChar *)"HUM_ADDRESS"))) {
-	    Config.hum_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"ROOMTEMP_UUID"))) {
+	    if (Config.roomtemp == NULL) {
+		Config.roomtemp = (sensor_var *)malloc(sizeof(sensor_var));
+		Config.roomtemp->uuid[0] = '\0';
+		Config.roomtemp->state = 1;        // missing
+		Config.roomtemp->value = 0;
+	    }
+	    snprintf(Config.roomtemp->uuid, 36, "%s", xmlNodeListGetString(doc, cur->xmlChildrenNode, 1));
 	}
 	if ((!xmlStrcmp(cur->name, (const xmlChar *)"LCDS"))) {
 	    parseLCDs(doc, cur);

mercurial