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