Added device configuration

Sat, 02 Aug 2014 22:33:15 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 02 Aug 2014 22:33:15 +0200
changeset 174
244de612c572
parent 173
7259ee8778e9
child 175
b73490398368

Added device configuration

thermferm/rdconfig.c file | annotate | diff | comparison | revisions
thermferm/server.c file | annotate | diff | comparison | revisions
thermferm/thermferm.c file | annotate | diff | comparison | revisions
www-thermferm/css/style.css file | annotate | diff | comparison | revisions
www-thermferm/devices.php file | annotate | diff | comparison | revisions
--- a/thermferm/rdconfig.c	Fri Aug 01 22:53:58 2014 +0200
+++ b/thermferm/rdconfig.c	Sat Aug 02 22:33:15 2014 +0200
@@ -1035,7 +1035,7 @@
 	if ((!xmlStrcmp(cur->name, (const xmlChar *)"PRESENT"))) {
 	    key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
 	    for (i = 0; i < 4; i++) {
-		if (! xmlStrcmp(key, (const xmlChar *)DEVDIR[i])) {
+		if (! xmlStrcmp(key, (const xmlChar *)DEVPRESENT[i])) {
 		    device->present = i;
 		    break;
 		}
--- a/thermferm/server.c	Fri Aug 01 22:53:58 2014 +0200
+++ b/thermferm/server.c	Sat Aug 02 22:33:15 2014 +0200
@@ -38,6 +38,10 @@
 extern const char	UNITMODE[5][8];
 extern const char	UNITmode[5];
 extern const char	TEMPSTATE[3][8];
+extern const char	DEVTYPE[7][6];
+extern const char	DEVPRESENT[4][6];
+extern const char	DEVDIR[7][11];
+
 
 int			s;		/* connected socket			*/
 int			ls;		/* listen socket			*/
@@ -277,81 +281,263 @@
 
 
 
+int delete_Device(char *uuid)
+{
+    devices_list	*current = Config.devices;
+    devices_list	*previous = NULL;
+
+    while (current) {
+	if (strcmp(current->uuid, uuid) == 0) {
+	    if (previous == NULL) {
+		Config.devices = current->next;
+		free(current->uuid);
+		current->uuid = NULL;
+		free(current->address);
+		current->address = NULL;
+		free(current->description);
+		current->description = NULL;
+		free(current->comment);
+		current->comment = NULL;
+		free(current);
+		return 1;
+	    } else {
+		free(current->uuid);
+		current->uuid = NULL;
+		free(current->address);
+		current->address = NULL;
+		free(current->description);
+		current->description = NULL;
+		free(current->comment);
+		current->comment = NULL;
+		previous->next = current->next;
+		free(current);
+		current = previous->next;
+		return 1;
+	    }
+	} else {
+	    previous = current;
+	    current = current->next;
+	}
+    }
+    return 0;
+}
+
+
+
 /*
- * GET AIR uuid
- * GET BEER uuid
- * GET LED1 uuid
- * GET LED2 uuid
- * GET LED3 uuid
- * GET MODE uuid
- * GET TARGET uuid
+ * DEVICE ADD type
+ * DEVICE DEL uuid
+ * DEVICE LIST
+ * DEVICE GET uuid
+ * DEVICE PUT uuid
  */
-int cmd_get(char *buf)
+int cmd_device(char *buf)
 {
-    char	*opt, *uuid;
-    units_list	*unit;
+    char		*opt, *param, *kwd, *val, ibuf[SS_BUFSIZE];
+    devices_list	*device, *tmpd;
+    socklen_t		fromlen;
+    int			i, rlen, ival;
+    uuid_t		uu;
 
     opt = strtok(buf, " \0");
     opt = strtok(NULL, " \0");
-    uuid = strtok(NULL, "\0");
+
+    if (opt == NULL) {
+	srv_send((char *)"502 Missing command option");
+	return 1;
+    }
+    param = strtok(NULL, "\0");
 
-    if (uuid == NULL) {
-	srv_send((char *)"502 Missing command option");
+    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 *)".");
+	return 0;
+    }
+
+    if (param == NULL) {
+	srv_send((char *)"502 Missing command parameter");
 	return 1;
     }
 
-    for (unit = Config.units; unit; unit = unit->next) {
-	if (strcmp(uuid, unit->uuid) == 0) {
-
-	    if (strcmp(opt, (char *)"AIR") == 0) {
-		if (unit->air_state == 0)
-		    srv_send((char *)"215 AIR,%.3f", unit->air_temperature / 1000.0);
-		else
-		    srv_send((char *)"215 AIR,NA");
-		return 0;
-
-	    } else if (strcmp(opt, (char *)"BEER") == 0) {
-		if (unit->beer_state == 0)
-		    srv_send((char *)"215 BEER,%.3f", unit->beer_temperature / 1000.0);
-		else
-		    srv_send((char *)"215 BEER,NA");
-		return 0;
-
-	    } else if (strcmp(opt, (char *)"LED1") == 0) {
-		srv_send((char *)"215 HEATER,%d", (unit->heater_available && unit->heater_state) ? 1:0);
-		return 0;
+    if (strcmp(opt, (char *)"ADD") == 0) {
+	if ((strcmp(param, (char *)"RC433") == 0) || (strcmp(param, (char *)"DHT") == 0) ||
+	    (strcmp(param, (char *)"I2C") == 0) || (strcmp(param, (char *)"SPI") == 0)) {
 
-	    } else if (strcmp(opt, (char *)"LED2") == 0) {
-		srv_send((char *)"215 COOLER,%d", (unit->cooler_available && unit->cooler_state) ? 1:0);
-		return 0;
-
-	    } else if (strcmp(opt, (char *)"LED3") == 0) {
-		srv_send((char *)"215 FAN,%d", (unit->fan_available && unit->fan_state) ? 1:0);
-		return 0;
-
-	    } else if (strcmp(opt, (char *)"MODE") == 0) {
-		srv_send((char *)"215 MODE,%s", UNITMODE[unit->mode]);
-		return 0;
+	    device = (devices_list *)malloc(sizeof(devices_list));
+	    device->next = NULL;
+	    device->version = 1;
+	    device->uuid = malloc(37);
+	    uuid_generate(uu);
+	    uuid_unparse(uu, device->uuid);
+	    for (i = 0; i < 7; i++) {
+		if (strcmp(param, DEVTYPE[i]) == 0) {
+		    device->type = i;
+		    break;
+		}
+	    }
+	    device->direction = DEVDIR_UNDEF;
+	    device->value = device->subdevice = device->inuse = 0;
+	    device->present = DEVPRESENT_UNDEF;
+	    device->address = xstrcpy((char *)"Enter address here");
+	    device->gpiopin = -1;
+	    device->description = xstrcpy((char *)"Describe me here");
+	    device->comment = xstrcpy((char *)"Comment here");
 
-	    } else if (strcmp(opt, (char *)"TARGET") == 0) {
-		if (unit->mode == UNITMODE_BEER) {
-		    srv_send((char *)"215 TARGET,%.3f", unit->beer_set);
-		} else if (unit->mode == UNITMODE_FRIDGE) {
-		    srv_send((char *)"215 TARGET,%.3f", unit->fridge_set);
-		} else if (unit->mode == UNITMODE_PROFILE) {
-		    srv_send((char *)"215 TARGET,%.3f", unit->prof_target);
-		} else {
-		    srv_send((char *)"215 TARGET,NA");
+	    if (Config.devices == NULL) {
+		Config.devices = device;
+	    } else {
+	        for (tmpd = Config.devices; tmpd; tmpd = tmpd->next) {
+	    	    if (tmpd->next == NULL) {
+	    		tmpd->next = device;
+    			break;
+		    }
 		}
-		return 0;
 	    }
+	    syslog(LOG_NOTICE, "Device with uuid %s added", device->uuid);
+	    srv_send((char *)"211 Device with uuid %s added", device->uuid);
+	    return 0;
 
-	    srv_send((char *)"502 Unknown command option");
+	} else {
+	    srv_send((char *)"506 Wrong device parameter");
 	    return 1;
 	}
     }
 
-    srv_send((char *)"440 No such profile");
+    if (strcmp(opt, (char *)"DEL") == 0) {
+	
+	if (delete_Device(param)) {
+	    syslog(LOG_NOTICE, "Deleted device with %s", param);
+	    srv_send((char *)"211 Device %s deleted", param);
+	    return 0;
+	} else {
+	    srv_send((char *)"440 Delete Device: No such device %s", param);
+	    return 1;
+	}
+    }
+
+    if (strcmp(opt, (char *)"GET") == 0) {
+	for (device = Config.devices; device; device = device->next) {
+	    if (strcmp(device->uuid, param) == 0) {
+		srv_send((char *)"213 Device %s record follows:", device->uuid);
+		srv_send((char *)"TYPE,%s", DEVTYPE[device->type]);
+		srv_send((char *)"DIRECTION,%s", DEVDIR[device->direction]);
+		srv_send((char *)"VALUE,%d", device->value);
+		srv_send((char *)"PRESENT,%s", DEVPRESENT[device->present]);
+		srv_send((char *)"ADDRESS,%s", device->address);
+		srv_send((char *)"SUBDEVICE,%d", device->subdevice);
+		srv_send((char *)"GPIOPIN,%d", device->gpiopin);
+		srv_send((char *)"DESCRIPTION,%s", device->description);
+		srv_send((char *)"INUSE,%d", device->inuse);
+		srv_send((char *)"COMMENT,%s", device->comment);
+		srv_send((char *)"TIMESTAMP,%d", (int)device->timestamp);
+		srv_send((char *)".");
+		return 1;
+	    }
+	}
+	srv_send((char *)"440 No such device");
+	return 1;
+    }
+
+    if (strcmp(opt, (char *)"PUT") == 0) {
+	for (device = Config.devices; device; device = device->next) {
+	    if (strcmp(device->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 Device record");
+			    return 0;
+			}
+			kwd = strtok(ibuf, ",\0");
+			val = strtok(NULL, "\0");
+			if (kwd && val) {
+			    if (strcmp(kwd, (char *)"TYPE") == 0) {
+				for (i = 0; i < 7; i++) {
+				    if (strcmp(val, DEVTYPE[i]) == 0) {
+					device->type = i;
+					break;
+				    }
+				}
+
+			    } else if (strcmp(kwd, (char *)"DIRECTION") == 0) {
+				for (i = 0; i < 7; i++) {
+				    if (strcmp(val, DEVDIR[i]) == 0) {
+					device->direction = i;
+					break;
+				    }
+				}
+
+			    } else if (strcmp(kwd, (char *)"VALUE") == 0) {
+				if (sscanf(val, "%d", &ival) == 1)
+				    device->value = ival;
+
+			    } else if (strcmp(kwd, (char *)"PRESENT") == 0) {
+				for (i = 0; i < 4; i++) {
+				    if (strcmp(val, DEVPRESENT[i]) == 0)
+					device->present = i;
+				        break;
+				}
+
+			    } else if (strcmp(kwd, (char *)"ADDRESS") == 0) {
+				if (device->address)
+				    free(device->address);
+				device->address = xstrcpy(val);
+
+			    } else if (strcmp(kwd, (char *)"SUBDEVICE") == 0) {
+				if (sscanf(val, "%d", &ival) == 1)
+				    device->subdevice = ival;
+
+			    } else if (strcmp(kwd, (char *)"GPIOPIN") == 0) {
+				if (sscanf(val, "%d", &ival) == 1)
+				    device->gpiopin = ival;
+
+			    } else if (strcmp(kwd, (char *)"DESCRIPTION") == 0) {
+				if (device->description)
+				    free(device->description);
+				device->description = xstrcpy(val);
+
+			    } else if (strcmp(kwd, (char *)"COMMENT") == 0) {
+				if (device->comment)
+				    free(device->comment);
+				device->comment = xstrcpy(val);
+
+			    }
+			}
+		    }
+		}
+	    }
+	}
+	srv_send((char *)"440 No such device");
+	return 1;
+    }
+
+    srv_send((char *)"502 Unknown command option");
     return 1;
 }
 
@@ -359,7 +545,6 @@
 
 /*
  * LIST
- * LIST BUS
  * LIST LOG
  * LIST PROFILES
  * LIST UNIT
@@ -370,7 +555,6 @@
     units_list		*unit;
     profiles_list	*profile;
     prof_step		*step;
-    devices_list	*device;
     int			j;
     FILE		*fp;
 
@@ -388,17 +572,6 @@
 	srv_send((char *)".");
 	return 0;
 
-    } else if (strcmp(opt, (char *)"BUS") == 0) {
-	/*
-	 * Bus devices
-	 */
-	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 *)".");
-	return 0;
-
     } else if (strcmp(opt, (char *)"LOG") == 0) {
 	/*
 	 * Get the logfile data and emit only one line per hour.
@@ -1007,8 +1180,9 @@
 	    } else if (strncmp(buf, "DEL", 3) == 0) {
 		if (cmd_del(buf) == 0)
 		    wrconfig();
-	    } else if (strncmp(buf, "GET", 3) == 0) {
-		cmd_get(buf);
+	    } else if (strncmp(buf, "DEVICE", 6) == 0) {
+		if (cmd_device(buf) == 0)
+		    wrconfig();
 	    } else if (strncmp(buf, "HELP", 4) == 0) {
 		srv_send((char *)"100 Help text follows");
 		srv_send((char *)"Recognized commands:");
@@ -1018,19 +1192,13 @@
 		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 *)"GET AIR uuid                  Get Air temperature with uuid");
-		srv_send((char *)"GET BEER uuid                 Get Beer temperature with uuid");
-		srv_send((char *)"GET LED1 uuid                 Get LED 1 (cooler) state");
-		srv_send((char *)"GET LED2 uuid                 Get LED 2 (heater) state");
-		srv_send((char *)"GET LED3 uuid                 Get LED 3 (fan) state");
-		srv_send((char *)"GET MODE uuid                 Get Unit Mode");
-//		srv_send((char *)"GET SW1 uuid                  Get Switch 1 (cooler) state");
-//		srv_send((char *)"GET SW2 uuid                  Get Switch 2 (heater) state");
-//		srv_send((char *)"GET SW3 uuid                  Get Switch 3 (fan) state");
-		srv_send((char *)"GET TARGET uuid               Get Target temperature 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 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");
 		srv_send((char *)"LCD                           Get LCD screen (allways 4 rows of 20 characters)");
 		srv_send((char *)"LIST                          List all fermenter units");
-		srv_send((char *)"LIST BUS                      List 1-wire bus");
 		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");
--- a/thermferm/thermferm.c	Fri Aug 01 22:53:58 2014 +0200
+++ b/thermferm/thermferm.c	Sat Aug 02 22:33:15 2014 +0200
@@ -385,8 +385,10 @@
 		if (minutes == 60)
 		    minutes = 0;
 
-		if ((minutes == 15) || (minutes == 45))
+		if ((minutes == 15) || (minutes == 45)) {
+		    syslog(LOG_NOTICE, "minutes %d seconds %d", minutes, seconds);
 		    wrconfig();
+		}
 	    }
 	}
 	usleep(100000);
--- a/www-thermferm/css/style.css	Fri Aug 01 22:53:58 2014 +0200
+++ b/www-thermferm/css/style.css	Sat Aug 02 22:33:15 2014 +0200
@@ -69,6 +69,7 @@
     height: 320px;
     width: 978px;
     float: left;
+    overflow: auto;
 }
 
 #atable {
--- a/www-thermferm/devices.php	Fri Aug 01 22:53:58 2014 +0200
+++ b/www-thermferm/devices.php	Sat Aug 02 22:33:15 2014 +0200
@@ -30,7 +30,7 @@
     return;
 }
 
-socket_write($sock, "LIST BUS", 4096);
+socket_write($sock, "DEVICE LIST", 4096);
 $answer = "";
 while (1) {
     $line = socket_read($sock, 4096);
@@ -39,44 +39,544 @@
     $answer .= $line;
 }
 socket_close($sock);
+
+/*
+ * $arr contains the complete reply of the LIST BUS command
+ */
 $arr = explode("\r\n", $answer);
 
 
-$outstr  = build_header("ThermFerm - Devices Setup");
+if (isset($_GET['action'])) {
+    switch ($_GET['action']) {
+	case 'edit':            device_edit();
+				break;
+	default:                break;
+    }
+} elseif (isset($_POST['action'])) {
+    switch ($_POST['action']) {
+	case 'testdata':        testdata();
+				break;
+	default:                break;
+    }
+} else {
+    device_list();
+}
+
+exit;
+
+/****************************************************************************
+ *
+ */
+
+
+/*
+ * Device add
+ *
+ * @param string $_POST['Name'] The rpofile name
+ */
+function device_add() {
+
+    if ($_POST['key'] == 'Add') {
+		                                    
+	$cmd = "DEVICE ADD ".$_POST['Type'];
 
-$outstr .= '    <div id="errors">'.PHP_EOL;
-$outstr .= '    </div> <!-- errors -->'.PHP_EOL;
-$outstr .= '    <div id="etable">'.PHP_EOL;
+	$sock = open_socket();
+	if ($sock != false) {
+	    /*
+	     * Send command and absorb the result.
+	     */
+	    socket_write($sock, $cmd, 4096);
+	    while (1) {
+		$line = socket_read($sock, 4096);
+		if ($line === '')
+		    break;
+	    }
+	    socket_close($sock);
+	}
+    }
+
+    unset($_POST['UUID']);
+    unset($_POST['Name']);
+    unset($_POST['key']);
+    unset($_POST['command']);
+    load('devices.php');
+}
+
+
+
+/*
+ * Device update
+ *
+ * @param string $_POST['UUID'] The device UUID
+ * @param string $_POST['Type'] The device Type
+ * @param string $_POST['Direction'] The device IO Direction
+ * @param string $_POST['Value'] The device value
+ * @param string $_POST['Present'] The device Present state
+ * @param string $_POST['Address'] The device Address
+ * @param string $_POST['Subdevice'] The device Subaddress
+ * @param string $_POST['Gpiopin'] The device GPIO pin
+ * @param string $_POST['Description'] The device Description
+ * @param string $_POST['Comment'] The device Comment
+ * @param string $_POST['key'] The button pressed.
+ */
+function device_update() {
+    /*
+     * Build the update command
+     */
+    if ($_POST['key'] == 'Delete') {
+	$sock = open_socket();
+	if ($sock != false) {
+	    socket_write($sock, "DEVICE DEL ".$_POST['UUID'], 4096);
+	    /* Absorb response */
+	    while (1) {
+		$line = socket_read($sock, 4096);
+		if ($line === '')
+		    break;
+	    }
+	    socket_close($sock);
+	}
+    }
 
-$outstr .= '     <table class="setup">'.PHP_EOL;
-$outstr .= '      <tr class="trhead">'.PHP_EOL;
-$outstr .= '       <td class="setup">UUID</td>'.PHP_EOL;
-$outstr .= '       <td class="setup">Address</td>'.PHP_EOL;
-$outstr .= '       <td class="setup">Subdev</td>'.PHP_EOL;
-$outstr .= '       <td class="setup">Refcnt</td>'.PHP_EOL;
-$outstr .= '       <td class="setup">Comment</td>'.PHP_EOL;
-$outstr .= '      </tr>'.PHP_EOL;
+    if ($_POST['key'] == 'Save') {
+    	$sock = open_socket();
+    	if ($sock != false) {
+	    /*
+	     * Send command and absorb the result.
+	     */
+	    socket_write($sock, "DEVICE PUT ".$_POST['UUID'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "TYPE,".$_POST['Type'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "DIRECTION,".$_POST['Direction'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "VALUE,".$_POST['Value'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "PRESENT,".$_POST['Present'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "ADDRESS,".$_POST['Address'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "SUBDEVICE,".$_POST['Subdevice'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "GPIOPIN,".$_POST['Gpiopin'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "DESCRIPTION,".$_POST['Description'], 4096);
+	    usleep(20000);
+	    socket_write($sock, "COMMENT,".$_POST['Comment'], 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['Type']);
+    unset($_POST['Direction']);
+    unset($_POST['Value']);
+    unset($_POST['Present']);
+    unset($_POST['Address']);
+    unset($_POST['Subdevice']);
+    unset($_POST['Gpiopin']);
+    unset($_POST['Description']);
+    unset($_POST['Comment']);
+    unset($_POST['key']);
+    unset($_POST['command']);
+    load('devices.php');
+}
+
+
+
+/*
+ * Test input of a modified or new device.
+ *
+ * @param string $_POST['UUID'] Unique record UUID
+ * @param string $_POST['Type'] Device Type
+ * @param string $_POST['Direction']
+ * @param string $_POST['Value']
+ * @param string $_POST['Present']
+ * @param string $_POST['Address']
+ * @param string $_POST['Subdevice']
+ * @param string $_POST['Gpiopin']
+ * @param string $_POST['Description']
+ * @param string $_POST['Comment']
+ * @param string $_POST['key'] Key choice, Save or Cancel
+ * @param string $_POST['command'] Command used, 'add' or 'update'
+ *
+ * Return: 0 = Ok
+ *         1 = Missing data
+ *         2 = Address field too short
+ *         3 = Address/Subdevice already in use
+ *         4 = Description field too short
+ *         5 = Comment field too short
+ *        99 = Cancel key
+ */
+function test_thedata() {
+
+    global $arr;
+
+    if (isset($_POST['UUID']) && isset($_POST['Type']) && isset($_POST['Direction']) && isset($_POST['Value']) &&
+	isset($_POST['Present']) && isset($_POST['Address']) && isset($_POST['Subdevice']) && isset($_POST['Gpiopin']) &&
+	isset($_POST['Description']) && isset($_POST['Comment']) && isset($_POST['key']) && isset($_POST['command'])) {
+
+	if ($_POST['key'] == 'Cancel')
+	    return 99;
+
+	if (strlen($_POST['Address']) < 2)
+	    return 2;
+
+	if (startsWith($arr[0], "212")) {
+	    $j = 1;
+	    while (1) {
+		if (strcmp($arr[$j], ".") == 0)
+		    break;
+		$f = explode(",", $arr[$j]);
+		if (strcmp($f[0], $_POST['UUID']) && ($f[1] == $_POST['Address']) && ($f[2] == $_POST['Subdevice'])) {
+		    return 3;
+		}
+		$j++;
+	    }
+	}
+
+	if (strlen($_POST['Description']) < 2)
+	    return 4;
+
+	if (strlen($_POST['Comment']) < 2)
+	    return 5;
+
+    } else {
+	return 1;
+    }
+
+    return 0;
+}
+
+
+
+/*
+ * Test result from edit screen and do next action
+ */
+function testdata() {
+
+    $result = test_thedata();
+    $error = '';
 
-if (startsWith($arr[0], "212")) {
-    $j = 1;
+    switch ($result) {
+	case 0: if ($_POST['command'] == 'add') {
+		    device_add();
+		    return;
+		} else if ($_POST['command'] == 'update') {
+		    device_update();
+		    return;
+		}
+		break;
+	case 1: $error = 'Missing data';
+		break;
+	case 2: $error = 'The Address is too short';
+		break;
+	case 3: $error = 'The Address + Subdevice is already in use, choose another one';
+		break;
+	case 4:	$error = 'The Description is too short';
+		break;
+	case 5:	$error = 'The Comment is too short';
+		break;
+	case 99:        
+		load('devices.php');
+		break;
+    }
+
+    if ($_POST['command'] == 'add') {
+	$heading = 'ThermFerm - Add Device';
+    } else {
+	$heading = 'ThermFerm - Edit Device';
+    }
+
+    edit_screen($_POST['UUID'], $_POST['command'], $heading, $error);
+}
+
+
+
+/*
+ * Unit edit screen. Used by unit_edit(), unit_add() and testdata()
+ *
+ * @param string $UUID The record UUID (fixed).
+ * @param string $command 'add' or 'update'
+ * @param string $heading Page heading title.
+ * @Param string $error_message Blank or previous error.
+ */
+function edit_screen($UUID, $command, $heading, $error_message) {
+
+    $sock = open_socket();
+    if ($sock == false) {
+	load('devices.php');
+    }
+
+    socket_write($sock, "DEVICE GET ".$UUID, 4096);
+    $answer = "";
     while (1) {
-	if (strcmp($arr[$j], ".") == 0)
+	$line = socket_read($sock, 4096);
+	if ($line === '')
 	    break;
-	$f = explode(",", $arr[$j]);
-	$outstr .= '      <tr class="setup">'.PHP_EOL;
-	$outstr .= '       <td class="setup">'.$f[0].'</td>'.PHP_EOL;
-	$outstr .= '       <td class="setup">'.$f[1].'</td>'.PHP_EOL;
-	$outstr .= '       <td class="setup">'.$f[2].'</td>'.PHP_EOL;
-	$outstr .= '       <td class="setup">'.$f[3].'</td>'.PHP_EOL;
-	$outstr .= '       <td class="setup">'.$f[4].'</td>'.PHP_EOL;
-	$outstr .= '      </tr>'.PHP_EOL;
-	$j++;
+	$answer .= $line;
+    }
+    socket_close($sock);
+    $reply = explode("\r\n", $answer);
+
+    $outstr  = build_header($heading);
+    $outstr .= '    <div id="errors">'.PHP_EOL;
+    $outstr .= '     '.$error_message.PHP_EOL;
+    $outstr .= '    </div> <!-- errors -->'.PHP_EOL;
+    $outstr .= '    <div id="etable">'.PHP_EOL;
+    $outstr .= '     <form method="POST" action="devices.php">'.PHP_EOL;
+    $outstr .= '      <table class="editor">'.PHP_EOL;
+
+    if (startsWith($reply[0], "213")) {
+	$j = 1;
+	while (1) {
+	    if (strcmp($reply[$j], ".") == 0)
+		break;
+	    $f = explode(",", $reply[$j]);
+	    if ($f[0] == "TYPE") {
+		$type = $f[1];
+		/*
+		 * Only allow certain types to edit. Auto detected hardware cannot be changed.
+		 */
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Device Type</td>'.PHP_EOL;
+		if (($type == "W1") || ($type == "GPIO"))
+		    $outstr .= '        <td class="editfield"><input type="hidden" name="Type" value="'.$f[1].'">'.$f[1].'</td>'.PHP_EOL;
+		else
+		    $outstr .= '        <td class="editfield"><input type="text" name="Type" size="50" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "DIRECTION") {
+		$direction = $f[1];
+		/*
+		 * Only devices that cannot auto detect can be changed.
+		 */
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">IO Direction and mode</td>'.PHP_EOL;
+		if ($type == "W1")
+		    $outstr .= '        <td class="editfield"><input type="hidden" name="Direction" value="'.$f[1].'">'.$f[1].'</td>'.PHP_EOL;
+		else {
+		    $outstr .= '        <td class="editfield"><select name="Direction">'.PHP_EOL;
+		    if ($type == "GPIO") {
+			$se = ($f[1] == "UNDEF")?" selected":"";
+			$outstr .= '         <option value="UNDEF"'.$se.'>Undefined</option>'.PHP_EOL;
+			$se = ($f[1] == "IN_BIN")?" selected":"";
+			$outstr .= '         <option value="IN_BIN"'.$se.'>Binary input</option>'.PHP_EOL;
+			$se = ($f[1] == "OUT_BIN")?" selected":"";
+			$outstr .= '         <option value="OUT_BIN"'.$se.'>Binary output</option>'.PHP_EOL;
+			$se = ($f[1] == "OUT_PWM")?" selected":"";
+			$outstr .= '         <option value="OUT_PWM"'.$se.'>PWM output</option>'.PHP_EOL;
+		    }
+		    if ($type == "RC433") {
+			$se = ($f[1] == "UNDEF")?" selected":"";
+			$outstr .= '         <option value="UNDEF"'.$se.'>Undefined</option>'.PHP_EOL;
+			$se = ($f[1] == "OUT_BIN")?" selected":"";
+			$outstr .= '         <option value="OUT_BIN"'.$se.'>Binary output</option>'.PHP_EOL;
+		    }
+		    if ($type == "DHT") {
+			$se = ($f[1] == "UNDEF")?" selected":"";
+			$outstr .= '         <option value="UNDEF"'.$se.'>Undefined</option>'.PHP_EOL;
+			$se = ($f[1] == "IN_ANALOG")?" selected":"";
+			$outstr .= '         <option value="IN_ANALOG"'.$se.'>Analog input</option>'.PHP_EOL;
+		    }
+		    $outstr .= '        </select></td>'.PHP_EOL;
+		}
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "VALUE") {
+		/*
+		 * Only output can be changed
+		 */
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Value</td>'.PHP_EOL;
+		if (($direction == "OUT_BIN") || ($direction == "OUT_ANALOG") || ($direction == "OUT_PWM"))
+		    $outstr .= '        <td class="editfield"><input type="text" name="Value" size="50" value="'.$f[1].'"></td>'.PHP_EOL;
+		else
+		    $outstr .= '        <td class="editfield"><input type="hidden" name="Value" value="'.$f[1].'">'.$f[1].'</td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "PRESENT") {
+		/*
+		 * Only devices that cannot auto detect can be changed.
+		 */
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Device Present</td>'.PHP_EOL;
+		if (($type == "W1") || ($type == "GPIO"))
+		    $outstr .= '        <td class="editfield"><input type="hidden" name="Present" value="'.$f[1].'">'.$f[1].'</td>'.PHP_EOL;
+		else {
+		    $outstr .= '        <td class="editfield"><select name="Present">'.PHP_EOL;
+		    $se = ($f[1] == "UNDEF")?" selected":"";
+		    $outstr .= '         <option value="UNDEF"'.$se.'>Undefined</option>'.PHP_EOL;
+		    $se = ($f[1] == "NO")?" selected":"";
+		    $outstr .= '         <option value="NO"'.$se.'>Not present</option>'.PHP_EOL;
+		    $se = ($f[1] == "YES")?" selected":"";
+		    $outstr .= '         <option value="YES"'.$se.'>Present and Ok</option>'.PHP_EOL;
+		    $se = ($f[1] == "ERROR")?" selected":"";
+		    $outstr .= '         <option value="ERROR"'.$se.'>Present and Error</option>'.PHP_EOL;
+		    $outstr .= '        </select></td>'.PHP_EOL;
+		}
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "ADDRESS") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Address</td>'.PHP_EOL;
+		if (($type == "W1") || ($type == "GPIO"))
+		    $outstr .= '        <td class="editfield"><input type="hidden" name="Address" value="'.$f[1].'">'.$f[1].'</td>'.PHP_EOL;
+		else
+		    $outstr .= '        <td class="editfield"><input type="text" name="Address" size="50" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "SUBDEVICE") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Subdevice</td>'.PHP_EOL;
+		if (($type == "W1") || ($type == "GPIO"))
+		    $outstr .= '        <td class="editfield"><input type="hidden" name="Subdevice" value="'.$f[1].'">'.$f[1].'</td>'.PHP_EOL;
+		else
+		    $outstr .= '        <td class="editfield"><input type="text" name="Subdevice" size="5" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "GPIOPIN") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">GPIO pin</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><input type="text" name="Gpiopin" size="5" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;                  
+	    }
+	    if ($f[0] == "DESCRIPTION") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Description</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><input type="text" name="Description" size="50" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	    }
+	    if ($f[0] == "COMMENT") {
+		$outstr .= '       <tr class="editor">'.PHP_EOL;
+		$outstr .= '        <td class="editname">Comment</td>'.PHP_EOL;
+		$outstr .= '        <td class="editfield"><input type="text" name="Comment" size="50" value="'.$f[1].'"></td>'.PHP_EOL;
+		$outstr .= '       </tr>'.PHP_EOL;
+	     }
+	    $j++;
+	}
+    }
+
+    $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">';
+    $outstr .= '<input type="submit" value="Delete" name="key" style="margin-left: 100px;">';
+    $outstr .= '<input type="hidden" value="testdata" name="action">';
+    $outstr .= '<input type="hidden" value="'.$command.'" name="command">';
+    $outstr .= '<input type="hidden" value="'.$UUID.'" name="UUID"></td>'.PHP_EOL;
+    $outstr .= '       </tr>'.PHP_EOL;
+    $outstr .= '      </table>'.PHP_EOL;
+    $outstr .= '     </form>'.PHP_EOL;
+    $outstr .= '    </div> <!-- etable -->'.PHP_EOL;
+    $outstr .= build_footer();
+    echo $outstr;
+}
+
+
+
+/*
+ * Edit a Device. Fetches the record data and shows the edit screen.
+ *
+ * @param string $_GET['action'] Must be 'edit'.
+ * @param string $_GET['UUID'] The UUID of the Unit.
+ */
+function device_edit() {
+    if ($_GET['action'] == 'edit') {
+	edit_screen($_GET['UUID'], 'update', 'ThermFerm - Edit Device', '');
+	return;
+    } else {
+	load('devices.php');
     }
 }
 
-$outstr .= '     </table>'.PHP_EOL;
-$outstr .= '    </div> <!-- etable -->'.PHP_EOL;
-$outstr .= build_footer();
+
+
+/*
+ * @link edit device
+ * @link add device
+ */
+function device_list() {
+    global $arr;
+
+    $outstr  = build_header("ThermFerm - Devices Setup");
+    $outstr .= '    <div id="errors">'.PHP_EOL;
+    $outstr .= '    </div> <!-- errors -->'.PHP_EOL;
+    $outstr .= '    <div id="etable">'.PHP_EOL;
+    $outstr .= '     <table class="setup">'.PHP_EOL;
+    $outstr .= '      <tr class="trhead">'.PHP_EOL;
+    $outstr .= '       <td class="setup" style="width: 300px;">UUID</td>'.PHP_EOL;
+    $outstr .= '       <td class="setup" style="width: 120px;">Address</td>'.PHP_EOL;
+    $outstr .= '       <td class="setup" style="width: 30px;">Sub</td>'.PHP_EOL;
+    $outstr .= '       <td class="setup" style="width: 30px;">Ref</td>'.PHP_EOL;
+    $outstr .= '       <td class="setup" style="width: 300px;">Cmt</td>'.PHP_EOL;
+    $outstr .= '       <td class="setup" style="width: 35px;">Edit</td>'.PHP_EOL;
+    $outstr .= '      </tr>'.PHP_EOL;
 
-echo $outstr;
+    if (startsWith($arr[0], "212")) {
+    	$j = 1;
+    	while (1) {
+	    if (strcmp($arr[$j], ".") == 0)
+	    	break;
+	    $f = explode(",", $arr[$j]);
+	    $outstr .= '      <tr class="setup">'.PHP_EOL;
+	    $outstr .= '       <td class="setup">'.$f[0].'</td>'.PHP_EOL;
+	    $outstr .= '       <td class="setup">'.$f[1].'</td>'.PHP_EOL;
+	    $outstr .= '       <td class="setup">'.$f[2].'</td>'.PHP_EOL;
+	    $outstr .= '       <td class="setup">'.$f[3].'</td>'.PHP_EOL;
+	    $outstr .= '       <td class="setup">'.$f[4].'</td>'.PHP_EOL;
+	    if ($f[3] == 0)
+		$outstr .= '       <td class="setup"><a href="devices.php?action=edit&amp;UUID='.$f[0].'">Edit</a></td>'.PHP_EOL;
+	    else
+		$outstr .= '       <td class="setup">Busy</td>'.PHP_EOL;
+	    $outstr .= '      </tr>'.PHP_EOL;
+	    $j++;
+    	}
+    }
+
+    $outstr .= '     </table>'.PHP_EOL;
+    $outstr .= '    </div> <!-- etable -->'.PHP_EOL;
 
+    $outstr .= '    <div id="atable">'.PHP_EOL;
+    $outstr .= '     <form method="POST" action="devices.php">'.PHP_EOL;
+    $outstr .= '      <table class="editor">'.PHP_EOL;
+    $outstr .= '      <tr class="trhead"><td colspan="3">Add new Device</td></tr>'.PHP_EOL;
+    $outstr .= '       <tr class="editor">'.PHP_EOL;
+    $outstr .= '        <td class="editname">Select Device type</td>'.PHP_EOL;
+    $outstr .= '        <td class="editfield">'.PHP_EOL;
+    $outstr .= '         <select name="Type">'.PHP_EOL;
+    $outstr .= '          <option value="NA">Not Available</option>'.PHP_EOL;
+    $outstr .= '          <option value="RC433">433 Mhz Radio Controller</option>'.PHP_EOL;
+    $outstr .= '          <option value="DHT">DHTnn type sensor</option>'.PHP_EOL;
+    $outstr .= '          <option value="I2C">I2C bus device</option>'.PHP_EOL;
+    $outstr .= '          <option value="SPI">SPI bus device</option>'.PHP_EOL;
+    $outstr .= '         </select>'.PHP_EOL;
+    $outstr .= '        </td>'.PHP_EOL;
+    $outstr .= '        <td class="editsub"><input type="submit" value="Add" name="key"></td>'.PHP_EOL;
+    $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">';
+    $outstr .= '<input type="hidden" value="UNDEF" name="Direction">';
+    $outstr .= '<input type="hidden" value="0" name="Value">';
+    $outstr .= '<input type="hidden" value="UNDEF" name="Present">';
+    $outstr .= '<input type="hidden" value="address unknown" name="Address">';
+    $outstr .= '<input type="hidden" value="0" name="Subdevice">';
+    $outstr .= '<input type="hidden" value="-1" name="Gpiopin">';
+    $outstr .= '<input type="hidden" value="Describe me" name="Description">';
+    $outstr .= '<input type="hidden" value="Comment me" name="Comment">';
+    $outstr .= '       </tr>'.PHP_EOL;
+    $outstr .= '      </table>'.PHP_EOL;
+    $outstr .= '     </form>'.PHP_EOL;
+    $outstr .= '    </div> <!-- atable -->'.PHP_EOL;
+
+    $outstr .= build_footer();
+
+    echo $outstr;
+}
+

mercurial