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 27 16:43:25 2020 +0000
Revision:
12:138b2b3d041a
Parent:
11:101be77aa5db
Tiny HTTP server switching LED1 (or other DigitalOut) on/off.

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