2016年6月1日 星期三

AllAboutEE 的 ESP8266 伺服器測試 (三)

今天用另外一塊 Arduino+ESP8266 模組來做實驗, 並且將程式改為設在模式 2, 取得 ssid 與密碼後先設為模式 1, 再用 AT+CWJAP 更改連線設定.

這次我不使用手機來設定 ssid 與密碼, 改用筆電, 因為這次我要讓 ESP8266 連線到手機的無線基地台, 而 Android 手機不讓我們同時打開 wifi 與熱點分享, 據華為客服解釋, 這是因為同時打開這兩個功能會加劇手機耗電, 所以打開 wifi 時, 熱點分享就會被自動關閉, 反之亦然. 所以既然我要讓 ESP8266 透過手機熱點分享連上互聯網, 那我就沒辦法同時打開其 wifi 連線到 ESP8266 的 SoftAP (192.168.4.1) 去做連線設定, 所以就改用筆電連線 ESP8266 的 SoftAP 來設定.

前文參考 :

# AllAboutEE 的 ESP8266 伺服器測試 (二)

程式修改如下 :

#include <SoftwareSerial.h>
#define DEBUG true

SoftwareSerial esp8266(10,11); //(RX,TX)
const int MAX_PAGE_NAME_LEN=48;
char buffer[MAX_PAGE_NAME_LEN + 1];

void setup() {
  Serial.begin(9600);
  esp8266.begin(9600);
  sendData("AT+RST\r\n",2000,DEBUG); // reset module
  sendData("AT+CWMODE=2\r\n",1000,DEBUG); // configure as access point
  sendData("AT+CIFSR\r\n",1000,DEBUG); // get ip address
  sendData("AT+CIPMUX=1\r\n",1000,DEBUG); // configure for multiple connections
  sendData("AT+CIPSERVER=1,80\r\n",1000,DEBUG); // turn on server on port 80
  }

void loop() {
  if (esp8266.available()) { // check if the esp is sending a message  
    if (esp8266.find("+IPD,")) {
      delay(1000);
      //esp8266 link response : +IPD,0,498:GET / HTTP/1.1
      //retrieve connection ID from response (0~4, after "+IPD,")
      int connectionId=esp8266.read()-48;  //from ASCII to number
      //subtract 48 because read() returns ASCII decimal value
      //and in ASCII, "0" (the first decimal number) starts at 48
      if (esp8266.find("GET /")) { //retrieve page router from remaining response
        memset(buffer, 0, sizeof(buffer));  //clear buffer (all set to 0)
        if (esp8266.readBytesUntil('/', buffer, sizeof(buffer))) {
          if (strcmp(buffer, "update") == 0) { //update wifi
            //"?ssid=aaa&pwd=bbb HTTP/1.1"            
            esp8266.find("?ssid="); //skip ssid token
            memset(buffer, 0, sizeof(buffer));  //clear buffer (all set to 0)
            esp8266.readBytesUntil('&', buffer, sizeof(buffer)); //retrieve ssid
            String ssid=buffer;
            esp8266.find("pwd="); //skip pwd token
            memset(buffer, 0, sizeof(buffer));  //clear buffer (all set to 0)
            esp8266.readBytesUntil(' ', buffer, sizeof(buffer)); //retrieve pwd
            String pwd=buffer;
            //set joint AP
            sendData("AT+CWMODE=3\r\n",2000,DEBUG);          
            sendData("AT+CWJAP=\"" + ssid + "\",\"" + pwd + "\"\r\n",6000,DEBUG);
            sendData("AT+CIFSR\r\n",1000,DEBUG);
            //show result
            String webpage="<html>Wifi setup OK!</html>";
            String cipSend = "AT+CIPSEND=";
            cipSend += connectionId;
            cipSend += ",";
            cipSend +=webpage.length();
            cipSend +="\r\n";
            sendData(cipSend,1000,DEBUG);
            sendData(webpage,2000,DEBUG);
           
            String closeCommand = "AT+CIPCLOSE=";
            closeCommand+=connectionId; // append connection id
            closeCommand+="\r\n";  
            sendData(closeCommand,3000,DEBUG);                
            }
          else { //show setup page
            String webpage="<html><form method=get action='/update/'>SSID <input name=ssid type=text><br>";
            String cipSend = "AT+CIPSEND=";
            cipSend = "AT+CIPSEND=";
            cipSend += connectionId;
            cipSend += ",";
            cipSend +=webpage.length();
            cipSend +="\r\n";
            sendData(cipSend,1000,DEBUG);
            sendData(webpage,2000,DEBUG);

            webpage="PWD <input name=pwd type=text> ";
            cipSend = "AT+CIPSEND=";
            cipSend += connectionId;
            cipSend += ",";
            cipSend +=webpage.length();
            cipSend +="\r\n";
            sendData(cipSend,1000,DEBUG);
            sendData(webpage,2000,DEBUG);

            webpage="<input type=submit value=Connect></form></html>";
            cipSend = "AT+CIPSEND=";
            cipSend += connectionId;
            cipSend += ",";
            cipSend +=webpage.length();
            cipSend +="\r\n";
            sendData(cipSend,1000,DEBUG);
            sendData(webpage,2000,DEBUG);

            String closeCommand = "AT+CIPCLOSE=";
            closeCommand+=connectionId; // append connection id
            closeCommand+="\r\n";  
            sendData(closeCommand,3000,DEBUG);
            }
          }
        }
      }
    }
  }

String sendData(String command, const int timeout, boolean debug) {
  String response="";
  esp8266.print(command); // send the read character to the esp8266
  long int time=millis();
  while ((time+timeout) > millis()) {
    while(esp8266.available()) {
      // The esp has data so display its output to the serial window
      char c=esp8266.read(); // read the next character.
      response += c;
      }
    }
  if (debug) {Serial.print(response);}
  return response;
  }

將我的手機 4G 上網與可攜式 Wifi 基地台分享打開 (SSID 為 H30-L02-webbot), 然後用筆電的 wifi 連線 ESP8266 模式 2 下建立的 SoftAP, 打開筆電瀏覽器連線 192.168.4.1, 顯示 wifi 設定頁面, 輸入 SSID 與密碼後, 按 Connect 順利完成設定.






序列埠監控視窗輸出訊息如下 :

AT+RST


OK
bB�鑭b禔S��"軬B�侒��餾�
[System Ready, Vendor:www.ai-thinker.com]
AT+CWMODE=2

no change
AT+CIFSR

192.168.4.1

OK
AT+CIPMUX=1


OK
AT+CIPSERVER=1,80


OK
1.1
Host: 192.168.4.1
User-Agent: Mozilla/5.AT+CIPSEND=0,77

> <html><form method=get action='/update/'>SSID <input name=ssid
SEND OK
AT+CIPSEND=0,31

> PWD <input name=pwd type=text>
SEND OK
AT+CIPSEND=0,47

> <input type=submit value=Connect></form></html>
SEND OK
AT+CIPCLOSE=0


OK
Unlink
HTTP/1.1
HAT+CWMODE=3


OK
AT+CWJAP="H30-L02-webbot","1234567890"


OK
AT+CIFSR

192.168.4.1
192.168.43.40

OK
AT+CIPSEND=0,27

> <html>Wifi setup OK!</html>
SEND OK
AT+CIPCLOSE=0


OK
Unlink

其實應該是執行 AT+CWJAP 前改成模式 1 較合理, 但此處為了用 AT+CIFSR 確認是否有順利連上無線基地台才用模式 3, 可見確實從無線 AP 的 DHCP 獲得 192.168.43.40 這個 IP. 這時若改用此 IP 連線, 也會連線到 ESP8266 伺服器, 像 192.168.4.1 一樣顯示設定網頁 :



同時檢查手機的網路連線, 發現經過上面的連線設定後, ESP8266 確實連線到手機分享的無線基地台, 其 IP 為 192.168.43.40 :





所以我可能需要修正一下我對 Webduino 操作模式的猜測, 在其主機板上有一個單切雙擲開關, 當要設定 wifi 連線時, 關關要切到設定側, 這時 ESP8266 應該是在模式 2, 用手機連線到 192.168.4.1 做完 wifi 設定成功後拔掉電源, 把關關切到工作側, 再送電就會連線到指定的 AP 了, 這時 ESP8266 應該在模式 1.

2016-06-02 補充 :

注意, 以上只是一個測試專案的中間過程記錄, 不是最終結果.

今天把程式做最後修改測試, 我推翻上面的猜測, 仍維持最早的假定, 即在做 wifi 設定時 ESP8266 是在模式 3, 而在工作模式是設在模式 1. 參見此系列測試的完結篇 :

# AllAboutEE 的 ESP8266 伺服器測試 (四) : 完結篇


沒有留言 :