Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2014:mbed-http

Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

Obě strany předchozí revize Předchozí verze
Následující verze
Předchozí verze
2014:mbed-http [2015/01/19 04:50]
Maximilián Tydor [REALIZACE]
2014:mbed-http [2015/01/19 06:02] (aktuální)
Maximilián Tydor [vykreslení webové stránky]
Řádek 44: Řádek 44:
 Vytvořený skript hledá v HTTP hlavičce odeslané klientem tento řádek: //"​Authorization:​ Basic TVBPQToyMDE0"//,​ Vytvořený skript hledá v HTTP hlavičce odeslané klientem tento řádek: //"​Authorization:​ Basic TVBPQToyMDE0"//,​
 co je zahashovaná kombinace uživatelského jména //"​MPOA"//​ a hesla //"​2014"//​. co je zahashovaná kombinace uživatelského jména //"​MPOA"//​ a hesla //"​2014"//​.
-Pokud tuto kombinaci nenajde, odešle klientovi zprávu //"401 Authorization Required"//​+Pokud tuto kombinaci nenajde, odešle klientovi zprávu //"401 Authorization Required"//​
 +Prohlížeč pak vyzve uživatele k zadání přihlašovacích údajů jednoduchým formulářem. 
 + 
 +{{ 2014:​mbed-http:​auth.png |Přihlašovací dialog}} 
 + 
 +Pokud uživatel dialog zruší, daleko se nedostane... 
 + 
 +{{ 2014:​mbed-http:​unauthorized.png |Chybová stránka v případě zrušení přihlašovacího dialogu}} 
 + 
 +Pokouší-li se užívatel odklepnout formulář prázdný nebo s nesprávnými údaji vyskakuje okno pořád dokola.
  
 <code c> <code c>
 if(!strstr(buffer,​ "​Authorization:​ Basic TVBPQToyMDE0"​)){ ​       //MPOA 2014 if(!strstr(buffer,​ "​Authorization:​ Basic TVBPQToyMDE0"​)){ ​       //MPOA 2014
   sprintf(httpHeader,"​HTTP/​1.1 401 Authorization Required \r\nContent-Type:​ text\r\nWWW-Authenticate:​ Basic realm='​Login required!'​\r\n\r\n"​);​   sprintf(httpHeader,"​HTTP/​1.1 401 Authorization Required \r\nContent-Type:​ text\r\nWWW-Authenticate:​ Basic realm='​Login required!'​\r\n\r\n"​);​
-  client.send(httpHeader,​strlen(httpHeader));​+  client.send(httpHeader,​strlen(httpHeader)); ​                   //​Odeslání výzvy k přihlášení
   sprintf(httpHeader,​ "<​HTML>​\r\n\t<​HEAD>​\r\n\t\t<​TITLE>​Error</​TITLE>​\r\n\t</​HEAD>​\r\n\t<​BODY>​\r\n\t\t<​H1>​401 Unauthorised.</​H1>​\r\n\t</​BODY>​\r\n</​HTML>"​);​   sprintf(httpHeader,​ "<​HTML>​\r\n\t<​HEAD>​\r\n\t\t<​TITLE>​Error</​TITLE>​\r\n\t</​HEAD>​\r\n\t<​BODY>​\r\n\t\t<​H1>​401 Unauthorised.</​H1>​\r\n\t</​BODY>​\r\n</​HTML>"​);​
-  client.send(httpHeader,​strlen(httpHeader));​+  client.send(httpHeader,​strlen(httpHeader)); ​                   //​Formát stránky s chybovým hlášením
   client.close();​   client.close();​
 } }
 </​code>​ </​code>​
 +
 +==== metoda POST ====
 +Přesto že předat těch několik parametrů není problém skrze URL, tedy metodou GET, ale výsledek není zrovna lahodivý oku,
 +proto byla implementována podpora metody POST. Obsluha je ve výsledku velice jednoduchá (ale ladění zabralo jeden celý den).
 +Data se posílají dvěma pakety (i když i přes WireShark to lze jen těžko poznat). První obsahuje identifikační hlavičku s identifikátorem metody, prohlížeče klienta, autorizačních ůdajů apod.
 +V druhém paketu se nacházejí samotná data a je nutné jej příjmout až v samotném průběhu zpracování metody POST,
 +jinak by do toho kecal autorizační algoritmus a ani selektor metod by si s tím nevěděl rady.
 +
 +<code c>
 +}                                                        //konec metody GET
 +else if (!strncmp(buffer,​ "POST ", 5)) {                 //​ověření,​ že se jedná o POST data
 +  int n = client.receive(buffer,​ sizeof(buffer)); ​       //příjem dalšího paketu se samotnými daty  ​
 +  ...                                                    //​následuje zpracování přijatých dat
 +</​code>​
 +
 +==== vykreslení webové stránky ====
 +Dekódování přijatých dat je věc hraní si s řetězci a následnými převody, ale toho je internet plný a o radu v případě problému není nouze.
 +Zde tedy pár řádku k nahlédnutí jak vypadá generátor webové stránky uvnitř procesoru.
 +
 +<code c>
 +void display_page(void){
 +  sprintf(httpHeader,"​HTTP/​1.1 200 OK\r\nContent-Type:​ text/​html\r\nConnection:​ Close\r\n\r\n"​);​
 +  client.send(httpHeader,​strlen(httpHeader));​
 +  sprintf(httpHeader,"<​html>​\r\n\t<​head>​\r\n\t\t<​title>​K64F HTTP RGB controller</​title>​\r\n\t\t<​meta http-equiv='​refresh'​ content='​5'>​\r\n\t</​head>​\r\n\t<​body>​\r\n\t\t<​h1>​K64F RGB on-line controller</​h1>"​);​
 +  client.send(httpHeader,​strlen(httpHeader));​
 +  sprintf(httpHeader,"​\r\n\t\t<​table cellspacing='​5px'>​\r\n\t\t\t<​tr>​\r\n\t\t\t\t<​th colspan='​2'>​RGB controls & status</​th>​\r\n\t\t\t\t<​th>​SW2 status</​th>​\r\n\t\t\t\t<​th>​SW3 status</​th>​\r\n\t\t\t</​tr>​\r\n\t\t\t<​tr>​\r\n\t\t\t\t<​td><​form action=''​ method='​post'>"​);​
 +  client.send(httpHeader,​strlen(httpHeader));​
 +  sprintf(httpHeader,"​\r\n\t\t\t\t\t<​label for='​R'>​R:​\t</​label><​input type='​checkbox'​ name='​R'​ id='​R'"​);​
 +  if(r_on)
 +    strcat(httpHeader,​ " checked='​checked'><​br>"​);​
 +  else
 +    strcat(httpHeader,​ "><​br>"​);​
 +  client.send(httpHeader,​strlen(httpHeader));​
 +  sprintf(httpHeader,"​\r\n\t\t\t\t\t<​label for='​G'>​G:​\t</​label><​input type='​checkbox'​ name='​G'​ id='​G'"​);​
 +  if(g_on)
 +    strcat(httpHeader,​ " checked='​checked'><​br>"​);​
 +  else
 +    strcat(httpHeader,​ "><​br>"​);​
 +  client.send(httpHeader,​strlen(httpHeader));​
 +  sprintf(httpHeader,"​\r\n\t\t\t\t\t<​label for='​B'>​B:​\t</​label><​input type='​checkbox'​ name='​B'​ id='​B'"​);​
 +  if(b_on)
 +    strcat(httpHeader,​ " checked='​checked'><​br>"​);​
 +  else
 +    strcat(httpHeader,​ "><​br>"​);​
 +  client.send(httpHeader,​strlen(httpHeader));​
 +  sprintf(httpHeader,"​\r\n\t\t\t\t\t<​input type='​submit'​ value='​Save'>​\r\n\t\t\t\t</​form></​td>"​);​
 +  client.send(httpHeader,​strlen(httpHeader)); ​      
 +  sprintf(httpHeader,"​\r\n\t\t\t\t<​td style='​vertical-align:​ bottom;'><​div style='​background:​ #​%02x%02x%02x;​ width: 80px; height: 95%; border: 2px solid;'></​div></​td>",​r_col,​ g_col, b_col);
 +  client.send(httpHeader,​strlen(httpHeader));​
 +  sprintf(httpHeader,"​\r\n\t\t\t\t<​td style='​vertical-align:​ bottom;'><​div style='​background:​ black; width: 84px; height: %dpx;'></​div></​td>",​s2_col);​
 +  client.send(httpHeader,​strlen(httpHeader));​
 +  sprintf(httpHeader,"​\r\n\t\t\t\t<​td style='​vertical-align:​ bottom;'><​div style='​background:​ black; width: 84px; height: %dpx;'></​div></​td>",​s3_col);​
 +  client.send(httpHeader,​strlen(httpHeader));​
 +  sprintf(httpHeader,"​\r\n\t\t\t</​tr>​\r\n\t\t</​table>​\r\n\t</​body>​\r\n</​html>"​);​
 +  client.send(httpHeader,​strlen(httpHeader));​
 +}
 +</​code>​
 +
 +a zde výsledek, který už umí přechroustat snad každý prohlížeč:​
 +
 +<code html>
 +<​html>​
 + <​head>​
 + <​title>​K64F HTTP RGB controller</​title>​
 + <meta http-equiv='​refresh'​ content='​5'>​
 + </​head>​
 + <​body>​
 + <​h1>​K64F RGB on-line controller</​h1>​
 + <table cellspacing='​5px'>​
 + <​tr>​
 + <th colspan='​2'>​RGB controls & status</​th>​
 + <​th>​SW2 status</​th>​
 + <​th>​SW3 status</​th>​
 + </​tr>​
 + <​tr>​
 + <​td><​form action=''​ method='​post'>​
 + <​label for='​R'>​R:​ </​label><​input type='​checkbox'​ name='​R'​ id='​R'​ checked='​checked'><​br>​
 + <​label for='​G'>​G:​ </​label><​input type='​checkbox'​ name='​G'​ id='​G'​ checked='​checked'><​br>​
 + <​label for='​B'>​B:​ </​label><​input type='​checkbox'​ name='​B'​ id='​B'><​br>​
 + <​input type='​submit'​ value='​Save'>​
 + </​form></​td>​
 + <td style='​vertical-align:​ bottom;'><​div style='​background:​ #ffff00; width: 80px; height: 95; border: 2px solid;'></​div></​td>​
 + <td style='​vertical-align:​ bottom;'><​div style='​background:​ black; width: 84px; height: 30px;'></​div></​td>​
 + <td style='​vertical-align:​ bottom;'><​div style='​background:​ black; width: 84px; height: 70px;'></​div></​td>​
 + </​tr>​
 + </​table>​
 + </​body>​
 +</​html>​
 +</​code>​
 +
 +a zde ještě výsledek, který je mezi lidmi oblíbenější:​
 +
 +{{ 2014:​mbed-http:​webpage.png |Obrázek výsledné webové stránky}}
 +
 +Přes tuto stránku je možné zapínat a vypínat jednotlivé barvy RGB LED a hned vidět i výsledek bez nutnosti být zrovna u desky.
 +Výsledná barevná kombinace je spočítaná ze všech tří složek a kdyby se aplikace poupravila tak, že samostatné vlákno by simulovalo PWM modulaci,
 +pořád by přibližně odpovídala barva na webové stránce barvě na LED.
 +Je to možné velice snadno ověřit na [[http://​www.quackit.com/​css/​css_color_codes.cfm|paletě webových barev]].
 +Na stránce se dále zobrazují dva jakoby bargrafy simulující klasické tlačítka (v horní poloze neaktivní).
 +Pro větší pohodlí a uživatelský komfort se stránka sama obnovuje každých 5 sekund.
 +-------
 +
 +===== PŘÍLOHY =====
 +
 +==== Zdrojový kód main.cpp ====
 +
 +<code c>
 +#include "​mbed.h"​
 +#include "​EthernetInterface.h"​
 +#include "​SDFileSystem.h"​
 +#include <​stdio.h>​
 +#include <​string.h>​
 +
 +#define HTTPD_SERVER_PORT ​  80
 +#define HTTPD_MAX_REQ_LENGTH ​  1023
 +#define HTTPD_MAX_HDR_LENGTH ​  255
 +
 +Serial uart(USBTX, USBRX);
 +
 +EthernetInterface eth;
 +TCPSocketServer server;
 +TCPSocketConnection client;
 +
 +char buffer[HTTPD_MAX_REQ_LENGTH+1];​
 +char httpHeader[HTTPD_MAX_HDR_LENGTH+1];​
 +
 +char *uristr;
 +char *eou;
 +char *qrystr;
 +
 +int r_on=0, g_on=0, b_on=0;
 +int r_col=0, g_col=0, b_col=0, s2_col=80, s3_col=80;
 +
 +void display_page(void){
 +    ​
 +    sprintf(httpHeader,"​HTTP/​1.1 200 OK\r\nContent-Type:​ text/​html\r\nConnection:​ Close\r\n\r\n"​);​
 +    client.send(httpHeader,​strlen(httpHeader));​
 +    sprintf(httpHeader,"<​html>​\r\n\t<​head>​\r\n\t\t<​title>​K64F HTTP RGB controller</​title>​\r\n\t\t<​meta http-equiv='​refresh'​ content='​5'>​\r\n\t</​head>​\r\n\t<​body>​\r\n\t\t<​h1>​K64F RGB on-line controller</​h1>"​);​
 +    client.send(httpHeader,​strlen(httpHeader));​
 +    sprintf(httpHeader,"​\r\n\t\t<​table cellspacing='​5px'>​\r\n\t\t\t<​tr>​\r\n\t\t\t\t<​th colspan='​2'>​RGB controls & status</​th>​\r\n\t\t\t\t<​th>​SW2 status</​th>​\r\n\t\t\t\t<​th>​SW3 status</​th>​\r\n\t\t\t</​tr>​\r\n\t\t\t<​tr>​\r\n\t\t\t\t<​td><​form action=''​ method='​post'>"​);​
 +    client.send(httpHeader,​strlen(httpHeader));​
 +    sprintf(httpHeader,"​\r\n\t\t\t\t\t<​label for='​R'>​R:​\t</​label><​input type='​checkbox'​ name='​R'​ id='​R'"​);​
 +    if(r_on)
 +        strcat(httpHeader,​ " checked='​checked'><​br>"​);​
 +    else
 +        strcat(httpHeader,​ "><​br>"​);​
 +    client.send(httpHeader,​strlen(httpHeader));​
 +    sprintf(httpHeader,"​\r\n\t\t\t\t\t<​label for='​G'>​G:​\t</​label><​input type='​checkbox'​ name='​G'​ id='​G'"​);​
 +    if(g_on)
 +        strcat(httpHeader,​ " checked='​checked'><​br>"​);​
 +    else
 +        strcat(httpHeader,​ "><​br>"​);​
 +    client.send(httpHeader,​strlen(httpHeader));​
 +    sprintf(httpHeader,"​\r\n\t\t\t\t\t<​label for='​B'>​B:​\t</​label><​input type='​checkbox'​ name='​B'​ id='​B'"​);​
 +    if(b_on)
 +        strcat(httpHeader,​ " checked='​checked'><​br>"​);​
 +    else
 +        strcat(httpHeader,​ "><​br>"​);​
 +    client.send(httpHeader,​strlen(httpHeader));​
 +    sprintf(httpHeader,"​\r\n\t\t\t\t\t<​input type='​submit'​ value='​Save'>​\r\n\t\t\t\t</​form></​td>"​);​
 +    client.send(httpHeader,​strlen(httpHeader)); ​      
 +    sprintf(httpHeader,"​\r\n\t\t\t\t<​td style='​vertical-align:​ bottom;'><​div style='​background:​ #​%02x%02x%02x;​ width: 80px; height: 95%; border: 2px solid;'></​div></​td>",​r_col,​ g_col, b_col);
 +    client.send(httpHeader,​strlen(httpHeader));​
 +    sprintf(httpHeader,"​\r\n\t\t\t\t<​td style='​vertical-align:​ bottom;'><​div style='​background:​ black; width: 84px; height: %dpx;'></​div></​td>",​s2_col);​
 +    client.send(httpHeader,​strlen(httpHeader));​
 +    sprintf(httpHeader,"​\r\n\t\t\t\t<​td style='​vertical-align:​ bottom;'><​div style='​background:​ black; width: 84px; height: %dpx;'></​div></​td>",​s3_col);​
 +    client.send(httpHeader,​strlen(httpHeader));​
 +    sprintf(httpHeader,"​\r\n\t\t\t</​tr>​\r\n\t\t</​table>​\r\n\t</​body>​\r\n</​html>"​);​
 +    client.send(httpHeader,​strlen(httpHeader));​
 +
 +}
 +
 +int main (void)
 +{
 +//    RGB LED outputs
 +    DigitalOut ​ rled(LED_RED,​ 1);
 +    DigitalOut ​ gled(LED_GREEN,​ 1);
 +    DigitalOut ​ bled(LED_BLUE,​ 1);
 +    ​
 +//    SW2 & SW3 inputs
 +    DigitalIn ​  ​sw2(PTC6);​
 +    DigitalIn ​  ​sw3(PTA4);​
 +    ​
 +//    Serial Interface eth;
 +    uart.baud(115200);​
 +    uart.printf("​Initializing\n"​);​
 +
 +//    EthernetInterface eth;
 +    uart.printf("​Initializing Ethernet\n"​);​
 +    eth.init(); //Use DHCP
 +    uart.printf("​Connecting\n"​);​
 +    eth.connect();​
 +    uart.printf("​IP Address is %s\n", eth.getIPAddress());​
 +
 +//    TCPSocketServer server;
 +    server.bind(HTTPD_SERVER_PORT);​
 +    server.listen();​
 +    uart.printf("​Server Listening\n"​);​
 +
 +    while (true) {
 +        uart.printf("​\nWaiting for new connection...\r\n"​);​
 +        server.accept(client);​
 +        client.set_blocking(false,​ 1500); // Timeout after (1.5)s
 +        ​
 +        if(r_on){ ​          //​zadost o rozsviceni cervene LED
 +            rled=0; ​        //led aktivni logickou 0
 +        }
 +        else{
 +            rled=1;
 +        }
 +        ​
 +        if(g_on){ ​          //​zadost o rozsviceni zelene LED
 +            gled=0; ​        //led aktivni logickou 0
 +        }
 +        else{
 +            gled=1;
 +        }
 +        ​
 +        if(b_on){ ​          //​zadost o rozsviceni modre LED
 +            bled=0; ​        //led aktivni logickou 0
 +        }
 +        else{
 +            bled=1;
 +        }
 +        ​
 +        if(sw2){ ​           //nacteni stavu tlacitka SW2
 +            s2_col = 70;    //pokud neni tlacitko zmacknute zobrazi se vysoky sloupecek
 +        }
 +        else{
 +            s2_col = 30;    //pokud je tlacitko zmacknute zobrazi se nizky sloupecek
 +        }
 +        if(sw3){
 +            s3_col = 70;
 +        }
 +        else{  ​
 +            s3_col = 30;  ​
 +        }
 +        ​
 +        ​
 +        uart.printf("​Connection from: %s\r\n",​ client.get_address());​
 +        while (true) {
 +            ​
 +            int n = client.receive(buffer,​ sizeof(buffer));​
 +            if (n <= 0) break;
 +            uart.printf("​Recieved Data: %d\r\n\r\n%.*s\r\n",​n,​n,​buffer);​
 +            if (n >= 1024) {
 +                sprintf(httpHeader,"​HTTP/​1.1 413 Request Entity Too Large \r\nContent-Type:​ text\r\nConnection:​ Close\r\n\r\n"​);​
 +                client.send(httpHeader,​strlen(httpHeader));​
 +                client.send(buffer,​n);​
 +                break;
 +            } else {
 +                buffer[n]=0;​
 +            }
 +                        ​
 +            if(!strstr(buffer,​ "​Authorization:​ Basic TVBPQToyMDE0"​)){ ​       //MPOA 2014
 +                sprintf(httpHeader,"​HTTP/​1.1 401 Authorization Required \r\nContent-Type:​ text\r\nWWW-Authenticate:​ Basic realm='​Login required!'​\r\n\r\n"​);​
 +                client.send(httpHeader,​strlen(httpHeader));​
 +                sprintf(httpHeader,​ "<​HTML>​\r\n\t<​HEAD>​\r\n\t\t<​TITLE>​Error</​TITLE>​\r\n\t</​HEAD>​\r\n\t<​BODY>​\r\n\t\t<​H1>​401 Unauthorised.</​H1>​\r\n\t</​BODY>​\r\n</​HTML>"​);​
 +                client.send(httpHeader,​strlen(httpHeader));​
 +                client.close();​
 +            }
 +
 +                if (!strncmp(buffer,​ "GET ", 4)) {
 +                    uristr = buffer + 4;
 +                    eou = strstr(uristr,​ " ");
 +                    if (eou == NULL) {
 +                        sprintf(httpHeader,"​HTTP/​1.1 400 Bad Request \r\nContent-Type:​ text\r\nConnection:​ Close\r\n\r\n"​);​
 +                        client.send(httpHeader,​strlen(httpHeader));​
 +                        client.send(buffer,​n);​
 +                    } 
 +                    else {
 +                        *eou = 0;                                                ​
 +                        display_page();​
 +                        client.close();​
 +                    }
 +                }                ​
 +                else if (!strncmp(buffer,​ "POST ", 5)) {
 +                    ​
 +                    int n = client.receive(buffer,​ sizeof(buffer));​
 +                    ​
 +                    if (strstr(buffer,​ "​R=on"​)) {
 +                        r_on = 1;
 +                        r_col = 255;
 +                    }
 +                    else{
 +                        r_on = 0;
 +                        r_col = 0;
 +                    }
 +                    if (strstr(buffer,​ "​G=on"​)) {
 +                        g_on = 1;
 +                        g_col = 255;
 +                    }
 +                    else{
 +                        g_on = 0;
 +                        g_col = 0;
 +                    }
 +                    if (strstr(buffer,​ "​B=on"​)) {
 +                        b_on = 1;
 +                        b_col = 255;
 +                    }
 +                    else{
 +                        b_on = 0;
 +                        b_col = 0;
 +                    }
 +                    ​
 +                    display_page();​
 +                    client.close();​
 +                }           
 +            }
 +            client.close(); ​  
 +    }
 +}
 +
 +</​code>​
 +
 +-------
2014/mbed-http.1421639425.txt.gz · Poslední úprava: 2015/01/19 04:50 autor: Maximilián Tydor