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

Dependencies:   W5500Interface mbed

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. A WIZ550io module or W5500 Network-Shielld is used to assure connection between the mbed module and the Ethernet network (Internet).

Needed parts:

  • mbed board
  • WIZ550io module or W5500 Network-Shield
  • Wires
  • Web browser (Internet Explorer, Safari, Firefox, Chrome ...) running on Windows, Mac, Linux, iPhone or Android device.
/media/uploads/hudakz/webswitch_wiz.jpg/media/uploads/hudakz/webswitch_mobile01.jpg

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

NOTE:

Files at this revision

API Documentation at this revision

Comitter:
hudakz
Date:
Sun Mar 15 22:47:37 2015 +0000
Child:
1:343d3c7e13b8
Commit message:
Web Switch to turn on/off LED1 using the WIZ550io board. Compile, download, run and type 192.168.1.181/secret/ into your web browser.

Changed in this revision

W5500Interface.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/W5500Interface.lib	Sun Mar 15 22:47:37 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/teams/EthernetInterfaceW5500-makers/code/W5500Interface/#713b6d2aaefb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Mar 15 22:47:37 2015 +0000
@@ -0,0 +1,290 @@
+/* In this example LED1 on the mbed board is switched on/off using a web browser.
+ * The HTTP server is built from an mbed board and a WIZ550io board.
+ * The example is based on the Tuxgraphics Web Switch <http://www.tuxgraphics.org/>.
+ */
+#include "mbed.h"
+#include "EthernetInterface.h"
+#include <string>
+
+using namespace     std;
+
+Serial              serial(USBTX, USBRX);
+
+// Do not change the name! It is used within the UIPEthernet library.
+#if defined(TARGET_LPC1768)
+SPI                 spi(p11, p12, p13);     // MOSI, MISO, SCK
+EthernetInterface   eth(&spi, p8, p14);     // SPI, CS, RESET
+#elif defined(TARGET_FRDM_KL25Z)
+SPI                 spi(PTD2, PTD3, PTD1);  // MOSI, MISO, SCK
+EthernetInterface   eth(&spi, PTD0, PTD5);  // SPI, CS, RESET
+#elif defined(TARGET_FRDM_KL46Z)
+SPI                 spi(PTD2, PTD3, PTD1);  // MOSI, MISO, SCK
+EthernetInterface   eth(&spi, PTD0, PTD5);  // SPI, CS, RESET
+#elif defined(TARGET_LPC11U24)
+SPI                 spi(P16, P15, P13);     // MOSI, MISO, SCK
+EthernetInterface   eth(&spi, P17, P18);    // SPI, CS, RESET
+#elif defined(TARGET_NUCLEO_F030R8)
+SPI                 spi(PB_5, PB_4, PB_3);  // MOSI, MISO, SCK
+EthernetInterface   eth(&spi, PB_10, PA_8); // SPI, CS, RESET
+#elif defined(TARGET_NUCLEO_F072RB)
+SPI                 spi(PB_5, PB_4, PB_3);  // MOSI, MISO, SCK
+EthernetInterface   eth(&spi, PB_10, PA_8); // SPI, CS, RESET
+#elif defined(TARGET_NUCLEO_F103RB)
+SPI                 spi(PB_5, PB_4, PB_3);  // MOSI, MISO, SCK
+EthernetInterface   eth(&spi, PB_10, PA_8); // SPI, CS, RESET
+#elif defined(TARGET_NUCLEO_F401RE)
+SPI                 spi(PB_5, PB_4, PB_3);  // MOSI, MISO, SCK
+EthernetInterface   eth(&spi, PB_10, PA_8); // SPI, CS, RESET
+#elif defined(TARGET_NUCLEO_F411RE)
+SPI                 spi(PB_5, PB_4, PB_3);  // MOSI, MISO, SCK
+EthernetInterface   eth(&spi, PB_10, PA_8); // SPI, CS, RESET
+
+// If your board/plaform is not present yet then uncomment
+// the following three lines and replace modify as appropriate.
+
+//#elif defined(TARGET_YOUR_BOARD)
+//SPI                 spi(SPI_MOSI, SPI_MISO, SPI_SCK);   // MOSI, MISO, SCK
+//EthernetInterface   eth(&spi, SPI_CS, RESET);           // SPI, CS, RESET
+#endif
+
+// Note:
+// If it happends that any of the SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS or RESET pins collide with LED1 pin
+// then either use different SPI port (if available on the board) and change the pin names
+// in the constructor spi(...) accordingly or instead of using LED1 pin, select
+// a free pin (not used by SPI port) and connect to it an external LED which is connected
+// to a 220 Ohm resitor that is connected to the groud.
+// In the second case remember to replace LED1 in sw(LED1) constructor (see below).
+// IP address must be also unique and compatible with your network. Change as appropriate.
+const char          MY_IP[] = "192.168.1.181";
+const char          MY_NETMASK[] = "255.255.255.0";
+const char          MY_GATEWAY[] = "192.168.1.1";
+int                 MY_PORT = 80;
+
+TCPSocketServer     server;
+TCPSocketConnection client;
+bool                serverIsListening = false;
+
+DigitalOut          sw(LED1);   // Change LED1 to a pin of your choice.
+                                // However, make sure that it does not collide with any of the SPI pins
+                                // already used in the UIPEthernet(...) constructor above!
+
+const string        PASSWORD = "secret";    // change as you like
+const string        HTTP_OK = "HTTP/1.0 200 OK";
+const string        MOVED_PERM = "HTTP/1.0 301 Moved Permanently\r\nLocation: ";
+const string        UNAUTHORIZED = "HTTP/1.0 401 Unauthorized";
+
+string              httpHeader;     // HTTP header
+string              httpContent;    // HTTP content
+
+// analyse the url given
+// return values: -1 invalid password
+//                -2 no command given but password valid
+//                -3 just refresh page
+//                 0 switch off
+//                 1 switch on
+//
+//                The string passed to this function will look like this:
+//                GET /password HTTP/1.....
+//                GET /password/ HTTP/1.....
+//                GET /password/?sw=1 HTTP/1.....
+
+//                GET /password/?sw=0 HTTP/1.....
+int8_t analyse_get_url(string& str) {
+    if(str.substr(5, PASSWORD.size()) != PASSWORD)
+        return(-1);
+
+    uint8_t pos = 5 + PASSWORD.size();
+
+    if(str.substr(pos, 1) == " ")
+        return(-2);
+
+    if(str.substr(pos, 1) != "/")
+        return(-1);
+
+    pos++;
+
+    string  cmd(str.substr(pos, 5));
+
+    if(cmd == "?sw=0")
+        return(0);
+
+    if(cmd == "?sw=1")
+        return(1);
+
+    return(-3);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+string& moved_perm(uint8_t flag) {
+    if(flag == 1)
+        httpContent = "/" + PASSWORD + "/";
+    else
+        httpContent = "";
+
+    httpContent += "<h1>301 Moved Permanently</h1>\r\n";
+
+    return(httpContent);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+string& view(uint8_t status) {
+    httpContent = "<h2>Web Switch</h2>\r\n";
+
+    if(status == 1) {
+        httpContent += "<pre>\r\n  <font color=#FF0000>ON</font>";
+        httpContent += " <a href=\"./?sw=0\">[switch off]</a>\r\n";
+    }
+    else {
+        httpContent += "<pre>\r\n  <font color=#00FF00>OFF</font>";
+        httpContent += " <a href=\"./?sw=1\">[switch on]</a>\r\n";
+    }
+
+    httpContent += "  <a href=\".\">[refresh status]</a>\r\n";
+    httpContent += "</pre>\r\n";
+    httpContent += "<hr>\r\n";
+    return httpContent;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void http_send(TCPSocketConnection& client, string& header, string& content) {
+    char    content_length[5] = { };
+
+    header += "\r\nContent-Type: text/html\r\n";
+    header += "Content-Length: ";
+    sprintf(content_length, "%d", content.length());
+    header += string(content_length) + "\r\n";
+    header += "Pragma: no-cache\r\n";
+    header += "Connection: About to close\r\n";
+    header += "\r\n";
+
+    string  webpage = header + content;
+    client.send (const_cast<char*>(webpage.c_str ()), webpage.length ());
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+int main(void) {
+    int     ret = eth.init(MY_IP, MY_NETMASK, MY_GATEWAY);
+
+    if(!ret) {
+        serial.printf("Initialized, MY_MAC: %s\n", eth.getMACAddress());
+        serial.printf
+            (
+                "Connected, MY_IP: %s, MY_NETMASK: %s, MY_GATEWAY: %s\n",
+                eth.getIPAddress(),
+                eth.getNetworkMask(),
+                eth.getGateway()
+            );
+    }
+    else {
+        serial.printf("Error eth.init() - ret = %d\n", ret);
+        return -1;
+    }
+
+    //setup tcp socket
+    if(server.bind(MY_PORT) < 0) {
+        serial.printf("TCP server bind failed.\n\r");
+        return -1;
+    }
+    else {
+        serial.printf("TCP server bind succeeded.\n\r");
+        serverIsListening = true;
+    }
+
+    if(server.listen(1) < 0) {
+        serial.printf("TCP server listen failed.\n\r");
+        return -1;
+    }
+    else {
+        serial.printf("TCP server is listening...\n\r");
+    }
+
+    while(serverIsListening) {
+        if(server.accept(client) >= 0) {
+            char    buf[1024] = { };
+            size_t  size = 0;
+            
+            serial.printf("Client connected!\n\rIP: %s\n\r", client.get_address());
+            
+            switch(client.receive(buf, 1023)) {
+            case 0:
+                serial.printf("Recieved buffer is empty.\n\r");
+                break;
+
+            case -1:
+                serial.printf("Failed to read data from client.\n\r");
+                break;
+
+            default:
+                size = strlen(buf);
+
+                string  received((char*)buf);
+
+                if(received.substr(0, 3) != "GET") {
+                    httpHeader = HTTP_OK;
+                    httpContent = "<h1>200 OK</h1>";
+                    http_send(client, httpHeader, httpContent);
+                    continue;
+                }
+
+                if(received.substr(0, 6) == "GET / ") {
+                    httpHeader = HTTP_OK;
+                    httpContent = "<p>Usage: http://host_or_ip/password</p>\r\n";
+                    http_send(client, httpHeader, httpContent);
+                    continue;
+                }
+
+                int cmd = analyse_get_url(received);
+
+                if(cmd == -2) {
+
+                    // redirect to the right base url
+                    httpHeader = MOVED_PERM;
+                    http_send(client, httpHeader, moved_perm(1));
+                    continue;
+                }
+
+                if(cmd == -1) {
+                    httpHeader = UNAUTHORIZED;
+                    httpContent = "<h1>401 Unauthorized</h1>";
+                    http_send(client, httpHeader, httpContent);
+                    continue;
+                }
+
+                if(cmd == 1) {
+                    sw = 1; // switch on
+                }
+
+                if(cmd == 0) {
+                    sw = 0; // switch off
+                }
+
+                httpHeader = HTTP_OK;
+                http_send(client, httpHeader, view(sw));
+            }
+
+            client.close();
+
+            serial.printf("Connection closed.\n\rTCP server is listening...\n\r");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Mar 15 22:47:37 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/7e07b6fb45cf
\ No newline at end of file