Webserver controller with url trimming for value controls

Dependencies:   LCD_DISCO_F746NG BSP_DISCO_F746NG

main.cpp

Committer:
hudakz
Date:
2017-05-06
Revision:
4:d7c37f516f5f
Parent:
3:c927a415dd38
Child:
5:e1218721aefd

File content as of revision 4:d7c37f516f5f:

#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);
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

/**
 * @brief   Defines a custom MAC address
 * @note    Uncomment the code below to define a unique MAC address.
 *          Modify the mac array items as needed.
 * @param
 * @retval
 */
//extern "C" void mbed_mac_address(char* mac) {
//    mac[0] = 0x00;
//    mac[1] = 0x01;
//    mac[2] = 0x02;
//    mac[3] = 0x03;
//    mac[4] = 0x04;
//    mac[5] = 0x05;
//};

/**
 * @brief   Analyses the received URL
 * @note    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.....
 * @param   url URL string
 * @retval -1 invalid password
 *         -2 no command given but password valid
 *         -3 just refresh page
 *          0 switch off
 *          1 switch on
 */
int8_t analyseURL(string& url) {
    if(url.substr(5, PASSWORD.size()) != PASSWORD)
        return(-1);

    uint8_t pos = 5 + PASSWORD.size();

    if(url.substr(pos, 1) == " ")
        return(-2);

    if(url.substr(pos++, 1) != "/")
        return(-1);

    string  cmd(url.substr(pos, 5));

    if(cmd == "?sw=0")
        return(0);

    if(cmd == "?sw=1")
        return(1);

    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) {
    char roomTempStr[5];

    //roomTemp = ds1820.read();
    sprintf(roomTempStr, "%3.1f", roomTemp);

    httpContent = "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>"; 
    httpContent += "<pre>Temperature:\t" + string(roomTempStr) + "&deg;C\r\n</pre>";

    if(status == ON) {
        httpContent += "<pre>\r\nHeating:\t<font color=#FF0000>On </font>";
        httpContent += " <a href=\"./?sw=0\"><button>Turn off</button></a>\r\n";
    }
    else {
        httpContent += "<pre>\r\nHeating:\t<font color=#999999>Off</font>";
        httpContent += " <a href=\"./?sw=1\"><button>Turn on</button></a>\r\n";
    }

    httpContent += "</pre>\r\n";
    httpContent += "<hr>\r\n";
    httpContent += "<pre>2017 ARMmbed</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.set_network("192.168.1.181","255.255.255.0","192.168.1.1");  // use static IP address (IP address, netmask, gateway)
    ethernet.connect();
    printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n", ethernet.get_ip_address(), PASSWORD.c_str());

    /* 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) {
        printf("\r\n=========================================\r\n");
        printf("Ready to serve clients.\r\n");
        server.accept(&clientSocket, &clientAddress);
        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));
    }
}