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 Oct 30 16:41:15 2018 +0000
Revision:
8:47b0cb4b5b7d
Parent:
7:02a0635aeeac
Child:
9:161bed13b17e
Updated.

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