Tiny HTTP server controlling a DigitalOutput.

Turn LED1, or other digital output, on/off using a web browser.

In this example we create a HTTP server for the STM32F407VET6 black board that will serve a simple Web page to remotely turn LED1, or other digital output, on/off by using a web browser.

/media/uploads/hudakz/webswitch03.png/media/uploads/hudakz/webswitch_mobile01.jpg

Notice that DHCP is turned on by default. The IP address assigned to the WebSwitch server along with an instruction how to use it is printed to the connected PC's serial terminal window during program start up.
To use static IP address uncomment and adjust line #221 in main.cpp.

A DP83848 module is used as Ethernet interface.

/media/uploads/hudakz/dp83848_01.jpg

Wiring

DP83848 moduleSTM32F407VET6 board
VCC<=>+3.3V
GND<=>GND
MDIO<=>PA_2
MDC<=>PC_1
OSCIN<=>PA_1
CRS<=>PA_7
RX0<=>PC_4
RX1<=>PC_5
TX_EN<=>PB_11
TX0<=>PB_12
TX1<=>PB_13

Notice that because the RX_ER line is not used the DP83848 module doesn't have to be modified.

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

Revision:
6:55e13e19bec3
Parent:
5:92942d4f4ff6
Child:
7:482a6f018329
--- a/main.cpp	Sat May 18 11:18:59 2019 +0000
+++ b/main.cpp	Sat May 18 13:30:52 2019 +0000
@@ -3,37 +3,35 @@
 #include "TCPSocket.h"
 #include <stdio.h>
 #include <string>
- 
+
 using namespace     std;
- 
-#define IP         "192.168.1.181"
-#define GATEWAY    "192.168.1.1"
-#define NETMASK    "255.255.255.0"
-#define PORT        80
+
+#define IP      "192.168.1.181"
+#define GATEWAY "192.168.1.1"
+#define NETMASK "255.255.255.0"
+#define PORT    80
 
 Serial              pc(PC_6, PC_7);
 //Serial              pc(PA_9, PA_10);
-
 EthernetInterface*  net;
 
 TCPSocket           server;
 TCPSocket*          clientSocket;
 SocketAddress       clientAddress;
 char                receiveBuf[1024] = { };
- 
+
 const int           OFF = 1;
 const int           ON = 0;
- 
-DigitalOut          sw(PA_6);           // A switch
-float               roomTemp = 21.8;    // A temperature sensor output
- 
-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: ";
+
+DigitalOut          sw(PA_6);               // A switch
+float               roomTemp = 21.8;        // A temperature sensor output
+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
- 
+string              httpHeader;             // HTTP header
+string              httpContent;            // HTTP content
+
 /**
  * @brief   Analyses the received URL
  * @note    The string passed to this function will look like this:
@@ -48,61 +46,65 @@
  *          0 switch off
  *          1 switch on
  */
-int8_t analyseURL(string& url) {
-    if(url.length() < 5 + PASSWORD.size() + 1)
+int8_t analyseURL(string& url)
+{
+    if (url.length() < 5 + PASSWORD.size() + 1)
         return(-1);
-    
-    if(url.substr(5, PASSWORD.size()) != PASSWORD)
+
+    if (url.substr(5, PASSWORD.size()) != PASSWORD)
         return(-1);
- 
+
     uint8_t pos = 5 + PASSWORD.size();
-       
-    if(url.substr(pos, 1) != "/")
+
+    if (url.substr(pos, 1) != "/")
         return(-1);
 
-    if(url.substr(pos++, 1) == " ")
+    if (url.substr(pos++, 1) == " ")
         return(-2);
- 
+
     string  cmd(url.substr(pos, 5));
- 
-    if(cmd == "?sw=0")
+
+    if (cmd == "?sw=0")
         return(0);
- 
-    if(cmd == "?sw=1")
+
+    if (cmd == "?sw=1")
         return(1);
- 
+
     return(-3);
 }
- 
+
 /**
  * @brief
  * @note
  * @param
  * @retval
  */
-string& movedPermanently(uint8_t flag) {
-    if(flag == 1)
+string& movedPermanently(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& showWebPage(uint8_t status) {
-    char roomTempStr[5];
- 
+string& showWebPage(uint8_t status)
+{
+    /*$off*/
+    char    roomTempStr[5];
+
     //roomTemp = ds1820.read();
     sprintf(roomTempStr, "%3.1f", roomTemp);
- 
+
     // CSS toggle switch
     httpContent  = \
         "<head>"
@@ -151,14 +153,14 @@
         "}" \
         "</style>" \
         "</head>" \
-        
+
         // Web page
         "<body>"
         "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>" \
         "<pre>Temperature:\t" + string(roomTempStr) + "&deg;C</pre>" \
         "<pre>Heating:\t";
- 
-    if(status == ON) {
+
+    if (status == ON) {
         httpContent += \
             "<a href=\"./?sw=0\" class=\"switch\"> " \
             "<input type=\"checkbox\" checked>";
@@ -167,27 +169,30 @@
         httpContent += \
             "<a href=\"./?sw=1\" class=\"switch\"> " \
             "<input type=\"checkbox\">";
-   }
- 
-   httpContent +=  \
+    }
+
+    httpContent +=  \
         "<div class=\"slider\"></div>" \
         "</a></pre>" \
         "<hr>" \
         "<pre>2017 ARMmbed</pre>" \
         "</body>";
- 
+
     return httpContent;
+    /*$on*/
 }
- 
+
 /**
  * @brief
  * @note
  * @param
  * @retval
  */
-void sendHTTP(TCPSocket& client, string& header, string& content) {
+void sendHTTP(TCPSocket& client, string& header, string& content)
+{
+    /*$off*/
     char    content_length[5] = { };
- 
+
     header += \
         "\r\nContent-Type: text/html\r\n" \
         "Content-Length: ";
@@ -196,21 +201,23 @@
         string(content_length) + "\r\n" \
         "Pragma: no-cache\r\n" \
         "Connection: About to close\r\n\r\n";
- 
+
     string  webpage = header + content;
     client.send((char*)webpage.c_str(), webpage.length());
     pc.printf("HTTP message sent to client.\n\r");
+    /*$on*/
 }
- 
+
 /**
  * @brief
  * @note
  * @param
  * @retval
  */
-int main(void) {
+int main(void)
+{
     pc.printf("Starting.. \r\n\r\n");
-       
+
     net = new EthernetInterface();
 
     if (!net) {
@@ -219,91 +226,88 @@
     }
 
     //net->set_network (IP, NETMASK, GATEWAY);  // include this for using static IP address
-    
-    nsapi_size_or_error_t r = net->connect();
+    nsapi_size_or_error_t   r = net->connect();
     if (r != 0) {
         pc.printf("Error! net->connect() returned: %d\n", r);
         return r;
     }
 
-   // Show the network address
-    const char *ip = net->get_ip_address();
-    const char *netmask = net->get_netmask();
-    const char *gateway = net->get_gateway();
+    // Show the network address
+    const char*     ip = net->get_ip_address();
+    const char*     netmask = net->get_netmask();
+    const char*     gateway = net->get_gateway();
     pc.printf("IP address: %s\r\n", ip ? ip : "None");
     pc.printf("Netmask: %s\r\n", netmask ? netmask : "None");
-    pc.printf("Gateway: %s\r\n\r\n", gateway ? gateway : "None");   
+    pc.printf("Gateway: %s\r\n\r\n", gateway ? gateway : "None");
     pc.printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n\r\n", ip, PASSWORD.c_str());
- 
+
     /* Open the server on ethernet stack */
     server.open(net);
- 
+
     /* Bind the HTTP port (TCP 80) to the server */
     server.bind(ip, PORT);
- 
+
     /* Can handle 5 simultaneous connections */
     server.listen(5);
- 
+
     //listening for http GET request
-    while(true) {
+    while (true) {
         pc.printf("=========================================\r\n");
-        nsapi_error_t error;
+
+        nsapi_error_t   error;
         clientSocket = server.accept(&error);
         if (error != 0) {
             pc.printf("Connection failed!\r\n");
             clientSocket->close();
             continue;
         }
+
         clientSocket->getpeername(&clientAddress);
         pc.printf("Client with IP address %s connected.\r\n\r\n", clientAddress.get_ip_address());
         clientSocket->recv(receiveBuf, 1023);
         pc.printf("Data received:\r\n%s\n\r", receiveBuf);
- 
+
         string  received(receiveBuf);
- 
-        if(received.substr(0, 3) != "GET") {
+
+        if (received.substr(0, 3) != "GET") {
             httpHeader = HTTP_OK;
             httpContent = "<h1>200 OK</h1>";
             sendHTTP(*clientSocket, httpHeader, httpContent);
             clientSocket->close();
             continue;
         }
- 
-        if(received.substr(0, 6) == "GET / ") {
+
+        if (received.substr(0, 6) == "GET / ") {
             httpHeader = HTTP_OK;
             httpContent = "<p>Usage: Type http://ip_address/password/ into your web browser and hit ENTER</p>\r\n";
             sendHTTP(*clientSocket, httpHeader, httpContent);
             clientSocket->close();
             continue;
         }
- 
+
         int cmd = analyseURL(received);
- 
-        if(cmd == -2) {
- 
+
+        if (cmd == -2) {
             // redirect to the right base url
             httpHeader = MOVED_PERM;
             sendHTTP(*clientSocket, httpHeader, movedPermanently(1));
             clientSocket->close();
             continue;
         }
- 
-        if(cmd == -1) {
+
+        if (cmd == -1) {
             httpHeader = UNAUTHORIZED;
             httpContent = "<h1>401 Unauthorized</h1>";
             sendHTTP(*clientSocket, httpHeader, httpContent);
             clientSocket->close();
             continue;
         }
- 
-        if(cmd == 1) {
+
+        if (cmd == 1)
             sw = ON;    // turn the switch on
-        }
- 
-        if(cmd == 0) {
+        if (cmd == 0)
             sw = OFF;   // turn the switch off
-        }
- 
+            
         httpHeader = HTTP_OK;
         sendHTTP(*clientSocket, httpHeader, showWebPage(sw));
         clientSocket->close();