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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers WebPages.cpp Source File

WebPages.cpp

00001 
00002 #include "mbed.h"
00003 
00004 #include "EthernetInterface.h"
00005 #include "SW_String.h"
00006 #include "X10.h"
00007 #include "WebPages.h"
00008 #include "IniManager.h"         // v20
00009 
00010 extern INI ini;
00011 extern X10Interface cm17a;
00012 
00013 extern EthernetInterface eth;
00014 extern const char * BUILD_DATE;
00015 extern const char * PROG_NAME;
00016 extern const char * My_Name;
00017 extern const char * My_SerialNum;
00018 extern int Server_Port;
00019 
00020 extern bool swUpdateCheck;
00021 
00022 extern DigitalOut linkdata;
00023 
00024 extern "C" void mbed_reset();
00025 
00026 
00027 static const char hdrTypeHTML_NoCache[] = 
00028     "Content-Type: text/html\r\n"
00029     "Cache-Control: no-cache\r\n";
00030 
00031 
00032 // The /setup.xml file
00033 //
00034 // sprintf(buf, SETUP_TEMPLATE, "FriendlyName", "udn_hexstring", "serialNum", "ip.ad.dr", portNum);
00035 static const char SETUP_TEMPLATE[] =
00036     "<?xml version=\"1.0\"?>\n"
00037     "<root xmlns=\"urn:Belkin:device-1-0\">\n"
00038     " <specVersion>\n"
00039     "  <major>1</major>\n"
00040     "  <minor>0</minor>\n"
00041     " </specVersion>\n"
00042     " <device>\n"
00043     "  <deviceType>urn:Belkin:device:controllee:1</deviceType>\n"
00044     "  <friendlyName>%s</friendlyName>\n"
00045     "  <manufacturer>Belkin International Inc.</manufacturer>\n"            ///< must be "Belkin..." for Alexa discovery
00046     "  <manufacturerURL>http://www.smart-family.net</manufacturerURL>\n"    ///<
00047     "  <modelDescription>Special thing</modelDescription>\n"   ///<
00048     "  <modelName>Smart Node</modelName>\n"                                ///<
00049     "  <modelNumber>1.0.0</modelNumber>\n"
00050 #if 1
00051     "  <modelURL>http://www.smart-family.net</modelURL>\n"                  ///< This causes it to fail to send completely
00052 #endif
00053     "  <UDN>uuid:Socket-1_0-%s</UDN>\n"
00054     "  <serialNumber>%s</serialNumber>\n"
00055     "  <iconList>\n"
00056     "   <mimetype>jpg</mimetype>\n"
00057     "   <width>100</width>\n"
00058     "   <height>100</height>\n"
00059     "   <depth>100</depth>\n"
00060     "   <url>icon.jpg</url>\n"
00061     "  </iconList>\n"
00062     "  <presentationURL>http://%s:%d</presentationURL>\n"
00063 #if 0
00064     "  <serviceList>\n"
00065     "   <service>\n"
00066     "    <serviceType>urn:Belkin:service:WiFiSetup:1</serviceType>\n"
00067     "    <serviceId>urn:Belkin:serviceId:WiFiSetup1</serviceId>\n"
00068     "    <controlURL>/upnp/control/WiFiSetup1</controlURL>\n"
00069     "    <eventSubURL>/upnp/event/WiFiSetup1</eventSubURL>\n"
00070     "    <SCPDURL>/setupservice.xml</SCPDURL>\n"
00071     "   </service>\n"
00072     "   <service>\n"
00073     "    <serviceType>urn:Belkin:service:timesync:1</serviceType>\n"
00074     "    <serviceId>urn:Belkin:serviceId:timesync1</serviceId>\n"
00075     "    <controlURL>/upnp/control/timesync1</controlURL>\n"
00076     "    <eventSubURL>/upnp/event/timesync1</eventSubURL>\n"
00077     "    <SCPDURL>/timesyncservice.xml</SCPDURL>\n"
00078     "   </service>\n"
00079     "   <service>\n"
00080     "    <serviceType>urn:Belkin:service:basicevent:1</serviceType>\n"
00081     "    <serviceId>urn:Belkin:serviceId:basicevent1</serviceId>\n"
00082     "    <controlURL>/upnp/control/basicevent1</controlURL>\n"
00083     "    <eventSubURL>/upnp/event/basicevent1</eventSubURL>\n"
00084     "    <SCPDURL>/eventservice.xml</SCPDURL>\n"
00085     "   </service>\n"
00086     "   <service>\n"
00087     "    <serviceType>urn:Belkin:service:firmwareupdate:1</serviceType>\n"
00088     "    <serviceId>urn:Belkin:serviceId:firmwareupdate1</serviceId>\n"
00089     "    <controlURL>/upnp/control/firmwareupdate1</controlURL>\n"
00090     "    <eventSubURL>/upnp/event/firmwareupdate1</eventSubURL>\n"
00091     "    <SCPDURL>/firmwareupdate.xml</SCPDURL>\n"
00092     "   </service>\n"
00093     "   <service>\n"
00094     "    <serviceType>urn:Belkin:service:rules:1</serviceType>\n"
00095     "    <serviceId>urn:Belkin:serviceId:rules1</serviceId>\n"
00096     "    <controlURL>/upnp/control/rules1</controlURL>\n"
00097     "    <eventSubURL>/upnp/event/rules1</eventSubURL>\n"
00098     "    <SCPDURL>/rulesservice.xml</SCPDURL>\n"
00099     "   </service>\n"
00100     "   <service>\n"
00101     "    <serviceType>urn:Belkin:service:metainfo:1</serviceType>\n"
00102     "    <serviceId>urn:Belkin:serviceId:metainfo1</serviceId>\n"
00103     "    <controlURL>/upnp/control/metainfo1</controlURL>\n"
00104     "    <eventSubURL>/upnp/event/metainfo1</eventSubURL>\n"
00105     "    <SCPDURL>/metainfoservice.xml</SCPDURL>\n"
00106     "   </service>\n"
00107     "   <service>\n"
00108     "    <serviceType>urn:Belkin:service:remoteaccess:1</serviceType>\n"
00109     "    <serviceId>urn:Belkin:serviceId:remoteaccess1</serviceId>\n"
00110     "    <controlURL>/upnp/control/remoteaccess1</controlURL>\n"
00111     "    <eventSubURL>/upnp/event/remoteaccess1</eventSubURL>\n"
00112     "    <SCPDURL>/remoteaccess.xml</SCPDURL>\n"
00113     "   </service>\n"
00114     "   <service>\n"
00115     "    <serviceType>urn:Belkin:service:deviceinfo:1</serviceType>\n"
00116     "    <serviceId>urn:Belkin:serviceId:deviceinfo1</serviceId>\n"
00117     "    <controlURL>/upnp/control/deviceinfo1</controlURL>\n"
00118     "    <eventSubURL>/upnp/event/deviceinfo1</eventSubURL>\n"
00119     "    <SCPDURL>/deviceinfoservice.xml</SCPDURL>\n"
00120     "   </service>\n"
00121     "   <service>\n"
00122     "    <serviceType>urn:Belkin:service:smartsetup:1</serviceType>\n"
00123     "    <serviceId>urn:Belkin:serviceId:smartsetup1</serviceId>\n"
00124     "    <controlURL>/upnp/control/smartsetup1</controlURL>\n"
00125     "    <eventSubURL>/upnp/event/smartsetup1</eventSubURL>\n"
00126     "    <SCPDURL>/smartsetup.xml</SCPDURL>\n"
00127     "   </service>\n"
00128     "   <service>\n"
00129     "    <serviceType>urn:Belkin:service:manufacture:1</serviceType>\n"
00130     "    <serviceId>urn:Belkin:serviceId:manufacture1</serviceId>\n"
00131     "    <controlURL>/upnp/control/manufacture1</controlURL>\n"
00132     "    <eventSubURL>/upnp/event/manufacture1</eventSubURL>\n"
00133     "    <SCPDURL>/manufacture.xml</SCPDURL>\n"
00134     "   </service>\n"
00135     "  </serviceList>\n"
00136 #endif
00137     " </device>\n"
00138     "</root>\n";
00139 
00140 
00141 HTTPServer::CallBackResults Setup_xml(HTTPServer *svr, HTTPServer::CallBackType type, char * path,
00142                        const HTTPServer::namevalue *queryParams, int queryParamCount)
00143 {
00144     char BigBuffer[sizeof(SETUP_TEMPLATE) + 150];
00145     HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR;
00146     linkdata = true;
00147     switch (type) {
00148         case HTTPServer::SEND_PAGE:
00149             svr->header(HTTPServer::OK, "OK", hdrTypeHTML_NoCache);
00150             sprintf(BigBuffer, SETUP_TEMPLATE, 
00151                 My_Name, eth.getMACAddress(), My_SerialNum,
00152                 eth.getIPAddress(), Server_Port);
00153             svr->send(BigBuffer);
00154             ret = HTTPServer::ACCEPT_COMPLETE;
00155             break;
00156         case HTTPServer::CONTENT_LENGTH_REQUEST:
00157             ret = HTTPServer::ACCEPT_COMPLETE;
00158             break;
00159         case HTTPServer::DATA_TRANSFER:
00160             ret = HTTPServer::ACCEPT_COMPLETE;
00161             break;
00162         default:
00163             ret = HTTPServer::ACCEPT_ERROR;
00164             break;
00165     }
00166     linkdata = false;
00167     return ret;
00168 }
00169 
00170 
00171 
00172 HTTPServer::CallBackResults RootPage(HTTPServer *svr, HTTPServer::CallBackType type, char * path,
00173                        const HTTPServer::namevalue *queryParams, int queryParamCount)
00174 {
00175     char smallBuf[100];
00176     char bigBuf[3000] = "";      // sized by test and adjust, and then round up generously.
00177     int count;
00178     HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR;
00179     
00180     linkdata = true;
00181     switch (type) {
00182         case HTTPServer::SEND_PAGE:
00183             if (0 == strcmp(svr->GetParameter("SWUpdate"),"CheckNow")) {
00184                 swUpdateCheck = true;
00185                 svr->header(HTTPServer::Found, "Found", "Location: /\r\n");
00186                 svr->send("\r\n");
00187                 break;
00188             }
00189             count = svr->GetParameterCount();
00190             printf("Data Transfer: %d parameters\r\n", count);
00191             if (count) {
00192                 //for (int i=0; i<count; i++) {
00193                 //    const HTTPServer::namevalue * nv = svr->GetParameter(i);
00194                 //    printf("  %d: %s => %s\r\n", i, nv->name, nv->value);
00195                 //}
00196                 const char * p = svr->GetParameter("House");
00197                 if (p && strlen(p) == 1) {
00198                     char cmdBuf[7];     // "HUU +6"
00199                     strcpy_s(cmdBuf, sizeof(cmdBuf), p);
00200                     p = svr->GetParameter("Unit");
00201                     if (p && strlen(p) >= 1 && strlen(p) <= 2) {
00202                         strcat_s(cmdBuf, sizeof(cmdBuf), p);
00203                         p = svr->GetParameter("Cmd");
00204                         if (p && strlen(p) >= 1 && strlen(p) <= 2) {
00205                             strcat_s(cmdBuf, sizeof(cmdBuf), " ");
00206                             strcat_s(cmdBuf, sizeof(cmdBuf), p);
00207                             printf("Web Command: '%s'\r\n", cmdBuf);
00208                             cm17a.ParseCommand(cmdBuf);
00209                             svr->header(HTTPServer::Found, "Found", "Location: /\r\n");
00210                             svr->send("\r\n");
00211                             break;
00212                         }
00213                     }
00214                 }
00215             }
00216 
00217             svr->header(HTTPServer::OK, "OK", "Content-Type: text/html\r\n");
00218             strcat_s(bigBuf, sizeof(bigBuf), "<!DOCTYPE html>\r\n<html>\r\n<head>\r\n<title>X10 Server Info</title>\r\n");
00219             strcat_s(bigBuf, sizeof(bigBuf), "<style>\n");
00220             strcat_s(bigBuf, sizeof(bigBuf), "body {\n");
00221             strcat_s(bigBuf, sizeof(bigBuf), "   transform: scale(1.6);\n");
00222             strcat_s(bigBuf, sizeof(bigBuf), "   transform-origin: 0 0;\n");
00223             strcat_s(bigBuf, sizeof(bigBuf), "}\n");
00224             strcat_s(bigBuf, sizeof(bigBuf), "</style>\n");
00225             strcat_s(bigBuf, sizeof(bigBuf), "</head>\r\n");
00226             strcat_s(bigBuf, sizeof(bigBuf), "<body>\r\n");
00227             strcat_s(bigBuf, sizeof(bigBuf), "<h1>X10 Server Info</h1>\r\n");
00228             strcat_s(bigBuf, sizeof(bigBuf), "<blockquote>\r\n");
00229             strcat_s(bigBuf, sizeof(bigBuf), "<table border='1'>\r\n");
00230             strcat_s(bigBuf, sizeof(bigBuf), "<tr><th><h2>Command</h2></th></tr>\r\n");
00231             strcat_s(bigBuf, sizeof(bigBuf), "<tr><td>\r\n");
00232             strcat_s(bigBuf, sizeof(bigBuf), "<form method='get'>\r\n");
00233             strcat_s(bigBuf, sizeof(bigBuf), "<table border='0'><tr><th>House</th><th>Unit</th><th>Cmd</th><th>&nbsp;</th></tr>\r\n");
00234             // House code
00235             strcat_s(bigBuf, sizeof(bigBuf), "<tr><td align='center'><select name='House'>\r\n");
00236             for (int i = 'A'; i <= 'P'; i++) {
00237                 snprintf(smallBuf, 100, "<option value='%c'>%c</option>\r\n", i, i);
00238                 strcat_s(bigBuf, sizeof(bigBuf), smallBuf);
00239             }
00240             strcat_s(bigBuf, sizeof(bigBuf), "</select></td>\r\n");
00241             strcat_s(bigBuf, sizeof(bigBuf), "<td><select name='Unit'>\r\n");
00242             for (int i = 1; i <= 16; i++) {
00243                 snprintf(smallBuf, 100, "<option value='%d'>%d</option>\r\n", i, i);
00244                 strcat_s(bigBuf, sizeof(bigBuf), smallBuf);
00245             }
00246             strcat_s(bigBuf, sizeof(bigBuf), "</select></td>\r\n");
00247             // Unit code
00248             strcat_s(bigBuf, sizeof(bigBuf), "<td><select name='Cmd'>\r\n");
00249             for (int i = -6; i <= 7; i++) {
00250                 if (i < 0)
00251                     snprintf(smallBuf, 100, "<option value='%+d'>%+d</option>\r\n", i, i);
00252                 else if (i == 0) 
00253                     snprintf(smallBuf, 100, "<option value='%d' selected>%d</option>\r\n", i, i);
00254                 else if (i == 1)
00255                     snprintf(smallBuf, 100, "<option value='%d'>%d</option>\r\n", i, i);
00256                 else // if (i > 1)
00257                     snprintf(smallBuf, 100, "<option value='%+d'>%+d</option>\r\n", i-1, i-1);
00258                 strcat_s(bigBuf, sizeof(bigBuf), smallBuf);
00259             }
00260             strcat_s(bigBuf, sizeof(bigBuf), "</select></td>\r\n");
00261 
00262             strcat_s(bigBuf, sizeof(bigBuf), "<td><input type='Submit' value='Send'></td>\r\n");
00263             strcat_s(bigBuf, sizeof(bigBuf), "</tr></table>\r\n");
00264             strcat_s(bigBuf, sizeof(bigBuf), "</form>\r\n");
00265             strcat_s(bigBuf, sizeof(bigBuf), "</td></tr></table>\r\n");
00266             strcat_s(bigBuf, sizeof(bigBuf), "<br/><br/><a href='/info'>info Page</a> | <a href='/setup.xml'>setup.xml</a>\r\n");
00267             strcat_s(bigBuf, sizeof(bigBuf), "</blockquote>\r\n");
00268             strcat_s(bigBuf, sizeof(bigBuf), "X10 Server, Copyright &copy; 2019 by Smartware Computing, all rights reserved.");
00269             strcat_s(bigBuf, sizeof(bigBuf), "</body></html>");
00270             printf("bigBuf size is %d bytes\r\n", strlen(bigBuf));
00271             svr->send(bigBuf);
00272             ret = HTTPServer::ACCEPT_COMPLETE;
00273             break;
00274         case HTTPServer::CONTENT_LENGTH_REQUEST:
00275             ret = HTTPServer::ACCEPT_COMPLETE;
00276             break;
00277         case HTTPServer::DATA_TRANSFER:
00278             ret = HTTPServer::ACCEPT_COMPLETE;
00279             break;
00280         default:
00281             ret = HTTPServer::ACCEPT_ERROR;
00282             break;
00283     }
00284     linkdata = false;
00285     return ret;
00286 }
00287 
00288 
00289 HTTPServer::CallBackResults InfoPage(HTTPServer *svr, HTTPServer::CallBackType type, char * path,
00290                        const HTTPServer::namevalue *queryParams, int queryParamCount)
00291 {
00292     char lineBuf[60];
00293     char bigBuf[1000] = "";      // sized by test and adjust, and then round up generously.
00294     HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR;
00295     FILE * fh;
00296     
00297     linkdata = true;
00298     switch (type) {
00299         case HTTPServer::SEND_PAGE:
00300             svr->header(HTTPServer::OK, "OK", "Content-Type: text/html\r\n");
00301             strcat_s(bigBuf, sizeof(bigBuf), "<!DOCTYPE html>\r\n<html><head><title>X10 Server Info</title></head>\r\n");
00302             strcat_s(bigBuf, sizeof(bigBuf), "<body>\r\n");
00303             strcat_s(bigBuf, sizeof(bigBuf), "<h1>X10 Server Info</h1>\r\n");
00304             strcat_s(bigBuf, sizeof(bigBuf), "<table border='1' width='100%'>\r\n");
00305             strcat_s(bigBuf, sizeof(bigBuf), "<tr><th>Configuration</th><th>Software</th></tr>\r\n");
00306             strcat_s(bigBuf, sizeof(bigBuf), "<tr><td valign='top' width='50%'><pre>\r\n");
00307             fh = fopen("/local/X10svr.ini", "rt");
00308             if (fh) {
00309                 char fileBuf[60];
00310                 while(fgets(fileBuf, sizeof(fileBuf), fh)) {
00311                     strcat_s(bigBuf, sizeof(bigBuf), fileBuf);
00312                 }
00313                 fclose(fh);
00314             }
00315             strcat_s(bigBuf, sizeof(bigBuf), "</pre>\r\n");
00316             strcat_s(bigBuf, sizeof(bigBuf), "</td>\r\n");
00317             strcat_s(bigBuf, sizeof(bigBuf), "<td valign='top' width='50%'><pre>\r\n");
00318             if (INI::INI_SUCCESS == ini.ReadString("SWUpdate", "name", lineBuf, sizeof(lineBuf))) {
00319                 strcat_s(bigBuf, sizeof(bigBuf), "name=");
00320                 strcat_s(bigBuf, sizeof(bigBuf), lineBuf);
00321                 strcat_s(bigBuf, sizeof(bigBuf), "\r\nversion=");
00322                 lineBuf[6] = '\0';
00323                 char fname[45];
00324                 snprintf(fname, sizeof(fname), "/local/%s.ver", lineBuf);
00325                 fh = fopen(fname, "rt");
00326                 if (fh) {
00327                     while(fgets(lineBuf, sizeof(lineBuf), fh)) {
00328                         strcat_s(bigBuf, sizeof(bigBuf), lineBuf);
00329                     }
00330                     fclose(fh);
00331                 }
00332             }
00333             strcat_s(bigBuf, sizeof(bigBuf), "</pre>\r\n");
00334             strcat_s(bigBuf, sizeof(bigBuf), "<img src='/icon.png'>");
00335             strcat_s(bigBuf, sizeof(bigBuf), "</td></tr>\r\n");
00336             strcat_s(bigBuf, sizeof(bigBuf), "<tr>\r\n");
00337             strcat_s(bigBuf, sizeof(bigBuf), "<td><a href='/'>Home Page</a> | <a href='/reboot'>Reboot</a></td>\r\n");
00338             strcat_s(bigBuf, sizeof(bigBuf), "<td><a href='/software'>Software Update Check</a> | ");
00339             strcat_s(bigBuf, sizeof(bigBuf), "<a href='/setup.xml' target='_xml'>view setup.xml</a>\r\n");
00340             strcat_s(bigBuf, sizeof(bigBuf), "</td></tr></table>\r\n");
00341             strcat_s(bigBuf, sizeof(bigBuf), "</body></html>");
00342             printf("bigBuf size is %d bytes\r\n", strlen(bigBuf));
00343             svr->send(bigBuf);
00344             ret = HTTPServer::ACCEPT_COMPLETE;
00345             break;
00346         case HTTPServer::CONTENT_LENGTH_REQUEST:
00347             ret = HTTPServer::ACCEPT_COMPLETE;
00348             break;
00349         case HTTPServer::DATA_TRANSFER:
00350             ret = HTTPServer::ACCEPT_COMPLETE;
00351             break;
00352         default:
00353             ret = HTTPServer::ACCEPT_ERROR;
00354             break;
00355     }
00356     linkdata = false;
00357     return ret;
00358 }
00359 
00360 
00361 HTTPServer::CallBackResults SoftwarePage(HTTPServer *svr, HTTPServer::CallBackType type, char * path,
00362                        const HTTPServer::namevalue *queryParams, int queryParamCount)
00363 {
00364     HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR;
00365     
00366     linkdata = true;
00367     switch (type) {
00368         case HTTPServer::SEND_PAGE:
00369             swUpdateCheck = true;
00370             printf("SW Update Check scheduled.\r\n");
00371             svr->header(HTTPServer::Found, "Found", "Location: /\r\n");
00372             svr->send("\r\n");
00373             ret = HTTPServer::ACCEPT_COMPLETE;
00374             break;
00375         case HTTPServer::CONTENT_LENGTH_REQUEST:
00376             ret = HTTPServer::ACCEPT_COMPLETE;
00377             break;
00378         case HTTPServer::DATA_TRANSFER:
00379             ret = HTTPServer::ACCEPT_COMPLETE;
00380             break;
00381         default:
00382             ret = HTTPServer::ACCEPT_ERROR;
00383             break;
00384     }
00385     linkdata = false;
00386     return ret;
00387 }
00388 
00389 
00390 HTTPServer::CallBackResults RebootPage(HTTPServer *svr, HTTPServer::CallBackType type, char * path,
00391                        const HTTPServer::namevalue *queryParams, int queryParamCount)
00392 {
00393     HTTPServer::CallBackResults ret = HTTPServer::ACCEPT_ERROR;
00394     
00395     linkdata = true;
00396     switch (type) {
00397         case HTTPServer::SEND_PAGE:
00398             swUpdateCheck = true;
00399             printf("Reboot scheduled.\r\n");
00400             svr->header(HTTPServer::Found, "Found", "Location: /\r\n");
00401             svr->send("\r\n");
00402             Thread::wait(500);
00403             mbed_reset();
00404             ret = HTTPServer::ACCEPT_COMPLETE;
00405             break;
00406         case HTTPServer::CONTENT_LENGTH_REQUEST:
00407             ret = HTTPServer::ACCEPT_COMPLETE;
00408             break;
00409         case HTTPServer::DATA_TRANSFER:
00410             ret = HTTPServer::ACCEPT_COMPLETE;
00411             break;
00412         default:
00413             ret = HTTPServer::ACCEPT_ERROR;
00414             break;
00415     }
00416     linkdata = false;
00417     return ret;
00418 }