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.

Fork of WebSwitch_mbed-os by Zoltan Hudak

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.

/media/uploads/hudakz/webswitch03.png/media/uploads/hudakz/webswitch_mobile01.jpg

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.
To use static IP address uncomment and adjust line #221 in main.cpp.

The project was inspired by the Tuxgraphics Web Switch. Thank you Guido!

For a Web Switch using

Committer:
hudakz
Date:
Tue Jan 16 08:21:04 2018 +0000
Revision:
7:02a0635aeeac
Parent:
6:e2d251d535f0
Child:
8:47b0cb4b5b7d
Shows MAC address.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:e455fdb56bc8 1 #include "mbed.h"
hudakz 0:e455fdb56bc8 2 #include "EthernetInterface.h"
hudakz 0:e455fdb56bc8 3 #include "TCPServer.h"
hudakz 0:e455fdb56bc8 4 #include "TCPSocket.h"
hudakz 0:e455fdb56bc8 5 #include <stdio.h>
hudakz 0:e455fdb56bc8 6 #include <string>
hudakz 0:e455fdb56bc8 7
hudakz 0:e455fdb56bc8 8 using namespace std;
hudakz 0:e455fdb56bc8 9
hudakz 7:02a0635aeeac 10 #define IP "192.168.1.181"
hudakz 7:02a0635aeeac 11 #define GATEWAY "192.168.1.1"
hudakz 7:02a0635aeeac 12 #define MASK "255.255.255.0"
hudakz 7:02a0635aeeac 13
hudakz 7:02a0635aeeac 14
hudakz 0:e455fdb56bc8 15 #define PORT 80
hudakz 0:e455fdb56bc8 16
hudakz 0:e455fdb56bc8 17 EthernetInterface ethernet;
hudakz 0:e455fdb56bc8 18 TCPServer server;
hudakz 0:e455fdb56bc8 19 TCPSocket clientSocket;
hudakz 0:e455fdb56bc8 20 SocketAddress clientAddress;
hudakz 0:e455fdb56bc8 21 char receiveBuf[1024] = { };
hudakz 0:e455fdb56bc8 22
hudakz 0:e455fdb56bc8 23 const int OFF = 0;
hudakz 0:e455fdb56bc8 24 const int ON = 1;
hudakz 0:e455fdb56bc8 25
hudakz 0:e455fdb56bc8 26 DigitalOut sw(LED1);
hudakz 2:33e8bb5615a6 27 float roomTemp = 21.8; // A temperature sensor output
hudakz 0:e455fdb56bc8 28
hudakz 0:e455fdb56bc8 29 const string PASSWORD = "secret"; // change as you like
hudakz 0:e455fdb56bc8 30 const string HTTP_OK = "HTTP/1.0 200 OK";
hudakz 0:e455fdb56bc8 31 const string MOVED_PERM = "HTTP/1.0 301 Moved Permanently\r\nLocation: ";
hudakz 0:e455fdb56bc8 32 const string UNAUTHORIZED = "HTTP/1.0 401 Unauthorized";
hudakz 0:e455fdb56bc8 33 string httpHeader; // HTTP header
hudakz 0:e455fdb56bc8 34 string httpContent; // HTTP content
hudakz 2:33e8bb5615a6 35
hudakz 2:33e8bb5615a6 36 /**
hudakz 2:33e8bb5615a6 37 * @brief Defines a custom MAC address
hudakz 2:33e8bb5615a6 38 * @note Uncomment the code below to define a unique MAC address.
hudakz 2:33e8bb5615a6 39 * Modify the mac array items as needed.
hudakz 2:33e8bb5615a6 40 * @param
hudakz 2:33e8bb5615a6 41 * @retval
hudakz 2:33e8bb5615a6 42 */
hudakz 2:33e8bb5615a6 43 //extern "C" void mbed_mac_address(char* mac) {
hudakz 2:33e8bb5615a6 44 // mac[0] = 0x00;
hudakz 2:33e8bb5615a6 45 // mac[1] = 0x01;
hudakz 2:33e8bb5615a6 46 // mac[2] = 0x02;
hudakz 2:33e8bb5615a6 47 // mac[3] = 0x03;
hudakz 2:33e8bb5615a6 48 // mac[4] = 0x04;
hudakz 2:33e8bb5615a6 49 // mac[5] = 0x05;
hudakz 2:33e8bb5615a6 50 //};
hudakz 0:e455fdb56bc8 51
hudakz 2:33e8bb5615a6 52 /**
hudakz 2:33e8bb5615a6 53 * @brief Analyses the received URL
hudakz 2:33e8bb5615a6 54 * @note The string passed to this function will look like this:
hudakz 2:33e8bb5615a6 55 * GET /password HTTP/1.....
hudakz 2:33e8bb5615a6 56 * GET /password/ HTTP/1.....
hudakz 2:33e8bb5615a6 57 * GET /password/?sw=1 HTTP/1.....
hudakz 2:33e8bb5615a6 58 * GET /password/?sw=0 HTTP/1.....
hudakz 2:33e8bb5615a6 59 * @param url URL string
hudakz 2:33e8bb5615a6 60 * @retval -1 invalid password
hudakz 2:33e8bb5615a6 61 * -2 no command given but password valid
hudakz 2:33e8bb5615a6 62 * -3 just refresh page
hudakz 2:33e8bb5615a6 63 * 0 switch off
hudakz 2:33e8bb5615a6 64 * 1 switch on
hudakz 2:33e8bb5615a6 65 */
hudakz 2:33e8bb5615a6 66 int8_t analyseURL(string& url) {
hudakz 2:33e8bb5615a6 67 if(url.substr(5, PASSWORD.size()) != PASSWORD)
hudakz 0:e455fdb56bc8 68 return(-1);
hudakz 0:e455fdb56bc8 69
hudakz 0:e455fdb56bc8 70 uint8_t pos = 5 + PASSWORD.size();
hudakz 0:e455fdb56bc8 71
hudakz 2:33e8bb5615a6 72 if(url.substr(pos, 1) == " ")
hudakz 0:e455fdb56bc8 73 return(-2);
hudakz 0:e455fdb56bc8 74
hudakz 2:33e8bb5615a6 75 if(url.substr(pos++, 1) != "/")
hudakz 0:e455fdb56bc8 76 return(-1);
hudakz 0:e455fdb56bc8 77
hudakz 2:33e8bb5615a6 78 string cmd(url.substr(pos, 5));
hudakz 0:e455fdb56bc8 79
hudakz 0:e455fdb56bc8 80 if(cmd == "?sw=0")
hudakz 2:33e8bb5615a6 81 return(0);
hudakz 0:e455fdb56bc8 82
hudakz 0:e455fdb56bc8 83 if(cmd == "?sw=1")
hudakz 2:33e8bb5615a6 84 return(1);
hudakz 0:e455fdb56bc8 85
hudakz 0:e455fdb56bc8 86 return(-3);
hudakz 0:e455fdb56bc8 87 }
hudakz 0:e455fdb56bc8 88
hudakz 0:e455fdb56bc8 89 /**
hudakz 0:e455fdb56bc8 90 * @brief
hudakz 0:e455fdb56bc8 91 * @note
hudakz 0:e455fdb56bc8 92 * @param
hudakz 0:e455fdb56bc8 93 * @retval
hudakz 0:e455fdb56bc8 94 */
hudakz 0:e455fdb56bc8 95 string& movedPermanently(uint8_t flag) {
hudakz 0:e455fdb56bc8 96 if(flag == 1)
hudakz 0:e455fdb56bc8 97 httpContent = "/" + PASSWORD + "/";
hudakz 0:e455fdb56bc8 98 else
hudakz 0:e455fdb56bc8 99 httpContent = "";
hudakz 0:e455fdb56bc8 100
hudakz 0:e455fdb56bc8 101 httpContent += "<h1>301 Moved Permanently</h1>\r\n";
hudakz 0:e455fdb56bc8 102
hudakz 0:e455fdb56bc8 103 return(httpContent);
hudakz 0:e455fdb56bc8 104 }
hudakz 0:e455fdb56bc8 105
hudakz 0:e455fdb56bc8 106 /**
hudakz 0:e455fdb56bc8 107 * @brief
hudakz 0:e455fdb56bc8 108 * @note
hudakz 0:e455fdb56bc8 109 * @param
hudakz 0:e455fdb56bc8 110 * @retval
hudakz 0:e455fdb56bc8 111 */
hudakz 0:e455fdb56bc8 112 string& showWebPage(uint8_t status) {
hudakz 2:33e8bb5615a6 113 char roomTempStr[5];
hudakz 7:02a0635aeeac 114
hudakz 2:33e8bb5615a6 115 //roomTemp = ds1820.read();
hudakz 2:33e8bb5615a6 116 sprintf(roomTempStr, "%3.1f", roomTemp);
hudakz 2:33e8bb5615a6 117
hudakz 5:e1218721aefd 118 // CSS toggle switch
hudakz 5:e1218721aefd 119 httpContent = "<head>";
hudakz 5:e1218721aefd 120 httpContent += "<style>";
hudakz 7:02a0635aeeac 121
hudakz 5:e1218721aefd 122 httpContent += ".switch {";
hudakz 5:e1218721aefd 123 httpContent += "position: relative;";
hudakz 5:e1218721aefd 124 httpContent += "display: inline-block;";
hudakz 5:e1218721aefd 125 httpContent += "width: 60px;";
hudakz 5:e1218721aefd 126 httpContent += "height: 34px;";
hudakz 5:e1218721aefd 127 httpContent += "}";
hudakz 5:e1218721aefd 128
hudakz 5:e1218721aefd 129 httpContent += ".switch input {display:none;}";
hudakz 5:e1218721aefd 130
hudakz 5:e1218721aefd 131 httpContent += ".slider {";
hudakz 5:e1218721aefd 132 httpContent += "position: absolute;";
hudakz 5:e1218721aefd 133 httpContent += "cursor: pointer;";
hudakz 5:e1218721aefd 134 httpContent += "top: 0;";
hudakz 5:e1218721aefd 135 httpContent += "left: 0;";
hudakz 5:e1218721aefd 136 httpContent += "right: 0;";
hudakz 5:e1218721aefd 137 httpContent += "bottom: 0;";
hudakz 6:e2d251d535f0 138 httpContent += "border-radius: 34px;";
hudakz 5:e1218721aefd 139 httpContent += "background-color: #ccc;";
hudakz 5:e1218721aefd 140 httpContent += "-webkit-transition: .4s;";
hudakz 5:e1218721aefd 141 httpContent += "transition: .4s;";
hudakz 5:e1218721aefd 142 httpContent += "}";
hudakz 5:e1218721aefd 143
hudakz 5:e1218721aefd 144 httpContent += ".slider:before {";
hudakz 5:e1218721aefd 145 httpContent += "position: absolute;";
hudakz 5:e1218721aefd 146 httpContent += "content: \"\";";
hudakz 5:e1218721aefd 147 httpContent += "height: 26px;";
hudakz 5:e1218721aefd 148 httpContent += "width: 26px;";
hudakz 5:e1218721aefd 149 httpContent += "left: 4px;";
hudakz 5:e1218721aefd 150 httpContent += "bottom: 4px;";
hudakz 6:e2d251d535f0 151 httpContent += "border-radius: 50%;";
hudakz 5:e1218721aefd 152 httpContent += "background-color: white;";
hudakz 5:e1218721aefd 153 httpContent += "-webkit-transition: .4s;";
hudakz 5:e1218721aefd 154 httpContent += "transition: .4s;";
hudakz 5:e1218721aefd 155 httpContent += "}";
hudakz 5:e1218721aefd 156
hudakz 5:e1218721aefd 157 httpContent += "input:checked + .slider {";
hudakz 5:e1218721aefd 158 httpContent += "background-color: #8ce196;";
hudakz 5:e1218721aefd 159 httpContent += "}";
hudakz 5:e1218721aefd 160
hudakz 5:e1218721aefd 161 httpContent += "input:focus + .slider {";
hudakz 5:e1218721aefd 162 httpContent += "box-shadow: 0 0 1px #8ce196;";
hudakz 5:e1218721aefd 163 httpContent += "}";
hudakz 5:e1218721aefd 164
hudakz 5:e1218721aefd 165 httpContent += "input:checked + .slider:before {";
hudakz 5:e1218721aefd 166 httpContent += "-webkit-transform: translateX(26px);";
hudakz 5:e1218721aefd 167 httpContent += "-ms-transform: translateX(26px);";
hudakz 5:e1218721aefd 168 httpContent += "transform: translateX(26px);";
hudakz 5:e1218721aefd 169 httpContent += "}";
hudakz 5:e1218721aefd 170
hudakz 5:e1218721aefd 171 httpContent += "</style>";
hudakz 5:e1218721aefd 172 httpContent += "</head>";
hudakz 5:e1218721aefd 173
hudakz 5:e1218721aefd 174 httpContent += "<body>";
hudakz 7:02a0635aeeac 175 httpContent += "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>";
hudakz 5:e1218721aefd 176 httpContent += "<pre>Temperature:\t" + string(roomTempStr) + "&deg;C</pre>";
hudakz 6:e2d251d535f0 177 httpContent += "<pre>Heating:\t";
hudakz 0:e455fdb56bc8 178
hudakz 0:e455fdb56bc8 179 if(status == ON) {
hudakz 6:e2d251d535f0 180 httpContent += "<a href=\"./?sw=0\" class=\"switch\"> ";
hudakz 5:e1218721aefd 181 httpContent += "<input type=\"checkbox\" checked>";
hudakz 0:e455fdb56bc8 182 }
hudakz 0:e455fdb56bc8 183 else {
hudakz 6:e2d251d535f0 184 httpContent += "<a href=\"./?sw=1\" class=\"switch\"> ";
hudakz 5:e1218721aefd 185 httpContent += "<input type=\"checkbox\">";
hudakz 5:e1218721aefd 186 }
hudakz 7:02a0635aeeac 187
hudakz 5:e1218721aefd 188 httpContent += "<div class=\"slider\"></div>";
hudakz 6:e2d251d535f0 189 httpContent += "</a></pre>";
hudakz 5:e1218721aefd 190 httpContent += "<hr>";
hudakz 7:02a0635aeeac 191 httpContent += "<pre>2017 armMBED</pre>";
hudakz 5:e1218721aefd 192 httpContent += "</body>";
hudakz 0:e455fdb56bc8 193
hudakz 0:e455fdb56bc8 194 return httpContent;
hudakz 0:e455fdb56bc8 195 }
hudakz 0:e455fdb56bc8 196
hudakz 0:e455fdb56bc8 197 /**
hudakz 0:e455fdb56bc8 198 * @brief
hudakz 0:e455fdb56bc8 199 * @note
hudakz 0:e455fdb56bc8 200 * @param
hudakz 0:e455fdb56bc8 201 * @retval
hudakz 0:e455fdb56bc8 202 */
hudakz 0:e455fdb56bc8 203 void sendHTTP(TCPSocket& client, string& header, string& content) {
hudakz 0:e455fdb56bc8 204 char content_length[5] = { };
hudakz 0:e455fdb56bc8 205
hudakz 0:e455fdb56bc8 206 header += "\r\nContent-Type: text/html\r\n";
hudakz 0:e455fdb56bc8 207 header += "Content-Length: ";
hudakz 0:e455fdb56bc8 208 sprintf(content_length, "%d", content.length());
hudakz 0:e455fdb56bc8 209 header += string(content_length) + "\r\n";
hudakz 0:e455fdb56bc8 210 header += "Pragma: no-cache\r\n";
hudakz 0:e455fdb56bc8 211 header += "Connection: About to close\r\n";
hudakz 0:e455fdb56bc8 212 header += "\r\n";
hudakz 0:e455fdb56bc8 213
hudakz 0:e455fdb56bc8 214 string webpage = header + content;
hudakz 0:e455fdb56bc8 215 client.send((char*)webpage.c_str(), webpage.length());
hudakz 0:e455fdb56bc8 216 printf("HTTP sent.\n\r");
hudakz 0:e455fdb56bc8 217 }
hudakz 0:e455fdb56bc8 218
hudakz 0:e455fdb56bc8 219 /**
hudakz 0:e455fdb56bc8 220 * @brief
hudakz 0:e455fdb56bc8 221 * @note
hudakz 0:e455fdb56bc8 222 * @param
hudakz 0:e455fdb56bc8 223 * @retval
hudakz 0:e455fdb56bc8 224 */
hudakz 0:e455fdb56bc8 225 int main(void) {
hudakz 7:02a0635aeeac 226 // ethernet.set_network("192.168.1.181","255.255.255.0","192.168.1.1"); // use static IP address, netmask, gateway
hudakz 0:e455fdb56bc8 227 ethernet.connect();
hudakz 4:d7c37f516f5f 228 printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n", ethernet.get_ip_address(), PASSWORD.c_str());
hudakz 7:02a0635aeeac 229 const char *mac = ethernet.get_mac_address();
hudakz 7:02a0635aeeac 230 printf("MAC address is: %s\n\r", mac ? mac : "No MAC");
hudakz 0:e455fdb56bc8 231
hudakz 0:e455fdb56bc8 232 /* Open the server on ethernet stack */
hudakz 0:e455fdb56bc8 233 server.open(&ethernet);
hudakz 7:02a0635aeeac 234
hudakz 0:e455fdb56bc8 235 /* Bind the HTTP port (TCP 80) to the server */
hudakz 0:e455fdb56bc8 236 server.bind(ethernet.get_ip_address(), 80);
hudakz 7:02a0635aeeac 237
hudakz 0:e455fdb56bc8 238 /* Can handle 5 simultaneous connections */
hudakz 0:e455fdb56bc8 239 server.listen(5);
hudakz 0:e455fdb56bc8 240
hudakz 0:e455fdb56bc8 241 //listening for http GET request
hudakz 0:e455fdb56bc8 242 while(true) {
hudakz 7:02a0635aeeac 243 printf("=========================================\r\n");
hudakz 2:33e8bb5615a6 244 printf("Ready to serve clients.\r\n");
hudakz 0:e455fdb56bc8 245 server.accept(&clientSocket, &clientAddress);
hudakz 0:e455fdb56bc8 246 printf("Connection succeeded!\n\rIP: %s\n\r", clientAddress.get_ip_address());
hudakz 0:e455fdb56bc8 247 clientSocket.recv(receiveBuf, 1023);
hudakz 0:e455fdb56bc8 248 printf("Recieved Data: %d\n\r\n\r%.*s\n\r", strlen(receiveBuf), strlen(receiveBuf), receiveBuf);
hudakz 0:e455fdb56bc8 249
hudakz 0:e455fdb56bc8 250 string received(receiveBuf);
hudakz 7:02a0635aeeac 251
hudakz 0:e455fdb56bc8 252 if(received.substr(0, 3) != "GET") {
hudakz 0:e455fdb56bc8 253 httpHeader = HTTP_OK;
hudakz 0:e455fdb56bc8 254 httpContent = "<h1>200 OK</h1>";
hudakz 0:e455fdb56bc8 255 sendHTTP(clientSocket, httpHeader, httpContent);
hudakz 0:e455fdb56bc8 256 continue;
hudakz 0:e455fdb56bc8 257 }
hudakz 0:e455fdb56bc8 258
hudakz 0:e455fdb56bc8 259 if(received.substr(0, 6) == "GET / ") {
hudakz 0:e455fdb56bc8 260 httpHeader = HTTP_OK;
hudakz 0:e455fdb56bc8 261 httpContent = "<p>Usage: Type http://ip_address/password/ into your web browser and hit ENTER</p>\r\n";
hudakz 0:e455fdb56bc8 262 sendHTTP(clientSocket, httpHeader, httpContent);
hudakz 0:e455fdb56bc8 263 continue;
hudakz 0:e455fdb56bc8 264 }
hudakz 0:e455fdb56bc8 265
hudakz 0:e455fdb56bc8 266 int cmd = analyseURL(received);
hudakz 0:e455fdb56bc8 267
hudakz 0:e455fdb56bc8 268 if(cmd == -2) {
hudakz 0:e455fdb56bc8 269
hudakz 0:e455fdb56bc8 270 // redirect to the right base url
hudakz 0:e455fdb56bc8 271 httpHeader = MOVED_PERM;
hudakz 0:e455fdb56bc8 272 sendHTTP(clientSocket, httpHeader, movedPermanently(1));
hudakz 0:e455fdb56bc8 273 continue;
hudakz 0:e455fdb56bc8 274 }
hudakz 0:e455fdb56bc8 275
hudakz 0:e455fdb56bc8 276 if(cmd == -1) {
hudakz 0:e455fdb56bc8 277 httpHeader = UNAUTHORIZED;
hudakz 0:e455fdb56bc8 278 httpContent = "<h1>401 Unauthorized</h1>";
hudakz 0:e455fdb56bc8 279 sendHTTP(clientSocket, httpHeader, httpContent);
hudakz 0:e455fdb56bc8 280 continue;
hudakz 0:e455fdb56bc8 281 }
hudakz 0:e455fdb56bc8 282
hudakz 0:e455fdb56bc8 283 if(cmd == ON) {
hudakz 0:e455fdb56bc8 284 sw = ON; // turn the switch on
hudakz 0:e455fdb56bc8 285 }
hudakz 0:e455fdb56bc8 286
hudakz 0:e455fdb56bc8 287 if(cmd == OFF) {
hudakz 0:e455fdb56bc8 288 sw = OFF; // turn the switch off
hudakz 0:e455fdb56bc8 289 }
hudakz 0:e455fdb56bc8 290
hudakz 0:e455fdb56bc8 291 httpHeader = HTTP_OK;
hudakz 0:e455fdb56bc8 292 sendHTTP(clientSocket, httpHeader, showWebPage(sw));
hudakz 0:e455fdb56bc8 293 }
hudakz 0:e455fdb56bc8 294 }