HTTP Server serving a simple webpage which enables to remotely turn a digital output on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.

Dependencies:   UIPEthernet

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 the mbed board, on/off by using a web browser. An inexpensive ENC28J60 Ethernet module is used to assure connection between the mbed board and the Ethernet network (Internet). The ENC28J60 Ethernet module is driven by the UIPEthernet library.

Needed parts:

  • mbed board
  • ENC28J60 Ethernet module
  • Wires
  • Web browser (Internet Explorer, Safari, Firefox, Chrome ...) running on Windows, Mac, Linux, iPhone or Android device.
/media/uploads/hudakz/webswitch_enc.jpg/media/uploads/hudakz/webswitch_mobile01.jpg

Notice that DHCP is turned on by default. If you prefer to use static IP address then uncomment line 234

The IP address assigned to the WebSwitch server along with an instruction how to use it is printed in the connected PC's serial terminal window during program start up.

Warning

Please notice that the 3.3V power supply chip (RT8183-B) installed on an STM32F103C8T6 board is not rated to power also the ENC28J60 board.


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

NOTE:

Committer:
hudakz
Date:
Tue Aug 27 15:03:19 2019 +0000
Revision:
10:b47c7921346f
Parent:
5:0ab8292e37da
Child:
11:6c0b20227ca2
Mbed OS 5 enabled.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 10:b47c7921346f 1 #include "mbed.h"
hudakz 0:68a0003c4cb8 2 #include <string>
hudakz 10:b47c7921346f 3 #include "UipEthernet.h"
hudakz 10:b47c7921346f 4 #include "TcpServer.h"
hudakz 10:b47c7921346f 5 #include "TcpClient.h"
hudakz 0:68a0003c4cb8 6
hudakz 10:b47c7921346f 7 using namespace std;
hudakz 4:d34811deedab 8
hudakz 10:b47c7921346f 9 // To be used when static IP is needed
hudakz 10:b47c7921346f 10 #define IP "192.168.1.35"
hudakz 10:b47c7921346f 11 #define GATEWAY "192.168.1.1"
hudakz 10:b47c7921346f 12 #define NETMASK "255.255.255.0"
hudakz 10:b47c7921346f 13 #define PORT 80
hudakz 0:68a0003c4cb8 14
hudakz 10:b47c7921346f 15 // The ENC28J60 chip doesn't have a built-in MAC address.
hudakz 10:b47c7921346f 16 // It's up to us to provide one which is unique within the connected network.
hudakz 10:b47c7921346f 17 // So modify the one below accordingly.
hudakz 10:b47c7921346f 18 const uint8_t MAC[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
hudakz 10:b47c7921346f 19 UipEthernet net(MAC, D11, D12, D13, D10); // mosi, miso, sck, cs
hudakz 10:b47c7921346f 20 TcpServer server; // TCP server running on this mbed device
hudakz 10:b47c7921346f 21 TcpClient* client; // TCP client communicating with a HTTP Browser running on a PC or Mobile device
hudakz 10:b47c7921346f 22 const int OFF = 0;
hudakz 10:b47c7921346f 23 const int ON = 1;
hudakz 10:b47c7921346f 24 DigitalOut output(D3); // A digital output to be switched on/off
hudakz 10:b47c7921346f 25 float roomTemp = 21.8; // A dummy temperature sensor output
hudakz 10:b47c7921346f 26 const string PASSWORD = "secret"; // Change as you like
hudakz 10:b47c7921346f 27 string httpHeader; // HTTP header
hudakz 10:b47c7921346f 28 string httpContent; // HTTP content
hudakz 0:68a0003c4cb8 29
hudakz 10:b47c7921346f 30 /**
hudakz 10:b47c7921346f 31 * @brief Analyses the received URL
hudakz 10:b47c7921346f 32 * @note The string passed to this function will look like this:
hudakz 10:b47c7921346f 33 * GET /HTTP/1.....
hudakz 10:b47c7921346f 34 * GET /password HTTP/1.....
hudakz 10:b47c7921346f 35 * GET /password/ HTTP/1.....
hudakz 10:b47c7921346f 36 * GET /password/?sw=1 HTTP/1.....
hudakz 10:b47c7921346f 37 * GET /password/?sw=0 HTTP/1.....
hudakz 10:b47c7921346f 38 * @param url URL string
hudakz 10:b47c7921346f 39 * @retval -3 just refresh page
hudakz 10:b47c7921346f 40 * -2 no command given but password valid
hudakz 10:b47c7921346f 41 * -1 invalid password
hudakz 10:b47c7921346f 42 * 0 switch off
hudakz 10:b47c7921346f 43 * 1 switch on
hudakz 10:b47c7921346f 44 */
hudakz 10:b47c7921346f 45 int8_t analyseURL(string& url)
hudakz 10:b47c7921346f 46 {
hudakz 10:b47c7921346f 47 if (url.length() < 5 + PASSWORD.size() + 1)
hudakz 10:b47c7921346f 48 return(-1);
hudakz 0:68a0003c4cb8 49
hudakz 10:b47c7921346f 50 if (url.substr(5, PASSWORD.size()) != PASSWORD)
hudakz 0:68a0003c4cb8 51 return(-1);
hudakz 0:68a0003c4cb8 52
hudakz 0:68a0003c4cb8 53 uint8_t pos = 5 + PASSWORD.size();
hudakz 0:68a0003c4cb8 54
hudakz 10:b47c7921346f 55 if (url.substr(pos, 1) != "/")
hudakz 0:68a0003c4cb8 56 return(-1);
hudakz 0:68a0003c4cb8 57
hudakz 10:b47c7921346f 58 if (url.substr(pos++, 1) == " ")
hudakz 10:b47c7921346f 59 return(-2);
hudakz 0:68a0003c4cb8 60
hudakz 10:b47c7921346f 61 string cmd(url.substr(pos, 5));
hudakz 0:68a0003c4cb8 62
hudakz 10:b47c7921346f 63 if (cmd == "?sw=0")
hudakz 0:68a0003c4cb8 64 return(0);
hudakz 0:68a0003c4cb8 65
hudakz 10:b47c7921346f 66 if (cmd == "?sw=1")
hudakz 0:68a0003c4cb8 67 return(1);
hudakz 0:68a0003c4cb8 68
hudakz 0:68a0003c4cb8 69 return(-3);
hudakz 0:68a0003c4cb8 70 }
hudakz 0:68a0003c4cb8 71
hudakz 5:0ab8292e37da 72 /**
hudakz 5:0ab8292e37da 73 * @brief
hudakz 5:0ab8292e37da 74 * @note
hudakz 5:0ab8292e37da 75 * @param
hudakz 5:0ab8292e37da 76 * @retval
hudakz 5:0ab8292e37da 77 */
hudakz 10:b47c7921346f 78 string& movedPermanently(uint8_t flag)
hudakz 10:b47c7921346f 79 {
hudakz 10:b47c7921346f 80 if (flag == 1)
hudakz 5:0ab8292e37da 81 httpContent = "/" + PASSWORD + "/";
hudakz 0:68a0003c4cb8 82 else
hudakz 0:68a0003c4cb8 83 httpContent = "";
hudakz 0:68a0003c4cb8 84
hudakz 0:68a0003c4cb8 85 httpContent += "<h1>301 Moved Permanently</h1>\r\n";
hudakz 0:68a0003c4cb8 86
hudakz 5:0ab8292e37da 87 return(httpContent);
hudakz 0:68a0003c4cb8 88 }
hudakz 0:68a0003c4cb8 89
hudakz 5:0ab8292e37da 90 /**
hudakz 5:0ab8292e37da 91 * @brief
hudakz 5:0ab8292e37da 92 * @note
hudakz 5:0ab8292e37da 93 * @param
hudakz 5:0ab8292e37da 94 * @retval
hudakz 5:0ab8292e37da 95 */
hudakz 10:b47c7921346f 96 string& showWebPage(int status)
hudakz 10:b47c7921346f 97 {
hudakz 10:b47c7921346f 98 char roomTempStr[5];
hudakz 10:b47c7921346f 99
hudakz 10:b47c7921346f 100 //roomTemp = ds1820.read();
hudakz 10:b47c7921346f 101 sprintf(roomTempStr, "%3.1f", roomTemp);
hudakz 0:68a0003c4cb8 102
hudakz 10:b47c7921346f 103 /*$off*/
hudakz 10:b47c7921346f 104 httpContent =
hudakz 10:b47c7921346f 105 "<head>"
hudakz 10:b47c7921346f 106 "<meta charset=\"utf-8\">"
hudakz 10:b47c7921346f 107 "<meta name=\"viewport\" content=\" initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=0;\"/>"
hudakz 10:b47c7921346f 108 "<title>Smart Home</title>"
hudakz 10:b47c7921346f 109 "<link href='http://fonts.googleapis.com/css?family=Droid+Sans&v1' rel='stylesheet' type='text/css'>"
hudakz 10:b47c7921346f 110 "<style>"
hudakz 10:b47c7921346f 111 ".switch {"
hudakz 10:b47c7921346f 112 "position: relative;"
hudakz 10:b47c7921346f 113 "display: inline-block;"
hudakz 10:b47c7921346f 114 "width: 60px;"
hudakz 10:b47c7921346f 115 "height: 34px;"
hudakz 10:b47c7921346f 116 "}"
hudakz 10:b47c7921346f 117 ".switch input {display:none;}"
hudakz 10:b47c7921346f 118 ".slider {"
hudakz 10:b47c7921346f 119 "position: absolute;"
hudakz 10:b47c7921346f 120 "cursor: pointer;"
hudakz 10:b47c7921346f 121 "top: 0;"
hudakz 10:b47c7921346f 122 "left: 0;"
hudakz 10:b47c7921346f 123 "right: 0;"
hudakz 10:b47c7921346f 124 "bottom: 0;"
hudakz 10:b47c7921346f 125 "border-radius: 34px;"
hudakz 10:b47c7921346f 126 "background-color: #ccc;"
hudakz 10:b47c7921346f 127 "-webkit-transition: .4s;"
hudakz 10:b47c7921346f 128 "transition: .4s;"
hudakz 10:b47c7921346f 129 "}"
hudakz 10:b47c7921346f 130 ".slider:before {"
hudakz 10:b47c7921346f 131 "position: absolute;"
hudakz 10:b47c7921346f 132 "content: \"\";"
hudakz 10:b47c7921346f 133 "height: 26px;"
hudakz 10:b47c7921346f 134 "width: 26px;"
hudakz 10:b47c7921346f 135 "left: 4px;"
hudakz 10:b47c7921346f 136 "bottom: 4px;"
hudakz 10:b47c7921346f 137 "border-radius: 50%;"
hudakz 10:b47c7921346f 138 "background-color: white;"
hudakz 10:b47c7921346f 139 "-webkit-transition: .4s;"
hudakz 10:b47c7921346f 140 "transition: .4s;"
hudakz 10:b47c7921346f 141 "}"
hudakz 10:b47c7921346f 142 "input:checked + .slider {"
hudakz 10:b47c7921346f 143 "background-color: #8ce196;"
hudakz 10:b47c7921346f 144 "}"
hudakz 10:b47c7921346f 145 "input:focus + .slider {"
hudakz 10:b47c7921346f 146 "box-shadow: 0 0 1px #8ce196;"
hudakz 10:b47c7921346f 147 "}"
hudakz 10:b47c7921346f 148 "input:checked + .slider:before {"
hudakz 10:b47c7921346f 149 "-webkit-transform: translateX(26px);"
hudakz 10:b47c7921346f 150 "-ms-transform: translateX(26px);"
hudakz 10:b47c7921346f 151 "transform: translateX(26px);"
hudakz 10:b47c7921346f 152 "}"
hudakz 10:b47c7921346f 153 "</style>"
hudakz 10:b47c7921346f 154 "</head>"
hudakz 10:b47c7921346f 155
hudakz 10:b47c7921346f 156 "<body>"
hudakz 10:b47c7921346f 157 "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>"
hudakz 10:b47c7921346f 158 "<pre>Temperature:\t" + string(roomTempStr) + "&deg;C</pre>"
hudakz 10:b47c7921346f 159 "<pre>Heating:\t";
hudakz 10:b47c7921346f 160
hudakz 10:b47c7921346f 161 if(status == ON) {
hudakz 10:b47c7921346f 162 httpContent +=
hudakz 10:b47c7921346f 163 "<a href=\"./?sw=0\" class=\"switch\"> "
hudakz 10:b47c7921346f 164 "<input type=\"checkbox\" checked>";
hudakz 5:0ab8292e37da 165 }
hudakz 5:0ab8292e37da 166 else {
hudakz 10:b47c7921346f 167 httpContent +=
hudakz 10:b47c7921346f 168 "<a href=\"./?sw=1\" class=\"switch\"> "
hudakz 10:b47c7921346f 169 "<input type=\"checkbox\">";
hudakz 0:68a0003c4cb8 170 }
hudakz 0:68a0003c4cb8 171
hudakz 10:b47c7921346f 172 httpContent +=
hudakz 10:b47c7921346f 173 "<div class=\"slider\"></div>"
hudakz 10:b47c7921346f 174 "</a>"
hudakz 10:b47c7921346f 175 "</pre>"
hudakz 10:b47c7921346f 176 "<hr>"
hudakz 10:b47c7921346f 177 "<pre>2017 ARMmbed</pre>"
hudakz 10:b47c7921346f 178 "</body>";
hudakz 0:68a0003c4cb8 179
hudakz 10:b47c7921346f 180 return httpContent;
hudakz 10:b47c7921346f 181 /*$on*/
hudakz 0:68a0003c4cb8 182 }
hudakz 0:68a0003c4cb8 183
hudakz 5:0ab8292e37da 184 /**
hudakz 5:0ab8292e37da 185 * @brief
hudakz 5:0ab8292e37da 186 * @note
hudakz 5:0ab8292e37da 187 * @param
hudakz 5:0ab8292e37da 188 * @retval
hudakz 5:0ab8292e37da 189 */
hudakz 10:b47c7921346f 190 void sendHTTP(TcpClient& client, string& header, string& content)
hudakz 10:b47c7921346f 191 {
hudakz 10:b47c7921346f 192 /*$off*/
hudakz 10:b47c7921346f 193 char content_length[5] = { };
hudakz 10:b47c7921346f 194
hudakz 10:b47c7921346f 195 header +=
hudakz 10:b47c7921346f 196 "\r\nContent-Type: text/html\r\n"
hudakz 10:b47c7921346f 197 "Content-Length: ";
hudakz 10:b47c7921346f 198 sprintf(content_length, "%d", content.length());
hudakz 10:b47c7921346f 199 header +=
hudakz 10:b47c7921346f 200 string(content_length) + "\r\n"
hudakz 10:b47c7921346f 201 "Pragma: no-cache\r\n"
hudakz 10:b47c7921346f 202 "Connection: About to close\r\n\r\n";
hudakz 10:b47c7921346f 203
hudakz 10:b47c7921346f 204 string webpage = header + content;
hudakz 10:b47c7921346f 205 client.write((uint8_t*)webpage.c_str(), webpage.length());
hudakz 10:b47c7921346f 206 /*$on*/
hudakz 10:b47c7921346f 207 }
hudakz 10:b47c7921346f 208
hudakz 10:b47c7921346f 209 /**
hudakz 10:b47c7921346f 210 * @brief
hudakz 10:b47c7921346f 211 * @note
hudakz 10:b47c7921346f 212 * @param
hudakz 10:b47c7921346f 213 * @retval
hudakz 10:b47c7921346f 214 */
hudakz 10:b47c7921346f 215 int main(void)
hudakz 10:b47c7921346f 216 {
hudakz 10:b47c7921346f 217 printf("Starting ...\r\n");
hudakz 10:b47c7921346f 218
hudakz 10:b47c7921346f 219 // IP address must be unique and compatible with your network.
hudakz 10:b47c7921346f 220 //net->set_network(IP, NETMASK, GATEWAY); // include this for using static IP address
hudakz 10:b47c7921346f 221 net.connect();
hudakz 10:b47c7921346f 222
hudakz 10:b47c7921346f 223 // Show the network address
hudakz 10:b47c7921346f 224 const char* ip = net.get_ip_address();
hudakz 10:b47c7921346f 225 const char* netmask = net.get_netmask();
hudakz 10:b47c7921346f 226 const char* gateway = net.get_gateway();
hudakz 10:b47c7921346f 227
hudakz 10:b47c7921346f 228 printf("IP address: %s\r\n", ip ? ip : "None");
hudakz 10:b47c7921346f 229 printf("Netmask: %s\r\n", netmask ? netmask : "None");
hudakz 10:b47c7921346f 230 printf("Gateway: %s\r\n\r\n", gateway ? gateway : "None");
hudakz 10:b47c7921346f 231 printf("------------------------------------------------------\r\n");
hudakz 10:b47c7921346f 232 printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n\r\n", net.get_ip_address(), PASSWORD.c_str());
hudakz 10:b47c7921346f 233 printf("------------------------------------------------------\r\n");
hudakz 10:b47c7921346f 234
hudakz 10:b47c7921346f 235 /* Open the server on ethernet stack */
hudakz 10:b47c7921346f 236 server.open(&net);
hudakz 10:b47c7921346f 237
hudakz 10:b47c7921346f 238 /* Bind the HTTP port (TCP 80) to the server */
hudakz 10:b47c7921346f 239 server.bind(PORT);
hudakz 10:b47c7921346f 240
hudakz 10:b47c7921346f 241 /* Can handle 5 simultaneous connections */
hudakz 10:b47c7921346f 242 server.listen(5);
hudakz 10:b47c7921346f 243
hudakz 10:b47c7921346f 244 while (1) {
hudakz 10:b47c7921346f 245 client = server.accept();
hudakz 10:b47c7921346f 246
hudakz 10:b47c7921346f 247 if (client) {
hudakz 10:b47c7921346f 248 size_t size = client->available();
hudakz 10:b47c7921346f 249
hudakz 10:b47c7921346f 250 if (size > 0) {
hudakz 5:0ab8292e37da 251 uint8_t* buf = (uint8_t*)malloc(size);
hudakz 10:b47c7921346f 252 size = client->read(buf, size);
hudakz 10:b47c7921346f 253
hudakz 5:0ab8292e37da 254 string received((char*)buf);
hudakz 0:68a0003c4cb8 255 free(buf);
hudakz 10:b47c7921346f 256
hudakz 10:b47c7921346f 257 if (received.substr(0, 3) != "GET") {
hudakz 10:b47c7921346f 258 httpHeader = "HTTP/1.0 200 OK";
hudakz 0:68a0003c4cb8 259 httpContent = "<h1>200 OK</h1>";
hudakz 10:b47c7921346f 260 sendHTTP(*client, httpHeader, httpContent);
hudakz 10:b47c7921346f 261 client->close();
hudakz 0:68a0003c4cb8 262 continue;
hudakz 0:68a0003c4cb8 263 }
hudakz 0:68a0003c4cb8 264
hudakz 10:b47c7921346f 265 if (received.substr(0, 6) == "GET / ") {
hudakz 10:b47c7921346f 266 httpHeader = "HTTP/1.0 200 OK";
hudakz 10:b47c7921346f 267 httpContent = "<p>Usage: http://host_or_ip/password</p>\r\n";
hudakz 10:b47c7921346f 268 sendHTTP(*client, httpHeader, httpContent);
hudakz 10:b47c7921346f 269 client->close();
hudakz 0:68a0003c4cb8 270 continue;
hudakz 0:68a0003c4cb8 271 }
hudakz 0:68a0003c4cb8 272
hudakz 10:b47c7921346f 273 int cmd = analyseURL(received);
hudakz 10:b47c7921346f 274
hudakz 10:b47c7921346f 275 switch (cmd) {
hudakz 10:b47c7921346f 276 case -3:
hudakz 10:b47c7921346f 277 // update webpage
hudakz 10:b47c7921346f 278 httpHeader = "HTTP/1.0 200 OK";
hudakz 10:b47c7921346f 279 sendHTTP(*client, httpHeader, showWebPage(output));
hudakz 10:b47c7921346f 280 break;
hudakz 10:b47c7921346f 281
hudakz 10:b47c7921346f 282 case -2:
hudakz 10:b47c7921346f 283 // redirect to the right base url
hudakz 10:b47c7921346f 284 httpHeader = "HTTP/1.0 301 Moved Permanently\r\nLocation: ";
hudakz 10:b47c7921346f 285 sendHTTP(*client, httpHeader, movedPermanently(1));
hudakz 10:b47c7921346f 286 break;
hudakz 0:68a0003c4cb8 287
hudakz 10:b47c7921346f 288 case -1:
hudakz 10:b47c7921346f 289 httpHeader = "HTTP/1.0 401 Unauthorized";
hudakz 10:b47c7921346f 290 httpContent = "<h1>401 Unauthorized</h1>";
hudakz 10:b47c7921346f 291 sendHTTP(*client, httpHeader, httpContent);
hudakz 10:b47c7921346f 292 break;
hudakz 0:68a0003c4cb8 293
hudakz 10:b47c7921346f 294 case 0:
hudakz 10:b47c7921346f 295 output = OFF; // output off
hudakz 10:b47c7921346f 296 httpHeader = "HTTP/1.0 200 OK";
hudakz 10:b47c7921346f 297 sendHTTP(*client, httpHeader, showWebPage(output));
hudakz 10:b47c7921346f 298 break;
hudakz 0:68a0003c4cb8 299
hudakz 10:b47c7921346f 300 case 1:
hudakz 10:b47c7921346f 301 output = ON; // output on
hudakz 10:b47c7921346f 302 httpHeader = "HTTP/1.0 200 OK";
hudakz 10:b47c7921346f 303 sendHTTP(*client, httpHeader, showWebPage(output));
hudakz 10:b47c7921346f 304 break;
hudakz 10:b47c7921346f 305 }
hudakz 0:68a0003c4cb8 306 }
hudakz 10:b47c7921346f 307 client->close();
hudakz 0:68a0003c4cb8 308 }
hudakz 0:68a0003c4cb8 309 }
hudakz 0:68a0003c4cb8 310 }