2015-07-30

EVShield筆記(4 - 2) : EVShield WiFi Web Server Arduino 軟體功能

在前篇 " (4-1) 結合 Arduino WiFi Shield 的 EVShield Web Server " 中,主要探討的是硬體介面相關,包含: SPI介面Shields 推疊 以及 Arduino 腳位配置 

本篇將以軟體功能為主,包含:建立 WiFi 連結啟動 Web server 以及 處理瀏覽器的 HTTP request

【參考資訊】

(1) Arduino WiFi.h 程式庫 
(2) HTTP Headers for Dummies 
(3) EVShield筆記(2):UI Module使用者介面擴展板程式摘要 

【1. 建立WiFi連結】


  • 連接無線網路,需要確認 SSID 與 加密方式 ,再以 WiFi.begin() 進行加密認證。
  • 通過加密認證之後,會由 DHCP 配置動態 IP,也可以先以WiFi.config() 設定靜態 IP後再進行加密認證。
  • IP 位址可以由 WiFi.localIP() 取得資料型態為IPAddress,實際上為四個元素陣列的IPV4 格式



【2. 啟動 WiFi Server】

啟動 Web Server,需要先以 WiFiServer server(port no.) 建立server 物件再透過 server.begin()  啟動 server 開始偵聽來自 client 的封包。
以下的範例程式中包含了:以WPA加密認證連接無線網路取得動態IP以及啟動server物件偵聽 TCP 80 port 的 HTTP request 封包。

WiFiServer server(80);
WiFiClient client;
 
void setup()
{   
  char ssid[]  = "YourNetwork";  // Network SSID (name) 
  char key[]   = "YourWPAKey";   // WPA key
  int status   = WL_IDLE_STATUS; 
  char ipStr[17];
  
  evshield.init( SH_HardwareI2C );
  uim.begin();
  EVSH_UIM_MainPage("Arduino WIFI Web Server");
  
  if(WiFi.status() == WL_NO_SHIELD) {
    EVSH_UIM_actionMsg("No WiFi Shield");
    while (true);
  }
  
  EVSH_UIM_actionMsg("Connecting WLAN..");
  while (status != WL_CONNECTED) {
    status = WiFi.begin(ssid, key);
    delay(5000);
  }
     
  IPAddress myIP = WiFi.localIP();
  sprintf(ipStr, "%d.%d.%d.%d", myIP[0], myIP[1], myIP[2], myIP[3]);  
  EVSH_UIM_actionMsg(ipStr);
  EVSH_UIM_reportMsg("Connect this IP by browser", EVs_UIM_WHITE);
  evshield.bank_a.centerLedSetRGB(0,0,0);
  evshield.ledSetRGB(0,0,0); 
  server.begin();
  delay(2000);
}

【3. 處理 HTTP request 】

Web server 與 client 瀏覽器之間透過 HTTP 協定進行溝通,更明確的說,Web server需要處理來自 client 的 HTTP request並回應 HTTP response 給 client,以下是進行的程序:
  1. 當瀏覽器開啟Web server 的 URL之後,就會提交一個GET method 的 HTTP request 給Web server。
  2. Web server 在接收後,就會以HTTP Response回應給瀏覽器,其中包含了要給 client 顯示的網頁 HTML文件。
  3. 網頁中包含了四個 Submit buttons,選擇任何一個按下,瀏覽器就會提交一個 Post method 的 HTTP request 給 Web server,其中包含了所按下button的 key-value值。
  4. Web server 在接收解析key的value值之後,會依據value對應的指令,設定 EVShield的LED 顏色以及顯示執行的訊息在UI Module的螢幕上。
 處理 Client HTTP request程式碼:

void loop()
{
  char buffer[9], inChar;
      
  client = server.available();
  if (client) {
    while (client.connected()) {
      // A connected client has data available for reading.
      if (client.available()) {
        memset(buffer,0,sizeof(buffer));
        if (client.readBytesUntil('/',buffer,sizeof(buffer))) {
          if (strcmp(buffer,"POST ") == 0) { 
            client.find("\n\r"); // Skip body of http header
            if (client.findUntil("ledCmd", "\n\r")) {
              client.read();           // Read '='
              inChar = client.read();  // Read 'r','g','b','x'
              executeCmd(inChar);
            }
          } 
          else if (strcmp(buffer,"GET ") == 0) {            
                  // Response GET request to Client
                  sendWebPage();
                  executeCmd('x');
               }
          client.flush();
        }
      }
    } 
    delay(1);
    client.stop();
    client.flush();
  } 
}

 傳送HTTP response的程式碼:

Server 傳送 HTTP Response 封包

沒有留言:

張貼留言