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:
0:de1dfa2ab813
Child:
1:016d4400254b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebPages.cpp	Tue Jul 03 02:10:23 2018 +0000
@@ -0,0 +1,249 @@
+
+#include "mbed.h"
+
+#include "EthernetInterface.h"
+#include "WebPages.h"
+
+extern EthernetInterface eth;
+extern const char * BUILD_DATE;
+extern const char * PROG_NAME;
+extern const char * My_Name;
+extern const char * My_SerialNum;
+const int Server_Port = 80;
+
+
+// ##########################################
+// This test version controls the LEDs
+//
+DigitalOut leds[4] = { LED1, LED2, LED3, LED4 };
+
+
+static const char hdrTypeHTML_NoCache[] = 
+    "Content-Type: text/html\r\n"
+    "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/>\n"
+    "<form method='get'>\n"
+    "<table>\n"
+    "<tr><td>Build</td><td>%s</td></tr>\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
+//
+// sprintf(buf, SETUP_TEMPLATE, "FriendlyName", "udn_hexstring", "serialNum", "ip.ad.dr", portNum);
+static const char * SETUP_TEMPLATE =
+    "<?xml version=\"1.0\"?>\n"
+    "<root xmlns=\"urn:Belkin:device-1-0\">\n"
+    " <specVersion>\n"
+    "  <major>1</major>\n"
+    "  <minor>0</minor>\n"
+    " </specVersion>\n"
+    " <device>\n"
+    "  <deviceType>urn:Belkin:device:controllee:1</deviceType>\n"
+    "  <friendlyName>%s</friendlyName>\n"
+    "  <manufacturer>Belkin International Inc.</manufacturer>\n"            ///< must be "Belkin..." for Alexa discovery
+    "  <manufacturerURL>http://www.smart-family.net</manufacturerURL>\n"    ///<
+    "  <modelDescription>Special thing</modelDescription>\n"   ///<
+    "  <modelName>Smart Node</modelName>\n"                                ///<
+    "  <modelNumber>1.0.0</modelNumber>\n"
+#if 0
+    "  <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"
+    "  <serialNumber>%s</serialNumber>\n"
+    "  <iconList>\n"
+    "   <mimetype>jpg</mimetype>\n"
+    "   <width>100</width>\n"
+    "   <height>100</height>\n"
+    "   <depth>100</depth>\n"
+    "   <url>icon.jpg</url>\n"
+    "  </iconList>\n"
+    "  <presentationURL>http://%s:%d</presentationURL>\n"
+#if 0
+    "  <serviceList>\n"
+    "   <service>\n"
+    "    <serviceType>urn:Belkin:service:WiFiSetup:1</serviceType>\n"
+    "    <serviceId>urn:Belkin:serviceId:WiFiSetup1</serviceId>\n"
+    "    <controlURL>/upnp/control/WiFiSetup1</controlURL>\n"
+    "    <eventSubURL>/upnp/event/WiFiSetup1</eventSubURL>\n"
+    "    <SCPDURL>/setupservice.xml</SCPDURL>\n"
+    "   </service>\n"
+    "   <service>\n"
+    "    <serviceType>urn:Belkin:service:timesync:1</serviceType>\n"
+    "    <serviceId>urn:Belkin:serviceId:timesync1</serviceId>\n"
+    "    <controlURL>/upnp/control/timesync1</controlURL>\n"
+    "    <eventSubURL>/upnp/event/timesync1</eventSubURL>\n"
+    "    <SCPDURL>/timesyncservice.xml</SCPDURL>\n"
+    "   </service>\n"
+    "   <service>\n"
+    "    <serviceType>urn:Belkin:service:basicevent:1</serviceType>\n"
+    "    <serviceId>urn:Belkin:serviceId:basicevent1</serviceId>\n"
+    "    <controlURL>/upnp/control/basicevent1</controlURL>\n"
+    "    <eventSubURL>/upnp/event/basicevent1</eventSubURL>\n"
+    "    <SCPDURL>/eventservice.xml</SCPDURL>\n"
+    "   </service>\n"
+    "   <service>\n"
+    "    <serviceType>urn:Belkin:service:firmwareupdate:1</serviceType>\n"
+    "    <serviceId>urn:Belkin:serviceId:firmwareupdate1</serviceId>\n"
+    "    <controlURL>/upnp/control/firmwareupdate1</controlURL>\n"
+    "    <eventSubURL>/upnp/event/firmwareupdate1</eventSubURL>\n"
+    "    <SCPDURL>/firmwareupdate.xml</SCPDURL>\n"
+    "   </service>\n"
+    "   <service>\n"
+    "    <serviceType>urn:Belkin:service:rules:1</serviceType>\n"
+    "    <serviceId>urn:Belkin:serviceId:rules1</serviceId>\n"
+    "    <controlURL>/upnp/control/rules1</controlURL>\n"
+    "    <eventSubURL>/upnp/event/rules1</eventSubURL>\n"
+    "    <SCPDURL>/rulesservice.xml</SCPDURL>\n"
+    "   </service>\n"
+    "   <service>\n"
+    "    <serviceType>urn:Belkin:service:metainfo:1</serviceType>\n"
+    "    <serviceId>urn:Belkin:serviceId:metainfo1</serviceId>\n"
+    "    <controlURL>/upnp/control/metainfo1</controlURL>\n"
+    "    <eventSubURL>/upnp/event/metainfo1</eventSubURL>\n"
+    "    <SCPDURL>/metainfoservice.xml</SCPDURL>\n"
+    "   </service>\n"
+    "   <service>\n"
+    "    <serviceType>urn:Belkin:service:remoteaccess:1</serviceType>\n"
+    "    <serviceId>urn:Belkin:serviceId:remoteaccess1</serviceId>\n"
+    "    <controlURL>/upnp/control/remoteaccess1</controlURL>\n"
+    "    <eventSubURL>/upnp/event/remoteaccess1</eventSubURL>\n"
+    "    <SCPDURL>/remoteaccess.xml</SCPDURL>\n"
+    "   </service>\n"
+    "   <service>\n"
+    "    <serviceType>urn:Belkin:service:deviceinfo:1</serviceType>\n"
+    "    <serviceId>urn:Belkin:serviceId:deviceinfo1</serviceId>\n"
+    "    <controlURL>/upnp/control/deviceinfo1</controlURL>\n"
+    "    <eventSubURL>/upnp/event/deviceinfo1</eventSubURL>\n"
+    "    <SCPDURL>/deviceinfoservice.xml</SCPDURL>\n"
+    "   </service>\n"
+    "   <service>\n"
+    "    <serviceType>urn:Belkin:service:smartsetup:1</serviceType>\n"
+    "    <serviceId>urn:Belkin:serviceId:smartsetup1</serviceId>\n"
+    "    <controlURL>/upnp/control/smartsetup1</controlURL>\n"
+    "    <eventSubURL>/upnp/event/smartsetup1</eventSubURL>\n"
+    "    <SCPDURL>/smartsetup.xml</SCPDURL>\n"
+    "   </service>\n"
+    "   <service>\n"
+    "    <serviceType>urn:Belkin:service:manufacture:1</serviceType>\n"
+    "    <serviceId>urn:Belkin:serviceId:manufacture1</serviceId>\n"
+    "    <controlURL>/upnp/control/manufacture1</controlURL>\n"
+    "    <eventSubURL>/upnp/event/manufacture1</eventSubURL>\n"
+    "    <SCPDURL>/manufacture.xml</SCPDURL>\n"
+    "   </service>\n"
+    "  </serviceList>\n"
+#endif
+    " </device>\n"
+    "</root>\n";
+
+
+HTTPServer::CallBackResults Setup_xml(HTTPServer *svr, HTTPServer::CallBackType type, char * path,
+                       const HTTPServer::namevalue *queryParams, int queryParamCount)
+{
+    char BigBuffer[1000];
+    HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR;
+    printf("Setup.xml responder\n");
+    switch (type) {
+        case HTTPServer::SEND_PAGE:
+            svr->header(HTTPServer::OK, "OK", hdrTypeHTML_NoCache);
+            sprintf(BigBuffer, SETUP_TEMPLATE, 
+                My_Name, eth.getMACAddress(), My_SerialNum,
+                eth.getIPAddress(), Server_Port);
+            svr->send(BigBuffer);
+            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 RootPage(HTTPServer *svr, HTTPServer::CallBackType type, char * path,
+                       const HTTPServer::namevalue *queryParams, int queryParamCount)
+{
+    char BigBuffer[1000];
+    HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR;
+    printf("RootPage responder\n");
+    
+    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);
+            sprintf(BigBuffer, ROOTPAGE, PROG_NAME, PROG_NAME, BUILD_DATE);            
+            svr->send(BigBuffer);
+            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;
+}