要將ESP32設定成 Web Server,要有幾個步驟:
一、載入WiFi的函數庫
#include <WiFi.h>
二、設定要連上無線基地台的ID及密碼
const char* ssid = "無線基地台的名字";
const char* password = "連上無線基地台的密碼";
ESP32 Web Server成功連上無線基地台後,會得到基地台給虛擬的 IP。因此這個時候在同網段的電腦或是手機,就可以用網頁瀏覽器連上這個 IP,與 ESP32 Web Server連線傳輸。
三、宣告一個伺服器物件,名稱可以自訂,一般為了容易識別都設成 server;通訊埠也是設定網頁的80。若是要使用其他埠號,則用瀏覽器連上Web Server時,就要加上埠號。
WiFiServer server(80);
(似乎可以宣告兩個以上的伺服器物件,使用不同的埠號,這以後來測試看看)
四、啟動無線物件開始連結基地台,並不斷偵測無線是否已經連上了。如果沒有連上,每隔0.5秒不斷測試,並在監視視窗顯示狀態。
WiFi.begin(ssid,password);
while (WiFi.status() != WL_CONNECTED) { //利用迴圈偵測無線物件連線的狀態
delay(500);
Serial.print(".");
}
五、啟動 Web Server
server.begin();
六、顯示連上基地台後,分配給 ESP32 Web Server的IP位址。可供同網段的電腦或手機用瀏覽器連線。
1. 顯示在監視視窗上
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
顯示到連線到無線基地台所分配到的 IP是 192.168.1.116
2. 之前使用過 OLED Display,正好也可以將 IP顯示在OLED。這比用USB連線上到ESP32電路板上,才能知道IP位址。
display.setFont(ArialMT_Plain_16);
display.drawString(00,00,"WiFi connected.");
display.drawString(00,20,"IP address: ");
display.drawString(00,40,WiFi.localIP());
display.display();
在編譯後,OLED顯示器的 drawString()內的參數第3個是字串,跟 localIP()是 IPAddress是不匹配的,所以要把 localIP() 改成 String 資料型態。因此使用String()轉換型態。
String IPAddressofServer = String(Wifi.localIP());
display.drawString(00,40,IPAddressofServer);
結果在 OLED 上顯示的 IP 卻不是 192.168.1.116。所以 IPAddress()是整數矩陣型態,無法使用 String()型態轉換。在 Google搜尋了 "IPAddress() to string"的方法,找到了:
(1).建立一個轉換函數:
String IpAddress2String(const IPAddress& ipAddress) {
return String(ipAddress[0]) + String(".") +\
String(ipAddress[1]) + String(".") +\
String(ipAddress[2]) + String(".") +\
String(ipAddress[3]) ;
}
String IPAddressofServer = IpAddress2String(Wifi.localIP());
display.drawString(00,40,IPAddressofServer);
(2)後來查到一個Wifi.localIP()內建的方法:WiFi.localIP().toString()
display.drawString(00,40,WiFi.localIP().toString());
六、現在若是用手機(要在同一個網域,也就是手機也是連上同一台無線基地台)的瀏覽器上,輸入192.168.1.116,是一片空白。接下要設定當有使用端(client)連線上Web Server(ESP32)時,會適當給予回應。
先宣告一個client物件,是用來 Server有接受到連線時的使用端資訊(client)
WiFiClient client = server.available();
if (client) {
當有連線到 Web Server,client會接收到連線的資料。
所以可以使用 client.print(""); 將要顯示在資料顯示在網頁上
}
例如:
void loop() {
WiFiClient client = server.available();
if (client) {
client.println("HTTP/1.1 200 OK"); //因此顯示第一個顯示網頁的畫面
client.println("Content-type:text/html");
client.println();
client.print("<h1>");
client.print(" Web Server");
client.println("</h1>");
}
}
七、若要控制ESP32(例如傳給值給ESP32的Web Server,將偵測到的溫溼度顯示在OLED上)或是與Web Server互動(再將溫溼度顯示到手機上的網頁),這些首先都是要能把值傳到 ESP32上的Web Server,ESP32再根據接收的資料(控制字元),來判斷要回應甚麼動作。
1.client.read() 是用來讀取網頁上傳送過來的資料
2.client.connect() 用來確認client端是否還連線在 Web Server上,連線則傳回1,否則傳回0。
我們必須先用這個函數來確認,client還連線在Server,以確保下面讀取到
的資料是由client傳過來的。在測試的時候,曾拿掉這個判斷,會讀到還沒
連線前的資料,造成誤判。
我們必須先用這個函數來確認,client還連線在Server,以確保下面讀取到
的資料是由client傳過來的。在測試的時候,曾拿掉這個判斷,會讀到還沒
連線前的資料,造成誤判。
3.client.available() 用來確認網頁是否有資料可以讀取,如果沒有資料就會傳回0。
4.client傳遞資料的儲存
String newLine="" ; //宣告一個字串變數用來儲存clinet傳送過來的資料
if (c=='\n') { //如果讀到的字元是 '\n',表示這個網頁是第一次連上 Web Server。
if (c=='\n') { //如果讀到的字元是 '\n',表示這個網頁是第一次連上 Web Server。
if(newLine.length()==0){ //讀到字元\n,而且資料字串是空白,表示clint沒有傳遞資料,
所以是第一次連到 Server,所以顯示初始的網頁。
所以是第一次連到 Server,所以顯示初始的網頁。
client.println("HTTP/1.1 200 OK"); //初始的網頁,會有一個可以顯示溫溼度的連結
client.println("Content-Type:text/html");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.print("<h1>");
client.print(" Web Server");
client.println("</h1> <h3>");
client.print("Click <a href=\"/T\">Here</a> to Dispaly Temperature and Humidity.");
client.println("</h1></h3>");
client.println("</html>");
break; //顯示首頁完,跳出while迴圈
}
else { //讀到\n,而資料字串長度不是0,表示已經到client傳遞資料的尾端,清除資料
字串
字串
newLine="";
}
}
else if (c!='\r') { //新的client連線,但讀到資料不是 /n 跟 /r,把讀到的字元存入資料字串
newLine +=c;
}
5.判斷資料字串: endsWith用來判斷資料字串(newLine)是否是 "GET /T"結尾的。
if (newLine.endsWith("GET /T")){
ht(); //呼叫ht()函數,在 OLED上顯示溫濕度
}
6.相關的程式:
void ht(){
h=dht.readHumidity();
hh=h;
t=dht.readTemperature();
tt=t;
if (isnan(h)||isnan(t)){
display.drawString(00,5,"Failed to read from DHT sensor!");
display.display();
return;
}
display.clear();
display.drawString(00,1,"Humi:");
display.drawString(60,1,hh);
display.drawString(90,1,"%");
display.drawString(00,30,"Temp:");
display.drawString(60,30,tt);
display.drawString(90,30,"c");
display.display();
}
void loop() {
WiFiClient client = server.available();
if (client){ //有網頁連線上到 Web Server
display.clear();
display.drawString(00,00,"client connected.");
display.display();
String newLine="";
while(client.connected()){
if (client.available()){ //available()是表示client有傳遞資料
char c=client.read();
Serial.write(c);
if (c=='\n') { //如果讀到的字元是 '\n',表示這個網頁是第一次連上 Server
if (newLine.length()==0){
client.println("HTTP/1.1 200 OK"); //因此顯示首頁
client.println("Content-Type:text/html");
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.print("<h1>");
client.print(" Web Server");
client.println("</h1> <h3>");
client.print("Click <a href=\"/T\">Here</a> to Dispaly Temperature and Humidity.");
client.println("</h1></h3>");
client.println("</html>");
break; //顯示首頁完,跳出while迴圈
}
else {
newLine="";
}
}
else if (c!='\r') {
newLine +=c;
}
if (newLine.endsWith("GET /T")){ //呼叫ht()函數,在 OLED上顯示溫濕度
ht();
}
} //available
} //while
}
} //loop
參考資料:
1.ESP32程式設計(基礎篇),曹永忠,2020年2月,渥瑪數位。
沒有留言:
張貼留言