2017年5月8日 星期一

適用於ESP32 server應用的HttpRequestString類別



最近在測試ESP32他的SimepleWiFiServer範例直接使用WiFiServer類別建立server,ESP8266則直接提供WebServer類別,server.on()函數可以根據url後面的字串自動呼叫處理函數,這功能在ESP32目前尚無法使用因此撰寫了 HttpRequestString 類別用來支援參數分析只要將GET後面的字串帶入就可得到 Uri與參數的Name-Value該類別使用了 String 類別WString.hESP32提供的如果用於其他Core須自行修改例如 #include <String.h>

以下getClientRequest(),是參考ESP32DNS_Web_Server的範例, client連線時,取的GET後面的request字串:
String getClientRequest(WiFiClient client)
{
    // Wait for data from client to become available
    while(client.connected() && !client.available()){
        delay(1);
    }

    // Read the first line of HTTP request
    String request = client.readStringUntil('\r');

    // First line of HTTP request looks like "GET /path HTTP/1.1"
    // Retrieve the "/path" part by finding the spaces
    int addr_start = request.indexOf(' ');
    int addr_end = request.indexOf(' ', addr_start + 1);
    if (addr_start == -1 || addr_end == -1) {
        Serial.print("Invalid request: ");
        Serial.println(request);
        return "";
    }
    request = request.substring(addr_start + 1, addr_end);
    Serial.print("Request: ");
    Serial.println(request);
    client.flush();
    return request;
}

將上面取得的request字串傳入responseClientRequest()建立params物件後即可取得requesturi與參數的值,接著可用於response判斷。
void responseClientRequest(WiFiClient client, String request)
{
    HttpRequestParams params(request);
   
    if (params.Uri == "/")
    {
        sendHeader(client);
        //if (params.get("Level").length()>0)
        {
            client.print("Level is '");
            client.print(params.get("Level"));
            client.print("'<br>");
        }
        sendBody(client);
        sendTail(client);
    }
    // Check to see if the client request was "GET /H" or "GET /L":
    else if (params.Uri=="/H") {
        LedStatus = HIGH;
        digitalWrite(pinLED, LedStatus);               // GET /H turns the LED on
        Serial.println("LED ON");
        sendPage(client);
    }
    else if (params.Uri=="/L") {
         LedStatus = LOW;
         digitalWrite(pinLED, LedStatus);                // GET /L turns the LED off
         Serial.println("LED OFF");
         sendPage(client);
    }
    else {
        sendHeader(client);
        client.print("HTTP/1.1 404 Not Found\r\n\r\n");
        sendTail(client);
    }
   
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
}

以下是類別HttpRequestString.h:
// HttpRequestString.h

#ifndef HttpRequestString_h
#define HttpRequestString_h

#include <WString.h>

#define MaxParamaterCount 10

typedef struct {
    String Name;
    String Value; 
} HttpRequestParam;

class HttpRequestParams {
   public:   
        String Uri;
        HttpRequestParam param[MaxParamaterCount];
        int paramCount;
       
        HttpRequestParams(String request);
        String get(String Name);
};


#endif //HttpRequestString_h
//

以下是實做檔HttpRequestString.cpp:
// HttpRequestString.cpp

#include <Arduino.h>
#include "HttpRequestParams.h"

#define DEBUG_LEVEL   0

HttpRequestParams::HttpRequestParams(String request)
{   
    paramCount = 0;
   
    int param_start = request.indexOf('?'); 
    #if (DEBUG_LEVEL>0)
    Serial.print("param_start=");
    Serial.println(param_start);
    #endif
    if (param_start<0) {     
        Uri = request;
        return; //no parameters
    } else {
        Uri = request.substring(0, param_start-1);
    }
    #if (DEBUG_LEVEL>0)
    Serial.print("Uri=");
    Serial.println(Uri);
    #endif

    int param_separator = request.indexOf('=', param_start + 1);
    #if (DEBUG_LEVEL>0)
    Serial.print("param_separator=");
    Serial.println(param_separator);
    #endif 
    while (param_separator > 0) { //found a parameter    
        param[paramCount].Name = request.substring(param_start + 1, param_separator);
        int param_end = request.indexOf('&', param_start + 1);
        if (param_end<0) param_end = request.length(); //last parameter
        param[paramCount].Value = request.substring(param_separator + 1, param_end);
       
        #if (DEBUG_LEVEL>0)
        Serial.print("Param(");
        Serial.print(paramCount);
        Serial.print("): ");
        Serial.print(param[paramCount].Name);
        Serial.print("=");
        Serial.println(param[paramCount].Value);
        #endif

        paramCount++;
        param_start = param_end;
        param_separator = request.indexOf('=', param_start + 1);
    }
}

String HttpRequestParams::get(String Name)
{
    #if (DEBUG_LEVEL>1)
    Serial.print("Search ");
    Serial.print(Name);
    #endif
    
    for (int i=0; i<paramCount; i++) {
        #if (DEBUG_LEVEL>1)
        Serial.print(" ");
        Serial.print(i);
        #endif
        if (param[i].Name.equals(Name)) {
            #if (DEBUG_LEVEL>1)
            Serial.print(" Found ");
            Serial.println(param[i].Value);
            #endif
            return param[i].Value;
        }
    }
    #if (DEBUG_LEVEL>1)
    Serial.println();
    #endif
    return "";
}


沒有留言:

張貼留言