2022年8月23日 星期二

NodeMCU 上的 HTTP 服務器 Arduino IDE

 

介紹

超文本傳輸協議 (HTTP) 是標準應用層協議,用作服務器和客戶端之間的請求-響應協議。

它廣泛用於物聯網(物聯網)嵌入式應用程序,其中每個傳感器都連接到服務器,我們可以通過互聯網控制它們。

NodeMCU 具有板載 Wi-Fi 功能。有了這個 Wi-Fi 功能,NodeMCU 可以作為客戶端連接到任何 Wi-Fi 網絡,或者它可以創建一個網絡,其他支持 Wi-Fi 的設備可以連接到該網絡。

NodeMCU 作為 HTTP Server 使用 Wi-Fi AP 模式

NodeMCU wi-fi 具有接入點 (AP) 模式,通過該模式它可以創建無線 LAN,任何支持 wi-fi 的設備都可以連接到該模式,如下圖所示。

NodeMCU 作為 HTTP Server 使用 Wi-Fi AP 模式

NodeMCU 作為 HTTP Server 使用 Wi-Fi AP 模式

我們可以為 AP 模式設置 SSID 和密碼,用於在連接到其他設備時對其進行身份驗證。

NodeMCU 作為 HTTP Server 使用 Wi-Fi STA 模式

NodeMCU 具有站 (STA) 模式,使用該模式可以連接到現有的 wi-fi 網絡,並可以充當具有該網絡分配的 IP 地址的 HTTP 服務器。

NodeMCU 作為 HTTP Server 使用 Wi-Fi STA 模式

NodeMCU 作為 HTTP Server 使用 Wi-Fi STA 模式

NodeMCU 從它所連接的 Wi-Fi 路由器獲取 IP。有了這個 IP 地址,它就可以充當任何 wi-fi 設備都可以連接的 HTTP 服務器。

例子

讓我們編寫 Arduino Sketch 以啟用 NodeMCU 作為具有 Wi-Fi STA/AP 模式的 HTTP 服務器,並從客戶端控制連接在服務器端的 LED。

在這裡,我們將 LED 連接到引腳號。2 即 NodeMCU 板上的 D2 引腳,如下圖所示。

NodeMCU LED 接口

客戶端的 HTML 頁面

由於我們正在為 LED 開/關功能製作 HTTP 服務器,因此我們將製作一個簡單的 HTML 頁面,該頁面將在客戶端可見,並且能夠接受用戶對 LED 開/關的輸入。它是按鈕輸入的用戶友好表示,它在點擊時從用戶那裡獲取輸入。

我們需要為 LED ON 和 LED OFF 狀態編寫兩個 HTML 頁面,即當客戶端單擊 LED ON 按鈕時,在接下來的操作中,我們需要提供 LED OFF 的選項。下面是 LED 開和 LED 關狀態演示的兩個 HTML 代碼片段。

LED ON 的 HTML 代碼片段

<!DOCTYPE html>
<html>
<head><title>LED Control</title></head>
<body>
<h1>LED</h1>
<p>Click to switch LED on and off.</p>
<form method="get">
<input type="button" value="LED ON" onclick="window.location.href='/ledon'">
</form>
</body>
</html>

LED 關閉的HTML 代碼片段

<!DOCTYPE html>
<html>
<head><title>LED Control</title></head>
<body>
<h1>LED</h1>
<p>Click to switch LED on and off.</p>
<form method="get">
<input type="button" value="LED OFF" onclick="window.location.href='/ledoff'">
</form>
</body>
</html>

從上面的兩個 HTML 片段中,我們可以看到 LED ON 和 LED OFF 狀態只有形式不同。

讓我們看一下 HTML 行

<!DOCTYPE html>:此聲明將該文檔定義為 HTML 並幫助瀏覽器正確顯示網頁。它只能在頁面頂部出現一次。

<html>:此元素是 HTML 頁面的根元素

<head>:此元素包含有關文檔的元信息

<title>:此元素指定文檔的標題

<body>:該元素包含可見的頁面內容,即文檔的正文

<h1>:此元素定義標題的最大字體大小。同樣,我們可以使用 <h2>/<h3> 等來獲得較小的標題字體大小。

<p>:此元素定義一個段落。

<form>:該元素定義了一個用於收集用戶輸入的表單

window.location.href:這是一個告訴我們當前 URL 位置的屬性。更改屬性的值將重定向頁面。

例如window.location.href='/ledon'將當前頁面重定向到 URLcurrent_url/ledon 頁面。如果當前位置是,http://192.168.0.1那麼它將重定向到http://192.168.0.1/ledon 頁面。頁面重定向操作是在點擊事件上進行的(例如點擊按鈕)。  

這裡我們使用上述概念(頁面重定向)將客戶端從 LED ON 頁面重定向到 LED OFF 頁面,反之亦然。

要了解有關 HTML 的更多信息,請參閱https://www.w3schools.com/html/default.asp

現在我們可以在客戶端連接到服務器以及客戶端單擊按鈕時發送上述 HTML 片段。

 

程序

在 Wi-Fi 接入點 (AP) 模式下,NodeMCU 創建一個服務器,因此我們可以設置其 IP 地址、IP 子網掩碼和 IP 網關。

 

讓我們使用下面的SSID,加入網絡的密碼和AP模式的地址

  • SSID = “節點MCU”
  • 密碼 = “12345678”
  • IP = "192.168.2.1"
  • 子網絡掩碼 = "255.255.255.0"
  • 網關 = “192.168.2.1”

用於具有 wi-fi AP 模式的 HTTP 服務器的 Arduino Sketch

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

/* Put your SSID & Password */
const char* ssid = "NodeMCU";  // Enter SSID here
const char* password = "12345678";  //Enter Password here

/* Put IP Address details */
IPAddress local_ip(192,168,2,1);
IPAddress gateway(192,168,2,1);
IPAddress subnet(255,255,255,0);

ESP8266WebServer server(80);

uint8_t LEDpin = D2;
bool LEDstatus = LOW;

void setup() {
  Serial.begin(9600);
  pinMode(LEDpin, OUTPUT);

  WiFi.softAP(ssid, password);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  delay(100);
  
  server.on("/", handle_OnConnect);
  server.on("/ledon", handle_ledon);
  server.on("/ledoff", handle_ledoff);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");
}
void loop() {
  server.handleClient();
  if(LEDstatus)
  digitalWrite(LEDpin, HIGH);
  else
  digitalWrite(LEDpin, LOW);
}

void handle_OnConnect() {
  LEDstatus = LOW;
  server.send(200, "text/html", SendHTML(false)); 
}

void handle_ledon() {
  LEDstatus = HIGH;
  server.send(200, "text/html", SendHTML(true)); 
}

void handle_ledoff() {
  LEDstatus = LOW;
  server.send(200, "text/html", SendHTML(false)); 
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

String SendHTML(uint8_t led){
  String ptr = "<!DOCTYPE html>\n";
  ptr +="<html>\n";
  ptr +="<head>\n";
  ptr +="<title>LED Control</title>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<h1>LED</h1>\n";
  ptr +="<p>Click to switch LED on and off.</p>\n";
  ptr +="<form method=\"get\">\n";
  if(led)
  ptr +="<input type=\"button\" value=\"LED OFF\" onclick=\"window.location.href='/ledoff'\">\n";
  else
  ptr +="<input type=\"button\" value=\"LED ON\" onclick=\"window.location.href='/ledon'\">\n";
  ptr +="</form>\n";
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

注意:上述sketch客戶端上傳成功後,需要先連接NodeMCU創建的網絡。

從wifi連接到NodeMCU網絡後,在瀏覽器中輸入服務器地址,http://server_ip_address例如在我們的例子中,它是http://192.168.2.1按下 Enter 鍵後,我們可以看到來自服務器的 HTML 頁面響應,如下圖所示。現在只需單擊按鈕即可更改 LED 的狀態。

LED控制HTML頁面

現在,讓我們使用 Wi-Fi 站模式為 NodeMCU 做 HTTP 服務器。

在 Wi-Fi Station (STA) 模式下,NodeMCU 從 Wi-Fi 路由器(接入點)獲取 IP 地址。如果我們也在同一個網絡中,那麼我們可以只使用 IP 地址直接連接到 NodeMCU HTTP Server。

用於具有 wi-fi STA 模式的 HTTP 服務器的 Arduino Sketch

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

/*Put your SSID & Password*/
const char* ssid = "ssid";  // Enter SSID here
const char* password = "password";  //Enter Password here

ESP8266WebServer server(80);

uint8_t LEDpin = D2;
bool LEDstatus = LOW;

void setup() {
  Serial.begin(9600);
  delay(100);
  pinMode(LEDpin, OUTPUT);

  Serial.println("Connecting to ");
  Serial.println(ssid);

  //connect to your local wi-fi network
  WiFi.begin(ssid, password);

  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());

  server.on("/", handle_OnConnect);
  server.on("/ledon", handle_ledon);
  server.on("/ledoff", handle_ledoff);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");
}
void loop() {
  server.handleClient();
  if(LEDstatus)
  digitalWrite(LEDpin, HIGH);
  else
  digitalWrite(LEDpin, LOW);
}

void handle_OnConnect() {
  LEDstatus = LOW;
  server.send(200, "text/html", SendHTML(false)); 
}

void handle_ledon() {
  LEDstatus = HIGH;
  server.send(200, "text/html", SendHTML(true)); 
}

void handle_ledoff() {
  LEDstatus = LOW;
  server.send(200, "text/html", SendHTML(false)); 
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}

String SendHTML(uint8_t led){
  String ptr = "<!DOCTYPE html>\n";
  ptr +="<html>\n";
  ptr +="<head>\n";
  ptr +="<title>LED Control</title>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<h1>LED</h1>\n";
  ptr +="<p>Click to switch LED on and off.</p>\n";
  ptr +="<form method=\"get\">\n";
  if(led)
  ptr +="<input type=\"button\" value=\"LED OFF\" onclick=\"window.location.href='/ledoff'\">\n";
  else
  ptr +="<input type=\"button\" value=\"LED ON\" onclick=\"window.location.href='/ledon'\">\n";
  ptr +="</form>\n";
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

注意:在 wi-fi station 模式下,我們需要輸入現網的 SSID 和密碼。連接到 WiFi 網絡後,在瀏覽器中輸入服務器地址,即http://assigned_ip_address按下 Enter 鍵後,我們可以在瀏覽器中看到來自服務器的 HTML 頁面響應,如上圖所示的 AP 模式

視頻

資料來源:https://www.electronicwings.com/nodemcu/http-server-on-nodemcu-with-arduino-ide

沒有留言: