X10 Server - IOT device to leverage a collection of old X10 devices for home automation and lighting control.

Dependencies:   IniManager mbed HTTPClient SWUpdate mbed-rtos Watchdog X10 SW_HTTPServer SW_String EthernetInterface TimeInterface SSDP

X10 Server

See the X10 Server Nodebook page

Revision:
7:16129d213e6a
Parent:
4:5da66fab599c
Child:
8:a45fe77efcc5
--- a/WebPages.cpp	Sat Sep 01 01:46:33 2018 +0000
+++ b/WebPages.cpp	Wed Feb 27 18:24:32 2019 +0000
@@ -2,7 +2,13 @@
 #include "mbed.h"
 
 #include "EthernetInterface.h"
+#include "SW_String.h"
+#include "X10.h"
 #include "WebPages.h"
+#include "IniManager.h"         // v20
+
+extern INI ini;
+extern X10Interface cm17a;
 
 extern EthernetInterface eth;
 extern const char * BUILD_DATE;
@@ -11,6 +17,7 @@
 extern const char * My_SerialNum;
 extern int Server_Port;
 
+extern bool swUpdateCheck;
 
 // ##########################################
 // This test version controls the LEDs
@@ -23,55 +30,6 @@
     "Cache-Control: no-cache\r\n";
 
 
-// sprintf(buf, ROOTPAGE, "NodeName", "NodeName", "BuildDate", 
-static const char ROOTPAGE[] =
-    "<!DOCTYPE html>\r\n"
-    "<html><head><title>%s</title>\r\n"
-    "</head>\r\n"
-    "<body>\r\n"
-    "<h1>%s</h1>"
-    "This project demonstrates the Smartware web server and the Smartware SSDP discovery server.\n"
-    "You should be able to scan the network (e.g. in Windows Explorer) and find this device.\n"
-    "Then you can click on it to open this web page to interact with it.\n"
-    "<br/><br/>Build %s<br/><br/>\n"
-    "<font size='+5'>\n"
-    "<table><tr>\n"
-    "<td>"
-    "<button onclick=\"window.location.href='/?LED=1&CMD=1'\">LED 1 On</button><br/>\n"
-    "<button onclick=\"window.location.href='/?LED=1&CMD=0'\">LED 1 Off</button><br/>\n"
-    "</td><td>"
-    "<button onclick=\"window.location.href='/?LED=2&CMD=1'\">LED 2 On</button><br/>\n"
-    "<button onclick=\"window.location.href='/?LED=2&CMD=0'\">LED 2 Off</button><br/>\n"
-    "</td><td>"
-    "<button onclick=\"window.location.href='/?LED=3&CMD=1'\">LED 3 On</button><br/>\n"
-    "<button onclick=\"window.location.href='/?LED=3&CMD=0'\">LED 3 Off</button><br/>\n"
-    "</td><td>"
-    "<button onclick=\"window.location.href='/?LED=4&CMD=1'\">LED 4 On</button><br/>\n"
-    "<button onclick=\"window.location.href='/?LED=4&CMD=0'\">LED 4 Off</button><br/>\n"
-    "</td>"
-    "</tr></table>\n"
-    "</font>\n"
-    "<form method='get'>\n"
-    "<table>\n"
-    "<tr><td>Set LED</td>\n"
-    "<td><select name='LED'>\n"
-    "   <option value='1'>1</option>\n"
-    "   <option value='2'>2</option>\n"
-    "   <option value='3'>3</option>\n"
-    "   <option value='4'>4</option>\n"
-    " </select>\n"
-    " \n"
-    " <select name='CMD'>\n"
-    "   <option value='0'>Off</option>\n"
-    "   <option value='1'>On</option>\n"
-    " </select>\n"
-    "</td></tr>\n"
-    "<tr><td>&nbsp;</td><td><input type='submit' value='Apply'></td></tr>\n"
-    "</table>\n"
-    "</form>\n"
-    "</body>\n"
-    "</html>\n"
-    "";
 
 
 // The /setup.xml file
@@ -92,7 +50,7 @@
     "  <modelDescription>Special thing</modelDescription>\n"   ///<
     "  <modelName>Smart Node</modelName>\n"                                ///<
     "  <modelNumber>1.0.0</modelNumber>\n"
-#if 0
+#if 1
     "  <modelURL>http://www.smart-family.net</modelURL>\n"                  ///< This causes it to fail to send completely
 #endif
     "  <UDN>uuid:Socket-1_0-%s</UDN>\n"
@@ -215,43 +173,91 @@
 HTTPServer::CallBackResults RootPage(HTTPServer *svr, HTTPServer::CallBackType type, char * path,
                        const HTTPServer::namevalue *queryParams, int queryParamCount)
 {
-    #define bufSize (sizeof(ROOTPAGE) + 100)
-    char * BigBuffer = (char *)malloc(bufSize);
+    char buf[100];
+    int count;
     HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR;
-    if (!BigBuffer) {
-        printf("cannot allocate %d bytes\n", bufSize);
-        return ret;
-    }
-    
-    int led, cmd;
-    int mask = 0;
-    for (int i=0; i<queryParamCount; i++) {
-        if (strcmp(queryParams[i].name, "LED") == 0) {
-            led = atoi(queryParams[i].value);
-            mask |= 1;
-        } else if (strcmp(queryParams[i].name, "CMD") == 0) {
-            cmd = atoi(queryParams[i].value);
-            mask |= 2;
-        }
-    }
-    if (mask == 3) {
-        switch (led) {
-            case 1:
-            case 2:
-            case 3:
-            case 4:
-                leds[led - 1] = cmd;
-                break;
-            default:
-                break;
-        }
-    }
     
     switch (type) {
         case HTTPServer::SEND_PAGE:
-            svr->header(HTTPServer::OK, "OK", hdrTypeHTML_NoCache);
-            snprintf(BigBuffer, bufSize, ROOTPAGE, PROG_NAME, PROG_NAME, BUILD_DATE);            
-            svr->send(BigBuffer);
+            if (0 == strcmp(svr->GetParameter("SWUpdate"),"CheckNow")) {
+                swUpdateCheck = true;
+                svr->header(HTTPServer::Found, "Found", "Location: /\r\n");
+                svr->send("\r\n");
+                break;
+            }
+            count = svr->GetParameterCount();
+            printf("Data Transfer: %d parameters\r\n", count);
+            if (count) {
+                for (int i=0; i<count; i++) {
+                    const HTTPServer::namevalue * nv = svr->GetParameter(i);
+                    printf("  %d: %s => %s\r\n", i, nv->name, nv->value);
+                }
+                const char * p = svr->GetParameter("House");
+                if (p && strlen(p) == 1) {
+                    char cmdBuf[7];     // "HUU +6"
+                    strcpy_s(cmdBuf, sizeof(cmdBuf), p);
+                    p = svr->GetParameter("Unit");
+                    if (p && strlen(p) >= 1 && strlen(p) <= 2) {
+                        strcat_s(cmdBuf, sizeof(cmdBuf), p);
+                        p = svr->GetParameter("Cmd");
+                        if (p && strlen(p) >= 1 && strlen(p) <= 2) {
+                            strcat_s(cmdBuf, sizeof(cmdBuf), " ");
+                            strcat_s(cmdBuf, sizeof(cmdBuf), p);
+                            printf("Web Command: '%s'\r\n", cmdBuf);
+                            cm17a.ParseCommand(cmdBuf);
+                            svr->header(HTTPServer::Found, "Found", "Location: /\r\n");
+                            svr->send("\r\n");
+                            break;
+                        }
+                    }
+                }
+            }
+
+            svr->header(HTTPServer::OK, "OK", "Content-Type: text/html\r\n");
+            svr->send("<!DOCTYPE html>\r\n<html><head><title>X10 Server Info</title></head>\r\n");
+            svr->send("<body>\r\n");
+            svr->send("<h1>X10 Server Info</h1>\r\n");
+            svr->send("<blockquote>\r\n");
+            svr->send("<table border='1'>\r\n");
+            svr->send("<tr><th><h2>Command</h2></th></tr>\r\n");
+            svr->send("<tr><td>\r\n");
+            svr->send("<form method='get'>\r\n");
+            svr->send("<table border='1'><tr><th>House</th><th>Unit</th><th>Cmd</th><th>&nbsp;</th></tr>\r\n");
+            svr->send("<tr><td align='center'><select name='House'>\r\n");
+            for (int i = 'A'; i <= 'P'; i++) {
+                snprintf(buf, 100, "<option value='%c'>%c</option>\r\n", i, i);
+                svr->send(buf);
+            }
+            svr->send("</select></td>\r\n");
+            svr->send("<td><select name='Unit'>\r\n");
+            for (int i = 1; i <= 16; i++) {
+                snprintf(buf, 100, "<option value='%d'>%d</option>\r\n", i, i);
+                svr->send(buf);
+            }
+            svr->send("</select></td>\r\n");
+
+            svr->send("<td><select name='Cmd'>\r\n");
+            for (int i = -6; i <= 7; i++) {
+                if (i < 0)
+                    snprintf(buf, 100, "<option value='%+d'>%+d</option>\r\n", i, i);
+                else if (i == 0) 
+                    snprintf(buf, 100, "<option value='%d' selected>%d</option>\r\n", i, i);
+                else if (i == 1)
+                    snprintf(buf, 100, "<option value='%d'>%d</option>\r\n", i, i);
+                else // if (i > 1)
+                    snprintf(buf, 100, "<option value='%+d'>%+d</option>\r\n", i-1, i-1);
+                svr->send(buf);
+            }
+            svr->send("</select></td>\r\n");
+
+            svr->send("<td><input type='Submit' value='Send'></td>\r\n");
+            svr->send("</tr></table>\r\n");
+            svr->send("</form>\r\n");
+            svr->send("</td></tr></table>\r\n");
+            svr->send("<br/><br/><a href='/info'>info Page</a> | <a href='/setup.xml'>setup.xml</a>\r\n");
+            svr->send("</blockquote>\r\n");
+            svr->send("X10 Server, Copyright &copy; 2019 by Smartware Computing, all rights reserved.");
+            svr->send("</body></html>");
             ret = HTTPServer::ACCEPT_COMPLETE;
             break;
         case HTTPServer::CONTENT_LENGTH_REQUEST:
@@ -264,7 +270,102 @@
             ret = HTTPServer::ACCEPT_ERROR;
             break;
     }
-    if (BigBuffer)
-        free(BigBuffer);
     return ret;
 }
+
+
+HTTPServer::CallBackResults InfoPage(HTTPServer *svr, HTTPServer::CallBackType type, char * path,
+                       const HTTPServer::namevalue *queryParams, int queryParamCount)
+{
+    char lineBuf[60];
+    char buf[4000] = "";
+    HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR;
+    FILE * fh;
+    
+    switch (type) {
+        case HTTPServer::SEND_PAGE:
+            svr->header(HTTPServer::OK, "OK", "Content-Type: text/html\r\n");
+            strcpy_s(buf, sizeof(buf), "<!DOCTYPE html>\r\n<html><head><title>X10 Server Info</title></head>\r\n");
+            strcat_s(buf, sizeof(buf), "<body>\r\n");
+            strcat_s(buf, sizeof(buf), "<h1>X10 Server Info</h1>\r\n");
+            strcat_s(buf, sizeof(buf), "<table border='1' width='100%'>\r\n");
+            strcat_s(buf, sizeof(buf), "<tr><th>Configuration</th><th>Software</th></tr>\r\n");
+            strcat_s(buf, sizeof(buf), "<tr><td valign='top' width='50%'><pre>\r\n");
+            fh = fopen("/local/X10svr.ini", "rt");
+            if (fh) {
+                char fileBuf[60];
+                while(fgets(fileBuf, sizeof(fileBuf), fh)) {
+                    strcat_s(buf, sizeof(buf), fileBuf);
+                }
+                fclose(fh);
+            }
+            strcat_s(buf, sizeof(buf), "</pre>\r\n");
+            strcat_s(buf, sizeof(buf), "</td>\r\n");
+            strcat_s(buf, sizeof(buf), "<td valign='top' width='50%'><pre>\r\n");
+            if (INI::INI_SUCCESS == ini.ReadString("SWUpdate", "name", lineBuf, sizeof(lineBuf))) {
+                strcat_s(buf, sizeof(buf), "name=");
+                strcat_s(buf, sizeof(buf), lineBuf);
+                strcat_s(buf, sizeof(buf), "\r\nversion=");
+                lineBuf[6] = '\0';
+                char fname[45];
+                snprintf(fname, sizeof(fname), "/local/%s.ver", lineBuf);
+                fh = fopen(fname, "rt");
+                if (fh) {
+                    while(fgets(lineBuf, sizeof(lineBuf), fh)) {
+                        strcat_s(buf, sizeof(buf), lineBuf);
+                    }
+                    fclose(fh);
+                }
+            }
+            strcat_s(buf, sizeof(buf), "</pre>\r\n");
+            strcat_s(buf, sizeof(buf), "<img src='/icon.png'>");
+            strcat_s(buf, sizeof(buf), "</td></tr>\r\n");
+            strcat_s(buf, sizeof(buf), "<tr>\r\n");
+            strcat_s(buf, sizeof(buf), "<td><a href='/software'>Software Update Check</a></td>\r\n");
+            strcat_s(buf, sizeof(buf), "<td><a href='/'>Home Page</a> | ");
+            strcat_s(buf, sizeof(buf), "<a href='/setup.xml' target='_xml'>view setup.xml</a>\r\n");
+            strcat_s(buf, sizeof(buf), "</td></tr></table>\r\n");
+            strcat_s(buf, sizeof(buf), "</body></html>");
+            printf("big buf size is %d bytes\r\n", strlen(buf));
+            svr->send(buf);
+            ret = HTTPServer::ACCEPT_COMPLETE;
+            break;
+        case HTTPServer::CONTENT_LENGTH_REQUEST:
+            ret = HTTPServer::ACCEPT_COMPLETE;
+            break;
+        case HTTPServer::DATA_TRANSFER:
+            ret = HTTPServer::ACCEPT_COMPLETE;
+            break;
+        default:
+            ret = HTTPServer::ACCEPT_ERROR;
+            break;
+    }
+    return ret;
+}
+
+
+HTTPServer::CallBackResults SoftwarePage(HTTPServer *svr, HTTPServer::CallBackType type, char * path,
+                       const HTTPServer::namevalue *queryParams, int queryParamCount)
+{
+    HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR;
+    
+    switch (type) {
+        case HTTPServer::SEND_PAGE:
+            swUpdateCheck = true;
+            printf("SW Update Check scheduled.\r\n");
+            svr->header(HTTPServer::Found, "Found", "Location: /\r\n");
+            svr->send("\r\n");
+            ret = HTTPServer::ACCEPT_COMPLETE;
+            break;
+        case HTTPServer::CONTENT_LENGTH_REQUEST:
+            ret = HTTPServer::ACCEPT_COMPLETE;
+            break;
+        case HTTPServer::DATA_TRANSFER:
+            ret = HTTPServer::ACCEPT_COMPLETE;
+            break;
+        default:
+            ret = HTTPServer::ACCEPT_ERROR;
+            break;
+    }
+    return ret;
+}