Webserver controller with url trimming for value controls

Dependencies:   LCD_DISCO_F746NG BSP_DISCO_F746NG

Revision:
0:e455fdb56bc8
Child:
2:33e8bb5615a6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Apr 06 18:58:40 2017 +0000
@@ -0,0 +1,203 @@
+#include "mbed.h"
+#include "EthernetInterface.h"
+#include "TCPServer.h"
+#include "TCPSocket.h"
+#include <stdio.h>
+#include <string>
+
+using namespace     std;
+
+#define PORT        80
+
+EthernetInterface   ethernet;
+TCPServer           server;
+TCPSocket           clientSocket;
+SocketAddress       clientAddress;
+char                receiveBuf[1024] = { };
+
+const int           OFF = 0;
+const int           ON = 1;
+
+DigitalOut          sw(LED1);
+
+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 analyseURL(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);
+
+    string  cmd(str.substr(pos, 5));
+
+    if(cmd == "?sw=0")
+        return(OFF);
+
+    if(cmd == "?sw=1")
+        return(ON);
+
+    return(-3);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+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) {
+    httpContent = "<h2>WebSwitch - Smart Home</h2>\r\n";
+
+    httpContent += "<pre>Temperature:\t21.8&deg;C\r\n</pre>";
+
+    if(status == ON) {
+        httpContent += "<pre>\r\nHeating:\t<font color=#FF0000>ON </font>";
+        httpContent += " <a href=\"./?sw=0\">[Turn off]</a>\r\n";
+    }
+    else {
+        httpContent += "<pre>\r\nHeating:\t<font color=#BBBBBB>OFF</font>";
+        httpContent += " <a href=\"./?sw=1\">[Turn on]</a>\r\n";
+    }
+
+    //httpContent += "  \r\n";
+    //httpContent += "  <a href=\".\">Refresh status]</a>\r\n";
+    httpContent += "</pre>\r\n";
+    httpContent += "<hr>\r\n";
+    httpContent += "<pre>2017 ARMmbed Open Source</pre>";
+    return httpContent;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void sendHTTP(TCPSocket& 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((char*)webpage.c_str(), webpage.length());
+    printf("HTTP sent.\n\r");
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+int main(void) {
+
+    ethernet.connect();
+    printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n", ethernet.get_ip_address(), PASSWORD);
+
+    /* Open the server on ethernet stack */
+    server.open(&ethernet);
+   
+    /* Bind the HTTP port (TCP 80) to the server */
+    server.bind(ethernet.get_ip_address(), 80);
+    
+    /* Can handle 5 simultaneous connections */
+    server.listen(5);
+
+    //listening for http GET request
+    while(true) {
+        server.accept(&clientSocket, &clientAddress);
+        printf("\r\n=========================================\r\n");
+        printf("Connection succeeded!\n\rIP: %s\n\r", clientAddress.get_ip_address());
+        clientSocket.recv(receiveBuf, 1023);
+        printf("Recieved Data: %d\n\r\n\r%.*s\n\r", strlen(receiveBuf), strlen(receiveBuf), receiveBuf);
+
+        string  received(receiveBuf);
+        if(received.substr(0, 3) != "GET") {
+            httpHeader = HTTP_OK;
+            httpContent = "<h1>200 OK</h1>";
+            sendHTTP(clientSocket, httpHeader, httpContent);
+            continue;
+        }
+
+        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);
+            continue;
+        }
+
+        int cmd = analyseURL(received);
+
+        if(cmd == -2) {
+
+            // redirect to the right base url
+            httpHeader = MOVED_PERM;
+            sendHTTP(clientSocket, httpHeader, movedPermanently(1));
+            continue;
+        }
+
+        if(cmd == -1) {
+            httpHeader = UNAUTHORIZED;
+            httpContent = "<h1>401 Unauthorized</h1>";
+            sendHTTP(clientSocket, httpHeader, httpContent);
+            continue;
+        }
+
+        if(cmd == ON) {
+            sw = ON;    // turn the switch on
+        }
+
+        if(cmd == OFF) {
+            sw = OFF;   // turn the switch off
+        }
+
+        httpHeader = HTTP_OK;
+        sendHTTP(clientSocket, httpHeader, showWebPage(sw));
+    }
+}