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
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> </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 © 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 }
Generated on Wed Jul 13 2022 09:42:51 by 1.7.2