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:
Sun Aug 28 11:47:29 2016 +0000
Revision:
6:b38a3b476a45
Parent:
5:0ab8292e37da
Child:
7:f5e11393836d
Wrong SPI pin assignment fixed. Added support for STM32F103C8T6 boards.

Who changed what in which revision?

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