HTTP Server serving a simple webpage which enables to remotely turn a digital output on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.
main.cpp
00001 #include "mbed.h" 00002 #include <string> 00003 #include "UipEthernet.h" 00004 #include "TcpServer.h" 00005 #include "TcpClient.h" 00006 00007 //#define DEBUG 00008 // Static IP address must be unique and compatible with your network. 00009 #define IP "192.168.1.35" 00010 #define GATEWAY "192.168.1.1" 00011 #define NETMASK "255.255.255.0" 00012 #define PORT 80 00013 const uint8_t MAC[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x06 }; 00014 UipEthernet net(MAC, D11, D12, D13, D10); // mosi, miso, sck, cs 00015 TcpServer server; // Ethernet server 00016 TcpClient* client; 00017 char httpBuf[1500]; 00018 char httpHeader[256]; 00019 const int OFF = 0; 00020 const int ON = 1; 00021 DigitalOut output(D3); // A digital output to be switched on/off 00022 float roomTemp = 21.8f; // A temperature sensor output 00023 const char PASSWORD[] = "secret"; // Change as you like 00024 00025 /** 00026 * @brief Analyses the received URL 00027 * @note The string passed to this function will look like this: 00028 * GET /HTTP/1..... 00029 * GET /password HTTP/1..... 00030 * GET /password/ HTTP/1..... 00031 * GET /password/?sw=1 HTTP/1..... 00032 * GET /password/?sw=0 HTTP/1..... 00033 * @param url URL string 00034 * @retval -3 just refresh page 00035 * -2 no command given but password valid 00036 * -1 invalid password 00037 * 0 switch off 00038 * 1 switch on 00039 */ 00040 int8_t analyseURL(char* url) 00041 { 00042 if (strlen(url) < (5 + strlen(PASSWORD) + 1)) 00043 return(-1); 00044 00045 //if (url.substr(5, PASSWORD.size()) != PASSWORD) 00046 if (strncmp(url + 5, PASSWORD, strlen(PASSWORD)) != 0) 00047 return(-1); 00048 00049 uint8_t pos = 5 + strlen(PASSWORD); 00050 00051 //if (url.substr(pos, 1) != "/") 00052 00053 if (*(url + pos) != '/') 00054 return(-1); 00055 00056 //if (url.substr(pos++, 1) == " ") 00057 if (*(url + pos++) == ' ') 00058 return(-2); 00059 00060 //string cmd(url.substr(pos, 5)); 00061 *(url + pos + 5) = '\0'; // terminate the cmd string 00062 char* cmd = ((url + pos)); 00063 if (strcmp(cmd, "?sw=0") == 0) 00064 return(0); 00065 if (strcmp(cmd, "?sw=1") == 0) 00066 return(1); 00067 return(-3); 00068 } 00069 00070 /** 00071 * @brief 00072 * @note 00073 * @param 00074 * @retval 00075 */ 00076 char* movedPermanently(uint8_t flag) 00077 { 00078 memset(httpBuf, 0, sizeof(httpBuf)); 00079 if (flag == 1) { 00080 strcpy(httpBuf, "/"); 00081 strcat(httpBuf, PASSWORD); 00082 strcat(httpBuf, "/"); 00083 } 00084 00085 strcat(httpBuf, "<h1>301 Moved Permanently</h1>\r\n"); 00086 return(httpBuf); 00087 } 00088 00089 /** 00090 * @brief 00091 * @note 00092 * @param 00093 * @retval 00094 */ 00095 char* showWebPage(int status) 00096 { 00097 char roomTempStr[10] = { }; 00098 00099 //roomTemp = ds1820.read(); 00100 00101 sprintf(roomTempStr, "%3.1f", roomTemp); 00102 memset(httpBuf, 0, sizeof(httpBuf)); 00103 /*$off*/ 00104 strcat 00105 ( 00106 httpBuf, 00107 "<head>" 00108 "<meta charset=\"utf-8\">" 00109 "<meta name=\"viewport\" content=\" initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=0;\"/>" 00110 "<title>Smart Home</title>" 00111 "<link href='http://fonts.googleapis.com/css?family=Droid+Sans&v1' rel='stylesheet' type='text/css'>" 00112 "<style>" 00113 ".switch {" 00114 "position: relative;" 00115 "display: inline-block;" 00116 "width: 60px;" 00117 "height: 34px;" 00118 "}" 00119 ".switch input {display:none;}" 00120 ".slider {" 00121 "position: absolute;" 00122 "cursor: pointer;" 00123 "top: 0;" 00124 "left: 0;" 00125 "right: 0;" 00126 "bottom: 0;" 00127 "border-radius: 34px;" 00128 "background-color: #ccc;" 00129 "-webkit-transition: .4s;" 00130 "transition: .4s;" 00131 "}" 00132 ".slider:before {" 00133 "position: absolute;" 00134 "content: \"\";" 00135 "height: 26px;" 00136 "width: 26px;" 00137 "left: 4px;" 00138 "bottom: 4px;" 00139 "border-radius: 50%;" 00140 "background-color: white;" 00141 "-webkit-transition: .4s;" 00142 "transition: .4s;" 00143 "}" 00144 "input:checked + .slider {" 00145 "background-color: #8ce196;" 00146 "}" 00147 "input:focus + .slider {" 00148 "box-shadow: 0 0 1px #8ce196;" 00149 "}" 00150 "input:checked + .slider:before {" 00151 "-webkit-transform: translateX(26px);" 00152 "-ms-transform: translateX(26px);" 00153 "transform: translateX(26px);" 00154 "}" 00155 "</style>" 00156 "</head>" 00157 00158 "<body>" 00159 "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>" 00160 "<pre>Temperature:\t" 00161 ); 00162 strcat(httpBuf, roomTempStr); 00163 strcat(httpBuf, "°C</pre>"); 00164 strcat 00165 ( 00166 httpBuf, 00167 "<pre>Heating:\t" 00168 ); 00169 if(status == ON) { 00170 strcat 00171 ( 00172 httpBuf, 00173 "<a href=\"./?sw=0\" class=\"switch\"> " 00174 "<input type=\"checkbox\" checked>" 00175 ); 00176 } 00177 else { 00178 strcat 00179 ( 00180 httpBuf, 00181 "<a href=\"./?sw=1\" class=\"switch\"> " 00182 "<input type=\"checkbox\">" 00183 ); 00184 } 00185 strcat 00186 ( 00187 httpBuf, 00188 "<div class=\"slider\"></div>" 00189 "</a>" 00190 "</pre>" 00191 "<hr>" 00192 "<pre>2017 ARMmbed</pre>" 00193 "</body>" 00194 ); 00195 /*$on*/ 00196 return httpBuf; 00197 } 00198 00199 /** 00200 * @brief 00201 * @note 00202 * @param 00203 * @retval 00204 */ 00205 void sendHTTP(TcpClient* client, char* header, char* content) 00206 { 00207 char content_length[10] = { }; 00208 00209 sprintf(content_length, "%u\r\n", strlen(content)); 00210 00211 strcat(header, "\r\nContent-Type: text/html\r\n"); 00212 strcat(header, "Content-Length: "); 00213 strcat(header, content_length); 00214 strcat(header, "Pragma: no-cache\r\n"); 00215 strcat(header, "Connection: About to close\r\n\r\n"); 00216 00217 char c = content[0]; 00218 memmove(httpBuf + strlen(header), httpBuf, strlen(content)); // make room for the header 00219 strcpy(httpBuf, header); // copy the header on front of the content 00220 httpBuf[strlen(header)] = c; 00221 client->send((uint8_t*)httpBuf, strlen(httpBuf)); 00222 } 00223 00224 /** 00225 * @brief 00226 * @note 00227 * @param 00228 * @retval 00229 */ 00230 int main(void) 00231 { 00232 printf("Starting ...\r\n"); 00233 00234 //net.set_network(IP, NETMASK, GATEWAY); // include this for using static IP address 00235 if (net.connect(30) != 0) { 00236 00237 // 'connect' timeout in seconds (defaults to 60 sec) 00238 printf("Unable to connet.\r\n"); 00239 return -1; 00240 } 00241 00242 // Show the network address 00243 SocketAddress addr; 00244 net.get_ip_address(&addr); 00245 printf("IP address: %s\n", addr.get_ip_address() ? addr.get_ip_address() : "None"); 00246 net.get_netmask(&addr); 00247 printf("Netmask: %s\n", addr.get_ip_address() ? addr.get_ip_address() : "None"); 00248 net.get_gateway(&addr); 00249 printf("Gateway: %s\n", addr.get_ip_address() ? addr.get_ip_address() : "None"); 00250 00251 /* Open the server on ethernet stack */ 00252 server.open(&net); 00253 00254 /* Bind the HTTP port (TCP 80) to the server */ 00255 server.bind(PORT); 00256 00257 /* Can handle 4 simultaneous connections */ 00258 server.listen(4); 00259 00260 while (true) { 00261 client = server.accept(); 00262 if (client) { 00263 switch (client->recv((uint8_t*)httpBuf, client->available())) { 00264 case 0: 00265 printf("recieved buffer is empty.\n\r"); 00266 break; 00267 00268 case -1: 00269 printf("failed to read data from client.\n\r"); 00270 break; 00271 00272 default: 00273 #ifdef DEBUG 00274 printf("Client with IP address %s connected.\r\n\r\n", client->getpeername()); 00275 printf("Data received:\r\n%s\n\r", receiveBuf); 00276 #endif 00277 if (strncmp(httpBuf, "GET", 3) != 0) { 00278 strcpy(httpHeader, "HTTP/1.0 200 OK"); 00279 strcpy(httpBuf, "<h1>200 OK</h1>"); 00280 sendHTTP(client, httpHeader, httpBuf); 00281 } 00282 else 00283 if ((strncmp(httpBuf, "GET", 3) == 0) && (strncmp(httpBuf + 3, " / ", 3 == 0))) { 00284 strcpy(httpHeader, "HTTP/1.0 200 OK"); 00285 strcpy(httpBuf, "<p>Usage: http://host_or_ip/password</p>\r\n"); 00286 sendHTTP(client, httpHeader, httpBuf); 00287 } 00288 else { 00289 int cmd = analyseURL(httpBuf); 00290 switch (cmd) { 00291 case -3: 00292 // update webpage 00293 strcpy(httpHeader, "HTTP/1.0 200 OK"); 00294 sendHTTP(client, httpHeader, showWebPage(output)); 00295 break; 00296 00297 case -2: 00298 // redirect to the right base url 00299 strcpy(httpHeader, "HTTP/1.0 301 Moved Permanently\r\nLocation: "); 00300 sendHTTP(client, httpHeader, movedPermanently(1)); 00301 break; 00302 00303 case -1: 00304 strcpy(httpHeader, "HTTP/1.0 401 Unauthorized"); 00305 strcpy(httpBuf, "<h1>401 Unauthorized</h1>"); 00306 sendHTTP(client, httpHeader, httpBuf); 00307 break; 00308 00309 case 0: 00310 output = OFF; // output off 00311 strcpy(httpHeader, "HTTP/1.0 200 OK"); 00312 sendHTTP(client, httpHeader, showWebPage(output)); 00313 break; 00314 00315 case 1: 00316 output = ON; // output on 00317 strcpy(httpHeader, "HTTP/1.0 200 OK"); 00318 sendHTTP(client, httpHeader, showWebPage(output)); 00319 break; 00320 } 00321 } 00322 } 00323 00324 client->close(); 00325 } 00326 } 00327 }
Generated on Fri Jul 15 2022 10:29:21 by 1.7.2