Jack Hansdampf / Mbed OS WebSwitch_ENC28J60_GSOE

Dependencies:   UIPEthernet_GSOE

main.cpp

Committer:
hudakz
Date:
2019-08-30
Revision:
12:7c46dcf6f7e2
Parent:
11:6c0b20227ca2
Child:
14:810ac368dd6e

File content as of revision 12:7c46dcf6f7e2:

#include "mbed.h"
#include <string>
#include "UipEthernet.h"
#include "TcpServer.h"
#include "TcpClient.h"

using namespace std;

//#define DEBUG

#define IP      "192.168.1.35"
#define GATEWAY "192.168.1.1"
#define NETMASK "255.255.255.0"
#define PORT    80

const uint8_t   MAC[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x06 };
UipEthernet     net(MAC, D11, D12, D13, D10);   // mosi, miso, sck, cs
TcpServer       server;                         // Ethernet server
TcpClient*      client;
char            receiveBuf[1024];
const int       OFF = 0;
const int       ON = 1;
DigitalOut      output(D3);                     // A digital output to be switched on/off
float           roomTemp = 21.8;                // A temperature sensor output
const string    PASSWORD = "secret";            // Change as you like
string          httpHeader;                     // HTTP header
string          httpContent;                    // HTTP content

/**
 * @brief   Analyses the received URL
 * @note    The string passed to this function will look like this:
 *          GET /HTTP/1.....
 *          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 -3 just refresh page
 *         -2 no command given but password valid
 *         -1 invalid password
 *          0 switch off
 *          1 switch on
 */
int8_t analyseURL(string& url)
{
    if (url.length() < 5 + PASSWORD.size() + 1)
        return(-1);

    if (url.substr(5, PASSWORD.size()) != PASSWORD)
        return(-1);

    uint8_t pos = 5 + PASSWORD.size();

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

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

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

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

    /*$off*/
    httpContent  =
        "<head>"
        "<meta charset=\"utf-8\">"
        "<meta name=\"viewport\" content=\" initial-scale=1.0; maximum-scale=1.0; minimum-scale=1.0; user-scalable=0;\"/>"
        "<title>Smart Home</title>"
        "<link href='http://fonts.googleapis.com/css?family=Droid+Sans&v1' rel='stylesheet' type='text/css'>"
        "<style>"
        ".switch {"
            "position: relative;"
            "display: inline-block;"
            "width: 60px;"
            "height: 34px;"
        "}"
        ".switch input {display:none;}"
        ".slider {"
            "position: absolute;"
            "cursor: pointer;"
            "top: 0;"
            "left: 0;"
            "right: 0;"
            "bottom: 0;"
            "border-radius: 34px;"
            "background-color: #ccc;"
            "-webkit-transition: .4s;"
            "transition: .4s;"
        "}"
        ".slider:before {"
            "position: absolute;"
            "content: \"\";"
            "height: 26px;"
            "width: 26px;"
            "left: 4px;"
            "bottom: 4px;"
            "border-radius: 50%;"
            "background-color: white;"
            "-webkit-transition: .4s;"
            "transition: .4s;"
        "}"
        "input:checked + .slider {"
            "background-color: #8ce196;"
        "}"
        "input:focus + .slider {"
            "box-shadow: 0 0 1px #8ce196;"
        "}"
        "input:checked + .slider:before {"
            "-webkit-transform: translateX(26px);"
            "-ms-transform: translateX(26px);"
            "transform: translateX(26px);"
        "}"
        "</style>"
        "</head>"

        "<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) {
        httpContent +=
            "<a href=\"./?sw=0\" class=\"switch\"> "
            "<input type=\"checkbox\" checked>";
    }
    else {
        httpContent +=
            "<a href=\"./?sw=1\" class=\"switch\"> "
            "<input type=\"checkbox\">";
    }

    httpContent +=
        "<div class=\"slider\"></div>"
        "</a>"
        "</pre>"
        "<hr>"
        "<pre>2017 ARMmbed</pre>"
        "</body>";

    return httpContent;
    /*$on*/
}

/**
 * @brief
 * @note
 * @param
 * @retval
 */
void sendHTTP(TcpClient& client, string& header, string& content)
{
    /*$off*/
    char    content_length[5] = { };

    header +=
        "\r\nContent-Type: text/html\r\n"
        "Content-Length: ";
    sprintf(content_length, "%d", content.length());
    header +=
        string(content_length) + "\r\n"
        "Pragma: no-cache\r\n"
        "Connection: About to close\r\n\r\n";

    string  webpage = header + content;
    client.send((uint8_t*)webpage.c_str(), webpage.length());
    /*$on*/
}

/**
 * @brief
 * @note
 * @param
 * @retval
 */
int main(void)
{
    printf("Starting ...\r\n");

    // IP address must be unique and compatible with your network.
    //net.set_network(IP, NETMASK, GATEWAY);  // include this for using static IP address
    net.connect();

    // Show the network address
    const char*     ip = net.get_ip_address();
    const char*     netmask = net.get_netmask();
    const char*     gateway = net.get_gateway();

    printf("IP address: %s\r\n", ip ? ip : "None");
    printf("Netmask: %s\r\n", netmask ? netmask : "None");
    printf("Gateway: %s\r\n\r\n", gateway ? gateway : "None");
    printf("------------------------------------------------------\r\n");
    printf("Usage: Type %s/%s/ into your web browser and hit ENTER\r\n", net.get_ip_address(), PASSWORD.c_str());
    printf("------------------------------------------------------\r\n");

    /* Open the server on ethernet stack */
    server.open(&net);

    /* Bind the HTTP port (TCP 80) to the server */
    server.bind(PORT);

    /* Can handle 5 simultaneous connections */
    server.listen(5);

    while (true) {
        client = server.accept();

        if (client) {
            client->recv((uint8_t*)receiveBuf, client->available());
#ifdef DEBUG
            printf("Client with IP address %s connected.\r\n\r\n", client->getpeername());
            printf("Data received:\r\n%s\n\r", receiveBuf);
#endif
            string  received(receiveBuf);

            if (received.substr(0, 3) != "GET") {
                httpHeader = "HTTP/1.0 200 OK";
                httpContent = "<h1>200 OK</h1>";
                sendHTTP(*client, httpHeader, httpContent);
                client->close();
                continue;
            }

            if (received.substr(0, 6) == "GET / ") {
                httpHeader = "HTTP/1.0 200 OK";
                httpContent = "<p>Usage: http://host_or_ip/password</p>\r\n";
                sendHTTP(*client, httpHeader, httpContent);
                client->close();
                continue;
            }

            int cmd = analyseURL(received);

            switch (cmd) {
                case -3:
                    // update webpage
                    httpHeader = "HTTP/1.0 200 OK";
                    sendHTTP(*client, httpHeader, showWebPage(output));
                    break;

                case -2:
                    // redirect to the right base url
                    httpHeader = "HTTP/1.0 301 Moved Permanently\r\nLocation: ";
                    sendHTTP(*client, httpHeader, movedPermanently(1));
                    break;

                case -1:
                    httpHeader = "HTTP/1.0 401 Unauthorized";
                    httpContent = "<h1>401 Unauthorized</h1>";
                    sendHTTP(*client, httpHeader, httpContent);
                    break;

                case 0:
                    output = OFF;   // output off
                    httpHeader = "HTTP/1.0 200 OK";
                    sendHTTP(*client, httpHeader, showWebPage(output));
                    break;

                case 1:
                    output = ON;    // output on
                    httpHeader = "HTTP/1.0 200 OK";
                    sendHTTP(*client, httpHeader, showWebPage(output));
                    break;
            }

            client->close();
        }
    }
}