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 Jun 30 20:07:32 2017 +0000
Revision:
8:3bd85b731cca
Parent:
7:f5e11393836d
Child:
9:6f63abd61de8
Updated.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 7:f5e11393836d 1 /*
hudakz 5:0ab8292e37da 2 * In this project LED1 on the mbed board is switched on/off using a web browser.
hudakz 5:0ab8292e37da 3 * However, you can easily modify the project to remotely switch on/off any external device.
hudakz 5:0ab8292e37da 4 * The HTTP server is built from an mbed board and an ENC28J60 board.
hudakz 5:0ab8292e37da 5 * ENC28J60 is driven by the UIPEthernet library <https://github.com/ntruchsess/arduino_uip>.
hudakz 4:d34811deedab 6 * The example is based on the Tuxgraphics Web Switch <http://www.tuxgraphics.org/>.
hudakz 0:68a0003c4cb8 7 */
hudakz 7:f5e11393836d 8
hudakz 7:f5e11393836d 9 //#define TARGET_STM32F103C8T6 1 // uncomment this line when using STM32F103C8T6 boards!
hudakz 6:b38a3b476a45 10
hudakz 6:b38a3b476a45 11 #if defined(TARGET_STM32F103C8T6)
hudakz 7:f5e11393836d 12 #include "stm32f103c8t6.h"
hudakz 7:f5e11393836d 13 #define LED_PIN PC_13
hudakz 7:f5e11393836d 14 const int OFF = 1;
hudakz 7:f5e11393836d 15 const int ON = 0;
hudakz 6:b38a3b476a45 16 #else
hudakz 7:f5e11393836d 17 #define LED_PIN LED1
hudakz 7:f5e11393836d 18 const int OFF = 0;
hudakz 7:f5e11393836d 19 const int ON = 1;
hudakz 6:b38a3b476a45 20 #endif
hudakz 6:b38a3b476a45 21
hudakz 6:b38a3b476a45 22 #include "mbed.h"
hudakz 6:b38a3b476a45 23 #include "UIPEthernet.h"
hudakz 6:b38a3b476a45 24 #include "UIPServer.h"
hudakz 6:b38a3b476a45 25 #include "UIPClient.h"
hudakz 6:b38a3b476a45 26 #include "string"
hudakz 0:68a0003c4cb8 27
hudakz 5:0ab8292e37da 28 using namespace std;
hudakz 0:68a0003c4cb8 29
hudakz 6:b38a3b476a45 30 Serial pc(USBTX, USBRX);
hudakz 6:b38a3b476a45 31
hudakz 8:3bd85b731cca 32 #define DHCP 1 // if you'd like to use static IP address comment out this line
hudakz 6:b38a3b476a45 33
hudakz 8:3bd85b731cca 34 // uIPEthernet is the name of a global instance of UIPEthernet.
hudakz 0:68a0003c4cb8 35 // Do not change the name! It is used within the UIPEthernet library.
hudakz 0:68a0003c4cb8 36 #if defined(TARGET_LPC1768)
hudakz 8:3bd85b731cca 37 UIPEthernet uIPEthernet(p11, p12, p13, p8); // mosi, miso, sck, cs
hudakz 0:68a0003c4cb8 38 #elif defined(TARGET_LPC1114)
hudakz 8:3bd85b731cca 39 UIPEthernet uIPEthernet(dp2, dp1, dp6, dp25); // mosi, miso, sck, cs
hudakz 0:68a0003c4cb8 40 #elif defined(TARGET_LPC11U68)
hudakz 8:3bd85b731cca 41 UIPEthernet uIPEthernet(P0_9, P0_8, P1_29, P0_2); // mosi, miso, sck, cs
hudakz 6:b38a3b476a45 42 #elif defined(TARGET_NUCLEO_F103RB) || defined(TARGET_NUCLEO_L152RE) || defined(TARGET_NUCLEO_F030R8) \
hudakz 6:b38a3b476a45 43 || defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F302R8) || defined(TARGET_NUCLEO_L053R8) \
hudakz 6:b38a3b476a45 44 || defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F334R8) || defined(TARGET_NUCLEO_F072RB) \
hudakz 6:b38a3b476a45 45 || defined(TARGET_NUCLEO_F091RC) || defined(TARGET_NUCLEO_F303RE) || defined(TARGET_NUCLEO_F070RB)
hudakz 8:3bd85b731cca 46 //UIPEthernet uIPEthernet(D4, D5, D3, D2); // mosi, miso, sck, cs
hudakz 8:3bd85b731cca 47 //UIPEthernet uIPEthernet(D11, D12, D13, D10); // mosi, miso, sck, cs
hudakz 8:3bd85b731cca 48 UIPEthernet uIPEthernet(PA_7, PA_6, PA_5, PB_6); // mosi, miso, sck, cs
hudakz 4:d34811deedab 49
hudakz 5:0ab8292e37da 50 // If your board/plaform is not present yet then uncomment
hudakz 5:0ab8292e37da 51 // the following two lines and replace TARGET_YOUR_BOARD as appropriate.
hudakz 4:d34811deedab 52
hudakz 5:0ab8292e37da 53 //#elif defined(TARGET_YOUR_BOARD)
hudakz 8:3bd85b731cca 54 //UIPEthernet uIPEthernet(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS); // mosi, miso, sck, cs
hudakz 4:d34811deedab 55
hudakz 0:68a0003c4cb8 56 #endif
hudakz 0:68a0003c4cb8 57
hudakz 4:d34811deedab 58 // Note:
hudakz 4:d34811deedab 59 // If it happends that any of the SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS pins collide with LED1 pin
hudakz 5:0ab8292e37da 60 // then either use different SPI port (if available on the board) and change the pin names
hudakz 8:3bd85b731cca 61 // in the constructor uIPEthernet(...) accordingly or instead of using LED1 pin, select
hudakz 5:0ab8292e37da 62 // a free pin (not used by SPI port) and connect to it an external LED which is connected
hudakz 5:0ab8292e37da 63 // to a 220 Ohm resitor that is connected to the groud.
hudakz 4:d34811deedab 64 // In the second case remember to replace LED1 in sw(LED1) constructor (see below).
hudakz 5:0ab8292e37da 65 // MAC number must be unique within the connected network. Modify as appropriate.
hudakz 5:0ab8292e37da 66 const uint8_t MY_MAC[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x06 };
hudakz 5:0ab8292e37da 67 const uint16_t MY_PORT = 80; // for HTTP connection
hudakz 5:0ab8292e37da 68 EthernetServer myServer = EthernetServer(MY_PORT);
hudakz 5:0ab8292e37da 69
hudakz 0:68a0003c4cb8 70 // In this example we are turning on/off LED1.
hudakz 7:f5e11393836d 71 DigitalOut sw(LED_PIN); // Change LED_PIN to a pin of your choice.
hudakz 7:f5e11393836d 72 //DigitalOut sw(D9); // Change LED_PIN to a pin of your choice.
hudakz 7:f5e11393836d 73 float roomTemp = 21.8; // A temperature sensor output
hudakz 0:68a0003c4cb8 74
hudakz 5:0ab8292e37da 75 // However, make sure that it does not collide with any of the SPI pins
hudakz 8:3bd85b731cca 76 // already used in the uIPEthernet(...) constructor above!
hudakz 5:0ab8292e37da 77 const string PASSWORD = "secret"; // change as you like
hudakz 5:0ab8292e37da 78 const string HTTP_OK = "HTTP/1.0 200 OK";
hudakz 5:0ab8292e37da 79 const string MOVED_PERM = "HTTP/1.0 301 Moved Permanently\r\nLocation: ";
hudakz 5:0ab8292e37da 80 const string UNAUTHORIZED = "HTTP/1.0 401 Unauthorized";
hudakz 5:0ab8292e37da 81 string httpHeader; // HTTP header
hudakz 5:0ab8292e37da 82 string httpContent; // HTTP content
hudakz 0:68a0003c4cb8 83
hudakz 7:f5e11393836d 84 /**
hudakz 7:f5e11393836d 85 * @brief Analyses the received URL
hudakz 7:f5e11393836d 86 * @note The string passed to this function will look like this:
hudakz 7:f5e11393836d 87 * GET /password HTTP/1.....
hudakz 7:f5e11393836d 88 * GET /password/ HTTP/1.....
hudakz 7:f5e11393836d 89 * GET /password/?sw=1 HTTP/1.....
hudakz 7:f5e11393836d 90 * GET /password/?sw=0 HTTP/1.....
hudakz 7:f5e11393836d 91 * @param url URL string
hudakz 7:f5e11393836d 92 * @retval -1 invalid password
hudakz 7:f5e11393836d 93 * -2 no command given but password valid
hudakz 7:f5e11393836d 94 * -3 just refresh page
hudakz 7:f5e11393836d 95 * 0 switch off
hudakz 7:f5e11393836d 96 * 1 switch on
hudakz 7:f5e11393836d 97 */
hudakz 7:f5e11393836d 98 int8_t analyseURL(string& url) {
hudakz 7:f5e11393836d 99 if(url.substr(5, PASSWORD.size()) != PASSWORD)
hudakz 0:68a0003c4cb8 100 return(-1);
hudakz 0:68a0003c4cb8 101
hudakz 0:68a0003c4cb8 102 uint8_t pos = 5 + PASSWORD.size();
hudakz 0:68a0003c4cb8 103
hudakz 7:f5e11393836d 104 if(url.substr(pos, 1) == " ")
hudakz 0:68a0003c4cb8 105 return(-2);
hudakz 0:68a0003c4cb8 106
hudakz 7:f5e11393836d 107 if(url.substr(pos++, 1) != "/")
hudakz 0:68a0003c4cb8 108 return(-1);
hudakz 0:68a0003c4cb8 109
hudakz 7:f5e11393836d 110 string cmd(url.substr(pos, 5));
hudakz 0:68a0003c4cb8 111
hudakz 0:68a0003c4cb8 112 if(cmd == "?sw=0")
hudakz 6:b38a3b476a45 113 return(OFF);
hudakz 0:68a0003c4cb8 114
hudakz 0:68a0003c4cb8 115 if(cmd == "?sw=1")
hudakz 6:b38a3b476a45 116 return(ON);
hudakz 0:68a0003c4cb8 117
hudakz 0:68a0003c4cb8 118 return(-3);
hudakz 0:68a0003c4cb8 119 }
hudakz 0:68a0003c4cb8 120
hudakz 5:0ab8292e37da 121 /**
hudakz 5:0ab8292e37da 122 * @brief
hudakz 5:0ab8292e37da 123 * @note
hudakz 5:0ab8292e37da 124 * @param
hudakz 5:0ab8292e37da 125 * @retval
hudakz 5:0ab8292e37da 126 */
hudakz 7:f5e11393836d 127 string& movedPermanently(uint8_t flag)
hudakz 7:f5e11393836d 128 {
hudakz 0:68a0003c4cb8 129 if(flag == 1)
hudakz 5:0ab8292e37da 130 httpContent = "/" + PASSWORD + "/";
hudakz 0:68a0003c4cb8 131 else
hudakz 0:68a0003c4cb8 132 httpContent = "";
hudakz 0:68a0003c4cb8 133
hudakz 0:68a0003c4cb8 134 httpContent += "<h1>301 Moved Permanently</h1>\r\n";
hudakz 0:68a0003c4cb8 135
hudakz 5:0ab8292e37da 136 return(httpContent);
hudakz 0:68a0003c4cb8 137 }
hudakz 0:68a0003c4cb8 138
hudakz 5:0ab8292e37da 139 /**
hudakz 5:0ab8292e37da 140 * @brief
hudakz 5:0ab8292e37da 141 * @note
hudakz 5:0ab8292e37da 142 * @param
hudakz 5:0ab8292e37da 143 * @retval
hudakz 5:0ab8292e37da 144 */
hudakz 6:b38a3b476a45 145 string& showWebPage(uint8_t status) {
hudakz 7:f5e11393836d 146 char roomTempStr[5];
hudakz 7:f5e11393836d 147
hudakz 7:f5e11393836d 148 //roomTemp = ds1820.read();
hudakz 7:f5e11393836d 149 sprintf(roomTempStr, "%3.1f", roomTemp);
hudakz 7:f5e11393836d 150
hudakz 8:3bd85b731cca 151 httpContent = "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>";
hudakz 7:f5e11393836d 152 httpContent += "<pre>Temperature:\t" + string(roomTempStr) + "&deg;C\r\n</pre>";
hudakz 0:68a0003c4cb8 153
hudakz 6:b38a3b476a45 154 if(status == ON) {
hudakz 7:f5e11393836d 155 httpContent += "<pre>\r\nHeating:\t<font color=#FF0000>On </font>";
hudakz 7:f5e11393836d 156 httpContent += " <a href=\"./?sw=0\"><button>Turn off</button></a>\r\n";
hudakz 5:0ab8292e37da 157 }
hudakz 5:0ab8292e37da 158 else {
hudakz 7:f5e11393836d 159 httpContent += "<pre>\r\nHeating:\t<font color=#999999>Off</font>";
hudakz 7:f5e11393836d 160 httpContent += " <a href=\"./?sw=1\"><button>Turn on</button></a>\r\n";
hudakz 0:68a0003c4cb8 161 }
hudakz 0:68a0003c4cb8 162
hudakz 0:68a0003c4cb8 163 httpContent += "</pre>\r\n";
hudakz 0:68a0003c4cb8 164 httpContent += "<hr>\r\n";
hudakz 7:f5e11393836d 165 httpContent += "<pre>2017 ARMmbed</pre>";
hudakz 0:68a0003c4cb8 166 return httpContent;
hudakz 0:68a0003c4cb8 167 }
hudakz 0:68a0003c4cb8 168
hudakz 5:0ab8292e37da 169 /**
hudakz 5:0ab8292e37da 170 * @brief
hudakz 5:0ab8292e37da 171 * @note
hudakz 5:0ab8292e37da 172 * @param
hudakz 5:0ab8292e37da 173 * @retval
hudakz 5:0ab8292e37da 174 */
hudakz 7:f5e11393836d 175 void sendHTTP(EthernetClient& client, string& header, string& content)
hudakz 7:f5e11393836d 176 {
hudakz 5:0ab8292e37da 177 char content_length[5] = { };
hudakz 0:68a0003c4cb8 178
hudakz 2:76f339a1ba9b 179 header += "\r\nContent-Type: text/html\r\n";
hudakz 0:68a0003c4cb8 180 header += "Content-Length: ";
hudakz 0:68a0003c4cb8 181 sprintf(content_length, "%d", content.length());
hudakz 0:68a0003c4cb8 182 header += string(content_length) + "\r\n";
hudakz 0:68a0003c4cb8 183 header += "Pragma: no-cache\r\n";
hudakz 0:68a0003c4cb8 184 header += "Connection: About to close\r\n";
hudakz 0:68a0003c4cb8 185 header += "\r\n";
hudakz 5:0ab8292e37da 186
hudakz 5:0ab8292e37da 187 string webpage = header + content;
hudakz 5:0ab8292e37da 188 client.write((uint8_t*)webpage.c_str(), webpage.length());
hudakz 0:68a0003c4cb8 189 }
hudakz 0:68a0003c4cb8 190
hudakz 5:0ab8292e37da 191 /**
hudakz 5:0ab8292e37da 192 * @brief
hudakz 5:0ab8292e37da 193 * @note
hudakz 5:0ab8292e37da 194 * @param
hudakz 5:0ab8292e37da 195 * @retval
hudakz 5:0ab8292e37da 196 */
hudakz 7:f5e11393836d 197 int main(void)
hudakz 7:f5e11393836d 198 {
hudakz 7:f5e11393836d 199 #if defined(TARGET_STM32F103C8T6)
hudakz 7:f5e11393836d 200 confSysClock(); //Configure system clock (72MHz HSE clock, 48MHz USB clock)
hudakz 7:f5e11393836d 201 #endif
hudakz 6:b38a3b476a45 202 #if defined(DHCP)
hudakz 6:b38a3b476a45 203 pc.printf("Searching for DHCP server..\r\n");
hudakz 8:3bd85b731cca 204 if(uIPEthernet.begin(MY_MAC) != 1) {
hudakz 6:b38a3b476a45 205 pc.printf("No DHCP server found.\r\n");
hudakz 6:b38a3b476a45 206 pc.printf("Exiting application.\r\n");
hudakz 6:b38a3b476a45 207 return 0;
hudakz 6:b38a3b476a45 208 }
hudakz 6:b38a3b476a45 209 pc.printf("DHCP server found.\r\n");
hudakz 6:b38a3b476a45 210 #else
hudakz 6:b38a3b476a45 211 // IP address must be unique and compatible with your network.
hudakz 6:b38a3b476a45 212 const IPAddress MY_IP(192, 168, 1, 181); // Change as appropriate.
hudakz 8:3bd85b731cca 213 uIPEthernet.begin(MY_MAC, MY_IP);
hudakz 6:b38a3b476a45 214 #endif
hudakz 8:3bd85b731cca 215 IPAddress localIP = uIPEthernet.localIP();
hudakz 8:3bd85b731cca 216 pc.printf("Type %s secret/ into your web browser and hit ENTER\r\n", localIP.toString());
hudakz 8:3bd85b731cca 217 myServer.begin();
hudakz 0:68a0003c4cb8 218 while(1) {
hudakz 5:0ab8292e37da 219 EthernetClient client = myServer.available();
hudakz 5:0ab8292e37da 220 if(client) {
hudakz 5:0ab8292e37da 221 size_t size = client.available();
hudakz 0:68a0003c4cb8 222 if(size > 0) {
hudakz 5:0ab8292e37da 223 uint8_t* buf = (uint8_t*)malloc(size);
hudakz 0:68a0003c4cb8 224 size = client.read(buf, size);
hudakz 5:0ab8292e37da 225 string received((char*)buf);
hudakz 0:68a0003c4cb8 226 free(buf);
hudakz 7:f5e11393836d 227
hudakz 0:68a0003c4cb8 228 if(received.substr(0, 3) != "GET") {
hudakz 0:68a0003c4cb8 229 httpHeader = HTTP_OK;
hudakz 0:68a0003c4cb8 230 httpContent = "<h1>200 OK</h1>";
hudakz 6:b38a3b476a45 231 sendHTTP(client, httpHeader, httpContent);
hudakz 0:68a0003c4cb8 232 continue;
hudakz 0:68a0003c4cb8 233 }
hudakz 0:68a0003c4cb8 234
hudakz 0:68a0003c4cb8 235 if(received.substr(0, 6) == "GET / ") {
hudakz 0:68a0003c4cb8 236 httpHeader = HTTP_OK;
hudakz 0:68a0003c4cb8 237 httpContent = "<p>Usage: http://host_or_ip/password</p>\r\n";
hudakz 6:b38a3b476a45 238 sendHTTP(client, httpHeader, httpContent);
hudakz 0:68a0003c4cb8 239 continue;
hudakz 0:68a0003c4cb8 240 }
hudakz 0:68a0003c4cb8 241
hudakz 6:b38a3b476a45 242 int cmd = analyseURL(received);
hudakz 0:68a0003c4cb8 243
hudakz 0:68a0003c4cb8 244 if(cmd == -2) {
hudakz 0:68a0003c4cb8 245 // redirect to the right base url
hudakz 0:68a0003c4cb8 246 httpHeader = MOVED_PERM;
hudakz 6:b38a3b476a45 247 sendHTTP(client, httpHeader, movedPermanently(1));
hudakz 0:68a0003c4cb8 248 continue;
hudakz 0:68a0003c4cb8 249 }
hudakz 0:68a0003c4cb8 250
hudakz 0:68a0003c4cb8 251 if(cmd == -1) {
hudakz 0:68a0003c4cb8 252 httpHeader = UNAUTHORIZED;
hudakz 0:68a0003c4cb8 253 httpContent = "<h1>401 Unauthorized</h1>";
hudakz 6:b38a3b476a45 254 sendHTTP(client, httpHeader, httpContent);
hudakz 0:68a0003c4cb8 255 continue;
hudakz 0:68a0003c4cb8 256 }
hudakz 0:68a0003c4cb8 257
hudakz 6:b38a3b476a45 258 if(cmd == ON) {
hudakz 6:b38a3b476a45 259 sw = ON; // turn the switch on
hudakz 0:68a0003c4cb8 260 }
hudakz 0:68a0003c4cb8 261
hudakz 6:b38a3b476a45 262 if(cmd == OFF) {
hudakz 6:b38a3b476a45 263 sw = OFF; // turn the switch off
hudakz 0:68a0003c4cb8 264 }
hudakz 0:68a0003c4cb8 265
hudakz 0:68a0003c4cb8 266 httpHeader = HTTP_OK;
hudakz 6:b38a3b476a45 267 sendHTTP(client, httpHeader, showWebPage(sw));
hudakz 0:68a0003c4cb8 268 }
hudakz 0:68a0003c4cb8 269 }
hudakz 0:68a0003c4cb8 270 }
hudakz 0:68a0003c4cb8 271 }