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: EthernetInterface mbed-rtos mbed-dev
Turn LED1, or other digital output, on/off using a web browser.
In this example we create a HTTP server that will serve a simple Web page to remotely turn LED1, or other digital output, on/off by using a web browser.
![]() | ![]() | ||
Notice that DHCP is turned on by default. The IP address assigned to the WebSwitch server along with an instruction how to use it is printed to the connected PC's serial terminal window during program start up.
The project was inspired by the Tuxgraphics Web Switch. Thank you Guido!
For a Web Switch using
- mbed OS 5 see WebSwitch_mbed-os
- ENC28J60 Ethernet module see WebSwitch_ENC28J60
- WIZ550io or W5500 Ethernet module see WebSwitch_Wiz550io.
main.cpp@2:4a51bdd24745, 2017-05-01 (annotated)
- Committer:
- hudakz
- Date:
- Mon May 01 20:03:14 2017 +0000
- Revision:
- 2:4a51bdd24745
- Parent:
- 1:c024e74b3a75
Button added.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hudakz | 0:da3404d26549 | 1 | #include "mbed.h" |
hudakz | 0:da3404d26549 | 2 | #include "EthernetInterface.h" |
hudakz | 0:da3404d26549 | 3 | #include <stdio.h> |
hudakz | 0:da3404d26549 | 4 | #include <string> |
hudakz | 0:da3404d26549 | 5 | |
hudakz | 0:da3404d26549 | 6 | using namespace std; |
hudakz | 0:da3404d26549 | 7 | |
hudakz | 1:c024e74b3a75 | 8 | #define PORT 80 |
hudakz | 0:da3404d26549 | 9 | |
hudakz | 0:da3404d26549 | 10 | EthernetInterface ethernet; |
hudakz | 0:da3404d26549 | 11 | |
hudakz | 0:da3404d26549 | 12 | TCPSocketServer server; |
hudakz | 0:da3404d26549 | 13 | bool serverIsListening = false; |
hudakz | 0:da3404d26549 | 14 | |
hudakz | 0:da3404d26549 | 15 | TCPSocketConnection client; |
hudakz | 0:da3404d26549 | 16 | bool clientIsConnected = false; |
hudakz | 0:da3404d26549 | 17 | |
hudakz | 0:da3404d26549 | 18 | const int OFF = 0; |
hudakz | 0:da3404d26549 | 19 | const int ON = 1; |
hudakz | 0:da3404d26549 | 20 | |
hudakz | 0:da3404d26549 | 21 | DigitalOut sw(LED1); |
hudakz | 2:4a51bdd24745 | 22 | float roomTemp = 21.8; // A temperature sensor output |
hudakz | 0:da3404d26549 | 23 | |
hudakz | 0:da3404d26549 | 24 | const string PASSWORD = "secret"; // change as you like |
hudakz | 0:da3404d26549 | 25 | const string HTTP_OK = "HTTP/1.0 200 OK"; |
hudakz | 0:da3404d26549 | 26 | const string MOVED_PERM = "HTTP/1.0 301 Moved Permanently\r\nLocation: "; |
hudakz | 0:da3404d26549 | 27 | const string UNAUTHORIZED = "HTTP/1.0 401 Unauthorized"; |
hudakz | 0:da3404d26549 | 28 | string httpHeader; // HTTP header |
hudakz | 0:da3404d26549 | 29 | string httpContent; // HTTP content |
hudakz | 2:4a51bdd24745 | 30 | |
hudakz | 0:da3404d26549 | 31 | /** |
hudakz | 1:c024e74b3a75 | 32 | * @brief Defines a custom MAC address |
hudakz | 1:c024e74b3a75 | 33 | * @note Uncomment the code below to define a unique MAC address. |
hudakz | 2:4a51bdd24745 | 34 | * Modify the mac array items as needed. |
hudakz | 0:da3404d26549 | 35 | * @param |
hudakz | 0:da3404d26549 | 36 | * @retval |
hudakz | 0:da3404d26549 | 37 | */ |
hudakz | 0:da3404d26549 | 38 | //extern "C" void mbed_mac_address(char* mac) { |
hudakz | 0:da3404d26549 | 39 | // mac[0] = 0x00; |
hudakz | 0:da3404d26549 | 40 | // mac[1] = 0x01; |
hudakz | 0:da3404d26549 | 41 | // mac[2] = 0x02; |
hudakz | 0:da3404d26549 | 42 | // mac[3] = 0x03; |
hudakz | 0:da3404d26549 | 43 | // mac[4] = 0x04; |
hudakz | 0:da3404d26549 | 44 | // mac[5] = 0x05; |
hudakz | 0:da3404d26549 | 45 | //}; |
hudakz | 0:da3404d26549 | 46 | |
hudakz | 1:c024e74b3a75 | 47 | /** |
hudakz | 1:c024e74b3a75 | 48 | * @brief Analyses the received URL |
hudakz | 1:c024e74b3a75 | 49 | * @note The string passed to this function will look like this: |
hudakz | 1:c024e74b3a75 | 50 | * GET /password HTTP/1..... |
hudakz | 1:c024e74b3a75 | 51 | * GET /password/ HTTP/1..... |
hudakz | 1:c024e74b3a75 | 52 | * GET /password/?sw=1 HTTP/1..... |
hudakz | 1:c024e74b3a75 | 53 | * GET /password/?sw=0 HTTP/1..... |
hudakz | 1:c024e74b3a75 | 54 | * @param url URL string |
hudakz | 1:c024e74b3a75 | 55 | * @retval -1 invalid password |
hudakz | 1:c024e74b3a75 | 56 | * -2 no command given but password valid |
hudakz | 1:c024e74b3a75 | 57 | * -3 just refresh page |
hudakz | 1:c024e74b3a75 | 58 | * 0 switch off |
hudakz | 1:c024e74b3a75 | 59 | * 1 switch on |
hudakz | 1:c024e74b3a75 | 60 | */ |
hudakz | 1:c024e74b3a75 | 61 | int8_t analyseURL(string& url) { |
hudakz | 1:c024e74b3a75 | 62 | if(url.substr(5, PASSWORD.size()) != PASSWORD) |
hudakz | 0:da3404d26549 | 63 | return(-1); |
hudakz | 0:da3404d26549 | 64 | |
hudakz | 0:da3404d26549 | 65 | uint8_t pos = 5 + PASSWORD.size(); |
hudakz | 0:da3404d26549 | 66 | |
hudakz | 1:c024e74b3a75 | 67 | if(url.substr(pos, 1) == " ") |
hudakz | 0:da3404d26549 | 68 | return(-2); |
hudakz | 0:da3404d26549 | 69 | |
hudakz | 1:c024e74b3a75 | 70 | if(url.substr(pos++, 1) != "/") |
hudakz | 0:da3404d26549 | 71 | return(-1); |
hudakz | 0:da3404d26549 | 72 | |
hudakz | 1:c024e74b3a75 | 73 | string cmd(url.substr(pos, 5)); |
hudakz | 0:da3404d26549 | 74 | |
hudakz | 0:da3404d26549 | 75 | if(cmd == "?sw=0") |
hudakz | 0:da3404d26549 | 76 | return(OFF); |
hudakz | 0:da3404d26549 | 77 | |
hudakz | 0:da3404d26549 | 78 | if(cmd == "?sw=1") |
hudakz | 0:da3404d26549 | 79 | return(ON); |
hudakz | 0:da3404d26549 | 80 | |
hudakz | 0:da3404d26549 | 81 | return(-3); |
hudakz | 0:da3404d26549 | 82 | } |
hudakz | 0:da3404d26549 | 83 | |
hudakz | 0:da3404d26549 | 84 | /** |
hudakz | 0:da3404d26549 | 85 | * @brief |
hudakz | 0:da3404d26549 | 86 | * @note |
hudakz | 0:da3404d26549 | 87 | * @param |
hudakz | 0:da3404d26549 | 88 | * @retval |
hudakz | 0:da3404d26549 | 89 | */ |
hudakz | 0:da3404d26549 | 90 | string& movedPermanently(uint8_t flag) { |
hudakz | 0:da3404d26549 | 91 | if(flag == 1) |
hudakz | 0:da3404d26549 | 92 | httpContent = "/" + PASSWORD + "/"; |
hudakz | 0:da3404d26549 | 93 | else |
hudakz | 0:da3404d26549 | 94 | httpContent = ""; |
hudakz | 0:da3404d26549 | 95 | |
hudakz | 0:da3404d26549 | 96 | httpContent += "<h1>301 Moved Permanently</h1>\r\n"; |
hudakz | 0:da3404d26549 | 97 | |
hudakz | 0:da3404d26549 | 98 | return(httpContent); |
hudakz | 0:da3404d26549 | 99 | } |
hudakz | 0:da3404d26549 | 100 | |
hudakz | 0:da3404d26549 | 101 | /** |
hudakz | 0:da3404d26549 | 102 | * @brief |
hudakz | 0:da3404d26549 | 103 | * @note |
hudakz | 0:da3404d26549 | 104 | * @param |
hudakz | 0:da3404d26549 | 105 | * @retval |
hudakz | 0:da3404d26549 | 106 | */ |
hudakz | 0:da3404d26549 | 107 | string& showWebPage(uint8_t status) { |
hudakz | 2:4a51bdd24745 | 108 | char roomTempStr[5]; |
hudakz | 0:da3404d26549 | 109 | |
hudakz | 2:4a51bdd24745 | 110 | //roomTemp = ds1820.read(); |
hudakz | 2:4a51bdd24745 | 111 | sprintf(roomTempStr, "%3.1f", roomTemp); |
hudakz | 2:4a51bdd24745 | 112 | |
hudakz | 2:4a51bdd24745 | 113 | httpContent = "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>"; |
hudakz | 2:4a51bdd24745 | 114 | httpContent += "<pre>Temperature:\t" + string(roomTempStr) + "°C\r\n</pre>"; |
hudakz | 0:da3404d26549 | 115 | |
hudakz | 0:da3404d26549 | 116 | if(status == ON) { |
hudakz | 2:4a51bdd24745 | 117 | httpContent += "<pre>\r\nHeating:\t<font color=#FF0000>On </font>"; |
hudakz | 2:4a51bdd24745 | 118 | httpContent += " <a href=\"./?sw=0\"><button>Turn off</button></a>\r\n"; |
hudakz | 0:da3404d26549 | 119 | } |
hudakz | 0:da3404d26549 | 120 | else { |
hudakz | 2:4a51bdd24745 | 121 | httpContent += "<pre>\r\nHeating:\t<font color=#999999>Off</font>"; |
hudakz | 2:4a51bdd24745 | 122 | httpContent += " <a href=\"./?sw=1\"><button>Turn on</button></a>\r\n"; |
hudakz | 0:da3404d26549 | 123 | } |
hudakz | 0:da3404d26549 | 124 | |
hudakz | 0:da3404d26549 | 125 | httpContent += "</pre>\r\n"; |
hudakz | 0:da3404d26549 | 126 | httpContent += "<hr>\r\n"; |
hudakz | 2:4a51bdd24745 | 127 | httpContent += "<pre>2017 ARMmbed</pre>"; |
hudakz | 0:da3404d26549 | 128 | return httpContent; |
hudakz | 0:da3404d26549 | 129 | } |
hudakz | 0:da3404d26549 | 130 | |
hudakz | 0:da3404d26549 | 131 | /** |
hudakz | 0:da3404d26549 | 132 | * @brief |
hudakz | 0:da3404d26549 | 133 | * @note |
hudakz | 0:da3404d26549 | 134 | * @param |
hudakz | 0:da3404d26549 | 135 | * @retval |
hudakz | 0:da3404d26549 | 136 | */ |
hudakz | 0:da3404d26549 | 137 | void sendHTTP(TCPSocketConnection& client, string& header, string& content) { |
hudakz | 1:c024e74b3a75 | 138 | char contentLength[5] = { }; |
hudakz | 0:da3404d26549 | 139 | |
hudakz | 0:da3404d26549 | 140 | header += "\r\nContent-Type: text/html\r\n"; |
hudakz | 0:da3404d26549 | 141 | header += "Content-Length: "; |
hudakz | 1:c024e74b3a75 | 142 | sprintf(contentLength, "%d", content.length()); |
hudakz | 1:c024e74b3a75 | 143 | header += string(contentLength) + "\r\n"; |
hudakz | 0:da3404d26549 | 144 | header += "Pragma: no-cache\r\n"; |
hudakz | 0:da3404d26549 | 145 | header += "Connection: About to close\r\n"; |
hudakz | 0:da3404d26549 | 146 | header += "\r\n"; |
hudakz | 0:da3404d26549 | 147 | |
hudakz | 0:da3404d26549 | 148 | string webpage = header + content; |
hudakz | 0:da3404d26549 | 149 | client.send((char*)webpage.c_str(), webpage.length()); |
hudakz | 0:da3404d26549 | 150 | clientIsConnected = false; |
hudakz | 0:da3404d26549 | 151 | printf("HTTP sent.\n\r"); |
hudakz | 0:da3404d26549 | 152 | } |
hudakz | 0:da3404d26549 | 153 | |
hudakz | 0:da3404d26549 | 154 | /** |
hudakz | 0:da3404d26549 | 155 | * @brief |
hudakz | 0:da3404d26549 | 156 | * @note |
hudakz | 0:da3404d26549 | 157 | * @param |
hudakz | 0:da3404d26549 | 158 | * @retval |
hudakz | 0:da3404d26549 | 159 | */ |
hudakz | 0:da3404d26549 | 160 | int main(void) { |
hudakz | 0:da3404d26549 | 161 | |
hudakz | 0:da3404d26549 | 162 | //setup ethernet interface |
hudakz | 0:da3404d26549 | 163 | ethernet.init(); //Use DHCP |
hudakz | 2:4a51bdd24745 | 164 | //ethernet.init("192.168.1.181", "255.255.255.0", "192.168.1.1"); // Use static IP |
hudakz | 0:da3404d26549 | 165 | ethernet.connect(); |
hudakz | 1:c024e74b3a75 | 166 | printf("USAGE: Type '%s/%s/' into your web browser and hit ENTER\r\n", ethernet.getIPAddress(), PASSWORD.c_str()); |
hudakz | 1:c024e74b3a75 | 167 | printf("NOTE: Don't forget to type the last '/'.\r\n\r\n"); |
hudakz | 0:da3404d26549 | 168 | |
hudakz | 0:da3404d26549 | 169 | //setup tcp socket |
hudakz | 0:da3404d26549 | 170 | if(server.bind(PORT) < 0) { |
hudakz | 0:da3404d26549 | 171 | printf("HTTP server bind failed.\n\r"); |
hudakz | 0:da3404d26549 | 172 | return -1; |
hudakz | 0:da3404d26549 | 173 | } |
hudakz | 0:da3404d26549 | 174 | else { |
hudakz | 1:c024e74b3a75 | 175 | printf("HTTP server bind succeeded.\n\r"); |
hudakz | 0:da3404d26549 | 176 | serverIsListening = true; |
hudakz | 0:da3404d26549 | 177 | } |
hudakz | 0:da3404d26549 | 178 | |
hudakz | 0:da3404d26549 | 179 | if(server.listen(1) < 0) { |
hudakz | 0:da3404d26549 | 180 | printf("HTTP server listen failed.\n\r"); |
hudakz | 0:da3404d26549 | 181 | return -1; |
hudakz | 0:da3404d26549 | 182 | } |
hudakz | 0:da3404d26549 | 183 | else { |
hudakz | 0:da3404d26549 | 184 | printf("HTTP server is listening...\n\r"); |
hudakz | 0:da3404d26549 | 185 | } |
hudakz | 0:da3404d26549 | 186 | |
hudakz | 0:da3404d26549 | 187 | //listening for http GET request |
hudakz | 0:da3404d26549 | 188 | while(serverIsListening) { |
hudakz | 0:da3404d26549 | 189 | |
hudakz | 0:da3404d26549 | 190 | if(server.accept(client) < 0) { |
hudakz | 0:da3404d26549 | 191 | printf("Failed to accept connection.\n\r"); |
hudakz | 0:da3404d26549 | 192 | } |
hudakz | 0:da3404d26549 | 193 | else { |
hudakz | 0:da3404d26549 | 194 | printf("\r\n=========================================\r\n"); |
hudakz | 1:c024e74b3a75 | 195 | printf("Connection accepted!\n\rIP: %s\n\r", client.get_address()); |
hudakz | 0:da3404d26549 | 196 | clientIsConnected = true; |
hudakz | 0:da3404d26549 | 197 | |
hudakz | 0:da3404d26549 | 198 | while(clientIsConnected) { |
hudakz | 0:da3404d26549 | 199 | char buffer[1024] = { }; |
hudakz | 0:da3404d26549 | 200 | switch(client.receive(buffer, 1023)) { |
hudakz | 0:da3404d26549 | 201 | case 0: |
hudakz | 0:da3404d26549 | 202 | printf("Recieved buffer is empty.\n\r"); |
hudakz | 0:da3404d26549 | 203 | clientIsConnected = false; |
hudakz | 0:da3404d26549 | 204 | break; |
hudakz | 0:da3404d26549 | 205 | |
hudakz | 0:da3404d26549 | 206 | case -1: |
hudakz | 0:da3404d26549 | 207 | printf("Failed to read data from client.\n\r"); |
hudakz | 0:da3404d26549 | 208 | clientIsConnected = false; |
hudakz | 0:da3404d26549 | 209 | break; |
hudakz | 0:da3404d26549 | 210 | |
hudakz | 0:da3404d26549 | 211 | default: |
hudakz | 0:da3404d26549 | 212 | printf("Recieved Data: %d\n\r\n\r%.*s\n\r", strlen(buffer), strlen(buffer), buffer); |
hudakz | 0:da3404d26549 | 213 | |
hudakz | 0:da3404d26549 | 214 | string received(buffer); |
hudakz | 0:da3404d26549 | 215 | if(received.substr(0, 3) != "GET") { |
hudakz | 0:da3404d26549 | 216 | httpHeader = HTTP_OK; |
hudakz | 0:da3404d26549 | 217 | httpContent = "<h1>200 OK</h1>"; |
hudakz | 0:da3404d26549 | 218 | sendHTTP(client, httpHeader, httpContent); |
hudakz | 0:da3404d26549 | 219 | continue; |
hudakz | 0:da3404d26549 | 220 | } |
hudakz | 0:da3404d26549 | 221 | |
hudakz | 0:da3404d26549 | 222 | if(received.substr(0, 6) == "GET / ") { |
hudakz | 0:da3404d26549 | 223 | httpHeader = HTTP_OK; |
hudakz | 1:c024e74b3a75 | 224 | httpContent = "<p>USAGE: Type 'http://ip_address/password/' into your web browser and hit ENTER</p>\r\n"; |
hudakz | 0:da3404d26549 | 225 | sendHTTP(client, httpHeader, httpContent); |
hudakz | 0:da3404d26549 | 226 | continue; |
hudakz | 0:da3404d26549 | 227 | } |
hudakz | 0:da3404d26549 | 228 | |
hudakz | 0:da3404d26549 | 229 | int cmd = analyseURL(received); |
hudakz | 0:da3404d26549 | 230 | |
hudakz | 0:da3404d26549 | 231 | if(cmd == -2) { |
hudakz | 0:da3404d26549 | 232 | |
hudakz | 1:c024e74b3a75 | 233 | // redirect to the correct base URL |
hudakz | 0:da3404d26549 | 234 | httpHeader = MOVED_PERM; |
hudakz | 0:da3404d26549 | 235 | sendHTTP(client, httpHeader, movedPermanently(1)); |
hudakz | 0:da3404d26549 | 236 | continue; |
hudakz | 0:da3404d26549 | 237 | } |
hudakz | 0:da3404d26549 | 238 | |
hudakz | 0:da3404d26549 | 239 | if(cmd == -1) { |
hudakz | 0:da3404d26549 | 240 | httpHeader = UNAUTHORIZED; |
hudakz | 0:da3404d26549 | 241 | httpContent = "<h1>401 Unauthorized</h1>"; |
hudakz | 0:da3404d26549 | 242 | sendHTTP(client, httpHeader, httpContent); |
hudakz | 0:da3404d26549 | 243 | continue; |
hudakz | 0:da3404d26549 | 244 | } |
hudakz | 0:da3404d26549 | 245 | |
hudakz | 0:da3404d26549 | 246 | if(cmd == ON) { |
hudakz | 0:da3404d26549 | 247 | sw = ON; // turn the switch on |
hudakz | 0:da3404d26549 | 248 | } |
hudakz | 0:da3404d26549 | 249 | |
hudakz | 0:da3404d26549 | 250 | if(cmd == OFF) { |
hudakz | 0:da3404d26549 | 251 | sw = OFF; // turn the switch off |
hudakz | 0:da3404d26549 | 252 | } |
hudakz | 0:da3404d26549 | 253 | |
hudakz | 0:da3404d26549 | 254 | httpHeader = HTTP_OK; |
hudakz | 0:da3404d26549 | 255 | sendHTTP(client, httpHeader, showWebPage(sw)); |
hudakz | 0:da3404d26549 | 256 | break; |
hudakz | 0:da3404d26549 | 257 | } |
hudakz | 0:da3404d26549 | 258 | } |
hudakz | 0:da3404d26549 | 259 | |
hudakz | 1:c024e74b3a75 | 260 | printf("Closing connection.\n\r"); |
hudakz | 1:c024e74b3a75 | 261 | printf("HTTP server is listening...\n\r"); |
hudakz | 0:da3404d26549 | 262 | client.close(); |
hudakz | 0:da3404d26549 | 263 | } |
hudakz | 0:da3404d26549 | 264 | } |
hudakz | 0:da3404d26549 | 265 | } |
hudakz | 2:4a51bdd24745 | 266 |