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:
Mon May 08 14:27:58 2017 +0000
Revision:
5:e1218721aefd
Parent:
4:d7c37f516f5f
Child:
6:e2d251d535f0
Added sliding switch button.

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