A tiny webserver alowing to remotely turn on or turn off a digital output on an STM32F407VET6 board. For more details see https://os.mbed.com/users/hudakz/code/STM32F407VET6_Hello/

Dependencies:   EthernetInterface mbed-rtos 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/off by using a web browser.

/media/uploads/hudakz/webswitch_desktop.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.

For more details on how to connect an Ethernet interface to a STM32F407VET6 board see https://os.mbed.com/users/hudakz/code/STM32F407VET6_Hello/.

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

main.cpp

Committer:
hudakz
Date:
2018-04-03
Revision:
1:a583ba376cc7
Parent:
0:7764029ff97d

File content as of revision 1:a583ba376cc7:

// Blinky demo for the STM32F407VET6 boards.
// See http://wiki.stm32duino.com/index.php?title=STM32F407.
//
// Use "Seed Arch Max" as target platform for the online compiler.

#include "mbed.h"
#include "EthernetInterface.h"
#include <stdio.h>
#include <string>

using namespace     std;

#define PORT        80

EthernetInterface   ethernet;

TCPSocketServer     server;
bool                serverIsListening = false;

TCPSocketConnection client;
bool                clientIsConnected = false;

const int           OFF = 1;
const int           ON = 0;

DigitalOut          sw(PA_6);
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(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) {
    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(TCPSocketConnection& client, string& header, string& content) {
    char    contentLength[5] = { };

    header += "\r\nContent-Type: text/html\r\n";
    header += "Content-Length: ";
    sprintf(contentLength, "%d", content.length());
    header += string(contentLength) + "\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());
    clientIsConnected = false;
    printf("HTTP sent.\n\r");
}

/**
 * @brief
 * @note
 * @param
 * @retval
 */
int main(void) {
    sw = OFF;
    //setup ethernet interface
    ethernet.init(); //Use DHCP
    //ethernet.init("192.168.1.181", "255.255.255.0", "192.168.1.1");   // Use static IP
    ethernet.connect();
    printf("USAGE: Type '%s/%s/' into your web browser and hit ENTER\r\n", ethernet.getIPAddress(), PASSWORD.c_str());
    printf("NOTE:  Don't forget to type the last '/'.\r\n\r\n");

    //setup tcp socket
    if(server.bind(PORT) < 0) {
        printf("HTTP server bind failed.\n\r");
        return -1;
    }
    else {
        printf("HTTP server bind succeeded.\n\r");
        serverIsListening = true;
    }

    if(server.listen(1) < 0) {
        printf("HTTP server listen failed.\n\r");
        return -1;
    }
    else {
        printf("HTTP server is listening...\n\r");
    }

    //listening for http GET request
    while(serverIsListening) {

        if(server.accept(client) < 0) {
            printf("Failed to accept connection.\n\r");
        }
        else {
            printf("\r\n=========================================\r\n");
            printf("Connection accepted!\n\rIP: %s\n\r", client.get_address());
            clientIsConnected = true;

            while(clientIsConnected) {
                char    buffer[1024] = { };
                switch(client.receive(buffer, 1023)) {
                case 0:
                    printf("Recieved buffer is empty.\n\r");
                    clientIsConnected = false;
                    break;

                case -1:
                    printf("Failed to read data from client.\n\r");
                    clientIsConnected = false;
                    break;

                default:
                    printf("Recieved Data: %d\n\r\n\r%.*s\n\r", strlen(buffer), strlen(buffer), buffer);

                    string  received(buffer);
                    if(received.substr(0, 3) != "GET") {
                        httpHeader = HTTP_OK;
                        httpContent = "<h1>200 OK</h1>";
                        sendHTTP(client, 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(client, httpHeader, httpContent);
                        continue;
                    }

                    int cmd = analyseURL(received);

                    if(cmd == -2) {

                        // redirect to the correct base URL
                        httpHeader = MOVED_PERM;
                        sendHTTP(client, httpHeader, movedPermanently(1));
                        continue;
                    }

                    if(cmd == -1) {
                        httpHeader = UNAUTHORIZED;
                        httpContent = "<h1>401 Unauthorized</h1>";
                        sendHTTP(client, 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(client, httpHeader, showWebPage(sw));
                    break;
                }
            }

            printf("Closing connection.\n\r");
            printf("HTTP server is listening...\n\r");
            client.close();
        }
    }
}