
HTTP Server serving a simple webpage which enables to remotely turn LED1 on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.
Dependencies: W5500Interface mbed
main.cpp
00001 /* 00002 * In this example LED1 on the mbed board is turned on/off using a web browser. 00003 * However, you can easily modify the project to remotely switch on/off any external device. 00004 * The HTTP server is built from an mbed board and a WIZ550io board. 00005 * The example is based on the Tuxgraphics Web Switch <http://www.tuxgraphics.org/>. 00006 * For more details see <https://developer.mbed.org/users/hudakz/code/WebSwitch_WIZ550io/wiki/Homepage> 00007 * Thanks to Jozsef Voros it works now also with the W5500 modules without a built-in MAC 00008 * See below how to enable that. 00009 */ 00010 #include "mbed.h" 00011 #include "EthernetInterface.h" 00012 #include <string> 00013 00014 using namespace std; 00015 00016 const int OFF = 0; 00017 const int ON = 1; 00018 00019 Serial serial(USBTX, USBRX); 00020 00021 #if defined(TARGET_LPC1768) 00022 EthernetInterface eth(p11, p12, p13, p8, p14); // MOSI, MISO, SCK, CS, RESET 00023 #elif defined(TARGET_LPC11U24) 00024 EthernetInterface eth(P16, P15, P13, P17, P18); // MOSI, MISO, SCK, CS, RESET 00025 #elif defined(TARGET_NUCLEO_F103RB) || defined(TARGET_NUCLEO_L152RE) || defined(TARGET_NUCLEO_F030R8) \ 00026 || defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F302R8) || defined(TARGET_NUCLEO_L053R8) \ 00027 || defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F334R8) || defined(TARGET_NUCLEO_F072RB) \ 00028 || defined(TARGET_NUCLEO_F091RC) || defined(TARGET_NUCLEO_F303RE) || defined(TARGET_NUCLEO_F070RB) \ 00029 || defined(TARGET_KL25Z ) || defined(TARGET_KL46Z) || defined(TARGET_K64F) || defined(TARGET_KL05Z) \ 00030 || defined(TARGET_K20D50M) || defined(TARGET_K22F) \ 00031 || defined(TARGET_NRF51822) \ 00032 || defined(TARGET_RZ_A1H) 00033 EthernetInterface eth(D4, D5, D3, D6, D7); // MOSI, MISO, SCK, CS, RESET 00034 00035 // If your board/plaform is not present yet then uncomment 00036 // the following two lines and replace modify as appropriate. 00037 00038 //#elif defined(TARGET_YOUR_BOARD) 00039 //EthernetInterface eth(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS, RESET); // MOSI, MISO, SCK, CS, RESET 00040 #endif 00041 00042 // Note: 00043 // If it happends that any of the SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS or RESET pins collide with LED1 pin 00044 // then either use different SPI port (if available on the board) and change the pin names 00045 // in the constructor spi(...) accordingly or instead of using LED1 pin, select 00046 // a free pin (not used by SPI port) and connect to it an external LED which is connected 00047 // to a 220 Ohm resitor that is connected to the groud. 00048 // In the second case remember to replace LED1 in sw(LED1) constructor (see below). 00049 // IP address must be also unique and compatible with your network. Change as appropriate. 00050 00051 // If instead of WIZ550io you'd like to use a W5500 module without a built-in MAC please uncommend the following line 00052 //#define W5500 1 00053 00054 #if defined(W5500) 00055 // The MAC number must be unique within the connected network. Modify as appropriate. 00056 uint8_t MY_MAC[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; 00057 #endif 00058 00059 const char MY_IP[] = "192.168.1.181"; 00060 const char MY_NETMASK[] = "255.255.255.0"; 00061 const char MY_GATEWAY[] = "192.168.1.1"; 00062 int MY_PORT = 80; 00063 00064 TCPSocketServer server; 00065 TCPSocketConnection client; 00066 bool serverIsListening = false; 00067 00068 DigitalOut sw(LED1); // Change LED1 to a pin of your choice. 00069 // However, make sure that it does not collide with any of the SPI pins 00070 float roomTemp = 21.8; // A temperature sensor output 00071 00072 const string PASSWORD = "secret"; // change as you like 00073 const string HTTP_OK = "HTTP/1.0 200 OK"; 00074 const string MOVED_PERM = "HTTP/1.0 301 Moved Permanently\r\nLocation: "; 00075 const string UNAUTHORIZED = "HTTP/1.0 401 Unauthorized"; 00076 00077 string httpHeader; // HTTP header 00078 string httpContent; // HTTP content 00079 00080 /** 00081 * @brief Analyses the received URL 00082 * @note The string passed to this function will look like this: 00083 * GET /password HTTP/1..... 00084 * GET /password/ HTTP/1..... 00085 * GET /password/?sw=1 HTTP/1..... 00086 * GET /password/?sw=0 HTTP/1..... 00087 * @param url URL string 00088 * @retval -1 invalid password 00089 * -2 no command given but password valid 00090 * -3 just refresh page 00091 * 0 switch off 00092 * 1 switch on 00093 */ 00094 int8_t analyseURL(string& url) { 00095 if(url.substr(5, PASSWORD.size()) != PASSWORD) 00096 return(-1); 00097 00098 uint8_t pos = 5 + PASSWORD.size(); 00099 00100 if(url.substr(pos, 1) == " ") 00101 return(-2); 00102 00103 if(url.substr(pos++, 1) != "/") 00104 return(-1); 00105 00106 string cmd(url.substr(pos, 5)); 00107 00108 if(cmd == "?sw=0") 00109 return(OFF); 00110 00111 if(cmd == "?sw=1") 00112 return(ON); 00113 00114 return(-3); 00115 } 00116 00117 /** 00118 * @brief 00119 * @note 00120 * @param 00121 * @retval 00122 */ 00123 string& movedPermanently(uint8_t flag) { 00124 if(flag == 1) 00125 httpContent = "/" + PASSWORD + "/"; 00126 else 00127 httpContent = ""; 00128 00129 httpContent += "<h1>301 Moved Permanently</h1>\r\n"; 00130 00131 return(httpContent); 00132 } 00133 00134 /** 00135 * @brief 00136 * @note 00137 * @param 00138 * @retval 00139 */ 00140 string& showWebPage(uint8_t status) { 00141 char roomTempStr[5]; 00142 00143 //roomTemp = ds1820.read(); 00144 sprintf(roomTempStr, "%3.1f", roomTemp); 00145 00146 httpContent = "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>"; 00147 httpContent += "<pre>Temperature:\t" + string(roomTempStr) + "°C\r\n</pre>"; 00148 00149 if(status == ON) { 00150 httpContent += "<pre>\r\nHeating:\t<font color=#FF0000>On </font>"; 00151 httpContent += " <a href=\"./?sw=0\"><button>Turn off</button></a>\r\n"; 00152 } 00153 else { 00154 httpContent += "<pre>\r\nHeating:\t<font color=#999999>Off</font>"; 00155 httpContent += " <a href=\"./?sw=1\"><button>Turn on</button></a>\r\n"; 00156 } 00157 00158 httpContent += "</pre>\r\n"; 00159 httpContent += "<hr>\r\n"; 00160 httpContent += "<pre>2017 ARMmbed</pre>"; 00161 return httpContent; 00162 } 00163 00164 /** 00165 * @brief 00166 * @note 00167 * @param 00168 * @retval 00169 */ 00170 void sendHTTP(TCPSocketConnection& client, string& header, string& content) { 00171 char contentLeght[5] = {}; 00172 00173 header += "\r\nContent-Type: text/html\r\n"; 00174 header += "Content-Length: "; 00175 sprintf(contentLeght, "%d", content.length()); 00176 header += string(contentLeght) + "\r\n"; 00177 header += "Pragma: no-cache\r\n"; 00178 header += "Connection: About to close\r\n"; 00179 header += "\r\n"; 00180 00181 string webpage = header + content; 00182 client.send(const_cast<char*>(webpage.c_str()), webpage.length()); 00183 } 00184 00185 /** 00186 * @brief 00187 * @note 00188 * @param 00189 * @retval 00190 */ 00191 void closeClient(void) { 00192 client.close(); 00193 serial.printf("Connection closed.\n\rTCP server is listening...\n\r"); 00194 } 00195 00196 /** 00197 * @brief 00198 * @note 00199 * @param 00200 * @retval 00201 */ 00202 int main(void) { 00203 #if defined(W5500) 00204 int ret = eth.init(MY_MAC, MY_IP, MY_NETMASK, MY_GATEWAY); 00205 #else 00206 int ret = eth.init(MY_IP, MY_NETMASK, MY_GATEWAY); 00207 #endif 00208 if(!ret) { 00209 serial.printf("Initialized, MY_MAC: %s\n", eth.getMACAddress()); 00210 serial.printf 00211 ( 00212 "Connected, MY_IP: %s, MY_NETMASK: %s, MY_GATEWAY: %s\n", 00213 eth.getIPAddress(), 00214 eth.getNetworkMask(), 00215 eth.getGateway() 00216 ); 00217 } 00218 else { 00219 serial.printf("Error eth.init() - ret = %d\n", ret); 00220 return -1; 00221 } 00222 00223 //setup tcp socket 00224 if(server.bind(MY_PORT) < 0) { 00225 serial.printf("TCP server bind failed.\n\r"); 00226 return -1; 00227 } 00228 else { 00229 serial.printf("TCP server bind succeeded.\n\r"); 00230 serverIsListening = true; 00231 } 00232 00233 if(server.listen(1) < 0) { 00234 serial.printf("TCP server listen failed.\n\r"); 00235 return -1; 00236 } 00237 else { 00238 serial.printf("TCP server is listening...\n\r"); 00239 } 00240 00241 while(serverIsListening) { 00242 if(server.accept(client) >= 0) { 00243 char buf[1024] = { }; 00244 00245 serial.printf("Client connected!\n\rIP: %s\n\r", client.get_address()); 00246 00247 switch(client.receive(buf, 1023)) { 00248 case 0: 00249 serial.printf("Recieved buffer is empty.\n\r"); 00250 break; 00251 00252 case -1: 00253 serial.printf("Failed to read data from client.\n\r"); 00254 break; 00255 00256 default: 00257 string received((char*)buf); 00258 00259 if(received.substr(0, 3) != "GET") { 00260 httpHeader = HTTP_OK; 00261 httpContent = "<h1>200 OK</h1>"; 00262 sendHTTP(client, httpHeader, httpContent); 00263 closeClient(); 00264 continue; 00265 } 00266 00267 if(received.substr(0, 6) == "GET / ") { 00268 httpHeader = HTTP_OK; 00269 httpContent = "<p>Usage: http://host_or_ip/password</p>\r\n"; 00270 sendHTTP(client, httpHeader, httpContent); 00271 closeClient(); 00272 continue; 00273 } 00274 00275 int cmd = analyseURL(received); 00276 00277 if(cmd == -2) { 00278 00279 // redirect to the right base url 00280 httpHeader = MOVED_PERM; 00281 sendHTTP(client, httpHeader, movedPermanently(1)); 00282 closeClient(); 00283 continue; 00284 } 00285 00286 if(cmd == -1) { 00287 httpHeader = UNAUTHORIZED; 00288 httpContent = "<h1>401 Unauthorized</h1>"; 00289 sendHTTP(client, httpHeader, httpContent); 00290 closeClient(); 00291 continue; 00292 } 00293 00294 if(cmd == ON) { 00295 sw = ON; // turn the switch on 00296 } 00297 00298 if(cmd == OFF) { 00299 sw = OFF; // turn the switch off 00300 } 00301 00302 httpHeader = HTTP_OK; 00303 sendHTTP(client, httpHeader, showWebPage(sw)); 00304 } 00305 closeClient(); 00306 } 00307 } 00308 }
Generated on Thu Jul 14 2022 09:10:05 by
