Units editing is more or less complete. Changed structures for heating, cooling, fan and door. Updated the web interface to confuigure all these things.

Sun, 03 Aug 2014 22:49:33 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 03 Aug 2014 22:49:33 +0200
changeset 175
b73490398368
parent 174
244de612c572
child 176
8c7d87a2c094

Units editing is more or less complete. Changed structures for heating, cooling, fan and door. Updated the web interface to confuigure all these things.

thermferm/rdconfig.c file | annotate | diff | comparison | revisions
thermferm/server.c file | annotate | diff | comparison | revisions
thermferm/thermferm.c file | annotate | diff | comparison | revisions
thermferm/thermferm.h file | annotate | diff | comparison | revisions
thermferm/units.c file | annotate | diff | comparison | revisions
www-thermferm/getstate.php file | annotate | diff | comparison | revisions
www-thermferm/index.php file | annotate | diff | comparison | revisions
www-thermferm/liveview.php file | annotate | diff | comparison | revisions
www-thermferm/units.php file | annotate | diff | comparison | revisions
--- a/thermferm/rdconfig.c	Sat Aug 02 22:33:15 2014 +0200
+++ b/thermferm/rdconfig.c	Sun Aug 03 22:49:33 2014 +0200
@@ -69,10 +69,14 @@
 	    free(tmp2->air_address);
 	if (tmp2->beer_address)
 	    free(tmp2->beer_address);
-	if (tmp2->io1_address)
-	    free(tmp2->io1_address);
-	if (tmp2->io2_address)
-	    free(tmp2->io2_address);
+	if (tmp2->heater_address)
+	    free(tmp2->heater_address);
+	if (tmp2->cooler_address)
+	    free(tmp2->cooler_address);
+	if (tmp2->fan_address)
+	    free(tmp2->fan_address);
+	if (tmp2->door_address)
+	    free(tmp2->door_address);
 	if (tmp2->profile)
 	    free(tmp2->profile);
 	free(tmp2);
@@ -308,25 +312,45 @@
 		    return 1;
 		}
 	    }
-	    if (tmp3->io1_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO1_ADDRESS", "%s", tmp3->io1_address)) < 0)) {
-		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-		return 1;
+	    if (tmp3->heater_address) {
+		if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HEATER_ADDRESS", "%s", tmp3->heater_address)) < 0)) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;
+		}
+		if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HEATER_STATE", "%d", tmp3->heater_state)) < 0)) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;
+		}
 	    }
-	    if (tmp3->io2_address && ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "IO2_ADDRESS", "%s", tmp3->io2_address)) < 0)) {
-		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-		return 1;
+	    if (tmp3->cooler_address) {
+		if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "COOLER_ADDRESS", "%s", tmp3->cooler_address)) < 0)) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;
+		}
+		if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "COOLER_STATE", "%d", tmp3->cooler_state)) < 0)) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;                                   
+		}
 	    }
-	    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HEATER", "%s", tmp3->heater_available ? "YES":"NO")) < 0) {
-		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
-		return 1;                           
+	    if (tmp3->fan_address) {
+		if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "FAN_ADDRESS", "%s", tmp3->fan_address)) < 0)) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;
+		}
+		if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "FAN_STATE", "%d", tmp3->fan_state)) < 0)) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		    return 1;                                   
+		}
 	    }
-	    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "COOLER", "%s", tmp3->cooler_available? "YES":"NO")) < 0) {
-		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+	    if (tmp3->door_address) {
+		if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "DOOR_ADDRESS", "%s", tmp3->door_address)) < 0)) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
 		return 1;
-	    }
-	    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "FAN", "%s", tmp3->fan_available ? "YES":"NO")) < 0) {
-		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
+		}
+		if (((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "DOOR_STATE", "%d", tmp3->door_state)) < 0)) {
+		    syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
 		return 1;
+		}
 	    }
 	    if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MODE", "%s", UNITMODE[tmp3->mode] )) < 0) {
 		syslog(LOG_NOTICE, "wrconfig: error at xmlTextWriterWriteFormatElement");
@@ -645,9 +669,9 @@
     unit = (units_list *)malloc(sizeof(units_list));
     unit->next = NULL;
     unit->version = 1;
-    unit->uuid = unit->name = unit->air_address = unit->beer_address = unit->io1_address = unit->io2_address = unit->profile = NULL;
+    unit->uuid = unit->name = unit->air_address = unit->beer_address = unit->heater_address = \
+		 unit->cooler_address = unit->fan_address = unit->door_address = unit->profile = NULL;
     unit->volume = 0.0;
-    unit->heater_available = unit->cooler_available = unit->fan_available = FALSE;
     unit->air_temperature = unit->beer_temperature = unit->beer_set = unit->fridge_set = 20.0;
     unit->air_state = unit->beer_state = 1; // missing
     unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = unit->prof_state = 0;
@@ -710,29 +734,17 @@
 		unit->beer_temperature = ival;
 	    xmlFree(key);
 	}
-	if ((!xmlStrcmp(cur->name, (const xmlChar *)"IO1_ADDRESS"))) {
-	    unit->io1_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
-	}
-	if ((!xmlStrcmp(cur->name, (const xmlChar *)"IO2_ADDRESS"))) {
-	    unit->io2_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"HEATER_ADDRESS"))) {
+	    unit->heater_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
 	}
-	if ((!xmlStrcmp(cur->name, (const xmlChar *)"HEATER"))) {
-	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
-	    if (! xmlStrcmp(key, (const xmlChar *)"TRUE"))
-		unit->heater_available = TRUE;
-	    xmlFree(key);
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"COOLER_ADDRESS"))) {
+	    unit->cooler_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
 	}
-	if ((!xmlStrcmp(cur->name, (const xmlChar *)"COOLER"))) {
-	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
-	    if (! xmlStrcmp(key, (const xmlChar *)"TRUE"))
-		unit->cooler_available = TRUE;
-	    xmlFree(key);
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"FAN_ADDRESS"))) {
+	    unit->fan_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
 	}
-	if ((!xmlStrcmp(cur->name, (const xmlChar *)"FAN"))) {
-	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
-	    if (! xmlStrcmp(key, (const xmlChar *)"TRUE"))
-		unit->fan_available = TRUE;
-	    xmlFree(key);
+	if ((!xmlStrcmp(cur->name, (const xmlChar *)"DOOR_ADDRESS"))) {
+	    unit->door_address = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
 	}
 	if ((!xmlStrcmp(cur->name, (const xmlChar *)"MODE"))) {
 	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
--- a/thermferm/server.c	Sat Aug 02 22:33:15 2014 +0200
+++ b/thermferm/server.c	Sun Aug 03 22:49:33 2014 +0200
@@ -41,6 +41,7 @@
 extern const char	DEVTYPE[7][6];
 extern const char	DEVPRESENT[4][6];
 extern const char	DEVDIR[7][11];
+extern const char	PROFSTATE[4][6];
 
 
 int			s;		/* connected socket			*/
@@ -98,11 +99,9 @@
 
 /*
  * ADD PROFILE name
- * ADD UNIT name
  */
 int unit_add(char *buf)
 {
-    units_list		*unit, *tmpu;
     profiles_list	*profile, *tmpp;
     uuid_t		uu;
     char		*opt, *param;
@@ -148,45 +147,6 @@
 	syslog(LOG_NOTICE, "Profile \"%s\" with uuid %s added", param, profile->uuid);
 	srv_send((char *)"211 Profile \"%s\" with uuid %s added", param, profile->uuid);
 	return 0;
-
-    } else if (strcmp(opt, (char *)"UNIT") == 0) {
-    	unit = (units_list *)malloc(sizeof(units_list));
-    	unit->next = NULL;
-	unit->version = 1;
-    	unit->uuid = malloc(37);
-    	uuid_generate(uu);
-    	uuid_unparse(uu, unit->uuid);
-	if (current_unit)
-	    free(current_unit);
-	current_unit = xstrcpy(unit->uuid);
-    	unit->name = xstrcpy(param);
-    	unit->air_address = unit->beer_address = unit->io1_address = unit->io2_address = unit->profile = NULL;
-    	unit->volume = 0.0;
-	unit->air_state = unit->beer_state = 1;
-    	unit->heater_available = unit->cooler_available = unit->fan_available = FALSE;
-    	unit->air_temperature = unit->beer_temperature = 20000;
-	unit->beer_set = unit->fridge_set = 20.0;
-    	unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = unit->prof_state = 0;
-    	unit->temp_set_min = 1.0;
-    	unit->temp_set_max = 30.0;
-    	unit->idle_rangeH = 1.0;
-    	unit->idle_rangeL = -1.0;
-    	unit->prof_started = (time_t)0;
-
-    	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, "Unit with uuid %s added", unit->uuid);
-    	srv_send((char *)"211 Unit with uuid %s added", unit->uuid);
-    	return 0;
     }
 
     srv_send((char *)"502 Unknown command option");
@@ -202,7 +162,6 @@
     profiles_list	*previous = NULL;
     prof_step		*step, *olds;
 
-
     while (current) {
 	if (strcmp(current->uuid, uuid) == 0) {
 	    if (previous == NULL) {
@@ -351,7 +310,7 @@
     if (strcmp(opt, (char *)"LIST") == 0) {
 	srv_send((char *)"212 bus devices:");
 	for (device = Config.devices; device; device = device->next) {
-	    srv_send((char *)"%s,%s,%d,%d,%s", device->uuid, device->address, device->subdevice, device->inuse, device->comment);
+	    srv_send((char *)"%s,%s,%d,%d,%s,%s", device->uuid, device->address, device->subdevice, device->inuse, device->comment, DEVDIR[device->direction]);
 	}
 	srv_send((char *)".");
 	return 0;
@@ -547,7 +506,6 @@
  * LIST
  * LIST LOG
  * LIST PROFILES
- * LIST UNIT
  */
 int cmd_list(char *buf)
 {
@@ -627,63 +585,6 @@
 	}
 	srv_send((char *)".");
 	return 0;
-
-    } else if (strcmp(opt, (char *)"UNIT") == 0) {
-	/*
-	 * List configured and selected fermenter unit
-	 */
-	if (current_unit == NULL) {
-	    srv_send((char *)"401 No fermenter unit selected");
-	    return 1;
-	}
-
-	srv_send((char *)"213 Unit %s listing follows:", current_unit);
-	for (unit = Config.units; unit; unit = unit->next) {
-	    if (strcmp(current_unit, unit->uuid) == 0) {
-		srv_send((char *)"NAME,%s", unit->name);
-		srv_send((char *)"UUID,%s", unit->uuid);
-		if (unit->air_address) {
-		    srv_send((char *)"AIR_ADDRESS,%s", unit->air_address);
-		    srv_send((char *)"AIR_STATE,%s", TEMPSTATE[unit->air_state]);
-		    srv_send((char *)"AIR_TEMPERATURE,%.3f", unit->air_temperature / 1000.0);
-		}
-		if (unit->beer_address) {
-		    srv_send((char *)"BEER_ADDRESS,%s", unit->beer_address);
-		    srv_send((char *)"BEER_STATE,%s", TEMPSTATE[unit->beer_state]);
-		    srv_send((char *)"BEER_TEMPERATURE,%.3f", unit->beer_temperature / 1000.0);
-		}
-		if (unit->io1_address) {
-		    srv_send((char *)"IO1_ADDRESS,%s", unit->io1_address);
-		}
-		if (unit->io2_address) {
-		    srv_send((char *)"IO2_ADDRESS,%s", unit->io2_address);
-		}
-		if (unit->heater_available) {
-		    srv_send((char *)"HEATER_AVAILABLE,%s", unit->heater_available);
-		    srv_send((char *)"HEATER_STATE,%d", unit->heater_state);
-		}
-		if (unit->cooler_available) {
-		    srv_send((char *)"COOLER_AVAILABLE,%s", unit->cooler_available);
-		    srv_send((char *)"COOLER_STATE,%d", unit->cooler_state);
-		}
-		if (unit->fan_available) {
-		    srv_send((char *)"FAN_AVAILABLE,%s", unit->fan_available);
-		    srv_send((char *)"FAN_STATE,%d", unit->fan_state);
-		}
-		srv_send((char *)"MODE,%s", UNITMODE[unit->mode]);
-		srv_send((char *)"FRIDGE_SET,%.1f", unit->fridge_set);
-		srv_send((char *)"BEER_SET,%.1f", unit->beer_set);
-		if (unit->profile) {
-		    srv_send((char *)"PROFILE,%s", unit->profile);
-		}
-		srv_send((char *)"TEMP_SET_MIN,%.1f", unit->temp_set_min);
-		srv_send((char *)"TEMP_SET_MAX,%.1f", unit->temp_set_max);
-		srv_send((char *)"IDLE_RANGE_L,%.1f", unit->idle_rangeL);
-		srv_send((char *)"IDLE_RANGE_H,%.1f", unit->idle_rangeH);
-	    }
-	}
-	srv_send((char *)".");
-	return 0;
     }
 
     srv_send((char *)"502 Unknown command option");
@@ -935,14 +836,6 @@
 
 
 /*
- * SET BEER float
- * SET FRIDGE float
- * SET VOLUME float
- * SET IDLE_LOW float
- * SET IDLE_HIGH float
- * SET TEMP_MIN float
- * SET TEMP_MAX float
- * SET NAME string
  * SET PROFILE string
  */
 int cmd_set(char *buf)
@@ -984,90 +877,7 @@
 	    break;
     }
 
-    /*
-     * If a valid parameter float value
-     */
-    if (rc == 1) {
-	if (strcmp(opt, (char *)"BEER") == 0) {
-	    if ((fval >= unit->temp_set_min) && (fval <= unit->temp_set_max)) {
-	    	unit->beer_set = fval;
-	    	srv_send((char *)"214 Unit %s BEER set to %.1f", current_unit, fval);
-	    	return 0;
-	    } else {
-		srv_send((char *)"510 New temperature not between %.1f and %.1f", unit->temp_set_min, unit->temp_set_max);
-		return 1;
-	    }
-	} else if (strcmp(opt, (char *)"FRIDGE") == 0) {
-	    if ((fval >= unit->temp_set_min) && (fval <= unit->temp_set_max)) {
-	    	unit->fridge_set = fval;
-	    	srv_send((char *)"214 Unit %s BEER set to %.1f", current_unit, fval);
-	    	return 0;
-	    } else {
-		srv_send((char *)"510 New temperature not between %.1f and %.1f", unit->temp_set_min, unit->temp_set_max);
-		return 1;
-	    }
-	} else if (strcmp(opt, (char *)"VOLUME") == 0) {
-	    /*
-	     * Must fit in a 2 TEU container
-	     */
-	    if ((fval >= 0.0) && (fval <=  77020.0)) {
-	    	unit->volume = fval;
-	    	srv_send((char *)"214 Unit %s VOLUME set to %.1f", current_unit, fval);
-	    	return 0;
-	    } else {
-		srv_send((char *)"510 New volume not between 0 and 77020");
-		return 1;
-	    }
-	} else if (strcmp(opt, (char *)"IDLE_LOW") == 0) {
-	    if ((fval >= -5.0) && (fval <=  -0.1)) {
-		unit->idle_rangeL = fval;
-		srv_send((char *)"214 Unit %s IDLE_LOW set to %.1f", current_unit, fval);
-		return 0;
-	    } else {
-		srv_send((char *)"510 New value not between -5.0 and -0.1");
-		return 1;
-	    }
-	} else if (strcmp(opt, (char *)"IDLE_HIGH") == 0) {
-	   if ((fval >= 0.1) && (fval <=  5.0)) {
-		unit->idle_rangeH = fval;
-		srv_send((char *)"214 Unit %s IDLE_HIGH set to %.1f", current_unit, fval);
-		return 0;
-	    } else {
-		srv_send((char *)"510 New value not between -5.0 and -0.1");
-		return 1;
-	    }
-	} else if (strcmp(opt, (char *)"TEMP_MIN") == 0) {
-	    if ((fval >= -2.0) && (fval <= 35.0) && (fval < unit->temp_set_max)) {
-		unit->temp_set_min = fval;
-		srv_send((char *)"214 Unit %s TEMP_MIN set to %.1f", current_unit, fval);
-		return 0;
-	    } else {
-		srv_send((char *)"510 New value not between -2.0 and 35.0 and lower then TEMP_MAX");
-		return 1;
-	    }
-	} else if (strcmp(opt, (char *)"TEMP_MAX") == 0) {
-	    if ((fval >= -2.0) && (fval <= 35.0) && (fval > unit->temp_set_min)) {
-		unit->temp_set_max = fval;
-		srv_send((char *)"214 Unit %s TEMP_MAX set to %.1f", current_unit, fval);
-		return 0;
-	    } else {
-		srv_send((char *)"510 New value not between -2.0 and 35.0 and higher then TEMP_MIN");
-		return 1;
-	    }
-	}
-    }
-
-    /*
-     * Set new unit or beer name
-     */
-    if (strcmp(opt, (char *)"NAME") == 0) {
-	if (unit->name)
-	    free(unit->name);
-	unit->name = xstrcpy(param);
-	srv_send((char *)"214 Unit %s NAME set to '%s'", current_unit, param);
-	// TODO: change logfile name
-	return 0;
-    } else if (strcmp(opt, (char *)"PROFILE") == 0) {
+    if (strcmp(opt, (char *)"PROFILE") == 0) {
 	/*
 	 * Check for active profile, already selected etc.
 	 */
@@ -1098,13 +908,98 @@
 
 
 
+int delete_Unit(char *uuid)
+{
+    units_list  *current = Config.units;
+    units_list	*previous = NULL;
+
+    while (current) {
+	if (strcmp(current->uuid, uuid) == 0) {
+	    if (previous == NULL) {
+		Config.units = current->next;
+		free(current->uuid);
+		current->uuid = NULL;
+		free(current->name);
+		current->name = NULL;
+		if (current->air_address)
+		    free(current->air_address);
+		current->air_address = NULL;
+		if (current->beer_address)
+		    free(current->beer_address);
+		current->beer_address = NULL;
+		if (current->heater_address)
+		    free(current->heater_address);
+		current->heater_address = NULL;
+		if (current->cooler_address)
+		    free(current->cooler_address);
+		current->cooler_address = NULL;
+		if (current->fan_address)
+		    free(current->fan_address);
+		current->fan_address = NULL;
+		if (current->door_address)
+		    free(current->door_address);
+		current->door_address = NULL;
+		if (current->profile)
+		    free(current->profile);
+		current->profile = NULL;
+		free(current);
+		return 1;
+	    } else {
+		free(current->uuid);
+		current->uuid = NULL;
+		free(current->name);
+		current->name = NULL;
+		if (current->air_address)
+		    free(current->air_address);
+		current->air_address = NULL;
+		if (current->beer_address)
+		    free(current->beer_address);
+		current->beer_address = NULL;
+		if (current->heater_address)
+		    free(current->heater_address);
+		current->heater_address = NULL;
+		if (current->cooler_address)
+		    free(current->cooler_address);
+		current->cooler_address = NULL;
+		if (current->fan_address)
+		    free(current->fan_address);
+		current->fan_address = NULL;
+		if (current->door_address)
+		    free(current->door_address);
+		current->door_address = NULL;
+		if (current->profile)
+		    free(current->profile);
+		current->profile = NULL;
+		free(current);
+		current = previous->next;
+		return 1;
+	    }
+	} else {
+	    previous = current;
+	    current = current->next;
+	}
+    }
+    return 0;
+}
+
+
+
 /*
  * UNIT uuid
+ * UNIT ADD name
+ * UNIT DEL uuid
+ * UNIT LIST
+ * UNIT GET uuid
+ * UNIT PUT uuid
  */
 int cmd_unit(char *buf)
 {
-    char                *opt;
-    units_list          *tmp;
+    char                *opt, *param = NULL, *kwd, *val, ibuf[SS_BUFSIZE];
+    units_list          *unit, *tmpu;
+    uuid_t		uu;
+    socklen_t		fromlen;
+    int			i, rlen;
+    float		fval;
 
     opt = strtok(buf, " \0");
     opt = strtok(NULL, " \0");
@@ -1113,24 +1008,271 @@
 	srv_send((char *)"501 Parameter missing");
 	return 1;
     }
+    param = strtok(NULL, "\0");
 
-    if (strlen(opt) == 36) {
+    /*
+     * UNIT uuid
+     */
+    if ((strlen(opt) == 36) && (param == NULL)) {
 	/*
 	 * Search using uuid
 	 */
-	for (tmp = Config.units; tmp; tmp = tmp->next) {
-	    if (strcmp(opt, tmp->uuid) == 0) {
-		srv_send((char *)"210 Unit %s selected", tmp->uuid);
+	for (unit = Config.units; unit; unit = unit->next) {
+	    if (strcmp(opt, unit->uuid) == 0) {
+		srv_send((char *)"210 Unit %s selected", unit->uuid);
 		if (current_unit)
 		    free(current_unit);
-		current_unit = xstrcpy(tmp->uuid);;
-		return 0;
+		current_unit = xstrcpy(unit->uuid);;
+		return 1;
+	    }
+	}
+	srv_send((char *)"410 No such unit");
+	return 1;
+    }
+
+    if ((strcmp(opt, (char *)"LIST") == 0) && (param == NULL)) {
+	srv_send((char *)"212 Fermenter Units list follows:");
+	for (unit = Config.units; unit; unit = unit->next) {
+	    srv_send((char *)"%s,%s,%s", unit->uuid, unit->name, UNITMODE[unit->mode]);
+	}
+	srv_send((char *)".");
+	return 1;
+    }
+
+    if (param == NULL) {
+	srv_send((char *)"501 Parameter missing");
+	return 1;
+    }
+
+    if (strcmp(opt, (char *)"ADD") == 0) {
+	unit = (units_list *)malloc(sizeof(units_list));
+	unit->next = NULL;
+	unit->version = 1;
+	unit->uuid = malloc(37);
+	uuid_generate(uu);
+	uuid_unparse(uu, unit->uuid);
+	if (current_unit)
+	    free(current_unit);
+	current_unit = xstrcpy(unit->uuid);
+	unit->name = xstrcpy(param);
+	unit->air_address = unit->beer_address = unit->heater_address = unit->cooler_address = \
+			    unit->fan_address = unit->door_address = unit->profile = NULL;
+	unit->volume = 0.0;
+	unit->air_state = unit->beer_state = 1;
+	unit->air_temperature = unit->beer_temperature = 20000;
+	unit->beer_set = unit->fridge_set = 20.0;
+	unit->heater_state = unit->cooler_state = unit->fan_state = unit->door_state = unit->mode = unit->prof_state = 0;
+	unit->temp_set_min = 1.0;
+	unit->temp_set_max = 30.0;
+	unit->idle_rangeH = 1.0;
+	unit->idle_rangeL = -1.0;
+	unit->prof_started = (time_t)0;
+
+	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, "Unit with uuid %s added", unit->uuid);
+	srv_send((char *)"211 Unit with uuid %s added", unit->uuid);
+	return 0;
+    }
+
+    if (strcmp(opt, (char *)"DEL") == 0) {
+	if (delete_Unit(param)) {
+	    syslog(LOG_NOTICE, "Deleted Unit with %s", param);
+	    srv_send((char *)"211 Unit %s deleted", param);
+	    return 0;
+	} else {
+	    srv_send((char *)"440 Delete Unit: No such unit %s", param);
+	    return 1;
+	}
+    }
+
+    if (strcmp(opt, (char *)"GET") == 0) {
+	for (unit = Config.units; unit; unit = unit->next) {
+	    if (strcmp(param, unit->uuid) == 0) {
+		srv_send((char *)"213 Unit %s listing follows:", unit->uuid);
+		srv_send((char *)"NAME,%s", unit->name);
+		srv_send((char *)"UUID,%s", unit->uuid);
+		srv_send((char *)"VOLUME,%2f", unit->volume);
+		srv_send((char *)"AIR_ADDRESS,%s", unit->air_address);
+		srv_send((char *)"AIR_STATE,%s", TEMPSTATE[unit->air_state]);
+		srv_send((char *)"AIR_TEMPERATURE,%.3f", unit->air_temperature / 1000.0);
+		srv_send((char *)"BEER_ADDRESS,%s", MBSE_SS(unit->beer_address));
+		srv_send((char *)"BEER_STATE,%s", TEMPSTATE[unit->beer_state]);
+		srv_send((char *)"BEER_TEMPERATURE,%.3f", unit->beer_temperature / 1000.0);
+		srv_send((char *)"HEATER_ADDRESS,%s", unit->heater_address);
+		srv_send((char *)"HEATER_STATE,%d", unit->heater_state);
+		srv_send((char *)"COOLER_ADDRESS,%s", unit->cooler_address);
+		srv_send((char *)"COOLER_STATE,%d", unit->cooler_state);
+		srv_send((char *)"FAN_ADDRESS,%s", unit->fan_address);
+		srv_send((char *)"FAN_STATE,%d", unit->fan_state);
+		srv_send((char *)"DOOR_ADDRESS,%s", unit->door_address);
+		srv_send((char *)"DOOR_STATE,%d", unit->door_state);
+		srv_send((char *)"MODE,%s", UNITMODE[unit->mode]);
+		srv_send((char *)"FRIDGE_SET,%.1f", unit->fridge_set);
+		srv_send((char *)"BEER_SET,%.1f", unit->beer_set);
+		srv_send((char *)"PROFILE,%s", unit->profile);
+		if (unit->profile) {
+		    srv_send((char *)"PROF_STARTED,%d", (int)unit->prof_started);
+		    srv_send((char *)"PROF_STATE,%s", PROFSTATE[unit->prof_state]);
+		    srv_send((char *)"PROF_TARGET,%.3f", unit->prof_target);
+		}
+		srv_send((char *)"TEMP_SET_MIN,%.1f", unit->temp_set_min);
+		srv_send((char *)"TEMP_SET_MAX,%.1f", unit->temp_set_max);
+		srv_send((char *)"IDLE_RANGE_L,%.1f", unit->idle_rangeL);
+		srv_send((char *)"IDLE_RANGE_H,%.1f", unit->idle_rangeH);
+		srv_send((char *)".");
+		return 1;
 	    }
 	}
 	srv_send((char *)"410 No such unit");
 	return 1;
     }
 
+    if (strcmp(opt, (char *)"PUT") == 0) {
+	for (unit = Config.units ; unit; unit = unit->next) {
+	     if (strcmp(unit->uuid, param) == 0) {
+		while (1) {
+		    memset((char *)&ibuf, 0, SS_BUFSIZE);
+		    fromlen = sizeof(peeraddr_in);
+		    rlen = recvfrom(s, ibuf, sizeof(ibuf) -1, 0, (struct sockaddr *)&peeraddr_in, &fromlen);
+		    if (rlen == -1) {
+			syslog(LOG_NOTICE, "recvfrom(): %s", strerror(errno));
+			srv_send((char *)"518 recfrom(): %s", strerror(errno));
+			return 1;
+		    }
+		    for (i = 0; i < strlen(ibuf); i++) {
+			if (ibuf[i] == '\n')
+			    ibuf[i] = '\0';
+			if (ibuf[i] == '\r')
+			    ibuf[i] = '\0';
+		    }
+		    for (i = strlen(ibuf) -1; i > 0; i--) {
+			if (ibuf[i] == ' ')
+			    ibuf[i] = '\0';
+			else
+			    break;
+		    }
+		    if (strlen(ibuf)) {
+			if (debug) {
+			    syslog(LOG_NOTICE, "recv: \"%s\"", ibuf);
+			    fprintf(stdout, "recv: \"%s\"\n", ibuf);
+			}
+			if (strcmp(ibuf, (char *)".") == 0) {
+			    srv_send((char *)"219 Accepted Unit record");
+			    return 0;
+			}
+			kwd = strtok(ibuf, ",\0");
+			val = strtok(NULL, "\0");
+			if (kwd && val) {
+			    /*
+			     * Accept writable data. The client can sent just one line,
+			     * but may also sent everything. Simply ignore things we
+			     * don't understand.
+			     */
+			    if (strcmp(kwd, (char *)"NAME") == 0) {
+				if (unit->name)
+				    free(unit->name);
+				unit->name = xstrcpy(val);
+
+			    } else if (strcmp(kwd, (char *)"VOLUME") == 0) {
+				if (sscanf(val, "%f", &fval) == 1)
+				    unit->volume = fval;
+
+			    } else if (strcmp(kwd, (char *)"AIR_ADDRESS") == 0) {
+				if (unit->air_address)
+				    free(unit->air_address);
+				unit->air_address  = xstrcpy(val);
+
+			    } else if (strcmp(kwd, (char *)"BEER_ADDRESS") == 0) {
+				if (unit->beer_address)
+				    free(unit->beer_address);
+				unit->beer_address = xstrcpy(val);
+
+			    } else if (strcmp(kwd, (char *)"HEATER_ADDRESS") == 0) {
+				if (unit->heater_address)
+				    free(unit->heater_address);
+				unit->heater_address = xstrcpy(val);
+
+			    } else if (strcmp(kwd, (char *)"COOLER_ADDRESS") == 0) {
+				if (unit->cooler_address)
+				    free(unit->cooler_address);
+				unit->cooler_address = xstrcpy(val);
+
+			    } else if (strcmp(kwd, (char *)"FAN_ADDRESS") == 0) {
+				if (unit->fan_address)
+				free(unit->fan_address);
+				unit->fan_address = xstrcpy(val);
+			   
+			    } else if (strcmp(kwd, (char *)"DOOR_ADDRESS") == 0) {
+				if (unit->door_address)
+				free(unit->door_address);
+				unit->door_address = xstrcpy(val);
+
+			    } else if (strcmp(kwd, (char *)"MODE") == 0) {
+				for (i = 0; i < 5; i++) {
+				    if (strcmp(val, UNITMODE[i]) == 0) {
+					unit->mode = i;
+					break;
+				    }
+				}
+
+			    } else if (strcmp(kwd, (char *)"FRIDGE_SET") == 0) {
+				if (sscanf(val, "%f", &fval) == 1)
+				    unit->fridge_set = fval;
+
+			    } else if (strcmp(kwd, (char *)"BEER_SET") == 0) {
+				if (sscanf(val, "%f", &fval) == 1)
+				    unit->beer_set = fval;
+
+			    } else if (strcmp(kwd, (char *)"PROFILE") == 0) {
+				if (unit->profile)
+				    free(unit->profile);
+				unit->profile = xstrcpy(val);
+
+			    } else if (strcmp(kwd, (char *)"PROF_STATE") == 0) {
+				for (i = 0; i < 4; i++) {
+				    if (strcmp(val, PROFSTATE[i]) == 0) {
+					unit->prof_state = i;
+					break;
+				    }
+				}
+
+			    } else if (strcmp(kwd, (char *)"TEMP_SET_MIN") == 0) {
+				if (sscanf(val, "%f", &fval) == 1)
+				    unit->temp_set_min = fval;
+
+			    } else if (strcmp(kwd, (char *)"TEMP_SET_MAX") == 0) {
+				if (sscanf(val, "%f", &fval) == 1)
+				    unit->temp_set_max = fval;
+
+			    } else if (strcmp(kwd, (char *)"IDLE_RANGE_L") == 0) {
+				if (sscanf(val, "%f", &fval) == 1)
+				    unit->idle_rangeL = fval;
+
+			    } else if (strcmp(kwd, (char *)"IDLE_RANGE_H") == 0) {
+				if (sscanf(val, "%f", &fval) == 1)
+				    unit->idle_rangeH = fval;
+
+			    }
+			}
+		    }
+		}
+	    }
+	}
+	srv_send((char *)"440 No such device");
+	return 1;
+    }
+
+
     srv_send((char *)"502 Unknown command option");
     return 1;
 }
@@ -1189,11 +1331,9 @@
 		srv_send((char *)"");
 //                                12345678901234567890123456789012345678901234567890123456789012345678901234567890
 		srv_send((char *)"ADD PROFILE name              Add a new profile with \"name\"");
-		srv_send((char *)"ADD UNIT name                 Add a new unit with \"name\"");
 		srv_send((char *)"DEL PROFILE uuid              Delete profile with uuid");
-//		srv_send((char *)"DEL UNIT uuid                 Delete unit with uuid");
 		srv_send((char *)"DEVICE ADD type               Add new Device type");
-//		srv_send((char *)"DEVICE DEL uuid               Delete Device by uuid");
+		srv_send((char *)"DEVICE DEL uuid               Delete Device by uuid");
 		srv_send((char *)"DEVICE LIST                   List Devices");
 		srv_send((char *)"DEVICE GET uuid               Get Device record by uuid");
 		srv_send((char *)"DEVICE PUT uuid               Put Device record by uuid");
@@ -1201,23 +1341,20 @@
 		srv_send((char *)"LIST                          List all fermenter units");
 		srv_send((char *)"LIST LOG                      List logfile data in 1 hour lines");
 		srv_send((char *)"LIST PROFILES                 List available profiles");
-		srv_send((char *)"LIST UNIT                     List fermenter unit");
 		srv_send((char *)"MODE OFF|NONE|BEER|FRIDGE|PROFILE");
 //		srv_send((char *)"PROFILE                       Profile status of current unit");
 		srv_send((char *)"PROFILE uuid,name             Profile rename");
 		srv_send((char *)"PROFILE GETS uuid             Profile get steps list");
 		srv_send((char *)"PROFILE PUTS uuid             Profile put steps list");
-		srv_send((char *)"SET BEER val                  Set beer temperature");
-		srv_send((char *)"SET FRIDGE val                Set fridge temperature");
-		srv_send((char *)"SET IDLE_LOW val              Set idle temperature low (-5.0 .. -0.1)");
-		srv_send((char *)"SET IDLE_HIGH val             Set idle temperature high (0.1 .. 5.0)");
-		srv_send((char *)"SET NAME name                 Set name or beername for the unit");
 		srv_send((char *)"SET PROFILE uuid              Set unit profile");
 //		srv_send((char *)"SET PROFILE start|stop|pause  Profile start, stop or pause");
-		srv_send((char *)"SET TEMP_MIN val              Set unit minimum temperature");
-		srv_send((char *)"SET TEMP_MAX val              Set unit maximum temperature");
 		srv_send((char *)"SET VOLUME val                Set unit volume");
 		srv_send((char *)"UNIT uuid                     Select unit by uuid");
+		srv_send((char *)"UNIT ADD name                 Add a new unit with name");
+		srv_send((char *)"UNIT DEL uuid                 Delete Unit by uuid");
+		srv_send((char *)"UNIT LIST                     List Units");
+		srv_send((char *)"UNIT GET uuid                 Get Unit record by uuid");
+		srv_send((char *)"UNIT PUT uuid                 Put Unit record by uuid");
 		srv_send((char *)".");
 	    } else if (strncmp(buf, "LCD", 3) == 0) {
 #ifdef HAVE_WIRINGPI_H
@@ -1245,7 +1382,8 @@
 		if (cmd_set(buf) == 0)
 		    wrconfig();
 	    } else if (strncmp(buf, "UNIT", 4) == 0) {
-		cmd_unit(buf);
+		if (cmd_unit(buf) == 0)
+		    wrconfig();
 	    } else {
 		if (debug)
 		    fprintf(stdout, "unknown command \"%s\"\n", buf);
--- a/thermferm/thermferm.c	Sat Aug 02 22:33:15 2014 +0200
+++ b/thermferm/thermferm.c	Sun Aug 03 22:49:33 2014 +0200
@@ -355,19 +355,20 @@
 			    snprintf(target, 39, "%.1f", unit->beer_set);
 			else if (unit->mode == UNITMODE_FRIDGE)
 			    snprintf(target, 39, "%.1f", unit->fridge_set);
-
-			if (unit->io1_address) {
-			    if (unit->heater_available) {
-
-			    }
-			    if (unit->cooler_available) {
+			else if (unit->mode == UNITMODE_PROFILE)
+			    snprintf(target, 39, "%.1f", unit->prof_target);
 
-			    }
+			if (unit->heater_address) {
+			    snprintf(heater, 39, "%d", unit->heater_state);
+			}
+			if (unit->cooler_address) {
+			    snprintf(cooler, 39, "%d", unit->cooler_state);
 			}
-			if (unit->io2_address) {
-			    if (unit->fan_available) {
-
-			    }
+			if (unit->fan_address) {
+			    snprintf(fan, 39, "%d", unit->fan_state);
+			}
+			if (unit->door_address) {
+			    snprintf(door, 39, "%d", unit->door_state);
 			}
 
 			snprintf(buf, 1023, "%s,%.3f,%.3f,%s,%s,%s,%s,%s", 
--- a/thermferm/thermferm.h	Sat Aug 02 22:33:15 2014 +0200
+++ b/thermferm/thermferm.h	Sun Aug 03 22:49:33 2014 +0200
@@ -72,14 +72,13 @@
     char		*beer_address;		/* DS18B20 address		*/
     int			beer_state;		/* 0=ok, 1=missing, 2=error 	*/
     int			beer_temperature;	/* Beer temperature in C * 1000	*/
-    char		*io1_address;		/* DS2413 address		*/
-    char		*io2_address;		/* DS2413 address		*/
-    int			heater_available;	/* Heater available		*/
+    char		*heater_address;	/* Heater relay or PWM		*/
     int			heater_state;		/* Heater status		*/
-    int			cooler_available;	/* Cooler available		*/
+    char		*cooler_address;	/* Cooler relay or PWM		*/
     int			cooler_state;		/* Cooler status		*/
-    int			fan_available;		/* Fan available		*/
+    char		*fan_address;		/* Fan relay or PWM 		*/
     int			fan_state;		/* Fan status			*/
+    char		*door_address;		/* Door input address		*/
     int			door_state;		/* Door and light status	*/
     int			mode;			/* Unit mode			*/
     float		beer_set;		/* Beer temperature setting	*/
--- a/thermferm/units.c	Sat Aug 02 22:33:15 2014 +0200
+++ b/thermferm/units.c	Sun Aug 03 22:49:33 2014 +0200
@@ -110,9 +110,9 @@
 		     * value with the previous one. If the difference is too
 		     * much, we don't send that value. That also means that if
 		     * the next value is ok again, it will be marked invalid too.
-		     * Maximum error is 20 degrees for now.
+		     * Maximum error is 40 degrees for now.
 		     */
-		    deviation = 20000;
+		    deviation = 40000;
 		    if ((unit->air_temperature == 0) ||
 			(unit->air_temperature && (temp > (int)unit->air_temperature - deviation) && (temp < ((int)unit->air_temperature + deviation)))) {
 			unit->air_temperature = temp;
@@ -135,7 +135,7 @@
 	    if (unit->beer_address) {
 		rc = read_w1_28(unit->beer_address, &temp);
 		if (rc == DEVPRESENT_YES) {
-		    deviation = 20000;
+		    deviation = 40000;
 		    if ((unit->beer_temperature == 0) ||
 		    	(unit->beer_temperature && (temp > (int)unit->beer_temperature - deviation) && (temp < ((int)unit->beer_temperature + deviation)))) {
 		    	unit->beer_temperature = temp;
--- a/www-thermferm/getstate.php	Sat Aug 02 22:33:15 2014 +0200
+++ b/www-thermferm/getstate.php	Sun Aug 03 22:49:33 2014 +0200
@@ -34,23 +34,7 @@
     return;
 }
 
-socket_write($sock, 'UNIT '.$uuid, 4096);
-$answer = "";
-while (1) {
-    $line = socket_read($sock, 4096);
-    if ($line === '')
-	break;
-    $answer .= $line;
-}
-socket_close($sock);
-
-$sock = open_socket();
-if ($sock == false) {
-    echo "";
-    return;
-}
-
-socket_write($sock, 'LIST UNIT', 4096);
+socket_write($sock, 'UNIT GET '.$uuid, 4096);
 $answer = "";
 while (1) {
     $line = socket_read($sock, 4096);
--- a/www-thermferm/index.php	Sat Aug 02 22:33:15 2014 +0200
+++ b/www-thermferm/index.php	Sun Aug 03 22:49:33 2014 +0200
@@ -35,8 +35,21 @@
  * Handle the post events
  */
 if (isset($_POST['mode']) && isset($_POST['UUID'])) {
-    send_cmd('UNIT '.$_POST['UUID']);
-    send_cmd('MODE '.$_POST['mode']);
+    $sock = open_socket();
+    if ($sock != false) {
+	socket_write($sock, 'UNIT PUT '.$_POST['UUID'], 4096);
+	usleep(20000);
+	socket_write($sock, 'MODE,'.$_POST['mode'], 4096);
+	usleep(20000);
+	socket_write($sock, '.', 4096);
+	/* Absorb response */
+	while (1) {
+	    $line = socket_read($sock, 4096);
+	    if ($line === '')
+		break;
+	}
+	socket_close($sock);
+    }
     unset($_POST['UUID']);
     unset($_POST['mode']);
 }
--- a/www-thermferm/liveview.php	Sat Aug 02 22:33:15 2014 +0200
+++ b/www-thermferm/liveview.php	Sun Aug 03 22:49:33 2014 +0200
@@ -38,22 +38,7 @@
 	return '';
     }
 
-    socket_write($sock, "UNIT " . $unit, 4096);
-    $answer = "";
-    while (1) {
-	$line = socket_read($sock, 4096);
-	if ($line === '')
-		break;
-	$answer .= $line;
-    }
-    socket_close($sock);
-
-    $sock = open_socket();
-    if ($sock == false) {
-	return '';
-    }
-
-    socket_write($sock, "LIST UNIT", 4096);
+    socket_write($sock, "UNIT GET ".$unit, 4096);
     $answer = "";
     while (1) {
 	$line = socket_read($sock, 4096);
--- a/www-thermferm/units.php	Sat Aug 02 22:33:15 2014 +0200
+++ b/www-thermferm/units.php	Sun Aug 03 22:49:33 2014 +0200
@@ -29,7 +29,7 @@
     load('index.php');
 }
 
-socket_write($sock, "LIST", 4096);
+socket_write($sock, "UNIT LIST", 4096);
 $answer = "";
 while (1) {
     $line = socket_read($sock, 4096);
@@ -76,7 +76,7 @@
 
     if ($_POST['key'] == 'Add') {
 		                
-	$cmd = "ADD UNIT ".$_POST['Name'];
+	$cmd = "UNIT ADD ".$_POST['Name'];
 
 	$sock = open_socket();
 	if ($sock != false) {
@@ -113,17 +113,11 @@
     /*
      * Build the update command
      */
-    if ($_POST['key'] == 'Delete')
-	$update_cmd = "DEL UNIT ".$_POST['UUID'];
-    else
-	$update_cmd = "XXXXXXX ".$_POST['UUID'].",".$_POST['Name'];
-
+    if ($_POST['key'] == 'Delete') {
 	$sock = open_socket();
 	if ($sock != false) {
-	    /*
-	     * Send command and absorb the result.
-	     */
-	    socket_write($sock, $update_cmd, 4096);
+	    socket_write($sock, "UNIT DEL ".$_POST['UUID'], 4096);
+	    /* Absorb response */
 	    while (1) {
 		$line = socket_read($sock, 4096);
 		if ($line === '')
@@ -131,9 +125,54 @@
 	    }
 	    socket_close($sock);
 	}
+    }
+
+    if ($_POST['key'] == 'Save') {
+	$sock = open_socket();
+	if ($sock != false) {
+	    /*
+	     * Send command and absorb the result.
+	     */
+	    socket_write($sock, "UNIT PUT ".$_POST['UUID'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "NAME,".$_POST['Name'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "VOLUME,".$_POST['Volume'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "AIR_ADDRESS,".$_POST['AirAddress'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "BEER_ADDRESS,".$_POST['BeerAddress'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "HEATER_ADDRESS,".$_POST['HeaterAddress'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "COOLER_ADDRESS,".$_POST['CoolerAddress'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "FAN_ADDRESS,".$_POST['FanAddress'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "DOOR_ADDRESS,".$_POST['DoorAddress'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "TEMP_SET_MIN,".$_POST['TempSetMin'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "TEMP_SET_MAX,".$_POST['TempSetMax'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "IDLE_RANGE_L,".$_POST['IdleRangeL'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "IDLE_RANGE_H,".$_POST['IdleRangeH'], 4096);
+	    usleep(20000);
+
+	    socket_write($sock, ".", 4096);
+	    while (1) {
+		$line = socket_read($sock, 4096);
+		if ($line === '')
+		    break;
+	    }
+	    socket_close($sock);
+	}
+    }
 
     unset($_POST['UUID']);
     unset($_POST['Name']);
+    unset($_POST['Volume']);
     unset($_POST['key']);
     unset($_POST['command']);
     load('units.php');
@@ -159,7 +198,10 @@
 
     global $arr;
 
-    if (isset($_POST['UUID']) && isset($_POST['Name']) && isset($_POST['key']) && isset($_POST['command'])) {
+    if (isset($_POST['UUID']) && isset($_POST['Name']) && isset($_POST['Volume']) && isset($_POST['AirAddress']) &&
+	isset($_POST['BeerAddress']) && isset($_POST['HeaterAddress']) && isset($_POST['CoolerAddress']) &&
+	isset($_POST['FanAddress']) && isset($_POST['DoorAddress']) && isset($_POST['TempSetMin']) && isset($_POST['TempSetMax']) &&
+	isset($_POST['IdleRangeL']) && isset($_POST['IdleRangeH']) && isset($_POST['key']) && isset($_POST['command'])) {
 
 	if ($_POST['key'] == 'Cancel')
 	    return 99;
@@ -223,7 +265,7 @@
 	$heading = 'ThermFerm - Edit Unit';
     }
 
-    edit_screen($_POST['UUID'], $_POST['Name'], $_POST['command'], $heading, $error);
+    edit_screen($_POST['UUID'], $_POST['command'], $heading, $error);
 }
 
 
@@ -232,12 +274,51 @@
  * Unit edit screen. Used by unit_edit(), unit_add() and testdata()
  *
  * @param string $UUID The record UUID (fixed).
- * @param string $Name The Unit Name.
  * @param string $command 'add' or 'update'
  * @param string $heading Page heading title.
  * @Param string $error_message Blank or previous error.
  */
-function edit_screen($UUID, $Name, $command, $heading, $error_message) {
+function edit_screen($UUID, $command, $heading, $error_message) {
+
+    /*
+     * Get list of devices, we need it later
+     */
+    $sock = open_socket();
+    if ($sock == false) {
+	load("units.php");
+	return;
+    }
+
+    socket_write($sock, "DEVICE LIST", 4096);
+    $answer = "";
+    while (1) {
+	$line = socket_read($sock, 4096);
+	if ($line === '')
+	    break;
+	$answer .= $line;
+    }
+    socket_close($sock);
+    $devices = explode("\r\n", $answer);
+
+    /*
+     * Get current unit data
+     */
+    $sock = open_socket();
+    if ($sock == false) {
+	load("units.php");
+	return;
+    }
+
+    socket_write($sock, "UNIT GET ".$UUID, 4096);
+    $answer = "";
+    while (1) {
+	$line = socket_read($sock, 4096);
+	if ($line === '')
+	    break;
+	$answer .= $line;
+    }
+    socket_close($sock);
+    $reply = explode("\r\n", $answer);
 
     $outstr  = build_header($heading);
     $outstr .= '    <div id="errors">'.PHP_EOL;
@@ -246,14 +327,179 @@
     $outstr .= '    <div id="etable">'.PHP_EOL;
     $outstr .= '     <form method="POST" action="units.php">'.PHP_EOL;
     $outstr .= '      <table class="editor">'.PHP_EOL;
-    $outstr .= '       <tr class="editor">'.PHP_EOL;
-    $outstr .= '        <td class="editname">UUID</td>'.PHP_EOL;
-    $outstr .= '        <td class="editfield">'.$UUID.'</td>'.PHP_EOL;
-    $outstr .= '       </tr>'.PHP_EOL;
-    $outstr .= '       <tr class="editor">'.PHP_EOL;
-    $outstr .= '        <td class="editname">Unit Name</td>'.PHP_EOL;
-    $outstr .= '        <td class="editfield"><input type="text" name="Name" size="50" value="'.$Name.'"></td>'.PHP_EOL;
-    $outstr .= '       </tr>'.PHP_EOL;
+
+    if (startsWith($reply[0], "213")) {
+	$i = 1;
+	while (1) {
+	    if (strcmp($reply[$i], ".") == 0)
+		break;
+	    $f = explode(",", $reply[$i]);
+
+	    if ($f[0] == "NAME") {
+    		$outstr .= '       <tr class="editor">'.PHP_EOL;
+    		$outstr .= '        <td class="editname">Unit Name</td>'.PHP_EOL;
+    		$outstr .= '        <td class="editfield"><input type="text" name="Name" size="50" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "VOLUME") {
+    		$outstr .= '       <tr class="editor">'.PHP_EOL;
+    		$outstr .= '        <td class="editname">Unit Volume</td>'.PHP_EOL;
+    		$outstr .= '        <td class="editfield"><input type="text" name="Volume" size="5" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "AIR_ADDRESS") {
+    		$outstr .= '       <tr class="editor">'.PHP_EOL;
+    		$outstr .= '        <td class="editname">Air Sensor Address</td>'.PHP_EOL;
+    		$outstr .= '        <td class="editfield"><select name="AirAddress">'.PHP_EOL;
+		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
+		if (startsWith($devices[0], "212")) {
+		    $j = 1;
+		    while (1) {
+	    	    	if (strcmp($devices[$j], ".") == 0)
+			    break;
+		    	$g = explode(",", $devices[$j]);
+		    	if ($g[5] == "IN_ANALOG") {
+			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
+			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
+		    	}
+		    	$j++;
+		    }
+		}
+    		$outstr .= '        </select></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "BEER_ADDRESS") {
+                $outstr .= '       <tr class="editor">'.PHP_EOL;
+                $outstr .= '        <td class="editname">Beer Sensor Address</td>'.PHP_EOL;
+                $outstr .= '        <td class="editfield"><select name="BeerAddress">'.PHP_EOL;
+                $outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
+                if (startsWith($devices[0], "212")) {
+                    $j = 1;
+                    while (1) {
+                        if (strcmp($devices[$j], ".") == 0)
+                            break;
+                        $g = explode(",", $devices[$j]);
+			if ($g[5] == "IN_ANALOG") {
+			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
+                            $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
+                        }
+                        $j++;
+                    }
+		}
+		$outstr .= '        </select></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "HEATER_ADDRESS") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Heater Switch Address</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><select name="HeaterAddress">'.PHP_EOL;
+		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
+		if (startsWith($devices[0], "212")) {
+		    $j = 1;
+		    while (1) {
+			if (strcmp($devices[$j], ".") == 0)
+			    break;
+			$g = explode(",", $devices[$j]);
+			if (($g[5] == "OUT_ANALOG") || ($g[5] == "OUT_BIN")) {
+			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
+			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
+			}
+			$j++;
+		    }
+		}
+		$outstr .= '        </select></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "COOLER_ADDRESS") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Cooler Switch Address</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><select name="CoolerAddress">'.PHP_EOL;
+		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
+		if (startsWith($devices[0], "212")) {
+		    $j = 1;
+		    while (1) {
+			if (strcmp($devices[$j], ".") == 0)
+			    break;
+			$g = explode(",", $devices[$j]);
+			if (($g[5] == "OUT_ANALOG") || ($g[5] == "OUT_BIN")) {
+			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
+			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
+			}
+			$j++;
+		    }
+		}
+		$outstr .= '        </select></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "FAN_ADDRESS") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Fan Switch Address</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><select name="FanAddress">'.PHP_EOL;
+		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
+		if (startsWith($devices[0], "212")) {
+		    $j = 1;
+		    while (1) {
+			if (strcmp($devices[$j], ".") == 0)
+			    break;
+			$g = explode(",", $devices[$j]);
+			if (($g[5] == "OUT_ANALOG") || ($g[5] == "OUT_BIN")) {
+			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
+			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
+			}
+			$j++;
+		    }
+		}
+		$outstr .= '        </select></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "DOOR_ADDRESS") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Door Sensor Address</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><select name="DoorAddress">'.PHP_EOL;
+		$outstr .= '         <option value="">Not Assigned</option>'.PHP_EOL;
+		if (startsWith($devices[0], "212")) {               
+		    $j = 1;                                                                     
+		    while (1) {                                                                                     
+		    	if (strcmp($devices[$j], ".") == 0)                                                                                         
+			    break;
+		    	$g = explode(",", $devices[$j]);
+		    	if ($g[5] == "IN_BIN") {
+			    ($f[1] == $g[0]) ? $se = " selected" : $se = "";
+			    $outstr .= '         <option value="'.$g[0].'"'.$se.'>'.$g[1].' '.$g[4].'</option>'.PHP_EOL;
+		    	}
+		    	$j++;
+		    }
+		}
+		$outstr .= '        </select></td>'.PHP_EOL;                        
+		$outstr .= '       </tr>'.PHP_EOL;                                  
+	    }
+	    if ($f[0] == "TEMP_SET_MIN") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Min. temp setting</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><input type="text" name="TempSetMin" size="5" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "TEMP_SET_MAX") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Max. temp setting</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><input type="text" name="TempSetMax" size="5" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "IDLE_RANGE_L") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Idle Range Low</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><input type="text" name="IdleRangeL" size="5" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "IDLE_RANGE_H") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Idle Range High</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><input type="text" name="IdleRangeH" size="5" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    $i++;
+	}
+    }
     $outstr .= '       <tr class="editor">'.PHP_EOL;
     $outstr .= '        <td class="editname"><input type="submit" value="Save" name="key"></td>'.PHP_EOL;
     $outstr .= '        <td class="editfield"><input type="submit" value="Cancel" name="key">';
@@ -278,27 +524,9 @@
  * @param string $_GET['UUID'] The UUID of the Unit.
  */
 function unit_edit() {
-
-    global $arr;
-
     if ($_GET['action'] == 'edit') {
-
-	if (startsWith($arr[0], "212")) {
-	    $j = 1;
-	    while (1) {
-		if (strcmp($arr[$j], ".") == 0)
-		    break;
-		$f = explode(",", $arr[$j]);
-		if (strcmp($f[0], $_GET['UUID']) == 0) {
-		    edit_screen($f[0], $f[1], 'update', 'ThermFerm - Edit Unit', '');
-		    return;
-		}
-		$j++;
-	    }
-	} else {
-	    load('units.php');
-	}
-
+	edit_screen($_GET['UUID'], 'update', 'ThermFerm - Edit Unit', '');
+	return;
     } else {
 	load('units.php');
     }
@@ -357,6 +585,7 @@
     $outstr .= '        <td class="editname">Unit Name</td>'.PHP_EOL;
     $outstr .= '        <td class="editfield"><input type="text" name="Name" size="50" value=""></td>'.PHP_EOL;
     $outstr .= '        <td class="editsub"><input type="submit" value="Add" name="key"></td>'.PHP_EOL;
+    $outstr .= '<input type="hidden" value="0.0" name="Volume">';
     $outstr .= '<input type="hidden" value="testdata" name="action">';
     $outstr .= '<input type="hidden" value="add" name="command">';
     $outstr .= '<input type="hidden" value="00000000-0000-0000-0000-000000000000" name="UUID">';

mercurial