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:
Sat Sep 07 17:53:02 2019 +0000
Revision:
14:810ac368dd6e
Parent:
12:7c46dcf6f7e2
Child:
15:9beb9b99695d
Updated.

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 11:6c0b20227ca2 9 //#define DEBUG
hudakz 11:6c0b20227ca2 10
hudakz 14:810ac368dd6e 11 // Static IP address must be unique and compatible with your network.
hudakz 10:b47c7921346f 12 #define IP "192.168.1.35"
hudakz 10:b47c7921346f 13 #define GATEWAY "192.168.1.1"
hudakz 10:b47c7921346f 14 #define NETMASK "255.255.255.0"
hudakz 10:b47c7921346f 15 #define PORT 80
hudakz 0:68a0003c4cb8 16
hudakz 11:6c0b20227ca2 17 const uint8_t MAC[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x06 };
hudakz 11:6c0b20227ca2 18 UipEthernet net(MAC, D11, D12, D13, D10); // mosi, miso, sck, cs
hudakz 12:7c46dcf6f7e2 19 TcpServer server; // Ethernet server
hudakz 11:6c0b20227ca2 20 TcpClient* client;
hudakz 11:6c0b20227ca2 21 char receiveBuf[1024];
hudakz 10:b47c7921346f 22 const int OFF = 0;
hudakz 10:b47c7921346f 23 const int ON = 1;
hudakz 11:6c0b20227ca2 24 DigitalOut output(D3); // A digital output to be switched on/off
hudakz 11:6c0b20227ca2 25 float roomTemp = 21.8; // A temperature sensor output
hudakz 11:6c0b20227ca2 26 const string PASSWORD = "secret"; // Change as you like
hudakz 11:6c0b20227ca2 27 string httpHeader; // HTTP header
hudakz 11:6c0b20227ca2 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 11:6c0b20227ca2 205 client.send((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 12:7c46dcf6f7e2 219 //net.set_network(IP, NETMASK, GATEWAY); // include this for using static IP address
hudakz 14:810ac368dd6e 220 if (net.connect(30) != 0) { // 'connect' timeout in seconds (defaults to 60 sec)
hudakz 14:810ac368dd6e 221 printf("Unable to connet.\r\n");
hudakz 14:810ac368dd6e 222 return -1;
hudakz 14:810ac368dd6e 223 }
hudakz 10:b47c7921346f 224
hudakz 10:b47c7921346f 225 // Show the network address
hudakz 10:b47c7921346f 226 const char* ip = net.get_ip_address();
hudakz 10:b47c7921346f 227 const char* netmask = net.get_netmask();
hudakz 10:b47c7921346f 228 const char* gateway = net.get_gateway();
hudakz 10:b47c7921346f 229
hudakz 10:b47c7921346f 230 printf("IP address: %s\r\n", ip ? ip : "None");
hudakz 10:b47c7921346f 231 printf("Netmask: %s\r\n", netmask ? netmask : "None");
hudakz 10:b47c7921346f 232 printf("Gateway: %s\r\n\r\n", gateway ? gateway : "None");
hudakz 14:810ac368dd6e 233 printf("------------------------------------------------------------------\r\n");
hudakz 14:810ac368dd6e 234 printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n", ip, PASSWORD.c_str());
hudakz 14:810ac368dd6e 235 printf("------------------------------------------------------------------\r\n");
hudakz 10:b47c7921346f 236
hudakz 10:b47c7921346f 237 /* Open the server on ethernet stack */
hudakz 10:b47c7921346f 238 server.open(&net);
hudakz 10:b47c7921346f 239
hudakz 10:b47c7921346f 240 /* Bind the HTTP port (TCP 80) to the server */
hudakz 10:b47c7921346f 241 server.bind(PORT);
hudakz 10:b47c7921346f 242
hudakz 14:810ac368dd6e 243 /* Can handle 4 simultaneous connections */
hudakz 14:810ac368dd6e 244 server.listen(4);
hudakz 10:b47c7921346f 245
hudakz 11:6c0b20227ca2 246 while (true) {
hudakz 10:b47c7921346f 247 client = server.accept();
hudakz 10:b47c7921346f 248
hudakz 10:b47c7921346f 249 if (client) {
hudakz 11:6c0b20227ca2 250 client->recv((uint8_t*)receiveBuf, client->available());
hudakz 11:6c0b20227ca2 251 #ifdef DEBUG
hudakz 11:6c0b20227ca2 252 printf("Client with IP address %s connected.\r\n\r\n", client->getpeername());
hudakz 11:6c0b20227ca2 253 printf("Data received:\r\n%s\n\r", receiveBuf);
hudakz 11:6c0b20227ca2 254 #endif
hudakz 11:6c0b20227ca2 255 string received(receiveBuf);
hudakz 10:b47c7921346f 256
hudakz 11:6c0b20227ca2 257 if (received.substr(0, 3) != "GET") {
hudakz 11:6c0b20227ca2 258 httpHeader = "HTTP/1.0 200 OK";
hudakz 11:6c0b20227ca2 259 httpContent = "<h1>200 OK</h1>";
hudakz 11:6c0b20227ca2 260 sendHTTP(*client, httpHeader, httpContent);
hudakz 11:6c0b20227ca2 261 client->close();
hudakz 11:6c0b20227ca2 262 continue;
hudakz 11:6c0b20227ca2 263 }
hudakz 0:68a0003c4cb8 264
hudakz 11:6c0b20227ca2 265 if (received.substr(0, 6) == "GET / ") {
hudakz 11:6c0b20227ca2 266 httpHeader = "HTTP/1.0 200 OK";
hudakz 11:6c0b20227ca2 267 httpContent = "<p>Usage: http://host_or_ip/password</p>\r\n";
hudakz 11:6c0b20227ca2 268 sendHTTP(*client, httpHeader, httpContent);
hudakz 11:6c0b20227ca2 269 client->close();
hudakz 11:6c0b20227ca2 270 continue;
hudakz 11:6c0b20227ca2 271 }
hudakz 0:68a0003c4cb8 272
hudakz 11:6c0b20227ca2 273 int cmd = analyseURL(received);
hudakz 10:b47c7921346f 274
hudakz 11:6c0b20227ca2 275 switch (cmd) {
hudakz 11:6c0b20227ca2 276 case -3:
hudakz 11:6c0b20227ca2 277 // update webpage
hudakz 11:6c0b20227ca2 278 httpHeader = "HTTP/1.0 200 OK";
hudakz 11:6c0b20227ca2 279 sendHTTP(*client, httpHeader, showWebPage(output));
hudakz 11:6c0b20227ca2 280 break;
hudakz 10:b47c7921346f 281
hudakz 11:6c0b20227ca2 282 case -2:
hudakz 11:6c0b20227ca2 283 // redirect to the right base url
hudakz 11:6c0b20227ca2 284 httpHeader = "HTTP/1.0 301 Moved Permanently\r\nLocation: ";
hudakz 11:6c0b20227ca2 285 sendHTTP(*client, httpHeader, movedPermanently(1));
hudakz 11:6c0b20227ca2 286 break;
hudakz 0:68a0003c4cb8 287
hudakz 11:6c0b20227ca2 288 case -1:
hudakz 11:6c0b20227ca2 289 httpHeader = "HTTP/1.0 401 Unauthorized";
hudakz 11:6c0b20227ca2 290 httpContent = "<h1>401 Unauthorized</h1>";
hudakz 11:6c0b20227ca2 291 sendHTTP(*client, httpHeader, httpContent);
hudakz 11:6c0b20227ca2 292 break;
hudakz 0:68a0003c4cb8 293
hudakz 11:6c0b20227ca2 294 case 0:
hudakz 11:6c0b20227ca2 295 output = OFF; // output off
hudakz 11:6c0b20227ca2 296 httpHeader = "HTTP/1.0 200 OK";
hudakz 11:6c0b20227ca2 297 sendHTTP(*client, httpHeader, showWebPage(output));
hudakz 11:6c0b20227ca2 298 break;
hudakz 0:68a0003c4cb8 299
hudakz 11:6c0b20227ca2 300 case 1:
hudakz 11:6c0b20227ca2 301 output = ON; // output on
hudakz 11:6c0b20227ca2 302 httpHeader = "HTTP/1.0 200 OK";
hudakz 11:6c0b20227ca2 303 sendHTTP(*client, httpHeader, showWebPage(output));
hudakz 11:6c0b20227ca2 304 break;
hudakz 0:68a0003c4cb8 305 }
hudakz 11:6c0b20227ca2 306
hudakz 10:b47c7921346f 307 client->close();
hudakz 0:68a0003c4cb8 308 }
hudakz 0:68a0003c4cb8 309 }
hudakz 0:68a0003c4cb8 310 }