Simple HTTP Server with one page index.html stored inside MBED as char vector and javascript to update a table content

Fork of HTTP_SERVER by Akifumi Takahashi

HTTP_SERVER.cpp

Committer:
mmdonatti
Date:
2018-05-10
Revision:
14:f21da0acc9f6
Parent:
10:4a48594c2f44

File content as of revision 14:f21da0acc9f6:

#include "HTTP_SERVER.h"

#ifndef DEBUG
//#define DEBUG
#endif

//HTML file - with Javascript
const char *index_html = "<html><head><title>DCM Heaters Driver</title><link rel=\"shortcut icon\" type=\"image/x-icon\" href=\"http://cnpem.br/wp-content/uploads/2018/01/LNLS_Sirius-02-293x300.png\" />\n\
<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script></head>\n\
<script language=\"javascript\" type=\"text/javascript\">\n\
function loop(){\n\
$.post(\"read_data\", function(data){\n\
if(data.length >0)\n\
{\n\
var str = data;\n\
var res = str.split(\" \");\n\
if(res.length == 97){\n\
var table = '<div id=\"data_table\">'+\n\
'<table width=\"100%\" border=\"1\" cellpadding=\"3\" cellspacing=\"1\" bgcolor=\"#E3EBFB\">'+\n\
'<tr align=\"center\" valign=\"middle\">'+\n\
'<td width=\"50\" height=\"40\"><strong>Channel</font></strong></td>'+\n\
'<td width=\"96\" height=\"40\"><strong>Voltage (V)</font></strong></td>'+\n\
'<td width=\"96\" height=\"40\"><strong>Current (A)</font></strong></td>'+\n\
'<td width=\"96\" height=\"40\"><strong>Control (%)</font></strong></td>'+\n\
'<td width=\"96\" height=\"40\"><strong>Current Limit (A)</font></strong></td>'+\n\
'<td width=\"96\" height=\"40\"><strong>Failure</font></strong></td>'+\n\
'<td width=\"96\" height=\"40\"><strong>Overload</font></strong></td>'+\n\
'<td width=\"96\" height=\"40\"><strong>No Load</font></strong></td>'+\n\
'<td width=\"96\" height=\"40\"><strong>Enable</font></strong></td></tr>';\n\
for(var i=0;i<8;i++){\n\
table = table + '<tr align=\"center\" valign=\"middle\">'+\n\
'<td width=\"50\" height=\"31\"bgcolor=\"#FFFFFF\"><span style=\"font-weight:bold;\">'+(i+1)+'</span></td>'+\n\
'<td width=\"96\" height=\"28\"bgcolor=\"#FFFFFF\"><span style=\"font-weight:bold;\">'+res[i*12]+'</span></td>'+\n\
'<td width=\"96\" height=\"28\"bgcolor=\"#FFFFFF\"><span style=\"font-weight:bold;\">'+res[i*12+1]+'</span></td>'+\n\
'<td width=\"96\" height=\"28\"bgcolor=\"#FFFFFF\"><span style=\"font-weight:bold;\">'+res[i*12+2]+'</span></td>'+\n\
'<td width=\"96\" height=\"28\"bgcolor=\"#FFFFFF\"><span style=\"font-weight:bold;\">'+res[i*12+3]+'</span></td>'+\n\
'<td width=\"96\" height=\"28\"bgcolor=\"'+res[i*12+4]+'\"><span style=\"font-weight:bold;\">'+res[i*12+5]+'</span></td>'+\n\
'<td width=\"96\" height=\"28\"bgcolor=\"'+res[i*12+6]+'\"><span style=\"font-weight:bold;\">'+res[i*12+7]+'</span></td>'+\n\
'<td width=\"96\" height=\"28\"bgcolor=\"'+res[i*12+8]+'\"><span style=\"font-weight:bold;\">'+res[i*12+9]+'</span></td>'+\n\
'<td width=\"96\" height=\"28\"bgcolor=\"'+res[i*12+10]+'\"><span style=\"font-weight:bold;\">'+res[i*12+11]+'</span></td>'+\n\
'</tr>';\n\
}\n\
table = table + '</table></div>';\n\
document.getElementById(\"data_table\").innerHTML = table;\n\
}}\n\
});\n\
setTimeout(function(){ loop() }, 2000);\n\
}\n\
</script>\n\
<body onLoad=\"loop()\">\n\
<table width=\"100%\"border=\"0\" cellspacing=\"0\" cellpadding=\"0\" style=\"font-weight:normal;\">\n\
<tr>\n\
<td width=\"25%\" height=\"142\" align=\"center\" valign=\"middle\" style=\"border-bottom: #000000 solid 1px;\">\n\
<a href=\"http://www.lnls.cnpem.br/\"><img src=\"http://lnls.cnpem.br/wp-content/themes/lnls-v2/assets/images/logo-header.svg\" alt=\"LNLS\" width=\"305\" height=\"142\" /></a></td>\n\
<td colspan=\"5\" height=\"142\" align=\"center\" scope=\"col\" style=\"border-bottom: #000000 solid 1px;\"><p><span class=\"style7\">DCM HEATERS DRIVER<br /><br/>\n\
<strong>DIAGNOSTICS<br/></strong></span></p>\n\
<p><span class=\"style7\"><strong><em> <a href=\"http://www.lnls.cnpem.br\">LNLS</a></em></strong></span></p></td>\n\
<td width=\"25%\" height=\"142\" align=\"center\" style=\"border-bottom: #000000 solid 1px;\">\n\
<a href=\"http://www.lnls.cnpem.br/grupos/gae/\"><img src=\"http://www.gae.agency/wp-content/uploads/2016/03/Logo_gae_hp_blue.png\" alt=\"GAE\" width=\"305\" height=\"99\" /></a></td>\n\
</tr>\n\
</table>\n<div id=\"data_table\"></div></body></html>\0";

//table colors vector
const char *color[] = {"#C8FFC8\0","#FF0000\0"};

int index_html_len; //index with html length

char buffer[MAX_BUFFER_SIZE];   //receive and transmit buffer
char tmp_buffer[200];           //aux buffer
int status_code;                //http status code
char reason_phrase[30];         //http reason phrase

char httpmethod[20];            //http method
char filepath[20];              //file requested
char http_ver[20];              //http version

int idx_buffer;                 //index buffer

//Debug functions
namespace HTTP_SERVER
{
void DEBUG_PRINT_LINE(const char* arg_line)
{
#ifdef DEBUG
    printf("(HTTP_SERVER) ")
    printf(arg_line);
    printf("\r\n");
#endif
}
template<typename T>
void DEBUG_PRINT_LINE(const char* arg_line, T arg_t)
{
#ifdef DEBUG
    printf("(HTTP_SERVER) ");
    printf(arg_line, arg_t);
    printf("\r\n");
#endif
}
template<typename T1, typename T2>
void DEBUG_PRINT_LINE(const char* arg_line, T1 arg_t1, T2 arg_t2)
{
#ifdef DEBUG
    printf("(HTTP_SERVER) ");
    printf(arg_line, arg_t1, arg_t2);
    printf("\r\n");
#endif
}
}
using namespace HTTP_SERVER;

HttpServer::HttpServer()
{
    buffer[0] = '\0';   //constructor
}

HttpServer::~HttpServer()
{
}
bool HttpServer::init()
{
    //  TCP Socket setup
    //  To open Server-side PORT
    if(tcpsvr.bind(TCP_PORT)< 0) {
        return false;
    } 
    tcpsvr.set_blocking(true,1500); //set blocking socket

    //  Server start listening Request from a web browser.
    
    if(tcpsvr.listen(5) < 0) {
        return false;
    }
    
    index_html_len = strlen(index_html);    //calculate string length

    return true;
}

bool HttpServer::run(channel *CH)
{            
    if(tcpsvr.accept(tcpcon) < 0) {
        //printf("(HTTP_SERVER) failed to accept connection.\r\n");
        return -1;
    }
    //  When conected
    while(tcpcon.is_connected()) 
    {
        tcpcon.set_blocking(false,100);
        //
        //  Request Analysis
        //
        
        DEBUG_PRINT_LINE("DEBUG MODE");
        switch(tcpcon.receive(buffer, 1023)) {
            case 0:
                //DEBUG_PRINT_LINE("received buffer is empty.");
                status_code = 400;
                sprintf(reason_phrase,"No Request\0");
                httpmethod[0]    = '\0';
                filepath[0]      = '\0';
                http_ver[0]      = '\0';
                break;  
            case -1:
                DEBUG_PRINT_LINE("failed to read data from client.");
                status_code = 500;
                sprintf(reason_phrase,"Internal Server Error\0");
                httpmethod[0]    = '\0';
                filepath[0]      = '\0';
                http_ver[0]      = '\0';
                break;
            default:
                DEBUG_PRINT_LINE("Received Data: %d",strlen(buffer));
                DEBUG_PRINT_LINE("-->\r\n");
                DEBUG_PRINT_LINE("%.*s[End of Request]",strlen(buffer),buffer);
                //  get HTTP method, File path, HTTP version
                sprintf(httpmethod,strtok(buffer," "));
                filepath[0]      = '\0';
                sprintf(http_ver,"HTTP/1.1\0");
                DEBUG_PRINT_LINE("httpmethod: %s", httpmethod);
                DEBUG_PRINT_LINE("file path:  %s", filepath);
                DEBUG_PRINT_LINE("http ver :  %s", http_ver);
                break;
        }
        
        if (httpmethod[0] == '\0') {
            buffer[MAX_BUFFER_SIZE - 1] = '\0';
            sprintf(buffer,"%s %d %s\r\nConnection: Close\r\n\r\n\0", http_ver, status_code, reason_phrase);
            DEBUG_PRINT_LINE("echo back done.");
            break;
        }
        
        //  Response
        if (strcmp(httpmethod,"GET") == 0 ) //GET request - always index.html stoed in index_html
        {
            DEBUG_PRINT_LINE("GET request incomming.");
            
            buffer[MAX_BUFFER_SIZE-1] = '\0';
            status_code = 200;
            sprintf(reason_phrase,"OK\0");

            sprintf(buffer,"%s %d %s\r\nConnection: Close\r\nContent-Type: text/html\r\nKeep-Alive: timeout=15\r\n\r\n\0", http_ver, status_code, reason_phrase);
            tcpcon.send_all(buffer,strlen(buffer));
            tcpcon.send_all((char*)index_html,index_html_len);
            
            break;
        } 
        if (strcmp(httpmethod,"POST") == 0 ) //POST request - javascript request
        {
            DEBUG_PRINT_LINE("POST request incomming.");
            status_code = 200;
            sprintf(reason_phrase,"OK\0");

            sprintf(buffer,"%s %d %s\r\nConnection: Close\r\n\r\n\0", http_ver, status_code, reason_phrase);

            for(idx_buffer=0;idx_buffer<=7;idx_buffer++)
            {
                sprintf(tmp_buffer,"%4.2f %3.2f %d %3.2f %s %d %s %d %s %d %s %d \0",CH[idx_buffer].voltage,CH[idx_buffer].current,CH[idx_buffer].control,CH[idx_buffer].limit,\
                    color[CH[idx_buffer].failure>0],CH[idx_buffer].failure,\
                    color[CH[idx_buffer].overload>ERROR_REP],CH[idx_buffer].overload>ERROR_REP,\
                    color[CH[idx_buffer].noload>ERROR_REP],CH[idx_buffer].noload>ERROR_REP,\
                    color[CH[idx_buffer].enable==0],CH[idx_buffer].enable);
                strcat(buffer,tmp_buffer);

            }
            tcpcon.send_all(buffer,strlen(buffer));
            break;
            

        }      
    }
    tcpcon.close(); //always close the connection
    return 0;
}